@solidjs/signals 2.0.0-rc.14 → 2.0.0-rc.15

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 (66) hide show
  1. package/dist/dev-shared.js +248 -189
  2. package/dist/dev.attribution.js +124 -41
  3. package/dist/dev.js +553 -322
  4. package/dist/observe/affects.js +34 -31
  5. package/dist/observe/boundaries.js +166 -132
  6. package/dist/observe/core/async.js +90 -83
  7. package/dist/observe/core/attribution-queries.js +1 -1
  8. package/dist/observe/core/attribution.js +281 -197
  9. package/dist/observe/core/constants.js +7 -2
  10. package/dist/observe/core/context.js +3 -3
  11. package/dist/observe/core/core.js +277 -245
  12. package/dist/observe/core/dev.js +3 -3
  13. package/dist/observe/core/effect.js +21 -21
  14. package/dist/observe/core/external.js +2 -2
  15. package/dist/observe/core/graph.js +25 -25
  16. package/dist/observe/core/heap.js +9 -9
  17. package/dist/observe/core/lanes.js +206 -160
  18. package/dist/observe/core/owner.js +27 -27
  19. package/dist/observe/core/scheduler.js +92 -86
  20. package/dist/observe/core/verdict.js +66 -54
  21. package/dist/observe/map.js +35 -35
  22. package/dist/observe/reveal.js +24 -24
  23. package/dist/observe/signals.js +38 -28
  24. package/dist/observe/store/affects.js +75 -68
  25. package/dist/observe/store/hooks.js +13 -0
  26. package/dist/observe/store/index.js +0 -2
  27. package/dist/observe/store/optimistic.js +67 -34
  28. package/dist/observe/store/projection.js +37 -31
  29. package/dist/observe/store/reconcile.js +32 -30
  30. package/dist/observe/store/store.js +128 -85
  31. package/dist/prod/affects.js +34 -31
  32. package/dist/prod/boundaries.js +143 -109
  33. package/dist/prod/core/async.js +64 -67
  34. package/dist/prod/core/constants.js +7 -2
  35. package/dist/prod/core/context.js +3 -3
  36. package/dist/prod/core/core.js +302 -270
  37. package/dist/prod/core/effect.js +38 -38
  38. package/dist/prod/core/external.js +4 -4
  39. package/dist/prod/core/graph.js +27 -27
  40. package/dist/prod/core/heap.js +30 -30
  41. package/dist/prod/core/lanes.js +257 -211
  42. package/dist/prod/core/owner.js +39 -39
  43. package/dist/prod/core/scheduler.js +125 -119
  44. package/dist/prod/core/verdict.js +70 -58
  45. package/dist/prod/map.js +73 -73
  46. package/dist/prod/reveal.js +38 -38
  47. package/dist/prod/signals.js +30 -20
  48. package/dist/prod/store/affects.js +75 -68
  49. package/dist/prod/store/hooks.js +13 -0
  50. package/dist/prod/store/index.js +0 -2
  51. package/dist/prod/store/optimistic.js +114 -81
  52. package/dist/prod/store/projection.js +30 -24
  53. package/dist/prod/store/reconcile.js +32 -30
  54. package/dist/prod/store/store.js +136 -93
  55. package/dist/types/boundaries.d.ts +4 -0
  56. package/dist/types/core/attribution.d.ts +6 -2
  57. package/dist/types/core/constants.d.ts +5 -0
  58. package/dist/types/core/core.d.ts +33 -3
  59. package/dist/types/core/lanes.d.ts +10 -0
  60. package/dist/types/core/scheduler.d.ts +12 -6
  61. package/dist/types/core/types.d.ts +0 -6
  62. package/dist/types/store/affects.d.ts +11 -0
  63. package/dist/types/store/hooks.d.ts +48 -0
  64. package/dist/types/store/index.d.ts +0 -1
  65. package/dist/types/store/store.d.ts +3 -38
  66. package/package.json +1 -1
@@ -18,11 +18,11 @@ import { schedule, dirtyQueue } from "./scheduler.js";
18
18
  // key off it, and the heap defers a zombie's recompute past the seam (no
19
19
  // second heap — the deferral list in scheduler.ts).
20
20
  function markDisposal(e) {
21
- let n = e.sn;
21
+ let n = e.nn;
22
22
  while (n) {
23
23
  n.R |= REACTIVE_ZOMBIE;
24
24
  markDisposal(n);
25
- n = n.rn;
25
+ n = n.tn;
26
26
  }
27
27
  }
28
28
 
@@ -33,7 +33,7 @@ function dispose(e) {
33
33
  // left queued would be recomputed and resurrected by the next flush (#2983)
34
34
  // — dep unlinking, child disposal) is exactly unobserved()'s body; only
35
35
  // this flag distinguishes death from dormancy.
36
- e.u &= ~CONFIG_AUTO_DISPOSE;
36
+ e.i &= ~CONFIG_AUTO_DISPOSE;
37
37
  unobserved(e);
38
38
  }
39
39
 
@@ -50,16 +50,16 @@ function disposeChildren(e, n = false, t) {
50
50
  e.R = i | REACTIVE_DISPOSED;
51
51
  if (e._parent === null && e.Ht) unregisterRoot(e);
52
52
  }
53
- if (n && e.re) {
54
- if (e.m !== null) e.m.De = null;
53
+ if (n && e.ee) {
54
+ if (e.m !== null) e.m.Te = null;
55
55
  // A death that can unblock the future (L2, `futureBlocked`): a held
56
56
  // flight's — a transaction's or a lane's (its `_x._transaction`) — or a
57
57
  // stale reader's (REACTIVE_FRAME_READ — a frame that derived from one).
58
58
  // Nothing else re-examines a dead node, so make sure a seam comes.
59
- if (e.G & STATUS_PENDING && e.m?._t != null || i & REACTIVE_FRAME_READ) schedule();
59
+ if (e.S & STATUS_PENDING && e.m?._t != null || i & REACTIVE_FRAME_READ) schedule();
60
60
  }
61
- let r = t ? e.m.St : e.sn;
62
- if (t) e.m.St = null; else e.sn = null;
61
+ let r = t ? e.m.St : e.nn;
62
+ if (t) e.m.St = null; else e.nn = null;
63
63
  while (r) {
64
64
  const e = r;
65
65
  // Owner teardown is death regardless of the child's own lifecycle
@@ -69,7 +69,7 @@ function disposeChildren(e, n = false, t) {
69
69
  // disposeChildren call early-returns on REACTIVE_DISPOSED) die too.
70
70
  // Only unobserved()'s own node keeps its dormancy — it is never in
71
71
  // this loop; its children are rebuilt fresh on reawaken.
72
- e.u &= ~CONFIG_AUTO_DISPOSE;
72
+ e.i &= ~CONFIG_AUTO_DISPOSE;
73
73
  // Heap removal must not be gated on `_deps`: a dependency-free
74
74
  // computation queued by refresh() has a null dep list but still sits in
75
75
  // the dirty heap, and left there the post-disposal flush recomputes it —
@@ -89,9 +89,9 @@ function disposeChildren(e, n = false, t) {
89
89
  // itself out of the detached chain, and a cleanup may then have linked
90
90
  // it at the fresh head, which rewrote the `_nextSibling` a pre-read
91
91
  // would still be holding.
92
- r = r.rn;
92
+ r = r.tn;
93
93
  }
94
- if (!t) e.Ct = 0;
94
+ if (!t) e.dt = 0;
95
95
  // O(1) splice out of parent's chain on individual dispose. Skipped during
96
96
  // batch dispose (parent already disposed) and for a zombie (it sits on the
97
97
  // parent's parked frame, drained whole by the commit). We leave
@@ -99,8 +99,8 @@ function disposeChildren(e, n = false, t) {
99
99
  // still reach later siblings.
100
100
  if (n && !t && !(i & REACTIVE_ZOMBIE) && e._parent !== null && !(e._parent.R & REACTIVE_DISPOSED)) {
101
101
  const n = e.Gt;
102
- const t = e.rn;
103
- if (n !== null) n.rn = t; else e._parent.sn = t;
102
+ const t = e.tn;
103
+ if (n !== null) n.tn = t; else e._parent.nn = t;
104
104
  if (t !== null) t.Gt = n;
105
105
  e.Gt = null;
106
106
  }
@@ -115,11 +115,11 @@ function disposeChildren(e, n = false, t) {
115
115
  }
116
116
 
117
117
  function linkChild(e, n) {
118
- const t = e.sn;
118
+ const t = e.nn;
119
119
  n.Gt = null;
120
- n.rn = t;
120
+ n.tn = t;
121
121
  if (t !== null) t.Gt = n;
122
- e.sn = n;
122
+ e.nn = n;
123
123
  }
124
124
 
125
125
  function runDisposal(e, n) {
@@ -129,9 +129,9 @@ function runDisposal(e, n) {
129
129
  // walk ran every entry a second time. Detached, the re-entrant drain finds
130
130
  // nothing. The same shape latched a throwing cleanup: the list survived the
131
131
  // throw and every later drain re-ran and re-threw it.
132
- const t = n ? e.m.ct : e.Pe;
132
+ const t = n ? e.m.ct : e.Re;
133
133
  if (!t) return;
134
- if (n) e.m.ct = null; else e.Pe = null;
134
+ if (n) e.m.ct = null; else e.Re = null;
135
135
  if (Array.isArray(t)) {
136
136
  // Unwind order (#3572, restores 1.x #1562): later registrations run
137
137
  // before earlier ones. Children have already been disposed by the caller,
@@ -148,8 +148,8 @@ function runDisposal(e, n) {
148
148
 
149
149
  function childId(e, n) {
150
150
  let t = e;
151
- while (t.u & CONFIG_TRANSPARENT && t._parent) t = t._parent;
152
- if (t.id != null) return formatId(t.id, n ? t.Ct++ : t.Ct);
151
+ while (t.i & CONFIG_TRANSPARENT && t._parent) t = t._parent;
152
+ if (t.id != null) return formatId(t.id, n ? t.dt++ : t.dt);
153
153
  throw new Error("");
154
154
  }
155
155
 
@@ -229,7 +229,7 @@ function formatId(e, n) {
229
229
  * checks. `cleanup()` is the unchecked primitive used by internals.
230
230
  */ function cleanup(e) {
231
231
  if (!context) return e;
232
- if (!context.Pe) context.Pe = e; else if (Array.isArray(context.Pe)) context.Pe.push(e); else context.Pe = [ context.Pe, e ];
232
+ if (!context.Re) context.Re = e; else if (Array.isArray(context.Re)) context.Re.push(e); else context.Re = [ context.Re, e ];
233
233
  return e;
234
234
  }
235
235
 
@@ -272,15 +272,15 @@ function disposeRootSelf(e = true) {
272
272
  // is a plain store rather than a shape fork between labelled and plain roots.
273
273
  const i = {
274
274
  id: inheritId(e, t, n),
275
- u: t ? CONFIG_TRANSPARENT : 0,
275
+ i: t ? CONFIG_TRANSPARENT : 0,
276
276
  Ht: true,
277
277
  gt: n?.Ht ? n.gt : n,
278
- sn: null,
279
- rn: null,
278
+ nn: null,
279
+ tn: null,
280
280
  Gt: null,
281
- Pe: null,
282
- U: n?.U || defaultContext,
283
- Ct: 0,
281
+ Re: null,
282
+ D: n?.D || defaultContext,
283
+ dt: 0,
284
284
  m: null,
285
285
  _parent: n,
286
286
  dispose: disposeRootSelf,
@@ -1,4 +1,4 @@
1
- import { EFFECT_RENDER, EFFECT_USER, CONFIG_HELD, CONFIG_OVERRIDE, NOT_PENDING, STATUS_UNINITIALIZED, STATUS_PENDING, CONFIG_STAGED, REACTIVE_DISPOSED, REACTIVE_ZOMBIE, CONFIG_VERDICT, CONFIG_HAS_SNAPSHOT, REACTIVE_RECOMPUTING_DEPS, REACTIVE_MISSED_WAKE, CONFIG_IN_SNAPSHOT_SCOPE, REACTIVE_SNAPSHOT_STALE, REACTIVE_LANE_DIRTY, CONFIG_INPUTS_PUBLISHED, EFFECT_TRACKED, REACTIVE_MANUAL_WRITE, CONFIG_GUESS, REACTIVE_FRAME_READ, CONFIG_REDERIVE } from "./constants.js";
1
+ import { EFFECT_RENDER, EFFECT_USER, CONFIG_HELD, CONFIG_OVERRIDE, NOT_PENDING, STATUS_UNINITIALIZED, STATUS_PENDING, CONFIG_STAGED, REACTIVE_DISPOSED, REACTIVE_ZOMBIE, CONFIG_VERDICT, CONFIG_HAS_SNAPSHOT, REACTIVE_RECOMPUTING_DEPS, REACTIVE_MISSED_WAKE, CONFIG_IN_SNAPSHOT_SCOPE, REACTIVE_SNAPSHOT_STALE, CONFIG_HELD_FRAME, REACTIVE_LANE_DIRTY, CONFIG_INPUTS_PUBLISHED, EFFECT_TRACKED, REACTIVE_MANUAL_WRITE, CONFIG_GUESS, REACTIVE_FRAME_READ, CONFIG_REDERIVE, STATUS_ERROR } from "./constants.js";
2
2
 
3
3
  import { attrHooks } from "./attribution-hooks.js";
4
4
 
@@ -19,12 +19,12 @@ import { devCheckQuiescent } from "./invariants.js";
19
19
 
20
20
  /** A transaction (listed here) or a lane (lanes.ts lists its own). */ function newTransaction(e, n = null) {
21
21
  const t = {
22
- nn: [],
22
+ Je: [],
23
23
  En: [ [], [] ],
24
24
  an: [],
25
- dn: null,
25
+ Sn: null,
26
26
  _parent: n,
27
- Z: e,
27
+ B: e,
28
28
  rt: null,
29
29
  tt: 0,
30
30
  nt: false,
@@ -78,7 +78,7 @@ function setPassLane(e) {
78
78
  * set it. */ let passTx = null;
79
79
 
80
80
  function joinPassTx(e, n) {
81
- if (globalQueue.ee && !n || flushTransaction !== null) return joinFuture(e);
81
+ if (globalQueue.X && !n || flushTransaction !== null) return joinFuture(e);
82
82
  if (passTx === null) passTx = resolveTx(e); else merge(resolveTx(e), passTx);
83
83
  schedule();
84
84
  }
@@ -95,7 +95,7 @@ function joinPassTx(e, n) {
95
95
  }
96
96
 
97
97
  function resolveTx(e) {
98
- while (e.dn !== null) e = e.dn;
98
+ while (e.Sn !== null) e = e.Sn;
99
99
  return e;
100
100
  }
101
101
 
@@ -106,7 +106,7 @@ function resolveTx(e) {
106
106
  if (n === null) {
107
107
  flushTransaction = e === null ? newTransaction(false) : resolveTx(e);
108
108
  } else if (e !== null) merge(resolveTx(e), n);
109
- if (!globalQueue.ee) schedule();
109
+ if (!globalQueue.X) schedule();
110
110
  }
111
111
 
112
112
  /** `t` merges into `f`: the work that touched both entangles them (A15).
@@ -116,12 +116,12 @@ function resolveTx(e) {
116
116
  // into the other would close a cycle `resolveTx` never leaves.
117
117
  e = resolveTx(e);
118
118
  n = resolveTx(n);
119
- if (e === n || e.Z || n.Z) return;
119
+ if (e === n || e.B || n.B) return;
120
120
  if (attrHooks !== null) attrHooks.transitionMerged(n, e);
121
- e.dn = n;
121
+ e.Sn = n;
122
122
  n.tt += e.tt;
123
123
  n.nt ||= e.nt;
124
- append(n.nn, e.nn);
124
+ append(n.Je, e.Je);
125
125
  append(n.En[0], e.En[0]);
126
126
  append(n.En[1], e.En[1]);
127
127
  append(n.an, e.an);
@@ -151,7 +151,7 @@ function resolveTx(e) {
151
151
  judge ??= e;
152
152
  // An action still running in it holds it open (action.ts). Its lanes
153
153
  // (lanes.ts): a lane under `t` blocks it while blocked itself.
154
- const t = e.tt !== 0 || blockedBy(e.nn, e) || !!GlobalQueue.Tn && GlobalQueue.Tn(e);
154
+ const t = e.tt !== 0 || blockedBy(e.Je, e) || !!GlobalQueue.dn && GlobalQueue.dn(e);
155
155
  judge = n;
156
156
  return t;
157
157
  }
@@ -162,9 +162,9 @@ let judge = null;
162
162
  * frame reader observes (`blockedBy`'s predicate, collected; the readers
163
163
  * themselves are not sources). */ function blockersOf(e) {
164
164
  const n = [];
165
- for (let t = 0; t < e.nn.length; t++) {
166
- const l = e.nn[t];
167
- if (!l.i && l.G & STATUS_PENDING && !(l.R & REACTIVE_DISPOSED) && (l.m._t === null || txOf(l) === e) && blockedBy([ l ], e)) n.push(l);
165
+ for (let t = 0; t < e.Je.length; t++) {
166
+ const l = e.Je[t];
167
+ if (!l.u && l.S & STATUS_PENDING && !(l.R & REACTIVE_DISPOSED) && (l.m._t === null || txOf(l) === e) && blockedBy([ l ], e)) n.push(l);
168
168
  }
169
169
  return n;
170
170
  }
@@ -174,7 +174,7 @@ let judge = null;
174
174
  * not (lanes.ts, the body-end corollary). A pending reader counts only if
175
175
  * one of the sources it waits on is `t`'s (a render effect marked pending
176
176
  * by a lane flight, never re-run, is the lane's wait, not the frame's). */ function ownFlights(e) {
177
- return blockedBy(e.nn, e, true);
177
+ return blockedBy(e.Je, e, true);
178
178
  }
179
179
 
180
180
  /** A source the pending node waits on that is `t`'s (held by it, or by no
@@ -192,15 +192,15 @@ let judge = null;
192
192
  function blockedBy(e, n, t = false) {
193
193
  for (let l = 0; l < e.length; l++) {
194
194
  const o = e[l];
195
- if (!(o.G & STATUS_PENDING) || o.R & REACTIVE_DISPOSED || o.u & CONFIG_GUESS || o.m._t !== null && txOf(o) !== n || t && !ownSource(o, n)) continue;
195
+ if (!(o.S & STATUS_PENDING) || o.R & REACTIVE_DISPOSED || o.i & CONFIG_GUESS || o.m._t !== null && txOf(o) !== n || t && !ownSource(o, n)) continue;
196
196
  // The frame's own pending observer (off screen: this one holds nothing;
197
197
  // the next listed node may).
198
- if (o.i === EFFECT_RENDER) {
198
+ if (o.u === EFFECT_RENDER) {
199
199
  if (onScreen(o, judge ?? n)) return true;
200
200
  continue;
201
201
  }
202
- for (let e = o.t; e !== null; e = e.l) {
203
- const t = e.o;
202
+ for (let e = o.t; e !== null; e = e.o) {
203
+ const t = e.l;
204
204
  // A frame reader: a render effect, or a stale reader of the flight
205
205
  // (REACTIVE_FRAME_READ — a verdict reader, `observeFlight`; lane work,
206
206
  // `frameRead`): served committed instead of going pending, it derives
@@ -212,7 +212,7 @@ function blockedBy(e, n, t = false) {
212
212
  // lane-membership ruling, 2026-10-05). An output that never committed
213
213
  // shows nothing — a mount the frame has not revealed — and holds
214
214
  // nothing.
215
- if ((t.i === EFFECT_RENDER || t.R & REACTIVE_FRAME_READ || t.u & CONFIG_REDERIVE && t.G === STATUS_PENDING) && (e.Ue === t.he || t.m?.v != null) && !(t.R & REACTIVE_DISPOSED) && onScreen(t, judge ?? n)) return true;
215
+ if ((t.u === EFFECT_RENDER && t.S & STATUS_PENDING || t.R & REACTIVE_FRAME_READ || t.i & CONFIG_REDERIVE && t.S === STATUS_PENDING) && (e.Pe === t.pe || t.m?.F != null) && !(t.R & REACTIVE_DISPOSED) && onScreen(t, judge ?? n)) return true;
216
216
  }
217
217
  }
218
218
  return false;
@@ -237,7 +237,7 @@ function blockedBy(e, n, t = false) {
237
237
  * the nearest non-zombie ancestor. */ function removalStagedBy(e, n) {
238
238
  let t = e;
239
239
  while (t !== null && t.R & REACTIVE_ZOMBIE) t = t._parent;
240
- return t !== null && (t.u & CONFIG_HELD) !== 0 && t.m?._t != null && txOf(t) === resolveTx(n);
240
+ return t !== null && (t.i & CONFIG_HELD) !== 0 && t.m?._t != null && txOf(t) === resolveTx(n);
241
241
  }
242
242
 
243
243
  /** Unchanged passes this flush whose stale dependency tail awaits the
@@ -264,7 +264,7 @@ function deferZombie(e) {
264
264
 
265
265
  /** Put a staged node in a transaction: flagged, stamped, on its landing
266
266
  * list. */ function holdNode(e, n) {
267
- e.u |= CONFIG_HELD;
267
+ e.i |= CONFIG_HELD;
268
268
  list(e, n);
269
269
  }
270
270
 
@@ -274,7 +274,7 @@ function deferZombie(e) {
274
274
  const t = ext(e);
275
275
  if (t._t === n) return;
276
276
  t._t = n;
277
- n.nn.push(e);
277
+ n.Je.push(e);
278
278
  }
279
279
 
280
280
  /** Hold the (uncommitted) frame under a held pass: every computed in the
@@ -290,16 +290,19 @@ function deferZombie(e) {
290
290
  * next read of it trips over (`laneRead` → `txOf`). Its frame is the lane's
291
291
  * too (ruling A: a lane pass's children are the lane's), revealed and
292
292
  * retired at the lane's seam. */ function holdFrame(e, n) {
293
- for (let t = e.sn; t !== null; t = t.rn) {
294
- if (t.m?._t?.Z) continue;
295
- if (t.re !== undefined && !(t.u & CONFIG_HELD)) holdNode(t, n);
293
+ for (let t = e.nn; t !== null; t = t.tn) {
294
+ if (t.m?._t?.B) continue;
295
+ if (t.ee !== undefined) {
296
+ if (!(t.i & CONFIG_HELD)) holdNode(t, n);
297
+ t.i |= CONFIG_HELD_FRAME;
298
+ }
296
299
  holdFrame(t, n);
297
300
  }
298
301
  }
299
302
 
300
303
  const dirtyQueue = {
301
304
  jt: new Array(2e3).fill(undefined),
302
- C: false,
305
+ N: false,
303
306
  ut: 0,
304
307
  Kt: 0
305
308
  };
@@ -364,7 +367,7 @@ function schedule() {
364
367
  }
365
368
  if (scheduled) return;
366
369
  scheduled = true;
367
- if (!syncDepth && !globalQueue.ee) {
370
+ if (!syncDepth && !globalQueue.X) {
368
371
  queueMicrotask(flush);
369
372
  }
370
373
  }
@@ -414,10 +417,10 @@ function notifyHalted() {
414
417
 
415
418
  class GlobalQueue {
416
419
  En=[ [], [] ];
417
- ee=false;
420
+ X=false;
418
421
  flush() {
419
- if (this.ee) return;
420
- this.ee = true;
422
+ if (this.X) return;
423
+ this.X = true;
421
424
  // A28: companions of nodes written since the last flush mirror the
422
425
  // flushed world — re-synced inside the running window (the write is
423
426
  // "flushed" from here on).
@@ -445,7 +448,7 @@ class GlobalQueue {
445
448
  if (false && !scheduled) ;
446
449
  if (false) ;
447
450
  } finally {
448
- this.ee = false;
451
+ this.X = false;
449
452
  passTx = null;
450
453
  }
451
454
  }
@@ -458,7 +461,7 @@ class GlobalQueue {
458
461
  // Lanes: an ended action body judges its guesses now that their passes
459
462
  // have run (lanes.ts); a correction's re-derivations run in one more
460
463
  // pure round — the parent's flights before the parent is judged below.
461
- if (GlobalQueue.Gn?.()) runHeap(dirtyQueue, GlobalQueue.et);
464
+ if (GlobalQueue.On?.()) runHeap(dirtyQueue, GlobalQueue.et);
462
465
  const e = flushTransaction;
463
466
  flushTransaction = null;
464
467
  // The frame's verdict is in: the guesses written since the last seam
@@ -466,11 +469,11 @@ class GlobalQueue {
466
469
  // parents a nested lane to it), or are dropped — the frame commits, and
467
470
  // there is nothing to be optimistic over. Their passes run next round;
468
471
  // a parent landing at this very seam ends the lane before they do.
469
- GlobalQueue.cn?.(e);
472
+ GlobalQueue.Gn?.(e);
470
473
  // A lane's own flush (its flight landing, its reveal) parks nothing: the
471
474
  // lane's work reached it per pass; the frame's plain writes commit.
472
475
  // (Resolved: a guess over another transaction's guess merged them.)
473
- const n = e !== null && !e.Z ? resolveTx(e) : null;
476
+ const n = e !== null && !e.B ? resolveTx(e) : null;
474
477
  if (n !== null) {
475
478
  // `t._nodes` grows under the walk (holdFrame pushes); the bound is
476
479
  // this flush's list, which does not.
@@ -480,7 +483,7 @@ class GlobalQueue {
480
483
  // Already held: the pass that re-staged it joined its transaction,
481
484
  // which is `t` (or merged into it). Lane work is the lane's (a
482
485
  // pending mark propagated onto it queued it here too).
483
- if (!(e.u & (CONFIG_HELD | CONFIG_OVERRIDE)) && (e.m === null || e.m._t === null || !e.m._t.Z)) {
486
+ if (!(e.i & (CONFIG_HELD | CONFIG_OVERRIDE)) && (e.m === null || e.m._t === null || !e.m._t.B)) {
484
487
  // A loading source — pending with nothing staged and no committed
485
488
  // value (A16, A19 exc. 1: uninitialized is loading, not pending)
486
489
  // that is not an observer — is nobody's frame: not held. Its
@@ -489,15 +492,15 @@ class GlobalQueue {
489
492
  // stale stamp was the bridge that entangled unrelated updates
490
493
  // with a never-resolving flight). Its observers are held and
491
494
  // wait on its flight (`blocked`).
492
- if (e.Ae === NOT_PENDING && e.G & STATUS_UNINITIALIZED && e.i !== EFFECT_RENDER) continue;
495
+ if (e.Oe === NOT_PENDING && e.S & STATUS_UNINITIALIZED && e.u !== EFFECT_RENDER) continue;
493
496
  // A34 (2): a tick whose writes net to the committed value made no
494
497
  // proposal (`setShow(false); setShow(true)` on a committed true) —
495
498
  // not staged, not held, pends nothing; a later write to it is
496
499
  // plain mainline. (A node already held stays held when written
497
500
  // back: A34 (1).)
498
- if (e.Ae !== NOT_PENDING && !(e.G & (STATUS_PENDING | STATUS_UNINITIALIZED)) && e.tn && e.tn(e.pe, e.Ae) && e.m?.St == null && e.m?.ct == null) {
499
- e.Ae = NOT_PENDING;
500
- e.u &= ~CONFIG_STAGED;
501
+ if (e.Oe !== NOT_PENDING && !(e.S & (STATUS_PENDING | STATUS_UNINITIALIZED)) && e.en && e.en(e.Ae, e.Oe) && e.m?.St == null && e.m?.ct == null) {
502
+ e.Oe = NOT_PENDING;
503
+ e.i &= ~CONFIG_STAGED;
501
504
  continue;
502
505
  }
503
506
  holdNode(e, n);
@@ -505,10 +508,10 @@ class GlobalQueue {
505
508
  // A held pass's frame is held with it (ruling A, O2): the children it
506
509
  // created are the transaction's — they compute, and a pass over them
507
510
  // or a write that reaches them joins; they effect at the landing.
508
- if (e.u & CONFIG_STAGED) holdFrame(e, n);
511
+ if (e.i & CONFIG_STAGED) holdFrame(e, n);
509
512
  }
510
513
  pendingNodes.length = 0;
511
- GlobalQueue.hn?.(n);
514
+ GlobalQueue.An?.(n);
512
515
  // (This flush's runs are stashed with `t` below — after the landings,
513
516
  // so a `t` that lands at this very seam runs them first, ahead of
514
517
  // the runs it held from earlier flushes.)
@@ -519,7 +522,7 @@ class GlobalQueue {
519
522
  // holder's verdict lane's work — before the lane seams, which reveal
520
523
  // it (nothing commits this seam that could dispose it).
521
524
  const t = deferredZombies.splice(0).sort((e, n) => e.it - n.it);
522
- for (let e = 0; e < t.length; e++) if ((t[e].R & (REACTIVE_DISPOSED | REACTIVE_ZOMBIE)) === REACTIVE_ZOMBIE && t[e].u & CONFIG_VERDICT) recompute(t[e]);
525
+ for (let e = 0; e < t.length; e++) if ((t[e].R & (REACTIVE_DISPOSED | REACTIVE_ZOMBIE)) === REACTIVE_ZOMBIE && t[e].i & CONFIG_VERDICT) recompute(t[e]);
523
526
  // The unchanged passes' tails stay linked (A30, #3469): their inputs
524
527
  // are held, and the committed frame still derives from them — no trim.
525
528
  } else {
@@ -531,7 +534,7 @@ class GlobalQueue {
531
534
  // `recompute`'s own gates.
532
535
  for (let e = 0; e < heldTrims.length; e++) {
533
536
  const n = heldTrims[e];
534
- if (n.m?.v == null && !n.lt) trimStaleDeps(n);
537
+ if (n.m?.F == null && !n.lt) trimStaleDeps(n);
535
538
  }
536
539
  }
537
540
  // The list is the flush's either way. Reset only when there is something
@@ -550,14 +553,14 @@ class GlobalQueue {
550
553
  // The passes that read this frame's stagings as the screen read held
551
554
  // writes if it parked: the lane seam re-derives them on the committed
552
555
  // world (a lane's runs wait this round).
553
- GlobalQueue._n?.(n !== null ? stagedReaders : null);
556
+ GlobalQueue.cn?.(n !== null ? stagedReaders : null);
554
557
  if (stagedReaders.length) stagedReaders.length = 0;
555
558
  this.En = [ [], [] ];
556
559
  for (let e = transactions.length - 1; e >= 0; e--) {
557
560
  const n = transactions[e];
558
561
  if (blocked(n)) continue;
559
562
  transactions.splice(e, 1);
560
- GlobalQueue.On?.(n);
563
+ GlobalQueue.Tn?.(n);
561
564
  land(n);
562
565
  // A landing's commits can dispose a zombie a transaction judged above
563
566
  // was blocked on (#3463: live "until the commit that disposes it") —
@@ -566,12 +569,13 @@ class GlobalQueue {
566
569
  }
567
570
  // The store folds the pending backings whose container nodes committed
568
571
  // — this flush's, or a landing's (store/store.ts installs it).
569
- GlobalQueue.Sn?.();
572
+ GlobalQueue.Rn?.();
570
573
  // Marks declared outside a transaction: the flush that carried them
571
574
  // parked (something async below) — the window is the frame's, the marks
572
575
  // are its transaction's; else they release at the seam, verdict-only,
573
576
  // nothing to show (affects.ts).
574
- GlobalQueue.D?.(n !== null && transactions.indexOf(n) !== -1 ? n : null);
577
+ const o = n && liveTx(n);
578
+ GlobalQueue.A?.(o);
575
579
  // The effect phase: lane work first (displayed ahead of the frame), then
576
580
  // this flush's runs, then the runs the landings held from earlier
577
581
  // flushes — as one pass would have queued them (#3540: a shell
@@ -579,8 +583,7 @@ class GlobalQueue {
579
583
  // write; #3528: a display-ahead swap before the count it is shown
580
584
  // beside). A parked frame's runs wait with its transaction instead: the
581
585
  // effect phase applies a committed frame.
582
- const o = n && liveTx(n);
583
- const u = o !== null;
586
+ const u = o !== null;
584
587
  // Attribution hook: this flush found its transaction incomplete — its
585
588
  // writes stay staged, its runs are stashed below. Before the effect
586
589
  // phase (the lanes' display-ahead runs are the visible acknowledgers);
@@ -607,7 +610,7 @@ class GlobalQueue {
607
610
  }
608
611
  // Boundaries: readers that settled, landed or died this flush are
609
612
  // dropped; a fallback with none left reveals next round.
610
- GlobalQueue.Ee?.();
613
+ GlobalQueue.ce?.();
611
614
  }
612
615
  run(e) {
613
616
  const n = this.En[e - 1];
@@ -638,7 +641,7 @@ class GlobalQueue {
638
641
  * A boundary between the observer and the root (boundaries.ts) is asked
639
642
  * first: a fallback catches what is not ready under it, and the root
640
643
  * never hears of it. */ notify(e, n, t, l) {
641
- if (GlobalQueue.fe && GlobalQueue.fe(e, t & n, l)) return true;
644
+ if (GlobalQueue.ie && GlobalQueue.ie(e, t & n, l)) return true;
642
645
  if (n & STATUS_PENDING) {
643
646
  if (t & STATUS_PENDING) {
644
647
  // A pass that went pending holds its frame: the async's own
@@ -674,14 +677,17 @@ class GlobalQueue {
674
677
  * it. */ function reruns(e) {
675
678
  for (let n = 0; n < e.an.length; n++) {
676
679
  const t = e.an[n];
677
- if (t.R & REACTIVE_DISPOSED) continue;
678
- if (t.R & REACTIVE_FRAME_READ) {
680
+ // An errored reader's display is its error (D-39): the landing gives it
681
+ // nothing to re-derive, and a re-run would be a read that retries the
682
+ // errored source (#3945).
683
+ if (t.R & REACTIVE_DISPOSED || t.S & STATUS_ERROR) continue;
684
+ if (t.R & REACTIVE_FRAME_READ || t.i & CONFIG_VERDICT) {
679
685
  t.R &= ~REACTIVE_FRAME_READ;
680
686
  t.lt = false;
681
687
  // Its frame is replaced by the re-derivation: a run one of its
682
688
  // children queued this flush (re-run by the same landing) is for the
683
689
  // frame being replaced — void too (#3404).
684
- for (let e = t.sn; e !== null; e = e.rn) if (e.i) e.lt = false;
690
+ for (let e = t.nn; e !== null; e = e.tn) if (e.u) e.lt = false;
685
691
  enqueueSub(t);
686
692
  }
687
693
  }
@@ -693,12 +699,12 @@ class GlobalQueue {
693
699
  // (`_nodes` still lists them).
694
700
  if (attrHooks !== null) attrHooks.transitionSettled(e);
695
701
  reruns(e);
696
- if (e.T !== null) GlobalQueue.A(e.T);
702
+ if (e.T !== null) GlobalQueue.k(e.T);
697
703
  // Old children die in the commits (cleanups first), then the stashed
698
704
  // effects run ahead of this flush's own. A node a lane took over since
699
705
  // (a guess written over the staged truth) is the lane's to land.
700
- for (let n = 0; n < e.nn.length; n++) {
701
- const t = e.nn[n];
706
+ for (let n = 0; n < e.Je.length; n++) {
707
+ const t = e.Je[n];
702
708
  if (t.m._t === null || txOf(t) !== e) continue;
703
709
  t.m._t = null;
704
710
  commitPendingNode(t);
@@ -738,7 +744,7 @@ class GlobalQueue {
738
744
 
739
745
  function queuePendingNode(e) {
740
746
  pendingNodes.push(e);
741
- if (!globalQueue.ee) markUnflushedStaged();
747
+ if (!globalQueue.X) markUnflushedStaged();
742
748
  // A28
743
749
  }
744
750
 
@@ -758,13 +764,13 @@ function insertSubs(e) {
758
764
  // Presence bits gate the optional-slot probes (see constants.ts): one
759
765
  // masked read of the always-present _config instead of missing-property
760
766
  // lookups in the hottest notify loop.
761
- const n = e.u;
767
+ const n = e.i;
762
768
  const t = (n & CONFIG_HAS_SNAPSHOT) !== 0 && e.m?.ot !== undefined;
763
769
  // Observe-tier fan-out: this walk visits every subscriber edge anyway, so
764
770
  // the graph-size count is one local increment here and no field anywhere.
765
771
  let l = 0;
766
- for (let n = e.t; n !== null; n = n.l) {
767
- const e = n.o;
772
+ for (let n = e.t; n !== null; n = n.o) {
773
+ const e = n.l;
768
774
  l++;
769
775
  // Missed-wake latch (#3037): this write is landing while the subscriber
770
776
  // is mid-recompute (a nested pull committing beneath its reads), and the
@@ -774,8 +780,8 @@ function insertSubs(e) {
774
780
  // pass either re-reads them fresh or trims them), and neither does the
775
781
  // tail link: it is the read IN FLIGHT — read() links before it pulls, so
776
782
  // this very commit is what that read returns.
777
- if (e.R & REACTIVE_RECOMPUTING_DEPS && n.Ue === e.he && n !== e.S) e.R |= REACTIVE_MISSED_WAKE;
778
- if (t && e.u & CONFIG_IN_SNAPSHOT_SCOPE) {
783
+ if (e.R & REACTIVE_RECOMPUTING_DEPS && n.Pe === e.pe && n !== e.p) e.R |= REACTIVE_MISSED_WAKE;
784
+ if (t && e.i & CONFIG_IN_SNAPSHOT_SCOPE) {
779
785
  e.R |= REACTIVE_SNAPSHOT_STALE;
780
786
  continue;
781
787
  }
@@ -792,9 +798,9 @@ function insertSubs(e) {
792
798
  * is a live write if the effect becomes a zombie later this flush — an
793
799
  * on-screen reader whose removal an adopted write stages follows the lane
794
800
  * (the lane-membership ruling, 2026-10-05; `_update`). */ function laneDirty(e, n) {
795
- for (let t = e.t; t !== null; t = t.l) {
796
- const e = t.o.m?._t;
797
- if (e?.Z ? sameLane(e, n) : t.o.i) t.o.R |= REACTIVE_LANE_DIRTY;
801
+ for (let t = e.t; t !== null; t = t.o) {
802
+ const e = t.l.m?._t;
803
+ if (e?.B ? sameLane(e, n) : t.l.u) t.l.R |= REACTIVE_LANE_DIRTY;
798
804
  }
799
805
  }
800
806
 
@@ -809,24 +815,24 @@ function commitPendingNode(e) {
809
815
  // staged) stays uncommitted: a re-pass disposes its children on the spot,
810
816
  // and the frame it parked stays the frame until a pass of this node
811
817
  // commits a value.
812
- if (!n.re) {
813
- e.u &= -385;
814
- if (e.Ae !== NOT_PENDING) {
815
- e.pe = e.Ae;
816
- e.Ae = NOT_PENDING;
818
+ if (!n.ee) {
819
+ e.i &= -385;
820
+ if (e.Oe !== NOT_PENDING) {
821
+ e.Ae = e.Oe;
822
+ e.Oe = NOT_PENDING;
817
823
  }
818
824
  return;
819
825
  }
820
826
  // Computeds only from here (`_statusFlags` is not a signal field). A
821
827
  // commit beneath a flight publishes its inputs (A15 reveal corollary,
822
828
  // #3305): a reveal of it must observe, not show the pre-flight value.
823
- const t = e.Ae === NOT_PENDING && (n.G & STATUS_PENDING) !== 0;
824
- e.u = t ? e.u & ~CONFIG_HELD | CONFIG_INPUTS_PUBLISHED : e.u & -1409;
825
- if (e.Ae !== NOT_PENDING) {
826
- e.pe = e.Ae;
827
- e.Ae = NOT_PENDING;
829
+ const t = e.Oe === NOT_PENDING && (n.S & STATUS_PENDING) !== 0;
830
+ e.i = t ? e.i & -1048833 | CONFIG_INPUTS_PUBLISHED : e.i & -1049985;
831
+ if (e.Oe !== NOT_PENDING) {
832
+ e.Ae = e.Oe;
833
+ e.Oe = NOT_PENDING;
828
834
  // A node born staged (recompute) initializes at this commit.
829
- n.G &= ~STATUS_UNINITIALIZED;
835
+ n.S &= ~STATUS_UNINITIALIZED;
830
836
  // A quiet re-ask's classification survives its landing and dies with
831
837
  // the landed value's commit (A19 exc. 2, #3178): verdict-quiet through
832
838
  // the reveal. (The sweep of a node still in flight is not a landing.)
@@ -834,15 +840,15 @@ function commitPendingNode(e) {
834
840
  if (n.m != null) n.m.It = false, n.m.ht = NOT_PENDING;
835
841
  // An effect with a staged value was born held (L2): its first run is
836
842
  // this commit's, not its creation's (A29) — queue it now.
837
- if (e.i && e.i !== EFFECT_TRACKED) {
843
+ if (e.u && e.u !== EFFECT_TRACKED) {
838
844
  e.lt = true;
839
- globalQueue.enqueue(e.i, e.J ??= GlobalQueue.X.bind(null, n));
845
+ globalQueue.enqueue(e.u, e.Y ??= GlobalQueue.q.bind(null, n));
840
846
  }
841
847
  }
842
848
  // The committed value is the first observable answer for a loading-window
843
849
  // node — the window closes here, not at compute time (#2990). Unconditional
844
850
  // store to an always-present computed slot.
845
- n._e = false;
851
+ n.De = false;
846
852
  n.R &= ~REACTIVE_MANUAL_WRITE;
847
853
  // The dependencies of the pass that produced the value are the frame's now:
848
854
  // the previous frame's tail goes (A30, #3410; `recompute` left it for a
@@ -850,11 +856,11 @@ function commitPendingNode(e) {
850
856
  // pass or by the node's own landing (whose pass was clean), so a set
851
857
  // `_error` means the last pass threw, kept its full list, and `_depsTail`
852
858
  // marks where it stopped.
853
- if (n.m?.v == null) trimStaleDeps(n);
854
- if (!(n.G & STATUS_PENDING)) n.G &= ~STATUS_UNINITIALIZED;
859
+ if (n.m?.F == null) trimStaleDeps(n);
860
+ if (!(n.S & STATUS_PENDING)) n.S &= ~STATUS_UNINITIALIZED;
855
861
  // L2: the children this commit publishes are the frame's now — the frame
856
862
  // they replace, parked by the pass (`recompute`), goes.
857
- if (!t && n.m != null && (n.m.St !== null || n.m.ct !== null)) GlobalQueue.st(n, false, true);
863
+ if (!t && n.m != null && (n.m.St !== null || n.m.ct !== null)) GlobalQueue.Et(n, false, true);
858
864
  }
859
865
 
860
866
  function commitPendingNodes() {
@@ -863,7 +869,7 @@ function commitPendingNodes() {
863
869
  // A node a lane pass re-staged this round is the lane's to reveal; one
864
870
  // a transaction holds (born held by a mainline pass, `passTx`) is that
865
871
  // transaction's to commit, at its landing.
866
- if (!(n.u & (CONFIG_OVERRIDE | CONFIG_HELD))) commitPendingNode(n);
872
+ if (!(n.i & (CONFIG_OVERRIDE | CONFIG_HELD))) commitPendingNode(n);
867
873
  }
868
874
  pendingNodes.length = 0;
869
875
  }
@@ -888,7 +894,7 @@ function flush(e) {
888
894
  }
889
895
  }
890
896
  }
891
- if (globalQueue.ee) {
897
+ if (globalQueue.X) {
892
898
  return;
893
899
  }
894
900
  if (halted) return;