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

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 (74) hide show
  1. package/dist/dev-shared.js +553 -264
  2. package/dist/dev.attribution.js +18 -18
  3. package/dist/dev.js +1030 -439
  4. package/dist/observe/affects.js +12 -2
  5. package/dist/observe/boundaries.js +168 -115
  6. package/dist/observe/core/async.js +57 -37
  7. package/dist/observe/core/attribution.js +6 -6
  8. package/dist/observe/core/constants.js +9 -1
  9. package/dist/observe/core/copies.js +10 -0
  10. package/dist/observe/core/core.js +261 -181
  11. package/dist/observe/core/effect.js +32 -27
  12. package/dist/observe/core/graph.js +7 -7
  13. package/dist/observe/core/heap.js +29 -29
  14. package/dist/observe/core/lanes.js +301 -101
  15. package/dist/observe/core/owner.js +13 -13
  16. package/dist/observe/core/scheduler.js +124 -69
  17. package/dist/observe/core/truth.js +9 -7
  18. package/dist/observe/core/verdict.js +160 -98
  19. package/dist/observe/deferred.js +1 -1
  20. package/dist/observe/index.js +2 -0
  21. package/dist/observe/map.js +120 -116
  22. package/dist/observe/reveal.js +48 -48
  23. package/dist/observe/signals.js +5 -5
  24. package/dist/observe/store/affects.js +2 -2
  25. package/dist/observe/store/optimistic.js +272 -176
  26. package/dist/observe/store/projection.js +21 -10
  27. package/dist/observe/store/reconcile.js +8 -2
  28. package/dist/observe/store/store.js +91 -55
  29. package/dist/observe/store/types.js +11 -1
  30. package/dist/observe/store/utils.js +1 -1
  31. package/dist/prod/affects.js +12 -2
  32. package/dist/prod/boundaries.js +164 -109
  33. package/dist/prod/core/async.js +201 -181
  34. package/dist/prod/core/constants.js +9 -1
  35. package/dist/prod/core/copies.js +10 -0
  36. package/dist/prod/core/core.js +244 -164
  37. package/dist/prod/core/dev.js +108 -3
  38. package/dist/prod/core/effect.js +28 -23
  39. package/dist/prod/core/graph.js +9 -9
  40. package/dist/prod/core/heap.js +16 -16
  41. package/dist/prod/core/identities.js +1 -1
  42. package/dist/prod/core/lanes.js +307 -95
  43. package/dist/prod/core/owner.js +22 -22
  44. package/dist/prod/core/scheduler.js +266 -211
  45. package/dist/prod/core/truth.js +9 -7
  46. package/dist/prod/core/verdict.js +161 -99
  47. package/dist/prod/deferred.js +1 -1
  48. package/dist/prod/index.js +2 -0
  49. package/dist/prod/map.js +78 -74
  50. package/dist/prod/reveal.js +34 -34
  51. package/dist/prod/signals.js +3 -3
  52. package/dist/prod/store/affects.js +15 -15
  53. package/dist/prod/store/optimistic.js +185 -89
  54. package/dist/prod/store/projection.js +49 -38
  55. package/dist/prod/store/reconcile.js +8 -2
  56. package/dist/prod/store/store.js +99 -63
  57. package/dist/prod/store/types.js +11 -1
  58. package/dist/types/affects.d.ts +3 -2
  59. package/dist/types/boundaries.d.ts +14 -2
  60. package/dist/types/core/async.d.ts +2 -1
  61. package/dist/types/core/constants.d.ts +8 -0
  62. package/dist/types/core/copies.d.ts +54 -0
  63. package/dist/types/core/core.d.ts +15 -0
  64. package/dist/types/core/dev.d.ts +1 -1
  65. package/dist/types/core/lanes.d.ts +8 -1
  66. package/dist/types/core/scheduler.d.ts +36 -4
  67. package/dist/types/core/truth.d.ts +3 -1
  68. package/dist/types/core/types.d.ts +6 -0
  69. package/dist/types/index.d.ts +2 -0
  70. package/dist/types/store/hooks.d.ts +15 -1
  71. package/dist/types/store/store.d.ts +2 -1
  72. package/dist/types/store/target.d.ts +5 -0
  73. package/dist/types/store/types.d.ts +7 -0
  74. 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, 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";
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, CONFIG_STAGED_ERROR, REACTIVE_LANE_DIRTY, CONFIG_GUESS, REACTIVE_RECOMPUTING_DEPS, CONFIG_ASYNC, CONFIG_LAGS, EFFECT_RENDER, CONFIG_HELD_FRAME, EFFECT_TRACKED, CONFIG_STAGED, 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
 
@@ -10,7 +10,7 @@ import { insertIntoHeap, deleteFromHeap, insertIntoHeapHeight, enqueueSub, markN
10
10
 
11
11
  import { inheritId, linkChild, disposeChildren, markDisposal } from "./owner.js";
12
12
 
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";
13
+ import { schedule, externalUntrackHook, clock, txOf, flushTransaction, laneWriteHook, joinFuture, queuePendingNode, globalQueue, notifyEpoch, insertSubs, dirtyQueue, observeFlightHook, laneStageHook, passLane, laneReadHook, wireExternalSourceHook, bumpNotifyEpoch, setPassLane, joinPassTx, freshHook, guessing, holdWorkHook, GlobalQueue, laneOutcomeHook, passTx, holdNode, laneDirty, heldTrim, staleReader, laneServedHook, latestOpened, stagedReaders, laneSeamsHook, 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
@@ -161,20 +161,41 @@ function recompute(e, t = false) {
161
161
  // Restored at the end, after this pass's staging and runs have been
162
162
  // routed.
163
163
  // Lanes exist only with the lane engine installed (`laneStageHook`): a
164
- // bundle without it seats every pass on mainline, and folds the seat away.
164
+ // bundle without it seats every pass on mainline (`passLane` is never set)
165
+ // and folds the seat, and its restores, away.
165
166
  const E = passLane;
166
167
  // The mount a first pass belongs to: its creator's lane, or the one its
167
168
  // creator's own mount came from — a render effect a verdict lane's mount's
168
169
  // content creates is that mount's too (#4166). Lanes only, like the seat.
169
170
  const s = laneRoot;
170
171
  const i = laneStageHook && (laneRoot = t && (E || s));
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
+ if (laneStageHook) setPassLane((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
173
  t && E?._parent.Pe != E && creatorPass(context)?.R & REACTIVE_RECOMPUTING_DEPS ? E : null);
173
174
  // CARVE 2: lane posture resolution (OPTIMISTIC_DIRTY, derived-override
174
175
  // re-derivation, lane adoption through deps) went with the optimistic engine.
175
- if (!t) {
176
+ // An error a pass staged, which this pass replaces (`valueChanged`).
177
+ const l = e.l & CONFIG_STAGED_ERROR;
178
+ if (!t) {
176
179
  deleteFromHeap(e, dirtyQueue);
180
+ // A pending flight is the transition's own work (#3884), and so is a
181
+ // held async memo's re-run with no verdict window of its own (D-25,
182
+ // `holdWork`): a pass that takes no verdict role this time. A probe on
183
+ // an earlier pass left CONFIG_VERDICT, and a frame read here would serve
184
+ // the committed screen, settle the flight and drop the hold — a
185
+ // superseding write's verdict would depend on that probe. Cleared for
186
+ // this pass, before the flight it judges by is superseded; a probe in
187
+ // the body re-stamps it after the plain reads. Not an effect: it has no
188
+ // flight of its own (its pending is a source's), and a verdict memo's
189
+ // change may have just made it a verdict reader (`laneDirty`). Only a
190
+ // build with the lane engine (`laneStageHook`; verdict.ts imports it)
191
+ // ever sets CONFIG_VERDICT: without it the line folds away.
192
+ if (laneStageHook && !n && (e.m & STATUS_PENDING || (e.l & (CONFIG_ASYNC | CONFIG_HELD)) === (CONFIG_ASYNC | CONFIG_HELD))) e.l &= ~CONFIG_VERDICT;
177
193
  if (e.T !== null) {
194
+ // The seam's re-derive runs with the parked flight still current; any
195
+ // later pass asks its own question (`_parked`; only the lane engine
196
+ // parks one).
197
+ const t = laneStageHook && e.T.He;
198
+ if (t && t !== e.T.Ee) e.T.He = undefined;
178
199
  e.T.Ee = null;
179
200
  // Supersede is where an iterator flight dies (#3122): close it now.
180
201
  // Idempotent with the cleanup-channel close.
@@ -193,13 +214,7 @@ function recompute(e, t = false) {
193
214
  // A).
194
215
  // A boundary's structure (CONFIG_FRAME) is the frame like a render
195
216
  // effect: it publishes mainline outside its transaction's flush (#4283).
196
- // A pending flight is the transition's own work (#3884). A probe on an
197
- // earlier pass left CONFIG_VERDICT, and a frame read here would serve the
198
- // committed screen, settle the flight and drop the hold — a superseding
199
- // write's verdict would depend on that probe. Cleared for this pass; a
200
- // probe in the body re-stamps it after the plain reads.
201
- if (e.m & STATUS_PENDING) e.l &= ~CONFIG_VERDICT;
202
- if (e.l & CONFIG_HELD) {
217
+ if (e.l & CONFIG_HELD) {
203
218
  const t = txOf(e);
204
219
  // Held by a blocked lane: the frame joins nothing — a lane never holds
205
220
  // a sync write (#3460). The pass is the lane's if it reads the lane's
@@ -216,8 +231,12 @@ function recompute(e, t = false) {
216
231
  // children die below (`disposeChildren`). The landing re-derives a
217
232
  // fresh held frame for the reveal (`_reruns`).
218
233
  // Not held any more, whichever frame reader it is: its readers read
219
- // the value this pass publishes.
220
- e.ie = NOT_PENDING;
234
+ // the value this pass publishes — those that read the staging it
235
+ // supersedes re-derive, even when it publishes the committed value
236
+ // back (no change to notify them by): their held runs carry the
237
+ // superseded frame, and the landing would apply them (#4378).
238
+ if (e.ue !== NOT_PENDING) insertSubs(e);
239
+ e.ue = NOT_PENDING;
221
240
  e.l &= ~CONFIG_HELD;
222
241
  }
223
242
  }
@@ -235,57 +254,59 @@ function recompute(e, t = false) {
235
254
  deferReleases(o = []);
236
255
  disposeChildren(e);
237
256
  deferReleases(t);
238
- } else if (e.pe !== null || e.He !== null) parkChildren(e);
257
+ } else if (e.pe !== null || e.ke !== null) parkChildren(e);
239
258
  // An error a pass staged (D-41) is replaced by this pass's answer: a
240
259
  // value, a flight, or an error of its own (#4109, #4145).
241
260
  if (e.l & CONFIG_STAGED_ERROR) {
242
- e.ie = NOT_PENDING;
261
+ e.ue = NOT_PENDING;
243
262
  e.l ^= CONFIG_STAGED_ERROR;
244
263
  }
245
264
  }
246
- const l = !!(e.m & STATUS_UNINITIALIZED);
265
+ const r = !!(e.m & STATUS_UNINITIALIZED);
247
266
  // Capture both error and pending status before the compute clears them.
248
267
  // A conditional can drop its pending source and recover to an unchanged
249
268
  // value, leaving blocked dependents outside that source’s settle walk.
250
- const r = e.m & STATUS_ERROR ? e.T?.U : undefined;
251
- const u = (e.m & STATUS_PENDING) !== 0;
252
- const a = u ? e.T?.fe : undefined;
269
+ const a = e.m & STATUS_ERROR && e.T?.U;
270
+ const _ = (e.m & STATUS_PENDING) !== 0;
271
+ const u = _ && e.T?.se;
253
272
  // Pending SOURCE-hood, captured before the compute clears status: a node
254
273
  // whose own flight parked dependents self-registers in _pendingSources
255
274
  // (notifyStatus, isSource). If this recompute supersedes that flight and
256
275
  // settles synchronously, those dependents settle HERE — asyncWrite's
257
276
  // settlePendingSource walk never runs for a landing that was preempted
258
277
  // (#3181).
259
- const _ = e.T?.fe?.has(e);
278
+ const I = e.T?.se?.has(e);
260
279
  // D-41: this pass's error is staged, not published (`stageError`).
261
- let I = false;
280
+ let N = false;
262
281
  // A19 exc. 2: a `refresh()` re-asks the question already answered — quiet
263
282
  // for the verdict — unless the question in flight is a new one, which the
264
283
  // re-ask does not launder (a poll during a quiet confirm stays quiet).
265
- const N = (e.R & REACTIVE_REASK) !== 0 && !(e.m & STATUS_PENDING && e.T !== null && !e.T.Ve);
266
- const f = context;
284
+ // Nor a guess's new question whose answer is still held (#4336: an
285
+ // action's refresh after an outside input change has not committed it).
286
+ const f = (e.R & REACTIVE_REASK) !== 0 && !((e.m & STATUS_PENDING || guessing && e.ue !== NOT_PENDING) && e.T !== null && !e.T.Ve);
287
+ const T = context;
267
288
  context = e;
268
289
  e._ = null;
269
- e.Ne++;
290
+ e.de++;
270
291
  // REACTIVE_ZOMBIE is position: it says the node sits on its owner's parked
271
292
  // frame, and the splice/reawaken paths key off it. A zombie reruns for
272
293
  // live writes until the commit that disposes it, so every per-pass wipe
273
294
  // — here, the finally below, updateIfNecessary — carries it (#3543).
274
295
  e.R = REACTIVE_RECOMPUTING_DEPS | e.R & (REACTIVE_ZOMBIE | REACTIVE_REASK);
275
- e.Se = clock;
296
+ e.ie = clock;
276
297
  // The pass's previous value: its staging, else a lane node's lane value
277
298
  // when it has one (lanes.ts), else the committed one.
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;
280
- let c = false;
299
+ let S = e.ue !== NOT_PENDING ? e.ue : e.l & CONFIG_OVERRIDE && e.T.P !== NOT_PENDING ? e.T.P : e.le;
300
+ let c = e.he;
301
+ let A = false;
281
302
  // L2: did this pass read the future (REACTIVE_JOINED, set by read) — or,
282
303
  // a lane's mount, a staging of this flush (#3851, #4166)?
283
- let A = false;
284
- let R = tracking;
304
+ let R = false;
305
+ let C = tracking;
285
306
  tracking = true;
286
307
  try {
287
308
  if (!false && e.l & CONFIG_SYNC) {
288
- T = e.X(T);
309
+ S = e.X(S);
289
310
  if (e.T !== null) e.T.Ee = null;
290
311
  e.ce = false;
291
312
  } else {
@@ -293,12 +314,15 @@ function recompute(e, t = false) {
293
314
  // (with the commit as setter): its undefined return is not a sync
294
315
  // answer, and the outer handleAsync must not clobber the registration.
295
316
  const t = e.T?.Ee;
296
- const n = e.X(T);
317
+ const n = e.X(S);
297
318
  const o = typeof n === "object" && n !== null;
298
319
  const E = e.T?.Ee !== t;
299
- T = E || !o ? n : handleAsync(e, n);
320
+ S = E || !o ? n : handleAsync(e, n);
300
321
  if (!E && !o) {
301
- if (e.T !== null) e.T.Ee = null;
322
+ if (e.T !== null) {
323
+ e.T.Ee = null;
324
+ if (holdWorkHook) e.l &= ~CONFIG_ASYNC;
325
+ }
302
326
  // A sync (non-object) return is the first real answer; async-shaped
303
327
  // results clear inside handleAsync at their own landing points, and a
304
328
  // self-registered flight clears when its own handleAsync lands.
@@ -312,6 +336,10 @@ function recompute(e, t = false) {
312
336
  if (e.m !== 0 || e.T !== null) clearStatus(e, t);
313
337
  } catch (t) {
314
338
  const n = t instanceof NotReadyError;
339
+ // An error answers, and so does a loading window's unready read (D-25,
340
+ // verdict.ts `holdWork`): no flight is its own. A pass left pending
341
+ // keeps the last answer's. (Kept by the verdict engine alone.)
342
+ if (holdWorkHook && (!n || e.ce)) e.l &= ~CONFIG_ASYNC;
315
343
  if (n && e.ce) {
316
344
  // Loading window with an unready sync dependency: register for the
317
345
  // source's settle (the settlePendingSource walk runs off
@@ -324,12 +352,12 @@ function recompute(e, t = false) {
324
352
  } else {
325
353
  // D-41: a pass of a held node, or one that read a staging of this
326
354
  // flush, stages its error (`stageError`).
327
- if (n || !(I = stageError(e, t, true))) {
328
- if (n) ext(e).se = true;
355
+ if (n || !(N = stageError(e, t, true))) {
356
+ if (n) ext(e).fe = true;
329
357
  notifyStatus(e, n ? STATUS_PENDING : STATUS_ERROR, t);
330
358
  // The replacement source is fully propagated now. If no new flight
331
359
  // re-owned self, retire the superseded flight and its dependent copies.
332
- if (n && _ && !e.T?.Ee) settlePendingSource(e);
360
+ if (n && I && !e.T?.Ee) settlePendingSource(e);
333
361
  }
334
362
  // A re-park drops what the earlier pass carried (#3456): a source this
335
363
  // pass no longer reaches — its branch switched, or a fresh flight
@@ -340,25 +368,29 @@ function recompute(e, t = false) {
340
368
  // re-park twin of the unchanged-value recovery sweep below; dependents
341
369
  // with another path keep the source (retryReaches). A staged error
342
370
  // answered what the pass carried: the same.
343
- if ((n || I) && a) for (const t of a) if (t !== e && !e.T?.fe?.has(t)) settlePendingSource(e, t);
371
+ if ((n || N) && u) for (const t of u) if (t !== e && !e.T?.se?.has(t)) settlePendingSource(e, t);
344
372
  }
345
373
  } finally {
346
- tracking = R;
374
+ tracking = C;
347
375
  if (laneStageHook) laneRoot = s;
348
376
  // Consume the missed-wake latch (#3037, set by insertSubs): a dep write
349
377
  // landed beneath this pass on a link it had already validated. The wipe
350
378
  // below must not key off DIRTY/CHECK — the read-time pull protocol
351
379
  // (markNode(c) in read()) marks the running node as part of ordinary
352
380
  // bookkeeping, and those marks are correctly discarded here.
353
- c = (e.R & REACTIVE_MISSED_WAKE) !== 0;
381
+ A = (e.R & REACTIVE_MISSED_WAKE) !== 0;
354
382
  // A mount's staged read joins it — except a nested derivation left
355
383
  // pending: no render effect reaches it yet, so it holds nothing and
356
- // reaches no boundary (Reader, #4203). A reader that does is caught.
357
- A = !!(e.R & (i && (E || n || !(e.m & STATUS_PENDING)) ? REACTIVE_JOINED | REACTIVE_STAGED_READ : REACTIVE_JOINED));
384
+ // reaches no boundary (Reader, #4203), whatever it read — a memo the
385
+ // mount bore held over the staging included, at any depth (#4340). A
386
+ // reader that does is caught.
387
+ R = !!(e.R & (i ? E || n || !(e.m & STATUS_PENDING) ? REACTIVE_JOINED | REACTIVE_STAGED_READ : 0 : REACTIVE_JOINED));
358
388
  // A verdict reader is one for as long as it probes, or reads a memo
359
389
  // that does (`read`): a pass that did neither (REACTIVE_PROBED, the same
360
- // bit) is an ordinary derivation again.
361
- e.l = e.l & ~CONFIG_VERDICT | e.R & REACTIVE_PROBED;
390
+ // bit) is an ordinary derivation again. Its async posture is the
391
+ // verdict engine's to keep (CONFIG_ASYNC, verdict.ts `holdWork`, D-25).
392
+ // (Only the verdict engine probes: without it the line folds away.)
393
+ if (observeFlightHook) e.l = e.l & ~CONFIG_VERDICT | e.R & REACTIVE_PROBED;
362
394
  // REACTIVE_DISPOSED survives too (#3621): the pass may have disposed its
363
395
  // own owner (a memo calling its root's `dispose()`, a cleanup doing so
364
396
  // #3601/#3606), and `disposeChildren` set the flag on this node
@@ -367,12 +399,12 @@ function recompute(e, t = false) {
367
399
  // this pass's verdict for the landing; the next pass's wipe at the top
368
400
  // clears it.
369
401
  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);
370
- context = f;
402
+ context = T;
371
403
  if (o) for (const e of o) releaseIfSettledUnobserved(e);
372
404
  // A19 exc. 2: a pass that went pending on a `refresh()` re-asks the
373
405
  // question already answered — quiet for the verdict; any other pending
374
406
  // pass is a new question. Settled, there is nothing to classify.
375
- if (e.T !== null) e.T.Ve = N && (e.m & STATUS_PENDING) !== 0;
407
+ if (e.T !== null) e.T.Ve = f && (e.m & STATUS_PENDING) !== 0;
376
408
  }
377
409
  // A node that died during its own pass (#3621) is dead at the end of it,
378
410
  // and the pass is void. Its owner's teardown already unlinked its deps,
@@ -388,7 +420,7 @@ function recompute(e, t = false) {
388
420
  if (e.R & REACTIVE_DISPOSED) {
389
421
  clearDeps(e);
390
422
  if (e.T !== null) e.T.Ee = null;
391
- setPassLane(E);
423
+ if (laneStageHook) setPassLane(E);
392
424
  return;
393
425
  }
394
426
  // The lane this pass is work of, if any: its seat (the node's, its
@@ -396,21 +428,25 @@ function recompute(e, t = false) {
396
428
  // seat that read none of the lane's world has left it: its result is the
397
429
  // frame's (a derivation whose branch no longer reaches the guess). A
398
430
  // guess is written, not derived — it never leaves this way.
399
- let C = !laneStageHook ? null : passLane;
431
+ let O = !laneStageHook ? null : passLane;
400
432
  // Listed before its staging, a pending pass included (the lane's own
401
433
  // flight is the lane's); false: the pass left the lane (lanes.ts).
402
- const d = !!e.T?.U || I;
403
- if (laneStageHook && C !== null) {
404
- if (laneStageHook(e, C, t, d)) setPassLane(C); else C = null;
434
+ const d = !!e.T?.U || N;
435
+ if (laneStageHook && O !== null) {
436
+ if (laneStageHook(e, O, t, d)) setPassLane(O); else O = null;
405
437
  }
406
438
  if (!d) {
407
439
  // INV-11 (#3330): the equality gate compares against the slot this run
408
440
  // publishes to — the staged `_pendingValue` when staged; a lane node's
409
441
  // lane value (a node entering the lane this pass has none yet — its
410
442
  // committed value, `laneStage` having voided a frame staging).
411
- const o = e.ie !== NOT_PENDING ? e.ie : e.l & CONFIG_OVERRIDE && e.T.P !== NOT_PENDING ? e.T.P : e.le;
443
+ const o = e.ue !== NOT_PENDING ? e.ue : e.l & CONFIG_OVERRIDE && e.T.P !== NOT_PENDING ? e.T.P : e.le;
412
444
  // A throwing comparator is contained inside `isSame` (A3, #2837; #4111).
413
- const E = !n && l || !!e.T?.Ie || !isSame(e, o, T);
445
+ // A pass replacing an error this node staged is a new answer, even the
446
+ // committed value (D-41: a recovery equal to the last good value is a
447
+ // change): the slot it publishes to held the error, and the readers that
448
+ // derived from it — `latest()` throws it — re-derive (#4403).
449
+ const E = !n && r || !!e.T?.Te || !!l || !isSame(e, o, S);
414
450
  // Effects use `_equals: false` (no per-effect closure). The side effects that
415
451
  // the equals closure used to perform — flagging the effect dirty and enqueueing
416
452
  // its runner — happen here instead. `!create` matches the previous `initialized`
@@ -419,16 +455,16 @@ function recompute(e, t = false) {
419
455
  if (n && E &&
420
456
  // A stale reader of a lane (REACTIVE_SCREEN_READ) that computed what it
421
457
  // last applied owes no run (lanes.ts).
422
- !(e.R & REACTIVE_SCREEN_READ && !e.Ae && Object.is(e.ke, T)) &&
458
+ !(e.R & REACTIVE_SCREEN_READ && !e.Ae && Object.is(e.ge, S)) &&
423
459
  // A re-staging pass owes no run: the commit replays the effect (#3802).
424
- e.ie === NOT_PENDING) {
460
+ e.ue === NOT_PENDING) {
425
461
  e.Ae = !e.T?.U;
426
462
  // Reuse one bound runner per effect — runEffect no-ops on a stale
427
463
  // `_modified`, so re-enqueueing the same function is harmless.
428
464
  // Lane work's run is the lane's (released at its reveal) — a first
429
465
  // pass under a lane too: `effect()` skips the synchronous first run of
430
466
  // a lane's node.
431
- if (!t || C !== null) globalQueue.enqueue(n, e.W ??= GlobalQueue.K.bind(null, e), C);
467
+ if (!t || O !== null) globalQueue.enqueue(n, e.W ??= GlobalQueue.q.bind(null, e), O);
432
468
  }
433
469
  // Lanes. A written guess's own pass from the frame: its source
434
470
  // recomputed it — the truth (A18: "the source is whatever recomputes the
@@ -437,7 +473,7 @@ function recompute(e, t = false) {
437
473
  // only a correction: an equal truth re-runs nothing (lanes.ts). (As the
438
474
  // lane's own work the lane judged it — `laneStage`.)
439
475
  // (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) {
476
+ if (laneOutcomeHook && !t && O === null && e.l & CONFIG_GUESS && laneOutcomeHook(e, S, d)) ; else if (d) ; else if (E) {
441
477
  // L2: a first pass is born held — staged, committed with the
442
478
  // transaction, its effect's first run the landing's (A29; `effect()`
443
479
  // skips the synchronous first run on a staged value) — when the flush
@@ -454,15 +490,15 @@ function recompute(e, t = false) {
454
490
  // pass that runs before anything joins: the pass's input, not a verdict
455
491
  // after it. An effect still carrying an uncommitted staged value
456
492
  // re-stages: the commit applies the latest pass, not the born-held one.
457
- if (C !== null) {
493
+ if (O !== null) {
458
494
  // Lane work: the lane's value — into the slot while the lane has not
459
495
  // revealed (its reveal shows it), as its staging once it has (the
460
496
  // next reveal promotes it; the screen keeps the revealed value). An
461
497
  // effect's value slot is private: the run the lane holds is what
462
498
  // shows it — unless the effect was born held, whose first run is the
463
499
  // commit's (A29): it re-stages, as below.
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) {
500
+ if (n && e.ue === NOT_PENDING) e.le = S; else if (n || O.Ue) e.ue = S; else e.T.P = S;
501
+ } else if (t ? !((flushTransaction !== null || passTx !== null) && (R || creatorPass(T)?.R & REACTIVE_JOINED)) : n && e.ue === NOT_PENDING) {
466
502
  // A first pass publishes directly. So does an effect: its value slot
467
503
  // is private (only its own run reads it), and the staging round-trip
468
504
  // (queuePendingNode + commitPendingNodes) paid per effect on the
@@ -473,9 +509,13 @@ function recompute(e, t = false) {
473
509
  // sources commit) must see the fresh value while PLAIN reads stay
474
510
  // committed until flush (#3009 purity). The pending round-trip is
475
511
  // that separation; it cannot be skipped on any path a pull can reach.
476
- e.le = T;
512
+ e.le = S;
477
513
  } else {
478
- e.ie = T;
514
+ e.ue = S;
515
+ // D-39: a staged recovery keeps the error it replaces the display
516
+ // until it commits (`commitPendingNode`), as a write over one does
517
+ // (`setMemo`).
518
+ if (a) e.T.Te = a;
479
519
  // Born held: in the transaction from birth, so a read of it this
480
520
  // tick is a read of its world (the mount-during-a-hold case), not
481
521
  // only after the seam parks it.
@@ -501,9 +541,9 @@ function recompute(e, t = false) {
501
541
  if (e.o !== null) {
502
542
  insertSubs(e);
503
543
  // Lane work re-staged: the lane's members re-derive as its work.
504
- if (C !== null) laneDirty(e, C);
544
+ if (O !== null) laneDirty(e, O);
505
545
  }
506
- } else if (e.he != S) {
546
+ } else if (e.he != c) {
507
547
  for (let t = e.o; t !== null; t = t.t) insertIntoHeapHeight(t.u, dirtyQueue);
508
548
  }
509
549
  // Silent recovery: errored → unchanged value fires no notification, but
@@ -512,15 +552,15 @@ function recompute(e, t = false) {
512
552
  // recoveries ride insertSubs above; a comparator throw re-errored the node
513
553
  // (el._x?._error re-set), so this only runs on a genuinely clean recovery.
514
554
  if (!E && !e.T?.U) {
515
- if (r !== undefined) settleErroredDependents(e, r);
555
+ if (a) settleErroredDependents(e, a);
516
556
  // Self-registration (this node's own superseded flight) is the #3181
517
557
  // sweep's business below — retiring it here too would walk twice.
518
- if (a) for (const t of a) if (t !== e) settlePendingSource(e, t);
558
+ if (u) for (const t of u) if (t !== e) settlePendingSource(e, t);
519
559
  }
520
560
  // #3181: a synchronous settle supersedes the old landing callback, so
521
561
  // recompute owns its pending-source sweep. An uninitialized node without
522
562
  // a replacement source still has no truth to reveal and must stay parked.
523
- if (_ && !(e.m & (STATUS_PENDING | STATUS_UNINITIALIZED))) settlePendingSource(e);
563
+ if (I && !(e.m & (STATUS_PENDING | STATUS_UNINITIALIZED))) settlePendingSource(e);
524
564
  }
525
565
  // A first pass that went pending where the born-held arm would have held
526
566
  // its value (it read a held node, or a verdict lane's mount read a staging,
@@ -530,7 +570,7 @@ function recompute(e, t = false) {
530
570
  // hold's commit (D-12) — but the hold does not wait for it: its only
531
571
  // readers are behind the fallback (`_hidden`; F-4, #3540). A boundary
532
572
  // re-armed by `on` owns what it collects outright (D-14): not held.
533
- if (t && C === null && A && e.m & STATUS_PENDING) {
573
+ if (t && O === null && R && e.m & STATUS_PENDING) {
534
574
  const t = flushTransaction ?? passTx;
535
575
  if (t && !t.P && freshHook?.(e) !== CAUGHT_REARMED) holdNode(e, t);
536
576
  }
@@ -551,7 +591,7 @@ function recompute(e, t = false) {
551
591
  // kept at a park — one spurious recompute at most). A creation pass and a
552
592
  // tracked effect trim now: their frames are replaceable like a direct
553
593
  // commit, and a tracked effect's spurious run would be user-visible.
554
- if (!e.T?.U && e.ie === NOT_PENDING && !(n && e.Ae)) {
594
+ if (!e.T?.U && e.ue === NOT_PENDING && !(n && e.Ae)) {
555
595
  if (t || n === EFFECT_TRACKED) trimStaleDeps(e); else heldTrim(e);
556
596
  }
557
597
  // A staged value, a parked frame (L2: the commit retires it), or status the
@@ -559,18 +599,18 @@ function recompute(e, t = false) {
559
599
  // node for this flush's commit. A first pass queues only when pending or
560
600
  // born held: otherwise its value published directly. A queued pass's
561
601
  // children are uncommitted (CONFIG_STAGED) until that commit.
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)) {
602
+ if (e.ue !== NOT_PENDING || e.T !== null && (e.T.me !== null || e.T.Le !== null) || (e.m & (STATUS_PENDING | STATUS_UNINITIALIZED)) !== 0 && (!t || (e.m & STATUS_PENDING) !== 0)) {
563
603
  e.l |= CONFIG_STAGED;
564
604
  // Lane work is the lane's to reveal (its seam), not this flush's commit.
565
- if (C === null) queuePendingNode(e);
605
+ if (O === null) queuePendingNode(e);
566
606
  }
567
- setPassLane(E);
607
+ if (laneStageHook) setPassLane(E);
568
608
  // Missed-wake reschedule (see the finally above): values this pass read
569
609
  // before the nested commit are stale, so run again now that the heap will
570
610
  // accept the node. Equality gates stop same-value landings from cascading,
571
611
  // and a re-run only latches again if another nested commit changes a dep
572
612
  // beneath it — convergent unless deps genuinely keep changing.
573
- if (c) {
613
+ if (A) {
574
614
  enqueueSub(e);
575
615
  schedule();
576
616
  }
@@ -595,7 +635,7 @@ function updateIfNecessary(e) {
595
635
  }
596
636
  }
597
637
  }
598
- if (e.R & REACTIVE_DIRTY || e.T?.U && e.Se < clock && !e.T?.Ee) {
638
+ if (e.R & REACTIVE_DIRTY || e.T?.U && e.ie < clock && !e.T?.Ee) {
599
639
  recompute(e);
600
640
  }
601
641
  // The guard above refused an already-disposed node; the recompute it just
@@ -625,30 +665,30 @@ function computed(e, t) {
625
665
  // plus the slots.
626
666
  const E = {
627
667
  id: inheritId(t, n, context),
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),
629
- xe: t?.equals ?? isEqual,
630
- He: null,
668
+ l: (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?.xe ?? 0) | (snapshotCaptureActive && ownerInSnapshotScope(context) ? CONFIG_IN_SNAPSHOT_SCOPE : 0),
669
+ ye: t?.equals ?? isEqual,
670
+ ke: null,
631
671
  A: context?.A ?? defaultContext,
632
- ye: 0,
672
+ be: 0,
633
673
  X: e,
634
674
  le: o ? t.loadingValue : undefined,
635
675
  he: 0,
636
- be: undefined,
676
+ ve: undefined,
637
677
  We: null,
638
678
  C: null,
639
679
  _: null,
640
- Ne: 0,
680
+ de: 0,
641
681
  o: null,
642
- ve: null,
682
+ Ze: null,
643
683
  _parent: context,
644
684
  Ge: null,
645
- Ze: null,
685
+ we: null,
646
686
  pe: null,
647
687
  R: t?.lazy ? REACTIVE_LAZY : REACTIVE_NONE,
648
688
  // A loadingValue node is born committed: commit #0 is already in _value.
649
689
  m: o ? 0 : STATUS_UNINITIALIZED,
650
- Se: clock,
651
- ie: NOT_PENDING,
690
+ ie: clock,
691
+ ue: NOT_PENDING,
652
692
  Me: -1,
653
693
  ce: o,
654
694
  // Cold machinery (async slots) lives one hop away in the lazily-allocated extension — the core literal MUST
@@ -656,7 +696,7 @@ function computed(e, t) {
656
696
  // allocation spills to a backing store and creation cost ~4x's).
657
697
  T: null
658
698
  };
659
- if (t?.unobserved) ext(E).we = t.unobserved;
699
+ if (t?.unobserved) ext(E).Ye = t.unobserved;
660
700
  setupComputedNode(E, t);
661
701
  return E;
662
702
  }
@@ -667,22 +707,22 @@ function computed(e, t) {
667
707
  * Never call ext() just to store a field's default. */ function ext(e) {
668
708
  return e.T ??= {
669
709
  Ee: null,
670
- ae: null,
710
+ Se: null,
671
711
  U: undefined,
672
- se: undefined,
673
712
  fe: undefined,
674
- we: undefined,
713
+ se: undefined,
714
+ Ye: undefined,
675
715
  De: undefined,
676
- Ue: null,
677
716
  me: null,
717
+ Le: null,
678
718
  Re: null,
679
719
  Ve: false,
680
720
  je: NOT_PENDING,
681
721
  Be: -1,
682
- Te: 0,
722
+ Ie: 0,
683
723
  P: NOT_PENDING,
684
724
  I: 0,
685
- Ie: undefined
725
+ Te: null
686
726
  };
687
727
  }
688
728
 
@@ -762,6 +802,9 @@ function computed(e, t) {
762
802
  // head), and the pass may then read a guess and become the lane's.
763
803
  if (E === flushTransaction && !o && !n || bornInto(e, E)) return false;
764
804
  staleReader(e, E);
805
+ // Lane work or a verdict reader no longer waits on `el`'s flight (lanes.ts
806
+ // `laneServed`, A15).
807
+ if (o || n) laneServedHook(e, t);
765
808
  return true;
766
809
  }
767
810
 
@@ -775,7 +818,14 @@ function computed(e, t) {
775
818
 
776
819
  /** The computed whose pass a creation under `owner` belongs to (a root's is
777
820
  * its nearest computed ancestor's), or null outside every pass. */ function creatorPass(e) {
778
- return e !== null && e.Qe ? e.Ye : e;
821
+ return e !== null && e.Qe ? e.Ke : e;
822
+ }
823
+
824
+ /** What `born` and the passes still running around `p` read — its
825
+ * creator's, theirs — of the future or a staging (REACTIVE_JOINED |
826
+ * REACTIVE_STAGED_READ): a pass created by one that did has no screen; its
827
+ * branch exists only in that world (#4341). */ function creatorReads(e, t) {
828
+ return (e = creatorPass(e._parent))?.R & REACTIVE_RECOMPUTING_DEPS ? creatorReads(e, t | e.R) : t & (REACTIVE_JOINED | REACTIVE_STAGED_READ);
779
829
  }
780
830
 
781
831
  /** L2 — park the previous pass's frame for this node's commit: the children
@@ -784,11 +834,11 @@ function computed(e, t) {
784
834
  * the frame that replaces them (`commitPendingNode`) or when the owner does. */ function parkChildren(e) {
785
835
  markDisposal(e);
786
836
  const t = ext(e);
787
- t.me = e.He;
788
- t.Ue = e.pe;
789
- e.He = null;
837
+ t.Le = e.ke;
838
+ t.me = e.pe;
839
+ e.ke = null;
790
840
  e.pe = null;
791
- e.ye = 0;
841
+ e.be = 0;
792
842
  }
793
843
 
794
844
  /**
@@ -808,36 +858,36 @@ function computed(e, t) {
808
858
  l:
809
859
  // CONFIG_FRAME for a render effect (EFFECT_RENDER = 1; a user
810
860
  // 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),
812
- xe: false,
813
- He: null,
861
+ o << 23 | (s ? CONFIG_TRANSPARENT : 0) | (E?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (E?.sync ? CONFIG_SYNC : 0) | (E?.xe ?? 0) | (snapshotCaptureActive && ownerInSnapshotScope(context) ? CONFIG_IN_SNAPSHOT_SCOPE : 0),
862
+ ye: false,
863
+ ke: null,
814
864
  A: context?.A ?? defaultContext,
815
- ye: 0,
865
+ be: 0,
816
866
  X: e,
817
867
  le: undefined,
818
868
  he: 0,
819
- be: undefined,
869
+ ve: undefined,
820
870
  We: null,
821
871
  C: null,
822
872
  _: null,
823
- Ne: 0,
873
+ de: 0,
824
874
  o: null,
825
- ve: null,
875
+ Ze: null,
826
876
  _parent: context,
827
877
  Ge: null,
828
- Ze: null,
878
+ we: null,
829
879
  pe: null,
830
880
  R: REACTIVE_LAZY,
831
881
  m: STATUS_UNINITIALIZED,
832
- Se: clock,
833
- ie: NOT_PENDING,
882
+ ie: clock,
883
+ ue: NOT_PENDING,
834
884
  Me: -1,
835
885
  ce: false,
836
886
  Ae: false,
837
- ke: undefined,
838
- Ke: t,
839
- qe: n,
840
- Je: undefined,
887
+ ge: undefined,
888
+ qe: t,
889
+ Je: n,
890
+ ze: undefined,
841
891
  i: o,
842
892
  T: null
843
893
  };
@@ -846,7 +896,7 @@ function computed(e, t) {
846
896
  // allocation on EVERY effect at creation (an alloc + 19 field stores,
847
897
  // +23% effect creation, caught by the creation benches). Only genuinely
848
898
  // per-node channels (boundaries) live on _x.
849
- if (E?.unobserved) ext(i).we = E.unobserved;
899
+ if (E?.unobserved) ext(i).Ye = E.unobserved;
850
900
  setupComputedNode(i, lazyOptions);
851
901
  return i;
852
902
  }
@@ -876,7 +926,7 @@ const lazyOptions = {
876
926
 
877
927
  function setupComputedNode(e, t) {
878
928
  e.We = e;
879
- const n = context?.Qe ? context.Ye : context;
929
+ const n = context?.Qe ? context.Ke : context;
880
930
  if (context) linkChild(context, e);
881
931
  if (n) e.he = n.he + 1;
882
932
  wireExternalSourceHook?.(e);
@@ -892,13 +942,13 @@ function signal(e, t) {
892
942
  // createSignal nodes so ownerPath can locate signal subjects; null here,
893
943
  // and staying null on internal signals — one shape either way).
894
944
  const n = {
895
- xe: t?.equals ?? isEqual,
896
- l: (t?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (t?.ue ? CONFIG_NO_SNAPSHOT : 0),
945
+ ye: t?.equals ?? isEqual,
946
+ l: (t?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (t?.ae ? CONFIG_NO_SNAPSHOT : 0),
897
947
  le: e,
898
948
  o: null,
899
- ve: null,
900
- Se: clock,
901
- ie: NOT_PENDING,
949
+ Ze: null,
950
+ ie: clock,
951
+ ue: NOT_PENDING,
902
952
  // Signal-literal diet (§12e): NO _time/_fn/_statusFlags slots. Stores
903
953
  // materialize one signal per touched leaf, so signal bytes are store
904
954
  // bytes. _time is write-only on signals (every read site is computed-
@@ -907,7 +957,7 @@ function signal(e, t) {
907
957
  Me: -1,
908
958
  T: null
909
959
  };
910
- if (t?.unobserved) ext(n).we = t.unobserved;
960
+ if (t?.unobserved) ext(n).Ye = t.unobserved;
911
961
  if (snapshotCaptureActive && !(n.l & CONFIG_NO_SNAPSHOT)) takeSnapshot(n, e);
912
962
  return n;
913
963
  }
@@ -928,17 +978,17 @@ function isEqual(e, t) {
928
978
  * and location slots (the store relabels `store.<key>` and stamps the
929
979
  * store's `loc` when the engine is installed). */ function slotSignal(e, t, n, o, E) {
930
980
  const s = {
931
- xe: t,
981
+ ye: t,
932
982
  l: CONFIG_OWNED_WRITE | CONFIG_SLOT_NODE,
933
983
  le: e,
934
984
  o: null,
935
- ve: null,
936
- Se: clock,
937
- ie: NOT_PENDING,
985
+ Ze: null,
986
+ ie: clock,
987
+ ue: NOT_PENDING,
938
988
  Me: -1,
939
989
  T: null,
940
990
  O: n,
941
- ze: o,
991
+ Xe: o,
942
992
  acc: E,
943
993
  px: undefined,
944
994
  pxv: undefined
@@ -1064,7 +1114,7 @@ function setVerdict(e) {
1064
1114
  * never the graph — A32).
1065
1115
  * False means the reader derives from the staged value.
1066
1116
  */ function readerSeesCommitted(e, t) {
1067
- return !t || e.ie === NOT_PENDING || t.l & CONFIG_CHILDREN_FORBIDDEN;
1117
+ return !t || e.ue === NOT_PENDING || t.l & CONFIG_CHILDREN_FORBIDDEN;
1068
1118
  }
1069
1119
 
1070
1120
  /** A28 — set when a node is staged (queuePendingNode) OUTSIDE a flush;
@@ -1085,7 +1135,7 @@ function markUnflushedStaged() {
1085
1135
  * is unflushed. Exempt: promoted writes (A28 (4): a write issued inside a
1086
1136
  * recompute is promoted at that recompute's end — boundary and loading
1087
1137
  * machinery, signals declared for in-computation writes). */ function unflushedValue(e) {
1088
- if (globalQueue.q || e.ie === NOT_PENDING || e.l & CONFIG_PROMOTED) return NOT_PENDING;
1138
+ if (globalQueue.Y || e.ue === NOT_PENDING || e.l & CONFIG_PROMOTED) return NOT_PENDING;
1089
1139
  // A held node (L2) carries a staged value between flushes too, but it was
1090
1140
  // flushed — and parked. Not an unflushed write — unless rewritten since:
1091
1141
  // then the flushed staging is what the world sees until the next flush.
@@ -1098,7 +1148,7 @@ function markUnflushedStaged() {
1098
1148
  * stash is stamped with the clock, which that flush advances. */ function stashFlushed(e) {
1099
1149
  const t = e.T;
1100
1150
  if (t.Be !== clock) {
1101
- t.je = e.ie;
1151
+ t.je = e.ue;
1102
1152
  t.Be = clock;
1103
1153
  unflushedStaged = true;
1104
1154
  }
@@ -1146,18 +1196,19 @@ function resyncUnflushedCompanions() {
1146
1196
 
1147
1197
  function read(e) {
1148
1198
  let t = context;
1149
- if (t?.Qe) t = t.Ye;
1199
+ if (t?.Qe) t = t.Ke;
1150
1200
  const n = e;
1151
1201
  // CARVE 1: `owner` was `el._firewall || el` — a store leaf's status,
1152
1202
  // height and error were read off its projection computed. (Typed loosely
1153
1203
  // as the `||` expression was: a signal's `_statusFlags`/`_height` read as
1154
1204
  // undefined and mask to 0 on every site below.)
1155
1205
  const o = e;
1156
- if (typeof n.X === "function") prepareComputed(e);
1157
1206
  // The verdict windows (`latest`, `isPending`; verdict.ts): one cold path,
1158
- // off this one, present only while a window is open.
1207
+ // off this one, present only while a window is open. It wakes a lazy or
1208
+ // dormant memo itself, outside the window (#4366).
1159
1209
  if (verdict !== null) return verdict(e, t);
1160
- if (!n.X && e.T?.De === undefined && !snapshotCaptureActive && (!unflushedStaged || e.ie === NOT_PENDING) && // A28, see readNodeFast
1210
+ if (typeof n.X === "function") prepareComputed(e);
1211
+ if (!n.X && e.T?.De === undefined && !snapshotCaptureActive && (!unflushedStaged || e.ue === NOT_PENDING) && // A28, see readNodeFast
1161
1212
  !(e.l & CONFIG_OVERRIDE) && // lanes: the slow path's one arm
1162
1213
  true) {
1163
1214
  if (t) {
@@ -1178,13 +1229,13 @@ function read(e) {
1178
1229
  }
1179
1230
  }
1180
1231
  // Committed visibility for untracked and children-forbidden readers.
1181
- if (!t || e.ie === NOT_PENDING || t.l & CONFIG_CHILDREN_FORBIDDEN) return e.le;
1232
+ if (!t || e.ue === NOT_PENDING || t.l & CONFIG_CHILDREN_FORBIDDEN) return e.le;
1182
1233
  // (A plain signal is never uninitialized — the carve-out is `serve`'s.)
1183
1234
  // Lane work over a folded lane (D-34), once the frame has a
1184
1235
  // transaction, reads the screen too.
1185
1236
  if ((observeFlightHook && t.l & CONFIG_VERDICT || laneStageHook && passLane?.folded) && stagedScreen(t)) return e.le;
1186
1237
  stagedRead(t);
1187
- return e.ie;
1238
+ return e.ue;
1188
1239
  }
1189
1240
  // Rule 3: this read serves the committed value to a render effect outside a
1190
1241
  // parking flush (decided after the pull below — a pull can join).
@@ -1199,7 +1250,8 @@ function read(e) {
1199
1250
  // it probed inline: it reads held values as the screen and shows the
1200
1251
  // verdict now. Not an effect: a render effect is a frame reader
1201
1252
  // already, and a user effect's posture is its own reads'.
1202
- if (!t.i) t.R |= o.l & CONFIG_VERDICT;
1253
+ // (A verdict memo exists only with the verdict engine installed.)
1254
+ if (observeFlightHook && !t.i) t.R |= o.l & CONFIG_VERDICT;
1203
1255
  }
1204
1256
  }
1205
1257
  // L2, as in the fast block above (tracked or not). A node born into the
@@ -1225,7 +1277,7 @@ function read(e) {
1225
1277
  const n = e.T?.De;
1226
1278
  if (n !== undefined && !(o.m & STATUS_ERROR)) {
1227
1279
  const o = n === NO_SNAPSHOT ? undefined : n;
1228
- const E = e.ie !== NOT_PENDING ? e.ie : e.le;
1280
+ const E = e.ue !== NOT_PENDING ? e.ue : e.le;
1229
1281
  if (E !== o) t.R |= REACTIVE_SNAPSHOT_STALE;
1230
1282
  return o;
1231
1283
  }
@@ -1244,11 +1296,12 @@ function read(e) {
1244
1296
  // — unless the flight committed beneath inputs already on screen
1245
1297
  // (`observeFlight`), or the reader was born into the flight's transaction
1246
1298
  // (#4010): it has no screen, and waits on the flight with its frame.
1247
- if (o.m & STATUS_PENDING && !E && !(e.l & CONFIG_OVERRIDE) && !(o.m & STATUS_UNINITIALIZED)) {
1299
+ // (A lane, and a verdict reader, exist only with their engines installed —
1300
+ // the verdict engine imports the lane engine: without it the test folds.)
1301
+ if (laneStageHook && o.m & STATUS_PENDING && !E && !(e.l & CONFIG_OVERRIDE) && !(o.m & STATUS_UNINITIALIZED)) {
1248
1302
  // A reader with no committed value yet sees the flight pending: a
1249
1303
  // boundary a lane mounts shows its fallback (A29's boundary exemption).
1250
- // (A lane, and a verdict reader, exist only with their engines installed.)
1251
- if (laneStageHook && passLane !== null && !(t?.m & STATUS_UNINITIALIZED)) E = true; else if (observeFlightHook && t !== null && t.l & CONFIG_VERDICT) E = observeFlightHook(t, o);
1304
+ if (passLane !== null && !(t?.m & STATUS_UNINITIALIZED)) E = true; else if (t !== null && t.l & CONFIG_VERDICT) E = observeFlightHook(t, o);
1252
1305
  }
1253
1306
  if (o.m & STATUS_PENDING && !E) {
1254
1307
  // A reader landing on a pending node throws; an untracked read of an
@@ -1274,16 +1327,24 @@ function read(e) {
1274
1327
  // Only a genuine reactive re-read may retry an errored async source:
1275
1328
  // - tracking: owned/tracked scope only (never events / `untrack` / effect side-effect phase)
1276
1329
  // - owner._time < clock: only on a later cycle than the one the error was found
1277
- if (tracking && o.Se < clock) {
1330
+ if (tracking && o.ie < clock) {
1278
1331
  recompute(o);
1279
1332
  return read(e);
1280
- } else throw o.T?.U;
1333
+ }
1334
+ // D-41: a staged error replacing the shown one is this flush's answer
1335
+ // (`stageError`): a reader served the staging (`serve`) throws it, as it
1336
+ // would read a staged value, and stages its own error with it; one
1337
+ // served the screen throws the shown error. Thrown the shown error, a
1338
+ // reader born this flush published it, and its readers' stale error
1339
+ // committed after the new one (#4404).
1340
+ if (!E && e.l & CONFIG_STAGED_ERROR) serve(e, t);
1341
+ throw o.T?.U;
1281
1342
  }
1282
- if (E) return e.le;
1283
- // D-41: an untracked read reads the screen, and a shown error is on it
1284
- // until the answer that replaces it commits.
1285
- if (!t && e.T?.Ie) throw e.T.Ie;
1286
- const s = serve(e, t);
1343
+ // D-41: an untracked read reads the screen, and so does a frame reader
1344
+ // served the committed value — `serve` hands it that value as it does an
1345
+ // untracked read — a shown error included (`throwShown`).
1346
+ if (E || !t) throwShown(e);
1347
+ const s = serve(e, E ? null : t);
1287
1348
  if (!t && typeof n.X === "function" && e.l & CONFIG_AUTO_DISPOSE && !(o.m & STATUS_PENDING) && !e.o) {
1288
1349
  // Deferred, not inline (#3078): an inline unobserved() here made untracked
1289
1350
  // reads destructive — dispose on this read, full revival recompute on the
@@ -1297,6 +1358,12 @@ function read(e) {
1297
1358
  return s;
1298
1359
  }
1299
1360
 
1361
+ /** D-41: a reader served the screen — an untracked read, a frame reader
1362
+ * served the committed value, a verdict reader (`serve`) — reads a shown
1363
+ * error there until the answer that replaces it commits. */ function throwShown(e) {
1364
+ if (e.T?.Te) throw e.T.Te;
1365
+ }
1366
+
1300
1367
  /**
1301
1368
  * Rule 1, the one slow implementation (DESIGN-CONSOLIDATION move 3b, step
1302
1369
  * 6c): the value a reader `c` (null = untracked, no pass) is served from
@@ -1311,18 +1378,17 @@ function read(e) {
1311
1378
  // an untracked reader has nothing to serve and holds (A19 exception 1) — a
1312
1379
  // bookkeeping read (`spectate`) likewise, and a children-forbidden reader
1313
1380
  // (A32: the frame, which has nothing here).
1314
- if (e.ie !== NOT_PENDING && e.m & STATUS_UNINITIALIZED && (!t || spectating || t.l & CONFIG_CHILDREN_FORBIDDEN)) throw new NotReadyError(null);
1381
+ if (e.ue !== NOT_PENDING && e.m & STATUS_UNINITIALIZED && (!t || spectating || t.l & CONFIG_CHILDREN_FORBIDDEN)) throw new NotReadyError(null);
1315
1382
  const n = t && unflushedStaged ? unflushedValue(e) : NOT_PENDING;
1316
1383
  if (n !== NOT_PENDING) {
1317
1384
  markLateLinker(t);
1318
1385
  return n;
1319
1386
  }
1320
- if (readerSeesCommitted(e, t)) return e.le;
1321
- if (observeFlightHook && t.l & CONFIG_VERDICT && !(e.m & STATUS_UNINITIALIZED) && stagedScreen(t)) return e.le;
1387
+ if (readerSeesCommitted(e, t) || observeFlightHook && t.l & CONFIG_VERDICT && !(e.m & STATUS_UNINITIALIZED) && stagedScreen(t) && !throwShown(e)) return e.le;
1322
1388
  stagedRead(t, e);
1323
1389
  // D-41: the staged answer is an error (`stageError`).
1324
- if (e.l & CONFIG_STAGED_ERROR) throw e.ie;
1325
- return e.ie;
1390
+ if (e.l & CONFIG_STAGED_ERROR) throw e.ue;
1391
+ return e.ue;
1326
1392
  }
1327
1393
 
1328
1394
  /** A pass read a staging of this flush: it derives from what the flush may
@@ -1342,7 +1408,13 @@ function read(e) {
1342
1408
  * round (#3969: nor does it make a later lane read a re-derive, `enterLane`). */ function stagedRead(e, t) {
1343
1409
  if (!(t?.m & STATUS_UNINITIALIZED)) {
1344
1410
  e.R |= REACTIVE_STAGED_READ;
1345
- if (laneSeamsHook && passLane !== null) stagedReaders.push(e);
1411
+ // A verdict reader's too when it is an effect, before the frame has a
1412
+ // transaction (after, `stagedScreen` serves it the screen): the staging
1413
+ // is the frame's read, and the pass re-derives once as a verdict reader
1414
+ // if the flush parks (D-22; D-25: the probe decides the posture in either
1415
+ // read order). A memo's is the frame's derivation either way: a memo is
1416
+ // not a leaf (`frameRead`).
1417
+ if (laneSeamsHook && (passLane !== null || e.i && e.l & CONFIG_VERDICT)) stagedReaders.push(e);
1346
1418
  }
1347
1419
  }
1348
1420
 
@@ -1356,6 +1428,14 @@ function read(e) {
1356
1428
  * its only value (A29). Nor has a reader born into the flush's transaction
1357
1429
  * (`bornInto`, #4010): its branch exists only there. */ function stagedScreen(e) {
1358
1430
  if (flushTransaction === null || bornInto(e, flushTransaction)) return false;
1431
+ // A transaction only a `latest()` read opened holds nothing: the staging
1432
+ // is the frame's read for a pass in the frame's seat, as it is before the
1433
+ // frame has one, and the seam re-derives the pass once only if the flush
1434
+ // parks (D-22, F-10). Lane work sees the screen (D-37). Not a pass with no
1435
+ // value yet: its first answer is nobody's hold (D-6) and would commit the
1436
+ // staging whether or not the frame parks — it reads the screen, and runs
1437
+ // again at the landing.
1438
+ if (observeFlightHook && flushTransaction === latestOpened && passLane === null && e.l & CONFIG_VERDICT && !(e.m & STATUS_UNINITIALIZED)) return !stagedReaders.push(e);
1359
1439
  staleReader(e, flushTransaction);
1360
1440
  return true;
1361
1441
  }
@@ -1363,7 +1443,7 @@ function read(e) {
1363
1443
  /** A28 (4) — written inside a recompute that runs OUTSIDE a flush (a
1364
1444
  * creation-time compute): promoted at that pass's end, visible to the rest of
1365
1445
  * the block. Cold: only contextual writes reach here. */ function notePromotedWrite(e) {
1366
- if (globalQueue.q || e.l & CONFIG_PROMOTED) return;
1446
+ if (globalQueue.Y || e.l & CONFIG_PROMOTED) return;
1367
1447
  e.l |= CONFIG_PROMOTED;
1368
1448
  promotedWrites.push(e);
1369
1449
  }
@@ -1411,9 +1491,9 @@ function takeSnapshot(e, t) {
1411
1491
  * unwinding a flush or a setter; answered "same" so nothing commits.
1412
1492
  * @internal
1413
1493
  */ function isSame(e, t, n) {
1414
- if (e.xe === isEqual) return t === n;
1494
+ if (e.ye === isEqual) return t === n;
1415
1495
  try {
1416
- return e.xe && e.xe(t, n);
1496
+ return e.ye && e.ye(t, n);
1417
1497
  } catch (t) {
1418
1498
  if (!(t instanceof NotReadyError)) return notifyStatus(e, STATUS_ERROR, t), true;
1419
1499
  }
@@ -1421,7 +1501,7 @@ function takeSnapshot(e, t) {
1421
1501
 
1422
1502
  function setSignal(e, t) {
1423
1503
  if (writeHook !== null) writeHook(e);
1424
- const n = e.ie === NOT_PENDING ? e.le : e.ie;
1504
+ const n = e.ue === NOT_PENDING ? e.le : e.ue;
1425
1505
  if (typeof t === "function") t = t(n);
1426
1506
  // Lanes: a write landing on a guess is its truth (A18 — an async guess's
1427
1507
  // own landing), judged against the guess; one landing on a lane's
@@ -1436,7 +1516,7 @@ function setSignal(e, t) {
1436
1516
  // user comparator must not run against `undefined` (matches recompute).
1437
1517
  // D-41: a write over a shown error is a change whatever the last good
1438
1518
  // value was — the error leaves at its commit (`commitPendingNode`).
1439
- const o = !!(e.m & STATUS_UNINITIALIZED) || !!e.T?.Ie || !isSame(e, n, t);
1519
+ const o = !!(e.m & STATUS_UNINITIALIZED) || !!e.T?.Te || !isSame(e, n, t);
1440
1520
  if (!o) return t;
1441
1521
  // A write during hydration's snapshot capture to a source that has no
1442
1522
  // snapshot — created BEFORE capture began (module-level state: an identity
@@ -1448,16 +1528,16 @@ function setSignal(e, t) {
1448
1528
  // pass reads a value the server never had. Store leaves written here are
1449
1529
  // plain signals and qualify the same way.
1450
1530
  if (snapshotCaptureActive) captureWriteSnapshot(e, n);
1451
- const E = e.ie !== NOT_PENDING;
1531
+ const E = e.ue !== NOT_PENDING;
1452
1532
  if (!E) queuePendingNode(e);
1453
1533
  // A28: a held node rewritten outside a flush keeps its flushed staging
1454
1534
  // for every reader until the flush that carries the rewrite.
1455
- else if (e.l & CONFIG_HELD && !globalQueue.q) stashFlushed(e);
1456
- e.ie = t;
1535
+ else if (e.l & CONFIG_HELD && !globalQueue.Y) stashFlushed(e);
1536
+ e.ue = t;
1457
1537
  if (context !== null) notePromotedWrite(e);
1458
1538
  // _time is a computed-only slot (§12e): writing it on a signal would fork
1459
1539
  // the lean shape. Every read site is computed-typed.
1460
- if (e.X !== undefined) e.Se = clock;
1540
+ if (e.X !== undefined) e.ie = clock;
1461
1541
  // Staged-rewrite fast path (§12d): a re-write to a node whose subscribers
1462
1542
  // were already walked — and where nothing has recomputed or linked since
1463
1543
  // (epoch) — re-stages the value and stops. The walk is idempotent (subs
@@ -1498,8 +1578,8 @@ function setSignal(e, t) {
1498
1578
  // every later read keeps throwing the error the derivation left behind.
1499
1579
  // The error stays the display until the write commits (D-41).
1500
1580
  if (e.m & STATUS_ERROR) {
1501
- e.T.Ie = e.T.U;
1502
- notifyStatus(e, STATUS_NONE, undefined);
1581
+ e.T.Te = e.T.U;
1582
+ notifyStatus(e, STATUS_NONE);
1503
1583
  }
1504
1584
  t = setSignal(e, t);
1505
1585
  // A write replaces an error a pass staged (D-41): it is a value again.
@@ -1510,7 +1590,7 @@ function setSignal(e, t) {
1510
1590
  e.R = e.R & ~REACTIVE_CHECK | REACTIVE_DIRTY;
1511
1591
  insertIntoHeap(e, dirtyQueue);
1512
1592
  schedule();
1513
- } else if (e.ie !== NOT_PENDING) e.R |= REACTIVE_MANUAL_WRITE;
1593
+ } else if (e.ue !== NOT_PENDING) e.R |= REACTIVE_MANUAL_WRITE;
1514
1594
  return t;
1515
1595
  }
1516
1596
 
@@ -1571,4 +1651,4 @@ function staleValues(e, t = true) {
1571
1651
  }
1572
1652
  }
1573
1653
 
1574
- 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 };
1654
+ export { bornInto, captureWriteSnapshot, clearSnapshots, computed, context, createEffectNode, creatorPass, creatorReads, 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 };