@solidjs/signals 2.0.0-rc.17 → 2.0.0-rc.19

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 (71) hide show
  1. package/dist/dev-shared.js +426 -241
  2. package/dist/dev.attribution.js +19 -16
  3. package/dist/dev.js +768 -409
  4. package/dist/observe/boundaries.js +88 -67
  5. package/dist/observe/core/action.js +8 -0
  6. package/dist/observe/core/async.js +183 -138
  7. package/dist/observe/core/attribution.js +30 -28
  8. package/dist/observe/core/constants.js +23 -1
  9. package/dist/observe/core/core.js +185 -157
  10. package/dist/observe/core/effect.js +34 -37
  11. package/dist/observe/core/graph.js +8 -8
  12. package/dist/observe/core/heap.js +5 -5
  13. package/dist/observe/core/lanes.js +104 -84
  14. package/dist/observe/core/owner.js +17 -16
  15. package/dist/observe/core/scheduler.js +61 -47
  16. package/dist/observe/core/truth.js +6 -6
  17. package/dist/observe/core/verdict.js +15 -15
  18. package/dist/observe/deferred.js +40 -38
  19. package/dist/observe/from.js +248 -0
  20. package/dist/observe/index.js +4 -2
  21. package/dist/observe/map.js +22 -22
  22. package/dist/observe/reveal.js +5 -5
  23. package/dist/observe/signals.js +57 -15
  24. package/dist/observe/store/affects.js +1 -1
  25. package/dist/observe/store/hooks.js +3 -0
  26. package/dist/observe/store/optimistic.js +11 -11
  27. package/dist/observe/store/projection.js +34 -21
  28. package/dist/observe/store/reconcile.js +138 -122
  29. package/dist/observe/store/store.js +628 -641
  30. package/dist/observe/store/target.js +1 -5
  31. package/dist/observe/store/utils.js +7 -2
  32. package/dist/prod/boundaries.js +153 -132
  33. package/dist/prod/core/action.js +8 -0
  34. package/dist/prod/core/async.js +242 -197
  35. package/dist/prod/core/constants.js +16 -1
  36. package/dist/prod/core/core.js +166 -138
  37. package/dist/prod/core/effect.js +31 -34
  38. package/dist/prod/core/graph.js +5 -5
  39. package/dist/prod/core/heap.js +12 -12
  40. package/dist/prod/core/lanes.js +98 -78
  41. package/dist/prod/core/owner.js +15 -14
  42. package/dist/prod/core/scheduler.js +64 -50
  43. package/dist/prod/core/truth.js +6 -6
  44. package/dist/prod/core/verdict.js +17 -17
  45. package/dist/prod/deferred.js +40 -38
  46. package/dist/prod/from.js +248 -0
  47. package/dist/prod/index.js +4 -2
  48. package/dist/prod/map.js +14 -14
  49. package/dist/prod/reveal.js +8 -8
  50. package/dist/prod/signals.js +46 -4
  51. package/dist/prod/store/affects.js +1 -1
  52. package/dist/prod/store/hooks.js +3 -0
  53. package/dist/prod/store/optimistic.js +16 -16
  54. package/dist/prod/store/projection.js +22 -9
  55. package/dist/prod/store/reconcile.js +138 -122
  56. package/dist/prod/store/store.js +308 -331
  57. package/dist/prod/store/target.js +13 -17
  58. package/dist/prod/store/utils.js +2 -0
  59. package/dist/types/core/action.d.ts +8 -0
  60. package/dist/types/core/async.d.ts +12 -2
  61. package/dist/types/core/constants.d.ts +25 -0
  62. package/dist/types/core/core.d.ts +33 -4
  63. package/dist/types/core/dev.d.ts +1 -1
  64. package/dist/types/core/index.d.ts +1 -1
  65. package/dist/types/core/lanes.d.ts +5 -1
  66. package/dist/types/core/scheduler.d.ts +17 -3
  67. package/dist/types/from.d.ts +47 -0
  68. package/dist/types/index.d.ts +4 -1
  69. package/dist/types/signals.d.ts +37 -0
  70. package/dist/types/store/target.d.ts +2 -0
  71. package/package.json +1 -1
@@ -8,7 +8,7 @@ import { unobserved, clearDeps } from "./graph.js";
8
8
 
9
9
  import { deleteFromHeap } from "./heap.js";
10
10
 
11
- import { globalQueue, schedule, dirtyQueue } from "./scheduler.js";
11
+ import { globalQueue, pendingNodes, schedule, dirtyQueue } from "./scheduler.js";
12
12
 
13
13
  // L2 (step 2): the parked frame. A pass parks the previous frame's children
14
14
  // and `_disposal` list on `_x._pendingFirstChild` / `_x._pendingDisposal`
@@ -69,21 +69,22 @@ function disposeChildren(e, n = false, r) {
69
69
  // cleanups never run and it stays subscribed, rerunning in a torn-down
70
70
  // tree (#3561). Death only (`self`): a re-pass leaves the frame reacting
71
71
  // until the commit.
72
- if (n && !r && e.T !== null && (e.T.Nt !== null || e.T.ft !== null)) disposeChildren(e, false, true);
72
+ if (n && !r && e.T !== null && (e.T.ft !== null || e.T.Nt !== null)) disposeChildren(e, false, true);
73
73
  if (n) {
74
74
  e.R = t | REACTIVE_DISPOSED;
75
75
  if (e._parent === null && e.Pt) unregisterRoot(e);
76
76
  }
77
77
  if (n && e.X) {
78
- if (e.T !== null) e.T.Se = null;
78
+ if (e.T !== null) e.T.Ee = null;
79
79
  // A death that can unblock the future (L2, `futureBlocked`): a held
80
80
  // flight's — a transaction's or a lane's (its `_x._transaction`) — or a
81
81
  // stale reader's (REACTIVE_FRAME_READ — a frame that derived from one).
82
+ // An idle pending queue would also pin it until an unrelated flush.
82
83
  // Nothing else re-examines a dead node, so make sure a seam comes.
83
- if (e.m & STATUS_PENDING && e.T?.Je != null || t & REACTIVE_FRAME_READ) schedule();
84
+ if (e.m & STATUS_PENDING && e.T?.Je != null || t & REACTIVE_FRAME_READ || pendingNodes.length) schedule();
84
85
  }
85
- let l = r ? e.T.Nt : e.ze;
86
- if (r) e.T.Nt = null; else e.ze = null;
86
+ let l = r ? e.T.ft : e.ze;
87
+ if (r) e.T.ft = null; else e.ze = null;
87
88
  while (l) {
88
89
  const e = l;
89
90
  // Owner teardown is death regardless of the child's own lifecycle
@@ -107,7 +108,7 @@ function disposeChildren(e, n = false, r) {
107
108
  // on the fresh head and survives. Pointing each drained child's prev at
108
109
  // itself routes its later splice onto the detached chain, never the head,
109
110
  // and keeps the dev owner-chain-head invariant honest for those children.
110
- l.Ct = l;
111
+ l.dt = l;
111
112
  disposeChildren(l, true);
112
113
  // Read after, not before: a sibling this disposal made dormant spliced
113
114
  // itself out of the detached chain, and a cleanup may then have linked
@@ -122,11 +123,11 @@ function disposeChildren(e, n = false, r) {
122
123
  // node._nextSibling intact so outer walks that already advanced past us
123
124
  // still reach later siblings.
124
125
  if (n && !r && !(t & REACTIVE_ZOMBIE) && e._parent !== null && !(e._parent.R & REACTIVE_DISPOSED)) {
125
- const n = e.Ct;
126
+ const n = e.dt;
126
127
  const r = e.Xe;
127
128
  if (n !== null) n.Xe = r; else e._parent.ze = r;
128
- if (r !== null) r.Ct = n;
129
- e.Ct = null;
129
+ if (r !== null) r.dt = n;
130
+ e.dt = null;
130
131
  }
131
132
  runDisposal(e, r);
132
133
  // Final effect-returned cleanup fires at true disposal, after `_disposal`
@@ -140,9 +141,9 @@ function disposeChildren(e, n = false, r) {
140
141
 
141
142
  function linkChild(e, n) {
142
143
  const r = e.ze;
143
- n.Ct = null;
144
+ n.dt = null;
144
145
  n.Xe = r;
145
- if (r !== null) r.Ct = n;
146
+ if (r !== null) r.dt = n;
146
147
  e.ze = n;
147
148
  }
148
149
 
@@ -153,9 +154,9 @@ function runDisposal(e, n) {
153
154
  // walk ran every entry a second time. Detached, the re-entrant drain finds
154
155
  // nothing. The same shape latched a throwing cleanup: the list survived the
155
156
  // throw and every later drain re-ran and re-threw it.
156
- const r = n ? e.T.ft : e.rt;
157
+ const r = n ? e.T.Nt : e.rt;
157
158
  if (!r) return;
158
- if (n) e.T.ft = null; else e.rt = null;
159
+ if (n) e.T.Nt = null; else e.rt = null;
159
160
  if (Array.isArray(r)) {
160
161
  // Unwind order (#3572, restores 1.x #1562): later registrations run
161
162
  // before earlier ones. Children have already been disposed by the caller,
@@ -308,10 +309,10 @@ function disposeRootSelf(e = true) {
308
309
  // was 12 KB and most of disposal's time (2026-10-17).
309
310
  R: REACTIVE_NONE,
310
311
  Pt: true,
311
- Ht: n?.Pt ? n.Ht : n,
312
+ ht: n?.Pt ? n.ht : n,
312
313
  ze: null,
313
314
  Xe: null,
314
- Ct: null,
315
+ dt: null,
315
316
  rt: null,
316
317
  A: n?.A || defaultContext,
317
318
  ct: 0,
@@ -130,7 +130,7 @@ function setExternalHooks(e, o) {
130
130
 
131
131
  /** A transaction (listed here) or a lane (lanes.ts lists its own). */ function newTransaction(e, o = null) {
132
132
  const n = {
133
- je: [],
133
+ Ye: [],
134
134
  un: [ [], [] ],
135
135
  En: [],
136
136
  eo: null,
@@ -232,7 +232,7 @@ function resolveTx(e) {
232
232
  e.eo = o;
233
233
  o.tt += e.tt;
234
234
  o.nt ||= e.nt;
235
- append(o.je, e.je);
235
+ append(o.Ye, e.Ye);
236
236
  append(o.un[0], e.un[0]);
237
237
  append(o.un[1], e.un[1]);
238
238
  append(o.En, e.En);
@@ -262,7 +262,7 @@ function resolveTx(e) {
262
262
  judge ??= e;
263
263
  // An action still running in it holds it open (action.ts). Its lanes
264
264
  // (lanes.ts): a lane under `t` blocks it while blocked itself.
265
- const n = e.tt !== 0 || blockedBy(e.je, e) || !!lanesBlockedHook?.(e);
265
+ const n = e.tt !== 0 || blockedBy(e.Ye, e) || !!lanesBlockedHook?.(e);
266
266
  judge = o;
267
267
  return n;
268
268
  }
@@ -273,8 +273,8 @@ let judge = null;
273
273
  * frame reader observes (`blockedBy`'s predicate, collected; the readers
274
274
  * themselves are not sources). */ function blockersOf(e) {
275
275
  const o = [];
276
- for (let n = 0; n < e.je.length; n++) {
277
- const t = e.je[n];
276
+ for (let n = 0; n < e.Ye.length; n++) {
277
+ const t = e.Ye[n];
278
278
  if (!t.i && t.m & STATUS_PENDING && !(t.R & REACTIVE_DISPOSED) && (t.T.Je === null || txOf(t) === e) && blockedBy([ t ], e)) o.push(t);
279
279
  }
280
280
  return o;
@@ -285,13 +285,13 @@ let judge = null;
285
285
  * not (lanes.ts, the body-end corollary). A pending reader counts only if
286
286
  * one of the sources it waits on is `t`'s (a render effect marked pending
287
287
  * by a lane flight, never re-run, is the lane's wait, not the frame's). */ function ownFlights(e) {
288
- return blockedBy(e.je, e, true);
288
+ return blockedBy(e.Ye, e, true);
289
289
  }
290
290
 
291
291
  /** A source the pending node waits on that is `t`'s (held by it, or by no
292
292
  * one) — not another transaction's or lane's work. Itself, when it is the
293
293
  * source. */ function ownSource(e, o) {
294
- const n = e.T?.fe;
294
+ const n = e.T?.se;
295
295
  if (n === undefined) return true;
296
296
  for (const e of n) {
297
297
  const n = e.T?.Je;
@@ -323,7 +323,7 @@ function blockedBy(e, o, n = false) {
323
323
  // lane-membership ruling, 2026-10-05). An output that never committed
324
324
  // shows nothing — a mount the frame has not revealed — and holds
325
325
  // nothing.
326
- if ((n.i === EFFECT_RENDER && n.m & STATUS_PENDING || n.R & REACTIVE_FRAME_READ || n.l & CONFIG_REDERIVE && n.m === STATUS_PENDING) && (e.Te === n.Ne || n.T?.F != null) && !(n.R & REACTIVE_DISPOSED) && onScreen(n, judge ?? o)) return true;
326
+ if ((n.i === EFFECT_RENDER && n.m & STATUS_PENDING || n.R & REACTIVE_FRAME_READ || n.l & CONFIG_REDERIVE && n.m === STATUS_PENDING) && (e.Ie === n.Ne || n.T?.F != null) && !(n.R & REACTIVE_DISPOSED) && onScreen(n, judge ?? o)) return true;
327
327
  }
328
328
  }
329
329
  return false;
@@ -385,7 +385,7 @@ function deferZombie(e) {
385
385
  const n = ext(e);
386
386
  if (n.Je === o) return;
387
387
  n.Je = o;
388
- o.je.push(e);
388
+ o.Ye.push(e);
389
389
  }
390
390
 
391
391
  /** Hold the (uncommitted) frame under a held pass: every computed in the
@@ -427,7 +427,7 @@ function deferZombie(e) {
427
427
  const dirtyQueue = {
428
428
  gt: new Array(2e3).fill(undefined),
429
429
  p: false,
430
- st: 0,
430
+ lt: 0,
431
431
  jt: 0
432
432
  };
433
433
 
@@ -509,12 +509,14 @@ function schedule() {
509
509
  * hook machinery (pay-for-use).
510
510
  */ const ROOT_ERROR_HOOK = Symbol.for("solid-js/root-error-hook");
511
511
 
512
+ const HALTED = "[REACTIVITY_HALTED]";
513
+
512
514
  function haltReactivity(e) {
513
515
  if (halted) return;
514
516
  halted = true;
515
517
  // A cleanup error collected before the halt is dropped (owner.ts).
516
518
  rethrowCleanupError(true);
517
- let o = "[REACTIVITY_HALTED]";
519
+ let o = HALTED;
518
520
  // Surface the cause here too: callers rethrow it, but a creation-time throw
519
521
  // unwinds through ancestor recomputes that convert it to status instead of
520
522
  // surfacing it (#2884), so the rethrow alone cannot guarantee visibility.
@@ -542,7 +544,7 @@ function haltReactivity(e) {
542
544
  function notifyHalted() {
543
545
  if (haltNotified) return;
544
546
  haltNotified = true;
545
- console.error("[REACTIVITY_HALTED]");
547
+ console.error(HALTED);
546
548
  }
547
549
 
548
550
  /** @internal Test/dev-reload hook. Revives scheduling after a halt. */ function resetErrorHalt() {
@@ -573,7 +575,7 @@ class GlobalQueue {
573
575
  clock++;
574
576
  // A write the commit sweep staged with no subscriber to dirty is work
575
577
  // too — the next round commits it.
576
- scheduled = dirtyQueue.jt >= dirtyQueue.st || pendingNodes.length !== 0;
578
+ scheduled = dirtyQueue.jt >= dirtyQueue.lt || pendingNodes.length !== 0;
577
579
  this.run(EFFECT_RENDER);
578
580
  this.run(EFFECT_USER);
579
581
  if (true && holding) {
@@ -627,18 +629,18 @@ class GlobalQueue {
627
629
  // stale stamp was the bridge that entangled unrelated updates
628
630
  // with a never-resolving flight). Its observers are held and
629
631
  // wait on its flight (`blocked`).
630
- if (e.ue === NOT_PENDING && e.m & STATUS_UNINITIALIZED && e.i !== EFFECT_RENDER) continue;
632
+ if (e.ie === NOT_PENDING && e.m & STATUS_UNINITIALIZED && e.i !== EFFECT_RENDER) continue;
631
633
  // A34 (2): a tick whose writes net to the committed value made no
632
634
  // proposal (`setShow(false); setShow(true)` on a committed true) —
633
635
  // not staged, not held, pends nothing; a later write to it is
634
636
  // plain mainline. (A node already held stays held when written
635
637
  // back: A34 (1).)
636
- if (e.ue !== NOT_PENDING && !(e.m & (STATUS_PENDING | STATUS_UNINITIALIZED)) && e.T?.Nt == null && e.T?.ft == null &&
638
+ if (e.ie !== NOT_PENDING && !(e.m & (STATUS_PENDING | STATUS_UNINITIALIZED)) && e.T?.ft == null && e.T?.Nt == null &&
637
639
  // The comparator last: a pass that created children (an object
638
640
  // owning a fresh async memo, #4111) must not have it read them.
639
641
  // A NotReady read there is a change (`isSame`).
640
- isSame(e, e.Ie, e.ue)) {
641
- e.ue = NOT_PENDING;
642
+ isSame(e, e.le, e.ie)) {
643
+ e.ie = NOT_PENDING;
642
644
  e.l &= ~CONFIG_STAGED;
643
645
  continue;
644
646
  }
@@ -692,11 +694,12 @@ class GlobalQueue {
692
694
  // This flush's own runs, the lanes' reveals, and the landings' held runs
693
695
  // are collected apart and ordered below.
694
696
  const n = this.un;
695
- const t = this.un = [ [], [] ];
697
+ const t = [ [], [] ];
696
698
  // The passes that read this frame's stagings as the screen read held
697
699
  // writes if it parked: the lane seam re-derives them on the committed
698
700
  // world (a lane's runs wait this round).
699
701
  if (laneSeamsHook) {
702
+ this.un = t;
700
703
  laneSeamsHook(o !== null ? stagedReaders : null);
701
704
  if (stagedReaders.length) stagedReaders.length = 0;
702
705
  }
@@ -819,37 +822,40 @@ class GlobalQueue {
819
822
  * or without the held read) owes nothing. A run this transaction stashed
820
823
  * for it is void (#3322: an effect has one value slot, and the stale pass
821
824
  * overwrote the value that run was for) — the re-derivation's run replaces
822
- * it. */ function reruns(e) {
823
- for (let o = 0; o < e.En.length; o++) {
824
- const n = e.En[o];
825
+ * it. Truthy when an effect re-derives (`land`). */ function reruns(e) {
826
+ let o;
827
+ for (let n = 0; n < e.En.length; n++) {
828
+ const t = e.En[n];
825
829
  // An errored reader's display is its error (D-39): the landing gives it
826
830
  // nothing to re-derive, and a re-run would be a read that retries the
827
831
  // errored source (#3945).
828
- if (n.R & REACTIVE_DISPOSED || n.m & STATUS_ERROR) continue;
829
- if (n.R & REACTIVE_FRAME_READ || n.l & CONFIG_VERDICT) {
830
- n.R &= ~REACTIVE_FRAME_READ;
831
- n.Qe = false;
832
+ if (t.R & REACTIVE_DISPOSED || t.m & STATUS_ERROR) continue;
833
+ if (t.R & REACTIVE_FRAME_READ || t.l & CONFIG_VERDICT) {
834
+ o ||= t.i;
835
+ t.R &= ~REACTIVE_FRAME_READ;
836
+ t.Qe = false;
832
837
  // Its frame is replaced by the re-derivation: a run one of its
833
838
  // children queued this flush (re-run by the same landing) is for the
834
839
  // frame being replaced — void too (#3404).
835
- for (let e = n.ze; e !== null; e = e.Xe) if (e.i) e.Qe = false;
836
- enqueueSub(n);
840
+ for (let e = t.ze; e !== null; e = e.Xe) if (e.i) e.Qe = false;
841
+ enqueueSub(t);
837
842
  }
838
843
  }
839
844
  e.En.length = 0;
845
+ return o;
840
846
  }
841
847
 
842
848
  /** The landing: the held frame becomes the frame. */ function land(e) {
843
849
  // Attribution hook: judged complete — its held writes commit next
844
850
  // (`_nodes` still lists them).
845
851
  if (attrHooks !== null) attrHooks.transitionSettled(e);
846
- reruns(e);
847
- if (e.I !== null) releaseMarksHook(e.I);
852
+ const o = reruns(e);
853
+ if (releaseMarksHook && e.I !== null) releaseMarksHook(e.I);
848
854
  // Old children die in the commits (cleanups first), then the stashed
849
855
  // effects run ahead of this flush's own. A node a lane took over since
850
856
  // (a guess written over the staged truth) is the lane's to land.
851
- for (let o = 0; o < e.je.length; o++) {
852
- const n = e.je[o];
857
+ for (let o = 0; o < e.Ye.length; o++) {
858
+ const n = e.Ye[o];
853
859
  if (n.T.Je === null || txOf(n) !== e) continue;
854
860
  n.T.Je = null;
855
861
  commitPendingNode(n);
@@ -858,7 +864,15 @@ class GlobalQueue {
858
864
  // `u`, which has left `transactions`: the write is this landing's, and
859
865
  // the next flush must not park in it (#4089).
860
866
  if (flushTransaction === e) flushTransaction = null;
861
- releaseQueues(e);
867
+ // An effect re-derives next round (`reruns`): the held runs wait for it
868
+ // (D-9, the A15 reveal corollary, #4071). Its re-derivation can discover a
869
+ // flight — a stale reader whose mainline pass stopped reading it, now
870
+ // reading the landed world — and a landing that showed its runs first
871
+ // would reveal the held write beside a frame that can only show its old
872
+ // value. Queued last in this effect phase, the release hands them to the
873
+ // next round's own runs, ahead of the re-derivation's: they show with it,
874
+ // or park with it in the hold its pending opens. The commits stand.
875
+ if (o) globalQueue.un[1].push(() => releaseQueues(e)); else releaseQueues(e);
862
876
  }
863
877
 
864
878
  /** The held runs join this flush's effect phase after its own runs (the
@@ -914,7 +928,7 @@ function insertSubs(e) {
914
928
  // masked read of the always-present _config instead of missing-property
915
929
  // lookups in the hottest notify loop.
916
930
  const o = e.l;
917
- const n = (o & CONFIG_HAS_SNAPSHOT) !== 0 && e.T?.lt !== undefined;
931
+ const n = (o & CONFIG_HAS_SNAPSHOT) !== 0 && e.T?.st !== undefined;
918
932
  // Observe-tier fan-out: this walk visits every subscriber edge anyway, so
919
933
  // the graph-size count is one local increment here and no field anywhere.
920
934
  let t = 0;
@@ -929,7 +943,7 @@ function insertSubs(e) {
929
943
  // pass either re-reads them fresh or trims them), and neither does the
930
944
  // tail link: it is the read IN FLIGHT — read() links before it pulls, so
931
945
  // this very commit is what that read returns.
932
- if (e.R & REACTIVE_RECOMPUTING_DEPS && o.Te === e.Ne && o !== e._) e.R |= REACTIVE_MISSED_WAKE;
946
+ if (e.R & REACTIVE_RECOMPUTING_DEPS && o.Ie === e.Ne && o !== e._) e.R |= REACTIVE_MISSED_WAKE;
933
947
  if (n && e.l & CONFIG_IN_SNAPSHOT_SCOPE) {
934
948
  e.R |= REACTIVE_SNAPSHOT_STALE;
935
949
  continue;
@@ -966,32 +980,32 @@ function commitPendingNode(e) {
966
980
  // commits a value.
967
981
  if (!o.X) {
968
982
  e.l &= -385;
969
- if (e.ue !== NOT_PENDING) {
970
- e.Ie = e.ue;
971
- e.ue = NOT_PENDING;
983
+ if (e.ie !== NOT_PENDING) {
984
+ e.le = e.ie;
985
+ e.ie = NOT_PENDING;
972
986
  }
973
987
  return;
974
988
  }
975
989
  // Computeds only from here (`_statusFlags` is not a signal field). A
976
990
  // commit beneath a flight publishes its inputs (A15 reveal corollary,
977
991
  // #3305): a reveal of it must observe, not show the pre-flight value.
978
- const n = e.ue === NOT_PENDING && (o.m & STATUS_PENDING) !== 0;
992
+ const n = e.ie === NOT_PENDING && (o.m & STATUS_PENDING) !== 0;
979
993
  const t = e.l & CONFIG_STAGED_ERROR;
980
994
  // An answer commits: the error it replaces leaves the display (D-41).
981
- if (!n && o.T) o.T.de = undefined;
995
+ if (!n && o.T) o.T.Te = undefined;
982
996
  e.l = n ? e.l & -1048833 | CONFIG_INPUTS_PUBLISHED : e.l & -3147137;
983
997
  // D-41: the staged answer is an error — published now, when a value would
984
998
  // show, through the ordinary error path (`stageError`). Its readers first
985
999
  // see it in the cycle after this seam: a tracked re-read there is not a
986
1000
  // retry (`read`), or a boundary re-derived by it would retry it forever.
987
1001
  if (t) {
988
- const n = e.ue;
989
- e.ue = NOT_PENDING;
990
- e.ie = clock + 1;
1002
+ const n = e.ie;
1003
+ e.ie = NOT_PENDING;
1004
+ e.ae = clock + 1;
991
1005
  notifyStatus(o, STATUS_ERROR, n);
992
- } else if (e.ue !== NOT_PENDING) {
993
- e.Ie = e.ue;
994
- e.ue = NOT_PENDING;
1006
+ } else if (e.ie !== NOT_PENDING) {
1007
+ e.le = e.ie;
1008
+ e.ie = NOT_PENDING;
995
1009
  // A node born staged (recompute) initializes at this commit.
996
1010
  o.m &= ~STATUS_UNINITIALIZED;
997
1011
  // A quiet re-ask's classification survives its landing and dies with
@@ -1021,7 +1035,7 @@ function commitPendingNode(e) {
1021
1035
  if (!(o.m & STATUS_PENDING)) o.m &= ~STATUS_UNINITIALIZED;
1022
1036
  // L2: the children this commit publishes are the frame's now — the frame
1023
1037
  // they replace, parked by the pass (`recompute`), goes.
1024
- if (!n && o.T != null && (o.T.Nt !== null || o.T.ft !== null)) GlobalQueue.et(o, false, true);
1038
+ if (!n && o.T != null && (o.T.ft !== null || o.T.Nt !== null)) GlobalQueue.et(o, false, true);
1025
1039
  }
1026
1040
 
1027
1041
  function commitPendingNodes() {
@@ -1085,4 +1099,4 @@ function runQueue(e, o) {
1085
1099
  for (let n = 0; n < e.length; n++) e[n](o);
1086
1100
  }
1087
1101
 
1088
- export { GlobalQueue, MAINLINE_QUESTION, ROOT_ERROR_HOOK, actionDepth, applyGuessesHook, blocked, blockersOf, boundarySeamHook, bumpNotifyEpoch, catchHook, clock, commitPendingNode, deferZombie, dirtyQueue, endLanesHook, enforceLoadingBoundary, enterAction, exitAction, externalUntrackHook, flush, flushTransaction, freshHook, globalQueue, haltReactivity, haltReactivityAt, heldRunHook, heldTrim, heldUnder, hiddenHook, holdNode, insertSubs, installBoundaryHooks, installLaneHooks, installMarkHooks, installStoreHooks, installVerdictHooks, joinFuture, joinPassTx, laneCorrectionsHook, laneDirty, laneOutcomeHook, laneReadHook, laneSeamsHook, laneStageHook, laneWriteHook, lanesBlockedHook, list, liveTx, merge, newTransaction, nextQuestion, notifyEpoch, observeFlightHook, ownFlights, passLane, passTx, question, queuePendingNode, releaseAmbientMarksHook, releaseMarksHook, releaseQueues, reruns, resetErrorHalt, resolveTx, sameLane, schedule, setExternalHooks, setPassLane, setQuestion, stagedReaders, staleReader, storeCommitHook, storeParkHook, txOf, unhold, wireExternalSourceHook };
1102
+ export { GlobalQueue, MAINLINE_QUESTION, ROOT_ERROR_HOOK, actionDepth, applyGuessesHook, blocked, blockersOf, boundarySeamHook, bumpNotifyEpoch, catchHook, clock, commitPendingNode, deferZombie, dirtyQueue, endLanesHook, enforceLoadingBoundary, enterAction, exitAction, externalUntrackHook, flush, flushTransaction, freshHook, globalQueue, haltReactivity, haltReactivityAt, heldRunHook, heldTrim, heldUnder, hiddenHook, holdNode, insertSubs, installBoundaryHooks, installLaneHooks, installMarkHooks, installStoreHooks, installVerdictHooks, joinFuture, joinPassTx, laneCorrectionsHook, laneDirty, laneOutcomeHook, laneReadHook, laneSeamsHook, laneStageHook, laneWriteHook, lanesBlockedHook, list, liveTx, merge, newTransaction, nextQuestion, notifyEpoch, observeFlightHook, ownFlights, passLane, passTx, pendingNodes, question, queuePendingNode, releaseAmbientMarksHook, releaseMarksHook, releaseQueues, reruns, resetErrorHalt, resolveTx, sameLane, schedule, setExternalHooks, setPassLane, setQuestion, stagedReaders, staleReader, storeCommitHook, storeParkHook, txOf, unhold, wireExternalSourceHook };
@@ -12,9 +12,9 @@ import { enqueueSub } from "./heap.js";
12
12
  * staging a shown lane holds for its next reveal, else its slot; the
13
13
  * committed value while it has none (its first lane pass in flight). */
14
14
  function laneValueOf(r) {
15
- if (!(r.l & CONFIG_GUESS) && r.ue !== NOT_PENDING) return r.ue;
15
+ if (!(r.l & CONFIG_GUESS) && r.ie !== NOT_PENDING) return r.ie;
16
16
  const t = r.T.V;
17
- return t !== NOT_PENDING ? t : r.Ie;
17
+ return t !== NOT_PENDING ? t : r.le;
18
18
  }
19
19
 
20
20
  /** Truth readers (`until`, `refresh`; CONFIG_AUTHORITATIVE) — pay-for-use:
@@ -25,19 +25,19 @@ function laneValueOf(r) {
25
25
  * value. */ function truthRead(r) {
26
26
  if (truth(r)) return laneValueOf(r);
27
27
  if (!(r.l & CONFIG_GUESS)) throw new NotReadyError(null);
28
- return r.ue !== NOT_PENDING ? r.ue : r.Ie;
28
+ return r.ie !== NOT_PENDING ? r.ie : r.le;
29
29
  }
30
30
 
31
31
  /** A guess confirmed: its lane's truth readers re-read — of the lane's
32
32
  * derivations too, which may be the truth now (#3943). */ function truthConfirmed(r) {
33
- for (let t = 0; t < r.je.length; t++) for (let e = r.je[t].o; e !== null; e = e.t) if (e.u.l & CONFIG_AUTHORITATIVE) enqueueSub(e.u);
33
+ for (let t = 0; t < r.Ye.length; t++) for (let e = r.Ye[t].o; e !== null; e = e.t) if (e.u.l & CONFIG_AUTHORITATIVE) enqueueSub(e.u);
34
34
  }
35
35
 
36
36
  /** A lane node's value is the truth when every guess beneath it is
37
37
  * confirmed — its source staged a value equal to the guess — and nothing
38
38
  * beneath it is held in the parent: same inputs, same value. */ function truth(r) {
39
- if (r.l & CONFIG_GUESS) return r.ue !== NOT_PENDING && r.Ye && r.Ye(r.T.V, r.ue);
40
- if (r.ue !== NOT_PENDING) return;
39
+ if (r.l & CONFIG_GUESS) return r.ie !== NOT_PENDING && r.je && r.je(r.T.V, r.ie);
40
+ if (r.ie !== NOT_PENDING) return;
41
41
  if (r.l & CONFIG_OVERRIDE) for (let t = r.C; t; t = t.G) if (!truth(t.S)) return;
42
42
  return 1;
43
43
  }
@@ -139,8 +139,8 @@ let probeFound = false;
139
139
  * when every flight it waits on is. */ function quietPending(e) {
140
140
  const t = e.T;
141
141
  if (t === null) return false;
142
- if (t.fe !== undefined) {
143
- for (const e of t.fe) if (!e.T?.ut) return false;
142
+ if (t.se !== undefined) {
143
+ for (const e of t.se) if (!e.T?.ut) return false;
144
144
  return true;
145
145
  }
146
146
  return t.ut;
@@ -159,7 +159,7 @@ let probeFound = false;
159
159
  * flight — a staging equal to what is displayed changes nothing when it
160
160
  * lands: final now (maintainer, 2026-10-02). */ function heldNotFinal(e) {
161
161
  if ((e.m & STATUS_PENDING) !== 0 && !quietPending(e)) return true;
162
- return e.ue !== NOT_PENDING && !latestActive && !e.T.ut && !(e.m & STATUS_UNINITIALIZED) && (!!e.T.de || !e.Ye || !e.Ye(e.Ie, e.ue));
162
+ return e.ie !== NOT_PENDING && !latestActive && !e.T.ut && !(e.m & STATUS_UNINITIALIZED) && (!!e.T.Te || !e.je || !e.je(e.le, e.ie));
163
163
  }
164
164
 
165
165
  /** `isPending`'s answer for an unheld node whose flight is up (cause ii). */ function pendingVerdict(e, t) {
@@ -177,7 +177,7 @@ let probeFound = false;
177
177
  * a router's link claim probing inside the computation that creates the
178
178
  * anchor). A throw still reaches the pass through `untrack`. */ function markVerdictReader(e) {
179
179
  let t = context;
180
- if (t?.Pt) t = t.Ht;
180
+ if (t?.Pt) t = t.ht;
181
181
  if (t !== null && tracking) {
182
182
  t.l |= CONFIG_VERDICT;
183
183
  t.R |= REACTIVE_PROBED;
@@ -261,8 +261,8 @@ let probeFound = false;
261
261
  }
262
262
 
263
263
  /** The staging, or the staged error thrown (D-41). */ function staged(e) {
264
- if (e.l & CONFIG_STAGED_ERROR) throw e.ue;
265
- return e.ue;
264
+ if (e.l & CONFIG_STAGED_ERROR) throw e.ie;
265
+ return e.ie;
266
266
  }
267
267
 
268
268
  /** `latest()` of a held node: the flushed staging — the proposal — and, for
@@ -322,7 +322,7 @@ let probeFound = false;
322
322
  if (i) verdictRead(t, r._parent ?? r);
323
323
  const u = (n.m & STATUS_PENDING) !== 0 && !quietPending(n);
324
324
  if (e.l & CONFIG_GUESS) {
325
- if (probing && (u || e.ue !== NOT_PENDING && (!e.Ye || !e.Ye(e.T.V, e.ue)))) probeFound = true;
325
+ if (probing && (u || e.ie !== NOT_PENDING && (!e.je || !e.je(e.T.V, e.ie)))) probeFound = true;
326
326
  // A lane a correction folded under (D-34): `latest()` shows the hold's
327
327
  // world whole — the truth beneath each guess, else what it covered.
328
328
  if (latestActive && r.folded) return r.folded(null, e);
@@ -342,28 +342,28 @@ let probeFound = false;
342
342
  // `isPending` is answered below either way.
343
343
  if (i && !probing && t.i === EFFECT_RENDER && passLane === null && r.it !== null && r.it.ln && flushTransaction !== r) {
344
344
  staleReader(t, r.it);
345
- return e.Ie;
345
+ return e.le;
346
346
  }
347
347
  if (i) verdictRead(t, r);
348
348
  if (probing && heldNotFinal(n)) probeFound = true;
349
- if (latestActive && e.ue !== NOT_PENDING) {
349
+ if (latestActive && e.ie !== NOT_PENDING) {
350
350
  // An action body reading another transaction's proposal derives
351
351
  // from it: the two settle as one (A15; posture C, 2026-09-15). An
352
352
  // untracked read elsewhere has no transaction to entangle.
353
353
  if (!i && flushTransaction !== null && !globalQueue.q) joinFuture(txOf(e));
354
354
  return heldLatest(e, i ? t : null);
355
355
  }
356
- return e.Ie;
356
+ return e.le;
357
357
  }
358
358
  // Born into the future: its staging is its only value. It has no
359
359
  // committed value, so no verdict: `isPending` reads it as its read does —
360
360
  // the owner joins the hold (held with it, or caught by a boundary that
361
361
  // has not shown content) and answers for the commit, where it is final.
362
- if (e.ue !== NOT_PENDING && !(n.m & STATUS_PENDING)) {
362
+ if (e.ie !== NOT_PENDING && !(n.m & STATUS_PENDING)) {
363
363
  if (probing && r) joinPass(t, e);
364
364
  return staged(e);
365
365
  }
366
- } else if (e.ue !== NOT_PENDING) {
366
+ } else if (e.ie !== NOT_PENDING) {
367
367
  if (n.m & STATUS_PENDING && !u) pendingVerdict(i ? t : null, n); else if (i && globalQueue.q) provisionalVerdict(t, !latestActive && !u);
368
368
  // Outside a flush, the staging is an unflushed write (A28): the probe
369
369
  // answers for the flushed world, and watches the seam of the flush that
@@ -378,12 +378,12 @@ let probeFound = false;
378
378
  if (globalQueue.q) return staged(e);
379
379
  if (t !== null) markLateLinker(t);
380
380
  }
381
- return e.Ie;
381
+ return e.le;
382
382
  }
383
383
  if (n.m & STATUS_PENDING) {
384
384
  if (!u) {
385
385
  pendingVerdict(i ? t : null, n);
386
- return e.Ie;
386
+ return e.le;
387
387
  }
388
388
  // As `read()`: an untracked read of a pending node still re-runs its
389
389
  // reader when the node settles (a projection's pull reads its firewall
@@ -392,7 +392,7 @@ let probeFound = false;
392
392
  throw n.T?.F;
393
393
  }
394
394
  if (n.X !== undefined && n.m & STATUS_ERROR) throw n.T.F;
395
- return e.Ie;
395
+ return e.le;
396
396
  }
397
397
 
398
398
  // Installed at module evaluation — present exactly when something imports
@@ -123,7 +123,7 @@ GlobalQueue.er = e => lagging.size !== 0 ? lagOf(e, new Set) : undefined;
123
123
  * does not replace (D-40) — restaged as the committed value, the hold's
124
124
  * readers would re-derive against the old input. */ const serve = e => {
125
125
  const r = handleAsync(t, e);
126
- return t.l & CONFIG_HELD && t.ue !== NOT_PENDING ? t.ue : r;
126
+ return t.l & CONFIG_HELD && t.ie !== NOT_PENDING ? t.ie : r;
127
127
  };
128
128
  const end = () => t.R & REACTIVE_DISPOSED && land(o);
129
129
  return accessor(computed(r => {
@@ -135,49 +135,51 @@ GlobalQueue.er = e => lagging.size !== 0 ? lagOf(e, new Set) : undefined;
135
135
  // Sticky, and read before this wrapper ever opens the window itself.
136
136
  const n = l ||= !(t.m & STATUS_UNINITIALIZED) && !t.ce;
137
137
  if (n) t.ce = true, t.l |= CONFIG_LAGS;
138
- let c;
139
138
  try {
140
- c = e(r);
139
+ const t = e(r);
140
+ if (n && typeof t === "object" && t !== null) {
141
+ if (isThenable(t)) {
142
+ ask(t);
143
+ const done = () => land(t, true);
144
+ t.then(done, done);
145
+ return serve(t);
146
+ }
147
+ const e = t[Symbol.asyncIterator];
148
+ if (e) {
149
+ // A stream's flight ends at its first yield (or its end).
150
+ const r = e.call(t);
151
+ let o = true;
152
+ const done = () => land(n, true);
153
+ const n = {
154
+ // Registered ahead of the engine's own reaction to the same
155
+ // promise, as for a plain flight: verdict and value in one flush.
156
+ next: e => {
157
+ const t = r.next(e);
158
+ if (o) {
159
+ o = false;
160
+ if (isThenable(t)) t.then(done, done); else done();
161
+ }
162
+ return t;
163
+ },
164
+ return: e => r.return?.(e) ?? Promise.resolve({
165
+ done: true,
166
+ value: e
167
+ })
168
+ };
169
+ ask(n);
170
+ return serve({
171
+ [Symbol.asyncIterator]: () => n
172
+ });
173
+ }
174
+ }
175
+ land(o);
176
+ return t;
141
177
  } catch (e) {
142
178
  // The wrapping form: an unready source parks the node in the window,
143
179
  // and the wait is its flight until the source's settle re-runs it.
144
- if (n && e instanceof NotReadyError) ask(e);
180
+ if (n && e instanceof NotReadyError) ask(e); else land(o);
145
181
  throw e;
146
182
  }
147
- if (n && typeof c === "object" && c !== null) {
148
- if (isThenable(c)) {
149
- ask(c);
150
- const done = () => land(c, true);
151
- c.then(done, done);
152
- return serve(c);
153
- }
154
- const e = c[Symbol.asyncIterator];
155
- if (e) {
156
- // A stream's flight ends at its first yield (or its end).
157
- const r = e.call(c);
158
- let t = true;
159
- const done = () => land(o, true);
160
- const o = {
161
- // Registered ahead of the engine's own reaction to the same
162
- // promise, as for a plain flight: verdict and value in one flush.
163
- next: e => {
164
- const o = r.next(e);
165
- if (t) t = false, o.then(done, done);
166
- return o;
167
- },
168
- return: e => r.return?.(e) ?? Promise.resolve({
169
- done: true,
170
- value: e
171
- })
172
- };
173
- ask(o);
174
- return serve({
175
- [Symbol.asyncIterator]: () => o
176
- });
177
- }
178
- }
179
- land(o);
180
- return c;
181
183
  }, r));
182
184
  }
183
185