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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist/dev-shared.js +168 -88
  2. package/dist/dev.attribution.js +16 -13
  3. package/dist/dev.js +272 -129
  4. package/dist/observe/boundaries.js +88 -67
  5. package/dist/observe/core/action.js +8 -0
  6. package/dist/observe/core/async.js +46 -34
  7. package/dist/observe/core/attribution.js +30 -28
  8. package/dist/observe/core/constants.js +21 -1
  9. package/dist/observe/core/core.js +164 -136
  10. package/dist/observe/core/effect.js +6 -6
  11. package/dist/observe/core/graph.js +3 -3
  12. package/dist/observe/core/heap.js +5 -5
  13. package/dist/observe/core/lanes.js +104 -84
  14. package/dist/observe/core/owner.js +10 -9
  15. package/dist/observe/core/scheduler.js +38 -35
  16. package/dist/observe/core/truth.js +6 -6
  17. package/dist/observe/core/verdict.js +13 -13
  18. package/dist/observe/deferred.js +39 -40
  19. package/dist/observe/index.js +2 -2
  20. package/dist/observe/map.js +22 -22
  21. package/dist/observe/reveal.js +5 -5
  22. package/dist/observe/signals.js +57 -15
  23. package/dist/observe/store/affects.js +1 -1
  24. package/dist/observe/store/hooks.js +3 -0
  25. package/dist/observe/store/optimistic.js +11 -11
  26. package/dist/observe/store/projection.js +34 -21
  27. package/dist/observe/store/reconcile.js +2 -2
  28. package/dist/observe/store/store.js +63 -53
  29. package/dist/observe/store/utils.js +7 -2
  30. package/dist/prod/boundaries.js +153 -132
  31. package/dist/prod/core/action.js +8 -0
  32. package/dist/prod/core/async.js +55 -43
  33. package/dist/prod/core/constants.js +14 -1
  34. package/dist/prod/core/core.js +162 -134
  35. package/dist/prod/core/effect.js +9 -9
  36. package/dist/prod/core/graph.js +3 -3
  37. package/dist/prod/core/heap.js +12 -12
  38. package/dist/prod/core/lanes.js +98 -78
  39. package/dist/prod/core/owner.js +15 -14
  40. package/dist/prod/core/scheduler.js +43 -40
  41. package/dist/prod/core/truth.js +6 -6
  42. package/dist/prod/core/verdict.js +17 -17
  43. package/dist/prod/deferred.js +39 -40
  44. package/dist/prod/index.js +2 -2
  45. package/dist/prod/map.js +14 -14
  46. package/dist/prod/reveal.js +8 -8
  47. package/dist/prod/signals.js +46 -4
  48. package/dist/prod/store/affects.js +1 -1
  49. package/dist/prod/store/hooks.js +3 -0
  50. package/dist/prod/store/optimistic.js +16 -16
  51. package/dist/prod/store/projection.js +22 -9
  52. package/dist/prod/store/reconcile.js +2 -2
  53. package/dist/prod/store/store.js +262 -262
  54. package/dist/prod/store/utils.js +2 -0
  55. package/dist/types/core/action.d.ts +8 -0
  56. package/dist/types/core/constants.d.ts +20 -0
  57. package/dist/types/core/core.d.ts +14 -1
  58. package/dist/types/core/dev.d.ts +1 -1
  59. package/dist/types/core/index.d.ts +1 -1
  60. package/dist/types/core/lanes.d.ts +5 -1
  61. package/dist/types/core/scheduler.d.ts +2 -0
  62. package/dist/types/index.d.ts +3 -1
  63. package/dist/types/signals.d.ts +37 -0
  64. package/dist/types/store/target.d.ts +2 -0
  65. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
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, 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, NewSet, STATUS_NONE } 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, CONFIG_HELD, REACTIVE_MANUAL_WRITE, STATUS_ERROR, REACTIVE_DIRTY, CONFIG_OVERRIDE, NO_SNAPSHOT, CONFIG_HAS_SNAPSHOT, 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, NewSet, STATUS_NONE } from "./constants.js";
4
4
 
5
5
  import { NotReadyError } from "./error.js";
6
6
 
@@ -24,7 +24,7 @@ GlobalQueue._e = e => {
24
24
  if (e.i === EFFECT_TRACKED) {
25
25
  deleteFromHeap(e, dirtyQueue);
26
26
  e.Ae = true;
27
- globalQueue.enqueue(EFFECT_USER, e.M);
27
+ globalQueue.enqueue(EFFECT_USER, e.Z);
28
28
  }
29
29
  // L2: a zombie's fate is the seam's — its owner's commit disposes it, or
30
30
  // the park cancels the pass (the write that dirtied it is held). It runs
@@ -51,7 +51,7 @@ GlobalQueue._e = e => {
51
51
  * hole's render effect). */ function laneFrameMember(e) {
52
52
  let t = e._parent;
53
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;
54
+ return (t.l & (CONFIG_OVERRIDE | CONFIG_GUESS)) === CONFIG_OVERRIDE || t.i && t.T?.Re?.P;
55
55
  }
56
56
 
57
57
  GlobalQueue.Ce = disposeChildren;
@@ -81,8 +81,20 @@ function setSnapshotCapture(e) {
81
81
  if (e && !snapshotSources) snapshotSources = new NewSet;
82
82
  }
83
83
 
84
- function markSnapshotScope(e) {
85
- e.Oe = true;
84
+ /**
85
+ * Marks `owner` a snapshot scope: while capture is on, the readers created
86
+ * under it serve each source's snapshot (the value it had when hydration
87
+ * began) and replay at `releaseSnapshotScope`.
88
+ *
89
+ * With `served` (hydration), `owner` is instead a hydrated computed and
90
+ * `served` its server answer — what the server rendered every reader of the
91
+ * node with — landing after the node was created pending (so the creation
92
+ * arm skipped it). It becomes the node's snapshot when it has none, whether
93
+ * the node committed the answer or a client write had already taken its
94
+ * compute over. A claim made later reads the value its markup shows, and
95
+ * replays the node's own value at its release, as for a written signal.
96
+ */ function markSnapshotScope(e, t) {
97
+ if (arguments.length < 2) e.Oe = true; else if (snapshotCaptureActive && e.T?.De === undefined) takeSnapshot(e, t);
86
98
  }
87
99
 
88
100
  function releaseSnapshotScope(e) {
@@ -92,10 +104,10 @@ function releaseSnapshotScope(e) {
92
104
  }
93
105
 
94
106
  function releaseSubtree(e) {
95
- let t = e.De;
107
+ let t = e.pe;
96
108
  while (t) {
97
109
  if (t.Oe) {
98
- t = t.pe;
110
+ t = t.Ge;
99
111
  continue;
100
112
  }
101
113
  if (t.X) {
@@ -104,12 +116,12 @@ function releaseSubtree(e) {
104
116
  if (e.R & REACTIVE_SNAPSHOT_STALE) {
105
117
  e.R &= ~REACTIVE_SNAPSHOT_STALE;
106
118
  e.R |= REACTIVE_DIRTY;
107
- if (dirtyQueue.Ge > e.Fe) dirtyQueue.Ge = e.Fe;
119
+ if (dirtyQueue.Fe > e.he) dirtyQueue.Fe = e.he;
108
120
  insertIntoHeap(e, dirtyQueue);
109
121
  }
110
122
  }
111
123
  releaseSubtree(t);
112
- t = t.pe;
124
+ t = t.Ge;
113
125
  }
114
126
  }
115
127
 
@@ -121,7 +133,7 @@ function clearSnapshots() {
121
133
  // `!== undefined` — assign, don't `delete`: deleting a field pushes the
122
134
  // object to dictionary mode for every later read of every field.
123
135
  const t = e.T;
124
- if (t != null) t.Pe = undefined;
136
+ if (t != null) t.De = undefined;
125
137
  }
126
138
  snapshotSources = null;
127
139
  }
@@ -156,14 +168,14 @@ function recompute(e, t = false) {
156
168
  // content creates is that mount's too (#4166). Lanes only, like the seat.
157
169
  const s = laneRoot;
158
170
  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);
171
+ setPassLane(!laneStageHook ? null : (e.R & REACTIVE_LANE_DIRTY || (e.l & (CONFIG_OVERRIDE | CONFIG_GUESS)) === CONFIG_OVERRIDE) && e.T?.Re?.P ? e.T.Re : // Loose `!=`: false with no creator lane (undefined == null).
172
+ t && E?._parent.Pe != E && creatorPass(context)?.R & REACTIVE_RECOMPUTING_DEPS ? E : null);
161
173
  // CARVE 2: lane posture resolution (OPTIMISTIC_DIRTY, derived-override
162
174
  // re-derivation, lane adoption through deps) went with the optimistic engine.
163
175
  if (!t) {
164
176
  deleteFromHeap(e, dirtyQueue);
165
177
  if (e.T !== null) {
166
- e.T.Se = null;
178
+ e.T.Ee = null;
167
179
  // Supersede is where an iterator flight dies (#3122): close it now.
168
180
  // Idempotent with the cleanup-channel close.
169
181
  releaseFlightTeardown(e);
@@ -179,6 +191,8 @@ function recompute(e, t = false) {
179
191
  // A29, or mounted by a pass of it still awaiting its commit, #4010) keeps
180
192
  // staging: live writes keep it current, it effects at the swap (ruling
181
193
  // A).
194
+ // A boundary's structure (CONFIG_FRAME) is the frame like a render
195
+ // effect: it publishes mainline outside its transaction's flush (#4283).
182
196
  // A pending flight is the transition's own work (#3884). A probe on an
183
197
  // earlier pass left CONFIG_VERDICT, and a frame read here would serve the
184
198
  // committed screen, settle the flight and drop the hold — a superseding
@@ -192,15 +206,19 @@ function recompute(e, t = false) {
192
206
  // world (`read`), and has left it otherwise.
193
207
  // An answered deferred node's re-pass is a lagging question (D-40):
194
208
  // 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)) {
209
+ // `EFFECT_RENDER << 23` is CONFIG_FRAME (a render effect, a boundary's
210
+ // tree and output), spelled from the effect type as at creation.
211
+ if (t.P || e.l & CONFIG_LAGS) ; else if (!(e.l & (CONFIG_VERDICT | EFFECT_RENDER << 23))) joinPassTx(t, freshHook?.(e, e.m & STATUS_UNINITIALIZED)); else if (t !== flushTransaction && !(e.m & STATUS_UNINITIALIZED || e.l & CONFIG_HELD_FRAME)) {
196
212
  // Published mainline, it is not held: the frame this pass builds is
197
213
  // replaced on the spot (#3404) — this flush's commit retires the
198
214
  // committed frame the held pass had parked (`commitPendingNode`),
199
215
  // after the new frame's first runs, and the held pass's own
200
216
  // children die below (`disposeChildren`). The landing re-derives a
201
217
  // fresh held frame for the reveal (`_reruns`).
202
- e.ue = NOT_PENDING;
203
- if (n === EFFECT_RENDER) e.l &= ~CONFIG_HELD;
218
+ // Not held any more, whichever frame reader it is: its readers read
219
+ // the value this pass publishes.
220
+ e.ie = NOT_PENDING;
221
+ e.l &= ~CONFIG_HELD;
204
222
  }
205
223
  }
206
224
  // The previous pass's frame. If that pass is still awaiting its commit
@@ -217,11 +235,11 @@ function recompute(e, t = false) {
217
235
  deferReleases(o = []);
218
236
  disposeChildren(e);
219
237
  deferReleases(t);
220
- } else if (e.De !== null || e.He !== null) parkChildren(e);
238
+ } else if (e.pe !== null || e.He !== null) parkChildren(e);
221
239
  // An error a pass staged (D-41) is replaced by this pass's answer: a
222
240
  // value, a flight, or an error of its own (#4109, #4145).
223
241
  if (e.l & CONFIG_STAGED_ERROR) {
224
- e.ue = NOT_PENDING;
242
+ e.ie = NOT_PENDING;
225
243
  e.l ^= CONFIG_STAGED_ERROR;
226
244
  }
227
245
  }
@@ -229,16 +247,16 @@ function recompute(e, t = false) {
229
247
  // Capture both error and pending status before the compute clears them.
230
248
  // A conditional can drop its pending source and recover to an unchanged
231
249
  // value, leaving blocked dependents outside that source’s settle walk.
232
- const r = e.m & STATUS_ERROR ? e.T?.F : undefined;
250
+ const r = e.m & STATUS_ERROR ? e.T?.U : undefined;
233
251
  const u = (e.m & STATUS_PENDING) !== 0;
234
- const _ = u ? e.T?.fe : undefined;
252
+ const a = u ? e.T?.fe : undefined;
235
253
  // Pending SOURCE-hood, captured before the compute clears status: a node
236
254
  // whose own flight parked dependents self-registers in _pendingSources
237
255
  // (notifyStatus, isSource). If this recompute supersedes that flight and
238
256
  // settles synchronously, those dependents settle HERE — asyncWrite's
239
257
  // settlePendingSource walk never runs for a landing that was preempted
240
258
  // (#3181).
241
- const a = e.T?.fe?.has(e);
259
+ const _ = e.T?.fe?.has(e);
242
260
  // D-41: this pass's error is staged, not published (`stageError`).
243
261
  let I = false;
244
262
  // A19 exc. 2: a `refresh()` re-asks the question already answered — quiet
@@ -254,11 +272,11 @@ function recompute(e, t = false) {
254
272
  // live writes until the commit that disposes it, so every per-pass wipe
255
273
  // — here, the finally below, updateIfNecessary — carries it (#3543).
256
274
  e.R = REACTIVE_RECOMPUTING_DEPS | e.R & (REACTIVE_ZOMBIE | REACTIVE_REASK);
257
- e.ie = clock;
275
+ e.Se = clock;
258
276
  // The pass's previous value: its staging, else a lane node's lane value
259
277
  // when it has one (lanes.ts), else the committed one.
260
- let T = e.ue !== NOT_PENDING ? e.ue : e.l & CONFIG_OVERRIDE && e.T.v !== NOT_PENDING ? e.T.v : e.Ie;
261
- let S = e.Fe;
278
+ let T = e.ie !== NOT_PENDING ? e.ie : e.l & CONFIG_OVERRIDE && e.T.P !== NOT_PENDING ? e.T.P : e.le;
279
+ let S = e.he;
262
280
  let c = false;
263
281
  // L2: did this pass read the future (REACTIVE_JOINED, set by read) — or,
264
282
  // a lane's mount, a staging of this flush (#3851, #4166)?
@@ -268,19 +286,19 @@ function recompute(e, t = false) {
268
286
  try {
269
287
  if (!false && e.l & CONFIG_SYNC) {
270
288
  T = e.X(T);
271
- if (e.T !== null) e.T.Se = null;
289
+ if (e.T !== null) e.T.Ee = null;
272
290
  e.ce = false;
273
291
  } else {
274
292
  // A projection's body self-registers its flight through handleAsync
275
293
  // (with the commit as setter): its undefined return is not a sync
276
294
  // answer, and the outer handleAsync must not clobber the registration.
277
- const t = e.T?.Se;
295
+ const t = e.T?.Ee;
278
296
  const n = e.X(T);
279
297
  const o = typeof n === "object" && n !== null;
280
- const E = e.T?.Se !== t;
298
+ const E = e.T?.Ee !== t;
281
299
  T = E || !o ? n : handleAsync(e, n);
282
300
  if (!E && !o) {
283
- if (e.T !== null) e.T.Se = null;
301
+ if (e.T !== null) e.T.Ee = null;
284
302
  // A sync (non-object) return is the first real answer; async-shaped
285
303
  // results clear inside handleAsync at their own landing points, and a
286
304
  // self-registered flight clears when its own handleAsync lands.
@@ -311,7 +329,7 @@ function recompute(e, t = false) {
311
329
  notifyStatus(e, n ? STATUS_PENDING : STATUS_ERROR, t);
312
330
  // The replacement source is fully propagated now. If no new flight
313
331
  // re-owned self, retire the superseded flight and its dependent copies.
314
- if (n && a && !e.T?.Se) settlePendingSource(e);
332
+ if (n && _ && !e.T?.Ee) settlePendingSource(e);
315
333
  }
316
334
  // A re-park drops what the earlier pass carried (#3456): a source this
317
335
  // pass no longer reaches — its branch switched, or a fresh flight
@@ -322,7 +340,7 @@ function recompute(e, t = false) {
322
340
  // re-park twin of the unchanged-value recovery sweep below; dependents
323
341
  // with another path keep the source (retryReaches). A staged error
324
342
  // 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);
343
+ if ((n || I) && a) for (const t of a) if (t !== e && !e.T?.fe?.has(t)) settlePendingSource(e, t);
326
344
  }
327
345
  } finally {
328
346
  tracking = R;
@@ -369,7 +387,7 @@ function recompute(e, t = false) {
369
387
  // attribution frame opened at the top is still closed.
370
388
  if (e.R & REACTIVE_DISPOSED) {
371
389
  clearDeps(e);
372
- if (e.T !== null) e.T.Se = null;
390
+ if (e.T !== null) e.T.Ee = null;
373
391
  setPassLane(E);
374
392
  return;
375
393
  }
@@ -381,7 +399,7 @@ function recompute(e, t = false) {
381
399
  let C = !laneStageHook ? null : passLane;
382
400
  // Listed before its staging, a pending pass included (the lane's own
383
401
  // flight is the lane's); false: the pass left the lane (lanes.ts).
384
- const d = !!e.T?.F || I;
402
+ const d = !!e.T?.U || I;
385
403
  if (laneStageHook && C !== null) {
386
404
  if (laneStageHook(e, C, t, d)) setPassLane(C); else C = null;
387
405
  }
@@ -390,9 +408,9 @@ function recompute(e, t = false) {
390
408
  // publishes to — the staged `_pendingValue` when staged; a lane node's
391
409
  // lane value (a node entering the lane this pass has none yet — its
392
410
  // committed value, `laneStage` having voided a frame staging).
393
- const o = e.ue !== NOT_PENDING ? e.ue : e.l & CONFIG_OVERRIDE && e.T.v !== NOT_PENDING ? e.T.v : e.Ie;
411
+ const o = e.ie !== NOT_PENDING ? e.ie : e.l & CONFIG_OVERRIDE && e.T.P !== NOT_PENDING ? e.T.P : e.le;
394
412
  // A throwing comparator is contained inside `isSame` (A3, #2837; #4111).
395
- const E = !n && l || !!e.T?.de || !isSame(e, o, T);
413
+ const E = !n && l || !!e.T?.Ie || !isSame(e, o, T);
396
414
  // Effects use `_equals: false` (no per-effect closure). The side effects that
397
415
  // the equals closure used to perform — flagging the effect dirty and enqueueing
398
416
  // its runner — happen here instead. `!create` matches the previous `initialized`
@@ -401,10 +419,10 @@ function recompute(e, t = false) {
401
419
  if (n && E &&
402
420
  // A stale reader of a lane (REACTIVE_SCREEN_READ) that computed what it
403
421
  // last applied owes no run (lanes.ts).
404
- !(e.R & REACTIVE_SCREEN_READ && !e.Ae && Object.is(e.ge, T)) &&
422
+ !(e.R & REACTIVE_SCREEN_READ && !e.Ae && Object.is(e.ke, T)) &&
405
423
  // A re-staging pass owes no run: the commit replays the effect (#3802).
406
- e.ue === NOT_PENDING) {
407
- e.Ae = !e.T?.F;
424
+ e.ie === NOT_PENDING) {
425
+ e.Ae = !e.T?.U;
408
426
  // Reuse one bound runner per effect — runEffect no-ops on a stale
409
427
  // `_modified`, so re-enqueueing the same function is harmless.
410
428
  // Lane work's run is the lane's (released at its reveal) — a first
@@ -418,7 +436,8 @@ function recompute(e, t = false) {
418
436
  // confirm is a landing too — the lane's end commits it) and notifies
419
437
  // only a correction: an equal truth re-runs nothing (lanes.ts). (As the
420
438
  // lane's own work the lane judged it — `laneStage`.)
421
- if (!t && C === null && e.l & CONFIG_GUESS && laneOutcomeHook(e, T, d)) ; else if (d) ; else if (E) {
439
+ // (The hook first: a build without lanes folds the arm away.)
440
+ if (laneOutcomeHook && !t && C === null && e.l & CONFIG_GUESS && laneOutcomeHook(e, T, d)) ; else if (d) ; else if (E) {
422
441
  // L2: a first pass is born held — staged, committed with the
423
442
  // transaction, its effect's first run the landing's (A29; `effect()`
424
443
  // skips the synchronous first run on a staged value) — when the flush
@@ -442,8 +461,8 @@ function recompute(e, t = false) {
442
461
  // effect's value slot is private: the run the lane holds is what
443
462
  // shows it — unless the effect was born held, whose first run is the
444
463
  // commit's (A29): it re-stages, as below.
445
- if (n && e.ue === NOT_PENDING) e.Ie = T; else if (n || C.ke) e.ue = T; else e.T.v = T;
446
- } else if (t ? !((flushTransaction !== null || passTx !== null) && (A || creatorPass(f)?.R & REACTIVE_JOINED)) : n && e.ue === NOT_PENDING) {
464
+ if (n && e.ie === NOT_PENDING) e.le = T; else if (n || C.ge) e.ie = T; else e.T.P = T;
465
+ } else if (t ? !((flushTransaction !== null || passTx !== null) && (A || creatorPass(f)?.R & REACTIVE_JOINED)) : n && e.ie === NOT_PENDING) {
447
466
  // A first pass publishes directly. So does an effect: its value slot
448
467
  // is private (only its own run reads it), and the staging round-trip
449
468
  // (queuePendingNode + commitPendingNodes) paid per effect on the
@@ -454,9 +473,9 @@ function recompute(e, t = false) {
454
473
  // sources commit) must see the fresh value while PLAIN reads stay
455
474
  // committed until flush (#3009 purity). The pending round-trip is
456
475
  // that separation; it cannot be skipped on any path a pull can reach.
457
- e.Ie = T;
476
+ e.le = T;
458
477
  } else {
459
- e.ue = T;
478
+ e.ie = T;
460
479
  // Born held: in the transaction from birth, so a read of it this
461
480
  // tick is a read of its world (the mount-during-a-hold case), not
462
481
  // only after the seam parks it.
@@ -484,7 +503,7 @@ function recompute(e, t = false) {
484
503
  // Lane work re-staged: the lane's members re-derive as its work.
485
504
  if (C !== null) laneDirty(e, C);
486
505
  }
487
- } else if (e.Fe != S) {
506
+ } else if (e.he != S) {
488
507
  for (let t = e.o; t !== null; t = t.t) insertIntoHeapHeight(t.u, dirtyQueue);
489
508
  }
490
509
  // Silent recovery: errored → unchanged value fires no notification, but
@@ -492,16 +511,16 @@ function recompute(e, t = false) {
492
511
  // in an errored run and may sit on stale commits (#2949). Changed-value
493
512
  // recoveries ride insertSubs above; a comparator throw re-errored the node
494
513
  // (el._x?._error re-set), so this only runs on a genuinely clean recovery.
495
- if (!E && !e.T?.F) {
514
+ if (!E && !e.T?.U) {
496
515
  if (r !== undefined) settleErroredDependents(e, r);
497
516
  // Self-registration (this node's own superseded flight) is the #3181
498
517
  // sweep's business below — retiring it here too would walk twice.
499
- if (_) for (const t of _) if (t !== e) settlePendingSource(e, t);
518
+ if (a) for (const t of a) if (t !== e) settlePendingSource(e, t);
500
519
  }
501
520
  // #3181: a synchronous settle supersedes the old landing callback, so
502
521
  // recompute owns its pending-source sweep. An uninitialized node without
503
522
  // a replacement source still has no truth to reveal and must stay parked.
504
- if (a && !(e.m & (STATUS_PENDING | STATUS_UNINITIALIZED))) settlePendingSource(e);
523
+ if (_ && !(e.m & (STATUS_PENDING | STATUS_UNINITIALIZED))) settlePendingSource(e);
505
524
  }
506
525
  // A first pass that went pending where the born-held arm would have held
507
526
  // its value (it read a held node, or a verdict lane's mount read a staging,
@@ -513,7 +532,7 @@ function recompute(e, t = false) {
513
532
  // re-armed by `on` owns what it collects outright (D-14): not held.
514
533
  if (t && C === null && A && e.m & STATUS_PENDING) {
515
534
  const t = flushTransaction ?? passTx;
516
- if (t && !t.v && freshHook?.(e) !== CAUGHT_REARMED) holdNode(e, t);
535
+ if (t && !t.P && freshHook?.(e) !== CAUGHT_REARMED) holdNode(e, t);
517
536
  }
518
537
  // Dependencies are the committed frame's until it is replaced (A30, #3410):
519
538
  // a pass that staged its value leaves the previous pass's tail linked for
@@ -532,7 +551,7 @@ function recompute(e, t = false) {
532
551
  // kept at a park — one spurious recompute at most). A creation pass and a
533
552
  // tracked effect trim now: their frames are replaceable like a direct
534
553
  // commit, and a tracked effect's spurious run would be user-visible.
535
- if (!e.T?.F && e.ue === NOT_PENDING && !(n && e.Ae)) {
554
+ if (!e.T?.U && e.ie === NOT_PENDING && !(n && e.Ae)) {
536
555
  if (t || n === EFFECT_TRACKED) trimStaleDeps(e); else heldTrim(e);
537
556
  }
538
557
  // A staged value, a parked frame (L2: the commit retires it), or status the
@@ -540,7 +559,7 @@ function recompute(e, t = false) {
540
559
  // node for this flush's commit. A first pass queues only when pending or
541
560
  // born held: otherwise its value published directly. A queued pass's
542
561
  // children are uncommitted (CONFIG_STAGED) until that commit.
543
- if (e.ue !== 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)) {
562
+ if (e.ie !== 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
563
  e.l |= CONFIG_STAGED;
545
564
  // Lane work is the lane's to reveal (its seam), not this flush's commit.
546
565
  if (C === null) queuePendingNode(e);
@@ -576,7 +595,7 @@ function updateIfNecessary(e) {
576
595
  }
577
596
  }
578
597
  }
579
- if (e.R & REACTIVE_DIRTY || e.T?.F && e.ie < clock && !e.T?.Se) {
598
+ if (e.R & REACTIVE_DIRTY || e.T?.U && e.Se < clock && !e.T?.Ee) {
580
599
  recompute(e);
581
600
  }
582
601
  // The guard above refused an already-disposed node; the recompute it just
@@ -606,14 +625,14 @@ function computed(e, t) {
606
625
  // plus the slots.
607
626
  const E = {
608
627
  id: inheritId(t, n, context),
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),
628
+ l: (n ? CONFIG_TRANSPARENT : 0) | (t?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (!context || t?.lazy ? CONFIG_AUTO_DISPOSE : 0) | (t?.sync ? CONFIG_SYNC : 0) | (t?.ue ? CONFIG_NO_SNAPSHOT : 0) | (t?.Le ?? 0) | (snapshotCaptureActive && ownerInSnapshotScope(context) ? CONFIG_IN_SNAPSHOT_SCOPE : 0),
610
629
  xe: t?.equals ?? isEqual,
611
630
  He: null,
612
631
  A: context?.A ?? defaultContext,
613
632
  ye: 0,
614
633
  X: e,
615
- Ie: o ? t.loadingValue : undefined,
616
- Fe: 0,
634
+ le: o ? t.loadingValue : undefined,
635
+ he: 0,
617
636
  be: undefined,
618
637
  We: null,
619
638
  C: null,
@@ -622,14 +641,14 @@ function computed(e, t) {
622
641
  o: null,
623
642
  ve: null,
624
643
  _parent: context,
625
- pe: null,
644
+ Ge: null,
626
645
  Ze: null,
627
- De: null,
646
+ pe: null,
628
647
  R: t?.lazy ? REACTIVE_LAZY : REACTIVE_NONE,
629
648
  // A loadingValue node is born committed: commit #0 is already in _value.
630
649
  m: o ? 0 : STATUS_UNINITIALIZED,
631
- ie: clock,
632
- ue: NOT_PENDING,
650
+ Se: clock,
651
+ ie: NOT_PENDING,
633
652
  Me: -1,
634
653
  ce: o,
635
654
  // Cold machinery (async slots) lives one hop away in the lazily-allocated extension — the core literal MUST
@@ -647,23 +666,23 @@ function computed(e, t) {
647
666
  * this; hot paths read `el._x?._field` gated by the _config presence bits.
648
667
  * Never call ext() just to store a field's default. */ function ext(e) {
649
668
  return e.T ??= {
650
- Se: null,
669
+ Ee: null,
651
670
  ae: null,
652
- F: undefined,
671
+ U: undefined,
653
672
  se: undefined,
654
673
  fe: undefined,
655
674
  we: undefined,
656
- Pe: undefined,
675
+ De: undefined,
657
676
  Ue: null,
658
677
  me: null,
659
678
  Re: null,
660
679
  Ve: false,
661
680
  je: NOT_PENDING,
662
681
  Be: -1,
663
- Ee: 0,
664
- v: NOT_PENDING,
682
+ Te: 0,
683
+ P: NOT_PENDING,
665
684
  I: 0,
666
- de: undefined
685
+ Ie: undefined
667
686
  };
668
687
  }
669
688
 
@@ -727,10 +746,16 @@ function computed(e, t) {
727
746
  // read the screen. Lane work with no committed value yet reads a flight
728
747
  // as a mount's memo does: it enters, and the boundary it mounts catches
729
748
  // the pending (#3540).
749
+ // A boundary's tree and output (CONFIG_FRAME) read as a render effect
750
+ // does: structure, not a derivation of what it shows (#4283). A mount
751
+ // under a hold still enters it: the content memo it reads is born held,
752
+ // with no committed value to serve.
730
753
  // (Verdict readers and lanes exist only with their engines installed.)
731
754
  const n = observeFlightHook && e.l & CONFIG_VERDICT;
732
755
  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;
756
+ if ((!o || e.m & STATUS_UNINITIALIZED && t.m & STATUS_PENDING) && !n && (
757
+ // CONFIG_FRAME, spelled as at the effect's creation.
758
+ !(e.l & EFFECT_RENDER << 23) || t.l & CONFIG_INPUTS_PUBLISHED)) return false;
734
759
  const E = txOf(t);
735
760
  // Lane work and verdict readers are never the transaction's pass, whichever
736
761
  // flush runs it: a node T holds re-enters T when it re-runs (`recompute`'s
@@ -760,9 +785,9 @@ function computed(e, t) {
760
785
  markDisposal(e);
761
786
  const t = ext(e);
762
787
  t.me = e.He;
763
- t.Ue = e.De;
788
+ t.Ue = e.pe;
764
789
  e.He = null;
765
- e.De = null;
790
+ e.pe = null;
766
791
  e.ye = 0;
767
792
  }
768
793
 
@@ -780,14 +805,17 @@ function computed(e, t) {
780
805
  // the options to get it.
781
806
  const i = {
782
807
  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),
808
+ l:
809
+ // CONFIG_FRAME for a render effect (EFFECT_RENDER = 1; a user
810
+ // effect's 1 << 24 is unused).
811
+ o << 23 | (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
812
  xe: false,
785
813
  He: null,
786
814
  A: context?.A ?? defaultContext,
787
815
  ye: 0,
788
816
  X: e,
789
- Ie: undefined,
790
- Fe: 0,
817
+ le: undefined,
818
+ he: 0,
791
819
  be: undefined,
792
820
  We: null,
793
821
  C: null,
@@ -796,17 +824,17 @@ function computed(e, t) {
796
824
  o: null,
797
825
  ve: null,
798
826
  _parent: context,
799
- pe: null,
827
+ Ge: null,
800
828
  Ze: null,
801
- De: null,
829
+ pe: null,
802
830
  R: REACTIVE_LAZY,
803
831
  m: STATUS_UNINITIALIZED,
804
- ie: clock,
805
- ue: NOT_PENDING,
832
+ Se: clock,
833
+ ie: NOT_PENDING,
806
834
  Me: -1,
807
835
  ce: false,
808
836
  Ae: false,
809
- ge: undefined,
837
+ ke: undefined,
810
838
  Ke: t,
811
839
  qe: n,
812
840
  Je: undefined,
@@ -850,15 +878,11 @@ function setupComputedNode(e, t) {
850
878
  e.We = e;
851
879
  const n = context?.Qe ? context.Ye : context;
852
880
  if (context) linkChild(context, e);
853
- if (n) e.Fe = n.Fe + 1;
881
+ if (n) e.he = n.he + 1;
854
882
  wireExternalSourceHook?.(e);
855
883
  !t?.lazy && recompute(e, true);
856
884
  if (snapshotCaptureActive && !t?.lazy) {
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;
860
- snapshotSources.add(e);
861
- }
885
+ if (!(e.m & STATUS_PENDING) && !(e.l & CONFIG_NO_SNAPSHOT)) takeSnapshot(e, e.le);
862
886
  }
863
887
  }
864
888
 
@@ -869,12 +893,12 @@ function signal(e, t) {
869
893
  // and staying null on internal signals — one shape either way).
870
894
  const n = {
871
895
  xe: t?.equals ?? isEqual,
872
- l: (t?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (t?.le ? CONFIG_NO_SNAPSHOT : 0),
873
- Ie: e,
896
+ l: (t?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (t?.ue ? CONFIG_NO_SNAPSHOT : 0),
897
+ le: e,
874
898
  o: null,
875
899
  ve: null,
876
- ie: clock,
877
- ue: NOT_PENDING,
900
+ Se: clock,
901
+ ie: NOT_PENDING,
878
902
  // Signal-literal diet (§12e): NO _time/_fn/_statusFlags slots. Stores
879
903
  // materialize one signal per touched leaf, so signal bytes are store
880
904
  // bytes. _time is write-only on signals (every read site is computed-
@@ -884,11 +908,7 @@ function signal(e, t) {
884
908
  T: null
885
909
  };
886
910
  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;
890
- snapshotSources.add(n);
891
- }
911
+ if (snapshotCaptureActive && !(n.l & CONFIG_NO_SNAPSHOT)) takeSnapshot(n, e);
892
912
  return n;
893
913
  }
894
914
 
@@ -910,11 +930,11 @@ function isEqual(e, t) {
910
930
  const s = {
911
931
  xe: t,
912
932
  l: CONFIG_OWNED_WRITE | CONFIG_SLOT_NODE,
913
- Ie: e,
933
+ le: e,
914
934
  o: null,
915
935
  ve: null,
916
- ie: clock,
917
- ue: NOT_PENDING,
936
+ Se: clock,
937
+ ie: NOT_PENDING,
918
938
  Me: -1,
919
939
  T: null,
920
940
  O: n,
@@ -1044,7 +1064,7 @@ function setVerdict(e) {
1044
1064
  * never the graph — A32).
1045
1065
  * False means the reader derives from the staged value.
1046
1066
  */ function readerSeesCommitted(e, t) {
1047
- return !t || e.ue === NOT_PENDING || t.l & CONFIG_CHILDREN_FORBIDDEN;
1067
+ return !t || e.ie === NOT_PENDING || t.l & CONFIG_CHILDREN_FORBIDDEN;
1048
1068
  }
1049
1069
 
1050
1070
  /** A28 — set when a node is staged (queuePendingNode) OUTSIDE a flush;
@@ -1065,12 +1085,12 @@ function markUnflushedStaged() {
1065
1085
  * is unflushed. Exempt: promoted writes (A28 (4): a write issued inside a
1066
1086
  * recompute is promoted at that recompute's end — boundary and loading
1067
1087
  * machinery, signals declared for in-computation writes). */ function unflushedValue(e) {
1068
- if (globalQueue.q || e.ue === NOT_PENDING || e.l & CONFIG_PROMOTED) return NOT_PENDING;
1088
+ if (globalQueue.q || e.ie === NOT_PENDING || e.l & CONFIG_PROMOTED) return NOT_PENDING;
1069
1089
  // A held node (L2) carries a staged value between flushes too, but it was
1070
1090
  // flushed — and parked. Not an unflushed write — unless rewritten since:
1071
1091
  // then the flushed staging is what the world sees until the next flush.
1072
1092
  if (e.l & CONFIG_HELD) return e.T.Be === clock ? e.T.je : NOT_PENDING;
1073
- return e.Ie;
1093
+ return e.le;
1074
1094
  }
1075
1095
 
1076
1096
  /** A28: a held node rewritten outside a flush keeps the staging the last
@@ -1078,7 +1098,7 @@ function markUnflushedStaged() {
1078
1098
  * stash is stamped with the clock, which that flush advances. */ function stashFlushed(e) {
1079
1099
  const t = e.T;
1080
1100
  if (t.Be !== clock) {
1081
- t.je = e.ue;
1101
+ t.je = e.ie;
1082
1102
  t.Be = clock;
1083
1103
  unflushedStaged = true;
1084
1104
  }
@@ -1107,7 +1127,7 @@ function resyncUnflushedCompanions() {
1107
1127
  /** A tracked read's pull of a computed: bring it current when the flush has
1108
1128
  * reached its height (or the reader is a fresh-pull waiter), and sit the
1109
1129
  * reader above it. */ function pullComputed(e, t) {
1110
- if (e.Fe >= dirtyQueue.Ge) {
1130
+ if (e.he >= dirtyQueue.Fe) {
1111
1131
  markNode(t);
1112
1132
  markHeap(dirtyQueue);
1113
1133
  updateIfNecessary(e);
@@ -1119,9 +1139,9 @@ function resyncUnflushedCompanions() {
1119
1139
  // node no-ops and updateIfNecessary refuses disposed nodes (#2983) —
1120
1140
  // a dead target serves its last value, which is already quiescent.
1121
1141
  else if (t.l & CONFIG_FRESH_READ) updateIfNecessary(e);
1122
- const n = e.Fe;
1142
+ const n = e.he;
1123
1143
  // parent check is shallow, might need to be recursive
1124
- if (n >= t.Fe && e._parent !== t) t.Fe = n + 1;
1144
+ if (n >= t.he && e._parent !== t) t.he = n + 1;
1125
1145
  }
1126
1146
 
1127
1147
  function read(e) {
@@ -1137,7 +1157,7 @@ function read(e) {
1137
1157
  // The verdict windows (`latest`, `isPending`; verdict.ts): one cold path,
1138
1158
  // off this one, present only while a window is open.
1139
1159
  if (verdict !== null) return verdict(e, t);
1140
- if (!n.X && e.T?.Pe === undefined && !snapshotCaptureActive && (!unflushedStaged || e.ue === NOT_PENDING) && // A28, see readNodeFast
1160
+ if (!n.X && e.T?.De === undefined && !snapshotCaptureActive && (!unflushedStaged || e.ie === NOT_PENDING) && // A28, see readNodeFast
1141
1161
  !(e.l & CONFIG_OVERRIDE) && // lanes: the slow path's one arm
1142
1162
  true) {
1143
1163
  if (t) {
@@ -1153,18 +1173,18 @@ function read(e) {
1153
1173
  // future (REACTIVE_JOINED): a first pass that did is born held (A29),
1154
1174
  // wherever it was created. Lane work sees the screen (`frameRead`).
1155
1175
  if (e.l & CONFIG_HELD && !(t.l & CONFIG_CHILDREN_FORBIDDEN)) {
1156
- if (frameRead(t, e)) return e.Ie;
1176
+ if (frameRead(t, e)) return e.le;
1157
1177
  joinPass(t, e);
1158
1178
  }
1159
1179
  }
1160
1180
  // Committed visibility for untracked and children-forbidden readers.
1161
- if (!t || e.ue === NOT_PENDING || t.l & CONFIG_CHILDREN_FORBIDDEN) return e.Ie;
1181
+ if (!t || e.ie === NOT_PENDING || t.l & CONFIG_CHILDREN_FORBIDDEN) return e.le;
1162
1182
  // (A plain signal is never uninitialized — the carve-out is `serve`'s.)
1163
1183
  // Lane work over a folded lane (D-34), once the frame has a
1164
1184
  // transaction, reads the screen too.
1165
- if ((observeFlightHook && t.l & CONFIG_VERDICT || laneStageHook && passLane?.folded) && stagedScreen(t)) return e.Ie;
1185
+ if ((observeFlightHook && t.l & CONFIG_VERDICT || laneStageHook && passLane?.folded) && stagedScreen(t)) return e.le;
1166
1186
  stagedRead(t);
1167
- return e.ue;
1187
+ return e.ie;
1168
1188
  }
1169
1189
  // Rule 3: this read serves the committed value to a render effect outside a
1170
1190
  // parking flush (decided after the pull below — a pull can join).
@@ -1197,6 +1217,19 @@ function read(e) {
1197
1217
  const n = laneReadHook(t, e);
1198
1218
  if (n !== NOT_PENDING) return n;
1199
1219
  }
1220
+ // A reader in a snapshot scope (a hydration claim) is served the value the
1221
+ // server rendered with: a client write's recompute still in flight does
1222
+ // not pull the claim off the markup it adopts — the reader replays at the
1223
+ // scope's release. An errored node throws below as for any reader.
1224
+ if (snapshotCaptureActive && t && t.l & CONFIG_IN_SNAPSHOT_SCOPE) {
1225
+ const n = e.T?.De;
1226
+ if (n !== undefined && !(o.m & STATUS_ERROR)) {
1227
+ const o = n === NO_SNAPSHOT ? undefined : n;
1228
+ const E = e.ie !== NOT_PENDING ? e.ie : e.le;
1229
+ if (E !== o) t.R |= REACTIVE_SNAPSHOT_STALE;
1230
+ return o;
1231
+ }
1232
+ }
1200
1233
  // A stale reader of a held flight (rule 3, A15's reveal corollary) is served
1201
1234
  // the committed value — coherent with the frame, whose inputs are the
1202
1235
  // committed ones too — and does not go pending on it. So is lane work
@@ -1229,10 +1262,10 @@ function read(e) {
1229
1262
  // the node settles — unless nobody is reading (`spectating`, #3528)
1230
1263
  // or the reader is the node itself.
1231
1264
  if (!tracking && !spectating && e !== t) link(e, t);
1232
- throw o.T?.F;
1265
+ throw o.T?.U;
1233
1266
  }
1234
1267
  } else if (o.m & STATUS_UNINITIALIZED) {
1235
- throw o.T?.F;
1268
+ throw o.T?.U;
1236
1269
  }
1237
1270
  }
1238
1271
  // An errored derive throws for every late reader instead of silently
@@ -1241,24 +1274,15 @@ function read(e) {
1241
1274
  // Only a genuine reactive re-read may retry an errored async source:
1242
1275
  // - tracking: owned/tracked scope only (never events / `untrack` / effect side-effect phase)
1243
1276
  // - owner._time < clock: only on a later cycle than the one the error was found
1244
- if (tracking && o.ie < clock) {
1277
+ if (tracking && o.Se < clock) {
1245
1278
  recompute(o);
1246
1279
  return read(e);
1247
- } else throw o.T?.F;
1248
- }
1249
- if (snapshotCaptureActive && t && t.l & CONFIG_IN_SNAPSHOT_SCOPE) {
1250
- const n = e.T?.Pe;
1251
- if (n !== undefined) {
1252
- const o = n === NO_SNAPSHOT ? undefined : n;
1253
- const E = e.ue !== NOT_PENDING ? e.ue : e.Ie;
1254
- if (E !== o) t.R |= REACTIVE_SNAPSHOT_STALE;
1255
- return o;
1256
- }
1280
+ } else throw o.T?.U;
1257
1281
  }
1258
- if (E) return e.Ie;
1282
+ if (E) return e.le;
1259
1283
  // D-41: an untracked read reads the screen, and a shown error is on it
1260
1284
  // until the answer that replaces it commits.
1261
- if (!t && e.T?.de) throw e.T.de;
1285
+ if (!t && e.T?.Ie) throw e.T.Ie;
1262
1286
  const s = serve(e, t);
1263
1287
  if (!t && typeof n.X === "function" && e.l & CONFIG_AUTO_DISPOSE && !(o.m & STATUS_PENDING) && !e.o) {
1264
1288
  // Deferred, not inline (#3078): an inline unobserved() here made untracked
@@ -1287,18 +1311,18 @@ function read(e) {
1287
1311
  // an untracked reader has nothing to serve and holds (A19 exception 1) — a
1288
1312
  // bookkeeping read (`spectate`) likewise, and a children-forbidden reader
1289
1313
  // (A32: the frame, which has nothing here).
1290
- if (e.ue !== NOT_PENDING && e.m & STATUS_UNINITIALIZED && (!t || spectating || t.l & CONFIG_CHILDREN_FORBIDDEN)) throw new NotReadyError(null);
1314
+ if (e.ie !== NOT_PENDING && e.m & STATUS_UNINITIALIZED && (!t || spectating || t.l & CONFIG_CHILDREN_FORBIDDEN)) throw new NotReadyError(null);
1291
1315
  const n = t && unflushedStaged ? unflushedValue(e) : NOT_PENDING;
1292
1316
  if (n !== NOT_PENDING) {
1293
1317
  markLateLinker(t);
1294
1318
  return n;
1295
1319
  }
1296
- if (readerSeesCommitted(e, t)) return e.Ie;
1297
- if (observeFlightHook && t.l & CONFIG_VERDICT && !(e.m & STATUS_UNINITIALIZED) && stagedScreen(t)) return e.Ie;
1320
+ if (readerSeesCommitted(e, t)) return e.le;
1321
+ if (observeFlightHook && t.l & CONFIG_VERDICT && !(e.m & STATUS_UNINITIALIZED) && stagedScreen(t)) return e.le;
1298
1322
  stagedRead(t, e);
1299
1323
  // D-41: the staged answer is an error (`stageError`).
1300
- if (e.l & CONFIG_STAGED_ERROR) throw e.ue;
1301
- return e.ue;
1324
+ if (e.l & CONFIG_STAGED_ERROR) throw e.ie;
1325
+ return e.ie;
1302
1326
  }
1303
1327
 
1304
1328
  /** A pass read a staging of this flush: it derives from what the flush may
@@ -1352,8 +1376,12 @@ function read(e) {
1352
1376
  * REVEALS — the creation-time arm skips pending computeds for the same
1353
1377
  * reason. Firewall leaves belong to a projection whose compute is the tree's
1354
1378
  * own work, captured (or deliberately not) at creation. */ function captureWriteSnapshot(e, t) {
1355
- if (e.l & CONFIG_NO_SNAPSHOT || e.X !== undefined || e.T?.Pe !== undefined) return;
1356
- ext(e).Pe = t === undefined ? NO_SNAPSHOT : t;
1379
+ if (e.l & CONFIG_NO_SNAPSHOT || e.X !== undefined || e.T?.De !== undefined) return;
1380
+ takeSnapshot(e, t);
1381
+ }
1382
+
1383
+ function takeSnapshot(e, t) {
1384
+ ext(e).De = t === undefined ? NO_SNAPSHOT : t;
1357
1385
  e.l |= CONFIG_HAS_SNAPSHOT;
1358
1386
  snapshotSources.add(e);
1359
1387
  }
@@ -1393,7 +1421,7 @@ function read(e) {
1393
1421
 
1394
1422
  function setSignal(e, t) {
1395
1423
  if (writeHook !== null) writeHook(e);
1396
- const n = e.ue === NOT_PENDING ? e.Ie : e.ue;
1424
+ const n = e.ie === NOT_PENDING ? e.le : e.ie;
1397
1425
  if (typeof t === "function") t = t(n);
1398
1426
  // Lanes: a write landing on a guess is its truth (A18 — an async guess's
1399
1427
  // own landing), judged against the guess; one landing on a lane's
@@ -1408,7 +1436,7 @@ function setSignal(e, t) {
1408
1436
  // user comparator must not run against `undefined` (matches recompute).
1409
1437
  // D-41: a write over a shown error is a change whatever the last good
1410
1438
  // value was — the error leaves at its commit (`commitPendingNode`).
1411
- const o = !!(e.m & STATUS_UNINITIALIZED) || !!e.T?.de || !isSame(e, n, t);
1439
+ const o = !!(e.m & STATUS_UNINITIALIZED) || !!e.T?.Ie || !isSame(e, n, t);
1412
1440
  if (!o) return t;
1413
1441
  // A write during hydration's snapshot capture to a source that has no
1414
1442
  // snapshot — created BEFORE capture began (module-level state: an identity
@@ -1420,16 +1448,16 @@ function setSignal(e, t) {
1420
1448
  // pass reads a value the server never had. Store leaves written here are
1421
1449
  // plain signals and qualify the same way.
1422
1450
  if (snapshotCaptureActive) captureWriteSnapshot(e, n);
1423
- const E = e.ue !== NOT_PENDING;
1451
+ const E = e.ie !== NOT_PENDING;
1424
1452
  if (!E) queuePendingNode(e);
1425
1453
  // A28: a held node rewritten outside a flush keeps its flushed staging
1426
1454
  // for every reader until the flush that carries the rewrite.
1427
1455
  else if (e.l & CONFIG_HELD && !globalQueue.q) stashFlushed(e);
1428
- e.ue = t;
1456
+ e.ie = t;
1429
1457
  if (context !== null) notePromotedWrite(e);
1430
1458
  // _time is a computed-only slot (§12e): writing it on a signal would fork
1431
1459
  // the lean shape. Every read site is computed-typed.
1432
- if (e.X !== undefined) e.ie = clock;
1460
+ if (e.X !== undefined) e.Se = clock;
1433
1461
  // Staged-rewrite fast path (§12d): a re-write to a node whose subscribers
1434
1462
  // were already walked — and where nothing has recomputed or linked since
1435
1463
  // (epoch) — re-stages the value and stops. The walk is idempotent (subs
@@ -1462,7 +1490,7 @@ function setSignal(e, t) {
1462
1490
  const n = e.l & CONFIG_HELD && !(e.R & REACTIVE_MANUAL_WRITE) && txOf(e) !== flushTransaction;
1463
1491
  // The writer read the committed frame; its updater composes on it.
1464
1492
  if (n && typeof t === "function") {
1465
- const n = t(e.Ie);
1493
+ const n = t(e.le);
1466
1494
  t = () => n;
1467
1495
  }
1468
1496
  // #4110: the write replaces a failed derivation's outcome. It lands without
@@ -1470,7 +1498,7 @@ function setSignal(e, t) {
1470
1498
  // every later read keeps throwing the error the derivation left behind.
1471
1499
  // The error stays the display until the write commits (D-41).
1472
1500
  if (e.m & STATUS_ERROR) {
1473
- e.T.de = e.T.F;
1501
+ e.T.Ie = e.T.U;
1474
1502
  notifyStatus(e, STATUS_NONE, undefined);
1475
1503
  }
1476
1504
  t = setSignal(e, t);
@@ -1482,7 +1510,7 @@ function setSignal(e, t) {
1482
1510
  e.R = e.R & ~REACTIVE_CHECK | REACTIVE_DIRTY;
1483
1511
  insertIntoHeap(e, dirtyQueue);
1484
1512
  schedule();
1485
- } else if (e.ue !== NOT_PENDING) e.R |= REACTIVE_MANUAL_WRITE;
1513
+ } else if (e.ie !== NOT_PENDING) e.R |= REACTIVE_MANUAL_WRITE;
1486
1514
  return t;
1487
1515
  }
1488
1516