@absolutejs/absolute 0.19.0-beta.747 → 0.19.0-beta.748

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.
@@ -679,6 +679,13 @@ const handleFullUpdate = async (message: HMRMessage) => {
679
679
  if (!indexPath) return;
680
680
 
681
681
  const doUpdate = async () => {
682
+ // Snapshot every instance that opted into `preserveAcrossHmr(this)`
683
+ // before destroying the app. The new instances created during
684
+ // bootstrap will read these values back via the same helper, so
685
+ // service state (auth tokens, cached data, subscriptions held by
686
+ // reference) survives a full re-bootstrap. Generic by class name
687
+ // — no per-app configuration here.
688
+ captureHmrPreservedInstanceStates();
682
689
  destroyAngularApp();
683
690
  await bootstrapAngularModule(indexPath, rootSelector, rootContainer);
684
691
  restoreComponentState(componentState);
@@ -689,3 +696,43 @@ const handleFullUpdate = async (message: HMRMessage) => {
689
696
 
690
697
  await runWithViewTransition(doUpdate);
691
698
  };
699
+
700
+ /* Snapshot every WeakRef-tracked instance's enumerable own properties
701
+ into the shared cache. The runtime helper `preserveAcrossHmr(this)`
702
+ from `@absolutejs/absolute/angular` populates the tracker, and on the
703
+ constructor of the next-bootstrapped instance reads back from the
704
+ cache. We talk to the same `globalThis`-anchored Map/Set as that
705
+ helper rather than importing it directly so this dev-client bundle
706
+ doesn't pull in the Angular runtime. */
707
+ type HmrPreserveScope = typeof globalThis & {
708
+ __ABS_HMR_INSTANCE_STATE__?: Map<string, Record<string, unknown>>;
709
+ __ABS_HMR_TRACKED_INSTANCES__?: Set<WeakRef<object>>;
710
+ };
711
+
712
+ const captureHmrPreservedInstanceStates = () => {
713
+ const scope = globalThis as HmrPreserveScope;
714
+ const tracker = scope.__ABS_HMR_TRACKED_INSTANCES__;
715
+ if (!tracker || tracker.size === 0) return;
716
+
717
+ const cache = (scope.__ABS_HMR_INSTANCE_STATE__ ??= new Map());
718
+ const dead: WeakRef<object>[] = [];
719
+
720
+ for (const ref of tracker) {
721
+ const instance = ref.deref();
722
+ if (!instance) {
723
+ dead.push(ref);
724
+ continue;
725
+ }
726
+
727
+ const key = instance.constructor?.name;
728
+ if (!key || key === 'Object') continue;
729
+
730
+ const props: Record<string, unknown> = {};
731
+ for (const prop of Object.keys(instance)) {
732
+ props[prop] = (instance as Record<string, unknown>)[prop];
733
+ }
734
+ cache.set(key, props);
735
+ }
736
+
737
+ dead.forEach((ref) => tracker.delete(ref));
738
+ };
@@ -2,6 +2,7 @@ export type { AngularPageDefinition, AngularPagePropsOf } from '../../types/angu
2
2
  export { ABSOLUTE_HTTP_TRANSFER_CACHE_SKIP_HEADER, buildAbsoluteHttpTransferCacheOptions } from './httpTransferCache';
3
3
  export { createDeterministicRandom, DETERMINISTIC_NOW, DETERMINISTIC_RANDOM, DETERMINISTIC_SEED, provideDeterministicEnv } from './deterministicEnv';
4
4
  export { defineAngularPage } from './page';
5
+ export { preserveAcrossHmr } from './preserveAcrossHmr';
5
6
  export { Island } from './Island.browser';
6
7
  export { withPendingTask } from './pendingTask';
7
8
  export { REQUEST, REQUEST_CONTEXT, RESPONSE_INIT } from './requestProviders';
@@ -4,6 +4,7 @@ export { ABSOLUTE_HTTP_TRANSFER_CACHE_SKIP_HEADER, buildAbsoluteHttpTransferCach
4
4
  export { createDeterministicRandom, DETERMINISTIC_NOW, DETERMINISTIC_RANDOM, DETERMINISTIC_SEED, provideDeterministicEnv } from './deterministicEnv';
5
5
  export { handleAngularPageRequest } from './pageHandler';
6
6
  export { defineAngularPage } from './page';
7
+ export { preserveAcrossHmr } from './preserveAcrossHmr';
7
8
  export { withPendingTask } from './pendingTask';
8
9
  export { REQUEST, REQUEST_CONTEXT, RESPONSE_INIT } from './requestProviders';
9
10
  export { createTypedIsland } from './createIsland';
@@ -0,0 +1,7 @@
1
+ /** Mark a service instance for state preservation across full Angular HMR
2
+ * re-bootstraps. Call once from the constructor. Safe in production
3
+ * (no-op outside dev mode). */
4
+ export declare const preserveAcrossHmr: (instance: object) => void;
5
+ /** Snapshot every tracked instance's enumerable own properties into the
6
+ * cache. Called by the HMR client right before `destroyAngularApp()`. */
7
+ export declare const captureTrackedInstanceStates: () => void;
package/package.json CHANGED
@@ -349,5 +349,5 @@
349
349
  ]
350
350
  }
351
351
  },
352
- "version": "0.19.0-beta.747"
352
+ "version": "0.19.0-beta.748"
353
353
  }