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