@solidjs/signals 2.0.0-rc.2 → 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 (198) hide show
  1. package/dist/dev-shared.js +6505 -0
  2. package/dist/dev.attribution.js +3484 -0
  3. package/dist/dev.js +10227 -9508
  4. package/dist/observe/affects-marks.js +86 -0
  5. package/dist/observe/affects.js +112 -0
  6. package/dist/observe/attribution.js +7 -0
  7. package/dist/observe/boundaries.js +696 -0
  8. package/dist/observe/core/action.js +182 -0
  9. package/dist/observe/core/async.js +824 -0
  10. package/dist/observe/core/attribution-costs.js +66 -0
  11. package/dist/observe/core/attribution-feedback.js +280 -0
  12. package/dist/observe/core/attribution-hooks.js +83 -0
  13. package/dist/observe/core/attribution-queries.js +43 -0
  14. package/dist/observe/core/attribution.js +3079 -0
  15. package/dist/observe/core/constants.js +269 -0
  16. package/dist/observe/core/context.js +63 -0
  17. package/dist/observe/core/copies.js +10 -0
  18. package/dist/observe/core/core.js +1707 -0
  19. package/dist/observe/core/dev.js +394 -0
  20. package/dist/observe/core/effect.js +193 -0
  21. package/dist/observe/core/error-hooks.js +71 -0
  22. package/dist/observe/core/error.js +82 -0
  23. package/dist/observe/core/external.js +97 -0
  24. package/dist/observe/core/graph.js +162 -0
  25. package/dist/observe/core/heap.js +124 -0
  26. package/dist/observe/core/identities.js +62 -0
  27. package/dist/observe/core/invariants.js +12 -0
  28. package/dist/observe/core/lanes.js +972 -0
  29. package/dist/observe/core/owner.js +371 -0
  30. package/dist/observe/core/scheduler.js +1157 -0
  31. package/dist/observe/core/truth.js +47 -0
  32. package/dist/observe/core/verdict.js +470 -0
  33. package/dist/observe/deferred.js +186 -0
  34. package/dist/observe/flatten.js +79 -0
  35. package/dist/observe/from.js +248 -0
  36. package/dist/observe/index.js +71 -0
  37. package/dist/observe/map.js +593 -0
  38. package/dist/observe/reveal.js +212 -0
  39. package/dist/observe/signals.js +717 -0
  40. package/dist/observe/store/affects.js +142 -0
  41. package/dist/observe/store/edges.js +39 -0
  42. package/dist/observe/store/hooks.js +16 -0
  43. package/dist/observe/store/index.js +47 -0
  44. package/dist/observe/store/optimistic.js +713 -0
  45. package/dist/observe/store/projection.js +345 -0
  46. package/dist/observe/store/reconcile.js +281 -0
  47. package/dist/observe/store/store.js +2127 -0
  48. package/dist/observe/store/storePath.js +103 -0
  49. package/dist/observe/store/target.js +46 -0
  50. package/dist/observe/store/types.js +83 -0
  51. package/dist/observe/store/utils.js +1063 -0
  52. package/dist/prod/affects-marks.js +86 -0
  53. package/dist/prod/affects.js +98 -112
  54. package/dist/prod/attribution.js +45 -0
  55. package/dist/prod/boundaries.js +578 -468
  56. package/dist/prod/core/action.js +92 -59
  57. package/dist/prod/core/async.js +522 -336
  58. package/dist/prod/core/attribution-hooks.js +3 -0
  59. package/dist/prod/core/constants.js +168 -44
  60. package/dist/prod/core/context.js +12 -16
  61. package/dist/prod/core/copies.js +10 -0
  62. package/dist/prod/core/core.js +1345 -627
  63. package/dist/prod/core/dev.js +123 -1
  64. package/dist/prod/core/effect.js +113 -80
  65. package/dist/prod/core/error-hooks.js +71 -0
  66. package/dist/prod/core/error.js +18 -4
  67. package/dist/prod/core/external.js +6 -7
  68. package/dist/prod/core/graph.js +119 -72
  69. package/dist/prod/core/heap.js +85 -109
  70. package/dist/prod/core/identities.js +62 -0
  71. package/dist/prod/core/invariants.js +1 -32
  72. package/dist/prod/core/lanes.js +931 -132
  73. package/dist/prod/core/owner.js +192 -129
  74. package/dist/prod/core/scheduler.js +948 -642
  75. package/dist/prod/core/truth.js +47 -0
  76. package/dist/prod/core/verdict.js +409 -420
  77. package/dist/prod/deferred.js +184 -0
  78. package/dist/prod/flatten.js +77 -0
  79. package/dist/prod/from.js +248 -0
  80. package/dist/prod/index.js +40 -16
  81. package/dist/prod/map.js +481 -211
  82. package/dist/prod/reveal.js +212 -0
  83. package/dist/prod/signals.js +401 -84
  84. package/dist/prod/store/affects.js +142 -0
  85. package/dist/prod/store/edges.js +39 -0
  86. package/dist/prod/store/hooks.js +16 -0
  87. package/dist/prod/store/index.js +27 -18
  88. package/dist/prod/store/optimistic.js +707 -0
  89. package/dist/prod/store/projection.js +331 -0
  90. package/dist/prod/store/reconcile.js +281 -0
  91. package/dist/prod/store/store.js +1952 -267
  92. package/dist/prod/store/storePath.js +1 -1
  93. package/dist/prod/store/target.js +43 -0
  94. package/dist/prod/store/types.js +83 -0
  95. package/dist/prod/store/utils.js +997 -138
  96. package/dist/types/affects-marks.d.ts +14 -0
  97. package/dist/types/affects.d.ts +12 -30
  98. package/dist/types/attribution.d.ts +19 -0
  99. package/dist/types/attribution.prod.d.ts +22 -0
  100. package/dist/types/boundaries.d.ts +99 -124
  101. package/dist/types/carved.d.ts +1 -0
  102. package/dist/types/core/action.d.ts +23 -9
  103. package/dist/types/core/async.d.ts +34 -6
  104. package/dist/types/core/attribution-costs.d.ts +35 -0
  105. package/dist/types/core/attribution-feedback.d.ts +133 -0
  106. package/dist/types/core/attribution-hooks.d.ts +307 -8
  107. package/dist/types/core/attribution-queries.d.ts +24 -0
  108. package/dist/types/core/attribution.d.ts +802 -72
  109. package/dist/types/core/constants.d.ts +195 -38
  110. package/dist/types/core/copies.d.ts +54 -0
  111. package/dist/types/core/core.d.ts +295 -65
  112. package/dist/types/core/dev.d.ts +509 -22
  113. package/dist/types/core/effect.d.ts +1 -1
  114. package/dist/types/core/error-hooks.d.ts +71 -0
  115. package/dist/types/core/error.d.ts +18 -1
  116. package/dist/types/core/graph.d.ts +40 -1
  117. package/dist/types/core/heap.d.ts +5 -5
  118. package/dist/types/core/identities.d.ts +17 -0
  119. package/dist/types/core/index.d.ts +11 -7
  120. package/dist/types/core/invariants.d.ts +1 -26
  121. package/dist/types/core/lanes.d.ts +74 -43
  122. package/dist/types/core/owner.d.ts +27 -9
  123. package/dist/types/core/scheduler.d.ts +353 -102
  124. package/dist/types/core/truth.d.ts +18 -0
  125. package/dist/types/core/types.d.ts +97 -71
  126. package/dist/types/core/verdict.d.ts +35 -0
  127. package/dist/types/deferred.d.ts +28 -0
  128. package/dist/types/flatten.d.ts +8 -0
  129. package/dist/types/from.d.ts +47 -0
  130. package/dist/types/index.d.ts +33 -7
  131. package/dist/types/map.d.ts +4 -2
  132. package/dist/types/reveal.d.ts +19 -0
  133. package/dist/types/signals.d.ts +196 -45
  134. package/dist/types/store/affects.d.ts +12 -0
  135. package/dist/types/store/edges.d.ts +9 -0
  136. package/dist/types/store/hooks.d.ts +62 -0
  137. package/dist/types/store/index.d.ts +42 -15
  138. package/dist/types/store/optimistic.d.ts +24 -45
  139. package/dist/types/store/projection.d.ts +17 -68
  140. package/dist/types/store/reconcile.d.ts +3 -46
  141. package/dist/types/store/store.d.ts +133 -136
  142. package/dist/types/store/storePath.d.ts +1 -1
  143. package/dist/types/store/target.d.ts +166 -0
  144. package/dist/types/store/types.d.ts +105 -0
  145. package/dist/types/store/utils.d.ts +188 -0
  146. package/package.json +31 -26
  147. package/dist/node.cjs +0 -8745
  148. package/dist/prod/core/optimistic.js +0 -265
  149. package/dist/prod/store/next/optimistic.js +0 -385
  150. package/dist/prod/store/next/projection.js +0 -172
  151. package/dist/prod/store/next/reconcile.js +0 -331
  152. package/dist/prod/store/next/store.js +0 -1499
  153. package/dist/prod/store/next/target.js +0 -20
  154. package/dist/types/core/optimistic.d.ts +0 -6
  155. package/dist/types/store/next/optimistic.d.ts +0 -20
  156. package/dist/types/store/next/projection.d.ts +0 -8
  157. package/dist/types/store/next/reconcile.d.ts +0 -3
  158. package/dist/types/store/next/store.d.ts +0 -77
  159. package/dist/types/store/next/target.d.ts +0 -117
  160. package/dist/types-cjs/affects.d.cts +0 -47
  161. package/dist/types-cjs/boundaries.d.cts +0 -175
  162. package/dist/types-cjs/core/action.d.cts +0 -64
  163. package/dist/types-cjs/core/async.d.cts +0 -21
  164. package/dist/types-cjs/core/attribution-hooks.d.cts +0 -52
  165. package/dist/types-cjs/core/attribution.d.cts +0 -186
  166. package/dist/types-cjs/core/constants.d.cts +0 -97
  167. package/dist/types-cjs/core/context.d.cts +0 -36
  168. package/dist/types-cjs/core/core.d.cts +0 -163
  169. package/dist/types-cjs/core/dev.d.cts +0 -81
  170. package/dist/types-cjs/core/effect.d.cts +0 -30
  171. package/dist/types-cjs/core/error.d.cts +0 -47
  172. package/dist/types-cjs/core/external.d.cts +0 -15
  173. package/dist/types-cjs/core/graph.d.cts +0 -6
  174. package/dist/types-cjs/core/heap.d.cts +0 -22
  175. package/dist/types-cjs/core/index.d.cts +0 -13
  176. package/dist/types-cjs/core/invariants.d.cts +0 -59
  177. package/dist/types-cjs/core/lanes.d.cts +0 -44
  178. package/dist/types-cjs/core/optimistic.d.cts +0 -6
  179. package/dist/types-cjs/core/owner.d.cts +0 -124
  180. package/dist/types-cjs/core/scheduler.d.cts +0 -180
  181. package/dist/types-cjs/core/types.d.cts +0 -192
  182. package/dist/types-cjs/core/verdict.d.cts +0 -2
  183. package/dist/types-cjs/index.d.cts +0 -10
  184. package/dist/types-cjs/map.d.cts +0 -69
  185. package/dist/types-cjs/package.json +0 -3
  186. package/dist/types-cjs/signals.d.cts +0 -624
  187. package/dist/types-cjs/store/index.d.cts +0 -19
  188. package/dist/types-cjs/store/next/optimistic.d.cts +0 -20
  189. package/dist/types-cjs/store/next/projection.d.cts +0 -8
  190. package/dist/types-cjs/store/next/reconcile.d.cts +0 -3
  191. package/dist/types-cjs/store/next/store.d.cts +0 -77
  192. package/dist/types-cjs/store/next/target.d.cts +0 -117
  193. package/dist/types-cjs/store/optimistic.d.cts +0 -45
  194. package/dist/types-cjs/store/projection.d.cts +0 -70
  195. package/dist/types-cjs/store/reconcile.d.cts +0 -46
  196. package/dist/types-cjs/store/store.d.cts +0 -138
  197. package/dist/types-cjs/store/storePath.d.cts +0 -58
  198. package/dist/types-cjs/store/utils.d.cts +0 -74
@@ -1,147 +1,946 @@
1
- import { NOT_PENDING, CONFIG_HAS_LANE } from "./constants.js";
2
-
3
- import { ext } from "./core.js";
4
-
5
- import { currentTransition, activeTransition } from "./scheduler.js";
6
-
7
- // Map from optimistic signal to its lane (reused for multiple writes to same signal)
8
- const signalLanes = new WeakMap;
9
-
10
- // All active lanes (for cleanup on transition completion)
11
- const activeLanes = new Set;
12
-
13
- /**
14
- * Get an existing lane for a signal or create a new one.
15
- * Reuses lane for multiple writes to the same signal.
16
- */ function getOrCreateLane(n) {
17
- let e = signalLanes.get(n);
18
- if (e) {
19
- return findLane(e);
20
- }
21
- // Detect parent lane: _parentSource chains from pendingSignal → pendingValueComputed → original.
22
- // The child lane should not merge with the parent lane.
23
- const i = n.o?.It;
24
- const t = i?.o?.Be;
25
- const r = t ? findLane(t) : null;
26
- e = {
27
- nn: n,
28
- Ae: new Set,
29
- en: [ [], [] ],
30
- tn: null,
31
- _e: activeTransition,
32
- rn: r
33
- };
34
- signalLanes.set(n, e);
35
- activeLanes.add(e);
36
- // A companion may have written before the owner's first optimistic write
37
- // (affects() as an action's first statement pokes the verdict companion of a
38
- // still lane-less node, #2887), leaving its lane parentless. Adopt it now:
39
- // parent-child is a property of the nodes, not of write order — otherwise
40
- // the owner's write merges the companion's subscribers into this lane and
41
- // their effects wait on its async instead of flushing immediately.
42
- adoptCompanionLane(n.o?.Ge, e);
43
- adoptCompanionLane(n.o?.ge, e);
44
- return e;
1
+ import { CONFIG_GUESS, NOT_PENDING, CONFIG_OVERRIDE, REACTIVE_DIRTY, REACTIVE_CHECK, REACTIVE_IN_HEAP, STATUS_PENDING, CONFIG_SLOT_NODE, REACTIVE_STAGED_READ, REACTIVE_DISPOSED, CONFIG_VERDICT, REACTIVE_PROBE_UNANSWERED, REACTIVE_LANE_DIRTY, CONFIG_HELD, REACTIVE_LANE_READ, STATUS_UNINITIALIZED, REACTIVE_RECOMPUTING_DEPS, CONFIG_AUTHORITATIVE, STATUS_ERROR, CONFIG_CHILDREN_FORBIDDEN, EFFECT_RENDER, REACTIVE_SCREEN_READ, REACTIVE_FRAME_READ, CONFIG_INPUTS_PUBLISHED, CONFIG_STAGED, REACTIVE_JOINED } from "./constants.js";
2
+
3
+ import { ext, bornInto, tracking, creatorReads, stagedRead } from "./core.js";
4
+
5
+ import { NotReadyError } from "./error.js";
6
+
7
+ import { removePendingSource, releaseFlightTeardown, handleAsync, notifyStatus, isThenable } from "./async.js";
8
+
9
+ import { laneValueOf } from "./truth.js";
10
+
11
+ import { enqueueSub } from "./heap.js";
12
+
13
+ import { schedule, question, nextQuestion, armGuessing, installLaneHooks, GlobalQueue, newTransaction, list, staleReader, resolveTx, txOf, commitPendingNode, ownFlights, stagedReaders, blocked, clock, insertSubs, laneDirty, flushTransaction, queuePendingNode, passLane, setPassLane, sameLane, releaseQueues, holdNode, reruns, merge } from "./scheduler.js";
14
+
15
+ // Lanes (plan sec. 28 replay, 2026-10-02; maintainer rulings 2026-10-01/02). A lane
16
+ // is "a new base of a transition": the sub-frame an optimistic write opens
17
+ // in the transition of the frame it is made in. It sees the screen plus its
18
+ // own guesses (plan sec. 19), breaks out of the parent's hold — its effects run now —
19
+ // and holds itself if its own derivations hit async (and, blocked, holds its
20
+ // parent). It ends when the parent lands: a guess reverts to the truth it
21
+ // covered, or lands as the truth that superseded it. A frame that does not
22
+ // park has nothing to be optimistic over: the write is void.
23
+ // Three places per node, each meaning one thing always: `_value` is the
24
+ // committed truth, `_pendingValue` a transaction's staging (the future), and
25
+ // `_x._lane` the lane's value — a written guess or a lane pass's derivation.
26
+ // The lane carries the state machine: `_shown` once it has revealed. The
27
+ // screen shows a lane's value once the lane has shown (`display`); a direct
28
+ // read sees it throughout (A17); an authoritative reader (`until`) sees the
29
+ // truth beneath it (Q3, 2026-10-02: "optimistic overrides are intentionally
30
+ // not part of authoritative truth").
31
+ // The seat of a pass is its node's (core.ts `recompute`): a node carrying a
32
+ // lane's derived value runs as the lane's whoever dirtied it; a derivation's
33
+ // tracked read of a lane's value moves its pass into the lane (`enterLane`);
34
+ // a leaf's never does — it reads the screen, a stale reader of a lane that
35
+ // has not shown (#3460). Lane work's values go to the lane slot (or, once
36
+ // the lane has shown, to its staging for the next reveal), its runs to the
37
+ // lane's queues.
38
+ // This module is the lane engine, installed on `GlobalQueue` when something
39
+ // imports it (`createOptimistic`, or verdict.ts for its verdict lanes). The
40
+ // core keeps only bit tests and `passLane`: a program with no optimism
41
+ // carries none of this.
42
+ /** Live lanes (parented). Scanned at every seam while non-empty. */
43
+ const lanes = [];
44
+
45
+ /** A pass left a shown slot the equality gate can no longer see (#3892). */ const LEFT_SHOWN = 1 << 20;
46
+
47
+ function newLane(e) {
48
+ const n = newTransaction(true, e);
49
+ lanes.push(n);
50
+ return n;
45
51
  }
46
52
 
47
- function adoptCompanionLane(n, e) {
48
- if (!n) return;
49
- const i = signalLanes.get(n);
50
- if (!i) return;
51
- const t = findLane(i);
52
- // Only the companion's own unmerged root is safely re-parentable: a root
53
- // that absorbed other lanes carries work that is not a child of this owner.
54
- if (t !== e && t.nn === n && !t.rn) t.rn = e;
53
+ /** What the screen shows for a lane's node: the lane's value once the lane
54
+ * has revealed, the committed truth before — NOT_PENDING when there is none
55
+ * (uninitialized, as `laneValueOf`): its read throws NotReady. */ function display(e) {
56
+ const n = e.T.P;
57
+ return e.T.Re.Ue && n !== NOT_PENDING ? n : e.m & STATUS_UNINITIALIZED ? NOT_PENDING : e.le;
55
58
  }
56
59
 
57
- /**
58
- * Union-find: find the root lane.
59
- */ function findLane(n) {
60
- while (n.tn) n = n.tn;
61
- return n;
60
+ /** Guesses written since the last seam (`[node, value, question, …]`).
61
+ * Applied at the seam, once the frame's verdict is known — the parent is
62
+ * the frame's transaction, and there is none to be optimistic over when the
63
+ * frame commits (the write is as if it never happened: nothing was
64
+ * applied). The lane's passes run in the next round of the same flush, so
65
+ * the guess is visible at flush like any write (A28). */ const pendingGuesses = [];
66
+
67
+ /** What the writer sees of a node: an unflushed guess to it, else the
68
+ * lane's value or the committed one — what an optimistic updater composes
69
+ * on (a store setter's draft too, store/optimistic.ts). */ function guessedValueOf(e) {
70
+ let n = pendingGuessOf(e);
71
+ return n !== NOT_PENDING || e.l & CONFIG_OVERRIDE && (n = laneValueOf(e)) !== NOT_PENDING ? n : e.le;
72
+ }
73
+
74
+ /** The unflushed guess to `n`, else NOT_PENDING. */ function pendingGuessOf(e) {
75
+ for (let n = pendingGuesses.length - 3; n >= 0; n -= 3) if (pendingGuesses[n] === e) return pendingGuesses[n + 1];
76
+ return NOT_PENDING;
77
+ }
78
+
79
+ /** This module's copy of scheduler.ts `guessing`: its readers here stay
80
+ * foldable when a bundler splits lanes.ts from scheduler.ts into separate
81
+ * chunks (a cross-chunk binding is not folded; the compiled live page). */ let guessed = false;
82
+
83
+ /** Guesses another action's lane took over (#4336): the node, its guess,
84
+ * the guess's lane, its question, the lane that took it. */ const kept = [];
85
+
86
+ /** Lanes a revert dissolved: the guesses they took come back at their
87
+ * parent's landing (`endLanes`). */ const reverted = /* @__PURE__ */ new WeakSet;
88
+
89
+ /** Lane `l` takes `n`'s guess (another action's), kept to come back if `l`
90
+ * reverts. Its readers saw the guess: they re-derive at the lane's reveal
91
+ * (and, a flight's, hold the lane while they would show it). `d`: a guess
92
+ * `l` takes without writing it (a store target's other slots) — the node
93
+ * shows its truth in `l`'s world until the guess comes back. */ function take(e, n, s) {
94
+ const t = e.T;
95
+ kept.push(e, t.P, t.Re, t.Ie, n);
96
+ rerun(e, n);
97
+ e.l &= s ? -10241 : ~CONFIG_GUESS;
98
+ if (s) t.Re = null, t.P = NOT_PENDING; else list(e, n);
62
99
  }
63
100
 
64
- /**
65
- * Merge two lanes when their dependency graphs overlap.
66
- */ function mergeLanes(n, e) {
67
- n = findLane(n);
68
- e = findLane(e);
69
- if (n === e) return n;
70
- e.tn = n;
71
- // Move (not copy) the merged lane's work: after the merge all routing goes
72
- // through findLane() to the root, so anything left behind here is dead —
73
- // and anything *added* here later is a routing bug (INV-5).
74
- for (const i of e.Ae) n.Ae.add(i);
75
- e.Ae.clear();
76
- n.en[0].push(...e.en[0]);
77
- n.en[1].push(...e.en[1]);
78
- e.en[0].length = 0;
79
- e.en[1].length = 0;
101
+ /** `n`'s readers are stale readers of `t` (re-derived at its landing). */ function rerun(e, n) {
102
+ for (let s = e.o; s !== null; s = s.t) staleReader(s.u, n);
103
+ }
104
+
105
+ function optimisticWrite(e, n) {
106
+ // What the user sees: an unflushed guess to the same node, else the lane's
107
+ // value or the committed one. The updater composes on it; guessing it
108
+ // again is no guess (the node's comparator, as for any write) — unless
109
+ // the node already carries one: the user re-asked, and the re-ask renews
110
+ // the guess's question and entangles its frame (#3347) without notifying.
111
+ const s = guessedValueOf(e);
112
+ if (typeof n === "function") n = n(s);
113
+ if (e.ye && e.ye(s, n) && !(e.l & CONFIG_GUESS)) return n;
114
+ pendingGuesses.push(e, n, question || nextQuestion());
115
+ armGuessing();
116
+ guessed = true;
117
+ schedule();
80
118
  return n;
81
119
  }
82
120
 
83
- /**
84
- * Resolve a node's lane: follow union-find chain, verify active, clear if stale.
85
- */ function resolveLane(n) {
86
- const e = n.o?.Be;
87
- if (!e) return undefined;
88
- const i = findLane(e);
89
- if (activeLanes.has(i)) return i;
90
- if (n.o !== null) n.o.Be = undefined;
91
- return undefined;
92
- }
93
-
94
- function resolveTransition(n) {
95
- // An active override answers with its owner, not its lane: lanes are
96
- // scheduling affinity and a shared subscriber merges them across
97
- // transactions (#2912) — the merged root's _transition would hand this
98
- // node's override to whichever action wrote last through the shared
99
- // reader. Chase merge chains; a dead owner settled through another path.
100
- if (hasActiveOverride(n) && n.o?.Et) {
101
- const e = ext(n).Et = currentTransition(n.o?.Et);
102
- if (e.an !== true) return e;
103
- if (n.o !== null) n.o.Et = null;
104
- }
105
- return resolveLane(n)?._e ?? n._e;
106
- }
107
-
108
- /**
109
- * Check if a node has an active optimistic override.
110
- */ function hasActiveOverride(n) {
111
- const e = n.o;
112
- return e !== null && e.De !== undefined && e.De !== NOT_PENDING;
113
- }
114
-
115
- /**
116
- * Assign or merge a lane onto a node. At convergence points (node already has
117
- * a different active lane), merge unless the node has an active override.
118
- */ function assignOrMergeLane(n, e) {
119
- const i = findLane(e);
120
- const t = n.o?.Be;
121
- if (t) {
122
- // If the subscriber's lane was merged into another lane, it's stale —
123
- // replace it with the new source lane instead of following the merge chain
124
- // (which would incorrectly merge the new lane into the old group)
125
- if (t.tn) {
126
- ext(n).Be = e;
127
- n.T |= CONFIG_HAS_LANE;
128
- return;
121
+ /** The seam: each guess becomes its node's lane value, in a lane — the
122
+ * node's own if it carries one (a later write into the same lane), else a
123
+ * new one under `parent` (the frame's transaction), under the hold already
124
+ * on the node (a guess over that transition's world — the truth it holds
125
+ * stays staged beneath, for the lane's end to commit), or under a
126
+ * transaction opened for the node's own in-flight refetch (the guess is
127
+ * that flight's observer — A17, "visible until its own fetch settles"). No
128
+ * parent: the guess is dropped. The truth is untouched; readers are
129
+ * dirtied for the next round. */
130
+ /** A guess's own truth is in flight: the node's own refetch — or, a store
131
+ * leaf's, its family's derive (the slot's flight; store/optimistic.ts
132
+ * installs the resolver). A17: the guess stands in for the flight. */ function inFlight(e) {
133
+ return e.m & STATUS_PENDING || e.l & CONFIG_SLOT_NODE && GlobalQueue.k?.(e);
134
+ }
135
+
136
+ function applyGuesses(e) {
137
+ let n = null;
138
+ for (let s = 0; s < pendingGuesses.length; s += 3) {
139
+ const t = pendingGuesses[s];
140
+ const l = pendingGuesses[s + 1];
141
+ let u = true;
142
+ // The frame already holding the slot: a guess over it is a second
143
+ // suggestion for the slot, and two cannot finish apart (A34 (1)) — the
144
+ // frames entangle.
145
+ let i = null;
146
+ if (t.l & CONFIG_OVERRIDE) {
147
+ // A lane's node already: a guess re-asked, or a derivation guessed
148
+ // over (its staging is void — the guess is the value now). The same
149
+ // value re-asked renews the question; nothing to notify.
150
+ u = !t.ye || !t.ye(laneValueOf(t), l);
151
+ if (!(t.l & CONFIG_GUESS)) {
152
+ t.ue = NOT_PENDING;
153
+ t.l |= CONFIG_GUESS;
154
+ }
155
+ t.T.P = l;
156
+ i = txOf(t)._parent;
157
+ } else {
158
+ let s;
159
+ // A held node: a truth staged there, or what a corrected guess showed.
160
+ // The guess composes on it, so it ends with that hold — and with its
161
+ // own frame's (F-11): it lands only when both have (the board's rapid
162
+ // adds — a later add's row reverted with an earlier add's landing).
163
+ if (t.l & CONFIG_HELD) s = newLane(i = txOf(t)); else {
164
+ if (e === null && inFlight(t)) e = newTransaction(false);
165
+ if (e === null) continue;
166
+ s = n ??= newLane(e);
167
+ }
168
+ // (A guess equal to a truth staged beneath it is confirmed at birth —
169
+ // A24 — and still re-derives its readers as the lane's: the truth's
170
+ // derivations are the transaction's world, the lane's are the
171
+ // screen's plus the guess (plan sec. 19) — a derivation reading a held write
172
+ // beside the guess must not show it. Two flights for one input, when
173
+ // the worlds coincide, is the price.)
174
+ ext(t).P = l;
175
+ t.l |= CONFIG_OVERRIDE | CONFIG_GUESS;
176
+ list(t, s);
177
+ }
178
+ if (e !== null && i !== null) merge(e, i);
179
+ ext(t).Ie = pendingGuesses[s + 2];
180
+ if (u) {
181
+ // The lane's members re-derive as its work (REACTIVE_LANE_DIRTY): a
182
+ // blocked lane's re-guess does not re-run its render effects as stale
183
+ // readers republishing the committed view (#3460).
184
+ insertSubs(t);
185
+ laneDirty(t, txOf(t));
186
+ }
187
+ }
188
+ pendingGuesses.length = 0;
189
+ }
190
+
191
+ /** The running pass read lane `l`'s work as a derivation: it is `l`'s — or,
192
+ * already another lane's, the frame it computes derives from both guesses
193
+ * and cannot show one without the other (#3335, A15 for lanes): the two
194
+ * lanes are linked — one reveal unit, each blocked while any is — while
195
+ * their lifetimes stay their own (#2912: a guess reverts with its own
196
+ * action, not with the one it shares a reader with). A nested lane reading
197
+ * through an ancestor's guess stays its own (the screen plus its own
198
+ * guesses). */ function enterLane(e, n) {
199
+ const s = n.R |= REACTIVE_LANE_READ, t = passLane;
200
+ if (t === null) {
201
+ const t = e._parent.Pe === e;
202
+ // A verdict lane's value (a memo of `latest` / `isPending`, F-6) read by
203
+ // a derivation that already read the frame's staging or joined its
204
+ // hold, or by any pass a pass that did is creating: the verdict read
205
+ // does not break it out — it stays the frame's, as the same read inline
206
+ // does (verdict.ts `markVerdictReader`, `route`; D-25, D-26). An
207
+ // effect's own reads do not count (its `_type`, 1–3, carries neither bit).
208
+ if (!(t && creatorReads(n, n.i || s))) {
209
+ setPassLane(e);
210
+ // The pass read a held write before its first lane read (it joined the
211
+ // frame's future as mainline would): lane work sees the screen — the
212
+ // seam re-derives it on the committed world next round (`stagedReaders`,
213
+ // the park's repair), as it does a lane pass that read a staging. Not a
214
+ // pass whose held reads were all of nodes born held (no staged read,
215
+ // `stagedRead`): it has no committed world to re-derive on (#3969).
216
+ // (A pass not joined: a held write beside a guess, #4336; a leaf of a
217
+ // verdict lane — its plain reads are the screen's, D-26 `[s(), L()]`.)
218
+ if (s & REACTIVE_STAGED_READ && (guessed || t || s & REACTIVE_JOINED)) stagedRead(n);
219
+ }
220
+ } else if (sameLane(t, e)) setPassLane(e); else if (!under(t, e)) {
221
+ if (!under(e, t)) linkLanes(t, e);
222
+ setPassLane(e);
223
+ }
224
+ }
225
+
226
+ /** Is `l` nested under `a` (an ancestor lane)? */ function under(e, n) {
227
+ for (let s = e._parent; s !== null && s.P; s = s._parent) if (s === n) return true;
228
+ return false;
229
+ }
230
+
231
+ /** One link group (a shared array) for both lanes' groups. */ function linkLanes(e, n) {
232
+ const s = e.en ?? (e.en = [ e ]);
233
+ const t = n.en;
234
+ if (t === s) return;
235
+ if (t === null) {
236
+ s.push(n);
237
+ n.en = s;
238
+ } else for (let e = 0; e < t.length; e++) {
239
+ s.push(t[e]);
240
+ t[e].en = s;
241
+ }
242
+ }
243
+
244
+ /** A linked lane blocked on its own account blocks the group — `blocked(k)`
245
+ * without the group recursion. (A guess in `k` whose own truth is in flight
246
+ * blocks `k`'s parent, not `k` — nor, through the link, `l`: the guess
247
+ * shows, A17.) */ function linkBlocked(e) {
248
+ const n = e.en;
249
+ if (n !== null) for (let s = 0; s < n.length; s++) {
250
+ const t = n[s];
251
+ if (t !== e && (t.tt !== 0 || ownFlights(t) || nestedBlocked(t))) return true;
252
+ }
253
+ return false;
254
+ }
255
+
256
+ function unlink(e) {
257
+ const n = e.en;
258
+ if (n === null) return;
259
+ const s = n.indexOf(e);
260
+ if (s !== -1) n.splice(s, 1);
261
+ e.en = null;
262
+ }
263
+
264
+ /** Verdicts (maintainer, 2026-10-01): `isPending` and `latest` are
265
+ * optimistic state the system supplies — a verdict is a guess ("pending,
266
+ * until this lands"; "the proposal is the value") decided at the seam like
267
+ * a user's, and its readers break out of the hold the same way: work of a
268
+ * lane under the holder, shown now, re-derived at the landing, ending with
269
+ * it. Judged at the seam like any lane: blocked while a verdict reader's
270
+ * own derivation is in flight (lane rule 3), shown otherwise. */ function verdictLane(e) {
271
+ return e.Pe ??= newLane(e);
272
+ }
273
+
274
+ /** A lane pass's node (core.ts `recompute`, before its staging; a pending
275
+ * propagation under a lane pass, async.ts): listed, carrying the lane's
276
+ * value from now (a derivation of a guess — its readers become lane work).
277
+ * Entering the lane supersedes a frame staging the node carried: this
278
+ * pass's answer replaces it, and the frame's hold on it is over. An
279
+ * effect's value slot is private (no lane value). A pass in a lane's seat
280
+ * that read none of the lane's world has left it (false): its result is the
281
+ * frame's — a derivation whose branch no longer reaches the guess — and no
282
+ * hold the lane took over from a transaction stays on it (#3698: lane work
283
+ * never makes its node transaction work; a born-held effect's hold went to
284
+ * the lane). A pass interrupted before it got there (pending, errored) did
285
+ * not leave (A30: it never got there). A first pass under a lane is the
286
+ * lane's (ruling A); a guess is written, not derived — it never leaves this
287
+ * way. `errored`: the pass has no answer — or, a lane pass's pending
288
+ * propagation (async.ts `propagateStatus`), the node gone pending. */ function laneStage(e, n, s, t) {
289
+ if (!(s || t || e.R & REACTIVE_LANE_READ || e.l & CONFIG_GUESS)) {
290
+ const n = e.T;
291
+ if (n !== null) {
292
+ const s = n.Re;
293
+ if (s?.P) {
294
+ // Cleared before equality, so a return to the committed value
295
+ // notifies nobody. The seam wakes it (#3892) — always for a pass
296
+ // outside any transaction's flush: its value is the screen's now
297
+ // (#4367). While a transaction's flush runs the pass and the lane's
298
+ // frame is still held, what the screen shows stays the screen until
299
+ // the landing, and `_value` takes it (as `dissolveLane` keeps a shown
300
+ // lane's), so this pass's answer — the frame's — is a change against
301
+ // what is seen and reaches the screen with the frame's commit. (Only
302
+ // a lane is ever `_shown`.)
303
+ if (s.Ue) if (!flushTransaction || !blocked(resolveTx(s._parent))) e.R |= LEFT_SHOWN; else e.le = display(e);
304
+ n.Re = null;
305
+ }
306
+ n.P = NOT_PENDING;
307
+ }
308
+ e.l &= -1050881;
309
+ return false;
310
+ }
311
+ if (!e.i) {
312
+ if (!(e.l & CONFIG_OVERRIDE)) {
313
+ e.ue = NOT_PENDING;
314
+ e.l = e.l & -1048833 | CONFIG_OVERRIDE;
315
+ ext(e);
316
+ }
317
+ // A written guess whose own pass is the lane's work — its source is a
318
+ // derivation of another guess (a guess over `config().courier` under a
319
+ // country guess) — is confirmed or corrected by the lane: a derivation
320
+ // of the lane from here (its value the lane's, its fate the lane's), no
321
+ // longer a written guess. A pass with no answer (pending, errored)
322
+ // leaves the guess.
323
+ // Nor a pass of another action's guess: the re-ask is this lane's new
324
+ // question, which the guess (over the old one) does not answer — the
325
+ // lane waits for its own answer (F-1, F-6, #4336). (A guess of the
326
+ // lane's own action, D-33's entangled slot, still stands in.)
327
+ // (Read behind `guessed`: a bundle without optimism drops the reads.)
328
+ if (guessed && e.l & CONFIG_GUESS && e.T.Re?.P && resolveTx(e.T.Re._parent) !== resolveTx(n._parent)) take(e, n); else if (!t) e.l &= ~CONFIG_GUESS;
329
+ }
330
+ // A leaf has no lane value to seat it (`recompute`): one left waiting on
331
+ // the lane's flight runs its next pass as the lane's — the landing that
332
+ // wakes it is the lane's re-staging (A31), and the lane holds its render
333
+ // effects until its derivations land (A17; #3766, F5). Not a leaf whose
334
+ // seat is its frame's, reached by a propagation from a node the screen has
335
+ // a value of: one a transaction holds (born held — its frame waits on it,
336
+ // A29), or one whose own mainline pass is running (it pulled the node;
337
+ // `laneRead` decides — its frame holds). Its pending is the frame's: queued
338
+ // for the commit sweep as mainline's (async.ts). A node born in the lane
339
+ // has nothing on screen: its leaf waits as the lane's.
340
+ else if (t) {
341
+ if (t !== true && !(t.m & STATUS_UNINITIALIZED) && (e.l & CONFIG_HELD || e.R & REACTIVE_RECOMPUTING_DEPS) && !e.T?.Re?.P) {
342
+ queuePendingNode(e);
343
+ return false;
344
+ }
345
+ e.R |= REACTIVE_LANE_DIRTY;
346
+ }
347
+ list(e, n);
348
+ return true;
349
+ }
350
+
351
+ /** The truth arrived for a written guess (A18): a correction dissolves the
352
+ * lane — the guess and everything derived from it is void, the truth is
353
+ * the parent's held write and the graph re-derives from it there, one frame
354
+ * at the parent's landing — while the display keeps what it shows until
355
+ * then. A confirmation is silent (A17): the truth stays staged beneath the
356
+ * guess for the parent's commit, the guess stays the value; only a reader
357
+ * of the truth (CONFIG_AUTHORITATIVE) is told its view changed. Either way
358
+ * the parent takes this node, not the tick that carried the truth (D-33):
359
+ * one landing answering two actions' guesses (a store re-ask over two
360
+ * rows) must not tie them together; a pass that derives from the held
361
+ * truth joins the parent on its own (`joinPass`). */
362
+ /** The correction round is replacing a guess with the value it covered (no
363
+ * landing beneath it): observe's "reverted"; the lane gives back the
364
+ * guesses it took (#4336, `endLanes`). */ let reverting = false;
365
+
366
+ function supersede(e, n, s) {
367
+ const t = txOf(e);
368
+ // Resolved: the parent may have merged into another transaction since the
369
+ // lane opened (two actions guessing one slot entangle, A34 (1)) — the
370
+ // truth is held by the transaction that lands, not the merged-away one.
371
+ const l = resolveTx(t._parent ?? t);
372
+ // A store row answered by a new object the store would reconcile into
373
+ // the guessed one unchanged is an echo, not a correction (#3898): the
374
+ // server's object never matches the guess by reference.
375
+ if (s && e.l & CONFIG_SLOT_NODE && GlobalQueue.nn?.(e.T.P, n)) s = false;
376
+ if (s) {
377
+ dissolveLane(t, l, e);
378
+ if (guessed && reverting) reverted.add(t);
379
+ // What the screen showed stays the screen until the parent lands (A18
380
+ // (c): display and untracked reads keep the override until the commit).
381
+ if (t.Ue) e.le = e.T.P;
382
+ e.l &= -10241;
383
+ e.T.P = NOT_PENDING;
384
+ holdNode(e, l);
385
+ if (e.o !== null) insertSubs(e);
386
+ } else {
387
+ e.l |= CONFIG_HELD;
388
+ // A confirmation is silent (A17); only truth readers are told.
389
+ GlobalQueue.sn?.(t);
390
+ }
391
+ e.ue = n;
392
+ }
393
+
394
+ /** A lane's end, two ways. `into === null`: the parent landed — the lane's
395
+ * values are the truth now: a guess lands the truth staged beneath it or
396
+ * reverts to the one it covered (`_value`, untouched by the guess); a
397
+ * derivation's latest value commits (its frame with it); what the screen
398
+ * showed and changes notifies. Otherwise the lane dissolves into `into`
399
+ * (the parent, on a correction): its values are void — what it showed stays
400
+ * the screen (`_value` takes it, so the parent's re-derivation compares
401
+ * against what is seen), a truth staged beneath a guess is the parent's to
402
+ * land, and the runs it held (showing the void guess) are dropped: the
403
+ * parent's re-derivation makes the runs that show. */ function dissolveLane(e, n, s) {
404
+ const t = lanes.indexOf(e);
405
+ if (t !== -1) lanes.splice(t, 1);
406
+ unlink(e);
407
+ // Its verdicts end with it (a correction's dissolution reaches here before
408
+ // `endLanes` would): the readers re-derive from the truth's notification.
409
+ const l = e.Pe;
410
+ if (l !== null) {
411
+ e.Pe = null;
412
+ if (lanes.indexOf(l) !== -1) dissolveLane(l, null);
413
+ }
414
+ // First loads this dissolution leaves loading (below).
415
+ const u = [];
416
+ for (let t = 0; t < e.tn.length; t++) {
417
+ const l = e.tn[t];
418
+ const i = l.T;
419
+ if (l === s || i.Re !== e) continue;
420
+ const r = l.i;
421
+ const o = l.l & CONFIG_GUESS;
422
+ const E = i.P;
423
+ // What the screen shows of it (NOT_PENDING: nothing — a lane pass that
424
+ // errored or pends staged no value), and the lane's latest.
425
+ const a = e.Ue && !r ? E : l.le;
426
+ const f = laneValueOf(l);
427
+ i.P = NOT_PENDING;
428
+ l.l &= -10241;
429
+ if (n === null) {
430
+ // A derivation the revert re-derives (dirtied by the guess's
431
+ // notification — listed before it), or one still in flight, shows the
432
+ // lane's answer beside inputs that are the truth now: a fresh reader
433
+ // of its flight observes it (#3648, #3651; #3305's commit beneath a
434
+ // flight).
435
+ // Not a first load the lane produced nothing for whose own flight is
436
+ // up, nor one pending on such a load kept here (an identity memo of
437
+ // it, a derived store's derive): committing its empty `_value` would
438
+ // initialize it as `undefined`, which `latest()` would serve and
439
+ // `isPending()` call pending. It stays loading until its flight
440
+ // answers (D-22, A19 exc. 1; async-gen 3289 #929, 91501 #504, #156).
441
+ i.Re = null;
442
+ if (!r && !o) E === NOT_PENDING && (l.m & (STATUS_UNINITIALIZED | STATUS_PENDING)) === (STATUS_UNINITIALIZED | STATUS_PENDING) && (i.Ee || u.some(e => i.se?.has(e))) ? u.push(l) : l.ue = f;
443
+ commitPendingNode(l);
444
+ if (!r) {
445
+ if (l.R & (REACTIVE_IN_HEAP | REACTIVE_DIRTY | REACTIVE_CHECK) || l.m & STATUS_PENDING) l.l |= CONFIG_INPUTS_PUBLISHED;
446
+ if (a !== NOT_PENDING && (!l.ye || !l.ye(a, l.le))) insertSubs(l);
447
+ }
448
+ // A stale reader's own error — its pass (a memo's or a render
449
+ // effect's) threw over the committed value of what the parent held
450
+ // (A10), served as the screen — is no answer of the world landing now:
451
+ // it re-derives on it (A15; D-39, the landing is the new answer). The
452
+ // landing's `reruns` skips an errored reader: its error is an errored
453
+ // source's (#3945).
454
+ if (l.R & REACTIVE_FRAME_READ && l.m & STATUS_ERROR && i.U.source === l) enqueueSub(l);
455
+ } else if (o) {
456
+ // A guess of a dissolving lane: its truth — a landing held beneath it,
457
+ // else the value it covered — is the parent's to land, and its readers
458
+ // re-derive from it there. What the screen showed stays the screen
459
+ // until then (A18 (c)).
460
+ if (l.ue === NOT_PENDING) l.ue = covered(l);
461
+ if (e.Ue) l.le = E;
462
+ holdNode(l, n);
463
+ insertSubs(l);
464
+ } else {
465
+ // A correction: the lane's derivations are void. Shown, what the
466
+ // screen showed stays the screen (committed, inputs published — every
467
+ // one re-derives); never shown, nothing of it reached the screen (a
468
+ // node born in the lane stays uninitialized; its frame goes). One in
469
+ // flight is asking the void world's question: its landing is nobody's
470
+ // answer — it re-asks from the truth (whose notification may not reach
471
+ // it: an input's truth equal to its committed value is silent).
472
+ i.Re = null;
473
+ if (!r) {
474
+ if (a !== NOT_PENDING && e.Ue) l.ue = a;
475
+ if (l.m & STATUS_PENDING) {
476
+ i.Ee = null;
477
+ enqueueSub(l);
478
+ }
479
+ }
480
+ if (e.Ue) {
481
+ commitPendingNode(l);
482
+ if (!r) l.l |= CONFIG_INPUTS_PUBLISHED;
483
+ } else {
484
+ if (i.me !== null || i.Le !== null) GlobalQueue.Ce(l, false, true);
485
+ l.l &= -1048961;
486
+ }
487
+ }
488
+ }
489
+ // The parent landed: the runs the lane held (blocked on its own judgment
490
+ // alone — a zombie it could not dispose) are the landing's. A correction
491
+ // of a SHOWN lane keeps its runs too: "what it showed stays the screen"
492
+ // means the runs this round's lane passes queued (the body-end seam judges
493
+ // before the lane seam would have released them) must reach the screen —
494
+ // their derivations' values are the committed ones now, and a
495
+ // re-derivation that lands on the same value notifies nobody (a mapArray
496
+ // whose rows the lane pass already built). A never-shown lane's runs are
497
+ // void: nothing of it reached the screen. So are the runs a blocked lane
498
+ // parked: they show a re-guess the seam never revealed, beside derivations
499
+ // that keep what the screen showed.
500
+ if (n === null || e.Ue && !e.ln) releaseQueues(e); else e.un[0].length = e.un[1].length = 0;
501
+ }
502
+
503
+ /** Lanes. A lane's node is read by its reader's kind: an authoritative
504
+ * reader (`until`) sees the truth — staged beneath a guess, else committed
505
+ * — and is no lane's; an untracked read sees the lane's latest value (A17:
506
+ * "direct read shows optimistic"; A28); a children-forbidden reader sees
507
+ * the frame (A32). A render effect in the frame's seat reading a lane the
508
+ * seam found blocked, or a member whose own flight is up (held or not — the
509
+ * lane-membership ruling, 2026-10-05), sees the screen, re-derived at the
510
+ * reveal (#3460's stale reader) — or, the node a
511
+ * flight that has never shown (nothing to show), waits on it: its own frame
512
+ * holds (A15, #3334), not the lane's parent. Any other tracked reader is
513
+ * the lane's work from this read — a derivation; a leaf reading a lane that
514
+ * has shown, or one the seam has not judged yet (its run waits on the
515
+ * verdict: released if the lane shows, held if it blocks) — and sees the
516
+ * lane's latest. NOT_PENDING falls through: lane work's read of a pending
517
+ * member throws like any. A verdict reader entering a lane the seam has
518
+ * not judged reads ahead of it like a staging read: if the seam holds the
519
+ * lane, the pass re-derives on the screen (`entered`, #4284) — `latest()`
520
+ * beside the lane's nodes tears ahead of the hold however the reads are
521
+ * grouped into effects. */ function laneRead(e, n) {
522
+ const s = n.l & CONFIG_GUESS;
523
+ const t = txOf(n);
524
+ // A lane a correction folded under (D-34): store/optimistic.ts reads it.
525
+ // Before the authoritative arm: an `until` outside the lane reads the
526
+ // same truth there, and joins the hold it folded into — its posture over
527
+ // a foreign hold (D-31), which the truth read alone would not take.
528
+ const l = e !== null && t.folded;
529
+ if (l) {
530
+ const s = l(e, n);
531
+ if (s !== NOT_PENDING) return s;
532
+ }
533
+ if (e !== null && e.l & CONFIG_AUTHORITATIVE) return GlobalQueue.rn(n);
534
+ const u = n.m;
535
+ // An errored member's lane value predates its error; the error is the answer (#4106).
536
+ if (!s && u & STATUS_ERROR) return NOT_PENDING;
537
+ if (e === null) return laneValueOf(n);
538
+ const i = !s && u & STATUS_PENDING;
539
+ if (!tracking || e.l & CONFIG_CHILDREN_FORBIDDEN) {
540
+ // An untracked read inside lane work derives from the lane like a
541
+ // tracked one, minus the subscription — `untrack` is about
542
+ // dependencies, not about which world a pass derives from (a mapper's
543
+ // row reads under its root, store/map): the pass enters the lane (two
544
+ // lanes read by one pass link, as for tracked reads). Outside lane
545
+ // work, the screen.
546
+ if (passLane === null || e.l & CONFIG_CHILDREN_FORBIDDEN) return display(n);
547
+ } else if (e.i === EFFECT_RENDER) {
548
+ // A flight whose value has never shown: nothing to show — the leaf
549
+ // waits on it, and its own frame holds (A15, #3334), not the lane's
550
+ // parent. The landing lands the frame: its own pass (the flush joined
551
+ // its transaction) reads the answer it waited on — the lane's staging,
552
+ // revealed at this seam.
553
+ const l = i && n.T.P === NOT_PENDING;
554
+ // D-28: a leaf a verdict read moved into the lane still throws on such
555
+ // a flight — the pass leaves the lane, and its frame holds as if the
556
+ // read had come first (S-39, #4275). Nor does a verdict lane's seat carry
557
+ // the leaf into another lane (no link): it reads that lane as from the
558
+ // frame's seat (#4284).
559
+ if ((l || passLane !== t) && passLane?._parent.Pe === passLane) setPassLane(null);
560
+ if (passLane === null || !sameLane(passLane, t)) {
561
+ // (A lane that has never shown: the screen is the committed value.)
562
+ if (l && t.Ue) return NOT_PENDING;
563
+ if (!s && n.ue !== NOT_PENDING && e.l & CONFIG_HELD && flushTransaction !== null && resolveTx(flushTransaction) === txOf(e)) return n.ue;
564
+ if (t.ln || i) {
565
+ // Re-derived at the reveal; once per pass (the pass may also be a stale
566
+ // reader of a transaction, REACTIVE_FRAME_READ — both reruns apply).
567
+ // Before the throw below: a leaf that waits on a lane that has never
568
+ // shown has no flight to settle it — only the reveal re-derives it,
569
+ // and its pending holds its frame until then (#4338).
570
+ if (!(e.R & REACTIVE_SCREEN_READ)) {
571
+ e.R |= REACTIVE_FRAME_READ | REACTIVE_SCREEN_READ;
572
+ t.En.push(e);
573
+ }
574
+ // Nothing on screen yet (uninitialized: `display` is NOT_PENDING).
575
+ const s = display(n);
576
+ if (s === NOT_PENDING) throw new NotReadyError(null);
577
+ return s;
578
+ }
579
+ // A verdict reader reads ahead of the seam's verdict: re-derived on the
580
+ // screen if the lane holds (#4284).
581
+ if (e.l & CONFIG_VERDICT && t._parent.Pe !== t) entered.push(e);
582
+ }
583
+ }
584
+ enterLane(t, e);
585
+ return i ? NOT_PENDING : laneValueOf(n);
586
+ }
587
+
588
+ /** The value a guess covered: the node's committed value — a store slot's
589
+ * asked of the store (a chained link follows the inner store's commits). */ function covered(e) {
590
+ return e.l & CONFIG_SLOT_NODE && GlobalQueue.an !== undefined ? GlobalQueue.an(e) : e.le;
591
+ }
592
+
593
+ /** A guess in `l` whose own truth is in flight (its refetch — authoritative:
594
+ * the landing supersedes, not the body's end). */ function guessFlights(e) {
595
+ for (let n = 0; n < e.tn.length; n++) {
596
+ const s = e.tn[n];
597
+ if (s.l & CONFIG_GUESS && s.T.Re === e && inFlight(s)) return true;
598
+ }
599
+ return false;
600
+ }
601
+
602
+ /** The seam's verdict on a lane. Blocked — its own flight is up — nothing
603
+ * moves: the screen keeps what it shows, the lane's runs wait. Unblocked,
604
+ * the lane shows: its values are the screen from now (`_shown`), the
605
+ * staging its passes made since the last reveal is promoted, their frames
606
+ * (children) apply, the stale readers re-derive (#3460), its runs go. */
607
+ /** A18 body-end corollary (#3427), at the seam before the park decision
608
+ * (the guesses' own passes have run; a correction's re-derivations run in
609
+ * one more pure round and are the parent's flights before it is judged —
610
+ * #3409: the indicators clear together): the action body having returned,
611
+ * a guess whose own truth is not in flight has no answer coming — the truth
612
+ * beneath it is its truth, and the correction starts now rather than at the
613
+ * lane's flight. (A guess whose own refetch is up is superseded by its
614
+ * landing.) True when a lane was judged. */ function laneCorrections() {
615
+ let e = false;
616
+ const n = lanes.slice();
617
+ for (let s = 0; s < n.length; s++) {
618
+ const t = n[s];
619
+ if (lanes.indexOf(t) === -1) continue;
620
+ const l = resolveTx(t._parent);
621
+ if (!l.nt || l.tt !== 0 || l.P || ownFlights(l) || guessFlights(t)) continue;
622
+ e = true;
623
+ // Each guess's truth: the one beneath it (a landing held there), else
624
+ // the one it covered. (A correction dissolves the lane — the others are
625
+ // re-homed with theirs, `dissolveLane`.)
626
+ for (let e = 0; e < t.tn.length && lanes.indexOf(t) !== -1; e++) {
627
+ const n = t.tn[e];
628
+ if (n.l & CONFIG_GUESS && n.T.Re === t) {
629
+ const e = n.ue !== NOT_PENDING ? n.ue : covered(n);
630
+ if (guessed) reverting = n.ue === NOT_PENDING;
631
+ supersede(n, e, !n.ye || !n.ye(n.T.P, e));
632
+ if (guessed) reverting = false;
633
+ }
634
+ }
635
+ }
636
+ return e;
637
+ }
638
+
639
+ function laneSeam(e, n) {
640
+ // Blocked — or one of its passes read a write the frame holds this seam:
641
+ // its runs wait, the pass re-derives on the screen next round.
642
+ if (n || blocked(e)) {
643
+ e.ln = true;
644
+ return;
645
+ }
646
+ e.ln = false;
647
+ e.Ue = true;
648
+ if (reruns(e)) revealing.push(resolveTx(e._parent));
649
+ for (let n = 0; n < e.tn.length; n++) {
650
+ const s = e.tn[n];
651
+ if (s.R & LEFT_SHOWN) {
652
+ s.R ^= LEFT_SHOWN;
653
+ insertSubs(s);
654
+ }
655
+ const t = s.T;
656
+ if (t.Re !== e) continue;
657
+ if (!(s.l & CONFIG_GUESS) && !s.i && s.ue !== NOT_PENDING) {
658
+ t.P = s.ue;
659
+ s.ue = NOT_PENDING;
129
660
  }
130
- const r = findLane(t);
131
- if (activeLanes.has(r)) {
132
- if (r !== i && !hasActiveOverride(n)) {
133
- // Parent-child lanes stay independent so isPending resolves without
134
- // waiting for the parent's async. The child keeps ownership.
135
- if (i.rn && findLane(i.rn) === r) {
136
- ext(n).Be = e;
137
- n.T |= CONFIG_HAS_LANE;
138
- } else if (r.rn && findLane(r.rn) === i) ; else mergeLanes(i, r);
661
+ // The frame this pass built is the screen's now; the one it replaced
662
+ // goes (as `commitPendingNode` retires a committed pass's).
663
+ if (t.me !== null || t.Le !== null) GlobalQueue.Ce(s, false, true);
664
+ s.l &= ~CONFIG_STAGED;
665
+ }
666
+ releaseQueues(e);
667
+ }
668
+
669
+ /** The parent landed: its lanes end, nested first. (None is blocked: a
670
+ * blocked lane blocks its parent.) */ function endLanes(e) {
671
+ // A revert landing (#4336): the guesses its lane took from another action
672
+ // that is still out come back in this frame, over the truth it lands —
673
+ // its readers re-derive with the landing (one frame, no bare truth
674
+ // between). Taken by a later lane since, a node stays that lane's.
675
+ if (guessed) for (let n = kept.length - 5; n >= 0; n -= 5) if (resolveTx(kept[n + 4]._parent) === e) {
676
+ let [s, t, l, u, i] = kept.splice(n, 5);
677
+ // (A store slot's node now: the one taken, or a read's since.)
678
+ if (reverted.has(i) && lanes.includes(l) && (!(s.l & CONFIG_SLOT_NODE) || (s = GlobalQueue.fn(s, true)))) {
679
+ const n = ext(s);
680
+ if (n.Re === null || txOf(s) === e) {
681
+ commitPendingNode(s);
682
+ n.P = t;
683
+ n.Ie = u;
684
+ s.l |= CONFIG_OVERRIDE | CONFIG_GUESS;
685
+ list(s, l);
686
+ rerun(s, e);
139
687
  }
140
- return;
141
688
  }
142
689
  }
143
- ext(n).Be = e;
144
- n.T |= CONFIG_HAS_LANE;
690
+ for (let n = lanes.length - 1; n >= 0; n--) {
691
+ const s = lanes[n];
692
+ if (resolveTx(s._parent) !== e) continue;
693
+ endLanes(s);
694
+ dissolveLane(s, null);
695
+ }
145
696
  }
146
697
 
147
- export { activeLanes, assignOrMergeLane, findLane, getOrCreateLane, hasActiveOverride, mergeLanes, resolveLane, resolveTransition, signalLanes };
698
+ /** A blocked lane blocks its parent (maintainer, 2026-10-01): the lane's
699
+ * pending work derives from the frame's write through the guess, so the
700
+ * frame is not complete without it (A15) — landing it would commit the write
701
+ * beside a derivation still showing the old one. A guess whose own flight is
702
+ * up likewise: the question was asked in this frame. */ function lanesBlocked(e) {
703
+ return e.P && linkBlocked(e) || nestedBlocked(e);
704
+ }
705
+
706
+ /** Parents whose lane revealed this seam with readers to re-derive there
707
+ * (`laneSeam`): the lane shows ahead of its parent (F-6), so the parent lands
708
+ * a round later — after those readers have shown the lane's answer — even
709
+ * when nothing else holds it (#4393). */ const revealing = [];
710
+
711
+ /** The lanes under `t` (its own; a link group's are each other's). */ function nestedBlocked(e) {
712
+ if (revealing.indexOf(e) !== -1) return true;
713
+ for (let n = 0; n < lanes.length; n++) {
714
+ const s = lanes[n];
715
+ if (resolveTx(s._parent) !== e) continue;
716
+ if (blocked(s) || guessFlights(s)) return true;
717
+ }
718
+ return false;
719
+ }
720
+
721
+ /** A write landing on a lane's node (core.ts `setSignal`: a user's write, an
722
+ * async landing). On a guess it is its truth (A18 — an async guess's own
723
+ * landing), judged against the guess. On a derivation it is the lane's
724
+ * latest: its staging once the lane has shown (promoted at the next
725
+ * reveal), its slot before; the lane's members re-derive as its work. */ function laneWrite(e, n) {
726
+ // (A store slot's guess its derive's re-ask in another action's lane
727
+ // writes is that lane's derivation from here — store `_slotTake`, #4336.)
728
+ if (e.l & CONFIG_GUESS && !(guessed && GlobalQueue.fn?.(e))) {
729
+ // Provenance (A18, #3331; Q-D, plan sec. 39): a write asking an OLDER
730
+ // question than the guess's — another action's landing beneath it —
731
+ // is not its answer: held beneath (the truth for the commit; the
732
+ // guess's own question judges), and nothing moves. The writer's
733
+ // question is the one being asked (`question`: a slice's, a derive's
734
+ // continuation's — the flight's); unstamped writes and mainline are
735
+ // current.
736
+ // A store re-bases a keyed arrangement guess over an older truth, and
737
+ // folds a current one beneath it (D-34): true.
738
+ const s = stale(e, question);
739
+ if (GlobalQueue.Nn?.(e, n, s) || s) {
740
+ e.ue = n;
741
+ e.l |= CONFIG_HELD;
742
+ schedule();
743
+ return n;
744
+ }
745
+ supersede(e, n, !e.ye || !e.ye(e.T.P, n));
746
+ } else {
747
+ const s = txOf(e);
748
+ if (e.ye && e.ye(laneValueOf(e), n)) return n;
749
+ if (s.Ue) e.ue = n; else e.T.P = n;
750
+ if (e.X !== undefined) e.ie = clock;
751
+ insertSubs(e);
752
+ laneDirty(e, s);
753
+ }
754
+ schedule();
755
+ return n;
756
+ }
757
+
758
+ /** A written guess's own pass finished: its source recomputed it — the
759
+ * truth (A18: "the source is whatever recomputes the node"), authoritative
760
+ * or the lane's own derivation (a guess over `config().courier` under a
761
+ * country guess: the lane's config landing confirms or corrects it). An
762
+ * errored pass stages nothing. Provenance (A18, #3331): "the source" is the
763
+ * guess's own question or a newer one; an older action's answer landing
764
+ * over a newer guess (the two entangled when the newer guess was written)
765
+ * is stale — a slow source leaking back in over the user's latest intent.
766
+ * It is staged beneath the guess, for the commit like any landing, and
767
+ * nothing moves: no downstream re-ask, no pending flip on the guess's
768
+ * readers (`isPending` of the guess itself says the held truth differs,
769
+ * A24). The guess's own question answering supersedes as usual. */ function laneOutcome(e, n, s) {
770
+ if (s) return true;
771
+ if (stale(e, answered(e))) {
772
+ e.ue = n;
773
+ e.l |= CONFIG_HELD;
774
+ return true;
775
+ }
776
+ supersede(e, n, !e.ye || !e.ye(e.T.P, n));
777
+ return true;
778
+ }
779
+
780
+ /** THE provenance test, for a derivation's pass and a write alike: an
781
+ * answer to question `q` landing on a guess is stale when `q` is older
782
+ * than the guess's own; unstamped (0) and mainline are current. */ function stale(e, n) {
783
+ return n !== 0 && n < e.T.Ie;
784
+ }
785
+
786
+ /** The question a derivation's pass answered: the newest among the stamped
787
+ * sources that changed this round (a flight's landing carries the question
788
+ * that started it); 0 when none is stamped. */ function answered(e) {
789
+ let n = 0;
790
+ for (let s = e.C; s !== null; s = s.G) {
791
+ const e = s.S;
792
+ if (e.T !== null && e.T.Ie > n && e.ie === clock) n = e.T.Ie;
793
+ }
794
+ return n;
795
+ }
796
+
797
+ /** The lanes alive before this seam's guesses opened theirs (a prefix of
798
+ * `lanes`; nothing dissolves one between here and the seam loop): a lane
799
+ * born at the seam has no work to judge yet (its passes run next round) —
800
+ * it is neither shown nor blocked until it has. */ let judged = 0;
801
+
802
+ const applyGuessesAt = e => {
803
+ judged = lanes.length;
804
+ if (pendingGuesses.length !== 0) applyGuesses(e);
805
+ };
806
+
807
+ /** `t` is parked by `r`'s pass alone: each node keeping it — `t`'s own, or
808
+ * a lane's under it — is `r` itself (its flight, in the verdict lane) or a
809
+ * render effect pending on `r` only: the frame observing the lane work that
810
+ * read its staging. Anything else (an open action, a guess's flight,
811
+ * another flight) holds it on its own. */ function heldBy(e, n) {
812
+ if (e.tt !== 0 || e.P && linkBlocked(e)) return false;
813
+ for (let s = -1, t = e; t; t = lanes[++s]) if (t === e || resolveTx(t._parent) === e) {
814
+ if (t !== e && guessFlights(t)) return false;
815
+ for (let e = 0; e < t.tn.length; e++) {
816
+ const s = t.tn[e];
817
+ if (s === n || !(s.m & STATUS_PENDING) || s.T.Re !== null && txOf(s) !== t) continue;
818
+ const l = s.T.se;
819
+ if (s.i !== EFFECT_RENDER || l?.size !== 1 || !l.has(n)) return false;
820
+ }
821
+ }
822
+ return true;
823
+ }
824
+
825
+ const laneSeams = e => {
826
+ // Passes that read a write the parked frame holds as the screen
827
+ // (`stagedReaders`: lane work, a verdict reader before the verdict): they
828
+ // re-derive on the committed world next round (and register as stale
829
+ // readers of the transaction there); a lane's runs wait that round — a
830
+ // lane sees the screen plus its own guesses.
831
+ if (revealing.length) revealing.length = 0;
832
+ const n = [];
833
+ if (e !== null) for (let s = 0; s < stagedReaders.length; s++) {
834
+ const t = stagedReaders[s],
835
+ // A pass no transaction holds that read the frame's staging (an
836
+ // effect, a `[s(), latest(s)]` reader watched before the frame had
837
+ // a transaction): judged by the frame's — it re-derives only if the
838
+ // frame stays parked; landing here, what it read is the screen (one
839
+ // run, D-22).
840
+ l = t.T?.Re || (t.R & REACTIVE_STAGED_READ ? e : null);
841
+ // A verdict reader a later read of the same pass routed into a verdict
842
+ // lane answered for itself: it re-derives at the holder's landing, not
843
+ // now (one run — #3322, #3540). Other verdict-lane work re-derives only
844
+ // if the frame stays parked: a transaction landing at this seam makes
845
+ // what it read the screen (one run). The frame is the transaction that
846
+ // holds what it read (`t`, this flush's — not always the lane's parent:
847
+ // a landing that reached a frame held elsewhere joined that one). Nor
848
+ // when only this pass keeps it parked (`heldBy`): the frame lands with
849
+ // the pass's answer, so what the pass read is the screen when anything
850
+ // shows it — re-derived on the committed world, it would ask a question
851
+ // already asked, over inputs the landing replaces. A reader a
852
+ // transaction holds that read none of its stagings (a verdict reader
853
+ // that probed only a flight, held as the frame's pending observer or
854
+ // its staged derivation) has nothing to re-derive: its re-run
855
+ // re-enters that transaction and parks it again, every round — it
856
+ // runs at the landing (#4349). One that read a staging re-derives only
857
+ // if its frame stays parked: landing at this seam, what it read is the
858
+ // screen (one run, D-22). Not one born into that frame (a held pass's
859
+ // child, ruling A): it has no screen, its reads are the transaction's
860
+ // either way — it runs again at the landing, not now.
861
+ if (t.R & REACTIVE_DISPOSED || (l?.P ? l._parent?.Pe === l && (t.l & CONFIG_VERDICT ? !(t.R & REACTIVE_PROBE_UNANSWERED) : !blocked(e) || heldBy(e, t)) : l && !(t.R & REACTIVE_PROBE_UNANSWERED || t.R & REACTIVE_STAGED_READ && blocked(l) && !bornInto(t, l)))) continue;
862
+ // A leaked effect re-derives seated in its lane from its first read: it
863
+ // carries no lane value (`laneStage`), so without this its pass starts
864
+ // as mainline, joins the parked frame on its first held read and reads
865
+ // the staging, then re-enters the lane at its guess read and leaks
866
+ // again — every round (#4014). A computed is already seated by its
867
+ // override, and a written guess's own pass stays the frame's.
868
+ if (l?.P && t.i) t.R |= REACTIVE_LANE_DIRTY;
869
+ // R5 for an async reader: its frame pass asked the frame's question
870
+ // (F-6's lane gets its own pass now). That flight is the frame's
871
+ // answer: the landing adopts it rather than asking it again (F-9: a
872
+ // re-ask of the same question is no new question; `reruns`). A frame
873
+ // landing at this seam has nothing to re-derive: the pass was the
874
+ // landing's, its flight the screen's answer. Sync or async, the
875
+ // reader's lane pass is still to come: the verdict lane it joins does
876
+ // not reveal this seam (F-6: the lane's readers show its answer
877
+ // together, D-23: atomic with the value) — revealed now, it showed a
878
+ // verdict beside the frame pass's value, before the pass that answers
879
+ // for the lane, and a reader of the re-derived memo read it outside
880
+ // the shown lane and waited for the frame (#4393).
881
+ else if (!l?.P && t.R & REACTIVE_PROBE_UNANSWERED) {
882
+ if (isThenable(t.T?.Ee)) {
883
+ if (!blocked(e)) continue;
884
+ t.T.He = t.T.Ee;
885
+ } else if (blocked(e))
886
+ // A sync reader's lane pass re-derives the async memos over it (a
887
+ // memo over a verdict memo is a verdict reader, D-25 #4050; D-22:
888
+ // `latest()` extracted into a memo reads as inline). The flight
889
+ // each asked over its frame staging, up and held by `t`, is the
890
+ // frame's answer too: the landing adopts it (F-9).
891
+ for (let n = t.o, s; n; n = n.t) if (isThenable((s = n.u).T?.Ee) && s.T.se?.has(s) && s.l & CONFIG_HELD && txOf(s) === e) s.T.He = s.T.Ee;
892
+ if (e?.Pe && n.indexOf(e.Pe) === -1) n.push(e.Pe);
893
+ }
894
+ enqueueSub(t);
895
+ if (l?.P && n.indexOf(l) === -1) n.push(l);
896
+ }
897
+ // A verdict lane born at this seam is judged with it: it exists only once
898
+ // a pass routed into it — the park seam's zombie verdict readers re-run
899
+ // as its work so that this seam reveals them (#3444).
900
+ for (let e = lanes.length - 1; e >= 0; e--) if (e < judged || lanes[e]._parent?.Pe === lanes[e]) laneSeam(lanes[e], n.indexOf(lanes[e]) !== -1);
901
+ // A verdict reader that entered a lane this seam held: its run waits with
902
+ // the lane, and the verdict beside it would freeze — it re-derives next
903
+ // round from the frame's seat, a stale reader of the lane (#4284).
904
+ for (let e; e = entered.pop(); ) if (e.T.Re?.ln) {
905
+ e.R &= ~REACTIVE_LANE_DIRTY;
906
+ enqueueSub(e);
907
+ }
908
+ };
909
+
910
+ /** The landing's re-derive of a reader whose frame flight the seam parked
911
+ * (R5): the flight asked the question the landing would — adopted, it is
912
+ * asked once (F-9). Not over a pass already queued: that one asks anew.
913
+ * Registered as if this pass had returned it — the node pending on it, its
914
+ * landing the answer — through a promise of its own: the frame pass's
915
+ * registration still listens to the flight, and must not land it a second
916
+ * time. */ const adoptParked = e => {
917
+ const n = e.T?.He;
918
+ if (!n || e.R & (REACTIVE_DIRTY | REACTIVE_CHECK | REACTIVE_IN_HEAP)) return false;
919
+ e.T.He = undefined;
920
+ releaseFlightTeardown(e);
921
+ try {
922
+ handleAsync(e, n.then());
923
+ } catch {}
924
+ e.T.fe = true;
925
+ notifyStatus(e, STATUS_PENDING, new NotReadyError(e));
926
+ return true;
927
+ };
928
+
929
+ /** A15: lane work or a verdict reader was served `el`'s committed value
930
+ * (core.ts `frameRead`), so its pass does not wait on `el`'s flight: what
931
+ * `el`'s pending propagated onto it before the pass (its origins, `el`
932
+ * included) is not this pass's — the landing re-derives it (`reruns`).
933
+ * Kept, a pass that went pending on another source never woke when that
934
+ * source settled (#4397). Only a reader something made pending has anything
935
+ * to drop. */ const laneServed = (e, n) => {
936
+ const s = n.T?.se;
937
+ if (s && e.T?.se) for (const n of s) removePendingSource(e, n);
938
+ };
939
+
940
+ /** Render effects that read a verdict and entered a lane before its seam (#4284). */ const entered = [];
941
+
942
+ installLaneHooks(laneRead, laneStage, laneOutcome, laneWrite, applyGuessesAt, laneSeams, () => lanes.length !== 0 && laneCorrections(), endLanes, lanesBlocked, adoptParked, laneServed);
943
+
944
+ GlobalQueue.J = verdictLane;
945
+
946
+ export { display, enterLane, guessedValueOf, laneRead, laneStage, laneValueOf, optimisticWrite, pendingGuessOf, supersede, take, verdictLane };