@torpor/view 1.0.3 → 1.1.0

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/dist/dev.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { i as ProxySignal, n as Region, r as Computed, t as Effect } from "./Effect-COl3aRJV.cjs";
1
+ import { i as ProxySignal, n as Region, r as Computed, t as Effect } from "./Effect-Dewn7MLc.cjs";
2
2
  //#region src/types/ProxyData.d.ts
3
3
  interface ProxyData {
4
4
  target: Record<PropertyKey, any>;
package/dist/dev.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { i as ProxySignal, n as Region, r as Computed, t as Effect } from "./Effect-BTKurOpr.mjs";
1
+ import { i as ProxySignal, n as Region, r as Computed, t as Effect } from "./Effect-DazmAdyC.mjs";
2
2
  //#region src/types/ProxyData.d.ts
3
3
  interface ProxyData {
4
4
  target: Record<PropertyKey, any>;
package/dist/index.cjs CHANGED
@@ -24,7 +24,8 @@ const context = globalThis[CONTEXT_SYMBOL] ??= {
24
24
  mountEffects: [],
25
25
  stashedEvents: [],
26
26
  stashedAnimations: [],
27
- hydrationNode: null
27
+ hydrationNode: null,
28
+ serverValues: null
28
29
  };
29
30
  //#endregion
30
31
  //#region src/render/addAnimation.ts
@@ -1547,7 +1548,7 @@ function trackProxySignal(data, key) {
1547
1548
  * suspend up the cache chain by tainting the active reader, and notifies the
1548
1549
  * nearest `@await` boundary.
1549
1550
  *
1550
- * Return value (stale-while-revalidate, ASYNC.md §6.2): on a refresh suspend
1551
+ * Return value (ASYNC.md → "Stale-while-revalidate"): on a refresh suspend
1551
1552
  * (the computed has resolved before) returns the previously resolved value
1552
1553
  * held in `staleValue`, so readers keep displaying the old content instead of
1553
1554
  * a placeholder — an `@await` boundary thus keeps its content mounted
@@ -2257,10 +2258,23 @@ function runList(region, parent, anchor, buildItems, create, update, noWatch) {
2257
2258
  //#endregion
2258
2259
  //#region src/render/runAwait.ts
2259
2260
  /**
2261
+ * Comment prefix marking the embedded `source: "server"` values that the
2262
+ * server writes after a resolved boundary's anchor (`<!--t-await:[...]-->`,
2263
+ * see ASYNC.md → "Server rendering").
2264
+ */
2265
+ const SERVER_VALUES_PREFIX = "t-await:";
2266
+ /**
2260
2267
  * Renders an `@await` boundary. On the first run, content is rendered
2261
2268
  * speculatively; if any read inside suspends (`didSuspend`), the boundary
2262
2269
  * discards the partial render and shows the `with` branch instead.
2263
2270
  *
2271
+ * Hydration of a server-resolved boundary (ASYNC.md → "Server rendering"): when the server
2272
+ * shipped resolved content, its values ride in a payload comment after the
2273
+ * anchor. The boundary renders the content branch *with* hydration enabled
2274
+ * and `$async` seeds its computeds from the payload, so the server's HTML is
2275
+ * adopted directly — no speculative render, no `with`-branch dance, no
2276
+ * fallback flash.
2277
+ *
2264
2278
  * Fine-grained updates: on subsequent runs the boundary only decides whether
2265
2279
  * to SWITCH branches. It does so from its `pending` set — the suspended
2266
2280
  * computeds recorded by `suspendRead` — dropping entries that resolved and
@@ -2270,7 +2284,7 @@ function runList(region, parent, anchor, buildItems, create, update, noWatch) {
2270
2284
  * non-suspend dependency changes inside content are left to the child
2271
2285
  * effects that read them — the boundary isn't re-run by them at all.
2272
2286
  *
2273
- * Stale-while-revalidate (ASYNC.md §6.2): once content has been produced
2287
+ * Stale-while-revalidate (ASYNC.md): once content has been produced
2274
2288
  * (`hasContent`), a subsequent suspend during a refresh does NOT switch to
2275
2289
  * the `with` branch — the boundary keeps the stale content mounted. `$async`
2276
2290
  * retains the previous resolved value (`Computed.staleValue`) and
@@ -2292,6 +2306,18 @@ function runAwait(region, anchor, renderContent, renderWith, name) {
2292
2306
  let first = true;
2293
2307
  let hasContent = false;
2294
2308
  let theEffect = null;
2309
+ let serverValues = null;
2310
+ if (context.hydrationNode !== null && anchor !== null) {
2311
+ const next = anchor.nextSibling;
2312
+ if (next !== null && isCommentNode(next) && next.data.startsWith(SERVER_VALUES_PREFIX)) {
2313
+ try {
2314
+ serverValues = JSON.parse(next.data.substring(8));
2315
+ } catch {
2316
+ serverValues = null;
2317
+ }
2318
+ next.remove();
2319
+ }
2320
+ }
2295
2321
  const gen = region.generation = (region.generation ?? 0) + 1;
2296
2322
  $run(function runAwait() {
2297
2323
  if (region.generation !== gen) return;
@@ -2312,9 +2338,15 @@ function runAwait(region, anchor, renderContent, renderWith, name) {
2312
2338
  context.awaitBoundary = boundary;
2313
2339
  boundary.suspended = false;
2314
2340
  const savedHydration = context.hydrationNode;
2315
- if (savedHydration !== null) context.hydrationNode = null;
2341
+ const savedServerValues = context.serverValues;
2342
+ if (serverValues !== null && savedHydration !== null) context.serverValues = {
2343
+ values: serverValues,
2344
+ index: 0
2345
+ };
2346
+ else if (savedHydration !== null) context.hydrationNode = null;
2316
2347
  renderBranch(0, renderContent);
2317
- if (savedHydration !== null) context.hydrationNode = savedHydration;
2348
+ context.hydrationNode = savedHydration;
2349
+ context.serverValues = savedServerValues;
2318
2350
  context.awaitBoundary = oldBoundary;
2319
2351
  if (boundary.suspended && renderWith !== null) renderBranch(1, renderWith);
2320
2352
  else if (!boundary.suspended) hasContent = true;
@@ -2518,10 +2550,20 @@ function $batch(fn) {
2518
2550
  * over the computed object), so they fire on both the initial run and every
2519
2551
  * recalculation — `runComputed` and `checkComputed` are unchanged.
2520
2552
  *
2553
+ * Hydration seeding (ASYNC.md → "Server rendering"): while hydrating the content branch of
2554
+ * a boundary whose server HTML embedded resolved `source: "server"` values,
2555
+ * `context.serverValues` is set, and this read consumes the value at the
2556
+ * current position instead of suspending. The thunk still runs — once, in
2557
+ * the background — so the getter's dependencies are tracked and later
2558
+ * dependency changes re-fetch; the embedded value wins the generation race,
2559
+ * so there's no re-fetch wait and no fallback flash.
2560
+ *
2521
2561
  * @param fn A thunk returning the Promise to await. Signal reads inside `fn`
2522
2562
  * are tracked, so the fetch re-runs when dependencies change.
2563
+ * @param _options Accepted so the same getter source compiles into client and
2564
+ * server builds (`source: "server"` fetches during SSR); ignored here.
2523
2565
  */
2524
- function $async(fn) {
2566
+ function $async(fn, _options) {
2525
2567
  if (context.registerComputed === null) throw new Error("$async must be used in a getter");
2526
2568
  const computed = {
2527
2569
  type: 1,
@@ -2574,6 +2616,16 @@ function $async(fn) {
2574
2616
  };
2575
2617
  context.registerComputed(computed);
2576
2618
  runComputed(computed);
2619
+ const serverValues = context.serverValues;
2620
+ if (serverValues !== null && serverValues.index < serverValues.values.length) {
2621
+ computed.generation++;
2622
+ computed.didSuspend = false;
2623
+ computed.didError = false;
2624
+ computed.hasResolved = true;
2625
+ computed.lastErrored = false;
2626
+ computed.value = serverValues.values[serverValues.index++];
2627
+ computed.staleValue = computed.value;
2628
+ }
2577
2629
  return computed.value;
2578
2630
  }
2579
2631
  //#endregion
@@ -2703,7 +2755,7 @@ function $onmount(fn) {
2703
2755
  * subscription but don't propagate taint or notify a `@await` boundary.
2704
2756
  * This lets `$pending` return a plain boolean without itself suspending.
2705
2757
  *
2706
- * Quiet-on-refresh semantics (ASYNC.md §7.4): a suspend is *quiet* — and
2758
+ * Quiet-on-refresh semantics (ASYNC.md → "Loud vs quiet"): a suspend is *quiet* — and
2707
2759
  * therefore `$pending` returns `false` for it — when the computed has resolved
2708
2760
  * before and the re-fetch was a *silent* `$refresh(fn, { silent: true })` (a
2709
2761
  * bare refresh with no tracked dependency change, used for background
@@ -2730,7 +2782,7 @@ function $pending(fn) {
2730
2782
  //#region src/watch/$refresh.ts
2731
2783
  /**
2732
2784
  * Re-fetches the `$async` getters read inside `fn` without changing a
2733
- * dependency. A companion to `$pending` (ASYNC.md §6.2): pull-to-refresh,
2785
+ * dependency. A companion to `$pending` (ASYNC.md): pull-to-refresh,
2734
2786
  * refresh buttons, refetch-on-focus, polling, retry-after-error.
2735
2787
  *
2736
2788
  * `fn` is run in a tracking context that collects every `$async` computed it
package/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { n as SlotRender, t as Component } from "./Component-0MH0zd-m.cjs";
2
2
  import { t as Cleanup } from "./Cleanup-D0wvGW5d.cjs";
3
- import { n as Region, t as Effect } from "./Effect-COl3aRJV.cjs";
4
- import { a as buildStyles, c as ClassValue, i as StreamSource, n as fromServer, o as StyleValue, r as fromElement, s as buildClasses, t as fromWebSocket } from "./fromWebSocket-DeB35Q4w.cjs";
3
+ import { n as Region, t as Effect } from "./Effect-Dewn7MLc.cjs";
4
+ import { a as StreamSource, c as buildClasses, i as fromElement, l as ClassValue, n as fromWebSocket, o as buildStyles, r as fromServer, s as StyleValue, t as AsyncOptions } from "./AsyncOptions-BtMe2PAd.cjs";
5
5
  //#region src/types/Animation.d.ts
6
6
  interface Animation {
7
7
  keyframes: Keyframe[] | PropertyIndexedKeyframes;
@@ -345,6 +345,13 @@ declare function runList(region: Region, parent: ParentNode, anchor: Node | null
345
345
  * speculatively; if any read inside suspends (`didSuspend`), the boundary
346
346
  * discards the partial render and shows the `with` branch instead.
347
347
  *
348
+ * Hydration of a server-resolved boundary (ASYNC.md → "Server rendering"): when the server
349
+ * shipped resolved content, its values ride in a payload comment after the
350
+ * anchor. The boundary renders the content branch *with* hydration enabled
351
+ * and `$async` seeds its computeds from the payload, so the server's HTML is
352
+ * adopted directly — no speculative render, no `with`-branch dance, no
353
+ * fallback flash.
354
+ *
348
355
  * Fine-grained updates: on subsequent runs the boundary only decides whether
349
356
  * to SWITCH branches. It does so from its `pending` set — the suspended
350
357
  * computeds recorded by `suspendRead` — dropping entries that resolved and
@@ -354,7 +361,7 @@ declare function runList(region: Region, parent: ParentNode, anchor: Node | null
354
361
  * non-suspend dependency changes inside content are left to the child
355
362
  * effects that read them — the boundary isn't re-run by them at all.
356
363
  *
357
- * Stale-while-revalidate (ASYNC.md §6.2): once content has been produced
364
+ * Stale-while-revalidate (ASYNC.md): once content has been produced
358
365
  * (`hasContent`), a subsequent suspend during a refresh does NOT switch to
359
366
  * the `with` branch — the boundary keeps the stale content mounted. `$async`
360
367
  * retains the previous resolved value (`Computed.staleValue`) and
@@ -478,10 +485,20 @@ declare function $batch<T>(fn: () => T): T;
478
485
  * over the computed object), so they fire on both the initial run and every
479
486
  * recalculation — `runComputed` and `checkComputed` are unchanged.
480
487
  *
488
+ * Hydration seeding (ASYNC.md → "Server rendering"): while hydrating the content branch of
489
+ * a boundary whose server HTML embedded resolved `source: "server"` values,
490
+ * `context.serverValues` is set, and this read consumes the value at the
491
+ * current position instead of suspending. The thunk still runs — once, in
492
+ * the background — so the getter's dependencies are tracked and later
493
+ * dependency changes re-fetch; the embedded value wins the generation race,
494
+ * so there's no re-fetch wait and no fallback flash.
495
+ *
481
496
  * @param fn A thunk returning the Promise to await. Signal reads inside `fn`
482
497
  * are tracked, so the fetch re-runs when dependencies change.
498
+ * @param _options Accepted so the same getter source compiles into client and
499
+ * server builds (`source: "server"` fetches during SSR); ignored here.
483
500
  */
484
- declare function $async<T>(fn: () => Promise<T>): T;
501
+ declare function $async<T>(fn: () => Promise<T>, _options?: AsyncOptions): T;
485
502
  //#endregion
486
503
  //#region src/watch/$bind.d.ts
487
504
  /**
@@ -573,7 +590,7 @@ declare function $peek<T>(fn: () => T): T;
573
590
  * subscription but don't propagate taint or notify a `@await` boundary.
574
591
  * This lets `$pending` return a plain boolean without itself suspending.
575
592
  *
576
- * Quiet-on-refresh semantics (ASYNC.md §7.4): a suspend is *quiet* — and
593
+ * Quiet-on-refresh semantics (ASYNC.md → "Loud vs quiet"): a suspend is *quiet* — and
577
594
  * therefore `$pending` returns `false` for it — when the computed has resolved
578
595
  * before and the re-fetch was a *silent* `$refresh(fn, { silent: true })` (a
579
596
  * bare refresh with no tracked dependency change, used for background
@@ -603,7 +620,7 @@ interface RefreshOptions {
603
620
  }
604
621
  /**
605
622
  * Re-fetches the `$async` getters read inside `fn` without changing a
606
- * dependency. A companion to `$pending` (ASYNC.md §6.2): pull-to-refresh,
623
+ * dependency. A companion to `$pending` (ASYNC.md): pull-to-refresh,
607
624
  * refresh buttons, refetch-on-focus, polling, retry-after-error.
608
625
  *
609
626
  * `fn` is run in a tracking context that collects every `$async` computed it
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../src/types/Animation.ts","../src/render/addAnimation.ts","../src/render/addEvent.ts","../src/render/addElement.ts","../src/render/addFragment.ts","../src/render/applyProps.ts","../src/render/clearLayoutSlot.ts","../src/render/fillLayoutSlot.ts","../src/render/formatText.ts","../src/render/firstInsideNode.ts","../src/render/getFragment.ts","../src/render/getElementFragment.ts","../src/render/hydrate.ts","../src/render/mount.ts","../src/render/unmount.ts","../src/types/ListItemSpec.ts","../src/types/ListItem.ts","../src/render/newListItem.ts","../src/render/newRegion.ts","../src/render/nodeAnchor.ts","../src/render/nodeChild.ts","../src/render/nodeNext.ts","../src/render/nodeRootElement.ts","../src/render/nodeRoot.ts","../src/render/nodeSkip.ts","../src/render/popRegion.ts","../src/render/pushRegion.ts","../src/render/rerunRegionEffects.ts","../src/render/restoreHydration.ts","../src/render/runControl.ts","../src/render/runControlBranch.ts","../src/render/runList.ts","../src/render/runAwait.ts","../src/render/runTry.ts","../src/render/saveHydration.ts","../src/render/headElement.ts","../src/render/setAttribute.ts","../src/render/setDynamicElement.ts","../src/types/Bindable.ts","../src/watch/$batch.ts","../src/watch/$async.ts","../src/watch/$bind.ts","../src/watch/$cache.ts","../src/watch/$onmount.ts","../src/watch/$peek.ts","../src/watch/$pending.ts","../src/watch/$refresh.ts","../src/watch/$run.ts","../src/watch/$stream.ts","../src/watch/$unwrap.ts","../src/types/WatchOptions.ts","../src/watch/$watch.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/types/Animation.ts","../src/render/addAnimation.ts","../src/render/addEvent.ts","../src/render/addElement.ts","../src/render/addFragment.ts","../src/render/applyProps.ts","../src/render/clearLayoutSlot.ts","../src/render/fillLayoutSlot.ts","../src/render/formatText.ts","../src/render/firstInsideNode.ts","../src/render/getFragment.ts","../src/render/getElementFragment.ts","../src/render/hydrate.ts","../src/render/mount.ts","../src/render/unmount.ts","../src/types/ListItemSpec.ts","../src/types/ListItem.ts","../src/render/newListItem.ts","../src/render/newRegion.ts","../src/render/nodeAnchor.ts","../src/render/nodeChild.ts","../src/render/nodeNext.ts","../src/render/nodeRootElement.ts","../src/render/nodeRoot.ts","../src/render/nodeSkip.ts","../src/render/popRegion.ts","../src/render/pushRegion.ts","../src/render/rerunRegionEffects.ts","../src/render/restoreHydration.ts","../src/render/runControl.ts","../src/render/runControlBranch.ts","../src/render/runList.ts","../src/render/runAwait.ts","../src/render/runTry.ts","../src/render/saveHydration.ts","../src/render/headElement.ts","../src/render/setAttribute.ts","../src/render/setDynamicElement.ts","../src/types/Bindable.ts","../src/watch/$batch.ts","../src/watch/$async.ts","../src/watch/$bind.ts","../src/watch/$cache.ts","../src/watch/$onmount.ts","../src/watch/$peek.ts","../src/watch/$pending.ts","../src/watch/$refresh.ts","../src/watch/$run.ts","../src/watch/$stream.ts","../src/watch/$unwrap.ts","../src/types/WatchOptions.ts","../src/watch/$watch.ts"],"mappings":";;;;;UAAyB;EACxB,WAAW,aAAa;EACxB,mBAAmB;;;;iBCCI,aAAa,IAAI,aAAa,QAAQ,WAAW,OAAO;;;iBCDxD,SACvB,IAAI,SACJ,cACA,YAAA,MAAkB,SAAS;;;;;;;;;;;;;;;;;;;;;;iBCiBJ,WAAW,MAAM,SAAS,QAAQ,YAAY,QAAQ;;;iBCnBtD,YACvB,UAAU,kBACV,QAAQ,YACR,QAAQ,aACR,UAAU,WACV,YAAY;;;iBCLW,WACvB,IAAI,SACJ,OAAO,iCACP;;;;;;;;;;iBCKuB,gBAAgB,QAAQ;;;;;;;;;;;;;;;;;;iBCYxB,eACvB,WAAW,WACX,MAAM,YACN,QAAQ,YACR,QAAQ,aACR,SAAS,OAAO,mBAChB,WAAW,OAAO,oBAChB;;;iBC5BqB,WAAW;;;;;;;;iBCiBX,gBAAgB,QAAQ,YAAY;;;iBCnBpC,YACvB,UAAU,UACV,OAAO,oBACP,eACA,cACA,eACE;;;;;;;;;;;;;;;;;;;;;;;;;;;iBCkBqB,mBACvB,UAAU,UACV,OAAO,WACP,eACA,cACA,eACE;;;;;;;;;iBChBqB,QACvB,QAAQ,YACR,WAAW,WACX,QAAQ,qBACR,QAAQ,eAAe;;;;;;;;;;iBCJA,MACvB,QAAQ,YACR,WAAW,WACX,QAAQ,qBACR,QAAQ,eAAe;;;;;;;;;;;;;;;iBCFA,QAAQ,QAAQ;;;;;;;;;;;;;;;;;;;UCAf;EACxB;EACA;;;;UCfwB,iBAAiB,QAAQ;;;iBCD1B,YACvB,MAAM,OAAO,mBACb,WACA,gBACE;;;iBCJqB,UAAU,gBAAgB;;;;;;;;;;;;;;;;;iBCkB1B,WAAW,MAAM,YAAY;;;;;;;;;;iBCX7B,UAAU,QAAQ,OAAO;;;;;;;;;;;iBCGzB,SAAS,MAAM,WAAW,iBAAe;;;;;;;;;;;;;;;;;iBCKzC,gBAAgB,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;iBCShC,SAAS,QAAQ,MAAM,iBAAe;;;;;;;;;;;iBCftC,SAAS,MAAM,WAAW,gBAAgB;;;iBCP1C,UAAU,WAAW;;;iBCArB,WAAW,QAAQ,QAAQ,qBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;iBCyB9C,mBAAmB,QAAQ,QAAQ;;;;;;;;;;;;;;;;;iBCbnC,iBAAiB,MAAM;;;;;;;iBCLvB,WACvB,QAAQ,QACR,QAAQ,aACR,SAAS,QAAQ,sBACjB;;;iBCZuB,iBAAiB,QAAQ,QAAQ,kBAAkB;;;;;;;;;;;;;;;iBCkBnD,QACvB,QAAQ,QACR,QAAQ,YACR,QAAQ,aACR,kBAAkB,gBAClB,SAAS,MAAM,UAAU,QAAQ,sBACjC,SAAS,SAAS,UAAU,SAAS,uBACrC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBCyBuB,SACvB,QAAQ,QACR,QAAQ,aACR,gBAAgB,QAAQ,sBACxB,cAAc,QAAQ,8BACtB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBCAuB,OACvB,QAAQ,QACR,QAAQ,aACR,YAAY,QAAQ,sBACpB,eAAe,QAAQ,aAAa,6BACpC;;;;;;;;;iBCvDuB,iBAAiB;;;;;;;;;iBCFjB,YAAY,iBAAiB,mBAAmB;;;iBCNhD,aAAa,IAAI,SAAS,cAAc;;;iBCKxC,kBAAkB,IAAI,aAAa,cAAc;;;;;;;;;;;;;;;;;;;KCWpE,SAAS,KAAK;;;;;;;;;iBCNK,OAAO,GAAG,UAAU,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;iBCsBxB,OAAO,GAAG,UAAU,QAAQ,IAAI,WAAW,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBCG1D,MACvB,OAAO,OAAO,mBACd,OAAO,OAAO,kCACX;;;;;;;;iBC5BoB,OAAO,GAAG,UAAU,IAAI;;;;;;;;;;;;;;;;;;;;;;;;iBCcxB,SAAS,UAAU;;;;;;;;;;;iBCdnB,MAAM,GAAG,UAAU,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;iBCcvB,SAAS;;;;;;UCZhB;;;;;;;;EAQhB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA4CuB,SAAS,eAAe,UAAU;;;;;;;;;;iBChDlC,KACvB,UAAU,gBACV,eACA,UAAU,KAAK,0CACb;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBCqBqB,QAAQ,GAC/B,QAAQ,aAAa,IACrB,UAAU,OAAO,YACjB;EAAY;;;;;;;;;iBCrCW,QAAQ,UAAU,OAAO,mBAAmB,QAAQ,IAAI;;;;;;UCJvD;;;;EAIxB;;;;;;;;;;;;;iBCoBuB,OAAO,kBAAkB,QAAQ,GAAG,UAAU,eAAe"}
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { n as SlotRender, t as Component } from "./Component-0MH0zd-m.mjs";
2
2
  import { t as Cleanup } from "./Cleanup-D0wvGW5d.mjs";
3
- import { n as Region, t as Effect } from "./Effect-BTKurOpr.mjs";
4
- import { a as buildStyles, c as ClassValue, i as StreamSource, n as fromServer, o as StyleValue, r as fromElement, s as buildClasses, t as fromWebSocket } from "./fromWebSocket-B52kN3-W.mjs";
3
+ import { n as Region, t as Effect } from "./Effect-DazmAdyC.mjs";
4
+ import { a as StreamSource, c as buildClasses, i as fromElement, l as ClassValue, n as fromWebSocket, o as buildStyles, r as fromServer, s as StyleValue, t as AsyncOptions } from "./AsyncOptions-ClS1_ERX.mjs";
5
5
  //#region src/types/Animation.d.ts
6
6
  interface Animation {
7
7
  keyframes: Keyframe[] | PropertyIndexedKeyframes;
@@ -345,6 +345,13 @@ declare function runList(region: Region, parent: ParentNode, anchor: Node | null
345
345
  * speculatively; if any read inside suspends (`didSuspend`), the boundary
346
346
  * discards the partial render and shows the `with` branch instead.
347
347
  *
348
+ * Hydration of a server-resolved boundary (ASYNC.md → "Server rendering"): when the server
349
+ * shipped resolved content, its values ride in a payload comment after the
350
+ * anchor. The boundary renders the content branch *with* hydration enabled
351
+ * and `$async` seeds its computeds from the payload, so the server's HTML is
352
+ * adopted directly — no speculative render, no `with`-branch dance, no
353
+ * fallback flash.
354
+ *
348
355
  * Fine-grained updates: on subsequent runs the boundary only decides whether
349
356
  * to SWITCH branches. It does so from its `pending` set — the suspended
350
357
  * computeds recorded by `suspendRead` — dropping entries that resolved and
@@ -354,7 +361,7 @@ declare function runList(region: Region, parent: ParentNode, anchor: Node | null
354
361
  * non-suspend dependency changes inside content are left to the child
355
362
  * effects that read them — the boundary isn't re-run by them at all.
356
363
  *
357
- * Stale-while-revalidate (ASYNC.md §6.2): once content has been produced
364
+ * Stale-while-revalidate (ASYNC.md): once content has been produced
358
365
  * (`hasContent`), a subsequent suspend during a refresh does NOT switch to
359
366
  * the `with` branch — the boundary keeps the stale content mounted. `$async`
360
367
  * retains the previous resolved value (`Computed.staleValue`) and
@@ -478,10 +485,20 @@ declare function $batch<T>(fn: () => T): T;
478
485
  * over the computed object), so they fire on both the initial run and every
479
486
  * recalculation — `runComputed` and `checkComputed` are unchanged.
480
487
  *
488
+ * Hydration seeding (ASYNC.md → "Server rendering"): while hydrating the content branch of
489
+ * a boundary whose server HTML embedded resolved `source: "server"` values,
490
+ * `context.serverValues` is set, and this read consumes the value at the
491
+ * current position instead of suspending. The thunk still runs — once, in
492
+ * the background — so the getter's dependencies are tracked and later
493
+ * dependency changes re-fetch; the embedded value wins the generation race,
494
+ * so there's no re-fetch wait and no fallback flash.
495
+ *
481
496
  * @param fn A thunk returning the Promise to await. Signal reads inside `fn`
482
497
  * are tracked, so the fetch re-runs when dependencies change.
498
+ * @param _options Accepted so the same getter source compiles into client and
499
+ * server builds (`source: "server"` fetches during SSR); ignored here.
483
500
  */
484
- declare function $async<T>(fn: () => Promise<T>): T;
501
+ declare function $async<T>(fn: () => Promise<T>, _options?: AsyncOptions): T;
485
502
  //#endregion
486
503
  //#region src/watch/$bind.d.ts
487
504
  /**
@@ -573,7 +590,7 @@ declare function $peek<T>(fn: () => T): T;
573
590
  * subscription but don't propagate taint or notify a `@await` boundary.
574
591
  * This lets `$pending` return a plain boolean without itself suspending.
575
592
  *
576
- * Quiet-on-refresh semantics (ASYNC.md §7.4): a suspend is *quiet* — and
593
+ * Quiet-on-refresh semantics (ASYNC.md → "Loud vs quiet"): a suspend is *quiet* — and
577
594
  * therefore `$pending` returns `false` for it — when the computed has resolved
578
595
  * before and the re-fetch was a *silent* `$refresh(fn, { silent: true })` (a
579
596
  * bare refresh with no tracked dependency change, used for background
@@ -603,7 +620,7 @@ interface RefreshOptions {
603
620
  }
604
621
  /**
605
622
  * Re-fetches the `$async` getters read inside `fn` without changing a
606
- * dependency. A companion to `$pending` (ASYNC.md §6.2): pull-to-refresh,
623
+ * dependency. A companion to `$pending` (ASYNC.md): pull-to-refresh,
607
624
  * refresh buttons, refetch-on-focus, polling, retry-after-error.
608
625
  *
609
626
  * `fn` is run in a tracking context that collects every `$async` computed it
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/types/Animation.ts","../src/render/addAnimation.ts","../src/render/addEvent.ts","../src/render/addElement.ts","../src/render/addFragment.ts","../src/render/applyProps.ts","../src/render/clearLayoutSlot.ts","../src/render/fillLayoutSlot.ts","../src/render/formatText.ts","../src/render/firstInsideNode.ts","../src/render/getFragment.ts","../src/render/getElementFragment.ts","../src/render/hydrate.ts","../src/render/mount.ts","../src/render/unmount.ts","../src/types/ListItemSpec.ts","../src/types/ListItem.ts","../src/render/newListItem.ts","../src/render/newRegion.ts","../src/render/nodeAnchor.ts","../src/render/nodeChild.ts","../src/render/nodeNext.ts","../src/render/nodeRootElement.ts","../src/render/nodeRoot.ts","../src/render/nodeSkip.ts","../src/render/popRegion.ts","../src/render/pushRegion.ts","../src/render/rerunRegionEffects.ts","../src/render/restoreHydration.ts","../src/render/runControl.ts","../src/render/runControlBranch.ts","../src/render/runList.ts","../src/render/runAwait.ts","../src/render/runTry.ts","../src/render/saveHydration.ts","../src/render/headElement.ts","../src/render/setAttribute.ts","../src/render/setDynamicElement.ts","../src/types/Bindable.ts","../src/watch/$batch.ts","../src/watch/$async.ts","../src/watch/$bind.ts","../src/watch/$cache.ts","../src/watch/$onmount.ts","../src/watch/$peek.ts","../src/watch/$pending.ts","../src/watch/$refresh.ts","../src/watch/$run.ts","../src/watch/$stream.ts","../src/watch/$unwrap.ts","../src/types/WatchOptions.ts","../src/watch/$watch.ts"],"mappings":";;;;;UAAyB;EACxB,WAAW,aAAa;EACxB,mBAAmB;;;;iBCCI,aAAa,IAAI,aAAa,QAAQ,WAAW,OAAO;;;iBCDxD,SACvB,IAAI,SACJ,cACA,YAAA,MAAkB,SAAS;;;;;;;;;;;;;;;;;;;;;;iBCiBJ,WAAW,MAAM,SAAS,QAAQ,YAAY,QAAQ;;;iBCnBtD,YACvB,UAAU,kBACV,QAAQ,YACR,QAAQ,aACR,UAAU,WACV,YAAY;;;iBCLW,WACvB,IAAI,SACJ,OAAO,iCACP;;;;;;;;;;iBCKuB,gBAAgB,QAAQ;;;;;;;;;;;;;;;;;;iBCYxB,eACvB,WAAW,WACX,MAAM,YACN,QAAQ,YACR,QAAQ,aACR,SAAS,OAAO,mBAChB,WAAW,OAAO,oBAChB;;;iBC5BqB,WAAW;;;;;;;;iBCiBX,gBAAgB,QAAQ,YAAY;;;iBCnBpC,YACvB,UAAU,UACV,OAAO,oBACP,eACA,cACA,eACE;;;;;;;;;;;;;;;;;;;;;;;;;;;iBCkBqB,mBACvB,UAAU,UACV,OAAO,WACP,eACA,cACA,eACE;;;;;;;;;iBChBqB,QACvB,QAAQ,YACR,WAAW,WACX,QAAQ,qBACR,QAAQ,eAAe;;;;;;;;;;iBCJA,MACvB,QAAQ,YACR,WAAW,WACX,QAAQ,qBACR,QAAQ,eAAe;;;;;;;;;;;;;;;iBCFA,QAAQ,QAAQ;;;;;;;;;;;;;;;;;;;UCAf;EACxB;EACA;;;;UCfwB,iBAAiB,QAAQ;;;iBCD1B,YACvB,MAAM,OAAO,mBACb,WACA,gBACE;;;iBCJqB,UAAU,gBAAgB;;;;;;;;;;;;;;;;;iBCkB1B,WAAW,MAAM,YAAY;;;;;;;;;;iBCX7B,UAAU,QAAQ,OAAO;;;;;;;;;;;iBCGzB,SAAS,MAAM,WAAW,iBAAe;;;;;;;;;;;;;;;;;iBCKzC,gBAAgB,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;iBCShC,SAAS,QAAQ,MAAM,iBAAe;;;;;;;;;;;iBCftC,SAAS,MAAM,WAAW,gBAAgB;;;iBCP1C,UAAU,WAAW;;;iBCArB,WAAW,QAAQ,QAAQ,qBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;iBCyB9C,mBAAmB,QAAQ,QAAQ;;;;;;;;;;;;;;;;;iBCbnC,iBAAiB,MAAM;;;;;;;iBCLvB,WACvB,QAAQ,QACR,QAAQ,aACR,SAAS,QAAQ,sBACjB;;;iBCZuB,iBAAiB,QAAQ,QAAQ,kBAAkB;;;;;;;;;;;;;;;iBCkBnD,QACvB,QAAQ,QACR,QAAQ,YACR,QAAQ,aACR,kBAAkB,gBAClB,SAAS,MAAM,UAAU,QAAQ,sBACjC,SAAS,SAAS,UAAU,SAAS,uBACrC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBCUuB,SACvB,QAAQ,QACR,QAAQ,aACR,gBAAgB,QAAQ,sBACxB,cAAc,QAAQ,8BACtB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBCeuB,OACvB,QAAQ,QACR,QAAQ,aACR,YAAY,QAAQ,sBACpB,eAAe,QAAQ,aAAa,6BACpC;;;;;;;;;iBCvDuB,iBAAiB;;;;;;;;;iBCFjB,YAAY,iBAAiB,mBAAmB;;;iBCNhD,aAAa,IAAI,SAAS,cAAc;;;iBCKxC,kBAAkB,IAAI,aAAa,cAAc;;;;;;;;;;;;;;;;;;;KCWpE,SAAS,KAAK;;;;;;;;;iBCNK,OAAO,GAAG,UAAU,IAAI;;;;;;;;;;;;;;;;iBCWxB,OAAO,GAAG,UAAU,QAAQ,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBCcjC,MACvB,OAAO,OAAO,mBACd,OAAO,OAAO,kCACX;;;;;;;;iBC5BoB,OAAO,GAAG,UAAU,IAAI;;;;;;;;;;;;;;;;;;;;;;;;iBCcxB,SAAS,UAAU;;;;;;;;;;;iBCdnB,MAAM,GAAG,UAAU,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;iBCcvB,SAAS;;;;;;UCZhB;;;;;;;;EAQhB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA4CuB,SAAS,eAAe,UAAU;;;;;;;;;;iBChDlC,KACvB,UAAU,gBACV,eACA,UAAU,KAAK,0CACb;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBCqBqB,QAAQ,GAC/B,QAAQ,aAAa,IACrB,UAAU,OAAO,YACjB;EAAY;;;;;;;;;iBCrCW,QAAQ,UAAU,OAAO,mBAAmB,QAAQ,IAAI;;;;;;UCJvD;;;;EAIxB;;;;;;;;;;;;;iBCoBuB,OAAO,kBAAkB,QAAQ,GAAG,UAAU,eAAe"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/types/Animation.ts","../src/render/addAnimation.ts","../src/render/addEvent.ts","../src/render/addElement.ts","../src/render/addFragment.ts","../src/render/applyProps.ts","../src/render/clearLayoutSlot.ts","../src/render/fillLayoutSlot.ts","../src/render/formatText.ts","../src/render/firstInsideNode.ts","../src/render/getFragment.ts","../src/render/getElementFragment.ts","../src/render/hydrate.ts","../src/render/mount.ts","../src/render/unmount.ts","../src/types/ListItemSpec.ts","../src/types/ListItem.ts","../src/render/newListItem.ts","../src/render/newRegion.ts","../src/render/nodeAnchor.ts","../src/render/nodeChild.ts","../src/render/nodeNext.ts","../src/render/nodeRootElement.ts","../src/render/nodeRoot.ts","../src/render/nodeSkip.ts","../src/render/popRegion.ts","../src/render/pushRegion.ts","../src/render/rerunRegionEffects.ts","../src/render/restoreHydration.ts","../src/render/runControl.ts","../src/render/runControlBranch.ts","../src/render/runList.ts","../src/render/runAwait.ts","../src/render/runTry.ts","../src/render/saveHydration.ts","../src/render/headElement.ts","../src/render/setAttribute.ts","../src/render/setDynamicElement.ts","../src/types/Bindable.ts","../src/watch/$batch.ts","../src/watch/$async.ts","../src/watch/$bind.ts","../src/watch/$cache.ts","../src/watch/$onmount.ts","../src/watch/$peek.ts","../src/watch/$pending.ts","../src/watch/$refresh.ts","../src/watch/$run.ts","../src/watch/$stream.ts","../src/watch/$unwrap.ts","../src/types/WatchOptions.ts","../src/watch/$watch.ts"],"mappings":";;;;;UAAyB;EACxB,WAAW,aAAa;EACxB,mBAAmB;;;;iBCCI,aAAa,IAAI,aAAa,QAAQ,WAAW,OAAO;;;iBCDxD,SACvB,IAAI,SACJ,cACA,YAAA,MAAkB,SAAS;;;;;;;;;;;;;;;;;;;;;;iBCiBJ,WAAW,MAAM,SAAS,QAAQ,YAAY,QAAQ;;;iBCnBtD,YACvB,UAAU,kBACV,QAAQ,YACR,QAAQ,aACR,UAAU,WACV,YAAY;;;iBCLW,WACvB,IAAI,SACJ,OAAO,iCACP;;;;;;;;;;iBCKuB,gBAAgB,QAAQ;;;;;;;;;;;;;;;;;;iBCYxB,eACvB,WAAW,WACX,MAAM,YACN,QAAQ,YACR,QAAQ,aACR,SAAS,OAAO,mBAChB,WAAW,OAAO,oBAChB;;;iBC5BqB,WAAW;;;;;;;;iBCiBX,gBAAgB,QAAQ,YAAY;;;iBCnBpC,YACvB,UAAU,UACV,OAAO,oBACP,eACA,cACA,eACE;;;;;;;;;;;;;;;;;;;;;;;;;;;iBCkBqB,mBACvB,UAAU,UACV,OAAO,WACP,eACA,cACA,eACE;;;;;;;;;iBChBqB,QACvB,QAAQ,YACR,WAAW,WACX,QAAQ,qBACR,QAAQ,eAAe;;;;;;;;;;iBCJA,MACvB,QAAQ,YACR,WAAW,WACX,QAAQ,qBACR,QAAQ,eAAe;;;;;;;;;;;;;;;iBCFA,QAAQ,QAAQ;;;;;;;;;;;;;;;;;;;UCAf;EACxB;EACA;;;;UCfwB,iBAAiB,QAAQ;;;iBCD1B,YACvB,MAAM,OAAO,mBACb,WACA,gBACE;;;iBCJqB,UAAU,gBAAgB;;;;;;;;;;;;;;;;;iBCkB1B,WAAW,MAAM,YAAY;;;;;;;;;;iBCX7B,UAAU,QAAQ,OAAO;;;;;;;;;;;iBCGzB,SAAS,MAAM,WAAW,iBAAe;;;;;;;;;;;;;;;;;iBCKzC,gBAAgB,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;iBCShC,SAAS,QAAQ,MAAM,iBAAe;;;;;;;;;;;iBCftC,SAAS,MAAM,WAAW,gBAAgB;;;iBCP1C,UAAU,WAAW;;;iBCArB,WAAW,QAAQ,QAAQ,qBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;iBCyB9C,mBAAmB,QAAQ,QAAQ;;;;;;;;;;;;;;;;;iBCbnC,iBAAiB,MAAM;;;;;;;iBCLvB,WACvB,QAAQ,QACR,QAAQ,aACR,SAAS,QAAQ,sBACjB;;;iBCZuB,iBAAiB,QAAQ,QAAQ,kBAAkB;;;;;;;;;;;;;;;iBCkBnD,QACvB,QAAQ,QACR,QAAQ,YACR,QAAQ,aACR,kBAAkB,gBAClB,SAAS,MAAM,UAAU,QAAQ,sBACjC,SAAS,SAAS,UAAU,SAAS,uBACrC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBCyBuB,SACvB,QAAQ,QACR,QAAQ,aACR,gBAAgB,QAAQ,sBACxB,cAAc,QAAQ,8BACtB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBCAuB,OACvB,QAAQ,QACR,QAAQ,aACR,YAAY,QAAQ,sBACpB,eAAe,QAAQ,aAAa,6BACpC;;;;;;;;;iBCvDuB,iBAAiB;;;;;;;;;iBCFjB,YAAY,iBAAiB,mBAAmB;;;iBCNhD,aAAa,IAAI,SAAS,cAAc;;;iBCKxC,kBAAkB,IAAI,aAAa,cAAc;;;;;;;;;;;;;;;;;;;KCWpE,SAAS,KAAK;;;;;;;;;iBCNK,OAAO,GAAG,UAAU,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;iBCsBxB,OAAO,GAAG,UAAU,QAAQ,IAAI,WAAW,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBCG1D,MACvB,OAAO,OAAO,mBACd,OAAO,OAAO,kCACX;;;;;;;;iBC5BoB,OAAO,GAAG,UAAU,IAAI;;;;;;;;;;;;;;;;;;;;;;;;iBCcxB,SAAS,UAAU;;;;;;;;;;;iBCdnB,MAAM,GAAG,UAAU,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;iBCcvB,SAAS;;;;;;UCZhB;;;;;;;;EAQhB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA4CuB,SAAS,eAAe,UAAU;;;;;;;;;;iBChDlC,KACvB,UAAU,gBACV,eACA,UAAU,KAAK,0CACb;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBCqBqB,QAAQ,GAC/B,QAAQ,aAAa,IACrB,UAAU,OAAO,YACjB;EAAY;;;;;;;;;iBCrCW,QAAQ,UAAU,OAAO,mBAAmB,QAAQ,IAAI;;;;;;UCJvD;;;;EAIxB;;;;;;;;;;;;;iBCoBuB,OAAO,kBAAkB,QAAQ,GAAG,UAAU,eAAe"}
package/dist/index.mjs CHANGED
@@ -23,7 +23,8 @@ const context = globalThis[CONTEXT_SYMBOL] ??= {
23
23
  mountEffects: [],
24
24
  stashedEvents: [],
25
25
  stashedAnimations: [],
26
- hydrationNode: null
26
+ hydrationNode: null,
27
+ serverValues: null
27
28
  };
28
29
  //#endregion
29
30
  //#region src/render/addAnimation.ts
@@ -1546,7 +1547,7 @@ function trackProxySignal(data, key) {
1546
1547
  * suspend up the cache chain by tainting the active reader, and notifies the
1547
1548
  * nearest `@await` boundary.
1548
1549
  *
1549
- * Return value (stale-while-revalidate, ASYNC.md §6.2): on a refresh suspend
1550
+ * Return value (ASYNC.md → "Stale-while-revalidate"): on a refresh suspend
1550
1551
  * (the computed has resolved before) returns the previously resolved value
1551
1552
  * held in `staleValue`, so readers keep displaying the old content instead of
1552
1553
  * a placeholder — an `@await` boundary thus keeps its content mounted
@@ -2256,10 +2257,23 @@ function runList(region, parent, anchor, buildItems, create, update, noWatch) {
2256
2257
  //#endregion
2257
2258
  //#region src/render/runAwait.ts
2258
2259
  /**
2260
+ * Comment prefix marking the embedded `source: "server"` values that the
2261
+ * server writes after a resolved boundary's anchor (`<!--t-await:[...]-->`,
2262
+ * see ASYNC.md → "Server rendering").
2263
+ */
2264
+ const SERVER_VALUES_PREFIX = "t-await:";
2265
+ /**
2259
2266
  * Renders an `@await` boundary. On the first run, content is rendered
2260
2267
  * speculatively; if any read inside suspends (`didSuspend`), the boundary
2261
2268
  * discards the partial render and shows the `with` branch instead.
2262
2269
  *
2270
+ * Hydration of a server-resolved boundary (ASYNC.md → "Server rendering"): when the server
2271
+ * shipped resolved content, its values ride in a payload comment after the
2272
+ * anchor. The boundary renders the content branch *with* hydration enabled
2273
+ * and `$async` seeds its computeds from the payload, so the server's HTML is
2274
+ * adopted directly — no speculative render, no `with`-branch dance, no
2275
+ * fallback flash.
2276
+ *
2263
2277
  * Fine-grained updates: on subsequent runs the boundary only decides whether
2264
2278
  * to SWITCH branches. It does so from its `pending` set — the suspended
2265
2279
  * computeds recorded by `suspendRead` — dropping entries that resolved and
@@ -2269,7 +2283,7 @@ function runList(region, parent, anchor, buildItems, create, update, noWatch) {
2269
2283
  * non-suspend dependency changes inside content are left to the child
2270
2284
  * effects that read them — the boundary isn't re-run by them at all.
2271
2285
  *
2272
- * Stale-while-revalidate (ASYNC.md §6.2): once content has been produced
2286
+ * Stale-while-revalidate (ASYNC.md): once content has been produced
2273
2287
  * (`hasContent`), a subsequent suspend during a refresh does NOT switch to
2274
2288
  * the `with` branch — the boundary keeps the stale content mounted. `$async`
2275
2289
  * retains the previous resolved value (`Computed.staleValue`) and
@@ -2291,6 +2305,18 @@ function runAwait(region, anchor, renderContent, renderWith, name) {
2291
2305
  let first = true;
2292
2306
  let hasContent = false;
2293
2307
  let theEffect = null;
2308
+ let serverValues = null;
2309
+ if (context.hydrationNode !== null && anchor !== null) {
2310
+ const next = anchor.nextSibling;
2311
+ if (next !== null && isCommentNode(next) && next.data.startsWith(SERVER_VALUES_PREFIX)) {
2312
+ try {
2313
+ serverValues = JSON.parse(next.data.substring(8));
2314
+ } catch {
2315
+ serverValues = null;
2316
+ }
2317
+ next.remove();
2318
+ }
2319
+ }
2294
2320
  const gen = region.generation = (region.generation ?? 0) + 1;
2295
2321
  $run(function runAwait() {
2296
2322
  if (region.generation !== gen) return;
@@ -2311,9 +2337,15 @@ function runAwait(region, anchor, renderContent, renderWith, name) {
2311
2337
  context.awaitBoundary = boundary;
2312
2338
  boundary.suspended = false;
2313
2339
  const savedHydration = context.hydrationNode;
2314
- if (savedHydration !== null) context.hydrationNode = null;
2340
+ const savedServerValues = context.serverValues;
2341
+ if (serverValues !== null && savedHydration !== null) context.serverValues = {
2342
+ values: serverValues,
2343
+ index: 0
2344
+ };
2345
+ else if (savedHydration !== null) context.hydrationNode = null;
2315
2346
  renderBranch(0, renderContent);
2316
- if (savedHydration !== null) context.hydrationNode = savedHydration;
2347
+ context.hydrationNode = savedHydration;
2348
+ context.serverValues = savedServerValues;
2317
2349
  context.awaitBoundary = oldBoundary;
2318
2350
  if (boundary.suspended && renderWith !== null) renderBranch(1, renderWith);
2319
2351
  else if (!boundary.suspended) hasContent = true;
@@ -2517,10 +2549,20 @@ function $batch(fn) {
2517
2549
  * over the computed object), so they fire on both the initial run and every
2518
2550
  * recalculation — `runComputed` and `checkComputed` are unchanged.
2519
2551
  *
2552
+ * Hydration seeding (ASYNC.md → "Server rendering"): while hydrating the content branch of
2553
+ * a boundary whose server HTML embedded resolved `source: "server"` values,
2554
+ * `context.serverValues` is set, and this read consumes the value at the
2555
+ * current position instead of suspending. The thunk still runs — once, in
2556
+ * the background — so the getter's dependencies are tracked and later
2557
+ * dependency changes re-fetch; the embedded value wins the generation race,
2558
+ * so there's no re-fetch wait and no fallback flash.
2559
+ *
2520
2560
  * @param fn A thunk returning the Promise to await. Signal reads inside `fn`
2521
2561
  * are tracked, so the fetch re-runs when dependencies change.
2562
+ * @param _options Accepted so the same getter source compiles into client and
2563
+ * server builds (`source: "server"` fetches during SSR); ignored here.
2522
2564
  */
2523
- function $async(fn) {
2565
+ function $async(fn, _options) {
2524
2566
  if (context.registerComputed === null) throw new Error("$async must be used in a getter");
2525
2567
  const computed = {
2526
2568
  type: 1,
@@ -2573,6 +2615,16 @@ function $async(fn) {
2573
2615
  };
2574
2616
  context.registerComputed(computed);
2575
2617
  runComputed(computed);
2618
+ const serverValues = context.serverValues;
2619
+ if (serverValues !== null && serverValues.index < serverValues.values.length) {
2620
+ computed.generation++;
2621
+ computed.didSuspend = false;
2622
+ computed.didError = false;
2623
+ computed.hasResolved = true;
2624
+ computed.lastErrored = false;
2625
+ computed.value = serverValues.values[serverValues.index++];
2626
+ computed.staleValue = computed.value;
2627
+ }
2576
2628
  return computed.value;
2577
2629
  }
2578
2630
  //#endregion
@@ -2702,7 +2754,7 @@ function $onmount(fn) {
2702
2754
  * subscription but don't propagate taint or notify a `@await` boundary.
2703
2755
  * This lets `$pending` return a plain boolean without itself suspending.
2704
2756
  *
2705
- * Quiet-on-refresh semantics (ASYNC.md §7.4): a suspend is *quiet* — and
2757
+ * Quiet-on-refresh semantics (ASYNC.md → "Loud vs quiet"): a suspend is *quiet* — and
2706
2758
  * therefore `$pending` returns `false` for it — when the computed has resolved
2707
2759
  * before and the re-fetch was a *silent* `$refresh(fn, { silent: true })` (a
2708
2760
  * bare refresh with no tracked dependency change, used for background
@@ -2729,7 +2781,7 @@ function $pending(fn) {
2729
2781
  //#region src/watch/$refresh.ts
2730
2782
  /**
2731
2783
  * Re-fetches the `$async` getters read inside `fn` without changing a
2732
- * dependency. A companion to `$pending` (ASYNC.md §6.2): pull-to-refresh,
2784
+ * dependency. A companion to `$pending` (ASYNC.md): pull-to-refresh,
2733
2785
  * refresh buttons, refetch-on-focus, polling, retry-after-error.
2734
2786
  *
2735
2787
  * `fn` is run in a tracking context that collects every `$async` computed it