@solidjs/signals 2.0.0-rc.19 → 2.0.0-rc.20
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 +553 -264
- package/dist/dev.attribution.js +18 -18
- package/dist/dev.js +1030 -439
- package/dist/observe/affects.js +12 -2
- package/dist/observe/boundaries.js +168 -115
- package/dist/observe/core/async.js +57 -37
- package/dist/observe/core/attribution.js +6 -6
- package/dist/observe/core/constants.js +9 -1
- package/dist/observe/core/copies.js +10 -0
- package/dist/observe/core/core.js +261 -181
- package/dist/observe/core/effect.js +32 -27
- package/dist/observe/core/graph.js +7 -7
- package/dist/observe/core/heap.js +29 -29
- package/dist/observe/core/lanes.js +301 -101
- package/dist/observe/core/owner.js +13 -13
- package/dist/observe/core/scheduler.js +124 -69
- package/dist/observe/core/truth.js +9 -7
- package/dist/observe/core/verdict.js +160 -98
- package/dist/observe/deferred.js +1 -1
- package/dist/observe/index.js +2 -0
- package/dist/observe/map.js +120 -116
- package/dist/observe/reveal.js +48 -48
- package/dist/observe/signals.js +5 -5
- package/dist/observe/store/affects.js +2 -2
- package/dist/observe/store/optimistic.js +272 -176
- package/dist/observe/store/projection.js +21 -10
- package/dist/observe/store/reconcile.js +8 -2
- package/dist/observe/store/store.js +91 -55
- package/dist/observe/store/types.js +11 -1
- package/dist/observe/store/utils.js +1 -1
- package/dist/prod/affects.js +12 -2
- package/dist/prod/boundaries.js +164 -109
- package/dist/prod/core/async.js +201 -181
- package/dist/prod/core/constants.js +9 -1
- package/dist/prod/core/copies.js +10 -0
- package/dist/prod/core/core.js +244 -164
- package/dist/prod/core/dev.js +108 -3
- package/dist/prod/core/effect.js +28 -23
- package/dist/prod/core/graph.js +9 -9
- package/dist/prod/core/heap.js +16 -16
- package/dist/prod/core/identities.js +1 -1
- package/dist/prod/core/lanes.js +307 -95
- package/dist/prod/core/owner.js +22 -22
- package/dist/prod/core/scheduler.js +266 -211
- package/dist/prod/core/truth.js +9 -7
- package/dist/prod/core/verdict.js +161 -99
- package/dist/prod/deferred.js +1 -1
- package/dist/prod/index.js +2 -0
- package/dist/prod/map.js +78 -74
- package/dist/prod/reveal.js +34 -34
- package/dist/prod/signals.js +3 -3
- package/dist/prod/store/affects.js +15 -15
- package/dist/prod/store/optimistic.js +185 -89
- package/dist/prod/store/projection.js +49 -38
- package/dist/prod/store/reconcile.js +8 -2
- package/dist/prod/store/store.js +99 -63
- package/dist/prod/store/types.js +11 -1
- package/dist/types/affects.d.ts +3 -2
- package/dist/types/boundaries.d.ts +14 -2
- package/dist/types/core/async.d.ts +2 -1
- package/dist/types/core/constants.d.ts +8 -0
- package/dist/types/core/copies.d.ts +54 -0
- package/dist/types/core/core.d.ts +15 -0
- package/dist/types/core/dev.d.ts +1 -1
- package/dist/types/core/lanes.d.ts +8 -1
- package/dist/types/core/scheduler.d.ts +36 -4
- package/dist/types/core/truth.d.ts +3 -1
- package/dist/types/core/types.d.ts +6 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/store/hooks.d.ts +15 -1
- package/dist/types/store/store.d.ts +2 -1
- package/dist/types/store/target.d.ts +5 -0
- package/dist/types/store/types.d.ts +7 -0
- package/package.json +1 -1
package/dist/prod/core/lanes.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
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, EFFECT_RENDER, REACTIVE_SCREEN_READ, REACTIVE_FRAME_READ,
|
|
1
|
+
import { CONFIG_GUESS, NOT_PENDING, CONFIG_OVERRIDE, REACTIVE_DIRTY, REACTIVE_CHECK, REACTIVE_IN_HEAP, STATUS_PENDING, CONFIG_SLOT_NODE, REACTIVE_STAGED_READ, 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, EFFECT_RENDER, REACTIVE_SCREEN_READ, REACTIVE_FRAME_READ, CONFIG_INPUTS_PUBLISHED, CONFIG_STAGED, REACTIVE_JOINED } from "./constants.js";
|
|
2
2
|
|
|
3
|
-
import { ext, tracking, stagedRead } from "./core.js";
|
|
3
|
+
import { ext, bornInto, tracking, creatorReads, stagedRead } from "./core.js";
|
|
4
4
|
|
|
5
5
|
import { NotReadyError } from "./error.js";
|
|
6
6
|
|
|
7
|
+
import { removePendingSource, releaseFlightTeardown, handleAsync, notifyStatus, isThenable } from "./async.js";
|
|
8
|
+
|
|
7
9
|
import { laneValueOf } from "./truth.js";
|
|
8
10
|
|
|
9
11
|
import { enqueueSub } from "./heap.js";
|
|
10
12
|
|
|
11
|
-
import { schedule, question, nextQuestion, installLaneHooks, GlobalQueue, newTransaction, resolveTx, ownFlights,
|
|
13
|
+
import { schedule, question, nextQuestion, armGuessing, installLaneHooks, GlobalQueue, newTransaction, list, staleReader, resolveTx, txOf, commitPendingNode, ownFlights, stagedReaders, blocked, clock, insertSubs, laneDirty, flushTransaction, queuePendingNode, passLane, setPassLane, sameLane, releaseQueues, holdNode, reruns, merge } 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
|
|
@@ -49,9 +51,10 @@ function newLane(e) {
|
|
|
49
51
|
}
|
|
50
52
|
|
|
51
53
|
/** What the screen shows for a lane's node: the lane's value once the lane
|
|
52
|
-
* has revealed, the committed truth before
|
|
54
|
+
* has revealed, the committed truth before — NOT_PENDING when there is none
|
|
55
|
+
* (uninitialized, as `laneValueOf`): its read throws NotReady. */ function display(e) {
|
|
53
56
|
const n = e.T.P;
|
|
54
|
-
return e.T.Re.
|
|
57
|
+
return e.T.Re.Ue && n !== NOT_PENDING ? n : e.m & STATUS_UNINITIALIZED ? NOT_PENDING : e.le;
|
|
55
58
|
}
|
|
56
59
|
|
|
57
60
|
/** Guesses written since the last seam (`[node, value, question, …]`).
|
|
@@ -64,9 +67,8 @@ function newLane(e) {
|
|
|
64
67
|
/** What the writer sees of a node: an unflushed guess to it, else the
|
|
65
68
|
* lane's value or the committed one — what an optimistic updater composes
|
|
66
69
|
* on (a store setter's draft too, store/optimistic.ts). */ function guessedValueOf(e) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
return e.l & CONFIG_OVERRIDE ? laneValueOf(e) : e.le;
|
|
70
|
+
let n = pendingGuessOf(e);
|
|
71
|
+
return n !== NOT_PENDING || e.l & CONFIG_OVERRIDE && (n = laneValueOf(e)) !== NOT_PENDING ? n : e.le;
|
|
70
72
|
}
|
|
71
73
|
|
|
72
74
|
/** The unflushed guess to `n`, else NOT_PENDING. */ function pendingGuessOf(e) {
|
|
@@ -74,6 +76,32 @@ function newLane(e) {
|
|
|
74
76
|
return NOT_PENDING;
|
|
75
77
|
}
|
|
76
78
|
|
|
79
|
+
/** This module's copy of scheduler.ts `guessing`: its readers here stay
|
|
80
|
+
* foldable when a bundler splits lanes.ts from scheduler.ts into separate
|
|
81
|
+
* chunks (a cross-chunk binding is not folded; the compiled live page). */ let guessed = false;
|
|
82
|
+
|
|
83
|
+
/** Guesses another action's lane took over (#4336): the node, its guess,
|
|
84
|
+
* the guess's lane, its question, the lane that took it. */ const kept = [];
|
|
85
|
+
|
|
86
|
+
/** Lanes a revert dissolved: the guesses they took come back at their
|
|
87
|
+
* parent's landing (`endLanes`). */ const reverted = /* @__PURE__ */ new WeakSet;
|
|
88
|
+
|
|
89
|
+
/** Lane `l` takes `n`'s guess (another action's), kept to come back if `l`
|
|
90
|
+
* reverts. Its readers saw the guess: they re-derive at the lane's reveal
|
|
91
|
+
* (and, a flight's, hold the lane while they would show it). `d`: a guess
|
|
92
|
+
* `l` takes without writing it (a store target's other slots) — the node
|
|
93
|
+
* shows its truth in `l`'s world until the guess comes back. */ function take(e, n, s) {
|
|
94
|
+
const t = e.T;
|
|
95
|
+
kept.push(e, t.P, t.Re, t.Ie, n);
|
|
96
|
+
rerun(e, n);
|
|
97
|
+
e.l &= s ? -10241 : ~CONFIG_GUESS;
|
|
98
|
+
if (s) t.Re = null, t.P = NOT_PENDING; else list(e, n);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** `n`'s readers are stale readers of `t` (re-derived at its landing). */ function rerun(e, n) {
|
|
102
|
+
for (let s = e.o; s !== null; s = s.t) staleReader(s.u, n);
|
|
103
|
+
}
|
|
104
|
+
|
|
77
105
|
function optimisticWrite(e, n) {
|
|
78
106
|
// What the user sees: an unflushed guess to the same node, else the lane's
|
|
79
107
|
// value or the committed one. The updater composes on it; guessing it
|
|
@@ -82,8 +110,10 @@ function optimisticWrite(e, n) {
|
|
|
82
110
|
// the guess's question and entangles its frame (#3347) without notifying.
|
|
83
111
|
const s = guessedValueOf(e);
|
|
84
112
|
if (typeof n === "function") n = n(s);
|
|
85
|
-
if (e.
|
|
113
|
+
if (e.ye && e.ye(s, n) && !(e.l & CONFIG_GUESS)) return n;
|
|
86
114
|
pendingGuesses.push(e, n, question || nextQuestion());
|
|
115
|
+
armGuessing();
|
|
116
|
+
guessed = true;
|
|
87
117
|
schedule();
|
|
88
118
|
return n;
|
|
89
119
|
}
|
|
@@ -100,7 +130,7 @@ function optimisticWrite(e, n) {
|
|
|
100
130
|
/** A guess's own truth is in flight: the node's own refetch — or, a store
|
|
101
131
|
* leaf's, its family's derive (the slot's flight; store/optimistic.ts
|
|
102
132
|
* installs the resolver). A17: the guess stands in for the flight. */ function inFlight(e) {
|
|
103
|
-
return
|
|
133
|
+
return e.m & STATUS_PENDING || e.l & CONFIG_SLOT_NODE && GlobalQueue.k?.(e);
|
|
104
134
|
}
|
|
105
135
|
|
|
106
136
|
function applyGuesses(e) {
|
|
@@ -117,9 +147,9 @@ function applyGuesses(e) {
|
|
|
117
147
|
// A lane's node already: a guess re-asked, or a derivation guessed
|
|
118
148
|
// over (its staging is void — the guess is the value now). The same
|
|
119
149
|
// value re-asked renews the question; nothing to notify.
|
|
120
|
-
u = !t.
|
|
150
|
+
u = !t.ye || !t.ye(laneValueOf(t), l);
|
|
121
151
|
if (!(t.l & CONFIG_GUESS)) {
|
|
122
|
-
t.
|
|
152
|
+
t.ue = NOT_PENDING;
|
|
123
153
|
t.l |= CONFIG_GUESS;
|
|
124
154
|
}
|
|
125
155
|
t.T.P = l;
|
|
@@ -146,7 +176,7 @@ function applyGuesses(e) {
|
|
|
146
176
|
list(t, s);
|
|
147
177
|
}
|
|
148
178
|
if (e !== null && i !== null) merge(e, i);
|
|
149
|
-
ext(t).
|
|
179
|
+
ext(t).Ie = pendingGuesses[s + 2];
|
|
150
180
|
if (u) {
|
|
151
181
|
// The lane's members re-derive as its work (REACTIVE_LANE_DIRTY): a
|
|
152
182
|
// blocked lane's re-guess does not re-run its render effects as stale
|
|
@@ -166,24 +196,31 @@ function applyGuesses(e) {
|
|
|
166
196
|
* action, not with the one it shares a reader with). A nested lane reading
|
|
167
197
|
* through an ancestor's guess stays its own (the screen plus its own
|
|
168
198
|
* guesses). */ function enterLane(e, n) {
|
|
169
|
-
n.R |= REACTIVE_LANE_READ;
|
|
170
|
-
|
|
171
|
-
|
|
199
|
+
const s = n.R |= REACTIVE_LANE_READ, t = passLane;
|
|
200
|
+
if (t === null) {
|
|
201
|
+
const t = e._parent.Pe === e;
|
|
202
|
+
// A verdict lane's value (a memo of `latest` / `isPending`, F-6) read by
|
|
203
|
+
// a derivation that already read the frame's staging or joined its
|
|
204
|
+
// hold, or by any pass a pass that did is creating: the verdict read
|
|
205
|
+
// does not break it out — it stays the frame's, as the same read inline
|
|
206
|
+
// does (verdict.ts `markVerdictReader`, `route`; D-25, D-26). An
|
|
207
|
+
// effect's own reads do not count (its `_type`, 1–3, carries neither bit).
|
|
208
|
+
if (!(t && creatorReads(n, n.i || s))) {
|
|
209
|
+
setPassLane(e);
|
|
210
|
+
// The pass read a held write before its first lane read (it joined the
|
|
211
|
+
// frame's future as mainline would): lane work sees the screen — the
|
|
212
|
+
// seam re-derives it on the committed world next round (`stagedReaders`,
|
|
213
|
+
// the park's repair), as it does a lane pass that read a staging. Not a
|
|
214
|
+
// pass whose held reads were all of nodes born held (no staged read,
|
|
215
|
+
// `stagedRead`): it has no committed world to re-derive on (#3969).
|
|
216
|
+
// (A pass not joined: a held write beside a guess, #4336; a leaf of a
|
|
217
|
+
// verdict lane — its plain reads are the screen's, D-26 `[s(), L()]`.)
|
|
218
|
+
if (s & REACTIVE_STAGED_READ && (guessed || t || s & REACTIVE_JOINED)) stagedRead(n);
|
|
219
|
+
}
|
|
220
|
+
} else if (sameLane(t, e)) setPassLane(e); else if (!under(t, e)) {
|
|
221
|
+
if (!under(e, t)) linkLanes(t, e);
|
|
172
222
|
setPassLane(e);
|
|
173
|
-
// The pass read a held write before its first lane read (it joined the
|
|
174
|
-
// frame's future as mainline would): lane work sees the screen — the
|
|
175
|
-
// 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. Not a
|
|
177
|
-
// pass whose held reads were all of nodes born held (no staged read,
|
|
178
|
-
// `stagedRead`): it has no committed world to re-derive on (#3969).
|
|
179
|
-
if (n.R & REACTIVE_JOINED && n.R & REACTIVE_STAGED_READ) stagedRead(n);
|
|
180
|
-
return;
|
|
181
223
|
}
|
|
182
|
-
if (sameLane(s, e)) return setPassLane(e);
|
|
183
|
-
if (under(s, e)) return;
|
|
184
|
-
if (under(e, s)) return setPassLane(e);
|
|
185
|
-
linkLanes(s, e);
|
|
186
|
-
setPassLane(e);
|
|
187
224
|
}
|
|
188
225
|
|
|
189
226
|
/** Is `l` nested under `a` (an ancestor lane)? */ function under(e, n) {
|
|
@@ -253,10 +290,19 @@ function unlink(e) {
|
|
|
253
290
|
const n = e.T;
|
|
254
291
|
if (n !== null) {
|
|
255
292
|
const s = n.Re;
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
293
|
+
if (s?.P) {
|
|
294
|
+
// Cleared before equality, so a return to the committed value
|
|
295
|
+
// notifies nobody. The seam wakes it (#3892) — always for a pass
|
|
296
|
+
// outside any transaction's flush: its value is the screen's now
|
|
297
|
+
// (#4367). While a transaction's flush runs the pass and the lane's
|
|
298
|
+
// frame is still held, what the screen shows stays the screen until
|
|
299
|
+
// the landing, and `_value` takes it (as `dissolveLane` keeps a shown
|
|
300
|
+
// lane's), so this pass's answer — the frame's — is a change against
|
|
301
|
+
// what is seen and reaches the screen with the frame's commit. (Only
|
|
302
|
+
// a lane is ever `_shown`.)
|
|
303
|
+
if (s.Ue) if (!flushTransaction || !blocked(resolveTx(s._parent))) e.R |= LEFT_SHOWN; else e.le = display(e);
|
|
304
|
+
n.Re = null;
|
|
305
|
+
}
|
|
260
306
|
n.P = NOT_PENDING;
|
|
261
307
|
}
|
|
262
308
|
e.l &= -1050881;
|
|
@@ -264,7 +310,7 @@ function unlink(e) {
|
|
|
264
310
|
}
|
|
265
311
|
if (!e.i) {
|
|
266
312
|
if (!(e.l & CONFIG_OVERRIDE)) {
|
|
267
|
-
e.
|
|
313
|
+
e.ue = NOT_PENDING;
|
|
268
314
|
e.l = e.l & -1048833 | CONFIG_OVERRIDE;
|
|
269
315
|
ext(e);
|
|
270
316
|
}
|
|
@@ -274,7 +320,12 @@ function unlink(e) {
|
|
|
274
320
|
// of the lane from here (its value the lane's, its fate the lane's), no
|
|
275
321
|
// longer a written guess. A pass with no answer (pending, errored)
|
|
276
322
|
// leaves the guess.
|
|
277
|
-
|
|
323
|
+
// Nor a pass of another action's guess: the re-ask is this lane's new
|
|
324
|
+
// question, which the guess (over the old one) does not answer — the
|
|
325
|
+
// lane waits for its own answer (F-1, F-6, #4336). (A guess of the
|
|
326
|
+
// lane's own action, D-33's entangled slot, still stands in.)
|
|
327
|
+
// (Read behind `guessed`: a bundle without optimism drops the reads.)
|
|
328
|
+
if (guessed && e.l & CONFIG_GUESS && e.T.Re?.P && resolveTx(e.T.Re._parent) !== resolveTx(n._parent)) take(e, n); else if (!t) e.l &= ~CONFIG_GUESS;
|
|
278
329
|
}
|
|
279
330
|
// A leaf has no lane value to seat it (`recompute`): one left waiting on
|
|
280
331
|
// the lane's flight runs its next pass as the lane's — the landing that
|
|
@@ -297,6 +348,21 @@ function unlink(e) {
|
|
|
297
348
|
return true;
|
|
298
349
|
}
|
|
299
350
|
|
|
351
|
+
/** The truth arrived for a written guess (A18): a correction dissolves the
|
|
352
|
+
* lane — the guess and everything derived from it is void, the truth is
|
|
353
|
+
* the parent's held write and the graph re-derives from it there, one frame
|
|
354
|
+
* at the parent's landing — while the display keeps what it shows until
|
|
355
|
+
* then. A confirmation is silent (A17): the truth stays staged beneath the
|
|
356
|
+
* guess for the parent's commit, the guess stays the value; only a reader
|
|
357
|
+
* of the truth (CONFIG_AUTHORITATIVE) is told its view changed. Either way
|
|
358
|
+
* the parent takes this node, not the tick that carried the truth (D-33):
|
|
359
|
+
* one landing answering two actions' guesses (a store re-ask over two
|
|
360
|
+
* rows) must not tie them together; a pass that derives from the held
|
|
361
|
+
* truth joins the parent on its own (`joinPass`). */
|
|
362
|
+
/** The correction round is replacing a guess with the value it covered (no
|
|
363
|
+
* landing beneath it): observe's "reverted"; the lane gives back the
|
|
364
|
+
* guesses it took (#4336, `endLanes`). */ let reverting = false;
|
|
365
|
+
|
|
300
366
|
function supersede(e, n, s) {
|
|
301
367
|
const t = txOf(e);
|
|
302
368
|
// Resolved: the parent may have merged into another transaction since the
|
|
@@ -309,9 +375,10 @@ function supersede(e, n, s) {
|
|
|
309
375
|
if (s && e.l & CONFIG_SLOT_NODE && GlobalQueue.nn?.(e.T.P, n)) s = false;
|
|
310
376
|
if (s) {
|
|
311
377
|
dissolveLane(t, l, e);
|
|
378
|
+
if (guessed && reverting) reverted.add(t);
|
|
312
379
|
// What the screen showed stays the screen until the parent lands (A18
|
|
313
380
|
// (c): display and untracked reads keep the override until the commit).
|
|
314
|
-
if (t.
|
|
381
|
+
if (t.Ue) e.le = e.T.P;
|
|
315
382
|
e.l &= -10241;
|
|
316
383
|
e.T.P = NOT_PENDING;
|
|
317
384
|
holdNode(e, l);
|
|
@@ -321,8 +388,7 @@ function supersede(e, n, s) {
|
|
|
321
388
|
// A confirmation is silent (A17); only truth readers are told.
|
|
322
389
|
GlobalQueue.sn?.(t);
|
|
323
390
|
}
|
|
324
|
-
e.
|
|
325
|
-
joinFuture(l);
|
|
391
|
+
e.ue = n;
|
|
326
392
|
}
|
|
327
393
|
|
|
328
394
|
/** A lane's end, two ways. `into === null`: the parent landed — the lane's
|
|
@@ -345,18 +411,20 @@ function supersede(e, n, s) {
|
|
|
345
411
|
e.Pe = null;
|
|
346
412
|
if (lanes.indexOf(l) !== -1) dissolveLane(l, null);
|
|
347
413
|
}
|
|
414
|
+
// First loads this dissolution leaves loading (below).
|
|
415
|
+
const u = [];
|
|
348
416
|
for (let t = 0; t < e.tn.length; t++) {
|
|
349
417
|
const l = e.tn[t];
|
|
350
|
-
const
|
|
351
|
-
if (l === s ||
|
|
352
|
-
const
|
|
353
|
-
const
|
|
354
|
-
const
|
|
418
|
+
const i = l.T;
|
|
419
|
+
if (l === s || i.Re !== e) continue;
|
|
420
|
+
const r = l.i;
|
|
421
|
+
const o = l.l & CONFIG_GUESS;
|
|
422
|
+
const E = i.P;
|
|
355
423
|
// What the screen shows of it (NOT_PENDING: nothing — a lane pass that
|
|
356
424
|
// errored or pends staged no value), and the lane's latest.
|
|
357
|
-
const
|
|
425
|
+
const a = e.Ue && !r ? E : l.le;
|
|
358
426
|
const f = laneValueOf(l);
|
|
359
|
-
|
|
427
|
+
i.P = NOT_PENDING;
|
|
360
428
|
l.l &= -10241;
|
|
361
429
|
if (n === null) {
|
|
362
430
|
// A derivation the revert re-derives (dirtied by the guess's
|
|
@@ -364,20 +432,33 @@ function supersede(e, n, s) {
|
|
|
364
432
|
// lane's answer beside inputs that are the truth now: a fresh reader
|
|
365
433
|
// of its flight observes it (#3648, #3651; #3305's commit beneath a
|
|
366
434
|
// flight).
|
|
367
|
-
|
|
368
|
-
|
|
435
|
+
// Not a first load the lane produced nothing for whose own flight is
|
|
436
|
+
// up, nor one pending on such a load kept here (an identity memo of
|
|
437
|
+
// it, a derived store's derive): committing its empty `_value` would
|
|
438
|
+
// initialize it as `undefined`, which `latest()` would serve and
|
|
439
|
+
// `isPending()` call pending. It stays loading until its flight
|
|
440
|
+
// answers (D-22, A19 exc. 1; async-gen 3289 #929, 91501 #504, #156).
|
|
441
|
+
i.Re = null;
|
|
442
|
+
if (!r && !o) E === NOT_PENDING && (l.m & (STATUS_UNINITIALIZED | STATUS_PENDING)) === (STATUS_UNINITIALIZED | STATUS_PENDING) && (i.Ee || u.some(e => i.se?.has(e))) ? u.push(l) : l.ue = f;
|
|
369
443
|
commitPendingNode(l);
|
|
370
|
-
if (!
|
|
444
|
+
if (!r) {
|
|
371
445
|
if (l.R & (REACTIVE_IN_HEAP | REACTIVE_DIRTY | REACTIVE_CHECK) || l.m & STATUS_PENDING) l.l |= CONFIG_INPUTS_PUBLISHED;
|
|
372
|
-
if (
|
|
446
|
+
if (a !== NOT_PENDING && (!l.ye || !l.ye(a, l.le))) insertSubs(l);
|
|
373
447
|
}
|
|
374
|
-
|
|
448
|
+
// A stale reader's own error — its pass (a memo's or a render
|
|
449
|
+
// effect's) threw over the committed value of what the parent held
|
|
450
|
+
// (A10), served as the screen — is no answer of the world landing now:
|
|
451
|
+
// it re-derives on it (A15; D-39, the landing is the new answer). The
|
|
452
|
+
// landing's `reruns` skips an errored reader: its error is an errored
|
|
453
|
+
// source's (#3945).
|
|
454
|
+
if (l.R & REACTIVE_FRAME_READ && l.m & STATUS_ERROR && i.U.source === l) enqueueSub(l);
|
|
455
|
+
} else if (o) {
|
|
375
456
|
// A guess of a dissolving lane: its truth — a landing held beneath it,
|
|
376
457
|
// else the value it covered — is the parent's to land, and its readers
|
|
377
458
|
// re-derive from it there. What the screen showed stays the screen
|
|
378
459
|
// until then (A18 (c)).
|
|
379
|
-
if (l.
|
|
380
|
-
if (e.
|
|
460
|
+
if (l.ue === NOT_PENDING) l.ue = covered(l);
|
|
461
|
+
if (e.Ue) l.le = E;
|
|
381
462
|
holdNode(l, n);
|
|
382
463
|
insertSubs(l);
|
|
383
464
|
} else {
|
|
@@ -388,19 +469,19 @@ function supersede(e, n, s) {
|
|
|
388
469
|
// flight is asking the void world's question: its landing is nobody's
|
|
389
470
|
// answer — it re-asks from the truth (whose notification may not reach
|
|
390
471
|
// it: an input's truth equal to its committed value is silent).
|
|
391
|
-
|
|
392
|
-
if (!
|
|
393
|
-
if (
|
|
472
|
+
i.Re = null;
|
|
473
|
+
if (!r) {
|
|
474
|
+
if (a !== NOT_PENDING && e.Ue) l.ue = a;
|
|
394
475
|
if (l.m & STATUS_PENDING) {
|
|
395
|
-
|
|
476
|
+
i.Ee = null;
|
|
396
477
|
enqueueSub(l);
|
|
397
478
|
}
|
|
398
479
|
}
|
|
399
|
-
if (e.
|
|
480
|
+
if (e.Ue) {
|
|
400
481
|
commitPendingNode(l);
|
|
401
|
-
if (!
|
|
482
|
+
if (!r) l.l |= CONFIG_INPUTS_PUBLISHED;
|
|
402
483
|
} else {
|
|
403
|
-
if (
|
|
484
|
+
if (i.me !== null || i.Le !== null) GlobalQueue.Ce(l, false, true);
|
|
404
485
|
l.l &= -1048961;
|
|
405
486
|
}
|
|
406
487
|
}
|
|
@@ -416,7 +497,7 @@ function supersede(e, n, s) {
|
|
|
416
497
|
// void: nothing of it reached the screen. So are the runs a blocked lane
|
|
417
498
|
// parked: they show a re-guess the seam never revealed, beside derivations
|
|
418
499
|
// that keep what the screen showed.
|
|
419
|
-
if (n === null || e.
|
|
500
|
+
if (n === null || e.Ue && !e.ln) releaseQueues(e); else e.un[0].length = e.un[1].length = 0;
|
|
420
501
|
}
|
|
421
502
|
|
|
422
503
|
/** Lanes. A lane's node is read by its reader's kind: an authoritative
|
|
@@ -478,17 +559,22 @@ function supersede(e, n, s) {
|
|
|
478
559
|
if ((l || passLane !== t) && passLane?._parent.Pe === passLane) setPassLane(null);
|
|
479
560
|
if (passLane === null || !sameLane(passLane, t)) {
|
|
480
561
|
// (A lane that has never shown: the screen is the committed value.)
|
|
481
|
-
if (l && t.
|
|
482
|
-
if (!s && n.
|
|
562
|
+
if (l && t.Ue) return NOT_PENDING;
|
|
563
|
+
if (!s && n.ue !== NOT_PENDING && e.l & CONFIG_HELD && flushTransaction !== null && resolveTx(flushTransaction) === txOf(e)) return n.ue;
|
|
483
564
|
if (t.ln || i) {
|
|
484
|
-
if (!s && !t.ge && u & STATUS_UNINITIALIZED) throw new NotReadyError(null);
|
|
485
565
|
// Re-derived at the reveal; once per pass (the pass may also be a stale
|
|
486
566
|
// reader of a transaction, REACTIVE_FRAME_READ — both reruns apply).
|
|
487
|
-
|
|
567
|
+
// Before the throw below: a leaf that waits on a lane that has never
|
|
568
|
+
// shown has no flight to settle it — only the reveal re-derives it,
|
|
569
|
+
// and its pending holds its frame until then (#4338).
|
|
570
|
+
if (!(e.R & REACTIVE_SCREEN_READ)) {
|
|
488
571
|
e.R |= REACTIVE_FRAME_READ | REACTIVE_SCREEN_READ;
|
|
489
572
|
t.En.push(e);
|
|
490
573
|
}
|
|
491
|
-
|
|
574
|
+
// Nothing on screen yet (uninitialized: `display` is NOT_PENDING).
|
|
575
|
+
const s = display(n);
|
|
576
|
+
if (s === NOT_PENDING) throw new NotReadyError(null);
|
|
577
|
+
return s;
|
|
492
578
|
}
|
|
493
579
|
// A verdict reader reads ahead of the seam's verdict: re-derived on the
|
|
494
580
|
// screen if the lane holds (#4284).
|
|
@@ -501,7 +587,7 @@ function supersede(e, n, s) {
|
|
|
501
587
|
|
|
502
588
|
/** The value a guess covered: the node's committed value — a store slot's
|
|
503
589
|
* asked of the store (a chained link follows the inner store's commits). */ function covered(e) {
|
|
504
|
-
return e.l & CONFIG_SLOT_NODE && GlobalQueue.
|
|
590
|
+
return e.l & CONFIG_SLOT_NODE && GlobalQueue.an !== undefined ? GlobalQueue.an(e) : e.le;
|
|
505
591
|
}
|
|
506
592
|
|
|
507
593
|
/** A guess in `l` whose own truth is in flight (its refetch — authoritative:
|
|
@@ -540,8 +626,10 @@ function supersede(e, n, s) {
|
|
|
540
626
|
for (let e = 0; e < t.tn.length && lanes.indexOf(t) !== -1; e++) {
|
|
541
627
|
const n = t.tn[e];
|
|
542
628
|
if (n.l & CONFIG_GUESS && n.T.Re === t) {
|
|
543
|
-
const e = n.
|
|
544
|
-
|
|
629
|
+
const e = n.ue !== NOT_PENDING ? n.ue : covered(n);
|
|
630
|
+
if (guessed) reverting = n.ue === NOT_PENDING;
|
|
631
|
+
supersede(n, e, !n.ye || !n.ye(n.T.P, e));
|
|
632
|
+
if (guessed) reverting = false;
|
|
545
633
|
}
|
|
546
634
|
}
|
|
547
635
|
}
|
|
@@ -556,8 +644,8 @@ function laneSeam(e, n) {
|
|
|
556
644
|
return;
|
|
557
645
|
}
|
|
558
646
|
e.ln = false;
|
|
559
|
-
e.
|
|
560
|
-
reruns(e);
|
|
647
|
+
e.Ue = true;
|
|
648
|
+
if (reruns(e)) revealing.push(resolveTx(e._parent));
|
|
561
649
|
for (let n = 0; n < e.tn.length; n++) {
|
|
562
650
|
const s = e.tn[n];
|
|
563
651
|
if (s.R & LEFT_SHOWN) {
|
|
@@ -566,13 +654,13 @@ function laneSeam(e, n) {
|
|
|
566
654
|
}
|
|
567
655
|
const t = s.T;
|
|
568
656
|
if (t.Re !== e) continue;
|
|
569
|
-
if (!(s.l & CONFIG_GUESS) && !s.i && s.
|
|
570
|
-
t.P = s.
|
|
571
|
-
s.
|
|
657
|
+
if (!(s.l & CONFIG_GUESS) && !s.i && s.ue !== NOT_PENDING) {
|
|
658
|
+
t.P = s.ue;
|
|
659
|
+
s.ue = NOT_PENDING;
|
|
572
660
|
}
|
|
573
661
|
// The frame this pass built is the screen's now; the one it replaced
|
|
574
662
|
// goes (as `commitPendingNode` retires a committed pass's).
|
|
575
|
-
if (t.
|
|
663
|
+
if (t.me !== null || t.Le !== null) GlobalQueue.Ce(s, false, true);
|
|
576
664
|
s.l &= ~CONFIG_STAGED;
|
|
577
665
|
}
|
|
578
666
|
releaseQueues(e);
|
|
@@ -580,6 +668,25 @@ function laneSeam(e, n) {
|
|
|
580
668
|
|
|
581
669
|
/** The parent landed: its lanes end, nested first. (None is blocked: a
|
|
582
670
|
* blocked lane blocks its parent.) */ function endLanes(e) {
|
|
671
|
+
// A revert landing (#4336): the guesses its lane took from another action
|
|
672
|
+
// that is still out come back in this frame, over the truth it lands —
|
|
673
|
+
// its readers re-derive with the landing (one frame, no bare truth
|
|
674
|
+
// between). Taken by a later lane since, a node stays that lane's.
|
|
675
|
+
if (guessed) for (let n = kept.length - 5; n >= 0; n -= 5) if (resolveTx(kept[n + 4]._parent) === e) {
|
|
676
|
+
let [s, t, l, u, i] = kept.splice(n, 5);
|
|
677
|
+
// (A store slot's node now: the one taken, or a read's since.)
|
|
678
|
+
if (reverted.has(i) && lanes.includes(l) && (!(s.l & CONFIG_SLOT_NODE) || (s = GlobalQueue.fn(s, true)))) {
|
|
679
|
+
const n = ext(s);
|
|
680
|
+
if (n.Re === null || txOf(s) === e) {
|
|
681
|
+
commitPendingNode(s);
|
|
682
|
+
n.P = t;
|
|
683
|
+
n.Ie = u;
|
|
684
|
+
s.l |= CONFIG_OVERRIDE | CONFIG_GUESS;
|
|
685
|
+
list(s, l);
|
|
686
|
+
rerun(s, e);
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
}
|
|
583
690
|
for (let n = lanes.length - 1; n >= 0; n--) {
|
|
584
691
|
const s = lanes[n];
|
|
585
692
|
if (resolveTx(s._parent) !== e) continue;
|
|
@@ -596,7 +703,13 @@ function laneSeam(e, n) {
|
|
|
596
703
|
return e.P && linkBlocked(e) || nestedBlocked(e);
|
|
597
704
|
}
|
|
598
705
|
|
|
706
|
+
/** Parents whose lane revealed this seam with readers to re-derive there
|
|
707
|
+
* (`laneSeam`): the lane shows ahead of its parent (F-6), so the parent lands
|
|
708
|
+
* a round later — after those readers have shown the lane's answer — even
|
|
709
|
+
* when nothing else holds it (#4393). */ const revealing = [];
|
|
710
|
+
|
|
599
711
|
/** The lanes under `t` (its own; a link group's are each other's). */ function nestedBlocked(e) {
|
|
712
|
+
if (revealing.indexOf(e) !== -1) return true;
|
|
600
713
|
for (let n = 0; n < lanes.length; n++) {
|
|
601
714
|
const s = lanes[n];
|
|
602
715
|
if (resolveTx(s._parent) !== e) continue;
|
|
@@ -610,7 +723,9 @@ function laneSeam(e, n) {
|
|
|
610
723
|
* landing), judged against the guess. On a derivation it is the lane's
|
|
611
724
|
* latest: its staging once the lane has shown (promoted at the next
|
|
612
725
|
* reveal), its slot before; the lane's members re-derive as its work. */ function laneWrite(e, n) {
|
|
613
|
-
|
|
726
|
+
// (A store slot's guess its derive's re-ask in another action's lane
|
|
727
|
+
// writes is that lane's derivation from here — store `_slotTake`, #4336.)
|
|
728
|
+
if (e.l & CONFIG_GUESS && !(guessed && GlobalQueue.fn?.(e))) {
|
|
614
729
|
// Provenance (A18, #3331; Q-D, plan sec. 39): a write asking an OLDER
|
|
615
730
|
// question than the guess's — another action's landing beneath it —
|
|
616
731
|
// is not its answer: held beneath (the truth for the commit; the
|
|
@@ -621,18 +736,18 @@ function laneSeam(e, n) {
|
|
|
621
736
|
// A store re-bases a keyed arrangement guess over an older truth, and
|
|
622
737
|
// folds a current one beneath it (D-34): true.
|
|
623
738
|
const s = stale(e, question);
|
|
624
|
-
if (GlobalQueue.
|
|
625
|
-
e.
|
|
739
|
+
if (GlobalQueue.Nn?.(e, n, s) || s) {
|
|
740
|
+
e.ue = n;
|
|
626
741
|
e.l |= CONFIG_HELD;
|
|
627
742
|
schedule();
|
|
628
743
|
return n;
|
|
629
744
|
}
|
|
630
|
-
supersede(e, n, !e.
|
|
745
|
+
supersede(e, n, !e.ye || !e.ye(e.T.P, n));
|
|
631
746
|
} else {
|
|
632
747
|
const s = txOf(e);
|
|
633
|
-
if (e.
|
|
634
|
-
if (s.
|
|
635
|
-
if (e.X !== undefined) e.
|
|
748
|
+
if (e.ye && e.ye(laneValueOf(e), n)) return n;
|
|
749
|
+
if (s.Ue) e.ue = n; else e.T.P = n;
|
|
750
|
+
if (e.X !== undefined) e.ie = clock;
|
|
636
751
|
insertSubs(e);
|
|
637
752
|
laneDirty(e, s);
|
|
638
753
|
}
|
|
@@ -654,18 +769,18 @@ function laneSeam(e, n) {
|
|
|
654
769
|
* A24). The guess's own question answering supersedes as usual. */ function laneOutcome(e, n, s) {
|
|
655
770
|
if (s) return true;
|
|
656
771
|
if (stale(e, answered(e))) {
|
|
657
|
-
e.
|
|
772
|
+
e.ue = n;
|
|
658
773
|
e.l |= CONFIG_HELD;
|
|
659
774
|
return true;
|
|
660
775
|
}
|
|
661
|
-
supersede(e, n, !e.
|
|
776
|
+
supersede(e, n, !e.ye || !e.ye(e.T.P, n));
|
|
662
777
|
return true;
|
|
663
778
|
}
|
|
664
779
|
|
|
665
780
|
/** THE provenance test, for a derivation's pass and a write alike: an
|
|
666
781
|
* answer to question `q` landing on a guess is stale when `q` is older
|
|
667
782
|
* than the guess's own; unstamped (0) and mainline are current. */ function stale(e, n) {
|
|
668
|
-
return n !== 0 && n < e.T.
|
|
783
|
+
return n !== 0 && n < e.T.Ie;
|
|
669
784
|
}
|
|
670
785
|
|
|
671
786
|
/** The question a derivation's pass answered: the newest among the stamped
|
|
@@ -674,7 +789,7 @@ function laneSeam(e, n) {
|
|
|
674
789
|
let n = 0;
|
|
675
790
|
for (let s = e.C; s !== null; s = s.G) {
|
|
676
791
|
const e = s.S;
|
|
677
|
-
if (e.T !== null && e.T.
|
|
792
|
+
if (e.T !== null && e.T.Ie > n && e.ie === clock) n = e.T.Ie;
|
|
678
793
|
}
|
|
679
794
|
return n;
|
|
680
795
|
}
|
|
@@ -689,33 +804,100 @@ const applyGuessesAt = e => {
|
|
|
689
804
|
if (pendingGuesses.length !== 0) applyGuesses(e);
|
|
690
805
|
};
|
|
691
806
|
|
|
807
|
+
/** `t` is parked by `r`'s pass alone: each node keeping it — `t`'s own, or
|
|
808
|
+
* a lane's under it — is `r` itself (its flight, in the verdict lane) or a
|
|
809
|
+
* render effect pending on `r` only: the frame observing the lane work that
|
|
810
|
+
* read its staging. Anything else (an open action, a guess's flight,
|
|
811
|
+
* another flight) holds it on its own. */ function heldBy(e, n) {
|
|
812
|
+
if (e.tt !== 0 || e.P && linkBlocked(e)) return false;
|
|
813
|
+
for (let s = -1, t = e; t; t = lanes[++s]) if (t === e || resolveTx(t._parent) === e) {
|
|
814
|
+
if (t !== e && guessFlights(t)) return false;
|
|
815
|
+
for (let e = 0; e < t.tn.length; e++) {
|
|
816
|
+
const s = t.tn[e];
|
|
817
|
+
if (s === n || !(s.m & STATUS_PENDING) || s.T.Re !== null && txOf(s) !== t) continue;
|
|
818
|
+
const l = s.T.se;
|
|
819
|
+
if (s.i !== EFFECT_RENDER || l?.size !== 1 || !l.has(n)) return false;
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
return true;
|
|
823
|
+
}
|
|
824
|
+
|
|
692
825
|
const laneSeams = e => {
|
|
693
826
|
// Passes that read a write the parked frame holds as the screen
|
|
694
827
|
// (`stagedReaders`: lane work, a verdict reader before the verdict): they
|
|
695
828
|
// re-derive on the committed world next round (and register as stale
|
|
696
829
|
// readers of the transaction there); a lane's runs wait that round — a
|
|
697
830
|
// lane sees the screen plus its own guesses.
|
|
831
|
+
if (revealing.length) revealing.length = 0;
|
|
698
832
|
const n = [];
|
|
699
|
-
if (e !== null) for (let s = 0; s <
|
|
700
|
-
const t =
|
|
701
|
-
|
|
833
|
+
if (e !== null) for (let s = 0; s < stagedReaders.length; s++) {
|
|
834
|
+
const t = stagedReaders[s],
|
|
835
|
+
// A pass no transaction holds that read the frame's staging (an
|
|
836
|
+
// effect, a `[s(), latest(s)]` reader watched before the frame had
|
|
837
|
+
// a transaction): judged by the frame's — it re-derives only if the
|
|
838
|
+
// frame stays parked; landing here, what it read is the screen (one
|
|
839
|
+
// run, D-22).
|
|
840
|
+
l = t.T?.Re || (t.R & REACTIVE_STAGED_READ ? e : null);
|
|
702
841
|
// A verdict reader a later read of the same pass routed into a verdict
|
|
703
842
|
// lane answered for itself: it re-derives at the holder's landing, not
|
|
704
843
|
// now (one run — #3322, #3540). Other verdict-lane work re-derives only
|
|
705
844
|
// if the frame stays parked: a transaction landing at this seam makes
|
|
706
|
-
// what it read the screen (one run).
|
|
707
|
-
|
|
845
|
+
// what it read the screen (one run). The frame is the transaction that
|
|
846
|
+
// holds what it read (`t`, this flush's — not always the lane's parent:
|
|
847
|
+
// a landing that reached a frame held elsewhere joined that one). Nor
|
|
848
|
+
// when only this pass keeps it parked (`heldBy`): the frame lands with
|
|
849
|
+
// the pass's answer, so what the pass read is the screen when anything
|
|
850
|
+
// shows it — re-derived on the committed world, it would ask a question
|
|
851
|
+
// already asked, over inputs the landing replaces. A reader a
|
|
852
|
+
// transaction holds that read none of its stagings (a verdict reader
|
|
853
|
+
// that probed only a flight, held as the frame's pending observer or
|
|
854
|
+
// its staged derivation) has nothing to re-derive: its re-run
|
|
855
|
+
// re-enters that transaction and parks it again, every round — it
|
|
856
|
+
// runs at the landing (#4349). One that read a staging re-derives only
|
|
857
|
+
// if its frame stays parked: landing at this seam, what it read is the
|
|
858
|
+
// screen (one run, D-22). Not one born into that frame (a held pass's
|
|
859
|
+
// child, ruling A): it has no screen, its reads are the transaction's
|
|
860
|
+
// either way — it runs again at the landing, not now.
|
|
861
|
+
if (t.R & REACTIVE_DISPOSED || (l?.P ? l._parent?.Pe === l && (t.l & CONFIG_VERDICT ? !(t.R & REACTIVE_PROBE_UNANSWERED) : !blocked(e) || heldBy(e, t)) : l && !(t.R & REACTIVE_PROBE_UNANSWERED || t.R & REACTIVE_STAGED_READ && blocked(l) && !bornInto(t, l)))) continue;
|
|
708
862
|
// A leaked effect re-derives seated in its lane from its first read: it
|
|
709
863
|
// carries no lane value (`laneStage`), so without this its pass starts
|
|
710
864
|
// as mainline, joins the parked frame on its first held read and reads
|
|
711
865
|
// the staging, then re-enters the lane at its guess read and leaks
|
|
712
866
|
// again — every round (#4014). A computed is already seated by its
|
|
713
867
|
// override, and a written guess's own pass stays the frame's.
|
|
714
|
-
if (l
|
|
868
|
+
if (l?.P && t.i) t.R |= REACTIVE_LANE_DIRTY;
|
|
869
|
+
// R5 for an async reader: its frame pass asked the frame's question
|
|
870
|
+
// (F-6's lane gets its own pass now). That flight is the frame's
|
|
871
|
+
// answer: the landing adopts it rather than asking it again (F-9: a
|
|
872
|
+
// re-ask of the same question is no new question; `reruns`). A frame
|
|
873
|
+
// landing at this seam has nothing to re-derive: the pass was the
|
|
874
|
+
// landing's, its flight the screen's answer. Sync or async, the
|
|
875
|
+
// reader's lane pass is still to come: the verdict lane it joins does
|
|
876
|
+
// not reveal this seam (F-6: the lane's readers show its answer
|
|
877
|
+
// together, D-23: atomic with the value) — revealed now, it showed a
|
|
878
|
+
// verdict beside the frame pass's value, before the pass that answers
|
|
879
|
+
// for the lane, and a reader of the re-derived memo read it outside
|
|
880
|
+
// the shown lane and waited for the frame (#4393).
|
|
881
|
+
else if (!l?.P && t.R & REACTIVE_PROBE_UNANSWERED) {
|
|
882
|
+
if (isThenable(t.T?.Ee)) {
|
|
883
|
+
if (!blocked(e)) continue;
|
|
884
|
+
t.T.He = t.T.Ee;
|
|
885
|
+
} else if (blocked(e))
|
|
886
|
+
// A sync reader's lane pass re-derives the async memos over it (a
|
|
887
|
+
// memo over a verdict memo is a verdict reader, D-25 #4050; D-22:
|
|
888
|
+
// `latest()` extracted into a memo reads as inline). The flight
|
|
889
|
+
// each asked over its frame staging, up and held by `t`, is the
|
|
890
|
+
// frame's answer too: the landing adopts it (F-9).
|
|
891
|
+
for (let n = t.o, s; n; n = n.t) if (isThenable((s = n.u).T?.Ee) && s.T.se?.has(s) && s.l & CONFIG_HELD && txOf(s) === e) s.T.He = s.T.Ee;
|
|
892
|
+
if (e?.Pe && n.indexOf(e.Pe) === -1) n.push(e.Pe);
|
|
893
|
+
}
|
|
715
894
|
enqueueSub(t);
|
|
716
|
-
if (l
|
|
895
|
+
if (l?.P && n.indexOf(l) === -1) n.push(l);
|
|
717
896
|
}
|
|
718
|
-
|
|
897
|
+
// A verdict lane born at this seam is judged with it: it exists only once
|
|
898
|
+
// a pass routed into it — the park seam's zombie verdict readers re-run
|
|
899
|
+
// as its work so that this seam reveals them (#3444).
|
|
900
|
+
for (let e = lanes.length - 1; e >= 0; e--) if (e < judged || lanes[e]._parent?.Pe === lanes[e]) laneSeam(lanes[e], n.indexOf(lanes[e]) !== -1);
|
|
719
901
|
// A verdict reader that entered a lane this seam held: its run waits with
|
|
720
902
|
// the lane, and the verdict beside it would freeze — it re-derives next
|
|
721
903
|
// round from the frame's seat, a stale reader of the lane (#4284).
|
|
@@ -725,10 +907,40 @@ const laneSeams = e => {
|
|
|
725
907
|
}
|
|
726
908
|
};
|
|
727
909
|
|
|
910
|
+
/** The landing's re-derive of a reader whose frame flight the seam parked
|
|
911
|
+
* (R5): the flight asked the question the landing would — adopted, it is
|
|
912
|
+
* asked once (F-9). Not over a pass already queued: that one asks anew.
|
|
913
|
+
* Registered as if this pass had returned it — the node pending on it, its
|
|
914
|
+
* landing the answer — through a promise of its own: the frame pass's
|
|
915
|
+
* registration still listens to the flight, and must not land it a second
|
|
916
|
+
* time. */ const adoptParked = e => {
|
|
917
|
+
const n = e.T?.He;
|
|
918
|
+
if (!n || e.R & (REACTIVE_DIRTY | REACTIVE_CHECK | REACTIVE_IN_HEAP)) return false;
|
|
919
|
+
e.T.He = undefined;
|
|
920
|
+
releaseFlightTeardown(e);
|
|
921
|
+
try {
|
|
922
|
+
handleAsync(e, n.then());
|
|
923
|
+
} catch {}
|
|
924
|
+
e.T.fe = true;
|
|
925
|
+
notifyStatus(e, STATUS_PENDING, new NotReadyError(e));
|
|
926
|
+
return true;
|
|
927
|
+
};
|
|
928
|
+
|
|
929
|
+
/** A15: lane work or a verdict reader was served `el`'s committed value
|
|
930
|
+
* (core.ts `frameRead`), so its pass does not wait on `el`'s flight: what
|
|
931
|
+
* `el`'s pending propagated onto it before the pass (its origins, `el`
|
|
932
|
+
* included) is not this pass's — the landing re-derives it (`reruns`).
|
|
933
|
+
* Kept, a pass that went pending on another source never woke when that
|
|
934
|
+
* source settled (#4397). Only a reader something made pending has anything
|
|
935
|
+
* to drop. */ const laneServed = (e, n) => {
|
|
936
|
+
const s = n.T?.se;
|
|
937
|
+
if (s && e.T?.se) for (const n of s) removePendingSource(e, n);
|
|
938
|
+
};
|
|
939
|
+
|
|
728
940
|
/** Render effects that read a verdict and entered a lane before its seam (#4284). */ const entered = [];
|
|
729
941
|
|
|
730
|
-
installLaneHooks(laneRead, laneStage, laneOutcome, laneWrite, applyGuessesAt, laneSeams, () => lanes.length !== 0 && laneCorrections(), endLanes, lanesBlocked);
|
|
942
|
+
installLaneHooks(laneRead, laneStage, laneOutcome, laneWrite, applyGuessesAt, laneSeams, () => lanes.length !== 0 && laneCorrections(), endLanes, lanesBlocked, adoptParked, laneServed);
|
|
731
943
|
|
|
732
944
|
GlobalQueue.J = verdictLane;
|
|
733
945
|
|
|
734
|
-
export { display, enterLane, guessedValueOf, laneRead, laneStage, laneValueOf, optimisticWrite, pendingGuessOf, supersede, verdictLane };
|
|
946
|
+
export { display, enterLane, guessedValueOf, laneRead, laneStage, laneValueOf, optimisticWrite, pendingGuessOf, supersede, take, verdictLane };
|