@solidjs/signals 2.0.0-rc.14 → 2.0.0-rc.16
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.
- package/dist/dev-shared.js +882 -405
- package/dist/dev.attribution.js +172 -66
- package/dist/dev.js +1529 -745
- package/dist/observe/affects-marks.js +86 -0
- package/dist/observe/affects.js +32 -80
- package/dist/observe/boundaries.js +202 -166
- package/dist/observe/core/async.js +192 -141
- package/dist/observe/core/attribution-queries.js +1 -1
- package/dist/observe/core/attribution.js +315 -214
- package/dist/observe/core/constants.js +23 -4
- package/dist/observe/core/context.js +3 -3
- package/dist/observe/core/core.js +532 -360
- package/dist/observe/core/dev.js +63 -35
- package/dist/observe/core/effect.js +47 -47
- package/dist/observe/core/error.js +5 -3
- package/dist/observe/core/external.js +5 -6
- package/dist/observe/core/graph.js +56 -42
- package/dist/observe/core/heap.js +33 -33
- package/dist/observe/core/identities.js +62 -0
- package/dist/observe/core/lanes.js +242 -229
- package/dist/observe/core/owner.js +62 -50
- package/dist/observe/core/scheduler.js +322 -168
- package/dist/observe/core/truth.js +45 -0
- package/dist/observe/core/verdict.js +114 -64
- package/dist/observe/deferred.js +184 -0
- package/dist/observe/index.js +7 -1
- package/dist/observe/map.js +339 -254
- package/dist/observe/reveal.js +77 -77
- package/dist/observe/signals.js +54 -33
- package/dist/observe/store/affects.js +76 -69
- package/dist/observe/store/edges.js +39 -0
- package/dist/observe/store/hooks.js +13 -0
- package/dist/observe/store/index.js +0 -2
- package/dist/observe/store/optimistic.js +82 -44
- package/dist/observe/store/projection.js +83 -64
- package/dist/observe/store/reconcile.js +32 -30
- package/dist/observe/store/store.js +219 -123
- package/dist/prod/affects-marks.js +86 -0
- package/dist/prod/affects.js +33 -79
- package/dist/prod/boundaries.js +185 -149
- package/dist/prod/core/async.js +176 -135
- package/dist/prod/core/constants.js +23 -4
- package/dist/prod/core/context.js +3 -3
- package/dist/prod/core/core.js +521 -353
- package/dist/prod/core/effect.js +66 -66
- package/dist/prod/core/error.js +5 -3
- package/dist/prod/core/external.js +5 -6
- package/dist/prod/core/graph.js +56 -42
- package/dist/prod/core/heap.js +38 -38
- package/dist/prod/core/identities.js +62 -0
- package/dist/prod/core/lanes.js +237 -224
- package/dist/prod/core/owner.js +62 -51
- package/dist/prod/core/scheduler.js +312 -158
- package/dist/prod/core/truth.js +45 -0
- package/dist/prod/core/verdict.js +113 -63
- package/dist/prod/deferred.js +182 -0
- package/dist/prod/index.js +7 -1
- package/dist/prod/map.js +366 -281
- package/dist/prod/reveal.js +77 -77
- package/dist/prod/signals.js +59 -38
- package/dist/prod/store/affects.js +76 -69
- package/dist/prod/store/edges.js +39 -0
- package/dist/prod/store/hooks.js +13 -0
- package/dist/prod/store/index.js +0 -2
- package/dist/prod/store/optimistic.js +121 -84
- package/dist/prod/store/projection.js +46 -34
- package/dist/prod/store/reconcile.js +32 -30
- package/dist/prod/store/store.js +205 -116
- package/dist/types/affects-marks.d.ts +14 -0
- package/dist/types/boundaries.d.ts +5 -1
- package/dist/types/core/async.d.ts +10 -0
- package/dist/types/core/attribution.d.ts +6 -2
- package/dist/types/core/constants.d.ts +18 -1
- package/dist/types/core/core.d.ts +77 -5
- package/dist/types/core/dev.d.ts +43 -13
- package/dist/types/core/graph.d.ts +11 -0
- package/dist/types/core/identities.d.ts +17 -0
- package/dist/types/core/index.d.ts +2 -1
- package/dist/types/core/lanes.d.ts +2 -4
- package/dist/types/core/owner.d.ts +5 -3
- package/dist/types/core/scheduler.d.ts +59 -34
- package/dist/types/core/truth.d.ts +16 -0
- package/dist/types/core/types.d.ts +21 -6
- package/dist/types/core/verdict.d.ts +32 -0
- package/dist/types/deferred.d.ts +28 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types/map.d.ts +2 -2
- package/dist/types/signals.d.ts +28 -7
- package/dist/types/store/affects.d.ts +11 -0
- package/dist/types/store/edges.d.ts +9 -0
- package/dist/types/store/hooks.d.ts +48 -0
- package/dist/types/store/index.d.ts +10 -4
- package/dist/types/store/optimistic.d.ts +3 -2
- package/dist/types/store/projection.d.ts +4 -3
- package/dist/types/store/store.d.ts +4 -39
- package/dist/types/store/target.d.ts +16 -8
- package/dist/types/store/types.d.ts +14 -0
- package/package.json +1 -1
package/dist/prod/core/lanes.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import { CONFIG_GUESS, NOT_PENDING, CONFIG_OVERRIDE, REACTIVE_DISPOSED, CONFIG_VERDICT, REACTIVE_PROBE_UNANSWERED,
|
|
1
|
+
import { CONFIG_GUESS, NOT_PENDING, CONFIG_OVERRIDE, 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, STATUS_PENDING, EFFECT_RENDER, REACTIVE_SCREEN_READ, REACTIVE_FRAME_READ, REACTIVE_IN_HEAP, REACTIVE_DIRTY, REACTIVE_CHECK, CONFIG_INPUTS_PUBLISHED, CONFIG_SLOT_NODE, CONFIG_STAGED, REACTIVE_JOINED, REACTIVE_STAGED_READ } from "./constants.js";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { ext, tracking, stagedRead } from "./core.js";
|
|
4
4
|
|
|
5
5
|
import { NotReadyError } from "./error.js";
|
|
6
6
|
|
|
7
|
+
import { laneValueOf } from "./truth.js";
|
|
8
|
+
|
|
7
9
|
import { enqueueSub } from "./heap.js";
|
|
8
10
|
|
|
9
|
-
import { schedule, question, nextQuestion, GlobalQueue,
|
|
11
|
+
import { schedule, question, nextQuestion, installLaneHooks, GlobalQueue, newTransaction, resolveTx, ownFlights, blocked, txOf, clock, insertSubs, laneDirty, queuePendingNode, list, passLane, sameLane, flushTransaction, commitPendingNode, releaseQueues, holdNode, joinFuture, reruns, merge, setPassLane } from "./scheduler.js";
|
|
10
12
|
|
|
11
13
|
// Lanes (plan sec. 28 replay, 2026-10-02; maintainer rulings 2026-10-01/02). A lane
|
|
12
14
|
// is "a new base of a transition": the sub-frame an optimistic write opens
|
|
@@ -38,24 +40,18 @@ import { schedule, question, nextQuestion, GlobalQueue, blocked, txOf, passLane,
|
|
|
38
40
|
/** Live lanes (parented). Scanned at every seam while non-empty. */
|
|
39
41
|
const lanes = [];
|
|
40
42
|
|
|
43
|
+
/** A pass left a shown slot the equality gate can no longer see (#3892). */ const LEFT_SHOWN = 1 << 20;
|
|
44
|
+
|
|
41
45
|
function newLane(e) {
|
|
42
46
|
const n = newTransaction(true, e);
|
|
43
47
|
lanes.push(n);
|
|
44
48
|
return n;
|
|
45
49
|
}
|
|
46
50
|
|
|
47
|
-
/** A lane node's current value: its guess, or the latest it derived — the
|
|
48
|
-
* staging a shown lane holds for its next reveal, else its slot; the
|
|
49
|
-
* committed value while it has none (its first lane pass in flight). */ function laneValueOf(e) {
|
|
50
|
-
if (!(e.u & CONFIG_GUESS) && e.Ae !== NOT_PENDING) return e.Ae;
|
|
51
|
-
const n = e.m.Z;
|
|
52
|
-
return n !== NOT_PENDING ? n : e.pe;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
51
|
/** What the screen shows for a lane's node: the lane's value once the lane
|
|
56
52
|
* has revealed, the committed truth before. */ function display(e) {
|
|
57
|
-
const n = e.
|
|
58
|
-
return e.
|
|
53
|
+
const n = e.T.v;
|
|
54
|
+
return e.T.Re.ke && n !== NOT_PENDING ? n : e.Ie;
|
|
59
55
|
}
|
|
60
56
|
|
|
61
57
|
/** Guesses written since the last seam (`[node, value, question, …]`).
|
|
@@ -70,7 +66,7 @@ function newLane(e) {
|
|
|
70
66
|
* on (a store setter's draft too, store/optimistic.ts). */ function guessedValueOf(e) {
|
|
71
67
|
const n = pendingGuessOf(e);
|
|
72
68
|
if (n !== NOT_PENDING) return n;
|
|
73
|
-
return e.
|
|
69
|
+
return e.l & CONFIG_OVERRIDE ? laneValueOf(e) : e.Ie;
|
|
74
70
|
}
|
|
75
71
|
|
|
76
72
|
/** The unflushed guess to `n`, else NOT_PENDING. */ function pendingGuessOf(e) {
|
|
@@ -84,9 +80,9 @@ function optimisticWrite(e, n) {
|
|
|
84
80
|
// again is no guess (the node's comparator, as for any write) — unless
|
|
85
81
|
// the node already carries one: the user re-asked, and the re-ask renews
|
|
86
82
|
// the guess's question and entangles its frame (#3347) without notifying.
|
|
87
|
-
const
|
|
88
|
-
if (typeof n === "function") n = n(
|
|
89
|
-
if (e.
|
|
83
|
+
const s = guessedValueOf(e);
|
|
84
|
+
if (typeof n === "function") n = n(s);
|
|
85
|
+
if (e.xe && e.xe(s, n) && !(e.l & CONFIG_GUESS)) return n;
|
|
90
86
|
pendingGuesses.push(e, n, question || nextQuestion());
|
|
91
87
|
schedule();
|
|
92
88
|
return n;
|
|
@@ -104,35 +100,40 @@ function optimisticWrite(e, n) {
|
|
|
104
100
|
/** A guess's own truth is in flight: the node's own refetch — or, a store
|
|
105
101
|
* leaf's, its family's derive (the slot's flight; store/optimistic.ts
|
|
106
102
|
* installs the resolver). A17: the guess stands in for the flight. */ function inFlight(e) {
|
|
107
|
-
return (e.
|
|
103
|
+
return (e.m & STATUS_PENDING) !== 0 || (e.l & CONFIG_SLOT_NODE) !== 0 && GlobalQueue.k?.(e) === true;
|
|
108
104
|
}
|
|
109
105
|
|
|
110
106
|
function applyGuesses(e) {
|
|
111
107
|
let n = null;
|
|
112
|
-
for (let
|
|
113
|
-
const
|
|
114
|
-
const
|
|
115
|
-
let
|
|
116
|
-
|
|
108
|
+
for (let s = 0; s < pendingGuesses.length; s += 3) {
|
|
109
|
+
const t = pendingGuesses[s];
|
|
110
|
+
const l = pendingGuesses[s + 1];
|
|
111
|
+
let u = true;
|
|
112
|
+
// The frame already holding the slot: a guess over it is a second
|
|
113
|
+
// suggestion for the slot, and two cannot finish apart (A34 (1)) — the
|
|
114
|
+
// frames entangle.
|
|
115
|
+
let i = null;
|
|
116
|
+
if (t.l & CONFIG_OVERRIDE) {
|
|
117
117
|
// A lane's node already: a guess re-asked, or a derivation guessed
|
|
118
|
-
// over (its staging is void — the guess is the value now).
|
|
119
|
-
//
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
l.Ae = NOT_PENDING;
|
|
125
|
-
l.u |= CONFIG_GUESS;
|
|
118
|
+
// over (its staging is void — the guess is the value now). The same
|
|
119
|
+
// value re-asked renews the question; nothing to notify.
|
|
120
|
+
u = !t.xe || !t.xe(laneValueOf(t), l);
|
|
121
|
+
if (!(t.l & CONFIG_GUESS)) {
|
|
122
|
+
t.se = NOT_PENDING;
|
|
123
|
+
t.l |= CONFIG_GUESS;
|
|
126
124
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
if (e !== null && n !== null) merge(e, n);
|
|
125
|
+
t.T.v = l;
|
|
126
|
+
i = txOf(t)._parent;
|
|
130
127
|
} else {
|
|
131
|
-
let
|
|
132
|
-
|
|
133
|
-
|
|
128
|
+
let s;
|
|
129
|
+
// A held node: a truth staged there, or what a corrected guess showed.
|
|
130
|
+
// The guess composes on it, so it ends with that hold — and with its
|
|
131
|
+
// own frame's (F-11): it lands only when both have (the board's rapid
|
|
132
|
+
// adds — a later add's row reverted with an earlier add's landing).
|
|
133
|
+
if (t.l & CONFIG_HELD) s = newLane(i = txOf(t)); else {
|
|
134
|
+
if (e === null && inFlight(t)) e = newTransaction(false);
|
|
134
135
|
if (e === null) continue;
|
|
135
|
-
|
|
136
|
+
s = n ??= newLane(e);
|
|
136
137
|
}
|
|
137
138
|
// (A guess equal to a truth staged beneath it is confirmed at birth —
|
|
138
139
|
// A24 — and still re-derives its readers as the lane's: the truth's
|
|
@@ -140,17 +141,18 @@ function applyGuesses(e) {
|
|
|
140
141
|
// screen's plus the guess (plan sec. 19) — a derivation reading a held write
|
|
141
142
|
// beside the guess must not show it. Two flights for one input, when
|
|
142
143
|
// the worlds coincide, is the price.)
|
|
143
|
-
ext(
|
|
144
|
-
l
|
|
145
|
-
list(
|
|
144
|
+
ext(t).v = l;
|
|
145
|
+
t.l |= CONFIG_OVERRIDE | CONFIG_GUESS;
|
|
146
|
+
list(t, s);
|
|
146
147
|
}
|
|
147
|
-
|
|
148
|
-
|
|
148
|
+
if (e !== null && i !== null) merge(e, i);
|
|
149
|
+
ext(t).Ee = pendingGuesses[s + 2];
|
|
150
|
+
if (u) {
|
|
149
151
|
// The lane's members re-derive as its work (REACTIVE_LANE_DIRTY): a
|
|
150
152
|
// blocked lane's re-guess does not re-run its render effects as stale
|
|
151
153
|
// readers republishing the committed view (#3460).
|
|
152
|
-
insertSubs(
|
|
153
|
-
laneDirty(
|
|
154
|
+
insertSubs(t);
|
|
155
|
+
laneDirty(t, txOf(t));
|
|
154
156
|
}
|
|
155
157
|
}
|
|
156
158
|
pendingGuesses.length = 0;
|
|
@@ -165,38 +167,40 @@ function applyGuesses(e) {
|
|
|
165
167
|
* through an ancestor's guess stays its own (the screen plus its own
|
|
166
168
|
* guesses). */ function enterLane(e, n) {
|
|
167
169
|
n.R |= REACTIVE_LANE_READ;
|
|
168
|
-
const
|
|
169
|
-
if (
|
|
170
|
+
const s = passLane;
|
|
171
|
+
if (s === null) {
|
|
170
172
|
setPassLane(e);
|
|
171
173
|
// The pass read a held write before its first lane read (it joined the
|
|
172
174
|
// frame's future as mainline would): lane work sees the screen — the
|
|
173
175
|
// seam re-derives it on the committed world next round (`stagedReaders`,
|
|
174
|
-
// the park's repair), as it does a lane pass that read a staging.
|
|
175
|
-
|
|
176
|
+
// the park's repair), as it does a lane pass that read a staging. Not a
|
|
177
|
+
// pass whose held reads were all of nodes born held (no staged read,
|
|
178
|
+
// `stagedRead`): it has no committed world to re-derive on (#3969).
|
|
179
|
+
if (n.R & REACTIVE_JOINED && n.R & REACTIVE_STAGED_READ) stagedRead(n);
|
|
176
180
|
return;
|
|
177
181
|
}
|
|
178
|
-
if (sameLane(
|
|
179
|
-
if (under(
|
|
180
|
-
if (under(e,
|
|
181
|
-
linkLanes(
|
|
182
|
+
if (sameLane(s, e)) return setPassLane(e);
|
|
183
|
+
if (under(s, e)) return;
|
|
184
|
+
if (under(e, s)) return setPassLane(e);
|
|
185
|
+
linkLanes(s, e);
|
|
182
186
|
setPassLane(e);
|
|
183
187
|
}
|
|
184
188
|
|
|
185
189
|
/** Is `l` nested under `a` (an ancestor lane)? */ function under(e, n) {
|
|
186
|
-
for (let
|
|
190
|
+
for (let s = e._parent; s !== null && s.v; s = s._parent) if (s === n) return true;
|
|
187
191
|
return false;
|
|
188
192
|
}
|
|
189
193
|
|
|
190
194
|
/** One link group (a shared array) for both lanes' groups. */ function linkLanes(e, n) {
|
|
191
|
-
const
|
|
192
|
-
const
|
|
193
|
-
if (
|
|
194
|
-
if (
|
|
195
|
-
|
|
196
|
-
n.
|
|
197
|
-
} else for (let e = 0; e <
|
|
198
|
-
|
|
199
|
-
|
|
195
|
+
const s = e.en ?? (e.en = [ e ]);
|
|
196
|
+
const t = n.en;
|
|
197
|
+
if (t === s) return;
|
|
198
|
+
if (t === null) {
|
|
199
|
+
s.push(n);
|
|
200
|
+
n.en = s;
|
|
201
|
+
} else for (let e = 0; e < t.length; e++) {
|
|
202
|
+
s.push(t[e]);
|
|
203
|
+
t[e].en = s;
|
|
200
204
|
}
|
|
201
205
|
}
|
|
202
206
|
|
|
@@ -204,20 +208,20 @@ function applyGuesses(e) {
|
|
|
204
208
|
* without the group recursion. (A guess in `k` whose own truth is in flight
|
|
205
209
|
* blocks `k`'s parent, not `k` — nor, through the link, `l`: the guess
|
|
206
210
|
* shows, A17.) */ function linkBlocked(e) {
|
|
207
|
-
const n = e.
|
|
208
|
-
if (n !== null) for (let
|
|
209
|
-
const
|
|
210
|
-
if (
|
|
211
|
+
const n = e.en;
|
|
212
|
+
if (n !== null) for (let s = 0; s < n.length; s++) {
|
|
213
|
+
const t = n[s];
|
|
214
|
+
if (t !== e && (t.tt !== 0 || ownFlights(t) || nestedBlocked(t))) return true;
|
|
211
215
|
}
|
|
212
216
|
return false;
|
|
213
217
|
}
|
|
214
218
|
|
|
215
219
|
function unlink(e) {
|
|
216
|
-
const n = e.
|
|
220
|
+
const n = e.en;
|
|
217
221
|
if (n === null) return;
|
|
218
|
-
const
|
|
219
|
-
if (
|
|
220
|
-
e.
|
|
222
|
+
const s = n.indexOf(e);
|
|
223
|
+
if (s !== -1) n.splice(s, 1);
|
|
224
|
+
e.en = null;
|
|
221
225
|
}
|
|
222
226
|
|
|
223
227
|
/** Verdicts (maintainer, 2026-10-01): `isPending` and `latest` are
|
|
@@ -227,7 +231,7 @@ function unlink(e) {
|
|
|
227
231
|
* lane under the holder, shown now, re-derived at the landing, ending with
|
|
228
232
|
* it. Judged at the seam like any lane: blocked while a verdict reader's
|
|
229
233
|
* own derivation is in flight (lane rule 3), shown otherwise. */ function verdictLane(e) {
|
|
230
|
-
return e.
|
|
234
|
+
return e.he ??= newLane(e);
|
|
231
235
|
}
|
|
232
236
|
|
|
233
237
|
/** A lane pass's node (core.ts `recompute`, before its staging; a pending
|
|
@@ -244,19 +248,24 @@ function unlink(e) {
|
|
|
244
248
|
* not leave (A30: it never got there). A first pass under a lane is the
|
|
245
249
|
* lane's (ruling A); a guess is written, not derived — it never leaves this
|
|
246
250
|
* way. `errored`: the pass has no answer — or, a lane pass's pending
|
|
247
|
-
* propagation (async.ts `propagateStatus`), the node gone pending. */ function laneStage(e, n,
|
|
248
|
-
if (!(
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
251
|
+
* propagation (async.ts `propagateStatus`), the node gone pending. */ function laneStage(e, n, s, t) {
|
|
252
|
+
if (!(s || t || e.R & REACTIVE_LANE_READ || e.l & CONFIG_GUESS)) {
|
|
253
|
+
const n = e.T;
|
|
254
|
+
if (n !== null) {
|
|
255
|
+
const s = n.Re;
|
|
256
|
+
// Cleared before equality, so a return to the committed value notifies
|
|
257
|
+
// nobody. The seam wakes it unless the frame is still held (#3892).
|
|
258
|
+
if (s?.ke && !blocked(resolveTx(s._parent))) e.R |= LEFT_SHOWN;
|
|
259
|
+
if (s?.v) n.Re = null;
|
|
260
|
+
n.v = NOT_PENDING;
|
|
252
261
|
}
|
|
253
|
-
e.
|
|
262
|
+
e.l &= -1050881;
|
|
254
263
|
return false;
|
|
255
264
|
}
|
|
256
265
|
if (!e.i) {
|
|
257
|
-
if (!(e.
|
|
258
|
-
e.
|
|
259
|
-
e.
|
|
266
|
+
if (!(e.l & CONFIG_OVERRIDE)) {
|
|
267
|
+
e.se = NOT_PENDING;
|
|
268
|
+
e.l = e.l & -1048833 | CONFIG_OVERRIDE;
|
|
260
269
|
ext(e);
|
|
261
270
|
}
|
|
262
271
|
// A written guess whose own pass is the lane's work — its source is a
|
|
@@ -265,7 +274,7 @@ function unlink(e) {
|
|
|
265
274
|
// of the lane from here (its value the lane's, its fate the lane's), no
|
|
266
275
|
// longer a written guess. A pass with no answer (pending, errored)
|
|
267
276
|
// leaves the guess.
|
|
268
|
-
if (!
|
|
277
|
+
if (!t) e.l &= ~CONFIG_GUESS;
|
|
269
278
|
}
|
|
270
279
|
// A leaf has no lane value to seat it (`recompute`): one left waiting on
|
|
271
280
|
// the lane's flight runs its next pass as the lane's — the landing that
|
|
@@ -277,8 +286,8 @@ function unlink(e) {
|
|
|
277
286
|
// `laneRead` decides — its frame holds). Its pending is the frame's: queued
|
|
278
287
|
// for the commit sweep as mainline's (async.ts). A node born in the lane
|
|
279
288
|
// has nothing on screen: its leaf waits as the lane's.
|
|
280
|
-
else if (
|
|
281
|
-
if (
|
|
289
|
+
else if (t) {
|
|
290
|
+
if (t !== true && !(t.m & STATUS_UNINITIALIZED) && (e.l & CONFIG_HELD || e.R & REACTIVE_RECOMPUTING_DEPS) && !e.T?.Re?.v) {
|
|
282
291
|
queuePendingNode(e);
|
|
283
292
|
return false;
|
|
284
293
|
}
|
|
@@ -288,29 +297,32 @@ function unlink(e) {
|
|
|
288
297
|
return true;
|
|
289
298
|
}
|
|
290
299
|
|
|
291
|
-
function supersede(e, n,
|
|
292
|
-
const
|
|
300
|
+
function supersede(e, n, s) {
|
|
301
|
+
const t = txOf(e);
|
|
293
302
|
// Resolved: the parent may have merged into another transaction since the
|
|
294
303
|
// lane opened (two actions guessing one slot entangle, A34 (1)) — the
|
|
295
304
|
// truth is held by the transaction that lands, not the merged-away one.
|
|
296
|
-
const
|
|
297
|
-
|
|
298
|
-
|
|
305
|
+
const l = resolveTx(t._parent ?? t);
|
|
306
|
+
// A store row answered by a new object the store would reconcile into
|
|
307
|
+
// the guessed one unchanged is an echo, not a correction (#3898): the
|
|
308
|
+
// server's object never matches the guess by reference.
|
|
309
|
+
if (s && e.l & CONFIG_SLOT_NODE && GlobalQueue.nn?.(e.T.v, n)) s = false;
|
|
310
|
+
if (s) {
|
|
311
|
+
dissolveLane(t, l, e);
|
|
299
312
|
// What the screen showed stays the screen until the parent lands (A18
|
|
300
313
|
// (c): display and untracked reads keep the override until the commit).
|
|
301
|
-
if (
|
|
302
|
-
e.
|
|
303
|
-
e.
|
|
304
|
-
e
|
|
305
|
-
|
|
306
|
-
joinFuture(t);
|
|
307
|
-
if (e.t !== null) insertSubs(e);
|
|
314
|
+
if (t.ke) e.Ie = e.T.v;
|
|
315
|
+
e.l &= -10241;
|
|
316
|
+
e.T.v = NOT_PENDING;
|
|
317
|
+
holdNode(e, l);
|
|
318
|
+
if (e.o !== null) insertSubs(e);
|
|
308
319
|
} else {
|
|
309
|
-
e.
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
for (let n = e.t; n !== null; n = n.l) if (n.o.u & CONFIG_AUTHORITATIVE) enqueueSub(n.o);
|
|
320
|
+
e.l |= CONFIG_HELD;
|
|
321
|
+
// A confirmation is silent (A17); only truth readers are told.
|
|
322
|
+
GlobalQueue.sn?.(t);
|
|
313
323
|
}
|
|
324
|
+
e.se = n;
|
|
325
|
+
joinFuture(l);
|
|
314
326
|
}
|
|
315
327
|
|
|
316
328
|
/** A lane's end, two ways. `into === null`: the parent landed — the lane's
|
|
@@ -322,52 +334,52 @@ function supersede(e, n, u) {
|
|
|
322
334
|
* the screen (`_value` takes it, so the parent's re-derivation compares
|
|
323
335
|
* against what is seen), a truth staged beneath a guess is the parent's to
|
|
324
336
|
* land, and the runs it held (showing the void guess) are dropped: the
|
|
325
|
-
* parent's re-derivation makes the runs that show. */ function dissolveLane(e, n,
|
|
326
|
-
const
|
|
327
|
-
if (
|
|
337
|
+
* parent's re-derivation makes the runs that show. */ function dissolveLane(e, n, s) {
|
|
338
|
+
const t = lanes.indexOf(e);
|
|
339
|
+
if (t !== -1) lanes.splice(t, 1);
|
|
328
340
|
unlink(e);
|
|
329
341
|
// Its verdicts end with it (a correction's dissolution reaches here before
|
|
330
342
|
// `endLanes` would): the readers re-derive from the truth's notification.
|
|
331
|
-
const
|
|
332
|
-
if (
|
|
333
|
-
e.
|
|
334
|
-
if (lanes.indexOf(
|
|
343
|
+
const l = e.he;
|
|
344
|
+
if (l !== null) {
|
|
345
|
+
e.he = null;
|
|
346
|
+
if (lanes.indexOf(l) !== -1) dissolveLane(l, null);
|
|
335
347
|
}
|
|
336
|
-
for (let
|
|
337
|
-
const
|
|
338
|
-
const
|
|
339
|
-
if (
|
|
340
|
-
const i =
|
|
341
|
-
const r =
|
|
342
|
-
const o =
|
|
348
|
+
for (let t = 0; t < e.tn.length; t++) {
|
|
349
|
+
const l = e.tn[t];
|
|
350
|
+
const u = l.T;
|
|
351
|
+
if (l === s || u.Re !== e) continue;
|
|
352
|
+
const i = l.i;
|
|
353
|
+
const r = l.l & CONFIG_GUESS;
|
|
354
|
+
const o = u.v;
|
|
343
355
|
// What the screen shows of it (NOT_PENDING: nothing — a lane pass that
|
|
344
356
|
// errored or pends staged no value), and the lane's latest.
|
|
345
|
-
const E = e.
|
|
346
|
-
const f = laneValueOf(
|
|
347
|
-
|
|
348
|
-
|
|
357
|
+
const E = e.ke && !i ? o : l.Ie;
|
|
358
|
+
const f = laneValueOf(l);
|
|
359
|
+
u.v = NOT_PENDING;
|
|
360
|
+
l.l &= -10241;
|
|
349
361
|
if (n === null) {
|
|
350
362
|
// A derivation the revert re-derives (dirtied by the guess's
|
|
351
363
|
// notification — listed before it), or one still in flight, shows the
|
|
352
364
|
// lane's answer beside inputs that are the truth now: a fresh reader
|
|
353
365
|
// of its flight observes it (#3648, #3651; #3305's commit beneath a
|
|
354
366
|
// flight).
|
|
355
|
-
|
|
356
|
-
if (!i && !r)
|
|
357
|
-
commitPendingNode(
|
|
367
|
+
u.Re = null;
|
|
368
|
+
if (!i && !r) l.se = f;
|
|
369
|
+
commitPendingNode(l);
|
|
358
370
|
if (!i) {
|
|
359
|
-
if (
|
|
360
|
-
if (E !== NOT_PENDING && (!
|
|
371
|
+
if (l.R & (REACTIVE_IN_HEAP | REACTIVE_DIRTY | REACTIVE_CHECK) || l.m & STATUS_PENDING) l.l |= CONFIG_INPUTS_PUBLISHED;
|
|
372
|
+
if (E !== NOT_PENDING && (!l.xe || !l.xe(E, l.Ie))) insertSubs(l);
|
|
361
373
|
}
|
|
362
374
|
} else if (r) {
|
|
363
375
|
// A guess of a dissolving lane: its truth — a landing held beneath it,
|
|
364
376
|
// else the value it covered — is the parent's to land, and its readers
|
|
365
377
|
// re-derive from it there. What the screen showed stays the screen
|
|
366
378
|
// until then (A18 (c)).
|
|
367
|
-
if (
|
|
368
|
-
if (e.
|
|
369
|
-
holdNode(
|
|
370
|
-
insertSubs(
|
|
379
|
+
if (l.se === NOT_PENDING) l.se = covered(l);
|
|
380
|
+
if (e.ke) l.Ie = o;
|
|
381
|
+
holdNode(l, n);
|
|
382
|
+
insertSubs(l);
|
|
371
383
|
} else {
|
|
372
384
|
// A correction: the lane's derivations are void. Shown, what the
|
|
373
385
|
// screen showed stays the screen (committed, inputs published — every
|
|
@@ -376,20 +388,20 @@ function supersede(e, n, u) {
|
|
|
376
388
|
// flight is asking the void world's question: its landing is nobody's
|
|
377
389
|
// answer — it re-asks from the truth (whose notification may not reach
|
|
378
390
|
// it: an input's truth equal to its committed value is silent).
|
|
379
|
-
|
|
391
|
+
u.Re = null;
|
|
380
392
|
if (!i) {
|
|
381
|
-
if (E !== NOT_PENDING && e.
|
|
382
|
-
if (
|
|
383
|
-
|
|
384
|
-
enqueueSub(
|
|
393
|
+
if (E !== NOT_PENDING && e.ke) l.se = E;
|
|
394
|
+
if (l.m & STATUS_PENDING) {
|
|
395
|
+
u.Se = null;
|
|
396
|
+
enqueueSub(l);
|
|
385
397
|
}
|
|
386
398
|
}
|
|
387
|
-
if (e.
|
|
388
|
-
commitPendingNode(
|
|
389
|
-
if (!i)
|
|
399
|
+
if (e.ke) {
|
|
400
|
+
commitPendingNode(l);
|
|
401
|
+
if (!i) l.l |= CONFIG_INPUTS_PUBLISHED;
|
|
390
402
|
} else {
|
|
391
|
-
if (
|
|
392
|
-
|
|
403
|
+
if (u.Ue !== null || u.me !== null) GlobalQueue.Ce(l, false, true);
|
|
404
|
+
l.l &= -1048961;
|
|
393
405
|
}
|
|
394
406
|
}
|
|
395
407
|
}
|
|
@@ -404,7 +416,7 @@ function supersede(e, n, u) {
|
|
|
404
416
|
// void: nothing of it reached the screen. So are the runs a blocked lane
|
|
405
417
|
// parked: they show a re-guess the seam never revealed, beside derivations
|
|
406
418
|
// that keep what the screen showed.
|
|
407
|
-
if (n === null || e.
|
|
419
|
+
if (n === null || e.ke && !e.ln) releaseQueues(e); else e.un[0].length = e.un[1].length = 0;
|
|
408
420
|
}
|
|
409
421
|
|
|
410
422
|
/** Lanes. A lane's node is read by its reader's kind: an authoritative
|
|
@@ -422,59 +434,61 @@ function supersede(e, n, u) {
|
|
|
422
434
|
* verdict: released if the lane shows, held if it blocks) — and sees the
|
|
423
435
|
* lane's latest. NOT_PENDING falls through: lane work's read of a pending
|
|
424
436
|
* member throws like any. */ function laneRead(e, n) {
|
|
425
|
-
const
|
|
426
|
-
if (e !== null && e.
|
|
437
|
+
const s = n.l & CONFIG_GUESS;
|
|
438
|
+
if (e !== null && e.l & CONFIG_AUTHORITATIVE) return GlobalQueue.rn(n);
|
|
439
|
+
const t = n.m;
|
|
440
|
+
// An errored member's lane value predates its error; the error is the answer (#4106).
|
|
441
|
+
if (!s && t & STATUS_ERROR) return NOT_PENDING;
|
|
427
442
|
if (e === null) return laneValueOf(n);
|
|
428
443
|
const l = txOf(n);
|
|
429
|
-
|
|
430
|
-
if (!tracking || e.u & CONFIG_CHILDREN_FORBIDDEN) {
|
|
444
|
+
if (!tracking || e.l & CONFIG_CHILDREN_FORBIDDEN) {
|
|
431
445
|
// An untracked read inside lane work derives from the lane like a
|
|
432
446
|
// tracked one, minus the subscription — `untrack` is about
|
|
433
447
|
// dependencies, not about which world a pass derives from (a mapper's
|
|
434
448
|
// row reads under its root, store/map): the pass enters the lane (two
|
|
435
449
|
// lanes read by one pass link, as for tracked reads). Outside lane
|
|
436
450
|
// work, the screen.
|
|
437
|
-
if (passLane === null || e.
|
|
451
|
+
if (passLane === null || e.l & CONFIG_CHILDREN_FORBIDDEN) return display(n);
|
|
438
452
|
enterLane(l, e);
|
|
439
|
-
if (!
|
|
453
|
+
if (!s && t & STATUS_PENDING) return NOT_PENDING;
|
|
440
454
|
return laneValueOf(n);
|
|
441
455
|
}
|
|
442
456
|
if (e.i === EFFECT_RENDER && (passLane === null || !sameLane(passLane, l))) {
|
|
443
|
-
if (!
|
|
457
|
+
if (!s) {
|
|
444
458
|
// A flight whose value has never shown: nothing to show — the leaf
|
|
445
459
|
// waits on it, and its own frame holds (A15, #3334), not the lane's
|
|
446
460
|
// parent. The landing lands the frame: its own pass (the flush
|
|
447
461
|
// joined its transaction) reads the answer it waited on — the lane's
|
|
448
462
|
// staging, revealed at this seam.
|
|
449
|
-
if (t & STATUS_PENDING && n.
|
|
450
|
-
if (n.
|
|
463
|
+
if (t & STATUS_PENDING && n.T.v === NOT_PENDING) return NOT_PENDING;
|
|
464
|
+
if (n.se !== NOT_PENDING && e.l & CONFIG_HELD && flushTransaction !== null && resolveTx(flushTransaction) === txOf(e)) return n.se;
|
|
451
465
|
}
|
|
452
|
-
if (l.ln || !
|
|
453
|
-
if (!
|
|
466
|
+
if (l.ln || !s && t & STATUS_PENDING) {
|
|
467
|
+
if (!s && !l.ke && t & STATUS_UNINITIALIZED) throw new NotReadyError(null);
|
|
454
468
|
// Re-derived at the reveal; once per pass (the pass may also be a stale
|
|
455
469
|
// reader of a transaction, REACTIVE_FRAME_READ — both reruns apply).
|
|
456
470
|
if (!(e.R & REACTIVE_SCREEN_READ)) {
|
|
457
471
|
e.R |= REACTIVE_FRAME_READ | REACTIVE_SCREEN_READ;
|
|
458
|
-
l.
|
|
472
|
+
l.En.push(e);
|
|
459
473
|
}
|
|
460
474
|
return display(n);
|
|
461
475
|
}
|
|
462
476
|
}
|
|
463
477
|
enterLane(l, e);
|
|
464
|
-
if (!
|
|
478
|
+
if (!s && t & STATUS_PENDING) return NOT_PENDING;
|
|
465
479
|
return laneValueOf(n);
|
|
466
480
|
}
|
|
467
481
|
|
|
468
482
|
/** The value a guess covered: the node's committed value — a store slot's
|
|
469
483
|
* asked of the store (a chained link follows the inner store's commits). */ function covered(e) {
|
|
470
|
-
return e.
|
|
484
|
+
return e.l & CONFIG_SLOT_NODE && GlobalQueue.fn !== undefined ? GlobalQueue.fn(e) : e.Ie;
|
|
471
485
|
}
|
|
472
486
|
|
|
473
487
|
/** A guess in `l` whose own truth is in flight (its refetch — authoritative:
|
|
474
488
|
* the landing supersedes, not the body's end). */ function guessFlights(e) {
|
|
475
|
-
for (let n = 0; n < e.
|
|
476
|
-
const
|
|
477
|
-
if (
|
|
489
|
+
for (let n = 0; n < e.tn.length; n++) {
|
|
490
|
+
const s = e.tn[n];
|
|
491
|
+
if (s.l & CONFIG_GUESS && s.T.Re === e && inFlight(s)) return true;
|
|
478
492
|
}
|
|
479
493
|
return false;
|
|
480
494
|
}
|
|
@@ -494,20 +508,20 @@ function supersede(e, n, u) {
|
|
|
494
508
|
* landing.) True when a lane was judged. */ function laneCorrections() {
|
|
495
509
|
let e = false;
|
|
496
510
|
const n = lanes.slice();
|
|
497
|
-
for (let
|
|
498
|
-
const
|
|
499
|
-
if (lanes.indexOf(
|
|
500
|
-
const
|
|
501
|
-
if (!
|
|
511
|
+
for (let s = 0; s < n.length; s++) {
|
|
512
|
+
const t = n[s];
|
|
513
|
+
if (lanes.indexOf(t) === -1) continue;
|
|
514
|
+
const l = resolveTx(t._parent);
|
|
515
|
+
if (!l.nt || l.tt !== 0 || l.v || ownFlights(l) || guessFlights(t)) continue;
|
|
502
516
|
e = true;
|
|
503
517
|
// Each guess's truth: the one beneath it (a landing held there), else
|
|
504
518
|
// the one it covered. (A correction dissolves the lane — the others are
|
|
505
519
|
// re-homed with theirs, `dissolveLane`.)
|
|
506
|
-
for (let e = 0; e <
|
|
507
|
-
const n =
|
|
508
|
-
if (n.
|
|
509
|
-
const e = n.
|
|
510
|
-
supersede(n, e, !n.
|
|
520
|
+
for (let e = 0; e < t.tn.length && lanes.indexOf(t) !== -1; e++) {
|
|
521
|
+
const n = t.tn[e];
|
|
522
|
+
if (n.l & CONFIG_GUESS && n.T.Re === t) {
|
|
523
|
+
const e = n.se !== NOT_PENDING ? n.se : covered(n);
|
|
524
|
+
supersede(n, e, !n.xe || !n.xe(n.T.v, e));
|
|
511
525
|
}
|
|
512
526
|
}
|
|
513
527
|
}
|
|
@@ -522,20 +536,24 @@ function laneSeam(e, n) {
|
|
|
522
536
|
return;
|
|
523
537
|
}
|
|
524
538
|
e.ln = false;
|
|
525
|
-
e.
|
|
539
|
+
e.ke = true;
|
|
526
540
|
reruns(e);
|
|
527
|
-
for (let n = 0; n < e.
|
|
528
|
-
const
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
541
|
+
for (let n = 0; n < e.tn.length; n++) {
|
|
542
|
+
const s = e.tn[n];
|
|
543
|
+
if (s.R & LEFT_SHOWN) {
|
|
544
|
+
s.R ^= LEFT_SHOWN;
|
|
545
|
+
insertSubs(s);
|
|
546
|
+
}
|
|
547
|
+
const t = s.T;
|
|
548
|
+
if (t.Re !== e) continue;
|
|
549
|
+
if (!(s.l & CONFIG_GUESS) && !s.i && s.se !== NOT_PENDING) {
|
|
550
|
+
t.v = s.se;
|
|
551
|
+
s.se = NOT_PENDING;
|
|
534
552
|
}
|
|
535
553
|
// The frame this pass built is the screen's now; the one it replaced
|
|
536
554
|
// goes (as `commitPendingNode` retires a committed pass's).
|
|
537
|
-
if (
|
|
538
|
-
|
|
555
|
+
if (t.Ue !== null || t.me !== null) GlobalQueue.Ce(s, false, true);
|
|
556
|
+
s.l &= ~CONFIG_STAGED;
|
|
539
557
|
}
|
|
540
558
|
releaseQueues(e);
|
|
541
559
|
}
|
|
@@ -543,10 +561,10 @@ function laneSeam(e, n) {
|
|
|
543
561
|
/** The parent landed: its lanes end, nested first. (None is blocked: a
|
|
544
562
|
* blocked lane blocks its parent.) */ function endLanes(e) {
|
|
545
563
|
for (let n = lanes.length - 1; n >= 0; n--) {
|
|
546
|
-
const
|
|
547
|
-
if (resolveTx(
|
|
548
|
-
endLanes(
|
|
549
|
-
dissolveLane(
|
|
564
|
+
const s = lanes[n];
|
|
565
|
+
if (resolveTx(s._parent) !== e) continue;
|
|
566
|
+
endLanes(s);
|
|
567
|
+
dissolveLane(s, null);
|
|
550
568
|
}
|
|
551
569
|
}
|
|
552
570
|
|
|
@@ -555,14 +573,14 @@ function laneSeam(e, n) {
|
|
|
555
573
|
* frame is not complete without it (A15) — landing it would commit the write
|
|
556
574
|
* beside a derivation still showing the old one. A guess whose own flight is
|
|
557
575
|
* up likewise: the question was asked in this frame. */ function lanesBlocked(e) {
|
|
558
|
-
return e.
|
|
576
|
+
return e.v && linkBlocked(e) || nestedBlocked(e);
|
|
559
577
|
}
|
|
560
578
|
|
|
561
579
|
/** The lanes under `t` (its own; a link group's are each other's). */ function nestedBlocked(e) {
|
|
562
580
|
for (let n = 0; n < lanes.length; n++) {
|
|
563
|
-
const
|
|
564
|
-
if (resolveTx(
|
|
565
|
-
if (blocked(
|
|
581
|
+
const s = lanes[n];
|
|
582
|
+
if (resolveTx(s._parent) !== e) continue;
|
|
583
|
+
if (blocked(s) || guessFlights(s)) return true;
|
|
566
584
|
}
|
|
567
585
|
return false;
|
|
568
586
|
}
|
|
@@ -572,7 +590,7 @@ function laneSeam(e, n) {
|
|
|
572
590
|
* landing), judged against the guess. On a derivation it is the lane's
|
|
573
591
|
* latest: its staging once the lane has shown (promoted at the next
|
|
574
592
|
* reveal), its slot before; the lane's members re-derive as its work. */ function laneWrite(e, n) {
|
|
575
|
-
if (e.
|
|
593
|
+
if (e.l & CONFIG_GUESS) {
|
|
576
594
|
// Provenance (A18, #3331; Q-D, plan sec. 39): a write asking an OLDER
|
|
577
595
|
// question than the guess's — another action's landing beneath it —
|
|
578
596
|
// is not its answer: held beneath (the truth for the commit; the
|
|
@@ -581,20 +599,20 @@ function laneSeam(e, n) {
|
|
|
581
599
|
// continuation's — the flight's); unstamped writes and mainline are
|
|
582
600
|
// current.
|
|
583
601
|
if (stale(e, question)) {
|
|
584
|
-
e.
|
|
585
|
-
e.
|
|
586
|
-
GlobalQueue.
|
|
602
|
+
e.se = n;
|
|
603
|
+
e.l |= CONFIG_HELD;
|
|
604
|
+
GlobalQueue.an?.(e, n);
|
|
587
605
|
schedule();
|
|
588
606
|
return n;
|
|
589
607
|
}
|
|
590
|
-
supersede(e, n, !e.
|
|
608
|
+
supersede(e, n, !e.xe || !e.xe(e.T.v, n));
|
|
591
609
|
} else {
|
|
592
|
-
const
|
|
593
|
-
if (e.
|
|
594
|
-
if (
|
|
595
|
-
if (e.
|
|
610
|
+
const s = txOf(e);
|
|
611
|
+
if (e.xe && e.xe(laneValueOf(e), n)) return n;
|
|
612
|
+
if (s.ke) e.se = n; else e.T.v = n;
|
|
613
|
+
if (e.X !== undefined) e.ie = clock;
|
|
596
614
|
insertSubs(e);
|
|
597
|
-
laneDirty(e,
|
|
615
|
+
laneDirty(e, s);
|
|
598
616
|
}
|
|
599
617
|
schedule();
|
|
600
618
|
return n;
|
|
@@ -611,80 +629,75 @@ function laneSeam(e, n) {
|
|
|
611
629
|
* It is staged beneath the guess, for the commit like any landing, and
|
|
612
630
|
* nothing moves: no downstream re-ask, no pending flip on the guess's
|
|
613
631
|
* readers (`isPending` of the guess itself says the held truth differs,
|
|
614
|
-
* A24). The guess's own question answering supersedes as usual. */ function laneOutcome(e, n,
|
|
615
|
-
if (
|
|
632
|
+
* A24). The guess's own question answering supersedes as usual. */ function laneOutcome(e, n, s) {
|
|
633
|
+
if (s) return true;
|
|
616
634
|
if (stale(e, answered(e))) {
|
|
617
|
-
e.
|
|
618
|
-
e.
|
|
635
|
+
e.se = n;
|
|
636
|
+
e.l |= CONFIG_HELD;
|
|
619
637
|
return true;
|
|
620
638
|
}
|
|
621
|
-
supersede(e, n, !e.
|
|
639
|
+
supersede(e, n, !e.xe || !e.xe(e.T.v, n));
|
|
622
640
|
return true;
|
|
623
641
|
}
|
|
624
642
|
|
|
625
643
|
/** THE provenance test, for a derivation's pass and a write alike: an
|
|
626
644
|
* answer to question `q` landing on a guess is stale when `q` is older
|
|
627
645
|
* than the guess's own; unstamped (0) and mainline are current. */ function stale(e, n) {
|
|
628
|
-
return n !== 0 && n < e.
|
|
646
|
+
return n !== 0 && n < e.T.Ee;
|
|
629
647
|
}
|
|
630
648
|
|
|
631
649
|
/** The question a derivation's pass answered: the newest among the stamped
|
|
632
650
|
* sources that changed this round (a flight's landing carries the question
|
|
633
651
|
* that started it); 0 when none is stamped. */ function answered(e) {
|
|
634
652
|
let n = 0;
|
|
635
|
-
for (let
|
|
636
|
-
const e =
|
|
637
|
-
if (e.
|
|
653
|
+
for (let s = e.C; s !== null; s = s.G) {
|
|
654
|
+
const e = s.S;
|
|
655
|
+
if (e.T !== null && e.T.Ee > n && e.ie === clock) n = e.T.Ee;
|
|
638
656
|
}
|
|
639
657
|
return n;
|
|
640
658
|
}
|
|
641
659
|
|
|
642
|
-
GlobalQueue.Nt = laneRead;
|
|
643
|
-
|
|
644
|
-
GlobalQueue.M = laneStage;
|
|
645
|
-
|
|
646
|
-
GlobalQueue.Qe = laneOutcome;
|
|
647
|
-
|
|
648
|
-
GlobalQueue.Tt = laneWrite;
|
|
649
|
-
|
|
650
660
|
/** The lanes alive before this seam's guesses opened theirs (a prefix of
|
|
651
661
|
* `lanes`; nothing dissolves one between here and the seam loop): a lane
|
|
652
662
|
* born at the seam has no work to judge yet (its passes run next round) —
|
|
653
663
|
* it is neither shown nor blocked until it has. */ let judged = 0;
|
|
654
664
|
|
|
655
|
-
|
|
665
|
+
const applyGuessesAt = e => {
|
|
656
666
|
judged = lanes.length;
|
|
657
667
|
if (pendingGuesses.length !== 0) applyGuesses(e);
|
|
658
668
|
};
|
|
659
669
|
|
|
660
|
-
|
|
670
|
+
const laneSeams = e => {
|
|
661
671
|
// Passes that read a write the parked frame holds as the screen
|
|
662
672
|
// (`stagedReaders`: lane work, a verdict reader before the verdict): they
|
|
663
673
|
// re-derive on the committed world next round (and register as stale
|
|
664
674
|
// readers of the transaction there); a lane's runs wait that round — a
|
|
665
675
|
// lane sees the screen plus its own guesses.
|
|
666
676
|
const n = [];
|
|
667
|
-
if (e !== null) for (let
|
|
668
|
-
const
|
|
669
|
-
const
|
|
677
|
+
if (e !== null) for (let s = 0; s < e.length; s++) {
|
|
678
|
+
const t = e[s];
|
|
679
|
+
const l = t.T?.Re;
|
|
670
680
|
// A verdict reader a later read of the same pass routed into a verdict
|
|
671
681
|
// lane answered for itself: it re-derives at the holder's landing, not
|
|
672
682
|
// now (one run — #3322, #3540). Other verdict-lane work re-derives only
|
|
673
683
|
// if the frame stays parked: a transaction landing at this seam makes
|
|
674
684
|
// what it read the screen (one run).
|
|
675
|
-
if (
|
|
676
|
-
|
|
677
|
-
|
|
685
|
+
if (t.R & REACTIVE_DISPOSED || l != null && l._parent?.he === l && (t.l & CONFIG_VERDICT ? !(t.R & REACTIVE_PROBE_UNANSWERED) : !blocked(l._parent))) continue;
|
|
686
|
+
// A leaked effect re-derives seated in its lane from its first read: it
|
|
687
|
+
// carries no lane value (`laneStage`), so without this its pass starts
|
|
688
|
+
// as mainline, joins the parked frame on its first held read and reads
|
|
689
|
+
// the staging, then re-enters the lane at its guess read and leaks
|
|
690
|
+
// again — every round (#4014). A computed is already seated by its
|
|
691
|
+
// override, and a written guess's own pass stays the frame's.
|
|
692
|
+
if (l != null && l.v && t.i) t.R |= REACTIVE_LANE_DIRTY;
|
|
693
|
+
enqueueSub(t);
|
|
694
|
+
if (l != null && l.v && n.indexOf(l) === -1) n.push(l);
|
|
678
695
|
}
|
|
679
696
|
for (let e = Math.min(judged, lanes.length) - 1; e >= 0; e--) laneSeam(lanes[e], n.indexOf(lanes[e]) !== -1);
|
|
680
697
|
};
|
|
681
698
|
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
GlobalQueue.In = endLanes;
|
|
685
|
-
|
|
686
|
-
GlobalQueue.cn = lanesBlocked;
|
|
699
|
+
installLaneHooks(laneRead, laneStage, laneOutcome, laneWrite, applyGuessesAt, laneSeams, () => lanes.length !== 0 && laneCorrections(), endLanes, lanesBlocked);
|
|
687
700
|
|
|
688
|
-
GlobalQueue.
|
|
701
|
+
GlobalQueue.J = verdictLane;
|
|
689
702
|
|
|
690
703
|
export { display, enterLane, guessedValueOf, laneRead, laneStage, laneValueOf, optimisticWrite, pendingGuessOf, supersede, verdictLane };
|