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