@async/framework 0.11.1 → 0.11.3

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.
package/CHANGELOG.md CHANGED
@@ -1,9 +1,39 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.11.3 - 2026-06-18
4
+
5
+ - Isolated runtime-owned signal, async-signal, scheduler, request, and cache
6
+ state so each `createApp(...)` call materializes fresh mutable state from
7
+ reusable app declarations.
8
+ - Preserved reusable app declarations across runtime destroy/recreate cycles,
9
+ late `app.use(...)` adoption, server render repetition, and peer async-signal
10
+ subscribers.
11
+ - Added direct runtime-isolation regression coverage and regenerated the
12
+ published browser/server artifacts.
13
+ - Bundle size from bundled TypeScript source: `browser.ts` 179,469 B raw /
14
+ 33,612 B gzip -> `browser.min.js` 76,458 B raw / 22,690 B gzip
15
+ (-103,011 B raw, -10,922 B gzip).
16
+
17
+ ## 0.11.2 - 2026-06-18
18
+
19
+ - Published the post-`0.11.1` feedback-regression hardening now on `main`,
20
+ including scheduler scope revival, server error envelopes, async-signal SSR
21
+ snapshot restore, lazy component error handling, router prefetch context,
22
+ server proxy transport validation, and package export smoke coverage.
23
+ - Refreshed the generated Async Pipeline workflow and lock metadata to
24
+ `@async/pipeline` `0.9.1`.
25
+ - Ignored local `docs/goals/` GoalBuddy planning bundles.
26
+
3
27
  ## 0.11.1 - 2026-06-17
4
28
 
5
29
  - Removed the literal old global fetch identifier from published release notes
6
30
  so package-wide text scans stay focused on runtime artifacts.
31
+ - Hardened scheduler scope revival, server error envelopes, async-signal SSR
32
+ snapshot restore, lazy component sync-rendering errors, router prefetch
33
+ context, server proxy transport validation, and package export smoke tests.
34
+ - Bundle size from bundled TypeScript source: `browser.ts` 177,243 B raw /
35
+ 33,354 B gzip -> `browser.min.js` 75,517 B raw / 22,516 B gzip
36
+ (-101,726 B raw, -10,838 B gzip).
7
37
 
8
38
  ## 0.11.0 - 2026-06-17
9
39
 
package/README.md CHANGED
@@ -430,7 +430,9 @@ Singular registry keys are canonical: `signal`, `handler`, `server`,
430
430
  ### Registry Inspection
431
431
 
432
432
  `Async.registry` is the global inspection surface for registered app pieces.
433
- Every runtime and concrete registry also points at the same backing store:
433
+ Every runtime owns fresh mutable signal and cache state materialized from the
434
+ app declaration store. Concrete registries inside one runtime share that
435
+ runtime's registry view:
434
436
 
435
437
  ```js
436
438
  Async.registry.keys("signal");
package/browser.js CHANGED
@@ -185,6 +185,28 @@ const __asyncSignalModule = (() => {
185
185
  };
186
186
  },
187
187
 
188
+ _cloneSignalDeclaration() {
189
+ return asyncSignal(id, fn);
190
+ },
191
+
192
+ _restore(snapshot = {}) {
193
+ if (!isAsyncSignalSnapshot(snapshot)) {
194
+ return state.set(snapshot);
195
+ }
196
+ if (activeAbort && !activeAbort.aborted) {
197
+ activeAbort.cancel(new Error(`Async signal "${registeredId}" restored from snapshot.`));
198
+ }
199
+ value = snapshot.value;
200
+ loading = Boolean(snapshot.loading);
201
+ error = snapshot.error ?? null;
202
+ status = typeof snapshot.status === "string" ? snapshot.status : inferStatus({ value, loading, error });
203
+ if (Number.isFinite(snapshot.version)) {
204
+ version = snapshot.version;
205
+ }
206
+ notify();
207
+ return state;
208
+ },
209
+
188
210
  _bindRegistry(nextRegistry, nextId) {
189
211
  registry = nextRegistry;
190
212
  registeredId = nextId;
@@ -270,6 +292,27 @@ const __asyncSignalModule = (() => {
270
292
  return Boolean(value?.[asyncSignalKind]);
271
293
  }
272
294
 
295
+ function isAsyncSignalSnapshot(value) {
296
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
297
+ return false;
298
+ }
299
+ return Object.hasOwn(value, "value")
300
+ && (Object.hasOwn(value, "loading")
301
+ || Object.hasOwn(value, "error")
302
+ || Object.hasOwn(value, "status")
303
+ || Object.hasOwn(value, "version"));
304
+ }
305
+
306
+ function inferStatus({ value, loading, error }) {
307
+ if (loading) {
308
+ return "loading";
309
+ }
310
+ if (error) {
311
+ return "error";
312
+ }
313
+ return value === undefined ? "idle" : "ready";
314
+ }
315
+
273
316
  function attachCancel(signal, controller) {
274
317
  Object.defineProperty(signal, "cancel", {
275
318
  configurable: true,
@@ -917,7 +960,12 @@ const __cacheModule = (() => {
917
960
  return registryStore.entries(`${type}.entries`);
918
961
  },
919
962
 
920
- _adoptMany() {
963
+ _adoptMany(map = {}) {
964
+ for (const [id, definition] of Object.entries(map ?? {})) {
965
+ if (!definitions.has(id)) {
966
+ registryApi.register(id, definition);
967
+ }
968
+ }
921
969
  return registryApi;
922
970
  }
923
971
  }, registryStore, type);
@@ -1075,6 +1123,10 @@ const __signalsModule = (() => {
1075
1123
 
1076
1124
  snapshot() {
1077
1125
  return value;
1126
+ },
1127
+
1128
+ _cloneSignalDeclaration() {
1129
+ return createSignal(value);
1078
1130
  }
1079
1131
  };
1080
1132
 
@@ -1117,6 +1169,10 @@ const __signalsModule = (() => {
1117
1169
  return backing.snapshot();
1118
1170
  },
1119
1171
 
1172
+ _cloneSignalDeclaration() {
1173
+ return computed(fn);
1174
+ },
1175
+
1120
1176
  _bindRegistry(registry, id) {
1121
1177
  return registry.effect(() => {
1122
1178
  backing.set(fn.call({
@@ -1141,6 +1197,9 @@ const __signalsModule = (() => {
1141
1197
  [effectKind]: true,
1142
1198
  kind: "effect",
1143
1199
  fn,
1200
+ _cloneSignalDeclaration() {
1201
+ return effect(fn);
1202
+ },
1144
1203
  _bindRegistry(registry) {
1145
1204
  return registry.effect(fn);
1146
1205
  }
@@ -1359,10 +1418,14 @@ const __signalsModule = (() => {
1359
1418
  },
1360
1419
 
1361
1420
  _adoptMany(map = {}) {
1362
- for (const id of Object.keys(map ?? {})) {
1363
- if (entries.has(id)) {
1364
- bindEntry(id, entries.get(id));
1421
+ for (const [id, signalLike] of Object.entries(map ?? {})) {
1422
+ if (!entries.has(id)) {
1423
+ const entry = cloneSignalDeclaration(signalLike);
1424
+ entries.set(id, entry);
1425
+ bindEntry(id, entry);
1426
+ continue;
1365
1427
  }
1428
+ bindEntry(id, entries.get(id));
1366
1429
  }
1367
1430
  return registry;
1368
1431
  }
@@ -1440,6 +1503,16 @@ const __signalsModule = (() => {
1440
1503
  return createSignal(signalLike);
1441
1504
  }
1442
1505
 
1506
+ function cloneSignalDeclaration(signalLike) {
1507
+ if (typeof signalLike?._cloneSignalDeclaration === "function") {
1508
+ return signalLike._cloneSignalDeclaration();
1509
+ }
1510
+ if (isSignalLike(signalLike)) {
1511
+ return createSignal(typeof signalLike.snapshot === "function" ? signalLike.snapshot() : signalLike.value);
1512
+ }
1513
+ return createSignal(signalLike);
1514
+ }
1515
+
1443
1516
  function isSignalLike(value) {
1444
1517
  return Boolean(value && typeof value === "object" && typeof value.subscribe === "function");
1445
1518
  }
@@ -1618,7 +1691,7 @@ const __signalsModule = (() => {
1618
1691
  frame.add(path);
1619
1692
  }
1620
1693
  }
1621
- return { createSignal, computed, effect, createSignalRegistry, isSignalRef, signal };
1694
+ return { createSignal, computed, effect, createSignalRegistry, cloneSignalDeclaration, isSignalRef, signal };
1622
1695
  })();
1623
1696
 
1624
1697
  const __htmlModule = (() => {
@@ -1860,7 +1933,12 @@ const __componentModule = (() => {
1860
1933
  return lazyComponents.get(id);
1861
1934
  },
1862
1935
 
1863
- _adoptMany() {
1936
+ _adoptMany(map = {}) {
1937
+ for (const [id, Component] of Object.entries(map ?? {})) {
1938
+ if (!entries.has(id)) {
1939
+ registry.register(id, Component);
1940
+ }
1941
+ }
1864
1942
  return registry;
1865
1943
  }
1866
1944
  }, registryStore, type);
@@ -1908,12 +1986,16 @@ const __componentModule = (() => {
1908
1986
  });
1909
1987
 
1910
1988
  const output = Component.call(context, props);
1989
+ if (output && typeof output.then === "function") {
1990
+ throw new TypeError(`Component "${componentName(Component)}" returned a Promise. Async components are not supported by synchronous renderComponent(). Use an async partial or handler instead.`);
1991
+ }
1911
1992
  const html = renderScopedTemplate(output);
1912
1993
 
1913
1994
  return {
1914
1995
  html,
1915
1996
  attach(target) {
1916
- for (const hook of attachHooks) {
1997
+ for (let index = 0; index < attachHooks.length; index += 1) {
1998
+ const hook = attachHooks[index];
1917
1999
  runtime.scheduler?.enqueue("lifecycle", () => {
1918
2000
  const cleanup = hook(target);
1919
2001
  if (typeof cleanup === "function") {
@@ -1921,7 +2003,7 @@ const __componentModule = (() => {
1921
2003
  }
1922
2004
  }, {
1923
2005
  scope,
1924
- key: `attach:${attachHooks.indexOf(hook)}`
2006
+ key: `attach:${index}`
1925
2007
  }) ?? runAttachHook(hook, target);
1926
2008
  }
1927
2009
  },
@@ -1929,8 +2011,12 @@ const __componentModule = (() => {
1929
2011
  this.attach(target);
1930
2012
  },
1931
2013
  visible(target, observeVisible) {
1932
- for (const hook of visibleHooks) {
1933
- const cleanup = observeVisible(target, () => {
2014
+ if (visibleHooks.length === 0) {
2015
+ return;
2016
+ }
2017
+ const cleanup = observeVisible(target, () => {
2018
+ for (let index = 0; index < visibleHooks.length; index += 1) {
2019
+ const hook = visibleHooks[index];
1934
2020
  runtime.scheduler?.enqueue("lifecycle", () => {
1935
2021
  const hookCleanup = hook(target);
1936
2022
  if (typeof hookCleanup === "function") {
@@ -1938,12 +2024,12 @@ const __componentModule = (() => {
1938
2024
  }
1939
2025
  }, {
1940
2026
  scope,
1941
- key: `visible:${visibleHooks.indexOf(hook)}`
2027
+ key: `visible:${index}`
1942
2028
  }) ?? runVisibleHook(hook, target);
1943
- });
1944
- if (typeof cleanup === "function") {
1945
- cleanups.push(cleanup);
1946
2029
  }
2030
+ });
2031
+ if (typeof cleanup === "function") {
2032
+ cleanups.push(cleanup);
1947
2033
  }
1948
2034
  },
1949
2035
  cleanup() {
@@ -2199,11 +2285,12 @@ const __serverModule = (() => {
2199
2285
  signal: context.abort
2200
2286
  });
2201
2287
 
2288
+ assertTransportResponse(id, response);
2202
2289
  if (!response.ok) {
2203
2290
  throw new Error(`Server function "${id}" failed with ${response.status}.`);
2204
2291
  }
2205
2292
 
2206
- const result = await readServerResponse(response);
2293
+ const result = await readServerResponse(id, response);
2207
2294
  await applyServerResult(result, runContext);
2208
2295
  return markAppliedServerValue(unwrapServerResult(result));
2209
2296
  }
@@ -2244,6 +2331,11 @@ const __serverModule = (() => {
2244
2331
  return result;
2245
2332
  }
2246
2333
 
2334
+ if (result.error) {
2335
+ markAppliedServerResult(result);
2336
+ throw toError(result.error);
2337
+ }
2338
+
2247
2339
  if (result.signals && context.signals) {
2248
2340
  for (const [path, value] of Object.entries(result.signals)) {
2249
2341
  context.signals.set?.(path, value);
@@ -2262,15 +2354,7 @@ const __serverModule = (() => {
2262
2354
  await context.router?.navigate?.(result.redirect);
2263
2355
  }
2264
2356
 
2265
- if (result.error) {
2266
- throw toError(result.error);
2267
- }
2268
-
2269
- Object.defineProperty(result, appliedServerResult, {
2270
- configurable: true,
2271
- enumerable: false,
2272
- value: true
2273
- });
2357
+ markAppliedServerResult(result);
2274
2358
 
2275
2359
  return result;
2276
2360
  }
@@ -2289,6 +2373,15 @@ const __serverModule = (() => {
2289
2373
  return value;
2290
2374
  }
2291
2375
 
2376
+ function markAppliedServerResult(result) {
2377
+ Object.defineProperty(result, appliedServerResult, {
2378
+ configurable: true,
2379
+ enumerable: false,
2380
+ value: true
2381
+ });
2382
+ return result;
2383
+ }
2384
+
2292
2385
  function defaultInput(context = {}) {
2293
2386
  const form = findForm(context);
2294
2387
  if (form) {
@@ -2366,10 +2459,37 @@ const __serverModule = (() => {
2366
2459
  return namespace([]);
2367
2460
  }
2368
2461
 
2369
- async function readServerResponse(response) {
2462
+ function assertTransportResponse(id, response) {
2463
+ if (!response || typeof response !== "object") {
2464
+ throw new Error(`Server function "${id}" transport returned an invalid response: expected a fetch Response-like object.`);
2465
+ }
2466
+ if (typeof response.ok !== "boolean") {
2467
+ throw new Error(`Server function "${id}" transport returned an invalid response: missing boolean ok.`);
2468
+ }
2469
+ if (!response.headers || typeof response.headers.get !== "function") {
2470
+ throw new Error(`Server function "${id}" transport returned an invalid response: missing headers.get(name).`);
2471
+ }
2472
+ }
2473
+
2474
+ async function readServerResponse(id, response) {
2475
+ if (response.status === 204) {
2476
+ return { value: undefined };
2477
+ }
2370
2478
  const type = response.headers.get("content-type") ?? "";
2371
2479
  if (type.includes("application/json")) {
2372
- return response.json();
2480
+ if (typeof response.json !== "function") {
2481
+ throw new Error(`Server function "${id}" transport returned an invalid response: missing json().`);
2482
+ }
2483
+ try {
2484
+ return await response.json();
2485
+ } catch (cause) {
2486
+ throw new Error(`Server function "${id}" returned invalid JSON: ${errorMessage(cause)}`, {
2487
+ cause
2488
+ });
2489
+ }
2490
+ }
2491
+ if (typeof response.text !== "function") {
2492
+ throw new Error(`Server function "${id}" transport returned an invalid response: missing text().`);
2373
2493
  }
2374
2494
  return { value: await response.text() };
2375
2495
  }
@@ -2482,6 +2602,9 @@ const __serverModule = (() => {
2482
2602
  if (tag === "[object File]" || tag === "[object Blob]" || tag === "[object FormData]") {
2483
2603
  throw new Error("Server proxy JSON transport does not support File, Blob, or FormData values yet.");
2484
2604
  }
2605
+ if (isUnsupportedJsonTransportObject(value, tag)) {
2606
+ throw new Error("Server proxy JSON transport does not support URLSearchParams, Headers, Request, Response, ReadableStream, ArrayBuffer, or typed array values yet.");
2607
+ }
2485
2608
  if (Array.isArray(value)) {
2486
2609
  for (const item of value) {
2487
2610
  assertJsonTransportable(item, stack);
@@ -2495,6 +2618,16 @@ const __serverModule = (() => {
2495
2618
  stack.delete(value);
2496
2619
  }
2497
2620
 
2621
+ function isUnsupportedJsonTransportObject(value, tag = Object.prototype.toString.call(value)) {
2622
+ return tag === "[object URLSearchParams]"
2623
+ || tag === "[object Headers]"
2624
+ || tag === "[object Request]"
2625
+ || tag === "[object Response]"
2626
+ || tag === "[object ReadableStream]"
2627
+ || tag === "[object ArrayBuffer]"
2628
+ || ArrayBuffer.isView(value);
2629
+ }
2630
+
2498
2631
  function joinEndpoint(endpoint, id) {
2499
2632
  return `${String(endpoint).replace(/\/$/, "")}/${encodeURIComponent(id)}`;
2500
2633
  }
@@ -2516,6 +2649,10 @@ const __serverModule = (() => {
2516
2649
  return new Error(String(value));
2517
2650
  }
2518
2651
 
2652
+ function errorMessage(error) {
2653
+ return error instanceof Error ? error.message : String(error);
2654
+ }
2655
+
2519
2656
  function assertServerId(id) {
2520
2657
  if (typeof id !== "string" || id.length === 0) {
2521
2658
  throw new TypeError("Server function id must be a non-empty string.");
@@ -2641,7 +2778,12 @@ const __handlersModule = (() => {
2641
2778
  return results;
2642
2779
  },
2643
2780
 
2644
- _adoptMany() {
2781
+ _adoptMany(map = {}) {
2782
+ for (const [id, fn] of Object.entries(map ?? {})) {
2783
+ if (!handlers.has(id)) {
2784
+ registry.register(id, fn);
2785
+ }
2786
+ }
2645
2787
  return registry;
2646
2788
  }
2647
2789
  }, registryStore, type);
@@ -2748,7 +2890,8 @@ const __schedulerModule = (() => {
2748
2890
  const phases = [...(options.phases ?? defaultPhases)];
2749
2891
  const queues = new Map(phases.map((phase) => [phase, []]));
2750
2892
  const keyedJobs = new Map();
2751
- const destroyedScopes = new Set();
2893
+ const destroyedObjectScopes = new WeakSet();
2894
+ const destroyedPrimitiveScopes = new Set();
2752
2895
  const objectScopeIds = new WeakMap();
2753
2896
  const onError = typeof options.onError === "function" ? options.onError : undefined;
2754
2897
  const maxDepth = options.maxDepth ?? 100;
@@ -2796,7 +2939,7 @@ const __schedulerModule = (() => {
2796
2939
  throw new TypeError("scheduler.enqueue(phase, fn) requires a function.");
2797
2940
  }
2798
2941
  const scope = options.scope;
2799
- if (scope !== undefined && destroyedScopes.has(scope)) {
2942
+ if (isScopeDestroyed(scope)) {
2800
2943
  return noop;
2801
2944
  }
2802
2945
 
@@ -2900,14 +3043,29 @@ const __schedulerModule = (() => {
2900
3043
 
2901
3044
  markScopeDestroyed(scope) {
2902
3045
  if (scope !== undefined) {
2903
- destroyedScopes.add(scope);
3046
+ if (isObjectScope(scope)) {
3047
+ destroyedObjectScopes.add(scope);
3048
+ } else {
3049
+ destroyedPrimitiveScopes.add(scope);
3050
+ }
2904
3051
  api.cancelScope(scope);
2905
3052
  }
2906
3053
  return api;
2907
3054
  },
2908
3055
 
3056
+ reviveScope(scope) {
3057
+ if (scope !== undefined) {
3058
+ if (isObjectScope(scope)) {
3059
+ destroyedObjectScopes.delete(scope);
3060
+ } else {
3061
+ destroyedPrimitiveScopes.delete(scope);
3062
+ }
3063
+ }
3064
+ return api;
3065
+ },
3066
+
2909
3067
  isScopeDestroyed(scope) {
2910
- return scope !== undefined && destroyedScopes.has(scope);
3068
+ return isScopeDestroyed(scope);
2911
3069
  },
2912
3070
 
2913
3071
  inspect() {
@@ -2919,7 +3077,7 @@ const __schedulerModule = (() => {
2919
3077
  strategy,
2920
3078
  phases: [...phases],
2921
3079
  pending: counts,
2922
- scopesDestroyed: destroyedScopes.size,
3080
+ scopesDestroyed: destroyedPrimitiveScopes.size,
2923
3081
  flushing,
2924
3082
  scheduled
2925
3083
  };
@@ -2934,7 +3092,7 @@ const __schedulerModule = (() => {
2934
3092
  queue.length = 0;
2935
3093
  }
2936
3094
  keyedJobs.clear();
2937
- destroyedScopes.clear();
3095
+ destroyedPrimitiveScopes.clear();
2938
3096
  }
2939
3097
  };
2940
3098
 
@@ -2974,7 +3132,7 @@ const __schedulerModule = (() => {
2974
3132
  if (job.key) {
2975
3133
  keyedJobs.delete(job.key);
2976
3134
  }
2977
- if (job.canceled || (job.scope !== undefined && destroyedScopes.has(job.scope))) {
3135
+ if (job.canceled || isScopeDestroyed(job.scope)) {
2978
3136
  continue;
2979
3137
  }
2980
3138
  try {
@@ -3031,6 +3189,20 @@ const __schedulerModule = (() => {
3031
3189
  }
3032
3190
  return String(scope);
3033
3191
  }
3192
+
3193
+ function isScopeDestroyed(scope) {
3194
+ if (scope === undefined) {
3195
+ return false;
3196
+ }
3197
+ if (isObjectScope(scope)) {
3198
+ return destroyedObjectScopes.has(scope);
3199
+ }
3200
+ return destroyedPrimitiveScopes.has(scope);
3201
+ }
3202
+ }
3203
+
3204
+ function isObjectScope(scope) {
3205
+ return (typeof scope === "object" && scope !== null) || typeof scope === "function";
3034
3206
  }
3035
3207
 
3036
3208
  function scheduleMicrotask(fn) {
@@ -3091,6 +3263,7 @@ const __loaderModule = (() => {
3091
3263
 
3092
3264
  scan(rootOrFragment = rootNode) {
3093
3265
  assertActive();
3266
+ reviveScopes(rootOrFragment);
3094
3267
  bindSignalAttributes(rootOrFragment);
3095
3268
  bindClassAttributes(rootOrFragment);
3096
3269
  bindEventAttributes(rootOrFragment);
@@ -3594,6 +3767,12 @@ const __loaderModule = (() => {
3594
3767
  }
3595
3768
  }
3596
3769
 
3770
+ function reviveScopes(scope) {
3771
+ for (const element of elementsIn(scope)) {
3772
+ schedulerInstance.reviveScope?.(element);
3773
+ }
3774
+ }
3775
+
3597
3776
  return api;
3598
3777
  }
3599
3778
 
@@ -3893,7 +4072,12 @@ const __partialsModule = (() => {
3893
4072
  return normalizePartialResult(result, partialContext);
3894
4073
  },
3895
4074
 
3896
- _adoptMany() {
4075
+ _adoptMany(map = {}) {
4076
+ for (const [id, fn] of Object.entries(map ?? {})) {
4077
+ if (!entries.has(id)) {
4078
+ registry.register(id, fn);
4079
+ }
4080
+ }
3897
4081
  return registry;
3898
4082
  }
3899
4083
  }, registryStore, type);
@@ -4045,7 +4229,11 @@ const __routerModule = (() => {
4045
4229
  },
4046
4230
 
4047
4231
  _adoptMany(map = {}) {
4048
- for (const pattern of Object.keys(map ?? {})) {
4232
+ for (const [pattern, definition] of Object.entries(map ?? {})) {
4233
+ if (!entries.has(pattern)) {
4234
+ registry.register(pattern, definition);
4235
+ continue;
4236
+ }
4049
4237
  adoptRoute(pattern, entries.get(pattern));
4050
4238
  }
4051
4239
  return registry;
@@ -4157,7 +4345,10 @@ const __routerModule = (() => {
4157
4345
  }
4158
4346
  const matched = api.match(url);
4159
4347
  if (matched?.route?.partial && partials?.resolve?.(matched.route.partial)) {
4160
- return partials.render(matched.route.partial, matched.params, contextFor(matched));
4348
+ return partials.render(matched.route.partial, matched.params, {
4349
+ ...contextFor(matched),
4350
+ prefetch: true
4351
+ });
4161
4352
  }
4162
4353
  return Promise.resolve(null);
4163
4354
  },
@@ -4538,7 +4729,7 @@ const __appModule = (() => {
4538
4729
  const { createRouteRegistry, createRouter } = __routerModule;
4539
4730
  const { createScheduler } = __schedulerModule;
4540
4731
  const { createServerNamespace } = __serverModule;
4541
- const { createSignal, createSignalRegistry } = __signalsModule;
4732
+ const { cloneSignalDeclaration, createSignal, createSignalRegistry } = __signalsModule;
4542
4733
  const { createRegistryStore } = __registryStoreModule;
4543
4734
  const { attributeName, normalizeAttributeConfig } = __attributesModule;
4544
4735
  const { createLazyRegistry, defineRegistrySnapshot, sameRegistryValue } = __lazyRegistryModule;
@@ -4621,7 +4812,7 @@ const __appModule = (() => {
4621
4812
  registryAssets: options.registryAssets,
4622
4813
  importModule: options.importModule
4623
4814
  });
4624
- const registry = options.registry ?? app.registry.view({ target });
4815
+ const registry = options.registry ?? createRuntimeRegistry(app.registry, { target });
4625
4816
  const signals = options.signals ?? createSignalRegistry(undefined, { registry, type: "signal", lazyRegistry });
4626
4817
  const handlers = options.handlers ?? createHandlerRegistry(undefined, { registry, type: "handler", lazyRegistry });
4627
4818
  const serverCache = createCacheRegistry(undefined, { registry, type: "cache.server" });
@@ -5002,6 +5193,22 @@ const __appModule = (() => {
5002
5193
  registry?.registerMany?.(entries);
5003
5194
  }
5004
5195
 
5196
+ function createRuntimeRegistry(appRegistry, { target } = {}) {
5197
+ const declarations = appRegistry.rawSnapshot();
5198
+ return createRegistryStore({
5199
+ ...declarations,
5200
+ signal: cloneSignalDeclarations(declarations.signal)
5201
+ }, { target });
5202
+ }
5203
+
5204
+ function cloneSignalDeclarations(signals = {}) {
5205
+ const cloned = {};
5206
+ for (const [id, signalLike] of Object.entries(signals ?? {})) {
5207
+ cloned[id] = cloneSignalDeclaration(signalLike);
5208
+ }
5209
+ return cloned;
5210
+ }
5211
+
5005
5212
  function emptyDeclarations() {
5006
5213
  return {
5007
5214
  signal: {},
@@ -5193,6 +5400,13 @@ const __appModule = (() => {
5193
5400
  function setOrRegisterSignal(signals, path, value) {
5194
5401
  const id = String(path).split(".")[0];
5195
5402
  if (signals.has?.(id)) {
5403
+ if (path === id) {
5404
+ const entry = signals._entry?.(id);
5405
+ if (typeof entry?._restore === "function" && isAsyncSignalSnapshot(value)) {
5406
+ entry._restore(value);
5407
+ return;
5408
+ }
5409
+ }
5196
5410
  signals.set(path, value);
5197
5411
  return;
5198
5412
  }
@@ -5202,6 +5416,17 @@ const __appModule = (() => {
5202
5416
  }
5203
5417
  }
5204
5418
 
5419
+ function isAsyncSignalSnapshot(value) {
5420
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
5421
+ return false;
5422
+ }
5423
+ return Object.hasOwn(value, "value")
5424
+ && (Object.hasOwn(value, "loading")
5425
+ || Object.hasOwn(value, "error")
5426
+ || Object.hasOwn(value, "status")
5427
+ || Object.hasOwn(value, "version"));
5428
+ }
5429
+
5205
5430
  function attachServerCache(server, cache) {
5206
5431
  try {
5207
5432
  server.cache = cache;