@absolutejs/absolute 0.19.0-beta.851 → 0.19.0-beta.853

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
  2. package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
  3. package/dist/angular/index.js +3 -1
  4. package/dist/angular/index.js.map +3 -3
  5. package/dist/angular/server.js +3 -1
  6. package/dist/angular/server.js.map +3 -3
  7. package/dist/build.js +1919 -284
  8. package/dist/build.js.map +17 -7
  9. package/dist/dev/client/handlers/angular.ts +17 -234
  10. package/dist/dev/client/handlers/angularHmrShim.ts +77 -0
  11. package/dist/dev/client/handlers/angularRuntime.ts +0 -476
  12. package/dist/dev/client/hmrClient.ts +21 -0
  13. package/dist/index.js +2006 -329
  14. package/dist/index.js.map +18 -8
  15. package/dist/react/browser.js.map +1 -1
  16. package/dist/react/index.js +3 -1
  17. package/dist/react/index.js.map +3 -3
  18. package/dist/react/server.js +3 -1
  19. package/dist/react/server.js.map +2 -2
  20. package/dist/src/core/prepare.d.ts +25 -0
  21. package/dist/src/dev/angular/fastHmrCompiler.d.ts +19 -0
  22. package/dist/src/dev/angular/hmrCompiler.d.ts +18 -0
  23. package/dist/src/dev/angular/hmrImportGenerator.d.ts +3 -0
  24. package/dist/src/dev/angular/hmrInjectionPlugin.d.ts +7 -0
  25. package/dist/src/dev/angular/resolveOwningComponents.d.ts +8 -0
  26. package/dist/src/dev/angular/vendor/translator/api/ast_factory.d.ts +363 -0
  27. package/dist/src/dev/angular/vendor/translator/api/import_generator.d.ts +49 -0
  28. package/dist/src/dev/angular/vendor/translator/context.d.ts +18 -0
  29. package/dist/src/dev/angular/vendor/translator/translator.d.ts +75 -0
  30. package/dist/src/dev/angular/vendor/translator/ts_util.d.ts +12 -0
  31. package/dist/src/dev/angular/vendor/translator/typescript_ast_factory.d.ts +66 -0
  32. package/dist/src/dev/angular/vendor/translator/typescript_translator.d.ts +13 -0
  33. package/dist/src/plugins/hmr.d.ts +25 -0
  34. package/dist/src/react/UniversalRouter.d.ts +3 -1
  35. package/dist/src/vue/components/Image.d.ts +1 -1
  36. package/dist/svelte/index.js +3 -1
  37. package/dist/svelte/index.js.map +2 -2
  38. package/dist/svelte/server.js +3 -1
  39. package/dist/svelte/server.js.map +2 -2
  40. package/dist/types/globals.d.ts +0 -12
  41. package/dist/vue/index.js +3 -1
  42. package/dist/vue/index.js.map +2 -2
  43. package/dist/vue/server.js +3 -1
  44. package/dist/vue/server.js.map +2 -2
  45. package/package.json +1 -1
@@ -67,15 +67,6 @@ type HMRMessage = {
67
67
 
68
68
  type AngularHmrApi = {
69
69
  applyUpdate: (id: string, newCtor: unknown) => boolean;
70
- applyStyleUpdate?: (id: string, newCtor: unknown) => boolean;
71
- applyTemplateUpdate?: (id: string, newCtor: unknown) => boolean;
72
- applyServiceUpdate?: (id: string, newCtor: unknown) => boolean;
73
- beginStyleUpdateBatch?: () => void;
74
- endStyleUpdateBatch?: () => Array<{ id: string; ok: boolean }>;
75
- beginTemplateUpdateBatch?: () => void;
76
- endTemplateUpdateBatch?: () => Array<{ id: string; ok: boolean }>;
77
- beginServiceUpdateBatch?: () => void;
78
- endServiceUpdateBatch?: () => Array<{ id: string; ok: boolean }>;
79
70
  getRegistry?: () => Map<string, unknown>;
80
71
  refresh: () => void;
81
72
  hasPageExportsChanged?: (sourceId: string) => boolean;
@@ -348,237 +339,29 @@ const handleFastUpdate = async (message: HMRMessage) => {
348
339
  let activeMessage: Promise<void> | null = null;
349
340
  let pendingMessage: HMRMessage | null = null;
350
341
 
351
- /* Stub handlers for fast paths that aren't implemented yet. Each one
352
- * returns false to signal "couldn't handle, fall through to reboot",
353
- * letting Phase 2 ship piecewise — we land §2.1 (this dispatch table)
354
- * first, then §2.4 / §2.3 / §2.2 fill in the stubs one at a time
355
- * without further plumbing changes. */
356
- /* Template HMR — re-imports the rebuilt page chunk under FAST_PATCH +
357
- * TEMPLATE_UPDATE_MODE, then asks the runtime to swap the template
358
- * subgraph of `ɵcmp` (template factory, slot counts, queries,
359
- * dependencies, host bindings) on every re-registered component.
342
+ /* Surgical fast-path stubs.
360
343
  *
361
- * Live instances keep their state, services, queries, and DI tokens —
362
- * only the rendered output changes. After all components are patched,
363
- * a single `refresh()` call walks the subtree, marks each patched
364
- * component dirty, and ticks the app to repaint.
344
+ * Phase 2's dynamic-import-based handlers (component-style /
345
+ * template / service-method-only) are intentionally absent here
346
+ * they were architecturally wrong (dynamic-importing the rebuilt
347
+ * page chunk created a parallel class identity, tripping NG0912
348
+ * collisions and producing scope-ID drift on Emulated styles). The
349
+ * surgical pipeline that replaces them uses Angular'''s
350
+ * `ɵɵreplaceMetadata` primitive — see SURGICAL_HMR.md.
365
351
  *
366
- * Returns false on any partial failure so the orchestrator falls
367
- * through to a coherent reboot. */
368
- type TemplateUpdateWindow = FastPatchWindow & {
369
- __ANGULAR_HMR_TEMPLATE_UPDATE_MODE__?: boolean;
370
- };
371
-
372
- const handleTemplateUpdate = async (message: HMRMessage): Promise<boolean> => {
373
- const hmr = window.__ANGULAR_HMR__;
374
- if (
375
- !hmr ||
376
- !hmr.applyTemplateUpdate ||
377
- !hmr.beginTemplateUpdateBatch ||
378
- !hmr.endTemplateUpdateBatch
379
- ) {
380
- return false;
381
- }
382
-
383
- const indexPath = findIndexPath(
384
- message.data.manifest,
385
- message.data.sourceFile,
386
- 'angular'
387
- );
388
- if (!indexPath) return false;
389
-
390
- const w = window as TemplateUpdateWindow;
391
- w.__ANGULAR_HMR_FAST_PATCH__ = true;
392
- w.__ANGULAR_HMR_TEMPLATE_UPDATE_MODE__ = true;
393
- hmr.beginTemplateUpdateBatch();
394
-
395
- const origWarn = suppressNg0912();
396
- try {
397
- await import(`${indexPath}?t=${Date.now()}`);
398
-
399
- // Page-level routes/providers cannot ride a template update.
400
- if (hmr.hasPageExportsChanged?.(message.data.sourceFile || '')) {
401
- return false;
402
- }
403
-
404
- const results = hmr.endTemplateUpdateBatch();
405
- // Empty batch = the chunk's components weren't already in the
406
- // registry (off-page broadcast). No-op success — see the
407
- // matching comment in `handleComponentStyleUpdate`.
408
- if (results.length === 0) {
409
- console.warn = origWarn;
410
- return true;
411
- }
412
- if (!results.every((r) => r.ok)) return false;
413
-
414
- console.warn = origWarn;
415
- hmr.refresh();
416
-
417
- return true;
418
- } catch (err) {
419
- console.warn = origWarn;
420
- console.warn(
421
- '[HMR] Angular template update failed, falling back:',
422
- err
423
- );
424
- return false;
425
- } finally {
426
- delete w.__ANGULAR_HMR_FAST_PATCH__;
427
- delete w.__ANGULAR_HMR_TEMPLATE_UPDATE_MODE__;
428
- console.warn = origWarn;
429
- }
430
- };
431
-
432
- /* Component-style HMR — re-imports the rebuilt page chunk under the
433
- * combined `FAST_PATCH` and `STYLE_UPDATE_MODE` flags so:
434
- * - the chunk's bootstrap section is skipped (FAST_PATCH)
435
- * - every per-file auto-registration block routes its new ctor
436
- * through `applyStyleUpdate` instead of a no-op (STYLE_UPDATE_MODE)
437
- *
438
- * The registration-block path is the only way to reach CHILD
439
- * components — the page chunk's `export *` only re-exports the page's
440
- * own module, so a top-level export walk would miss imported
441
- * components like `LayoutComponent`. Each compiled .ts file emits a
442
- * registration block for its own component classes, so the chunk
443
- * covers the whole tree on re-evaluation.
444
- *
445
- * Returns true iff every component the chunk re-registered swapped
446
- * its styles cleanly. Any failure (Shadow DOM, length change, missing
447
- * live <style> tag) → reboot. The transactional check inside
448
- * `applyStyleUpdate` means we never apply a partial update — either
449
- * the page restyles coherently or we reboot. */
450
- type StyleUpdateWindow = FastPatchWindow & {
451
- __ANGULAR_HMR_STYLE_UPDATE_MODE__?: boolean;
452
- };
352
+ * Until that pipeline lands, classifications other than
353
+ * `class-component` fall through to the existing reboot path. The
354
+ * toast tells the developer why. */
355
+ const handleTemplateUpdate = async (_message: HMRMessage): Promise<boolean> =>
356
+ false;
453
357
 
454
358
  const handleComponentStyleUpdate = async (
455
- message: HMRMessage
456
- ): Promise<boolean> => {
457
- const hmr = window.__ANGULAR_HMR__;
458
- if (
459
- !hmr ||
460
- !hmr.applyStyleUpdate ||
461
- !hmr.beginStyleUpdateBatch ||
462
- !hmr.endStyleUpdateBatch
463
- ) {
464
- return false;
465
- }
466
-
467
- const indexPath = findIndexPath(
468
- message.data.manifest,
469
- message.data.sourceFile,
470
- 'angular'
471
- );
472
- if (!indexPath) return false;
473
-
474
- const w = window as StyleUpdateWindow;
475
- w.__ANGULAR_HMR_FAST_PATCH__ = true;
476
- w.__ANGULAR_HMR_STYLE_UPDATE_MODE__ = true;
477
- hmr.beginStyleUpdateBatch();
478
-
479
- try {
480
- await import(`${indexPath}?t=${Date.now()}`);
481
-
482
- // Page-level routes/providers cannot ride a style update — they
483
- // are read once during bootstrap. If they changed in this
484
- // rebuild, reboot rather than risk a stale router/injector.
485
- if (hmr.hasPageExportsChanged?.(message.data.sourceFile || '')) {
486
- return false;
487
- }
488
-
489
- const results = hmr.endStyleUpdateBatch();
490
- // Empty batch is a no-op success: the chunk re-evaluated but
491
- // none of its components were already in the registry, so they
492
- // couldn't be live on the page right now. Common when a CSS
493
- // edit affects multiple page bundles (the server broadcasts
494
- // once per page) and the user is only looking at one of them —
495
- // the off-page broadcasts add fresh entries to the registry but
496
- // produce no batch updates. Treating that as a failure forced
497
- // fallthrough to reboot for every off-page broadcast, which
498
- // fired `startViewTransition` repeatedly and produced the
499
- // "Transition was skipped" abort when the second reboot
500
- // superseded the first mid-flight.
501
- if (results.length === 0) return true;
502
- return results.every((r) => r.ok);
503
- } catch (err) {
504
- console.warn('[HMR] Angular style update failed, falling back:', err);
505
- return false;
506
- } finally {
507
- delete w.__ANGULAR_HMR_FAST_PATCH__;
508
- delete w.__ANGULAR_HMR_STYLE_UPDATE_MODE__;
509
- }
510
- };
511
-
512
- /* Service HMR — re-imports the rebuilt page chunk under FAST_PATCH +
513
- * SERVICE_UPDATE_MODE so the page's auto-registration block routes
514
- * each new service ctor through `applyServiceUpdate`. The runtime
515
- * does prototype method-swap (always) and best-effort field merge on
516
- * the live singleton (when reachable via the root injector and
517
- * donor-instantiable). Live components keep their references — they
518
- * just call into the new method bodies on next invocation.
519
- *
520
- * This path only runs when the server-side classifier returned
521
- * `service-method-only` — services with side-effecting constructors
522
- * never get here, so the live singleton's existing subscriptions /
523
- * timers / listeners stay intact and we don't double-register them. */
524
- type ServiceUpdateWindow = FastPatchWindow & {
525
- __ANGULAR_HMR_SERVICE_UPDATE_MODE__?: boolean;
526
- };
359
+ _message: HMRMessage
360
+ ): Promise<boolean> => false;
527
361
 
528
362
  const handleServiceMethodSwap = async (
529
- message: HMRMessage
530
- ): Promise<boolean> => {
531
- const hmr = window.__ANGULAR_HMR__;
532
- if (
533
- !hmr ||
534
- !hmr.applyServiceUpdate ||
535
- !hmr.beginServiceUpdateBatch ||
536
- !hmr.endServiceUpdateBatch
537
- ) {
538
- return false;
539
- }
540
-
541
- const indexPath = findIndexPath(
542
- message.data.manifest,
543
- message.data.sourceFile,
544
- 'angular'
545
- );
546
- if (!indexPath) return false;
547
-
548
- const w = window as ServiceUpdateWindow;
549
- w.__ANGULAR_HMR_FAST_PATCH__ = true;
550
- w.__ANGULAR_HMR_SERVICE_UPDATE_MODE__ = true;
551
- hmr.beginServiceUpdateBatch();
552
-
553
- try {
554
- await import(`${indexPath}?t=${Date.now()}`);
555
-
556
- // Page-level routes/providers cannot ride a service update.
557
- if (hmr.hasPageExportsChanged?.(message.data.sourceFile || '')) {
558
- return false;
559
- }
560
-
561
- const results = hmr.endServiceUpdateBatch();
562
- // Empty batch = off-page broadcast, see comment in
563
- // `handleComponentStyleUpdate`.
564
- if (results.length === 0) return true;
565
- if (!results.every((r) => r.ok)) return false;
566
-
567
- // New method bodies might compute new values for observable-fed
568
- // fields, so the existing component subtree should re-render.
569
- // `refresh()` ticks the app + marks any pending fast-patch
570
- // components dirty.
571
- hmr.refresh();
572
-
573
- return true;
574
- } catch (err) {
575
- console.warn('[HMR] Angular service update failed, falling back:', err);
576
- return false;
577
- } finally {
578
- delete w.__ANGULAR_HMR_FAST_PATCH__;
579
- delete w.__ANGULAR_HMR_SERVICE_UPDATE_MODE__;
580
- }
581
- };
363
+ _message: HMRMessage
364
+ ): Promise<boolean> => false;
582
365
 
583
366
  const logRebootReason = (message: HMRMessage) => {
584
367
  const reason = message.data.reason;
@@ -0,0 +1,77 @@
1
+ import type {} from '../../../types/globals';
2
+ /* `globalThis.__angularHmr` runtime shim.
3
+ *
4
+ * The HMR injection plugin
5
+ * (`src/dev/angular/hmrInjectionPlugin.ts`) appends per-component
6
+ * `__ng_hmr_load` blocks that subscribe via
7
+ * `globalThis.__angularHmr.on('angular:component-update', cb)`.
8
+ * This file installs that bus.
9
+ *
10
+ * It must run before any component chunk does — the injected blocks
11
+ * `if (… && globalThis.__angularHmr.on)` no-op if the shim isn't
12
+ * defined yet, so a registration would silently miss. We keep the
13
+ * shim setup synchronous + at module scope so it's installed during
14
+ * `hmrClient.ts`'s import-evaluation pass, before page chunks load. */
15
+
16
+ export type AngularHmrEvent = 'angular:component-update';
17
+ export type AngularComponentUpdate = {
18
+ id: string;
19
+ timestamp: number;
20
+ };
21
+ export type AngularHmrListener = (data: AngularComponentUpdate) => void;
22
+
23
+ type AngularHmrBus = {
24
+ on(event: AngularHmrEvent, cb: AngularHmrListener): void;
25
+ off(event: AngularHmrEvent, cb: AngularHmrListener): void;
26
+ dispatch(event: AngularHmrEvent, data: AngularComponentUpdate): void;
27
+ };
28
+
29
+ declare global {
30
+ interface Window {
31
+ __angularHmr?: AngularHmrBus;
32
+ }
33
+ // eslint-disable-next-line no-var
34
+ var __angularHmr: AngularHmrBus | undefined;
35
+ }
36
+
37
+ const installAngularHmrShim = (): AngularHmrBus => {
38
+ const listeners = new Map<AngularHmrEvent, Set<AngularHmrListener>>();
39
+
40
+ const bus: AngularHmrBus = {
41
+ on(event, cb) {
42
+ let set = listeners.get(event);
43
+ if (!set) {
44
+ set = new Set();
45
+ listeners.set(event, set);
46
+ }
47
+ set.add(cb);
48
+ },
49
+ off(event, cb) {
50
+ listeners.get(event)?.delete(cb);
51
+ },
52
+ dispatch(event, data) {
53
+ const set = listeners.get(event);
54
+ if (!set) return;
55
+ // Snapshot before iterating — handlers could remove themselves.
56
+ for (const cb of [...set]) {
57
+ try {
58
+ cb(data);
59
+ } catch (err) {
60
+ console.error('[absolutejs] angular HMR listener threw', err);
61
+ }
62
+ }
63
+ }
64
+ };
65
+
66
+ return bus;
67
+ };
68
+
69
+ if (typeof globalThis !== 'undefined' && !globalThis.__angularHmr) {
70
+ globalThis.__angularHmr = installAngularHmrShim();
71
+ }
72
+
73
+ export const dispatchAngularComponentUpdate = (
74
+ data: AngularComponentUpdate
75
+ ) => {
76
+ globalThis.__angularHmr?.dispatch('angular:component-update', data);
77
+ };