@solidjs/signals 2.0.0-rc.15 → 2.0.0-rc.17
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 +2268 -1734
- package/dist/dev.attribution.js +75 -52
- package/dist/dev.js +1348 -658
- package/dist/observe/affects-marks.js +86 -0
- package/dist/observe/affects.js +22 -73
- package/dist/observe/boundaries.js +192 -190
- package/dist/observe/core/async.js +177 -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 +5 -3
- package/dist/observe/core/core.js +520 -364
- package/dist/observe/core/dev.js +66 -38
- package/dist/observe/core/effect.js +50 -48
- package/dist/observe/core/error.js +5 -3
- package/dist/observe/core/external.js +5 -6
- package/dist/observe/core/graph.js +60 -44
- package/dist/observe/core/heap.js +33 -33
- package/dist/observe/core/identities.js +62 -0
- package/dist/observe/core/lanes.js +238 -260
- package/dist/observe/core/owner.js +117 -79
- package/dist/observe/core/scheduler.js +381 -217
- package/dist/observe/core/truth.js +45 -0
- package/dist/observe/core/verdict.js +91 -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 +47 -31
- package/dist/observe/store/affects.js +18 -18
- package/dist/observe/store/edges.js +39 -0
- package/dist/observe/store/optimistic.js +146 -100
- package/dist/observe/store/projection.js +68 -55
- package/dist/observe/store/store.js +180 -118
- package/dist/prod/affects-marks.js +86 -0
- package/dist/prod/affects.js +23 -72
- package/dist/prod/boundaries.js +156 -154
- package/dist/prod/core/async.js +173 -127
- package/dist/prod/core/constants.js +17 -3
- package/dist/prod/core/context.js +5 -3
- package/dist/prod/core/core.js +495 -343
- package/dist/prod/core/effect.js +70 -68
- package/dist/prod/core/error.js +5 -3
- package/dist/prod/core/external.js +5 -6
- package/dist/prod/core/graph.js +60 -44
- package/dist/prod/core/heap.js +38 -38
- package/dist/prod/core/identities.js +62 -0
- package/dist/prod/core/lanes.js +230 -252
- package/dist/prod/core/owner.js +114 -77
- package/dist/prod/core/scheduler.js +327 -163
- package/dist/prod/core/truth.js +45 -0
- package/dist/prod/core/verdict.js +90 -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 +42 -26
- package/dist/prod/store/affects.js +6 -6
- package/dist/prod/store/edges.js +39 -0
- package/dist/prod/store/optimistic.js +143 -98
- package/dist/prod/store/projection.js +25 -19
- package/dist/prod/store/store.js +157 -100
- 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 +54 -5
- package/dist/types/core/dev.d.ts +51 -13
- package/dist/types/core/error.d.ts +9 -1
- 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 +9 -3
- package/dist/types/core/scheduler.d.ts +70 -32
- 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,70 @@ 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
|
-
|
|
437
|
+
const s = n.l & CONFIG_GUESS;
|
|
438
|
+
const t = txOf(n);
|
|
439
|
+
// A lane a correction folded under (D-34): store/optimistic.ts reads it.
|
|
440
|
+
// Before the authoritative arm: an `until` outside the lane reads the
|
|
441
|
+
// same truth there, and joins the hold it folded into — its posture over
|
|
442
|
+
// a foreign hold (D-31), which the truth read alone would not take.
|
|
443
|
+
const l = e !== null && t.folded;
|
|
444
|
+
if (l) {
|
|
445
|
+
const s = l(e, n);
|
|
446
|
+
if (s !== NOT_PENDING) return s;
|
|
447
|
+
}
|
|
448
|
+
if (e !== null && e.l & CONFIG_AUTHORITATIVE) return GlobalQueue.rn(n);
|
|
449
|
+
const u = n.m;
|
|
450
|
+
// An errored member's lane value predates its error; the error is the answer (#4106).
|
|
451
|
+
if (!s && u & STATUS_ERROR) return NOT_PENDING;
|
|
462
452
|
if (e === null) return laneValueOf(n);
|
|
463
|
-
|
|
464
|
-
const l = n.S;
|
|
465
|
-
if (!tracking || e.i & CONFIG_CHILDREN_FORBIDDEN) {
|
|
453
|
+
if (!tracking || e.l & CONFIG_CHILDREN_FORBIDDEN) {
|
|
466
454
|
// An untracked read inside lane work derives from the lane like a
|
|
467
455
|
// tracked one, minus the subscription — `untrack` is about
|
|
468
456
|
// dependencies, not about which world a pass derives from (a mapper's
|
|
469
457
|
// row reads under its root, store/map): the pass enters the lane (two
|
|
470
458
|
// lanes read by one pass link, as for tracked reads). Outside lane
|
|
471
459
|
// work, the screen.
|
|
472
|
-
if (passLane === null || e.
|
|
473
|
-
enterLane(
|
|
474
|
-
if (!
|
|
460
|
+
if (passLane === null || e.l & CONFIG_CHILDREN_FORBIDDEN) return display(n);
|
|
461
|
+
enterLane(t, e);
|
|
462
|
+
if (!s && u & STATUS_PENDING) return NOT_PENDING;
|
|
475
463
|
return laneValueOf(n);
|
|
476
464
|
}
|
|
477
|
-
if (e.
|
|
478
|
-
if (!
|
|
465
|
+
if (e.i === EFFECT_RENDER && (passLane === null || !sameLane(passLane, t))) {
|
|
466
|
+
if (!s) {
|
|
479
467
|
// A flight whose value has never shown: nothing to show — the leaf
|
|
480
468
|
// waits on it, and its own frame holds (A15, #3334), not the lane's
|
|
481
469
|
// parent. The landing lands the frame: its own pass (the flush
|
|
482
470
|
// joined its transaction) reads the answer it waited on — the lane's
|
|
483
471
|
// staging, revealed at this seam.
|
|
484
|
-
if (
|
|
485
|
-
if (n.
|
|
472
|
+
if (u & STATUS_PENDING && n.T.v === NOT_PENDING) return NOT_PENDING;
|
|
473
|
+
if (n.se !== NOT_PENDING && e.l & CONFIG_HELD && flushTransaction !== null && resolveTx(flushTransaction) === txOf(e)) return n.se;
|
|
486
474
|
}
|
|
487
|
-
if (
|
|
488
|
-
if (!
|
|
475
|
+
if (t.ln || !s && u & STATUS_PENDING) {
|
|
476
|
+
if (!s && !t.ke && u & STATUS_UNINITIALIZED) throw new NotReadyError(null);
|
|
489
477
|
// Re-derived at the reveal; once per pass (the pass may also be a stale
|
|
490
478
|
// reader of a transaction, REACTIVE_FRAME_READ — both reruns apply).
|
|
491
479
|
if (!(e.R & REACTIVE_SCREEN_READ)) {
|
|
492
480
|
e.R |= REACTIVE_FRAME_READ | REACTIVE_SCREEN_READ;
|
|
493
|
-
|
|
481
|
+
t.En.push(e);
|
|
494
482
|
}
|
|
495
483
|
return display(n);
|
|
496
484
|
}
|
|
497
485
|
}
|
|
498
|
-
enterLane(
|
|
499
|
-
if (!
|
|
486
|
+
enterLane(t, e);
|
|
487
|
+
if (!s && u & STATUS_PENDING) return NOT_PENDING;
|
|
500
488
|
return laneValueOf(n);
|
|
501
489
|
}
|
|
502
490
|
|
|
503
491
|
/** The value a guess covered: the node's committed value — a store slot's
|
|
504
492
|
* asked of the store (a chained link follows the inner store's commits). */ function covered(e) {
|
|
505
|
-
return e.
|
|
493
|
+
return e.l & CONFIG_SLOT_NODE && GlobalQueue.fn !== undefined ? GlobalQueue.fn(e) : e.Ie;
|
|
506
494
|
}
|
|
507
495
|
|
|
508
496
|
/** A guess in `l` whose own truth is in flight (its refetch — authoritative:
|
|
509
497
|
* the landing supersedes, not the body's end). */ function guessFlights(e) {
|
|
510
|
-
for (let n = 0; n < e.
|
|
511
|
-
const
|
|
512
|
-
if (
|
|
498
|
+
for (let n = 0; n < e.tn.length; n++) {
|
|
499
|
+
const s = e.tn[n];
|
|
500
|
+
if (s.l & CONFIG_GUESS && s.T.Re === e && inFlight(s)) return true;
|
|
513
501
|
}
|
|
514
502
|
return false;
|
|
515
503
|
}
|
|
@@ -529,20 +517,20 @@ function supersede(e, n, t) {
|
|
|
529
517
|
* landing.) True when a lane was judged. */ function laneCorrections() {
|
|
530
518
|
let e = false;
|
|
531
519
|
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.
|
|
520
|
+
for (let s = 0; s < n.length; s++) {
|
|
521
|
+
const t = n[s];
|
|
522
|
+
if (lanes.indexOf(t) === -1) continue;
|
|
523
|
+
const l = resolveTx(t._parent);
|
|
524
|
+
if (!l.nt || l.tt !== 0 || l.v || ownFlights(l) || guessFlights(t)) continue;
|
|
537
525
|
e = true;
|
|
538
526
|
// Each guess's truth: the one beneath it (a landing held there), else
|
|
539
527
|
// the one it covered. (A correction dissolves the lane — the others are
|
|
540
528
|
// 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.
|
|
529
|
+
for (let e = 0; e < t.tn.length && lanes.indexOf(t) !== -1; e++) {
|
|
530
|
+
const n = t.tn[e];
|
|
531
|
+
if (n.l & CONFIG_GUESS && n.T.Re === t) {
|
|
532
|
+
const e = n.se !== NOT_PENDING ? n.se : covered(n);
|
|
533
|
+
supersede(n, e, !n.xe || !n.xe(n.T.v, e));
|
|
546
534
|
}
|
|
547
535
|
}
|
|
548
536
|
}
|
|
@@ -553,28 +541,28 @@ function laneSeam(e, n) {
|
|
|
553
541
|
// Blocked — or one of its passes read a write the frame holds this seam:
|
|
554
542
|
// its runs wait, the pass re-derives on the screen next round.
|
|
555
543
|
if (n || blocked(e)) {
|
|
556
|
-
e.
|
|
544
|
+
e.ln = true;
|
|
557
545
|
return;
|
|
558
546
|
}
|
|
559
|
-
e.
|
|
560
|
-
e.
|
|
547
|
+
e.ln = false;
|
|
548
|
+
e.ke = true;
|
|
561
549
|
reruns(e);
|
|
562
|
-
for (let n = 0; n < e.
|
|
563
|
-
const
|
|
564
|
-
if (
|
|
565
|
-
|
|
566
|
-
insertSubs(
|
|
550
|
+
for (let n = 0; n < e.tn.length; n++) {
|
|
551
|
+
const s = e.tn[n];
|
|
552
|
+
if (s.R & LEFT_SHOWN) {
|
|
553
|
+
s.R ^= LEFT_SHOWN;
|
|
554
|
+
insertSubs(s);
|
|
567
555
|
}
|
|
568
|
-
const
|
|
569
|
-
if (
|
|
570
|
-
if (!(
|
|
571
|
-
|
|
572
|
-
|
|
556
|
+
const t = s.T;
|
|
557
|
+
if (t.Re !== e) continue;
|
|
558
|
+
if (!(s.l & CONFIG_GUESS) && !s.i && s.se !== NOT_PENDING) {
|
|
559
|
+
t.v = s.se;
|
|
560
|
+
s.se = NOT_PENDING;
|
|
573
561
|
}
|
|
574
562
|
// The frame this pass built is the screen's now; the one it replaced
|
|
575
563
|
// goes (as `commitPendingNode` retires a committed pass's).
|
|
576
|
-
if (
|
|
577
|
-
|
|
564
|
+
if (t.Ue !== null || t.me !== null) GlobalQueue.Ce(s, false, true);
|
|
565
|
+
s.l &= ~CONFIG_STAGED;
|
|
578
566
|
}
|
|
579
567
|
releaseQueues(e);
|
|
580
568
|
}
|
|
@@ -582,10 +570,10 @@ function laneSeam(e, n) {
|
|
|
582
570
|
/** The parent landed: its lanes end, nested first. (None is blocked: a
|
|
583
571
|
* blocked lane blocks its parent.) */ function endLanes(e) {
|
|
584
572
|
for (let n = lanes.length - 1; n >= 0; n--) {
|
|
585
|
-
const
|
|
586
|
-
if (resolveTx(
|
|
587
|
-
endLanes(
|
|
588
|
-
dissolveLane(
|
|
573
|
+
const s = lanes[n];
|
|
574
|
+
if (resolveTx(s._parent) !== e) continue;
|
|
575
|
+
endLanes(s);
|
|
576
|
+
dissolveLane(s, null);
|
|
589
577
|
}
|
|
590
578
|
}
|
|
591
579
|
|
|
@@ -594,14 +582,14 @@ function laneSeam(e, n) {
|
|
|
594
582
|
* frame is not complete without it (A15) — landing it would commit the write
|
|
595
583
|
* beside a derivation still showing the old one. A guess whose own flight is
|
|
596
584
|
* up likewise: the question was asked in this frame. */ function lanesBlocked(e) {
|
|
597
|
-
return e.
|
|
585
|
+
return e.v && linkBlocked(e) || nestedBlocked(e);
|
|
598
586
|
}
|
|
599
587
|
|
|
600
588
|
/** The lanes under `t` (its own; a link group's are each other's). */ function nestedBlocked(e) {
|
|
601
589
|
for (let n = 0; n < lanes.length; n++) {
|
|
602
|
-
const
|
|
603
|
-
if (resolveTx(
|
|
604
|
-
if (blocked(
|
|
590
|
+
const s = lanes[n];
|
|
591
|
+
if (resolveTx(s._parent) !== e) continue;
|
|
592
|
+
if (blocked(s) || guessFlights(s)) return true;
|
|
605
593
|
}
|
|
606
594
|
return false;
|
|
607
595
|
}
|
|
@@ -611,7 +599,7 @@ function laneSeam(e, n) {
|
|
|
611
599
|
* landing), judged against the guess. On a derivation it is the lane's
|
|
612
600
|
* latest: its staging once the lane has shown (promoted at the next
|
|
613
601
|
* reveal), its slot before; the lane's members re-derive as its work. */ function laneWrite(e, n) {
|
|
614
|
-
if (e.
|
|
602
|
+
if (e.l & CONFIG_GUESS) {
|
|
615
603
|
// Provenance (A18, #3331; Q-D, plan sec. 39): a write asking an OLDER
|
|
616
604
|
// question than the guess's — another action's landing beneath it —
|
|
617
605
|
// is not its answer: held beneath (the truth for the commit; the
|
|
@@ -619,21 +607,23 @@ function laneSeam(e, n) {
|
|
|
619
607
|
// question is the one being asked (`question`: a slice's, a derive's
|
|
620
608
|
// continuation's — the flight's); unstamped writes and mainline are
|
|
621
609
|
// current.
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
610
|
+
// A store re-bases a keyed arrangement guess over an older truth, and
|
|
611
|
+
// folds a current one beneath it (D-34): true.
|
|
612
|
+
const s = stale(e, question);
|
|
613
|
+
if (GlobalQueue.an?.(e, n, s) || s) {
|
|
614
|
+
e.se = n;
|
|
615
|
+
e.l |= CONFIG_HELD;
|
|
626
616
|
schedule();
|
|
627
617
|
return n;
|
|
628
618
|
}
|
|
629
|
-
supersede(e, n, !e.
|
|
619
|
+
supersede(e, n, !e.xe || !e.xe(e.T.v, n));
|
|
630
620
|
} else {
|
|
631
|
-
const
|
|
632
|
-
if (e.
|
|
633
|
-
if (
|
|
634
|
-
if (e.
|
|
621
|
+
const s = txOf(e);
|
|
622
|
+
if (e.xe && e.xe(laneValueOf(e), n)) return n;
|
|
623
|
+
if (s.ke) e.se = n; else e.T.v = n;
|
|
624
|
+
if (e.X !== undefined) e.ie = clock;
|
|
635
625
|
insertSubs(e);
|
|
636
|
-
laneDirty(e,
|
|
626
|
+
laneDirty(e, s);
|
|
637
627
|
}
|
|
638
628
|
schedule();
|
|
639
629
|
return n;
|
|
@@ -650,87 +640,75 @@ function laneSeam(e, n) {
|
|
|
650
640
|
* It is staged beneath the guess, for the commit like any landing, and
|
|
651
641
|
* nothing moves: no downstream re-ask, no pending flip on the guess's
|
|
652
642
|
* 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 (
|
|
643
|
+
* A24). The guess's own question answering supersedes as usual. */ function laneOutcome(e, n, s) {
|
|
644
|
+
if (s) return true;
|
|
655
645
|
if (stale(e, answered(e))) {
|
|
656
|
-
e.
|
|
657
|
-
e.
|
|
646
|
+
e.se = n;
|
|
647
|
+
e.l |= CONFIG_HELD;
|
|
658
648
|
return true;
|
|
659
649
|
}
|
|
660
|
-
supersede(e, n, !e.
|
|
650
|
+
supersede(e, n, !e.xe || !e.xe(e.T.v, n));
|
|
661
651
|
return true;
|
|
662
652
|
}
|
|
663
653
|
|
|
664
654
|
/** THE provenance test, for a derivation's pass and a write alike: an
|
|
665
655
|
* answer to question `q` landing on a guess is stale when `q` is older
|
|
666
656
|
* than the guess's own; unstamped (0) and mainline are current. */ function stale(e, n) {
|
|
667
|
-
return n !== 0 && n < e.
|
|
657
|
+
return n !== 0 && n < e.T.Ee;
|
|
668
658
|
}
|
|
669
659
|
|
|
670
660
|
/** The question a derivation's pass answered: the newest among the stamped
|
|
671
661
|
* sources that changed this round (a flight's landing carries the question
|
|
672
662
|
* that started it); 0 when none is stamped. */ function answered(e) {
|
|
673
663
|
let n = 0;
|
|
674
|
-
for (let
|
|
675
|
-
const e =
|
|
676
|
-
if (e.
|
|
664
|
+
for (let s = e.C; s !== null; s = s.G) {
|
|
665
|
+
const e = s.S;
|
|
666
|
+
if (e.T !== null && e.T.Ee > n && e.ie === clock) n = e.T.Ee;
|
|
677
667
|
}
|
|
678
668
|
return n;
|
|
679
669
|
}
|
|
680
670
|
|
|
681
|
-
GlobalQueue.rt = laneRead;
|
|
682
|
-
|
|
683
|
-
GlobalQueue.W = laneStage;
|
|
684
|
-
|
|
685
|
-
GlobalQueue.We = laneOutcome;
|
|
686
|
-
|
|
687
|
-
GlobalQueue.Nt = laneWrite;
|
|
688
|
-
|
|
689
671
|
/** The lanes alive before this seam's guesses opened theirs (a prefix of
|
|
690
672
|
* `lanes`; nothing dissolves one between here and the seam loop): a lane
|
|
691
673
|
* born at the seam has no work to judge yet (its passes run next round) —
|
|
692
674
|
* it is neither shown nor blocked until it has. */ let judged = 0;
|
|
693
675
|
|
|
694
|
-
|
|
676
|
+
const applyGuessesAt = e => {
|
|
695
677
|
judged = lanes.length;
|
|
696
678
|
if (pendingGuesses.length !== 0) applyGuesses(e);
|
|
697
679
|
};
|
|
698
680
|
|
|
699
|
-
|
|
681
|
+
const laneSeams = e => {
|
|
700
682
|
// Passes that read a write the parked frame holds as the screen
|
|
701
683
|
// (`stagedReaders`: lane work, a verdict reader before the verdict): they
|
|
702
684
|
// re-derive on the committed world next round (and register as stale
|
|
703
685
|
// readers of the transaction there); a lane's runs wait that round — a
|
|
704
686
|
// lane sees the screen plus its own guesses.
|
|
705
687
|
const n = [];
|
|
706
|
-
if (e !== null) for (let
|
|
707
|
-
const
|
|
708
|
-
const l =
|
|
688
|
+
if (e !== null) for (let s = 0; s < e.length; s++) {
|
|
689
|
+
const t = e[s];
|
|
690
|
+
const l = t.T?.Re;
|
|
709
691
|
// A verdict reader a later read of the same pass routed into a verdict
|
|
710
692
|
// lane answered for itself: it re-derives at the holder's landing, not
|
|
711
693
|
// now (one run — #3322, #3540). Other verdict-lane work re-derives only
|
|
712
694
|
// if the frame stays parked: a transaction landing at this seam makes
|
|
713
695
|
// what it read the screen (one run).
|
|
714
|
-
if (
|
|
696
|
+
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
697
|
// A leaked effect re-derives seated in its lane from its first read: it
|
|
716
698
|
// carries no lane value (`laneStage`), so without this its pass starts
|
|
717
699
|
// as mainline, joins the parked frame on its first held read and reads
|
|
718
700
|
// the staging, then re-enters the lane at its guess read and leaks
|
|
719
701
|
// again — every round (#4014). A computed is already seated by its
|
|
720
702
|
// override, and a written guess's own pass stays the frame's.
|
|
721
|
-
if (l != null && l.
|
|
722
|
-
enqueueSub(
|
|
723
|
-
if (l != null && l.
|
|
703
|
+
if (l != null && l.v && t.i) t.R |= REACTIVE_LANE_DIRTY;
|
|
704
|
+
enqueueSub(t);
|
|
705
|
+
if (l != null && l.v && n.indexOf(l) === -1) n.push(l);
|
|
724
706
|
}
|
|
725
707
|
for (let e = Math.min(judged, lanes.length) - 1; e >= 0; e--) laneSeam(lanes[e], n.indexOf(lanes[e]) !== -1);
|
|
726
708
|
};
|
|
727
709
|
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
GlobalQueue.Gn = endLanes;
|
|
731
|
-
|
|
732
|
-
GlobalQueue.On = lanesBlocked;
|
|
710
|
+
installLaneHooks(laneRead, laneStage, laneOutcome, laneWrite, applyGuessesAt, laneSeams, () => lanes.length !== 0 && laneCorrections(), endLanes, lanesBlocked);
|
|
733
711
|
|
|
734
|
-
GlobalQueue
|
|
712
|
+
GlobalQueue.J = verdictLane;
|
|
735
713
|
|
|
736
|
-
export { display, enterLane, guessedValueOf, laneRead, laneStage, laneValueOf, optimisticWrite, pendingGuessOf, supersede,
|
|
714
|
+
export { display, enterLane, guessedValueOf, laneRead, laneStage, laneValueOf, optimisticWrite, pendingGuessOf, supersede, verdictLane };
|