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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/dist/dev-shared.js +248 -189
  2. package/dist/dev.attribution.js +124 -41
  3. package/dist/dev.js +553 -322
  4. package/dist/observe/affects.js +34 -31
  5. package/dist/observe/boundaries.js +166 -132
  6. package/dist/observe/core/async.js +90 -83
  7. package/dist/observe/core/attribution-queries.js +1 -1
  8. package/dist/observe/core/attribution.js +281 -197
  9. package/dist/observe/core/constants.js +7 -2
  10. package/dist/observe/core/context.js +3 -3
  11. package/dist/observe/core/core.js +277 -245
  12. package/dist/observe/core/dev.js +3 -3
  13. package/dist/observe/core/effect.js +21 -21
  14. package/dist/observe/core/external.js +2 -2
  15. package/dist/observe/core/graph.js +25 -25
  16. package/dist/observe/core/heap.js +9 -9
  17. package/dist/observe/core/lanes.js +206 -160
  18. package/dist/observe/core/owner.js +27 -27
  19. package/dist/observe/core/scheduler.js +92 -86
  20. package/dist/observe/core/verdict.js +66 -54
  21. package/dist/observe/map.js +35 -35
  22. package/dist/observe/reveal.js +24 -24
  23. package/dist/observe/signals.js +38 -28
  24. package/dist/observe/store/affects.js +75 -68
  25. package/dist/observe/store/hooks.js +13 -0
  26. package/dist/observe/store/index.js +0 -2
  27. package/dist/observe/store/optimistic.js +67 -34
  28. package/dist/observe/store/projection.js +37 -31
  29. package/dist/observe/store/reconcile.js +32 -30
  30. package/dist/observe/store/store.js +128 -85
  31. package/dist/prod/affects.js +34 -31
  32. package/dist/prod/boundaries.js +143 -109
  33. package/dist/prod/core/async.js +64 -67
  34. package/dist/prod/core/constants.js +7 -2
  35. package/dist/prod/core/context.js +3 -3
  36. package/dist/prod/core/core.js +302 -270
  37. package/dist/prod/core/effect.js +38 -38
  38. package/dist/prod/core/external.js +4 -4
  39. package/dist/prod/core/graph.js +27 -27
  40. package/dist/prod/core/heap.js +30 -30
  41. package/dist/prod/core/lanes.js +257 -211
  42. package/dist/prod/core/owner.js +39 -39
  43. package/dist/prod/core/scheduler.js +125 -119
  44. package/dist/prod/core/verdict.js +70 -58
  45. package/dist/prod/map.js +73 -73
  46. package/dist/prod/reveal.js +38 -38
  47. package/dist/prod/signals.js +30 -20
  48. package/dist/prod/store/affects.js +75 -68
  49. package/dist/prod/store/hooks.js +13 -0
  50. package/dist/prod/store/index.js +0 -2
  51. package/dist/prod/store/optimistic.js +114 -81
  52. package/dist/prod/store/projection.js +30 -24
  53. package/dist/prod/store/reconcile.js +32 -30
  54. package/dist/prod/store/store.js +136 -93
  55. package/dist/types/boundaries.d.ts +4 -0
  56. package/dist/types/core/attribution.d.ts +6 -2
  57. package/dist/types/core/constants.d.ts +5 -0
  58. package/dist/types/core/core.d.ts +33 -3
  59. package/dist/types/core/lanes.d.ts +10 -0
  60. package/dist/types/core/scheduler.d.ts +12 -6
  61. package/dist/types/core/types.d.ts +0 -6
  62. package/dist/types/store/affects.d.ts +11 -0
  63. package/dist/types/store/hooks.d.ts +48 -0
  64. package/dist/types/store/index.d.ts +0 -1
  65. package/dist/types/store/store.d.ts +3 -38
  66. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import { CONFIG_GUESS, NOT_PENDING, CONFIG_OVERRIDE, REACTIVE_DISPOSED, CONFIG_VERDICT, REACTIVE_PROBE_UNANSWERED, CONFIG_AUTHORITATIVE, CONFIG_CHILDREN_FORBIDDEN, STATUS_PENDING, EFFECT_RENDER, CONFIG_HELD, STATUS_UNINITIALIZED, REACTIVE_SCREEN_READ, REACTIVE_FRAME_READ, REACTIVE_LANE_READ, REACTIVE_RECOMPUTING_DEPS, REACTIVE_LANE_DIRTY, CONFIG_STAGED, REACTIVE_JOINED, CONFIG_SLOT_NODE, REACTIVE_IN_HEAP, REACTIVE_DIRTY, REACTIVE_CHECK, CONFIG_INPUTS_PUBLISHED } from "./constants.js";
1
+ import { CONFIG_GUESS, NOT_PENDING, CONFIG_OVERRIDE, REACTIVE_DISPOSED, CONFIG_VERDICT, REACTIVE_PROBE_UNANSWERED, REACTIVE_LANE_DIRTY, CONFIG_AUTHORITATIVE, CONFIG_CHILDREN_FORBIDDEN, STATUS_PENDING, EFFECT_RENDER, CONFIG_HELD, STATUS_UNINITIALIZED, REACTIVE_SCREEN_READ, REACTIVE_FRAME_READ, REACTIVE_LANE_READ, REACTIVE_RECOMPUTING_DEPS, CONFIG_STAGED, REACTIVE_JOINED, REACTIVE_STAGED_READ, CONFIG_SLOT_NODE, REACTIVE_IN_HEAP, REACTIVE_DIRTY, REACTIVE_CHECK, CONFIG_INPUTS_PUBLISHED } from "./constants.js";
2
2
 
3
3
  import { attrHooks } from "./attribution-hooks.js";
4
4
 
@@ -40,6 +40,8 @@ import { schedule, question, nextQuestion, GlobalQueue, blocked, resolveTx, txOf
40
40
  /** Live lanes (parented). Scanned at every seam while non-empty. */
41
41
  const lanes = [];
42
42
 
43
+ /** A pass left a shown slot the equality gate can no longer see (#3892). */ const LEFT_SHOWN = 1 << 20;
44
+
43
45
  function newLane(e) {
44
46
  const n = newTransaction(true, e);
45
47
  lanes.push(n);
@@ -49,15 +51,15 @@ function newLane(e) {
49
51
  /** A lane node's current value: its guess, or the latest it derived — the
50
52
  * staging a shown lane holds for its next reveal, else its slot; the
51
53
  * committed value while it has none (its first lane pass in flight). */ function laneValueOf(e) {
52
- if (!(e.u & CONFIG_GUESS) && e.Ae !== NOT_PENDING) return e.Ae;
53
- const n = e.m.Z;
54
- return n !== NOT_PENDING ? n : e.pe;
54
+ if (!(e.i & CONFIG_GUESS) && e.Oe !== NOT_PENDING) return e.Oe;
55
+ const n = e.m.B;
56
+ return n !== NOT_PENDING ? n : e.Ae;
55
57
  }
56
58
 
57
59
  /** What the screen shows for a lane's node: the lane's value once the lane
58
60
  * has revealed, the committed truth before. */ function display(e) {
59
- const n = e.m.Z;
60
- return e.m._t.Tt && n !== NOT_PENDING ? n : e.pe;
61
+ const n = e.m.B;
62
+ return e.m._t.Tt && n !== NOT_PENDING ? n : e.Ae;
61
63
  }
62
64
 
63
65
  /** Guesses written since the last seam (`[node, value, question, …]`).
@@ -72,7 +74,7 @@ function newLane(e) {
72
74
  * on (a store setter's draft too, store/optimistic.ts). */ function guessedValueOf(e) {
73
75
  const n = pendingGuessOf(e);
74
76
  if (n !== NOT_PENDING) return n;
75
- return e.u & CONFIG_OVERRIDE ? laneValueOf(e) : e.pe;
77
+ return e.i & CONFIG_OVERRIDE ? laneValueOf(e) : e.Ae;
76
78
  }
77
79
 
78
80
  /** The unflushed guess to `n`, else NOT_PENDING. */ function pendingGuessOf(e) {
@@ -88,7 +90,7 @@ function optimisticWrite(e, n) {
88
90
  // the guess's question and entangles its frame (#3347) without notifying.
89
91
  const t = guessedValueOf(e);
90
92
  if (typeof n === "function") n = n(t);
91
- if (e.tn && e.tn(t, n) && !(e.u & CONFIG_GUESS)) return n;
93
+ if (e.en && e.en(t, n) && !(e.i & CONFIG_GUESS)) return n;
92
94
  pendingGuesses.push(e, n, question || nextQuestion());
93
95
  schedule();
94
96
  return n;
@@ -106,33 +108,33 @@ function optimisticWrite(e, n) {
106
108
  /** A guess's own truth is in flight: the node's own refetch — or, a store
107
109
  * leaf's, its family's derive (the slot's flight; store/optimistic.ts
108
110
  * installs the resolver). A17: the guess stands in for the flight. */ function inFlight(e) {
109
- return (e.G & STATUS_PENDING) !== 0 || (e.u & CONFIG_SLOT_NODE) !== 0 && GlobalQueue.F?.(e) === true;
111
+ return (e.S & STATUS_PENDING) !== 0 || (e.i & CONFIG_SLOT_NODE) !== 0 && GlobalQueue.C?.(e) === true;
110
112
  }
111
113
 
112
114
  function applyGuesses(e) {
113
115
  let n = null;
114
116
  for (let t = 0; t < pendingGuesses.length; t += 3) {
115
- const s = pendingGuesses[t];
117
+ const u = pendingGuesses[t];
116
118
  const l = pendingGuesses[t + 1];
117
- let u = true;
118
- if (s.u & CONFIG_OVERRIDE) {
119
+ let s = true;
120
+ if (u.i & CONFIG_OVERRIDE) {
119
121
  // A lane's node already: a guess re-asked, or a derivation guessed
120
122
  // over (its staging is void — the guess is the value now). Two
121
123
  // suggestions for one slot cannot finish apart (A34 (1)): the frames
122
124
  // entangle. The same value re-asked renews the question; nothing to
123
125
  // notify.
124
- u = !s.tn || !s.tn(laneValueOf(s), l);
125
- if (!(s.u & CONFIG_GUESS)) {
126
- s.Ae = NOT_PENDING;
127
- s.u |= CONFIG_GUESS;
126
+ s = !u.en || !u.en(laneValueOf(u), l);
127
+ if (!(u.i & CONFIG_GUESS)) {
128
+ u.Oe = NOT_PENDING;
129
+ u.i |= CONFIG_GUESS;
128
130
  }
129
- s.m.Z = l;
130
- const n = txOf(s)._parent;
131
+ u.m.B = l;
132
+ const n = txOf(u)._parent;
131
133
  if (e !== null && n !== null) merge(e, n);
132
134
  } else {
133
135
  let t;
134
- if (s.u & CONFIG_HELD) t = newLane(txOf(s)); else {
135
- if (e === null && inFlight(s)) e = newTransaction(false);
136
+ if (u.i & CONFIG_HELD) t = newLane(txOf(u)); else {
137
+ if (e === null && inFlight(u)) e = newTransaction(false);
136
138
  if (e === null) continue;
137
139
  t = n ??= newLane(e);
138
140
  }
@@ -142,17 +144,17 @@ function applyGuesses(e) {
142
144
  // screen's plus the guess (plan sec. 19) — a derivation reading a held write
143
145
  // beside the guess must not show it. Two flights for one input, when
144
146
  // the worlds coincide, is the price.)
145
- ext(s).Z = l;
146
- s.u |= CONFIG_OVERRIDE | CONFIG_GUESS;
147
- list(s, t);
147
+ ext(u).B = l;
148
+ u.i |= CONFIG_OVERRIDE | CONFIG_GUESS;
149
+ list(u, t);
148
150
  }
149
- ext(s).Oe = pendingGuesses[t + 2];
150
- if (u) {
151
+ ext(u)._e = pendingGuesses[t + 2];
152
+ if (s) {
151
153
  // The lane's members re-derive as its work (REACTIVE_LANE_DIRTY): a
152
154
  // blocked lane's re-guess does not re-run its render effects as stale
153
155
  // readers republishing the committed view (#3460).
154
- insertSubs(s);
155
- laneDirty(s, txOf(s));
156
+ insertSubs(u);
157
+ laneDirty(u, txOf(u));
156
158
  }
157
159
  }
158
160
  pendingGuesses.length = 0;
@@ -173,8 +175,10 @@ function applyGuesses(e) {
173
175
  // The pass read a held write before its first lane read (it joined the
174
176
  // frame's future as mainline would): lane work sees the screen — the
175
177
  // seam re-derives it on the committed world next round (`stagedReaders`,
176
- // the park's repair), as it does a lane pass that read a staging.
177
- if (n.R & REACTIVE_JOINED) stagedRead(n);
178
+ // the park's repair), as it does a lane pass that read a staging. Not a
179
+ // pass whose held reads were all of nodes born held (no staged read,
180
+ // `stagedRead`): it has no committed world to re-derive on (#3969).
181
+ if (n.R & REACTIVE_JOINED && n.R & REACTIVE_STAGED_READ) stagedRead(n);
178
182
  return;
179
183
  }
180
184
  if (sameLane(t, e)) return setPassLane(e);
@@ -185,20 +189,20 @@ function applyGuesses(e) {
185
189
  }
186
190
 
187
191
  /** Is `l` nested under `a` (an ancestor lane)? */ function under(e, n) {
188
- for (let t = e._parent; t !== null && t.Z; t = t._parent) if (t === n) return true;
192
+ for (let t = e._parent; t !== null && t.B; t = t._parent) if (t === n) return true;
189
193
  return false;
190
194
  }
191
195
 
192
196
  /** One link group (a shared array) for both lanes' groups. */ function linkLanes(e, n) {
193
197
  const t = e.un ?? (e.un = [ e ]);
194
- const s = n.un;
195
- if (s === t) return;
196
- if (s === null) {
198
+ const u = n.un;
199
+ if (u === t) return;
200
+ if (u === null) {
197
201
  t.push(n);
198
202
  n.un = t;
199
- } else for (let e = 0; e < s.length; e++) {
200
- t.push(s[e]);
201
- s[e].un = t;
203
+ } else for (let e = 0; e < u.length; e++) {
204
+ t.push(u[e]);
205
+ u[e].un = t;
202
206
  }
203
207
  }
204
208
 
@@ -208,8 +212,8 @@ function applyGuesses(e) {
208
212
  * shows, A17.) */ function linkBlocked(e) {
209
213
  const n = e.un;
210
214
  if (n !== null) for (let t = 0; t < n.length; t++) {
211
- const s = n[t];
212
- if (s !== e && (s.tt !== 0 || ownFlights(s) || nestedBlocked(s))) return true;
215
+ const u = n[t];
216
+ if (u !== e && (u.tt !== 0 || ownFlights(u) || nestedBlocked(u))) return true;
213
217
  }
214
218
  return false;
215
219
  }
@@ -246,19 +250,24 @@ function unlink(e) {
246
250
  * not leave (A30: it never got there). A first pass under a lane is the
247
251
  * lane's (ruling A); a guess is written, not derived — it never leaves this
248
252
  * way. `errored`: the pass has no answer — or, a lane pass's pending
249
- * propagation (async.ts `propagateStatus`), the node gone pending. */ function laneStage(e, n, t, s) {
250
- if (!(t || s || e.R & REACTIVE_LANE_READ || e.u & CONFIG_GUESS)) {
251
- if (e.m !== null) {
252
- if (e.m._t?.Z) e.m._t = null;
253
- e.m.Z = NOT_PENDING;
253
+ * propagation (async.ts `propagateStatus`), the node gone pending. */ function laneStage(e, n, t, u) {
254
+ if (!(t || u || e.R & REACTIVE_LANE_READ || e.i & CONFIG_GUESS)) {
255
+ const n = e.m;
256
+ if (n !== null) {
257
+ const t = n._t;
258
+ // Cleared before equality, so a return to the committed value notifies
259
+ // nobody. The seam wakes it unless the frame is still held (#3892).
260
+ if (t?.Tt && !blocked(resolveTx(t._parent))) e.R |= LEFT_SHOWN;
261
+ if (t?.B) n._t = null;
262
+ n.B = NOT_PENDING;
254
263
  }
255
- e.u &= -2305;
264
+ e.i &= -1050881;
256
265
  return false;
257
266
  }
258
- if (!e.i) {
259
- if (!(e.u & CONFIG_OVERRIDE)) {
260
- e.Ae = NOT_PENDING;
261
- e.u = e.u & ~CONFIG_HELD | CONFIG_OVERRIDE;
267
+ if (!e.u) {
268
+ if (!(e.i & CONFIG_OVERRIDE)) {
269
+ e.Oe = NOT_PENDING;
270
+ e.i = e.i & -1048833 | CONFIG_OVERRIDE;
262
271
  ext(e);
263
272
  }
264
273
  // A written guess whose own pass is the lane's work — its source is a
@@ -267,7 +276,7 @@ function unlink(e) {
267
276
  // of the lane from here (its value the lane's, its fate the lane's), no
268
277
  // longer a written guess. A pass with no answer (pending, errored)
269
278
  // leaves the guess.
270
- if (!s) e.u &= ~CONFIG_GUESS;
279
+ if (!u) e.i &= ~CONFIG_GUESS;
271
280
  }
272
281
  // A leaf has no lane value to seat it (`recompute`): one left waiting on
273
282
  // the lane's flight runs its next pass as the lane's — the landing that
@@ -279,8 +288,8 @@ function unlink(e) {
279
288
  // `laneRead` decides — its frame holds). Its pending is the frame's: queued
280
289
  // for the commit sweep as mainline's (async.ts). A node born in the lane
281
290
  // has nothing on screen: its leaf waits as the lane's.
282
- else if (s) {
283
- if (s !== true && !(s.G & STATUS_UNINITIALIZED) && (e.u & CONFIG_HELD || e.R & REACTIVE_RECOMPUTING_DEPS) && !e.m?._t?.Z) {
291
+ else if (u) {
292
+ if (u !== true && !(u.S & STATUS_UNINITIALIZED) && (e.i & CONFIG_HELD || e.R & REACTIVE_RECOMPUTING_DEPS) && !e.m?._t?.B) {
284
293
  queuePendingNode(e);
285
294
  return false;
286
295
  }
@@ -301,32 +310,58 @@ function unlink(e) {
301
310
  * covered (no landing beneath it) — `optimisticReverted`'s "reverted". */ let reverting = false;
302
311
 
303
312
  function supersede(e, n, t) {
304
- const s = txOf(e);
313
+ const u = txOf(e);
305
314
  // Resolved: the parent may have merged into another transaction since the
306
315
  // lane opened (two actions guessing one slot entangle, A34 (1)) — the
307
316
  // truth is held by the transaction that lands, not the merged-away one.
308
- const l = resolveTx(s._parent ?? s);
317
+ const l = resolveTx(u._parent ?? u);
318
+ // A store row answered by a new object the store would reconcile into
319
+ // the guessed one unchanged is an echo, not a correction (#3898): the
320
+ // server's object never matches the guess by reference.
321
+ if (t && e.i & CONFIG_SLOT_NODE && GlobalQueue.sn?.(e.m.B, n)) t = false;
309
322
  if (t) {
310
323
  // Observe: a displayed guess is being replaced by a differing truth — a
311
324
  // landing's (superseded), or the value it covered (reverted: the body
312
325
  // ended with nothing coming true).
313
- if (s.Tt && attrHooks !== null) attrHooks.optimisticReverted(e, e.m.Z, n, reverting ? "reverted" : "superseded");
314
- dissolveLane(s, l, e);
326
+ if (u.Tt && attrHooks !== null) attrHooks.optimisticReverted(e, e.m.B, n, reverting ? "reverted" : "superseded");
327
+ dissolveLane(u, l, e);
315
328
  // What the screen showed stays the screen until the parent lands (A18
316
329
  // (c): display and untracked reads keep the override until the commit).
317
- if (s.Tt) e.pe = e.m.Z;
318
- e.u &= -10241;
319
- e.m.Z = NOT_PENDING;
320
- e.Ae = n;
330
+ if (u.Tt) e.Ae = e.m.B;
331
+ e.i &= -10241;
332
+ e.m.B = NOT_PENDING;
321
333
  holdNode(e, l);
322
- joinFuture(l);
323
334
  if (e.t !== null) insertSubs(e);
324
335
  } else {
325
- e.Ae = n;
326
- e.u |= CONFIG_HELD;
327
- joinFuture(l);
328
- for (let n = e.t; n !== null; n = n.l) if (n.o.u & CONFIG_AUTHORITATIVE) enqueueSub(n.o);
336
+ e.i |= CONFIG_HELD;
337
+ // A confirmation is silent (A17); only truth readers are told.
338
+ GlobalQueue.rn?.(u);
329
339
  }
340
+ e.Oe = n;
341
+ joinFuture(l);
342
+ }
343
+
344
+ /** Truth readers (`until`, `refresh`; CONFIG_AUTHORITATIVE) — pay-for-use:
345
+ * the first one installs these on GlobalQueue (signals.ts `watch`).
346
+ *
347
+ * A truth reader's read of a lane node: the lane's value when it is the
348
+ * truth (#3943), else the truth staged beneath a guess, else the committed
349
+ * value. */ function truthRead(e) {
350
+ return truth(e) ? laneValueOf(e) : e.i & CONFIG_GUESS && e.Oe !== NOT_PENDING ? e.Oe : e.Ae;
351
+ }
352
+
353
+ /** A guess confirmed: its lane's truth readers re-read — of the lane's
354
+ * derivations too, which may be the truth now (#3943). */ function truthConfirmed(e) {
355
+ for (let n = 0; n < e.Je.length; n++) for (let t = e.Je[n].t; t !== null; t = t.o) if (t.l.i & CONFIG_AUTHORITATIVE) enqueueSub(t.l);
356
+ }
357
+
358
+ /** A lane node's value is the truth when every guess beneath it is
359
+ * confirmed — its source staged a value equal to the guess — and nothing
360
+ * beneath it is held in the parent: same inputs, same value. */ function truth(e) {
361
+ if (e.i & CONFIG_GUESS) return e.Oe !== NOT_PENDING && e.en && e.en(e.m.B, e.Oe);
362
+ if (e.Oe !== NOT_PENDING) return;
363
+ if (e.i & CONFIG_OVERRIDE) for (let n = e.G; n; n = n._) if (!truth(n.I)) return;
364
+ return 1;
330
365
  }
331
366
 
332
367
  /** A lane's end, two ways. `into === null`: the parent landed — the lane's
@@ -339,8 +374,8 @@ function supersede(e, n, t) {
339
374
  * against what is seen), a truth staged beneath a guess is the parent's to
340
375
  * land, and the runs it held (showing the void guess) are dropped: the
341
376
  * parent's re-derivation makes the runs that show. */ function dissolveLane(e, n, t) {
342
- const s = lanes.indexOf(e);
343
- if (s !== -1) lanes.splice(s, 1);
377
+ const u = lanes.indexOf(e);
378
+ if (u !== -1) lanes.splice(u, 1);
344
379
  unlink(e);
345
380
  // Its verdicts end with it (a correction's dissolution reaches here before
346
381
  // `endLanes` would): the readers re-derive from the truth's notification.
@@ -349,19 +384,19 @@ function supersede(e, n, t) {
349
384
  e.rt = null;
350
385
  if (lanes.indexOf(l) !== -1) dissolveLane(l, null);
351
386
  }
352
- for (let s = 0; s < e.nn.length; s++) {
353
- const l = e.nn[s];
354
- const u = l.m;
355
- if (l === t || u._t !== e) continue;
356
- const r = l.i;
357
- const i = l.u & CONFIG_GUESS;
358
- const o = u.Z;
387
+ for (let u = 0; u < e.Je.length; u++) {
388
+ const l = e.Je[u];
389
+ const s = l.m;
390
+ if (l === t || s._t !== e) continue;
391
+ const r = l.u;
392
+ const i = l.i & CONFIG_GUESS;
393
+ const o = s.B;
359
394
  // What the screen shows of it (NOT_PENDING: nothing — a lane pass that
360
395
  // errored or pends staged no value), and the lane's latest.
361
- const f = e.Tt && !r ? o : l.pe;
396
+ const f = e.Tt && !r ? o : l.Ae;
362
397
  const E = laneValueOf(l);
363
- u.Z = NOT_PENDING;
364
- l.u &= -10241;
398
+ s.B = NOT_PENDING;
399
+ l.i &= -10241;
365
400
  if (n === null) {
366
401
  // The parent landed: a guess lands the truth beneath it or reverts to
367
402
  // the one it covered; a derivation's latest commits (its frame with
@@ -370,28 +405,28 @@ function supersede(e, n, t) {
370
405
  // beneath it (superseded by a landing held there) or the value it
371
406
  // covered (reverted: nothing came true).
372
407
  if (i && e.Tt && attrHooks !== null) {
373
- const e = l.Ae !== NOT_PENDING ? l.Ae : l.pe;
374
- if (e !== o) attrHooks.optimisticReverted(l, o, e, l.Ae !== NOT_PENDING ? "superseded" : "reverted");
408
+ const e = l.Oe !== NOT_PENDING ? l.Oe : l.Ae;
409
+ if (e !== o) attrHooks.optimisticReverted(l, o, e, l.Oe !== NOT_PENDING ? "superseded" : "reverted");
375
410
  }
376
411
  // A derivation the revert re-derives (dirtied by the guess's
377
412
  // notification — listed before it), or one still in flight, shows the
378
413
  // lane's answer beside inputs that are the truth now: a fresh reader
379
414
  // of its flight observes it (#3648, #3651; #3305's commit beneath a
380
415
  // flight).
381
- u._t = null;
382
- if (!r && !i) l.Ae = E;
416
+ s._t = null;
417
+ if (!r && !i) l.Oe = E;
383
418
  commitPendingNode(l);
384
419
  if (!r) {
385
- if (l.R & (REACTIVE_IN_HEAP | REACTIVE_DIRTY | REACTIVE_CHECK) || l.G & STATUS_PENDING) l.u |= CONFIG_INPUTS_PUBLISHED;
386
- if (f !== NOT_PENDING && (!l.tn || !l.tn(f, l.pe))) insertSubs(l);
420
+ if (l.R & (REACTIVE_IN_HEAP | REACTIVE_DIRTY | REACTIVE_CHECK) || l.S & STATUS_PENDING) l.i |= CONFIG_INPUTS_PUBLISHED;
421
+ if (f !== NOT_PENDING && (!l.en || !l.en(f, l.Ae))) insertSubs(l);
387
422
  }
388
423
  } else if (i) {
389
424
  // A guess of a dissolving lane: its truth — a landing held beneath it,
390
425
  // else the value it covered — is the parent's to land, and its readers
391
426
  // re-derive from it there. What the screen showed stays the screen
392
427
  // until then (A18 (c)).
393
- if (l.Ae === NOT_PENDING) l.Ae = covered(l);
394
- if (e.Tt) l.pe = o;
428
+ if (l.Oe === NOT_PENDING) l.Oe = covered(l);
429
+ if (e.Tt) l.Ae = o;
395
430
  holdNode(l, n);
396
431
  insertSubs(l);
397
432
  } else {
@@ -402,20 +437,20 @@ function supersede(e, n, t) {
402
437
  // flight is asking the void world's question: its landing is nobody's
403
438
  // answer — it re-asks from the truth (whose notification may not reach
404
439
  // it: an input's truth equal to its committed value is silent).
405
- u._t = null;
440
+ s._t = null;
406
441
  if (!r) {
407
- if (f !== NOT_PENDING && e.Tt) l.Ae = f;
408
- if (l.G & STATUS_PENDING) {
409
- u.De = null;
442
+ if (f !== NOT_PENDING && e.Tt) l.Oe = f;
443
+ if (l.S & STATUS_PENDING) {
444
+ s.Te = null;
410
445
  enqueueSub(l);
411
446
  }
412
447
  }
413
448
  if (e.Tt) {
414
449
  commitPendingNode(l);
415
- if (!r) l.u |= CONFIG_INPUTS_PUBLISHED;
450
+ if (!r) l.i |= CONFIG_INPUTS_PUBLISHED;
416
451
  } else {
417
- if (u.St !== null || u.ct !== null) GlobalQueue.st(l, false, true);
418
- l.u &= -385;
452
+ if (s.St !== null || s.ct !== null) GlobalQueue.Et(l, false, true);
453
+ l.i &= -1048961;
419
454
  }
420
455
  }
421
456
  }
@@ -448,59 +483,59 @@ function supersede(e, n, t) {
448
483
  * verdict: released if the lane shows, held if it blocks) — and sees the
449
484
  * lane's latest. NOT_PENDING falls through: lane work's read of a pending
450
485
  * member throws like any. */ function laneRead(e, n) {
451
- const t = n.u & CONFIG_GUESS;
452
- if (e !== null && e.u & CONFIG_AUTHORITATIVE) return t && n.Ae !== NOT_PENDING ? n.Ae : n.pe;
486
+ const t = n.i & CONFIG_GUESS;
487
+ if (e !== null && e.i & CONFIG_AUTHORITATIVE) return GlobalQueue.Nn(n);
453
488
  if (e === null) return laneValueOf(n);
454
- const s = txOf(n);
455
- const l = n.G;
456
- if (!tracking || e.u & CONFIG_CHILDREN_FORBIDDEN) {
489
+ const u = txOf(n);
490
+ const l = n.S;
491
+ if (!tracking || e.i & CONFIG_CHILDREN_FORBIDDEN) {
457
492
  // An untracked read inside lane work derives from the lane like a
458
493
  // tracked one, minus the subscription — `untrack` is about
459
494
  // dependencies, not about which world a pass derives from (a mapper's
460
495
  // row reads under its root, store/map): the pass enters the lane (two
461
496
  // lanes read by one pass link, as for tracked reads). Outside lane
462
497
  // work, the screen.
463
- if (passLane === null || e.u & CONFIG_CHILDREN_FORBIDDEN) return display(n);
464
- enterLane(s, e);
498
+ if (passLane === null || e.i & CONFIG_CHILDREN_FORBIDDEN) return display(n);
499
+ enterLane(u, e);
465
500
  if (!t && l & STATUS_PENDING) return NOT_PENDING;
466
501
  return laneValueOf(n);
467
502
  }
468
- if (e.i === EFFECT_RENDER && (passLane === null || !sameLane(passLane, s))) {
503
+ if (e.u === EFFECT_RENDER && (passLane === null || !sameLane(passLane, u))) {
469
504
  if (!t) {
470
505
  // A flight whose value has never shown: nothing to show — the leaf
471
506
  // waits on it, and its own frame holds (A15, #3334), not the lane's
472
507
  // parent. The landing lands the frame: its own pass (the flush
473
508
  // joined its transaction) reads the answer it waited on — the lane's
474
509
  // staging, revealed at this seam.
475
- if (l & STATUS_PENDING && n.m.Z === NOT_PENDING) return NOT_PENDING;
476
- if (n.Ae !== NOT_PENDING && e.u & CONFIG_HELD && flushTransaction !== null && resolveTx(flushTransaction) === txOf(e)) return n.Ae;
510
+ if (l & STATUS_PENDING && n.m.B === NOT_PENDING) return NOT_PENDING;
511
+ if (n.Oe !== NOT_PENDING && e.i & CONFIG_HELD && flushTransaction !== null && resolveTx(flushTransaction) === txOf(e)) return n.Oe;
477
512
  }
478
- if (s.fn || !t && l & STATUS_PENDING) {
479
- if (!t && !s.Tt && l & STATUS_UNINITIALIZED) throw new NotReadyError(null);
513
+ if (u.fn || !t && l & STATUS_PENDING) {
514
+ if (!t && !u.Tt && l & STATUS_UNINITIALIZED) throw new NotReadyError(null);
480
515
  // Re-derived at the reveal; once per pass (the pass may also be a stale
481
516
  // reader of a transaction, REACTIVE_FRAME_READ — both reruns apply).
482
517
  if (!(e.R & REACTIVE_SCREEN_READ)) {
483
518
  e.R |= REACTIVE_FRAME_READ | REACTIVE_SCREEN_READ;
484
- s.an.push(e);
519
+ u.an.push(e);
485
520
  }
486
521
  return display(n);
487
522
  }
488
523
  }
489
- enterLane(s, e);
524
+ enterLane(u, e);
490
525
  if (!t && l & STATUS_PENDING) return NOT_PENDING;
491
526
  return laneValueOf(n);
492
527
  }
493
528
 
494
529
  /** The value a guess covered: the node's committed value — a store slot's
495
530
  * asked of the store (a chained link follows the inner store's commits). */ function covered(e) {
496
- return e.u & CONFIG_SLOT_NODE && GlobalQueue.Nn !== undefined ? GlobalQueue.Nn(e) : e.pe;
531
+ return e.i & CONFIG_SLOT_NODE && GlobalQueue.In !== undefined ? GlobalQueue.In(e) : e.Ae;
497
532
  }
498
533
 
499
534
  /** A guess in `l` whose own truth is in flight (its refetch — authoritative:
500
535
  * the landing supersedes, not the body's end). */ function guessFlights(e) {
501
- for (let n = 0; n < e.nn.length; n++) {
502
- const t = e.nn[n];
503
- if (t.u & CONFIG_GUESS && t.m._t === e && inFlight(t)) return true;
536
+ for (let n = 0; n < e.Je.length; n++) {
537
+ const t = e.Je[n];
538
+ if (t.i & CONFIG_GUESS && t.m._t === e && inFlight(t)) return true;
504
539
  }
505
540
  return false;
506
541
  }
@@ -521,20 +556,20 @@ function supersede(e, n, t) {
521
556
  let e = false;
522
557
  const n = lanes.slice();
523
558
  for (let t = 0; t < n.length; t++) {
524
- const s = n[t];
525
- if (lanes.indexOf(s) === -1) continue;
526
- const l = resolveTx(s._parent);
527
- if (!l.nt || l.tt !== 0 || l.Z || ownFlights(l) || guessFlights(s)) continue;
559
+ const u = n[t];
560
+ if (lanes.indexOf(u) === -1) continue;
561
+ const l = resolveTx(u._parent);
562
+ if (!l.nt || l.tt !== 0 || l.B || ownFlights(l) || guessFlights(u)) continue;
528
563
  e = true;
529
564
  // Each guess's truth: the one beneath it (a landing held there), else
530
565
  // the one it covered. (A correction dissolves the lane — the others are
531
566
  // re-homed with theirs, `dissolveLane`.)
532
- for (let e = 0; e < s.nn.length && lanes.indexOf(s) !== -1; e++) {
533
- const n = s.nn[e];
534
- if (n.u & CONFIG_GUESS && n.m._t === s) {
535
- const e = n.Ae !== NOT_PENDING ? n.Ae : covered(n);
536
- reverting = n.Ae === NOT_PENDING;
537
- supersede(n, e, !n.tn || !n.tn(n.m.Z, e));
567
+ for (let e = 0; e < u.Je.length && lanes.indexOf(u) !== -1; e++) {
568
+ const n = u.Je[e];
569
+ if (n.i & CONFIG_GUESS && n.m._t === u) {
570
+ const e = n.Oe !== NOT_PENDING ? n.Oe : covered(n);
571
+ reverting = n.Oe === NOT_PENDING;
572
+ supersede(n, e, !n.en || !n.en(n.m.B, e));
538
573
  reverting = false;
539
574
  }
540
575
  }
@@ -552,18 +587,22 @@ function laneSeam(e, n) {
552
587
  e.fn = false;
553
588
  e.Tt = true;
554
589
  reruns(e);
555
- for (let n = 0; n < e.nn.length; n++) {
556
- const t = e.nn[n];
557
- const s = t.m;
558
- if (s._t !== e) continue;
559
- if (!(t.u & CONFIG_GUESS) && !t.i && t.Ae !== NOT_PENDING) {
560
- s.Z = t.Ae;
561
- t.Ae = NOT_PENDING;
590
+ for (let n = 0; n < e.Je.length; n++) {
591
+ const t = e.Je[n];
592
+ if (t.R & LEFT_SHOWN) {
593
+ t.R ^= LEFT_SHOWN;
594
+ insertSubs(t);
595
+ }
596
+ const u = t.m;
597
+ if (u._t !== e) continue;
598
+ if (!(t.i & CONFIG_GUESS) && !t.u && t.Oe !== NOT_PENDING) {
599
+ u.B = t.Oe;
600
+ t.Oe = NOT_PENDING;
562
601
  }
563
602
  // The frame this pass built is the screen's now; the one it replaced
564
603
  // goes (as `commitPendingNode` retires a committed pass's).
565
- if (s.St !== null || s.ct !== null) GlobalQueue.st(t, false, true);
566
- t.u &= ~CONFIG_STAGED;
604
+ if (u.St !== null || u.ct !== null) GlobalQueue.Et(t, false, true);
605
+ t.i &= ~CONFIG_STAGED;
567
606
  }
568
607
  releaseQueues(e);
569
608
  }
@@ -583,7 +622,7 @@ function laneSeam(e, n) {
583
622
  * frame is not complete without it (A15) — landing it would commit the write
584
623
  * beside a derivation still showing the old one. A guess whose own flight is
585
624
  * up likewise: the question was asked in this frame. */ function lanesBlocked(e) {
586
- return e.Z && linkBlocked(e) || nestedBlocked(e);
625
+ return e.B && linkBlocked(e) || nestedBlocked(e);
587
626
  }
588
627
 
589
628
  /** The lanes under `t` (its own; a link group's are each other's). */ function nestedBlocked(e) {
@@ -600,7 +639,7 @@ function laneSeam(e, n) {
600
639
  * landing), judged against the guess. On a derivation it is the lane's
601
640
  * latest: its staging once the lane has shown (promoted at the next
602
641
  * reveal), its slot before; the lane's members re-derive as its work. */ function laneWrite(e, n) {
603
- if (e.u & CONFIG_GUESS) {
642
+ if (e.i & CONFIG_GUESS) {
604
643
  // Provenance (A18, #3331; Q-D, plan sec. 39): a write asking an OLDER
605
644
  // question than the guess's — another action's landing beneath it —
606
645
  // is not its answer: held beneath (the truth for the commit; the
@@ -609,18 +648,18 @@ function laneSeam(e, n) {
609
648
  // continuation's — the flight's); unstamped writes and mainline are
610
649
  // current.
611
650
  if (stale(e, question)) {
612
- e.Ae = n;
613
- e.u |= CONFIG_HELD;
614
- GlobalQueue.In?.(e, n);
651
+ e.Oe = n;
652
+ e.i |= CONFIG_HELD;
653
+ GlobalQueue._n?.(e, n);
615
654
  schedule();
616
655
  return n;
617
656
  }
618
- supersede(e, n, !e.tn || !e.tn(e.m.Z, n));
657
+ supersede(e, n, !e.en || !e.en(e.m.B, n));
619
658
  } else {
620
659
  const t = txOf(e);
621
- if (e.tn && e.tn(laneValueOf(e), n)) return n;
622
- if (t.Tt) e.Ae = n; else e.m.Z = n;
623
- if (e.re !== undefined) e.Ne = clock;
660
+ if (e.en && e.en(laneValueOf(e), n)) return n;
661
+ if (t.Tt) e.Oe = n; else e.m.B = n;
662
+ if (e.ee !== undefined) e.Ie = clock;
624
663
  insertSubs(e);
625
664
  laneDirty(e, t);
626
665
  }
@@ -642,34 +681,34 @@ function laneSeam(e, n) {
642
681
  * A24). The guess's own question answering supersedes as usual. */ function laneOutcome(e, n, t) {
643
682
  if (t) return true;
644
683
  if (stale(e, answered(e))) {
645
- e.Ae = n;
646
- e.u |= CONFIG_HELD;
684
+ e.Oe = n;
685
+ e.i |= CONFIG_HELD;
647
686
  return true;
648
687
  }
649
- supersede(e, n, !e.tn || !e.tn(e.m.Z, n));
688
+ supersede(e, n, !e.en || !e.en(e.m.B, n));
650
689
  return true;
651
690
  }
652
691
 
653
692
  /** THE provenance test, for a derivation's pass and a write alike: an
654
693
  * answer to question `q` landing on a guess is stale when `q` is older
655
694
  * than the guess's own; unstamped (0) and mainline are current. */ function stale(e, n) {
656
- return n !== 0 && n < e.m.Oe;
695
+ return n !== 0 && n < e.m._e;
657
696
  }
658
697
 
659
698
  /** The question a derivation's pass answered: the newest among the stamped
660
699
  * sources that changed this round (a flight's landing carries the question
661
700
  * that started it); 0 when none is stamped. */ function answered(e) {
662
701
  let n = 0;
663
- for (let t = e._; t !== null; t = t.p) {
702
+ for (let t = e.G; t !== null; t = t._) {
664
703
  const e = t.I;
665
- if (e.m !== null && e.m.Oe > n && e.Ne === clock) n = e.m.Oe;
704
+ if (e.m !== null && e.m._e > n && e.Ie === clock) n = e.m._e;
666
705
  }
667
706
  return n;
668
707
  }
669
708
 
670
709
  GlobalQueue.Zt = laneRead;
671
710
 
672
- GlobalQueue.M = laneStage;
711
+ GlobalQueue.W = laneStage;
673
712
 
674
713
  GlobalQueue.ft = laneOutcome;
675
714
 
@@ -680,12 +719,12 @@ GlobalQueue.Qt = laneWrite;
680
719
  * born at the seam has no work to judge yet (its passes run next round) —
681
720
  * it is neither shown nor blocked until it has. */ let judged = 0;
682
721
 
683
- GlobalQueue.cn = e => {
722
+ GlobalQueue.Gn = e => {
684
723
  judged = lanes.length;
685
724
  if (pendingGuesses.length !== 0) applyGuesses(e);
686
725
  };
687
726
 
688
- GlobalQueue._n = e => {
727
+ GlobalQueue.cn = e => {
689
728
  // Passes that read a write the parked frame holds as the screen
690
729
  // (`stagedReaders`: lane work, a verdict reader before the verdict): they
691
730
  // re-derive on the committed world next round (and register as stale
@@ -693,36 +732,43 @@ GlobalQueue._n = e => {
693
732
  // lane sees the screen plus its own guesses.
694
733
  const n = [];
695
734
  if (e !== null) for (let t = 0; t < e.length; t++) {
696
- const s = e[t];
697
- const l = s.m?._t;
735
+ const u = e[t];
736
+ const l = u.m?._t;
698
737
  // A verdict reader a later read of the same pass routed into a verdict
699
738
  // lane answered for itself: it re-derives at the holder's landing, not
700
739
  // now (one run — #3322, #3540). Other verdict-lane work re-derives only
701
740
  // if the frame stays parked: a transaction landing at this seam makes
702
741
  // what it read the screen (one run).
703
- if (s.R & REACTIVE_DISPOSED || l != null && l._parent?.rt === l && (s.u & CONFIG_VERDICT ? !(s.R & REACTIVE_PROBE_UNANSWERED) : !blocked(l._parent))) continue;
704
- enqueueSub(s);
705
- if (l != null && l.Z && n.indexOf(l) === -1) n.push(l);
742
+ if (u.R & REACTIVE_DISPOSED || l != null && l._parent?.rt === l && (u.i & CONFIG_VERDICT ? !(u.R & REACTIVE_PROBE_UNANSWERED) : !blocked(l._parent))) continue;
743
+ // A leaked effect re-derives seated in its lane from its first read: it
744
+ // carries no lane value (`laneStage`), so without this its pass starts
745
+ // as mainline, joins the parked frame on its first held read and reads
746
+ // the staging, then re-enters the lane at its guess read and leaks
747
+ // again — every round (#4014). A computed is already seated by its
748
+ // override, and a written guess's own pass stays the frame's.
749
+ if (l != null && l.B && u.u) u.R |= REACTIVE_LANE_DIRTY;
750
+ enqueueSub(u);
751
+ if (l != null && l.B && n.indexOf(l) === -1) n.push(l);
706
752
  }
707
753
  for (let e = Math.min(judged, lanes.length) - 1; e >= 0; e--) laneSeam(lanes[e], n.indexOf(lanes[e]) !== -1);
708
754
  };
709
755
 
710
- GlobalQueue.Gn = () => lanes.length !== 0 && laneCorrections();
756
+ GlobalQueue.On = () => lanes.length !== 0 && laneCorrections();
711
757
 
712
- GlobalQueue.On = endLanes;
758
+ GlobalQueue.Tn = endLanes;
713
759
 
714
- GlobalQueue.Je = e => {
760
+ GlobalQueue.Qe = e => {
715
761
  const n = [];
716
762
  for (let t = 0; t < lanes.length; t++) {
717
- const s = lanes[t];
718
- if (resolveTx(s._parent) !== e) continue;
719
- for (let e = 0; e < s.nn.length; e++) if (s.nn[e].u & CONFIG_GUESS && s.nn[e].m._t === s) n.push(s.nn[e]);
763
+ const u = lanes[t];
764
+ if (resolveTx(u._parent) !== e) continue;
765
+ for (let e = 0; e < u.Je.length; e++) if (u.Je[e].i & CONFIG_GUESS && u.Je[e].m._t === u) n.push(u.Je[e]);
720
766
  }
721
767
  return n;
722
768
  };
723
769
 
724
- GlobalQueue.Tn = lanesBlocked;
770
+ GlobalQueue.dn = lanesBlocked;
725
771
 
726
- GlobalQueue.ne = verdictLane;
772
+ GlobalQueue.$ = verdictLane;
727
773
 
728
- export { display, enterLane, guessedValueOf, laneRead, laneStage, laneValueOf, optimisticWrite, pendingGuessOf, supersede, verdictLane };
774
+ export { display, enterLane, guessedValueOf, laneRead, laneStage, laneValueOf, optimisticWrite, pendingGuessOf, supersede, truthConfirmed, truthRead, verdictLane };