@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
|
@@ -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,70 @@ 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
|
-
|
|
463
|
+
const s = n.l & CONFIG_GUESS;
|
|
464
|
+
const t = txOf(n);
|
|
465
|
+
// A lane a correction folded under (D-34): store/optimistic.ts reads it.
|
|
466
|
+
// Before the authoritative arm: an `until` outside the lane reads the
|
|
467
|
+
// same truth there, and joins the hold it folded into — its posture over
|
|
468
|
+
// a foreign hold (D-31), which the truth read alone would not take.
|
|
469
|
+
const l = e !== null && t.folded;
|
|
470
|
+
if (l) {
|
|
471
|
+
const s = l(e, n);
|
|
472
|
+
if (s !== NOT_PENDING) return s;
|
|
473
|
+
}
|
|
474
|
+
if (e !== null && e.l & CONFIG_AUTHORITATIVE) return GlobalQueue.rn(n);
|
|
475
|
+
const u = n.m;
|
|
476
|
+
// An errored member's lane value predates its error; the error is the answer (#4106).
|
|
477
|
+
if (!s && u & STATUS_ERROR) return NOT_PENDING;
|
|
488
478
|
if (e === null) return laneValueOf(n);
|
|
489
|
-
|
|
490
|
-
const l = n.S;
|
|
491
|
-
if (!tracking || e.i & CONFIG_CHILDREN_FORBIDDEN) {
|
|
479
|
+
if (!tracking || e.l & CONFIG_CHILDREN_FORBIDDEN) {
|
|
492
480
|
// An untracked read inside lane work derives from the lane like a
|
|
493
481
|
// tracked one, minus the subscription — `untrack` is about
|
|
494
482
|
// dependencies, not about which world a pass derives from (a mapper's
|
|
495
483
|
// row reads under its root, store/map): the pass enters the lane (two
|
|
496
484
|
// lanes read by one pass link, as for tracked reads). Outside lane
|
|
497
485
|
// work, the screen.
|
|
498
|
-
if (passLane === null || e.
|
|
499
|
-
enterLane(
|
|
500
|
-
if (!
|
|
486
|
+
if (passLane === null || e.l & CONFIG_CHILDREN_FORBIDDEN) return display(n);
|
|
487
|
+
enterLane(t, e);
|
|
488
|
+
if (!s && u & STATUS_PENDING) return NOT_PENDING;
|
|
501
489
|
return laneValueOf(n);
|
|
502
490
|
}
|
|
503
|
-
if (e.
|
|
504
|
-
if (!
|
|
491
|
+
if (e.i === EFFECT_RENDER && (passLane === null || !sameLane(passLane, t))) {
|
|
492
|
+
if (!s) {
|
|
505
493
|
// A flight whose value has never shown: nothing to show — the leaf
|
|
506
494
|
// waits on it, and its own frame holds (A15, #3334), not the lane's
|
|
507
495
|
// parent. The landing lands the frame: its own pass (the flush
|
|
508
496
|
// joined its transaction) reads the answer it waited on — the lane's
|
|
509
497
|
// staging, revealed at this seam.
|
|
510
|
-
if (
|
|
511
|
-
if (n.
|
|
498
|
+
if (u & STATUS_PENDING && n.T.V === NOT_PENDING) return NOT_PENDING;
|
|
499
|
+
if (n.ue !== NOT_PENDING && e.l & CONFIG_HELD && flushTransaction !== null && resolveTx(flushTransaction) === txOf(e)) return n.ue;
|
|
512
500
|
}
|
|
513
|
-
if (
|
|
514
|
-
if (!
|
|
501
|
+
if (t.ln || !s && u & STATUS_PENDING) {
|
|
502
|
+
if (!s && !t.It && u & STATUS_UNINITIALIZED) throw new NotReadyError(null);
|
|
515
503
|
// Re-derived at the reveal; once per pass (the pass may also be a stale
|
|
516
504
|
// reader of a transaction, REACTIVE_FRAME_READ — both reruns apply).
|
|
517
505
|
if (!(e.R & REACTIVE_SCREEN_READ)) {
|
|
518
506
|
e.R |= REACTIVE_FRAME_READ | REACTIVE_SCREEN_READ;
|
|
519
|
-
|
|
507
|
+
t.En.push(e);
|
|
520
508
|
}
|
|
521
509
|
return display(n);
|
|
522
510
|
}
|
|
523
511
|
}
|
|
524
|
-
enterLane(
|
|
525
|
-
if (!
|
|
512
|
+
enterLane(t, e);
|
|
513
|
+
if (!s && u & STATUS_PENDING) return NOT_PENDING;
|
|
526
514
|
return laneValueOf(n);
|
|
527
515
|
}
|
|
528
516
|
|
|
529
517
|
/** The value a guess covered: the node's committed value — a store slot's
|
|
530
518
|
* asked of the store (a chained link follows the inner store's commits). */ function covered(e) {
|
|
531
|
-
return e.
|
|
519
|
+
return e.l & CONFIG_SLOT_NODE && GlobalQueue.fn !== undefined ? GlobalQueue.fn(e) : e.Ie;
|
|
532
520
|
}
|
|
533
521
|
|
|
534
522
|
/** A guess in `l` whose own truth is in flight (its refetch — authoritative:
|
|
535
523
|
* the landing supersedes, not the body's end). */ function guessFlights(e) {
|
|
536
|
-
for (let n = 0; n < e.
|
|
537
|
-
const
|
|
538
|
-
if (
|
|
524
|
+
for (let n = 0; n < e.je.length; n++) {
|
|
525
|
+
const s = e.je[n];
|
|
526
|
+
if (s.l & CONFIG_GUESS && s.T.Je === e && inFlight(s)) return true;
|
|
539
527
|
}
|
|
540
528
|
return false;
|
|
541
529
|
}
|
|
@@ -555,21 +543,21 @@ function supersede(e, n, t) {
|
|
|
555
543
|
* landing.) True when a lane was judged. */ function laneCorrections() {
|
|
556
544
|
let e = false;
|
|
557
545
|
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.
|
|
546
|
+
for (let s = 0; s < n.length; s++) {
|
|
547
|
+
const t = n[s];
|
|
548
|
+
if (lanes.indexOf(t) === -1) continue;
|
|
549
|
+
const l = resolveTx(t._parent);
|
|
550
|
+
if (!l.nt || l.tt !== 0 || l.V || ownFlights(l) || guessFlights(t)) continue;
|
|
563
551
|
e = true;
|
|
564
552
|
// Each guess's truth: the one beneath it (a landing held there), else
|
|
565
553
|
// the one it covered. (A correction dissolves the lane — the others are
|
|
566
554
|
// 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.
|
|
555
|
+
for (let e = 0; e < t.je.length && lanes.indexOf(t) !== -1; e++) {
|
|
556
|
+
const n = t.je[e];
|
|
557
|
+
if (n.l & CONFIG_GUESS && n.T.Je === t) {
|
|
558
|
+
const e = n.ue !== NOT_PENDING ? n.ue : covered(n);
|
|
559
|
+
reverting = n.ue === NOT_PENDING;
|
|
560
|
+
supersede(n, e, !n.Ye || !n.Ye(n.T.V, e));
|
|
573
561
|
reverting = false;
|
|
574
562
|
}
|
|
575
563
|
}
|
|
@@ -581,28 +569,28 @@ function laneSeam(e, n) {
|
|
|
581
569
|
// Blocked — or one of its passes read a write the frame holds this seam:
|
|
582
570
|
// its runs wait, the pass re-derives on the screen next round.
|
|
583
571
|
if (n || blocked(e)) {
|
|
584
|
-
e.
|
|
572
|
+
e.ln = true;
|
|
585
573
|
return;
|
|
586
574
|
}
|
|
587
|
-
e.
|
|
588
|
-
e.
|
|
575
|
+
e.ln = false;
|
|
576
|
+
e.It = true;
|
|
589
577
|
reruns(e);
|
|
590
|
-
for (let n = 0; n < e.
|
|
591
|
-
const
|
|
592
|
-
if (
|
|
593
|
-
|
|
594
|
-
insertSubs(
|
|
578
|
+
for (let n = 0; n < e.je.length; n++) {
|
|
579
|
+
const s = e.je[n];
|
|
580
|
+
if (s.R & LEFT_SHOWN) {
|
|
581
|
+
s.R ^= LEFT_SHOWN;
|
|
582
|
+
insertSubs(s);
|
|
595
583
|
}
|
|
596
|
-
const
|
|
597
|
-
if (
|
|
598
|
-
if (!(
|
|
599
|
-
|
|
600
|
-
|
|
584
|
+
const t = s.T;
|
|
585
|
+
if (t.Je !== e) continue;
|
|
586
|
+
if (!(s.l & CONFIG_GUESS) && !s.i && s.ue !== NOT_PENDING) {
|
|
587
|
+
t.V = s.ue;
|
|
588
|
+
s.ue = NOT_PENDING;
|
|
601
589
|
}
|
|
602
590
|
// The frame this pass built is the screen's now; the one it replaced
|
|
603
591
|
// goes (as `commitPendingNode` retires a committed pass's).
|
|
604
|
-
if (
|
|
605
|
-
|
|
592
|
+
if (t.Nt !== null || t.ft !== null) GlobalQueue.et(s, false, true);
|
|
593
|
+
s.l &= ~CONFIG_STAGED;
|
|
606
594
|
}
|
|
607
595
|
releaseQueues(e);
|
|
608
596
|
}
|
|
@@ -610,10 +598,10 @@ function laneSeam(e, n) {
|
|
|
610
598
|
/** The parent landed: its lanes end, nested first. (None is blocked: a
|
|
611
599
|
* blocked lane blocks its parent.) */ function endLanes(e) {
|
|
612
600
|
for (let n = lanes.length - 1; n >= 0; n--) {
|
|
613
|
-
const
|
|
614
|
-
if (resolveTx(
|
|
615
|
-
endLanes(
|
|
616
|
-
dissolveLane(
|
|
601
|
+
const s = lanes[n];
|
|
602
|
+
if (resolveTx(s._parent) !== e) continue;
|
|
603
|
+
endLanes(s);
|
|
604
|
+
dissolveLane(s, null);
|
|
617
605
|
}
|
|
618
606
|
}
|
|
619
607
|
|
|
@@ -622,14 +610,14 @@ function laneSeam(e, n) {
|
|
|
622
610
|
* frame is not complete without it (A15) — landing it would commit the write
|
|
623
611
|
* beside a derivation still showing the old one. A guess whose own flight is
|
|
624
612
|
* up likewise: the question was asked in this frame. */ function lanesBlocked(e) {
|
|
625
|
-
return e.
|
|
613
|
+
return e.V && linkBlocked(e) || nestedBlocked(e);
|
|
626
614
|
}
|
|
627
615
|
|
|
628
616
|
/** The lanes under `t` (its own; a link group's are each other's). */ function nestedBlocked(e) {
|
|
629
617
|
for (let n = 0; n < lanes.length; n++) {
|
|
630
|
-
const
|
|
631
|
-
if (resolveTx(
|
|
632
|
-
if (blocked(
|
|
618
|
+
const s = lanes[n];
|
|
619
|
+
if (resolveTx(s._parent) !== e) continue;
|
|
620
|
+
if (blocked(s) || guessFlights(s)) return true;
|
|
633
621
|
}
|
|
634
622
|
return false;
|
|
635
623
|
}
|
|
@@ -639,7 +627,7 @@ function laneSeam(e, n) {
|
|
|
639
627
|
* landing), judged against the guess. On a derivation it is the lane's
|
|
640
628
|
* latest: its staging once the lane has shown (promoted at the next
|
|
641
629
|
* reveal), its slot before; the lane's members re-derive as its work. */ function laneWrite(e, n) {
|
|
642
|
-
if (e.
|
|
630
|
+
if (e.l & CONFIG_GUESS) {
|
|
643
631
|
// Provenance (A18, #3331; Q-D, plan sec. 39): a write asking an OLDER
|
|
644
632
|
// question than the guess's — another action's landing beneath it —
|
|
645
633
|
// is not its answer: held beneath (the truth for the commit; the
|
|
@@ -647,21 +635,23 @@ function laneSeam(e, n) {
|
|
|
647
635
|
// question is the one being asked (`question`: a slice's, a derive's
|
|
648
636
|
// continuation's — the flight's); unstamped writes and mainline are
|
|
649
637
|
// current.
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
638
|
+
// A store re-bases a keyed arrangement guess over an older truth, and
|
|
639
|
+
// folds a current one beneath it (D-34): true.
|
|
640
|
+
const s = stale(e, question);
|
|
641
|
+
if (GlobalQueue.an?.(e, n, s) || s) {
|
|
642
|
+
e.ue = n;
|
|
643
|
+
e.l |= CONFIG_HELD;
|
|
654
644
|
schedule();
|
|
655
645
|
return n;
|
|
656
646
|
}
|
|
657
|
-
supersede(e, n, !e.
|
|
647
|
+
supersede(e, n, !e.Ye || !e.Ye(e.T.V, n));
|
|
658
648
|
} else {
|
|
659
|
-
const
|
|
660
|
-
if (e.
|
|
661
|
-
if (
|
|
662
|
-
if (e.
|
|
649
|
+
const s = txOf(e);
|
|
650
|
+
if (e.Ye && e.Ye(laneValueOf(e), n)) return n;
|
|
651
|
+
if (s.It) e.ue = n; else e.T.V = n;
|
|
652
|
+
if (e.X !== undefined) e.ie = clock;
|
|
663
653
|
insertSubs(e);
|
|
664
|
-
laneDirty(e,
|
|
654
|
+
laneDirty(e, s);
|
|
665
655
|
}
|
|
666
656
|
schedule();
|
|
667
657
|
return n;
|
|
@@ -678,97 +668,85 @@ function laneSeam(e, n) {
|
|
|
678
668
|
* It is staged beneath the guess, for the commit like any landing, and
|
|
679
669
|
* nothing moves: no downstream re-ask, no pending flip on the guess's
|
|
680
670
|
* 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 (
|
|
671
|
+
* A24). The guess's own question answering supersedes as usual. */ function laneOutcome(e, n, s) {
|
|
672
|
+
if (s) return true;
|
|
683
673
|
if (stale(e, answered(e))) {
|
|
684
|
-
e.
|
|
685
|
-
e.
|
|
674
|
+
e.ue = n;
|
|
675
|
+
e.l |= CONFIG_HELD;
|
|
686
676
|
return true;
|
|
687
677
|
}
|
|
688
|
-
supersede(e, n, !e.
|
|
678
|
+
supersede(e, n, !e.Ye || !e.Ye(e.T.V, n));
|
|
689
679
|
return true;
|
|
690
680
|
}
|
|
691
681
|
|
|
692
682
|
/** THE provenance test, for a derivation's pass and a write alike: an
|
|
693
683
|
* answer to question `q` landing on a guess is stale when `q` is older
|
|
694
684
|
* than the guess's own; unstamped (0) and mainline are current. */ function stale(e, n) {
|
|
695
|
-
return n !== 0 && n < e.
|
|
685
|
+
return n !== 0 && n < e.T.Ee;
|
|
696
686
|
}
|
|
697
687
|
|
|
698
688
|
/** The question a derivation's pass answered: the newest among the stamped
|
|
699
689
|
* sources that changed this round (a flight's landing carries the question
|
|
700
690
|
* that started it); 0 when none is stamped. */ function answered(e) {
|
|
701
691
|
let n = 0;
|
|
702
|
-
for (let
|
|
703
|
-
const e =
|
|
704
|
-
if (e.
|
|
692
|
+
for (let s = e.C; s !== null; s = s.G) {
|
|
693
|
+
const e = s.S;
|
|
694
|
+
if (e.T !== null && e.T.Ee > n && e.ie === clock) n = e.T.Ee;
|
|
705
695
|
}
|
|
706
696
|
return n;
|
|
707
697
|
}
|
|
708
698
|
|
|
709
|
-
GlobalQueue.Zt = laneRead;
|
|
710
|
-
|
|
711
|
-
GlobalQueue.W = laneStage;
|
|
712
|
-
|
|
713
|
-
GlobalQueue.ft = laneOutcome;
|
|
714
|
-
|
|
715
|
-
GlobalQueue.Qt = laneWrite;
|
|
716
|
-
|
|
717
699
|
/** The lanes alive before this seam's guesses opened theirs (a prefix of
|
|
718
700
|
* `lanes`; nothing dissolves one between here and the seam loop): a lane
|
|
719
701
|
* born at the seam has no work to judge yet (its passes run next round) —
|
|
720
702
|
* it is neither shown nor blocked until it has. */ let judged = 0;
|
|
721
703
|
|
|
722
|
-
|
|
704
|
+
const applyGuessesAt = e => {
|
|
723
705
|
judged = lanes.length;
|
|
724
706
|
if (pendingGuesses.length !== 0) applyGuesses(e);
|
|
725
707
|
};
|
|
726
708
|
|
|
727
|
-
|
|
709
|
+
const laneSeams = e => {
|
|
728
710
|
// Passes that read a write the parked frame holds as the screen
|
|
729
711
|
// (`stagedReaders`: lane work, a verdict reader before the verdict): they
|
|
730
712
|
// re-derive on the committed world next round (and register as stale
|
|
731
713
|
// readers of the transaction there); a lane's runs wait that round — a
|
|
732
714
|
// lane sees the screen plus its own guesses.
|
|
733
715
|
const n = [];
|
|
734
|
-
if (e !== null) for (let
|
|
735
|
-
const
|
|
736
|
-
const l =
|
|
716
|
+
if (e !== null) for (let s = 0; s < e.length; s++) {
|
|
717
|
+
const t = e[s];
|
|
718
|
+
const l = t.T?.Je;
|
|
737
719
|
// A verdict reader a later read of the same pass routed into a verdict
|
|
738
720
|
// lane answered for itself: it re-derives at the holder's landing, not
|
|
739
721
|
// now (one run — #3322, #3540). Other verdict-lane work re-derives only
|
|
740
722
|
// if the frame stays parked: a transaction landing at this seam makes
|
|
741
723
|
// what it read the screen (one run).
|
|
742
|
-
if (
|
|
724
|
+
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
725
|
// A leaked effect re-derives seated in its lane from its first read: it
|
|
744
726
|
// carries no lane value (`laneStage`), so without this its pass starts
|
|
745
727
|
// as mainline, joins the parked frame on its first held read and reads
|
|
746
728
|
// the staging, then re-enters the lane at its guess read and leaks
|
|
747
729
|
// again — every round (#4014). A computed is already seated by its
|
|
748
730
|
// override, and a written guess's own pass stays the frame's.
|
|
749
|
-
if (l != null && l.
|
|
750
|
-
enqueueSub(
|
|
751
|
-
if (l != null && l.
|
|
731
|
+
if (l != null && l.V && t.i) t.R |= REACTIVE_LANE_DIRTY;
|
|
732
|
+
enqueueSub(t);
|
|
733
|
+
if (l != null && l.V && n.indexOf(l) === -1) n.push(l);
|
|
752
734
|
}
|
|
753
735
|
for (let e = Math.min(judged, lanes.length) - 1; e >= 0; e--) laneSeam(lanes[e], n.indexOf(lanes[e]) !== -1);
|
|
754
736
|
};
|
|
755
737
|
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
GlobalQueue.Tn = endLanes;
|
|
738
|
+
installLaneHooks(laneRead, laneStage, laneOutcome, laneWrite, applyGuessesAt, laneSeams, () => lanes.length !== 0 && laneCorrections(), endLanes, lanesBlocked);
|
|
759
739
|
|
|
760
|
-
GlobalQueue.
|
|
740
|
+
GlobalQueue.Ke = e => {
|
|
761
741
|
const n = [];
|
|
762
|
-
for (let
|
|
763
|
-
const
|
|
764
|
-
if (resolveTx(
|
|
765
|
-
for (let e = 0; e <
|
|
742
|
+
for (let s = 0; s < lanes.length; s++) {
|
|
743
|
+
const t = lanes[s];
|
|
744
|
+
if (resolveTx(t._parent) !== e) continue;
|
|
745
|
+
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
746
|
}
|
|
767
747
|
return n;
|
|
768
748
|
};
|
|
769
749
|
|
|
770
|
-
GlobalQueue.
|
|
771
|
-
|
|
772
|
-
GlobalQueue.$ = verdictLane;
|
|
750
|
+
GlobalQueue.J = verdictLane;
|
|
773
751
|
|
|
774
|
-
export { display, enterLane, guessedValueOf, laneRead, laneStage, laneValueOf, optimisticWrite, pendingGuessOf, supersede,
|
|
752
|
+
export { display, enterLane, guessedValueOf, laneRead, laneStage, laneValueOf, optimisticWrite, pendingGuessOf, supersede, verdictLane };
|