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

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 (90) hide show
  1. package/dist/dev-shared.js +2268 -1734
  2. package/dist/dev.attribution.js +75 -52
  3. package/dist/dev.js +1348 -658
  4. package/dist/observe/affects-marks.js +86 -0
  5. package/dist/observe/affects.js +22 -73
  6. package/dist/observe/boundaries.js +192 -190
  7. package/dist/observe/core/async.js +177 -131
  8. package/dist/observe/core/attribution-queries.js +1 -1
  9. package/dist/observe/core/attribution.js +176 -159
  10. package/dist/observe/core/constants.js +17 -3
  11. package/dist/observe/core/context.js +5 -3
  12. package/dist/observe/core/core.js +520 -364
  13. package/dist/observe/core/dev.js +66 -38
  14. package/dist/observe/core/effect.js +50 -48
  15. package/dist/observe/core/error.js +5 -3
  16. package/dist/observe/core/external.js +5 -6
  17. package/dist/observe/core/graph.js +60 -44
  18. package/dist/observe/core/heap.js +33 -33
  19. package/dist/observe/core/identities.js +62 -0
  20. package/dist/observe/core/lanes.js +238 -260
  21. package/dist/observe/core/owner.js +117 -79
  22. package/dist/observe/core/scheduler.js +381 -217
  23. package/dist/observe/core/truth.js +45 -0
  24. package/dist/observe/core/verdict.js +91 -50
  25. package/dist/observe/deferred.js +184 -0
  26. package/dist/observe/index.js +7 -1
  27. package/dist/observe/map.js +345 -260
  28. package/dist/observe/reveal.js +76 -76
  29. package/dist/observe/signals.js +47 -31
  30. package/dist/observe/store/affects.js +18 -18
  31. package/dist/observe/store/edges.js +39 -0
  32. package/dist/observe/store/optimistic.js +146 -100
  33. package/dist/observe/store/projection.js +68 -55
  34. package/dist/observe/store/store.js +180 -118
  35. package/dist/prod/affects-marks.js +86 -0
  36. package/dist/prod/affects.js +23 -72
  37. package/dist/prod/boundaries.js +156 -154
  38. package/dist/prod/core/async.js +173 -127
  39. package/dist/prod/core/constants.js +17 -3
  40. package/dist/prod/core/context.js +5 -3
  41. package/dist/prod/core/core.js +495 -343
  42. package/dist/prod/core/effect.js +70 -68
  43. package/dist/prod/core/error.js +5 -3
  44. package/dist/prod/core/external.js +5 -6
  45. package/dist/prod/core/graph.js +60 -44
  46. package/dist/prod/core/heap.js +38 -38
  47. package/dist/prod/core/identities.js +62 -0
  48. package/dist/prod/core/lanes.js +230 -252
  49. package/dist/prod/core/owner.js +114 -77
  50. package/dist/prod/core/scheduler.js +327 -163
  51. package/dist/prod/core/truth.js +45 -0
  52. package/dist/prod/core/verdict.js +90 -49
  53. package/dist/prod/deferred.js +182 -0
  54. package/dist/prod/index.js +7 -1
  55. package/dist/prod/map.js +360 -275
  56. package/dist/prod/reveal.js +76 -76
  57. package/dist/prod/signals.js +42 -26
  58. package/dist/prod/store/affects.js +6 -6
  59. package/dist/prod/store/edges.js +39 -0
  60. package/dist/prod/store/optimistic.js +143 -98
  61. package/dist/prod/store/projection.js +25 -19
  62. package/dist/prod/store/store.js +157 -100
  63. package/dist/types/affects-marks.d.ts +14 -0
  64. package/dist/types/boundaries.d.ts +1 -1
  65. package/dist/types/core/async.d.ts +10 -0
  66. package/dist/types/core/constants.d.ts +13 -1
  67. package/dist/types/core/core.d.ts +54 -5
  68. package/dist/types/core/dev.d.ts +51 -13
  69. package/dist/types/core/error.d.ts +9 -1
  70. package/dist/types/core/graph.d.ts +11 -0
  71. package/dist/types/core/identities.d.ts +17 -0
  72. package/dist/types/core/index.d.ts +2 -1
  73. package/dist/types/core/lanes.d.ts +2 -14
  74. package/dist/types/core/owner.d.ts +9 -3
  75. package/dist/types/core/scheduler.d.ts +70 -32
  76. package/dist/types/core/truth.d.ts +16 -0
  77. package/dist/types/core/types.d.ts +21 -0
  78. package/dist/types/core/verdict.d.ts +32 -0
  79. package/dist/types/deferred.d.ts +28 -0
  80. package/dist/types/index.d.ts +6 -0
  81. package/dist/types/map.d.ts +2 -2
  82. package/dist/types/signals.d.ts +28 -7
  83. package/dist/types/store/edges.d.ts +9 -0
  84. package/dist/types/store/index.d.ts +10 -3
  85. package/dist/types/store/optimistic.d.ts +3 -2
  86. package/dist/types/store/projection.d.ts +4 -3
  87. package/dist/types/store/store.d.ts +1 -1
  88. package/dist/types/store/target.d.ts +16 -8
  89. package/dist/types/store/types.d.ts +14 -0
  90. package/package.json +1 -1
@@ -1,16 +1,16 @@
1
- import { releaseFlightTeardown, handleAsync, clearStatus, parkLoadingWindow, notifyStatus, settlePendingSource, settleErroredDependents } from "./async.js";
1
+ import { notifyStatus, releaseFlightTeardown, handleAsync, clearStatus, parkLoadingWindow, stageError, settlePendingSource, releaseIfSettledUnobserved, settleErroredDependents } from "./async.js";
2
2
 
3
- import { STATUS_UNINITIALIZED, REACTIVE_LAZY, REACTIVE_NONE, defaultContext, CONFIG_TRANSPARENT, CONFIG_OWNED_WRITE, CONFIG_AUTO_DISPOSE, CONFIG_SYNC, CONFIG_NO_SNAPSHOT, CONFIG_IN_SNAPSHOT_SCOPE, NOT_PENDING, NO_SNAPSHOT, CONFIG_HAS_SNAPSHOT, CONFIG_HELD, REACTIVE_MANUAL_WRITE, REACTIVE_DIRTY, CONFIG_OVERRIDE, REACTIVE_DISPOSED, REACTIVE_CHECK, REACTIVE_IN_HEAP, REACTIVE_REASK, REACTIVE_SNAPSHOT_STALE, REACTIVE_LANE_DIRTY, CONFIG_GUESS, REACTIVE_RECOMPUTING_DEPS, STATUS_PENDING, CONFIG_VERDICT, EFFECT_RENDER, CONFIG_HELD_FRAME, EFFECT_TRACKED, CONFIG_STAGED, STATUS_ERROR, REACTIVE_ZOMBIE, REACTIVE_MISSED_WAKE, REACTIVE_JOINED, REACTIVE_PROBED, REACTIVE_FRAME_READ, REACTIVE_STAGED_READ, REACTIVE_LANE_READ, REACTIVE_SCREEN_READ, REACTIVE_PROBE_UNANSWERED, CONFIG_CHILDREN_FORBIDDEN, CONFIG_PROMOTED, CONFIG_INPUTS_PUBLISHED, CONFIG_FRESH_READ, REACTIVE_IN_HEAP_HEIGHT, CONFIG_SLOT_NODE, EFFECT_USER } from "./constants.js";
3
+ import { STATUS_UNINITIALIZED, REACTIVE_LAZY, REACTIVE_NONE, defaultContext, CONFIG_TRANSPARENT, CONFIG_OWNED_WRITE, CONFIG_AUTO_DISPOSE, CONFIG_SYNC, CONFIG_NO_SNAPSHOT, CONFIG_IN_SNAPSHOT_SCOPE, NOT_PENDING, NO_SNAPSHOT, CONFIG_HAS_SNAPSHOT, CONFIG_HELD, REACTIVE_MANUAL_WRITE, STATUS_ERROR, REACTIVE_DIRTY, CONFIG_OVERRIDE, REACTIVE_DISPOSED, REACTIVE_CHECK, REACTIVE_IN_HEAP, REACTIVE_REASK, REACTIVE_SNAPSHOT_STALE, CONFIG_CHILDREN_FORBIDDEN, CONFIG_VERDICT, STATUS_PENDING, REACTIVE_LANE_DIRTY, CONFIG_GUESS, REACTIVE_RECOMPUTING_DEPS, CONFIG_LAGS, EFFECT_RENDER, CONFIG_HELD_FRAME, EFFECT_TRACKED, CONFIG_STAGED, CONFIG_STAGED_ERROR, REACTIVE_ZOMBIE, REACTIVE_MISSED_WAKE, REACTIVE_JOINED, REACTIVE_STAGED_READ, REACTIVE_PROBED, REACTIVE_FRAME_READ, REACTIVE_LANE_READ, REACTIVE_SCREEN_READ, REACTIVE_PROBE_UNANSWERED, CAUGHT_REARMED, CONFIG_PROMOTED, CONFIG_INPUTS_PUBLISHED, CONFIG_FRESH_READ, REACTIVE_IN_HEAP_HEIGHT, CONFIG_SLOT_NODE, EFFECT_USER, STATUS_NONE } from "./constants.js";
4
4
 
5
5
  import { NotReadyError } from "./error.js";
6
6
 
7
- import { clearDeps, trimStaleDeps, link, dormantNodes } from "./graph.js";
7
+ import { link, dormantNodes, clearDeps, trimStaleDeps, deferReleases, deferredReleases } from "./graph.js";
8
8
 
9
9
  import { insertIntoHeap, deleteFromHeap, insertIntoHeapHeight, enqueueSub, markNode, markHeap } from "./heap.js";
10
10
 
11
- import { inheritId, disposeChildren, linkChild, markDisposal } from "./owner.js";
11
+ import { inheritId, linkChild, disposeChildren, markDisposal } from "./owner.js";
12
12
 
13
- import { schedule, GlobalQueue, clock, txOf, flushTransaction, joinFuture, queuePendingNode, globalQueue, notifyEpoch, insertSubs, dirtyQueue, bumpNotifyEpoch, setPassLane, passLane, joinPassTx, passTx, holdNode, laneDirty, heldTrim, staleReader, stagedReaders, deferZombie } from "./scheduler.js";
13
+ import { schedule, externalUntrackHook, clock, txOf, flushTransaction, laneWriteHook, joinFuture, queuePendingNode, globalQueue, notifyEpoch, insertSubs, dirtyQueue, observeFlightHook, laneStageHook, passLane, laneReadHook, wireExternalSourceHook, bumpNotifyEpoch, setPassLane, joinPassTx, freshHook, GlobalQueue, laneOutcomeHook, passTx, holdNode, laneDirty, heldTrim, staleReader, laneSeamsHook, stagedReaders, deferZombie } from "./scheduler.js";
14
14
 
15
15
  // The heap's per-node step. A tracked effect's heap visit is its compute
16
16
  // phase — empty, like a user effect whose compute reads nothing — and hands
@@ -20,10 +20,10 @@ import { schedule, GlobalQueue, clock, txOf, flushTransaction, joinFuture, queue
20
20
  // render-effect callback stages its value for the next pass, but a wake pushed
21
21
  // directly into the user queue ran in the SAME pass, read the old value, and
22
22
  // nothing re-notified it when the value landed (#3291).
23
- GlobalQueue.Ce = e => {
24
- if (e.u === EFFECT_TRACKED) {
23
+ GlobalQueue._e = e => {
24
+ if (e.i === EFFECT_TRACKED) {
25
25
  deleteFromHeap(e, dirtyQueue);
26
- e.Ge = true;
26
+ e.Ae = true;
27
27
  globalQueue.enqueue(EFFECT_USER, e.M);
28
28
  }
29
29
  // L2: a zombie's fate is the seam's — its owner's commit disposes it, or
@@ -32,10 +32,29 @@ GlobalQueue.Ce = e => {
32
32
  // owner is held in the future). Its lane's own re-staging is a live write
33
33
  // (REACTIVE_LANE_DIRTY — a lane shows ahead of any park): it runs now, as
34
34
  // the lane's work, for the reveal this seam (#3463).
35
- else if (e.R & REACTIVE_ZOMBIE && !(e.R & REACTIVE_LANE_DIRTY)) deferZombie(e); else recompute(e);
35
+ else if (e.R & REACTIVE_ZOMBIE && !(e.R & REACTIVE_LANE_DIRTY)) deferZombie(e);
36
+ // A lane frame's member (parked by a lane pass, #3698) follows mainline
37
+ // writes only: a lane's dirty on it is cancelled — the lane's apply retires
38
+ // it, and the pass that replaced it already decided what that screen shows
39
+ // (#4137: a `<Show>` branch withdrawn by its own lane re-ran on a falsy
40
+ // condition).
41
+ // (Lanes exist only with the lane engine installed: folded away without.)
42
+ else if (laneStageHook && e.R & REACTIVE_ZOMBIE && laneFrameMember(e)) {
43
+ deleteFromHeap(e, dirtyQueue);
44
+ e.R &= -65540;
45
+ } else recompute(e);
36
46
  };
37
47
 
38
- GlobalQueue.Fe = disposeChildren;
48
+ /** The zombie's frame was parked by lane work: the nearest non-zombie owner
49
+ * (the one whose pass parked it) carries a lane's derived value — or, an
50
+ * effect (no lane value: `laneStage`), is listed in a lane (an `insert()`
51
+ * hole's render effect). */ function laneFrameMember(e) {
52
+ let t = e._parent;
53
+ while (t.R & REACTIVE_ZOMBIE) t = t._parent;
54
+ return (t.l & (CONFIG_OVERRIDE | CONFIG_GUESS)) === CONFIG_OVERRIDE || t.i && t.T?.Re?.v;
55
+ }
56
+
57
+ GlobalQueue.Ce = disposeChildren;
39
58
 
40
59
  let tracking = false;
41
60
 
@@ -43,11 +62,15 @@ let context = null;
43
62
 
44
63
  let snapshotCaptureActive = false;
45
64
 
65
+ /** The lane at the root of the running chain of first passes: the lane whose
66
+ * pass created the chain's first node (a mount), inherited by every first
67
+ * pass nested under it, whose seats are mainline (`recompute`, #4166). */ let laneRoot;
68
+
46
69
  let snapshotSources = null;
47
70
 
48
71
  function ownerInSnapshotScope(e) {
49
72
  while (e) {
50
- if (e.he) return true;
73
+ if (e.Oe) return true;
51
74
  e = e._parent;
52
75
  }
53
76
  return false;
@@ -59,34 +82,34 @@ function setSnapshotCapture(e) {
59
82
  }
60
83
 
61
84
  function markSnapshotScope(e) {
62
- e.he = true;
85
+ e.Oe = true;
63
86
  }
64
87
 
65
88
  function releaseSnapshotScope(e) {
66
- e.he = false;
89
+ e.Oe = false;
67
90
  releaseSubtree(e);
68
91
  schedule();
69
92
  }
70
93
 
71
94
  function releaseSubtree(e) {
72
- let t = e.Ve;
95
+ let t = e.De;
73
96
  while (t) {
74
- if (t.he) {
75
- t = t.ge;
97
+ if (t.Oe) {
98
+ t = t.pe;
76
99
  continue;
77
100
  }
78
- if (t.ee) {
101
+ if (t.X) {
79
102
  const e = t;
80
- e.i &= ~CONFIG_IN_SNAPSHOT_SCOPE;
103
+ e.l &= ~CONFIG_IN_SNAPSHOT_SCOPE;
81
104
  if (e.R & REACTIVE_SNAPSHOT_STALE) {
82
105
  e.R &= ~REACTIVE_SNAPSHOT_STALE;
83
106
  e.R |= REACTIVE_DIRTY;
84
- if (dirtyQueue.Ue > e.me) dirtyQueue.Ue = e.me;
107
+ if (dirtyQueue.Ge > e.Fe) dirtyQueue.Ge = e.Fe;
85
108
  insertIntoHeap(e, dirtyQueue);
86
109
  }
87
110
  }
88
111
  releaseSubtree(t);
89
- t = t.ge;
112
+ t = t.pe;
90
113
  }
91
114
  }
92
115
 
@@ -97,8 +120,8 @@ function clearSnapshots() {
97
120
  // pre-initialized to undefined (see ext()), and every reader tests
98
121
  // `!== undefined` — assign, don't `delete`: deleting a field pushes the
99
122
  // object to dictionary mode for every later read of every field.
100
- const t = e.m;
101
- if (t != null) t.Le = undefined;
123
+ const t = e.T;
124
+ if (t != null) t.Pe = undefined;
102
125
  }
103
126
  snapshotSources = null;
104
127
  }
@@ -108,7 +131,8 @@ function clearSnapshots() {
108
131
  function recompute(e, t = false) {
109
132
  // §12d: any recompute can clean a marked subscriber — invalidate skips.
110
133
  bumpNotifyEpoch();
111
- const n = e.u;
134
+ const n = e.i;
135
+ let o;
112
136
  // Lanes (plan sec. 28): the seat of a pass is its node's. A node carrying a lane's
113
137
  // derived value runs as the lane's whoever dirtied it — a sync write, a
114
138
  // boundary reset, a frame rerun — so its children and its result are the
@@ -124,15 +148,22 @@ function recompute(e, t = false) {
124
148
  // derivation's pass into the lane (`read`); a leaf's never moves.
125
149
  // Restored at the end, after this pass's staging and runs have been
126
150
  // routed.
151
+ // Lanes exist only with the lane engine installed (`laneStageHook`): a
152
+ // bundle without it seats every pass on mainline, and folds the seat away.
127
153
  const E = passLane;
128
- setPassLane((e.R & REACTIVE_LANE_DIRTY || (e.i & (CONFIG_OVERRIDE | CONFIG_GUESS)) === CONFIG_OVERRIDE) && e.m?.He?.B ? e.m.He : // Loose `!=`: false with no creator lane (undefined == null).
129
- t && E?._parent.xe != E && (creatorPass(context)?.R ?? 0) & REACTIVE_RECOMPUTING_DEPS ? E : null);
154
+ // The mount a first pass belongs to: its creator's lane, or the one its
155
+ // creator's own mount came from — a render effect a verdict lane's mount's
156
+ // content creates is that mount's too (#4166). Lanes only, like the seat.
157
+ const s = laneRoot;
158
+ const i = laneStageHook && (laneRoot = t && (E || s));
159
+ setPassLane(!laneStageHook ? null : (e.R & REACTIVE_LANE_DIRTY || (e.l & (CONFIG_OVERRIDE | CONFIG_GUESS)) === CONFIG_OVERRIDE) && e.T?.Re?.v ? e.T.Re : // Loose `!=`: false with no creator lane (undefined == null).
160
+ t && E?._parent.he != E && creatorPass(context)?.R & REACTIVE_RECOMPUTING_DEPS ? E : null);
130
161
  // CARVE 2: lane posture resolution (OPTIMISTIC_DIRTY, derived-override
131
162
  // re-derivation, lane adoption through deps) went with the optimistic engine.
132
163
  if (!t) {
133
164
  deleteFromHeap(e, dirtyQueue);
134
- if (e.m !== null) {
135
- e.m.Te = null;
165
+ if (e.T !== null) {
166
+ e.T.Se = null;
136
167
  // Supersede is where an iterator flight dies (#3122): close it now.
137
168
  // Idempotent with the cleanup-channel close.
138
169
  releaseFlightTeardown(e);
@@ -153,21 +184,23 @@ function recompute(e, t = false) {
153
184
  // committed screen, settle the flight and drop the hold — a superseding
154
185
  // write's verdict would depend on that probe. Cleared for this pass; a
155
186
  // probe in the body re-stamps it after the plain reads.
156
- if (e.S & STATUS_PENDING) e.i &= ~CONFIG_VERDICT;
157
- if (e.i & CONFIG_HELD) {
187
+ if (e.m & STATUS_PENDING) e.l &= ~CONFIG_VERDICT;
188
+ if (e.l & CONFIG_HELD) {
158
189
  const t = txOf(e);
159
190
  // Held by a blocked lane: the frame joins nothing — a lane never holds
160
191
  // a sync write (#3460). The pass is the lane's if it reads the lane's
161
192
  // world (`read`), and has left it otherwise.
162
- if (t.B) ; else if (n !== EFFECT_RENDER && !(e.i & CONFIG_VERDICT)) joinPassTx(t); else if (t !== flushTransaction && !(e.S & STATUS_UNINITIALIZED || e.i & CONFIG_HELD_FRAME)) {
193
+ // An answered deferred node's re-pass is a lagging question (D-40):
194
+ // it joins nothing, so the write that reached it commits mainline.
195
+ if (t.v || e.l & CONFIG_LAGS) ; else if (n !== EFFECT_RENDER && !(e.l & CONFIG_VERDICT)) joinPassTx(t, freshHook?.(e, e.m & STATUS_UNINITIALIZED)); else if (t !== flushTransaction && !(e.m & STATUS_UNINITIALIZED || e.l & CONFIG_HELD_FRAME)) {
163
196
  // Published mainline, it is not held: the frame this pass builds is
164
197
  // replaced on the spot (#3404) — this flush's commit retires the
165
198
  // committed frame the held pass had parked (`commitPendingNode`),
166
199
  // after the new frame's first runs, and the held pass's own
167
200
  // children die below (`disposeChildren`). The landing re-derives a
168
201
  // fresh held frame for the reveal (`_reruns`).
169
- e.Oe = NOT_PENDING;
170
- if (n === EFFECT_RENDER) e.i &= ~CONFIG_HELD;
202
+ e.se = NOT_PENDING;
203
+ if (n === EFFECT_RENDER) e.l &= ~CONFIG_HELD;
171
204
  }
172
205
  }
173
206
  // The previous pass's frame. If that pass is still awaiting its commit
@@ -175,75 +208,93 @@ function recompute(e, t = false) {
175
208
  // frame parked before it stays parked. Otherwise they ARE the frame:
176
209
  // park them until this pass commits. Tracked effects run after the seam
177
210
  // and own nothing to park.
178
- if (n === EFFECT_TRACKED || e.i & CONFIG_STAGED) disposeChildren(e); else if (e.Ve !== null || e.Re !== null) parkChildren(e);
211
+ if (n === EFFECT_TRACKED || e.l & CONFIG_STAGED) {
212
+ // A lazy node only those children read is released when this pass
213
+ // ends, if the pass doesn't read it again (#4142). A cleanup or
214
+ // `unobserved` hook that throws here neither stops the pass nor skips
215
+ // that drain: its error is rethrown when the flush ends (owner.ts).
216
+ const t = deferredReleases;
217
+ deferReleases(o = []);
218
+ disposeChildren(e);
219
+ deferReleases(t);
220
+ } else if (e.De !== null || e.He !== null) parkChildren(e);
221
+ // An error a pass staged (D-41) is replaced by this pass's answer: a
222
+ // value, a flight, or an error of its own (#4109, #4145).
223
+ if (e.l & CONFIG_STAGED_ERROR) {
224
+ e.se = NOT_PENDING;
225
+ e.l ^= CONFIG_STAGED_ERROR;
226
+ }
179
227
  }
180
- const u = !!(e.S & STATUS_UNINITIALIZED);
228
+ const l = !!(e.m & STATUS_UNINITIALIZED);
181
229
  // Capture both error and pending status before the compute clears them.
182
230
  // A conditional can drop its pending source and recover to an unchanged
183
231
  // value, leaving blocked dependents outside that source’s settle walk.
184
- const s = e.S & STATUS_ERROR ? e.m?.F : undefined;
185
- const i = (e.S & STATUS_PENDING) !== 0;
186
- const l = i ? e.m?.Se : undefined;
232
+ const r = e.m & STATUS_ERROR ? e.T?.F : undefined;
233
+ const u = (e.m & STATUS_PENDING) !== 0;
234
+ const _ = u ? e.T?.fe : undefined;
187
235
  // Pending SOURCE-hood, captured before the compute clears status: a node
188
236
  // whose own flight parked dependents self-registers in _pendingSources
189
237
  // (notifyStatus, isSource). If this recompute supersedes that flight and
190
238
  // settles synchronously, those dependents settle HERE — asyncWrite's
191
239
  // settlePendingSource walk never runs for a landing that was preempted
192
240
  // (#3181).
193
- const o = e.m?.Se?.has(e);
241
+ const a = e.T?.fe?.has(e);
242
+ // D-41: this pass's error is staged, not published (`stageError`).
243
+ let I = false;
194
244
  // A19 exc. 2: a `refresh()` re-asks the question already answered — quiet
195
245
  // for the verdict — unless the question in flight is a new one, which the
196
246
  // re-ask does not launder (a poll during a quiet confirm stays quiet).
197
- const _ = (e.R & REACTIVE_REASK) !== 0 && !(e.S & STATUS_PENDING && e.m !== null && !e.m.ke);
198
- const r = context;
247
+ const N = (e.R & REACTIVE_REASK) !== 0 && !(e.m & STATUS_PENDING && e.T !== null && !e.T.Ve);
248
+ const f = context;
199
249
  context = e;
200
- e.G = null;
201
- e.pe++;
250
+ e._ = null;
251
+ e.Ne++;
202
252
  // REACTIVE_ZOMBIE is position: it says the node sits on its owner's parked
203
253
  // frame, and the splice/reawaken paths key off it. A zombie reruns for
204
254
  // live writes until the commit that disposes it, so every per-pass wipe
205
255
  // — here, the finally below, updateIfNecessary — carries it (#3543).
206
- e.R = REACTIVE_RECOMPUTING_DEPS | e.R & REACTIVE_ZOMBIE;
207
- e.Ie = clock;
256
+ e.R = REACTIVE_RECOMPUTING_DEPS | e.R & (REACTIVE_ZOMBIE | REACTIVE_REASK);
257
+ e.ie = clock;
208
258
  // The pass's previous value: its staging, else a lane node's lane value
209
259
  // when it has one (lanes.ts), else the committed one.
210
- let I = e.Oe !== NOT_PENDING ? e.Oe : e.i & CONFIG_OVERRIDE && e.m.B !== NOT_PENDING ? e.m.B : e.Ae;
211
- let a = e.me;
212
- let N = false;
213
- // L2: did this pass read the future (REACTIVE_JOINED, set by read)?
214
- let f = false;
215
- let T = tracking;
260
+ let T = e.se !== NOT_PENDING ? e.se : e.l & CONFIG_OVERRIDE && e.T.v !== NOT_PENDING ? e.T.v : e.Ie;
261
+ let S = e.Fe;
262
+ let c = false;
263
+ // L2: did this pass read the future (REACTIVE_JOINED, set by read) — or,
264
+ // a lane's mount, a staging of this flush (#3851, #4166)?
265
+ let A = false;
266
+ let R = tracking;
216
267
  tracking = true;
217
268
  try {
218
- if (!false && e.i & CONFIG_SYNC) {
219
- I = e.ee(I);
220
- if (e.m !== null) e.m.Te = null;
221
- e.De = false;
269
+ if (!false && e.l & CONFIG_SYNC) {
270
+ T = e.X(T);
271
+ if (e.T !== null) e.T.Se = null;
272
+ e.ce = false;
222
273
  } else {
223
274
  // A projection's body self-registers its flight through handleAsync
224
275
  // (with the commit as setter): its undefined return is not a sync
225
276
  // answer, and the outer handleAsync must not clobber the registration.
226
- const t = e.m?.Te;
227
- const n = e.ee(I);
228
- const E = typeof n === "object" && n !== null;
229
- const u = e.m?.Te !== t;
230
- I = u || !E ? n : handleAsync(e, n);
231
- if (!u && !E) {
232
- if (e.m !== null) e.m.Te = null;
277
+ const t = e.T?.Se;
278
+ const n = e.X(T);
279
+ const o = typeof n === "object" && n !== null;
280
+ const E = e.T?.Se !== t;
281
+ T = E || !o ? n : handleAsync(e, n);
282
+ if (!E && !o) {
283
+ if (e.T !== null) e.T.Se = null;
233
284
  // A sync (non-object) return is the first real answer; async-shaped
234
285
  // results clear inside handleAsync at their own landing points, and a
235
286
  // self-registered flight clears when its own handleAsync lands.
236
- e.De = false;
287
+ e.ce = false;
237
288
  }
238
289
  }
239
290
  // On a status-free node clearStatus is a guaranteed no-op: every field
240
291
  // its body gates on is either _statusFlags or lives in the cold
241
292
  // extension — no extension, no status to clear. (_x from an unrelated
242
293
  // installer just makes clearStatus a cheap re-verified no-op.)
243
- if (e.S !== 0 || e.m !== null) clearStatus(e, t);
294
+ if (e.m !== 0 || e.T !== null) clearStatus(e, t);
244
295
  } catch (t) {
245
296
  const n = t instanceof NotReadyError;
246
- if (n && e.De) {
297
+ if (n && e.ce) {
247
298
  // Loading window with an unready sync dependency: register for the
248
299
  // source's settle (the settlePendingSource walk runs off
249
300
  // _pendingSources + _blocked alone) but take NO read-visible pending
@@ -253,11 +304,15 @@ function recompute(e, t = false) {
253
304
  // retry can actually run.
254
305
  parkLoadingWindow(e, t);
255
306
  } else {
256
- if (n) ext(e).de = true;
257
- notifyStatus(e, n ? STATUS_PENDING : STATUS_ERROR, t);
258
- // The replacement source is fully propagated now. If no new flight
259
- // re-owned self, retire the superseded flight and its dependent copies.
260
- if (n && o && !e.m?.Te) settlePendingSource(e);
307
+ // D-41: a pass of a held node, or one that read a staging of this
308
+ // flush, stages its error (`stageError`).
309
+ if (n || !(I = stageError(e, t, true))) {
310
+ if (n) ext(e).ue = true;
311
+ notifyStatus(e, n ? STATUS_PENDING : STATUS_ERROR, t);
312
+ // The replacement source is fully propagated now. If no new flight
313
+ // re-owned self, retire the superseded flight and its dependent copies.
314
+ if (n && a && !e.T?.Se) settlePendingSource(e);
315
+ }
261
316
  // A re-park drops what the earlier pass carried (#3456): a source this
262
317
  // pass no longer reaches — its branch switched, or a fresh flight
263
318
  // replaced the inputs' pending with its own — stays copied onto
@@ -265,21 +320,27 @@ function recompute(e, t = false) {
265
320
  // stops at this node (nothing left to retire) before it finds them. A
266
321
  // dependent then waits forever on a flight it has no path to. The
267
322
  // re-park twin of the unchanged-value recovery sweep below; dependents
268
- // with another path keep the source (retryReaches).
269
- if (n && l) for (const t of l) if (t !== e && !e.m?.Se?.has(t)) settlePendingSource(e, t);
323
+ // with another path keep the source (retryReaches). A staged error
324
+ // answered what the pass carried: the same.
325
+ if ((n || I) && _) for (const t of _) if (t !== e && !e.T?.fe?.has(t)) settlePendingSource(e, t);
270
326
  }
271
327
  } finally {
272
- tracking = T;
328
+ tracking = R;
329
+ if (laneStageHook) laneRoot = s;
273
330
  // Consume the missed-wake latch (#3037, set by insertSubs): a dep write
274
331
  // landed beneath this pass on a link it had already validated. The wipe
275
332
  // below must not key off DIRTY/CHECK — the read-time pull protocol
276
333
  // (markNode(c) in read()) marks the running node as part of ordinary
277
334
  // bookkeeping, and those marks are correctly discarded here.
278
- N = (e.R & REACTIVE_MISSED_WAKE) !== 0;
279
- f = (e.R & REACTIVE_JOINED) !== 0;
280
- // A verdict reader is one for as long as it probes: a pass that entered
281
- // no window (REACTIVE_PROBED) is an ordinary derivation again.
282
- if (!(e.R & REACTIVE_PROBED)) e.i &= ~CONFIG_VERDICT;
335
+ c = (e.R & REACTIVE_MISSED_WAKE) !== 0;
336
+ // A mount's staged read joins it — except a nested derivation left
337
+ // pending: no render effect reaches it yet, so it holds nothing and
338
+ // reaches no boundary (Reader, #4203). A reader that does is caught.
339
+ A = !!(e.R & (i && (E || n || !(e.m & STATUS_PENDING)) ? REACTIVE_JOINED | REACTIVE_STAGED_READ : REACTIVE_JOINED));
340
+ // A verdict reader is one for as long as it probes, or reads a memo
341
+ // that does (`read`): a pass that did neither (REACTIVE_PROBED, the same
342
+ // bit) is an ordinary derivation again.
343
+ e.l = e.l & ~CONFIG_VERDICT | e.R & REACTIVE_PROBED;
283
344
  // REACTIVE_DISPOSED survives too (#3621): the pass may have disposed its
284
345
  // own owner (a memo calling its root's `dispose()`, a cleanup doing so
285
346
  // #3601/#3606), and `disposeChildren` set the flag on this node
@@ -288,11 +349,12 @@ function recompute(e, t = false) {
288
349
  // this pass's verdict for the landing; the next pass's wipe at the top
289
350
  // clears it.
290
351
  e.R = e.R & (REACTIVE_ZOMBIE | REACTIVE_DISPOSED | REACTIVE_FRAME_READ | REACTIVE_STAGED_READ | REACTIVE_LANE_READ | REACTIVE_SCREEN_READ | REACTIVE_PROBE_UNANSWERED) | (t ? e.R & REACTIVE_SNAPSHOT_STALE : 0);
291
- context = r;
352
+ context = f;
353
+ if (o) for (const e of o) releaseIfSettledUnobserved(e);
292
354
  // A19 exc. 2: a pass that went pending on a `refresh()` re-asks the
293
355
  // question already answered — quiet for the verdict; any other pending
294
356
  // pass is a new question. Settled, there is nothing to classify.
295
- if (e.m !== null) e.m.ke = _ && (e.S & STATUS_PENDING) !== 0;
357
+ if (e.T !== null) e.T.Ve = N && (e.m & STATUS_PENDING) !== 0;
296
358
  }
297
359
  // A node that died during its own pass (#3621) is dead at the end of it,
298
360
  // and the pass is void. Its owner's teardown already unlinked its deps,
@@ -307,7 +369,7 @@ function recompute(e, t = false) {
307
369
  // attribution frame opened at the top is still closed.
308
370
  if (e.R & REACTIVE_DISPOSED) {
309
371
  clearDeps(e);
310
- if (e.m !== null) e.m.Te = null;
372
+ if (e.T !== null) e.T.Se = null;
311
373
  setPassLane(E);
312
374
  return;
313
375
  }
@@ -316,47 +378,39 @@ function recompute(e, t = false) {
316
378
  // seat that read none of the lane's world has left it: its result is the
317
379
  // frame's (a derivation whose branch no longer reaches the guess). A
318
380
  // guess is written, not derived — it never leaves this way.
319
- let S = passLane;
381
+ let C = !laneStageHook ? null : passLane;
320
382
  // Listed before its staging, a pending pass included (the lane's own
321
383
  // flight is the lane's); false: the pass left the lane (lanes.ts).
322
- const c = !!e.m?.F;
323
- if (S !== null) {
324
- if (GlobalQueue.W(e, S, t, c)) setPassLane(S); else S = null;
384
+ const d = !!e.T?.F || I;
385
+ if (laneStageHook && C !== null) {
386
+ if (laneStageHook(e, C, t, d)) setPassLane(C); else C = null;
325
387
  }
326
- if (!e.m?.F) {
388
+ if (!d) {
327
389
  // INV-11 (#3330): the equality gate compares against the slot this run
328
390
  // publishes to — the staged `_pendingValue` when staged; a lane node's
329
391
  // lane value (a node entering the lane this pass has none yet — its
330
392
  // committed value, `laneStage` having voided a frame staging).
331
- const i = e.Oe !== NOT_PENDING ? e.Oe : e.i & CONFIG_OVERRIDE && e.m.B !== NOT_PENDING ? e.m.B : e.Ae;
332
- let _ = false;
333
- try {
334
- _ = !n && u || !e.ye || !e.ye(i, I);
335
- } catch (t) {
336
- // A throwing user comparator is an error of this node's computation.
337
- // Route it through the same status path as a compute-phase throw so
338
- // error boundaries contain it; otherwise it unwinds the scheduler
339
- // flush, bypassing every boundary and wedging the queue (#2837).
340
- notifyStatus(e, STATUS_ERROR, t);
341
- }
393
+ const o = e.se !== NOT_PENDING ? e.se : e.l & CONFIG_OVERRIDE && e.T.v !== NOT_PENDING ? e.T.v : e.Ie;
394
+ // A throwing comparator is contained inside `isSame` (A3, #2837; #4111).
395
+ const E = !n && l || !!e.T?.de || !isSame(e, o, T);
342
396
  // Effects use `_equals: false` (no per-effect closure). The side effects that
343
397
  // the equals closure used to perform — flagging the effect dirty and enqueueing
344
398
  // its runner — happen here instead. `!create` matches the previous `initialized`
345
399
  // gate: the explicit recompute(node, true) inside effect() does not enqueue, so
346
400
  // effect() can call its runner synchronously for the first run.
347
- if (n && _ &&
401
+ if (n && E &&
348
402
  // A stale reader of a lane (REACTIVE_SCREEN_READ) that computed what it
349
403
  // last applied owes no run (lanes.ts).
350
- !(e.R & REACTIVE_SCREEN_READ && !e.Ge && Object.is(e.be, I)) &&
404
+ !(e.R & REACTIVE_SCREEN_READ && !e.Ae && Object.is(e.ge, T)) &&
351
405
  // A re-staging pass owes no run: the commit replays the effect (#3802).
352
- e.Oe === NOT_PENDING) {
353
- e.Ge = !e.m?.F;
406
+ e.se === NOT_PENDING) {
407
+ e.Ae = !e.T?.F;
354
408
  // Reuse one bound runner per effect — runEffect no-ops on a stale
355
409
  // `_modified`, so re-enqueueing the same function is harmless.
356
410
  // Lane work's run is the lane's (released at its reveal) — a first
357
411
  // pass under a lane too: `effect()` skips the synchronous first run of
358
412
  // a lane's node.
359
- if (!t || S !== null) globalQueue.enqueue(n, e.Y ??= GlobalQueue.q.bind(null, e), S);
413
+ if (!t || C !== null) globalQueue.enqueue(n, e.W ??= GlobalQueue.K.bind(null, e), C);
360
414
  }
361
415
  // Lanes. A written guess's own pass from the frame: its source
362
416
  // recomputed it — the truth (A18: "the source is whatever recomputes the
@@ -364,7 +418,7 @@ function recompute(e, t = false) {
364
418
  // confirm is a landing too — the lane's end commits it) and notifies
365
419
  // only a correction: an equal truth re-runs nothing (lanes.ts). (As the
366
420
  // lane's own work the lane judged it — `laneStage`.)
367
- if (!t && S === null && e.i & CONFIG_GUESS && GlobalQueue.We(e, I, c)) ; else if (c) ; else if (_) {
421
+ if (!t && C === null && e.l & CONFIG_GUESS && laneOutcomeHook(e, T, d)) ; else if (d) ; else if (E) {
368
422
  // L2: a first pass is born held — staged, committed with the
369
423
  // transaction, its effect's first run the landing's (A29; `effect()`
370
424
  // skips the synchronous first run on a staged value) — when the flush
@@ -381,15 +435,15 @@ function recompute(e, t = false) {
381
435
  // pass that runs before anything joins: the pass's input, not a verdict
382
436
  // after it. An effect still carrying an uncommitted staged value
383
437
  // re-stages: the commit applies the latest pass, not the born-held one.
384
- if (S !== null) {
438
+ if (C !== null) {
385
439
  // Lane work: the lane's value — into the slot while the lane has not
386
440
  // revealed (its reveal shows it), as its staging once it has (the
387
441
  // next reveal promotes it; the screen keeps the revealed value). An
388
442
  // effect's value slot is private: the run the lane holds is what
389
443
  // shows it — unless the effect was born held, whose first run is the
390
444
  // commit's (A29): it re-stages, as below.
391
- if (n && e.Oe === NOT_PENDING) e.Ae = I; else if (n || S.Ze) e.Oe = I; else e.m.B = I;
392
- } else if (t ? !((flushTransaction !== null || passTx !== null) && (f || E && e.R & REACTIVE_STAGED_READ || (creatorPass(r)?.R ?? 0) & REACTIVE_JOINED)) : n && e.Oe === NOT_PENDING) {
445
+ if (n && e.se === NOT_PENDING) e.Ie = T; else if (n || C.ke) e.se = T; else e.T.v = T;
446
+ } else if (t ? !((flushTransaction !== null || passTx !== null) && (A || creatorPass(f)?.R & REACTIVE_JOINED)) : n && e.se === NOT_PENDING) {
393
447
  // A first pass publishes directly. So does an effect: its value slot
394
448
  // is private (only its own run reads it), and the staging round-trip
395
449
  // (queuePendingNode + commitPendingNodes) paid per effect on the
@@ -400,9 +454,9 @@ function recompute(e, t = false) {
400
454
  // sources commit) must see the fresh value while PLAIN reads stay
401
455
  // committed until flush (#3009 purity). The pending round-trip is
402
456
  // that separation; it cannot be skipped on any path a pull can reach.
403
- e.Ae = I;
457
+ e.Ie = T;
404
458
  } else {
405
- e.Oe = I;
459
+ e.se = T;
406
460
  // Born held: in the transaction from birth, so a read of it this
407
461
  // tick is a read of its world (the mount-during-a-hold case), not
408
462
  // only after the seam parks it.
@@ -412,47 +466,54 @@ function recompute(e, t = false) {
412
466
  // (`commitPendingNode` initializes it) — every reader of it
413
467
  // derives from the future (`read`), an untracked one throws
414
468
  // (A19 exc. 1).
415
- e.S |= STATUS_UNINITIALIZED;
469
+ e.m |= STATUS_UNINITIALIZED;
416
470
  // A boundary that has not shown content catches it: its fallback
417
471
  // waits for the commit (#3540). (The pass's own status clear above
418
- // dropped what the read recorded.)
419
- GlobalQueue.fe?.(e);
472
+ // dropped what the read recorded.) Not when the flush has joined
473
+ // the hold and the pass is its own (not a verdict lane's mount,
474
+ // #3851): the mount is part of the hold, and the boundary appears
475
+ // at its commit, its fallback never seen (D-13, U-3) — a `<Show>`
476
+ // mounting it over a landing included.
477
+ freshHook?.(e, !i && flushTransaction);
420
478
  }
421
479
  }
422
480
  // insertSubs only walks _subs (no scheduling of its own), so a
423
481
  // subscriber-less node has nothing to notify.
424
- if (e.t !== null) {
482
+ if (e.o !== null) {
425
483
  insertSubs(e);
426
484
  // Lane work re-staged: the lane's members re-derive as its work.
427
- if (S !== null) laneDirty(e, S);
485
+ if (C !== null) laneDirty(e, C);
428
486
  }
429
- } else if (e.me != a) {
430
- for (let t = e.t; t !== null; t = t.o) insertIntoHeapHeight(t.l, dirtyQueue);
487
+ } else if (e.Fe != S) {
488
+ for (let t = e.o; t !== null; t = t.t) insertIntoHeapHeight(t.u, dirtyQueue);
431
489
  }
432
490
  // Silent recovery: errored → unchanged value fires no notification, but
433
491
  // dependents still holding the propagated error consumed their dirty flag
434
492
  // in an errored run and may sit on stale commits (#2949). Changed-value
435
493
  // recoveries ride insertSubs above; a comparator throw re-errored the node
436
494
  // (el._x?._error re-set), so this only runs on a genuinely clean recovery.
437
- if (!_ && !e.m?.F) {
438
- if (s !== undefined) settleErroredDependents(e, s);
495
+ if (!E && !e.T?.F) {
496
+ if (r !== undefined) settleErroredDependents(e, r);
439
497
  // Self-registration (this node's own superseded flight) is the #3181
440
498
  // sweep's business below — retiring it here too would walk twice.
441
- if (l) for (const t of l) if (t !== e) settlePendingSource(e, t);
499
+ if (_) for (const t of _) if (t !== e) settlePendingSource(e, t);
442
500
  }
443
501
  // #3181: a synchronous settle supersedes the old landing callback, so
444
502
  // recompute owns its pending-source sweep. An uninitialized node without
445
503
  // a replacement source still has no truth to reveal and must stay parked.
446
- if (o && !(e.S & (STATUS_PENDING | STATUS_UNINITIALIZED))) settlePendingSource(e);
504
+ if (a && !(e.m & (STATUS_PENDING | STATUS_UNINITIALIZED))) settlePendingSource(e);
447
505
  }
448
506
  // A first pass that went pending where the born-held arm would have held
449
507
  // its value (it read a held node, or a verdict lane's mount read a staging,
450
508
  // #3851) is held like it: its answer is the hold's, and the hold waits
451
- // for it (A29, #3800) — unless a boundary that has not shown content
452
- // catches it: then it is the boundary's, and the hold does not wait (#3540).
453
- if (t && S === null && (f || E && e.R & REACTIVE_STAGED_READ) && e.S & STATUS_PENDING) {
509
+ // for it (A29, #3800). A boundary that has not shown content catches it
510
+ // and it is held all the same — its answer reveals no earlier than the
511
+ // hold's commit (D-12) — but the hold does not wait for it: its only
512
+ // readers are behind the fallback (`_hidden`; F-4, #3540). A boundary
513
+ // re-armed by `on` owns what it collects outright (D-14): not held.
514
+ if (t && C === null && A && e.m & STATUS_PENDING) {
454
515
  const t = flushTransaction ?? passTx;
455
- if (t !== null && !t.B && !GlobalQueue.fe?.(e)) holdNode(e, t);
516
+ if (t && !t.v && freshHook?.(e) !== CAUGHT_REARMED) holdNode(e, t);
456
517
  }
457
518
  // Dependencies are the committed frame's until it is replaced (A30, #3410):
458
519
  // a pass that staged its value leaves the previous pass's tail linked for
@@ -471,7 +532,7 @@ function recompute(e, t = false) {
471
532
  // kept at a park — one spurious recompute at most). A creation pass and a
472
533
  // tracked effect trim now: their frames are replaceable like a direct
473
534
  // commit, and a tracked effect's spurious run would be user-visible.
474
- if (!e.m?.F && e.Oe === NOT_PENDING && !(n && e.Ge)) {
535
+ if (!e.T?.F && e.se === NOT_PENDING && !(n && e.Ae)) {
475
536
  if (t || n === EFFECT_TRACKED) trimStaleDeps(e); else heldTrim(e);
476
537
  }
477
538
  // A staged value, a parked frame (L2: the commit retires it), or status the
@@ -479,10 +540,10 @@ function recompute(e, t = false) {
479
540
  // node for this flush's commit. A first pass queues only when pending or
480
541
  // born held: otherwise its value published directly. A queued pass's
481
542
  // children are uncommitted (CONFIG_STAGED) until that commit.
482
- if (e.Oe !== NOT_PENDING || e.m !== null && (e.m.Qe !== null || e.m.ve !== null) || (e.S & (STATUS_PENDING | STATUS_UNINITIALIZED)) !== 0 && (!t || (e.S & STATUS_PENDING) !== 0)) {
483
- e.i |= CONFIG_STAGED;
543
+ if (e.se !== NOT_PENDING || e.T !== null && (e.T.Ue !== null || e.T.me !== null) || (e.m & (STATUS_PENDING | STATUS_UNINITIALIZED)) !== 0 && (!t || (e.m & STATUS_PENDING) !== 0)) {
544
+ e.l |= CONFIG_STAGED;
484
545
  // Lane work is the lane's to reveal (its seam), not this flush's commit.
485
- if (S === null) queuePendingNode(e);
546
+ if (C === null) queuePendingNode(e);
486
547
  }
487
548
  setPassLane(E);
488
549
  // Missed-wake reschedule (see the finally above): values this pass read
@@ -490,7 +551,7 @@ function recompute(e, t = false) {
490
551
  // accept the node. Equality gates stop same-value landings from cascading,
491
552
  // and a re-run only latches again if another nested commit changes a dep
492
553
  // beneath it — convergent unless deps genuinely keep changing.
493
- if (N) {
554
+ if (c) {
494
555
  enqueueSub(e);
495
556
  schedule();
496
557
  }
@@ -505,9 +566,9 @@ function updateIfNecessary(e) {
505
566
  // would resurrect it (#2983) — readers serve its last value.
506
567
  if (e.R & (REACTIVE_RECOMPUTING_DEPS | REACTIVE_DISPOSED)) return;
507
568
  if (e.R & REACTIVE_CHECK) {
508
- for (let t = e.p; t; t = t._) {
509
- const n = t.I;
510
- if (n.ee) {
569
+ for (let t = e.C; t; t = t.G) {
570
+ const n = t.S;
571
+ if (n.X) {
511
572
  updateIfNecessary(n);
512
573
  }
513
574
  if (e.R & REACTIVE_DIRTY) {
@@ -515,7 +576,7 @@ function updateIfNecessary(e) {
515
576
  }
516
577
  }
517
578
  }
518
- if (e.R & REACTIVE_DIRTY || e.m?.F && e.Ie < clock && !e.m?.Te) {
579
+ if (e.R & REACTIVE_DIRTY || e.T?.F && e.ie < clock && !e.T?.Se) {
519
580
  recompute(e);
520
581
  }
521
582
  // The guard above refused an already-disposed node; the recompute it just
@@ -534,74 +595,75 @@ function computed(e, t) {
534
595
  // `in` (not `!== undefined`): an explicit `loadingValue: undefined` on a
535
596
  // `T | undefined` node is a real commit #0. The typeof guard tolerates
536
597
  // non-object option values that older call shapes force through `as any`.
537
- const E = t !== null && typeof t === "object" && "loadingValue" in t;
598
+ const o = t !== null && typeof t === "object" && "loadingValue" in t;
538
599
  // Two literals, one per tier, selected at build time (the observe flag is
539
600
  // a literal after replacement; the untaken branch is dead code). The observe
540
- // literal is the prod literal plus its `_name` slot — a slot in the
541
- // boilerplate, because a post-construction `self._name = …` forces a
601
+ // literal is the prod literal plus its `_name` and `_loc` slots — slots in
602
+ // the boilerplate, because a post-construction `self._name = …` forces a
542
603
  // hidden-class transition and an out-of-object property store on EVERY node
543
604
  // (measured: the whole of the observe tier's creation overhead). Keep the
544
605
  // two in sync — the dist artifact test pins observe's key set to prod's
545
- // plus `_name`.
546
- const u = {
606
+ // plus the slots.
607
+ const E = {
547
608
  id: inheritId(t, n, context),
548
- i: (n ? CONFIG_TRANSPARENT : 0) | (t?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (!context || t?.lazy ? CONFIG_AUTO_DISPOSE : 0) | (t?.sync ? CONFIG_SYNC : 0) | (t?.ae ? CONFIG_NO_SNAPSHOT : 0) | (t?.Me ?? 0) | (snapshotCaptureActive && ownerInSnapshotScope(context) ? CONFIG_IN_SNAPSHOT_SCOPE : 0),
549
- ye: t?.equals ?? isEqual,
550
- Re: null,
551
- D: context?.D ?? defaultContext,
552
- Be: 0,
553
- ee: e,
554
- Ae: E ? t.loadingValue : undefined,
555
- me: 0,
556
- je: undefined,
557
- we: null,
558
- p: null,
559
- G: null,
560
- pe: 0,
561
- t: null,
562
- Ye: null,
609
+ l: (n ? CONFIG_TRANSPARENT : 0) | (t?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (!context || t?.lazy ? CONFIG_AUTO_DISPOSE : 0) | (t?.sync ? CONFIG_SYNC : 0) | (t?.le ? CONFIG_NO_SNAPSHOT : 0) | (t?.Le ?? 0) | (snapshotCaptureActive && ownerInSnapshotScope(context) ? CONFIG_IN_SNAPSHOT_SCOPE : 0),
610
+ xe: t?.equals ?? isEqual,
611
+ He: null,
612
+ A: context?.A ?? defaultContext,
613
+ ye: 0,
614
+ X: e,
615
+ Ie: o ? t.loadingValue : undefined,
616
+ Fe: 0,
617
+ be: undefined,
618
+ We: null,
619
+ C: null,
620
+ _: null,
621
+ Ne: 0,
622
+ o: null,
623
+ ve: null,
563
624
  _parent: context,
564
- ge: null,
565
- Ke: null,
566
- Ve: null,
625
+ pe: null,
626
+ Ze: null,
627
+ De: null,
567
628
  R: t?.lazy ? REACTIVE_LAZY : REACTIVE_NONE,
568
629
  // A loadingValue node is born committed: commit #0 is already in _value.
569
- S: E ? 0 : STATUS_UNINITIALIZED,
570
- Ie: clock,
571
- Oe: NOT_PENDING,
572
- qe: -1,
573
- De: E,
630
+ m: o ? 0 : STATUS_UNINITIALIZED,
631
+ ie: clock,
632
+ se: NOT_PENDING,
633
+ Me: -1,
634
+ ce: o,
574
635
  // Cold machinery (async slots) lives one hop away in the lazily-allocated extension — the core literal MUST
575
636
  // stay under V8's in-object boundary (§12: past ~39 fields every
576
637
  // allocation spills to a backing store and creation cost ~4x's).
577
- m: null
638
+ T: null
578
639
  };
579
- if (t?.unobserved) ext(u).Je = t.unobserved;
580
- setupComputedNode(u, t);
581
- return u;
640
+ if (t?.unobserved) ext(E).we = t.unobserved;
641
+ setupComputedNode(E, t);
642
+ return E;
582
643
  }
583
644
 
584
645
  /** Lazily allocate a node's cold extension (ONE shape for signals and
585
646
  * computeds — `_x` access stays monomorphic). Installers write through
586
647
  * this; hot paths read `el._x?._field` gated by the _config presence bits.
587
648
  * Never call ext() just to store a field's default. */ function ext(e) {
588
- return e.m ??= {
589
- Te: null,
590
- Ne: null,
649
+ return e.T ??= {
650
+ Se: null,
651
+ ae: null,
591
652
  F: undefined,
592
- de: undefined,
593
- Se: undefined,
594
- Je: undefined,
595
- Le: undefined,
596
- Qe: null,
597
- ve: null,
598
- He: null,
599
- ke: false,
600
- ze: NOT_PENDING,
601
- Xe: -1,
602
- _e: 0,
603
- B: NOT_PENDING,
604
- T: 0
653
+ ue: undefined,
654
+ fe: undefined,
655
+ we: undefined,
656
+ Pe: undefined,
657
+ Ue: null,
658
+ me: null,
659
+ Re: null,
660
+ Ve: false,
661
+ je: NOT_PENDING,
662
+ Be: -1,
663
+ Ee: 0,
664
+ v: NOT_PENDING,
665
+ I: 0,
666
+ de: undefined
605
667
  };
606
668
  }
607
669
 
@@ -622,7 +684,13 @@ function computed(e, t) {
622
684
  // catches it, the boundary's; otherwise the tick joins the hold (#3540:
623
685
  // the reader's position, not where the memo was created). Its catch, if
624
686
  // any, is at its staging.
625
- if (t.S & STATUS_UNINITIALIZED || e.u !== EFFECT_RENDER) joinPassTx(txOf(t), !e.u && e.S & STATUS_UNINITIALIZED || GlobalQueue.fe?.(e));
687
+ if (t.m & STATUS_UNINITIALIZED || e.i !== EFFECT_RENDER) joinPassTx(txOf(t), !e.i && e.m & STATUS_UNINITIALIZED || freshHook?.(e));
688
+ }
689
+
690
+ /** `joinPass` into the hold `t` (a folded guess's: store/optimistic.ts
691
+ * `foldedRead`, D-34) — a reader is never a render effect there. */ function joinPassAt(e, t) {
692
+ e.R |= REACTIVE_JOINED;
693
+ joinPassTx(t, !e.i && e.m & STATUS_UNINITIALIZED || freshHook?.(e));
626
694
  }
627
695
 
628
696
  /** A15's stale reader (shared-hole and reveal corollaries): a render effect
@@ -659,13 +727,15 @@ function computed(e, t) {
659
727
  // read the screen. Lane work with no committed value yet reads a flight
660
728
  // as a mount's memo does: it enters, and the boundary it mounts catches
661
729
  // the pending (#3540).
662
- const n = e.i & CONFIG_VERDICT;
663
- if ((passLane === null || e.S & STATUS_UNINITIALIZED && t.S & STATUS_PENDING) && !n && (e.u !== EFFECT_RENDER || t.i & CONFIG_INPUTS_PUBLISHED)) return false;
730
+ // (Verdict readers and lanes exist only with their engines installed.)
731
+ const n = observeFlightHook && e.l & CONFIG_VERDICT;
732
+ const o = laneStageHook && passLane !== null;
733
+ if ((!o || e.m & STATUS_UNINITIALIZED && t.m & STATUS_PENDING) && !n && (e.i !== EFFECT_RENDER || t.l & CONFIG_INPUTS_PUBLISHED)) return false;
664
734
  const E = txOf(t);
665
735
  // Lane work and verdict readers are never the transaction's pass, whichever
666
736
  // flush runs it: a node T holds re-enters T when it re-runs (`recompute`'s
667
737
  // head), and the pass may then read a guess and become the lane's.
668
- if (E === flushTransaction && passLane === null && !n || bornInto(e, E)) return false;
738
+ if (E === flushTransaction && !o && !n || bornInto(e, E)) return false;
669
739
  staleReader(e, E);
670
740
  return true;
671
741
  }
@@ -675,12 +745,12 @@ function computed(e, t) {
675
745
  * held passes built (CONFIG_HELD_FRAME). Its branch exists only in `t`: it
676
746
  * has no screen to read, so it reads `t`'s values, whichever flush runs it,
677
747
  * and keeps staging (#4010). */ function bornInto(e, t) {
678
- return (e.S & STATUS_UNINITIALIZED || e.i & CONFIG_HELD_FRAME) && e.i & CONFIG_HELD && txOf(e) === t;
748
+ return (e.m & STATUS_UNINITIALIZED || e.l & CONFIG_HELD_FRAME) && e.l & CONFIG_HELD && txOf(e) === t;
679
749
  }
680
750
 
681
751
  /** The computed whose pass a creation under `owner` belongs to (a root's is
682
752
  * its nearest computed ancestor's), or null outside every pass. */ function creatorPass(e) {
683
- return e !== null && e.$e ? e.et : e;
753
+ return e !== null && e.Qe ? e.Ye : e;
684
754
  }
685
755
 
686
756
  /** L2 — park the previous pass's frame for this node's commit: the children
@@ -689,11 +759,11 @@ function computed(e, t) {
689
759
  * the frame that replaces them (`commitPendingNode`) or when the owner does. */ function parkChildren(e) {
690
760
  markDisposal(e);
691
761
  const t = ext(e);
692
- t.ve = e.Re;
693
- t.Qe = e.Ve;
694
- e.Re = null;
695
- e.Ve = null;
696
- e.Be = 0;
762
+ t.me = e.He;
763
+ t.Ue = e.De;
764
+ e.He = null;
765
+ e.De = null;
766
+ e.ye = 0;
697
767
  }
698
768
 
699
769
  /**
@@ -701,54 +771,54 @@ function computed(e, t) {
701
771
  * so V8 sees the full hidden class shape at construction time. Effects always run in lazy
702
772
  * mode (recompute is called explicitly by `effect()`), so we hardcode the lazy bits and skip
703
773
  * the auto-dispose CONFIG bit (effect() previously cleared it post-construction).
704
- */ function createEffectNode(e, t, n, E, u) {
705
- const s = u?.transparent ?? false;
774
+ */ function createEffectNode(e, t, n, o, E) {
775
+ const s = E?.transparent ?? false;
706
776
  // Prod and observe boilerplates — see computed() for why the observe tier
707
777
  // gets its `_name` as a literal slot rather than a write after the fact.
708
778
  // The default label is the node kind (tracked effects relabel their computed
709
779
  // in trackedEffect); the wrappers in signals.ts no longer spread a name into
710
780
  // the options to get it.
711
781
  const i = {
712
- id: inheritId(u, s, context),
713
- i: (s ? CONFIG_TRANSPARENT : 0) | (u?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (u?.sync ? CONFIG_SYNC : 0) | (u?.Me ?? 0) | (snapshotCaptureActive && ownerInSnapshotScope(context) ? CONFIG_IN_SNAPSHOT_SCOPE : 0),
714
- ye: false,
715
- Re: null,
716
- D: context?.D ?? defaultContext,
717
- Be: 0,
718
- ee: e,
719
- Ae: undefined,
720
- me: 0,
721
- je: undefined,
722
- we: null,
723
- p: null,
724
- G: null,
725
- pe: 0,
726
- t: null,
727
- Ye: null,
782
+ id: inheritId(E, s, context),
783
+ l: (s ? CONFIG_TRANSPARENT : 0) | (E?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (E?.sync ? CONFIG_SYNC : 0) | (E?.Le ?? 0) | (snapshotCaptureActive && ownerInSnapshotScope(context) ? CONFIG_IN_SNAPSHOT_SCOPE : 0),
784
+ xe: false,
785
+ He: null,
786
+ A: context?.A ?? defaultContext,
787
+ ye: 0,
788
+ X: e,
789
+ Ie: undefined,
790
+ Fe: 0,
791
+ be: undefined,
792
+ We: null,
793
+ C: null,
794
+ _: null,
795
+ Ne: 0,
796
+ o: null,
797
+ ve: null,
728
798
  _parent: context,
729
- ge: null,
730
- Ke: null,
731
- Ve: null,
799
+ pe: null,
800
+ Ze: null,
801
+ De: null,
732
802
  R: REACTIVE_LAZY,
733
- S: STATUS_UNINITIALIZED,
734
- Ie: clock,
735
- Oe: NOT_PENDING,
736
- qe: -1,
737
- De: false,
738
- Ge: false,
739
- be: undefined,
740
- Et: t,
741
- ut: n,
742
- st: undefined,
743
- u: E,
744
- m: null
803
+ m: STATUS_UNINITIALIZED,
804
+ ie: clock,
805
+ se: NOT_PENDING,
806
+ Me: -1,
807
+ ce: false,
808
+ Ae: false,
809
+ ge: undefined,
810
+ Ke: t,
811
+ qe: n,
812
+ Je: undefined,
813
+ i: o,
814
+ T: null
745
815
  };
746
816
  // Effects dispatch status through the SHARED notifier (statusNotifierOf,
747
817
  // keyed off _type) — storing it per node forced a full NodeExtension
748
818
  // allocation on EVERY effect at creation (an alloc + 19 field stores,
749
819
  // +23% effect creation, caught by the creation benches). Only genuinely
750
820
  // per-node channels (boundaries) live on _x.
751
- if (u?.unobserved) ext(i).Je = u.unobserved;
821
+ if (E?.unobserved) ext(i).we = E.unobserved;
752
822
  setupComputedNode(i, lazyOptions);
753
823
  return i;
754
824
  }
@@ -769,7 +839,7 @@ function setEffectStatusNotify(e) {
769
839
  * 0, and only effect literals carry the field) get the shared notifier.
770
840
  * Presence doubles as the "display consumer" membership test in the status
771
841
  * walks, exactly as the per-node field did when every effect carried one. */ function statusNotifierOf(e) {
772
- return e.u ? effectStatusNotify ?? undefined : undefined;
842
+ return e.i ? effectStatusNotify ?? undefined : undefined;
773
843
  }
774
844
 
775
845
  const lazyOptions = {
@@ -777,16 +847,16 @@ const lazyOptions = {
777
847
  };
778
848
 
779
849
  function setupComputedNode(e, t) {
780
- e.we = e;
781
- const n = context?.$e ? context.et : context;
850
+ e.We = e;
851
+ const n = context?.Qe ? context.Ye : context;
782
852
  if (context) linkChild(context, e);
783
- if (n) e.me = n.me + 1;
784
- GlobalQueue.it?.(e);
853
+ if (n) e.Fe = n.Fe + 1;
854
+ wireExternalSourceHook?.(e);
785
855
  !t?.lazy && recompute(e, true);
786
856
  if (snapshotCaptureActive && !t?.lazy) {
787
- if (!(e.S & STATUS_PENDING) && !(e.i & CONFIG_NO_SNAPSHOT)) {
788
- ext(e).Le = e.Ae === undefined ? NO_SNAPSHOT : e.Ae;
789
- e.i |= CONFIG_HAS_SNAPSHOT;
857
+ if (!(e.m & STATUS_PENDING) && !(e.l & CONFIG_NO_SNAPSHOT)) {
858
+ ext(e).Pe = e.Ie === undefined ? NO_SNAPSHOT : e.Ie;
859
+ e.l |= CONFIG_HAS_SNAPSHOT;
790
860
  snapshotSources.add(e);
791
861
  }
792
862
  }
@@ -794,29 +864,29 @@ function setupComputedNode(e, t) {
794
864
 
795
865
  function signal(e, t) {
796
866
  // Prod and observe boilerplates — see computed(). The observe literal adds
797
- // `_name` and `_owner` (the creating owner, stamped by registerGraph for
867
+ // `_name`, `_loc` and `_owner` (the creating owner, stamped by registerGraph for
798
868
  // createSignal nodes so ownerPath can locate signal subjects; null here,
799
869
  // and staying null on internal signals — one shape either way).
800
870
  const n = {
801
- ye: t?.equals ?? isEqual,
802
- i: (t?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (t?.ae ? CONFIG_NO_SNAPSHOT : 0),
803
- Ae: e,
804
- t: null,
805
- Ye: null,
806
- Ie: clock,
807
- Oe: NOT_PENDING,
871
+ xe: t?.equals ?? isEqual,
872
+ l: (t?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (t?.le ? CONFIG_NO_SNAPSHOT : 0),
873
+ Ie: e,
874
+ o: null,
875
+ ve: null,
876
+ ie: clock,
877
+ se: NOT_PENDING,
808
878
  // Signal-literal diet (§12e): NO _time/_fn/_statusFlags slots. Stores
809
879
  // materialize one signal per touched leaf, so signal bytes are store
810
880
  // bytes. _time is write-only on signals (every read site is computed-
811
881
  // typed error-retry gating); _fn/_statusFlags read falsy-identically as
812
882
  // missing properties on the shared paths (undefined masks to 0).
813
- qe: -1,
814
- m: null
883
+ Me: -1,
884
+ T: null
815
885
  };
816
- if (t?.unobserved) ext(n).Je = t.unobserved;
817
- if (snapshotCaptureActive && !(n.i & CONFIG_NO_SNAPSHOT)) {
818
- ext(n).Le = e === undefined ? NO_SNAPSHOT : e;
819
- n.i |= CONFIG_HAS_SNAPSHOT;
886
+ if (t?.unobserved) ext(n).we = t.unobserved;
887
+ if (snapshotCaptureActive && !(n.l & CONFIG_NO_SNAPSHOT)) {
888
+ ext(n).Pe = e === undefined ? NO_SNAPSHOT : e;
889
+ n.l |= CONFIG_HAS_SNAPSHOT;
820
890
  snapshotSources.add(n);
821
891
  }
822
892
  return n;
@@ -835,20 +905,21 @@ function isEqual(e, t) {
835
905
  * object, no NodeExtension, no post-construction expandos. `ownedWrite` is
836
906
  * baked in: the setter carries the owned-scope guard; node-level writes are
837
907
  * the store's notification machinery. The observe literal adds the label
838
- * slot (the store relabels it `store.<key>` when the engine is installed). */ function slotSignal(e, t, n, E, u) {
908
+ * and location slots (the store relabels `store.<key>` and stamps the
909
+ * store's `loc` when the engine is installed). */ function slotSignal(e, t, n, o, E) {
839
910
  const s = {
840
- ye: t,
841
- i: CONFIG_OWNED_WRITE | CONFIG_SLOT_NODE,
842
- Ae: e,
843
- t: null,
844
- Ye: null,
845
- Ie: clock,
846
- Oe: NOT_PENDING,
847
- qe: -1,
848
- m: null,
849
- lt: n,
850
- ot: E,
851
- acc: u,
911
+ xe: t,
912
+ l: CONFIG_OWNED_WRITE | CONFIG_SLOT_NODE,
913
+ Ie: e,
914
+ o: null,
915
+ ve: null,
916
+ ie: clock,
917
+ se: NOT_PENDING,
918
+ Me: -1,
919
+ T: null,
920
+ O: n,
921
+ ze: o,
922
+ acc: E,
852
923
  px: undefined,
853
924
  pxv: undefined
854
925
  };
@@ -874,6 +945,16 @@ function setVerdict(e) {
874
945
  * Use `untrack` inside a memo or effect when you need to read a signal once
875
946
  * without making the surrounding computation depend on its future changes.
876
947
  *
948
+ * `untrack` stops dependency tracking, not async settlement. Reading an
949
+ * uninitialized async source still suspends the owning computation; it runs
950
+ * again when that source first resolves. Afterward, the untracked read is a
951
+ * snapshot and does not subscribe the computation to later changes.
952
+ *
953
+ * If the first read must return immediately, give the async source a
954
+ * `loadingValue` before reading it with `untrack`. `isPending` and `latest`
955
+ * inspect updates to an existing value; neither supplies a missing initial
956
+ * value.
957
+ *
877
958
  * Pass a `strictReadLabel` string to enable a dev-mode warning: any reactive
878
959
  * read inside `fn` that isn't inside a nested tracking scope will log a
879
960
  * warning naming the label.
@@ -887,13 +968,15 @@ function setVerdict(e) {
887
968
  * log(snapshot);
888
969
  * }
889
970
  * );
971
+ *
972
+ * const color = createMemo<string>(() => fetchColor(), { loadingValue: "gray" });
973
+ * const initialColor = untrack(color); // "gray" while the fetch is unresolved
890
974
  * ```
891
975
  */ function untrack(e, t) {
892
- if (GlobalQueue._t === null && !tracking && true) return e();
893
976
  const n = tracking;
894
977
  tracking = false;
895
978
  try {
896
- if (GlobalQueue._t) return GlobalQueue._t(e);
979
+ if (externalUntrackHook) return externalUntrackHook(e);
897
980
  return e();
898
981
  } finally {
899
982
  tracking = n;
@@ -927,13 +1010,13 @@ function setVerdict(e) {
927
1010
  // pay-for-use contract. Owner-lifecycle nodes are dead: recomputing would
928
1011
  // re-run user code in a torn-down tree (and discard manual writes on
929
1012
  // derived-writable signals), so reads return the last committed value.
930
- if (e.i & CONFIG_AUTO_DISPOSE) {
1013
+ if (e.l & CONFIG_AUTO_DISPOSE) {
931
1014
  const t = e._parent;
932
1015
  if (t !== null) {
933
1016
  // A dormant node was off the chain when its owner died, so the strip
934
1017
  // in disposeChildren missed it: freeze here instead (#3024).
935
1018
  if (t.R & REACTIVE_DISPOSED) {
936
- e.i &= ~CONFIG_AUTO_DISPOSE;
1019
+ e.l &= ~CONFIG_AUTO_DISPOSE;
937
1020
  return;
938
1021
  }
939
1022
  // A zombie never left its chain (the parked frame is drained whole,
@@ -961,7 +1044,7 @@ function setVerdict(e) {
961
1044
  * never the graph — A32).
962
1045
  * False means the reader derives from the staged value.
963
1046
  */ function readerSeesCommitted(e, t) {
964
- return !!(!t || e.Oe === NOT_PENDING || t.i & CONFIG_CHILDREN_FORBIDDEN);
1047
+ return !t || e.se === NOT_PENDING || t.l & CONFIG_CHILDREN_FORBIDDEN;
965
1048
  }
966
1049
 
967
1050
  /** A28 — set when a node is staged (queuePendingNode) OUTSIDE a flush;
@@ -982,21 +1065,21 @@ function markUnflushedStaged() {
982
1065
  * is unflushed. Exempt: promoted writes (A28 (4): a write issued inside a
983
1066
  * recompute is promoted at that recompute's end — boundary and loading
984
1067
  * machinery, signals declared for in-computation writes). */ function unflushedValue(e) {
985
- if (globalQueue.X || e.Oe === NOT_PENDING || e.i & CONFIG_PROMOTED) return NOT_PENDING;
1068
+ if (globalQueue.q || e.se === NOT_PENDING || e.l & CONFIG_PROMOTED) return NOT_PENDING;
986
1069
  // A held node (L2) carries a staged value between flushes too, but it was
987
1070
  // flushed — and parked. Not an unflushed write — unless rewritten since:
988
1071
  // then the flushed staging is what the world sees until the next flush.
989
- if (e.i & CONFIG_HELD) return e.m.Xe === clock ? e.m.ze : NOT_PENDING;
990
- return e.Ae;
1072
+ if (e.l & CONFIG_HELD) return e.T.Be === clock ? e.T.je : NOT_PENDING;
1073
+ return e.Ie;
991
1074
  }
992
1075
 
993
1076
  /** A28: a held node rewritten outside a flush keeps the staging the last
994
1077
  * flush left (`_flushed`) until the flush that carries the rewrite — the
995
1078
  * stash is stamped with the clock, which that flush advances. */ function stashFlushed(e) {
996
- const t = e.m;
997
- if (t.Xe !== clock) {
998
- t.ze = e.Oe;
999
- t.Xe = clock;
1079
+ const t = e.T;
1080
+ if (t.Be !== clock) {
1081
+ t.je = e.se;
1082
+ t.Be = clock;
1000
1083
  unflushedStaged = true;
1001
1084
  }
1002
1085
  }
@@ -1016,7 +1099,7 @@ function resyncUnflushedCompanions() {
1016
1099
  unflushedStaged = false;
1017
1100
  // Length-guarded: the common flush has nothing here and allocates nothing.
1018
1101
  if (promotedWrites.length !== 0) {
1019
- for (const e of promotedWrites) e.i &= ~CONFIG_PROMOTED;
1102
+ for (const e of promotedWrites) e.l &= ~CONFIG_PROMOTED;
1020
1103
  promotedWrites.length = 0;
1021
1104
  }
1022
1105
  }
@@ -1024,7 +1107,7 @@ function resyncUnflushedCompanions() {
1024
1107
  /** A tracked read's pull of a computed: bring it current when the flush has
1025
1108
  * reached its height (or the reader is a fresh-pull waiter), and sit the
1026
1109
  * reader above it. */ function pullComputed(e, t) {
1027
- if (e.me >= dirtyQueue.Ue) {
1110
+ if (e.Fe >= dirtyQueue.Ge) {
1028
1111
  markNode(t);
1029
1112
  markHeap(dirtyQueue);
1030
1113
  updateIfNecessary(e);
@@ -1035,27 +1118,27 @@ function resyncUnflushedCompanions() {
1035
1118
  // never read the PRE-re-ask value as settled. Self-guarded: a clean
1036
1119
  // node no-ops and updateIfNecessary refuses disposed nodes (#2983) —
1037
1120
  // a dead target serves its last value, which is already quiescent.
1038
- else if (t.i & CONFIG_FRESH_READ) updateIfNecessary(e);
1039
- const n = e.me;
1121
+ else if (t.l & CONFIG_FRESH_READ) updateIfNecessary(e);
1122
+ const n = e.Fe;
1040
1123
  // parent check is shallow, might need to be recursive
1041
- if (n >= t.me && e._parent !== t) t.me = n + 1;
1124
+ if (n >= t.Fe && e._parent !== t) t.Fe = n + 1;
1042
1125
  }
1043
1126
 
1044
1127
  function read(e) {
1045
1128
  let t = context;
1046
- if (t?.$e) t = t.et;
1129
+ if (t?.Qe) t = t.Ye;
1047
1130
  const n = e;
1048
1131
  // CARVE 1: `owner` was `el._firewall || el` — a store leaf's status,
1049
1132
  // height and error were read off its projection computed. (Typed loosely
1050
1133
  // as the `||` expression was: a signal's `_statusFlags`/`_height` read as
1051
1134
  // undefined and mask to 0 on every site below.)
1052
- const E = e;
1053
- if (typeof n.ee === "function") prepareComputed(e);
1135
+ const o = e;
1136
+ if (typeof n.X === "function") prepareComputed(e);
1054
1137
  // The verdict windows (`latest`, `isPending`; verdict.ts): one cold path,
1055
1138
  // off this one, present only while a window is open.
1056
1139
  if (verdict !== null) return verdict(e, t);
1057
- if (!n.ee && e.m?.Le === undefined && !snapshotCaptureActive && (!unflushedStaged || e.Oe === NOT_PENDING) && // A28, see readNodeFast
1058
- !(e.i & CONFIG_OVERRIDE) && // lanes: the slow path's one arm
1140
+ if (!n.X && e.T?.Pe === undefined && !snapshotCaptureActive && (!unflushedStaged || e.se === NOT_PENDING) && // A28, see readNodeFast
1141
+ !(e.l & CONFIG_OVERRIDE) && // lanes: the slow path's one arm
1059
1142
  true) {
1060
1143
  if (t) {
1061
1144
  if (tracking) link(e, t);
@@ -1069,38 +1152,49 @@ function read(e) {
1069
1152
  // stays out too (rule 3, `frameRead`). The pass remembers it read the
1070
1153
  // future (REACTIVE_JOINED): a first pass that did is born held (A29),
1071
1154
  // wherever it was created. Lane work sees the screen (`frameRead`).
1072
- if (e.i & CONFIG_HELD && !(t.i & CONFIG_CHILDREN_FORBIDDEN)) {
1073
- if (frameRead(t, e)) return e.Ae;
1155
+ if (e.l & CONFIG_HELD && !(t.l & CONFIG_CHILDREN_FORBIDDEN)) {
1156
+ if (frameRead(t, e)) return e.Ie;
1074
1157
  joinPass(t, e);
1075
1158
  }
1076
1159
  }
1077
1160
  // Committed visibility for untracked and children-forbidden readers.
1078
- if (!t || e.Oe === NOT_PENDING || t.i & CONFIG_CHILDREN_FORBIDDEN) return e.Ae;
1161
+ if (!t || e.se === NOT_PENDING || t.l & CONFIG_CHILDREN_FORBIDDEN) return e.Ie;
1079
1162
  // (A plain signal is never uninitialized — the carve-out is `serve`'s.)
1080
- if (t.i & CONFIG_VERDICT && stagedScreen(t)) return e.Ae;
1163
+ // Lane work over a folded lane (D-34), once the frame has a
1164
+ // transaction, reads the screen too.
1165
+ if ((observeFlightHook && t.l & CONFIG_VERDICT || laneStageHook && passLane?.folded) && stagedScreen(t)) return e.Ie;
1081
1166
  stagedRead(t);
1082
- return e.Oe;
1167
+ return e.se;
1083
1168
  }
1084
1169
  // Rule 3: this read serves the committed value to a render effect outside a
1085
1170
  // parking flush (decided after the pull below — a pull can join).
1086
- let u = false;
1171
+ let E = false;
1087
1172
  if (t) {
1088
1173
  if (tracking) {
1089
1174
  link(e, t);
1090
- if (E.ee) pullComputed(E, t);
1175
+ if (o.X) {
1176
+ pullComputed(o, t);
1177
+ // F-6 (#4050): a memo over a verdict reader's value derives from a
1178
+ // display-ahead read — a verdict reader from this pass's end, as if
1179
+ // it probed inline: it reads held values as the screen and shows the
1180
+ // verdict now. Not an effect: a render effect is a frame reader
1181
+ // already, and a user effect's posture is its own reads'.
1182
+ if (!t.i) t.R |= o.l & CONFIG_VERDICT;
1183
+ }
1091
1184
  }
1092
1185
  // L2, as in the fast block above (tracked or not). A node born into the
1093
1186
  // future (uninitialized) has no committed value: every reader derives
1094
1187
  // from the future there, a render effect included (A29: a stale reader
1095
1188
  // of it cannot fall back to the committed frame and enters instead).
1096
- if (e.i & CONFIG_HELD && !(e.i & CONFIG_OVERRIDE) && !(t.i & CONFIG_CHILDREN_FORBIDDEN)) {
1097
- if (E.S & STATUS_UNINITIALIZED || !frameRead(t, e)) joinPass(t, e); else u = true;
1189
+ if (e.l & CONFIG_HELD && !(e.l & CONFIG_OVERRIDE) && !(t.l & CONFIG_CHILDREN_FORBIDDEN)) {
1190
+ if (o.m & STATUS_UNINITIALIZED || !frameRead(t, e)) joinPass(t, e); else E = true;
1098
1191
  }
1099
1192
  }
1100
1193
  // Lanes: a lane's node (after the pull — the node is current). NOT_PENDING
1101
1194
  // falls through: lane work's read of a pending member throws like any.
1102
- if (e.i & CONFIG_OVERRIDE) {
1103
- const n = GlobalQueue.rt(t, e);
1195
+ // (CONFIG_OVERRIDE is the lane engine's: no engine, no lane's node.)
1196
+ if (laneReadHook && e.l & CONFIG_OVERRIDE) {
1197
+ const n = laneReadHook(t, e);
1104
1198
  if (n !== NOT_PENDING) return n;
1105
1199
  }
1106
1200
  // A stale reader of a held flight (rule 3, A15's reveal corollary) is served
@@ -1117,52 +1211,56 @@ function read(e) {
1117
1211
  // — unless the flight committed beneath inputs already on screen
1118
1212
  // (`observeFlight`), or the reader was born into the flight's transaction
1119
1213
  // (#4010): it has no screen, and waits on the flight with its frame.
1120
- if (E.S & STATUS_PENDING && !u && !(e.i & CONFIG_OVERRIDE) && !(E.S & STATUS_UNINITIALIZED)) {
1214
+ if (o.m & STATUS_PENDING && !E && !(e.l & CONFIG_OVERRIDE) && !(o.m & STATUS_UNINITIALIZED)) {
1121
1215
  // A reader with no committed value yet sees the flight pending: a
1122
1216
  // boundary a lane mounts shows its fallback (A29's boundary exemption).
1123
- if (passLane !== null && !(t?.S & STATUS_UNINITIALIZED)) u = true; else if (t !== null && t.i & CONFIG_VERDICT) u = GlobalQueue.It(t, E);
1217
+ // (A lane, and a verdict reader, exist only with their engines installed.)
1218
+ if (laneStageHook && passLane !== null && !(t?.m & STATUS_UNINITIALIZED)) E = true; else if (observeFlightHook && t !== null && t.l & CONFIG_VERDICT) E = observeFlightHook(t, o);
1124
1219
  }
1125
- if (E.S & STATUS_PENDING && !u) {
1220
+ if (o.m & STATUS_PENDING && !E) {
1126
1221
  // A reader landing on a pending node throws; an untracked read of an
1127
1222
  // UNINITIALIZED node has no committed value to serve and throws too. A
1128
1223
  // children-forbidden reader (createTrackedEffect / onSettled) sees the
1129
1224
  // frame, not the graph (A32): the committed value, and the NotReady only
1130
1225
  // where there is none (uninitialized).
1131
1226
  if (t) {
1132
- if (!(t.i & CONFIG_CHILDREN_FORBIDDEN) || E.S & STATUS_UNINITIALIZED) {
1227
+ if (!(t.l & CONFIG_CHILDREN_FORBIDDEN) || o.m & STATUS_UNINITIALIZED) {
1133
1228
  // An untracked read of a pending node still re-runs its reader when
1134
1229
  // the node settles — unless nobody is reading (`spectating`, #3528)
1135
1230
  // or the reader is the node itself.
1136
1231
  if (!tracking && !spectating && e !== t) link(e, t);
1137
- throw E.m?.F;
1232
+ throw o.T?.F;
1138
1233
  }
1139
- } else if (E.S & STATUS_UNINITIALIZED) {
1140
- throw E.m?.F;
1234
+ } else if (o.m & STATUS_UNINITIALIZED) {
1235
+ throw o.T?.F;
1141
1236
  }
1142
1237
  }
1143
1238
  // An errored derive throws for every late reader instead of silently
1144
1239
  // serving node values (memo parity, #2897 ruling).
1145
- if (E.ee && E.S & STATUS_ERROR) {
1240
+ if (o.X && o.m & STATUS_ERROR) {
1146
1241
  // Only a genuine reactive re-read may retry an errored async source:
1147
1242
  // - tracking: owned/tracked scope only (never events / `untrack` / effect side-effect phase)
1148
1243
  // - owner._time < clock: only on a later cycle than the one the error was found
1149
- if (tracking && E.Ie < clock) {
1150
- recompute(E);
1244
+ if (tracking && o.ie < clock) {
1245
+ recompute(o);
1151
1246
  return read(e);
1152
- } else throw E.m?.F;
1247
+ } else throw o.T?.F;
1153
1248
  }
1154
- if (snapshotCaptureActive && t && t.i & CONFIG_IN_SNAPSHOT_SCOPE) {
1155
- const n = e.m?.Le;
1249
+ if (snapshotCaptureActive && t && t.l & CONFIG_IN_SNAPSHOT_SCOPE) {
1250
+ const n = e.T?.Pe;
1156
1251
  if (n !== undefined) {
1157
- const E = n === NO_SNAPSHOT ? undefined : n;
1158
- const u = e.Oe !== NOT_PENDING ? e.Oe : e.Ae;
1159
- if (u !== E) t.R |= REACTIVE_SNAPSHOT_STALE;
1160
- return E;
1252
+ const o = n === NO_SNAPSHOT ? undefined : n;
1253
+ const E = e.se !== NOT_PENDING ? e.se : e.Ie;
1254
+ if (E !== o) t.R |= REACTIVE_SNAPSHOT_STALE;
1255
+ return o;
1161
1256
  }
1162
1257
  }
1163
- if (u) return e.Ae;
1258
+ if (E) return e.Ie;
1259
+ // D-41: an untracked read reads the screen, and a shown error is on it
1260
+ // until the answer that replaces it commits.
1261
+ if (!t && e.T?.de) throw e.T.de;
1164
1262
  const s = serve(e, t);
1165
- if (!t && typeof n.ee === "function" && e.i & CONFIG_AUTO_DISPOSE && !(E.S & STATUS_PENDING) && !e.t) {
1263
+ if (!t && typeof n.X === "function" && e.l & CONFIG_AUTO_DISPOSE && !(o.m & STATUS_PENDING) && !e.o) {
1166
1264
  // Deferred, not inline (#3078): an inline unobserved() here made untracked
1167
1265
  // reads destructive — dispose on this read, full revival recompute on the
1168
1266
  // next — so consecutive reads could answer differently with no write in
@@ -1189,21 +1287,26 @@ function read(e) {
1189
1287
  // an untracked reader has nothing to serve and holds (A19 exception 1) — a
1190
1288
  // bookkeeping read (`spectate`) likewise, and a children-forbidden reader
1191
1289
  // (A32: the frame, which has nothing here).
1192
- if (e.Oe !== NOT_PENDING && e.S & STATUS_UNINITIALIZED && (!t || spectating || t.i & CONFIG_CHILDREN_FORBIDDEN)) throw new NotReadyError(null);
1290
+ if (e.se !== NOT_PENDING && e.m & STATUS_UNINITIALIZED && (!t || spectating || t.l & CONFIG_CHILDREN_FORBIDDEN)) throw new NotReadyError(null);
1193
1291
  const n = t && unflushedStaged ? unflushedValue(e) : NOT_PENDING;
1194
1292
  if (n !== NOT_PENDING) {
1195
1293
  markLateLinker(t);
1196
1294
  return n;
1197
1295
  }
1198
- if (readerSeesCommitted(e, t)) return e.Ae;
1199
- if (t.i & CONFIG_VERDICT && !(e.S & STATUS_UNINITIALIZED) && stagedScreen(t)) return e.Ae;
1296
+ if (readerSeesCommitted(e, t)) return e.Ie;
1297
+ if (observeFlightHook && t.l & CONFIG_VERDICT && !(e.m & STATUS_UNINITIALIZED) && stagedScreen(t)) return e.Ie;
1200
1298
  stagedRead(t, e);
1201
- return e.Oe;
1299
+ // D-41: the staged answer is an error (`stageError`).
1300
+ if (e.l & CONFIG_STAGED_ERROR) throw e.se;
1301
+ return e.se;
1202
1302
  }
1203
1303
 
1204
1304
  /** A pass read a staging of this flush: it derives from what the flush may
1205
1305
  * yet hold (REACTIVE_STAGED_READ — the seam decides). Lane work too (plan sec. 28, a
1206
- * lane sees the screen plus its own guesses): the staging is the screen if
1306
+ * lane sees the screen plus its own guesses) — a folded lane's only before
1307
+ * the frame has a transaction (after, it reads the screen like a verdict
1308
+ * reader, `stagedScreen` — a list pass never pairs a held length with the
1309
+ * guess's rows, D-34): the staging is the screen if
1207
1310
  * the frame commits — one pass, the common case — and a held write if it
1208
1311
  * parks, which the seam repairs (`stagedReaders`): the pass re-derives on
1209
1312
  * the committed world and its lane's runs wait that round, so the held
@@ -1213,9 +1316,9 @@ function read(e) {
1213
1316
  * a read of a node born staged at all: it has no committed value to
1214
1317
  * re-derive on, and a re-run would read the same staging and re-queue every
1215
1318
  * round (#3969: nor does it make a later lane read a re-derive, `enterLane`). */ function stagedRead(e, t) {
1216
- if (!(t?.S & STATUS_UNINITIALIZED)) {
1319
+ if (!(t?.m & STATUS_UNINITIALIZED)) {
1217
1320
  e.R |= REACTIVE_STAGED_READ;
1218
- if (passLane !== null) stagedReaders.push(e);
1321
+ if (laneSeamsHook && passLane !== null) stagedReaders.push(e);
1219
1322
  }
1220
1323
  }
1221
1324
 
@@ -1236,8 +1339,8 @@ function read(e) {
1236
1339
  /** A28 (4) — written inside a recompute that runs OUTSIDE a flush (a
1237
1340
  * creation-time compute): promoted at that pass's end, visible to the rest of
1238
1341
  * the block. Cold: only contextual writes reach here. */ function notePromotedWrite(e) {
1239
- if (globalQueue.X || e.i & CONFIG_PROMOTED) return;
1240
- e.i |= CONFIG_PROMOTED;
1342
+ if (globalQueue.q || e.l & CONFIG_PROMOTED) return;
1343
+ e.l |= CONFIG_PROMOTED;
1241
1344
  promotedWrites.push(e);
1242
1345
  }
1243
1346
 
@@ -1249,28 +1352,64 @@ function read(e) {
1249
1352
  * REVEALS — the creation-time arm skips pending computeds for the same
1250
1353
  * reason. Firewall leaves belong to a projection whose compute is the tree's
1251
1354
  * own work, captured (or deliberately not) at creation. */ function captureWriteSnapshot(e, t) {
1252
- if (e.i & CONFIG_NO_SNAPSHOT || e.ee !== undefined || e.m?.Le !== undefined) return;
1253
- ext(e).Le = t === undefined ? NO_SNAPSHOT : t;
1254
- e.i |= CONFIG_HAS_SNAPSHOT;
1355
+ if (e.l & CONFIG_NO_SNAPSHOT || e.X !== undefined || e.T?.Pe !== undefined) return;
1356
+ ext(e).Pe = t === undefined ? NO_SNAPSHOT : t;
1357
+ e.l |= CONFIG_HAS_SNAPSHOT;
1255
1358
  snapshotSources.add(e);
1256
1359
  }
1257
1360
 
1361
+ /**
1362
+ * A callback run before every signal or store write lands, while set, with
1363
+ * the written signal or the store proxy whose setter runs. The
1364
+ * server-components client sets it while slot occurrences are left
1365
+ * unmounted after hydration (deferred hydration): a write may be one an
1366
+ * unmounted component would have observed, so the client mounts what is
1367
+ * left before the write applies, and clears the hook. `null` otherwise.
1368
+ */ let writeHook = null;
1369
+
1370
+ /** @internal */ function setWriteHook(e) {
1371
+ writeHook = e;
1372
+ }
1373
+
1374
+ /**
1375
+ * `el`'s comparator verdict (`_equals`), the one guarded call for recompute,
1376
+ * setSignal (user setters and async landings) and the seam's
1377
+ * staged-equals-committed check.
1378
+ * - A comparator that read an unresolved async source has not shown the
1379
+ * values equal (#4111): falsy, a change, whose readers suspend in their own
1380
+ * tracked context.
1381
+ * - Any other throw is an error of `el`'s computation (A3, #2837): routed
1382
+ * through the status path so error boundaries contain it, instead of
1383
+ * unwinding a flush or a setter; answered "same" so nothing commits.
1384
+ * @internal
1385
+ */ function isSame(e, t, n) {
1386
+ if (e.xe === isEqual) return t === n;
1387
+ try {
1388
+ return e.xe && e.xe(t, n);
1389
+ } catch (t) {
1390
+ if (!(t instanceof NotReadyError)) return notifyStatus(e, STATUS_ERROR, t), true;
1391
+ }
1392
+ }
1393
+
1258
1394
  function setSignal(e, t) {
1259
- const n = e.Oe === NOT_PENDING ? e.Ae : e.Oe;
1395
+ if (writeHook !== null) writeHook(e);
1396
+ const n = e.se === NOT_PENDING ? e.Ie : e.se;
1260
1397
  if (typeof t === "function") t = t(n);
1261
1398
  // Lanes: a write landing on a guess is its truth (A18 — an async guess's
1262
1399
  // own landing), judged against the guess; one landing on a lane's
1263
1400
  // derivation (its flight) is the lane's staging (lanes.ts).
1264
- if (e.i & CONFIG_OVERRIDE) return GlobalQueue.Nt(e, t);
1401
+ if (laneWriteHook && e.l & CONFIG_OVERRIDE) return laneWriteHook(e, t);
1265
1402
  // L2 (T4) / A34 (1): a write to a node whose staged state is held is a
1266
1403
  // second proposal for the slot — the same value again or another — and
1267
1404
  // the two cannot finish at different times: the writer's tick joins the
1268
1405
  // hold, before the equality gate.
1269
- if (e.i & CONFIG_HELD) joinFuture(txOf(e));
1406
+ if (e.l & CONFIG_HELD) joinFuture(txOf(e));
1270
1407
  // Uninitialized check first: the first commit has no previous value, so the
1271
1408
  // user comparator must not run against `undefined` (matches recompute).
1272
- const E = !!(e.S & STATUS_UNINITIALIZED) || !e.ye || !e.ye(n, t);
1273
- if (!E) return t;
1409
+ // D-41: a write over a shown error is a change whatever the last good
1410
+ // value was — the error leaves at its commit (`commitPendingNode`).
1411
+ const o = !!(e.m & STATUS_UNINITIALIZED) || !!e.T?.de || !isSame(e, n, t);
1412
+ if (!o) return t;
1274
1413
  // A write during hydration's snapshot capture to a source that has no
1275
1414
  // snapshot — created BEFORE capture began (module-level state: an identity
1276
1415
  // minted from onSettled in the pass, a preference read from storage) —
@@ -1281,21 +1420,21 @@ function setSignal(e, t) {
1281
1420
  // pass reads a value the server never had. Store leaves written here are
1282
1421
  // plain signals and qualify the same way.
1283
1422
  if (snapshotCaptureActive) captureWriteSnapshot(e, n);
1284
- const u = e.Oe !== NOT_PENDING;
1285
- if (!u) queuePendingNode(e);
1423
+ const E = e.se !== NOT_PENDING;
1424
+ if (!E) queuePendingNode(e);
1286
1425
  // A28: a held node rewritten outside a flush keeps its flushed staging
1287
1426
  // for every reader until the flush that carries the rewrite.
1288
- else if (e.i & CONFIG_HELD && !globalQueue.X) stashFlushed(e);
1289
- e.Oe = t;
1427
+ else if (e.l & CONFIG_HELD && !globalQueue.q) stashFlushed(e);
1428
+ e.se = t;
1290
1429
  if (context !== null) notePromotedWrite(e);
1291
1430
  // _time is a computed-only slot (§12e): writing it on a signal would fork
1292
1431
  // the lean shape. Every read site is computed-typed.
1293
- if (e.ee !== undefined) e.Ie = clock;
1432
+ if (e.X !== undefined) e.ie = clock;
1294
1433
  // Staged-rewrite fast path (§12d): a re-write to a node whose subscribers
1295
1434
  // were already walked — and where nothing has recomputed or linked since
1296
1435
  // (epoch) — re-stages the value and stops. The walk is idempotent (subs
1297
1436
  // marked, heap entries flag-guarded, effects queued once).
1298
- if (u && e.qe === notifyEpoch) return t;
1437
+ if (E && e.Me === notifyEpoch) return t;
1299
1438
  insertSubs(e);
1300
1439
  schedule();
1301
1440
  return t;
@@ -1320,18 +1459,31 @@ function setSignal(e, t) {
1320
1459
  // of replacing it. A write made under the hold carries the mark and keeps
1321
1460
  // (1)'s last-write-wins. Only the user setter asks; an async landing
1322
1461
  // writing a held node is the transaction's own work.
1323
- const n = e.i & CONFIG_HELD && !(e.R & REACTIVE_MANUAL_WRITE) && txOf(e) !== flushTransaction;
1462
+ const n = e.l & CONFIG_HELD && !(e.R & REACTIVE_MANUAL_WRITE) && txOf(e) !== flushTransaction;
1324
1463
  // The writer read the committed frame; its updater composes on it.
1325
- if (n && typeof t === "function") t = t(e.Ae);
1326
- const E = setSignal(e, t);
1464
+ if (n && typeof t === "function") {
1465
+ const n = t(e.Ie);
1466
+ t = () => n;
1467
+ }
1468
+ // #4110: the write replaces a failed derivation's outcome. It lands without
1469
+ // re-running `_fn`, and nothing else clears STATUS_ERROR, so without this
1470
+ // every later read keeps throwing the error the derivation left behind.
1471
+ // The error stays the display until the write commits (D-41).
1472
+ if (e.m & STATUS_ERROR) {
1473
+ e.T.de = e.T.F;
1474
+ notifyStatus(e, STATUS_NONE, undefined);
1475
+ }
1476
+ t = setSignal(e, t);
1477
+ // A write replaces an error a pass staged (D-41): it is a value again.
1478
+ e.l &= ~CONFIG_STAGED_ERROR;
1327
1479
  if (n) {
1328
1480
  // The one write that re-runs: the staging it replaced was derived from
1329
1481
  // inputs the writer never saw, so the hold re-derives over the write.
1330
1482
  e.R = e.R & ~REACTIVE_CHECK | REACTIVE_DIRTY;
1331
1483
  insertIntoHeap(e, dirtyQueue);
1332
1484
  schedule();
1333
- } else if (e.Oe !== NOT_PENDING) e.R |= REACTIVE_MANUAL_WRITE;
1334
- return E;
1485
+ } else if (e.se !== NOT_PENDING) e.R |= REACTIVE_MANUAL_WRITE;
1486
+ return t;
1335
1487
  }
1336
1488
 
1337
1489
  /**
@@ -1354,14 +1506,14 @@ function setSignal(e, t) {
1354
1506
  * ```
1355
1507
  */ function runWithOwner(e, t) {
1356
1508
  const n = context;
1357
- const E = tracking;
1509
+ const o = tracking;
1358
1510
  context = e;
1359
1511
  tracking = false;
1360
1512
  try {
1361
1513
  return t();
1362
1514
  } finally {
1363
1515
  context = n;
1364
- tracking = E;
1516
+ tracking = o;
1365
1517
  }
1366
1518
  }
1367
1519
 
@@ -1378,7 +1530,7 @@ function staleValues(e, t = true) {
1378
1530
  * recompute as a quiet re-ask and schedules it; no-ops for non-derived or
1379
1531
  * disposed targets.
1380
1532
  */ function markRefresh(e) {
1381
- if (typeof e.ee === "function" && !(e.R & REACTIVE_DISPOSED)) {
1533
+ if (typeof e.X === "function" && !(e.R & REACTIVE_DISPOSED)) {
1382
1534
  // A manual write never refuses the re-run (A34 rule B): a refresh in the
1383
1535
  // write's own frame re-asks with the write as `prev`, like any source
1384
1536
  // change (#3026 generalized).
@@ -1391,4 +1543,4 @@ function staleValues(e, t = true) {
1391
1543
  }
1392
1544
  }
1393
1545
 
1394
- export { bornInto, captureWriteSnapshot, clearSnapshots, computed, context, createEffectNode, effectStatusNotify, ext, isEqual, joinPass, markLateLinker, markRefresh, markSnapshotScope, markUnflushedStaged, notePromotedWrite, prepareComputed, pullComputed, read, readerSeesCommitted, recompute, releaseSnapshotScope, resyncUnflushedCompanions, runWithOwner, serve, setEffectStatusNotify, setMemo, setSignal, setSnapshotCapture, setVerdict, signal, slotSignal, snapshotCaptureActive, snapshotSources, spectating, stagedRead, stagedScreen, staleValues, stashFlushed, statusNotifierOf, tracking, unflushedStaged, unflushedValue, untrack, verdict };
1546
+ export { bornInto, captureWriteSnapshot, clearSnapshots, computed, context, createEffectNode, effectStatusNotify, ext, isEqual, isSame, joinPass, joinPassAt, markLateLinker, markRefresh, markSnapshotScope, markUnflushedStaged, notePromotedWrite, prepareComputed, pullComputed, read, readerSeesCommitted, recompute, releaseSnapshotScope, resyncUnflushedCompanions, runWithOwner, serve, setEffectStatusNotify, setMemo, setSignal, setSnapshotCapture, setVerdict, setWriteHook, signal, slotSignal, snapshotCaptureActive, snapshotSources, spectating, stagedRead, stagedScreen, staleValues, stashFlushed, statusNotifierOf, tracking, unflushedStaged, unflushedValue, untrack, verdict, writeHook };