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