@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/truth.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CONFIG_GUESS, NOT_PENDING, CONFIG_AUTHORITATIVE, CONFIG_OVERRIDE } from "./constants.js";
|
|
1
|
+
import { CONFIG_GUESS, NOT_PENDING, STATUS_UNINITIALIZED, CONFIG_AUTHORITATIVE, CONFIG_OVERRIDE } from "./constants.js";
|
|
2
2
|
|
|
3
3
|
import { NotReadyError } from "./error.js";
|
|
4
4
|
|
|
@@ -10,11 +10,13 @@ import { enqueueSub } from "./heap.js";
|
|
|
10
10
|
// which exists once something installs lanes (`createOptimistic`, verdicts).
|
|
11
11
|
/** A lane node's current value: its guess, or the latest it derived — the
|
|
12
12
|
* staging a shown lane holds for its next reveal, else its slot; the
|
|
13
|
-
* committed value while it has none (its first lane pass in flight)
|
|
13
|
+
* committed value while it has none (its first lane pass in flight) —
|
|
14
|
+
* NOT_PENDING for a node with no committed value either (born in the lane,
|
|
15
|
+
* uninitialized: its reads throw NotReady, A7; #4363). */
|
|
14
16
|
function laneValueOf(r) {
|
|
15
|
-
if (!(r.l & CONFIG_GUESS) && r.
|
|
17
|
+
if (!(r.l & CONFIG_GUESS) && r.ue !== NOT_PENDING) return r.ue;
|
|
16
18
|
const t = r.T.P;
|
|
17
|
-
return t !== NOT_PENDING ? t : r.le;
|
|
19
|
+
return t !== NOT_PENDING || r.m & STATUS_UNINITIALIZED ? t : r.le;
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
/** Truth readers (`until`, `refresh`; CONFIG_AUTHORITATIVE) — pay-for-use:
|
|
@@ -25,7 +27,7 @@ function laneValueOf(r) {
|
|
|
25
27
|
* value. */ function truthRead(r) {
|
|
26
28
|
if (truth(r)) return laneValueOf(r);
|
|
27
29
|
if (!(r.l & CONFIG_GUESS)) throw new NotReadyError(null);
|
|
28
|
-
return r.
|
|
30
|
+
return r.ue !== NOT_PENDING ? r.ue : r.le;
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
/** A guess confirmed: its lane's truth readers re-read — of the lane's
|
|
@@ -36,8 +38,8 @@ function laneValueOf(r) {
|
|
|
36
38
|
/** A lane node's value is the truth when every guess beneath it is
|
|
37
39
|
* confirmed — its source staged a value equal to the guess — and nothing
|
|
38
40
|
* beneath it is held in the parent: same inputs, same value. */ function truth(r) {
|
|
39
|
-
if (r.l & CONFIG_GUESS) return r.
|
|
40
|
-
if (r.
|
|
41
|
+
if (r.l & CONFIG_GUESS) return r.ue !== NOT_PENDING && r.ye && r.ye(r.T.P, r.ue);
|
|
42
|
+
if (r.ue !== NOT_PENDING) return;
|
|
41
43
|
if (r.l & CONFIG_OVERRIDE) for (let t = r.C; t; t = t.G) if (!truth(t.S)) return;
|
|
42
44
|
return 1;
|
|
43
45
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { CONFIG_VERDICT,
|
|
1
|
+
import { REACTIVE_PROBED, REACTIVE_WINDOW, CONFIG_VERDICT, CONFIG_ASYNC, CONFIG_CHILDREN_FORBIDDEN, CONFIG_OVERRIDE, STATUS_ERROR, CONFIG_GUESS, STATUS_PENDING, NOT_PENDING, STATUS_UNINITIALIZED, CONFIG_HELD, EFFECT_RENDER, CONFIG_STAGED_ERROR, REACTIVE_STAGED_READ, REACTIVE_PROBE_UNANSWERED, REACTIVE_REASK, CONFIG_INPUTS_PUBLISHED, REACTIVE_JOINED, REACTIVE_LANE_READ } from "./constants.js";
|
|
2
2
|
|
|
3
|
-
import { context, tracking, setVerdict, verdict, pullComputed, joinPass, markLateLinker, spectating, unflushedValue, bornInto } from "./core.js";
|
|
3
|
+
import { context, creatorPass, tracking, creatorReads, setVerdict, verdict, prepareComputed, pullComputed, joinPass, markLateLinker, spectating, unflushedValue, bornInto } from "./core.js";
|
|
4
4
|
|
|
5
5
|
import { NotReadyError } from "./error.js";
|
|
6
6
|
|
|
@@ -38,7 +38,7 @@ function watchVerdict(e, t = false) {
|
|
|
38
38
|
* node's, or the staging of a write this flush may hold — and the verdict
|
|
39
39
|
* does not rescue it: its result shows at the landing, re-derived). A lane
|
|
40
40
|
* read, for `recompute`'s tail (REACTIVE_LANE_READ). */ function route(e, t) {
|
|
41
|
-
if (passLane
|
|
41
|
+
if (!passLane && !(e.R & (REACTIVE_JOINED | REACTIVE_STAGED_READ))) setPassLane(verdictLane(t));
|
|
42
42
|
e.R |= REACTIVE_LANE_READ;
|
|
43
43
|
}
|
|
44
44
|
|
|
@@ -65,7 +65,7 @@ function watchVerdict(e, t = false) {
|
|
|
65
65
|
* transaction (`bornInto`, #4010): it has no screen — it waits on the flight
|
|
66
66
|
* with the rest of its frame. */ function observeFlight(e, t) {
|
|
67
67
|
if (t.l & CONFIG_INPUTS_PUBLISHED || t.l & CONFIG_HELD && bornInto(e, txOf(t))) return false;
|
|
68
|
-
if (globalQueue.
|
|
68
|
+
if (globalQueue.Y) {
|
|
69
69
|
joinFuture(null);
|
|
70
70
|
if (!(t.l & CONFIG_HELD)) queuePendingNode(t);
|
|
71
71
|
verdictRead(e, flushTransaction, true);
|
|
@@ -90,9 +90,9 @@ let probeFound = false;
|
|
|
90
90
|
* value notifying anyone (a held write's commit; a held landing's): its
|
|
91
91
|
* reader re-derives there. `latest` shows the proposal that lands — a
|
|
92
92
|
* rewrite or a landing reaches its reader through the link it holds — so a
|
|
93
|
-
* re-run would only repeat the frame. */ function verdictRead(e, t,
|
|
93
|
+
* re-run would only repeat the frame. */ function verdictRead(e, t, r) {
|
|
94
94
|
route(e, t);
|
|
95
|
-
if (
|
|
95
|
+
if (r) staleReader(e, t); else if (probing && t.En[t.En.length - 1] !== e) t.En.push(e);
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
/** A verdict read of a node staged or in flight but not held yet: whether it
|
|
@@ -105,40 +105,41 @@ let probeFound = false;
|
|
|
105
105
|
* watches the seam and runs again if the flush parks (a plain sync write
|
|
106
106
|
* never glitches it true).
|
|
107
107
|
*
|
|
108
|
-
* `latest` has its answer either way — the proposal —
|
|
109
|
-
* membership
|
|
110
|
-
* (
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
if (flushTransaction !== null) {
|
|
123
|
-
if (t) probeFound = true;
|
|
108
|
+
* `latest` has its answer either way — the proposal — but its reader's
|
|
109
|
+
* membership is the seam's too: the frame opens no transaction for it
|
|
110
|
+
* (#4365 — one opened for the read alone made a plain read after the window
|
|
111
|
+
* take it for a hold, `stagedScreen`, and serve the screen beside the
|
|
112
|
+
* staging in a frame nothing held). The reader watches the seam like a
|
|
113
|
+
* probe before anything joined: its pass is the frame's, and runs again in
|
|
114
|
+
* the verdict lane if the flush parks. Once the flush has joined a
|
|
115
|
+
* transaction, the reader is its verdict lane's at once; a pass that also
|
|
116
|
+
* read the frame's own stagings plainly (REACTIVE_STAGED_READ) stays the
|
|
117
|
+
* frame's (`route` does not move it). */ function provisionalVerdict(e, t) {
|
|
118
|
+
if (flushTransaction) {
|
|
119
|
+
if (probing && t) probeFound = true;
|
|
124
120
|
verdictRead(e, flushTransaction);
|
|
125
|
-
if (e.R & REACTIVE_STAGED_READ) watchVerdict(e);
|
|
121
|
+
if (probing && e.R & REACTIVE_STAGED_READ) watchVerdict(e);
|
|
126
122
|
return;
|
|
127
123
|
}
|
|
128
124
|
// Before anything joined, a staging that would not be final held has no
|
|
129
125
|
// answer yet: whatever the seam decides, the pass runs again — a later
|
|
130
126
|
// plain read of the same pass may route it into the verdict lane
|
|
131
127
|
// (`observeFlight`), which the seam must not take as this probe's answer.
|
|
132
|
-
|
|
128
|
+
// `latest` opens no transaction for its answer either (#4365): the plain
|
|
129
|
+
// read of a staging after it took one opened for it for a hold and paired
|
|
130
|
+
// the staging with the screen, in a frame nothing held. Its pass is the
|
|
131
|
+
// frame's — whole — and re-derives once if the flush parks (unanswered:
|
|
132
|
+
// its membership is the seam's, not the transaction it joins).
|
|
133
|
+
watchVerdict(e, !probing || t);
|
|
133
134
|
}
|
|
134
135
|
|
|
135
136
|
/** A19 exc. 2 / A24: a flight that re-asks the question already answered
|
|
136
137
|
* (a `refresh()`, a poll) is quiet; a node pending through others is quiet
|
|
137
138
|
* when every flight it waits on is. */ function quietPending(e) {
|
|
138
139
|
const t = e.T;
|
|
139
|
-
if (t
|
|
140
|
-
if (t.
|
|
141
|
-
for (const e of t.
|
|
140
|
+
if (!t) return false;
|
|
141
|
+
if (t.se) {
|
|
142
|
+
for (const e of t.se) if (!e.T?.Ve) return false;
|
|
142
143
|
return true;
|
|
143
144
|
}
|
|
144
145
|
return t.Ve;
|
|
@@ -157,16 +158,24 @@ let probeFound = false;
|
|
|
157
158
|
* flight — a staging equal to what is displayed changes nothing when it
|
|
158
159
|
* lands: final now (maintainer, 2026-10-02). */ function heldNotFinal(e) {
|
|
159
160
|
if ((e.m & STATUS_PENDING) !== 0 && !quietPending(e)) return true;
|
|
160
|
-
return e.
|
|
161
|
+
return e.ue !== NOT_PENDING && !latestActive && !e.T.Ve && !(e.m & STATUS_UNINITIALIZED) && (!!e.T.Te || !e.ye || !e.ye(e.le, e.ue));
|
|
161
162
|
}
|
|
162
163
|
|
|
163
164
|
/** `isPending`'s answer for an unheld node whose flight is up (cause ii). */ function pendingVerdict(e, t) {
|
|
164
165
|
if (t.m & STATUS_UNINITIALIZED) return;
|
|
165
166
|
if (probing && !quietPending(t)) probeFound = true;
|
|
166
|
-
if (e
|
|
167
|
-
if (t.l & CONFIG_HELD) verdictRead(e, txOf(t)); else if (globalQueue.
|
|
167
|
+
if (e && tracking) {
|
|
168
|
+
if (t.l & CONFIG_HELD) verdictRead(e, txOf(t)); else if (globalQueue.Y) {
|
|
169
|
+
// `latest` of a flight serves the committed value, the frame's and the
|
|
170
|
+
// lane's alike (D-22): nothing is the seam's, so the reader is the
|
|
171
|
+
// verdict lane's now, as a plain read of a flight makes it
|
|
172
|
+
// (`observeFlight`). Its frame pass re-derived in the lane (R5) asked
|
|
173
|
+
// its question again (F-9, #4397). A staging's is the seam's (#4365).
|
|
174
|
+
if (!probing) joinFuture(null);
|
|
175
|
+
provisionalVerdict(e, false);
|
|
168
176
|
// decided above
|
|
169
|
-
|
|
177
|
+
}
|
|
178
|
+
}
|
|
170
179
|
}
|
|
171
180
|
|
|
172
181
|
/** The pass entering a verdict window is a verdict reader (CONFIG_VERDICT):
|
|
@@ -174,11 +183,19 @@ let probeFound = false;
|
|
|
174
183
|
* an untracked window: that is a snapshot, like any untracked read (#3946 —
|
|
175
184
|
* a router's link claim probing inside the computation that creates the
|
|
176
185
|
* anchor). A throw still reaches the pass through `untrack`. */ function markVerdictReader(e) {
|
|
177
|
-
|
|
178
|
-
if (t
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
186
|
+
const t = creatorPass(context);
|
|
187
|
+
if (t && tracking) {
|
|
188
|
+
// A pass run inside passes still running — its creator's, theirs — one
|
|
189
|
+
// of which read the future or a staging (a branch a held or staged
|
|
190
|
+
// condition opened, and whatever that branch creates) has no screen: the
|
|
191
|
+
// branch exists only in that world. It reads that world as any
|
|
192
|
+
// derivation of it does (`bornInto` once held) and stays its pass
|
|
193
|
+
// (`route`); a verdict reader from its next pass. #4341: a memo born in
|
|
194
|
+
// a newly opened <Match> read the screen, where its branch was closed.
|
|
195
|
+
// Not such a pass: a verdict reader now.
|
|
196
|
+
t.l &= ~CONFIG_ASYNC;
|
|
197
|
+
t.R |= REACTIVE_PROBED | REACTIVE_WINDOW | (creatorReads(t, 0) || (t.l |= CONFIG_VERDICT,
|
|
198
|
+
0));
|
|
182
199
|
}
|
|
183
200
|
}
|
|
184
201
|
|
|
@@ -186,14 +203,14 @@ let probeFound = false;
|
|
|
186
203
|
* restores the dispatch it found — none inside a memo's pass a window
|
|
187
204
|
* pulled (`verdictValue`). */ function latest(e) {
|
|
188
205
|
markVerdictReader();
|
|
189
|
-
const t = latestActive,
|
|
206
|
+
const t = latestActive, r = verdict;
|
|
190
207
|
latestActive = true;
|
|
191
208
|
setVerdict(verdictValue);
|
|
192
209
|
try {
|
|
193
210
|
return e();
|
|
194
211
|
} finally {
|
|
195
212
|
latestActive = t;
|
|
196
|
-
setVerdict(
|
|
213
|
+
setVerdict(r);
|
|
197
214
|
}
|
|
198
215
|
}
|
|
199
216
|
|
|
@@ -231,8 +248,8 @@ let probeFound = false;
|
|
|
231
248
|
*/ function isPending(e) {
|
|
232
249
|
markVerdictReader();
|
|
233
250
|
const t = probing;
|
|
234
|
-
const
|
|
235
|
-
const
|
|
251
|
+
const r = probeFound;
|
|
252
|
+
const i = verdict;
|
|
236
253
|
probing = true;
|
|
237
254
|
probeFound = false;
|
|
238
255
|
setVerdict(verdictValue);
|
|
@@ -250,23 +267,23 @@ let probeFound = false;
|
|
|
250
267
|
return probeFound;
|
|
251
268
|
} finally {
|
|
252
269
|
probing = t;
|
|
253
|
-
probeFound =
|
|
254
|
-
setVerdict(
|
|
270
|
+
probeFound = r;
|
|
271
|
+
setVerdict(i);
|
|
255
272
|
}
|
|
256
273
|
}
|
|
257
274
|
|
|
258
275
|
/** The staging, or the staged error thrown (D-41). */ function staged(e) {
|
|
259
|
-
if (e.l & CONFIG_STAGED_ERROR) throw e.
|
|
260
|
-
return e.
|
|
276
|
+
if (e.l & CONFIG_STAGED_ERROR) throw e.ue;
|
|
277
|
+
return e.ue;
|
|
261
278
|
}
|
|
262
279
|
|
|
263
280
|
/** `latest()` of a held node: the flushed staging — the proposal — and, for
|
|
264
281
|
* a tracked reader of a rewrite not yet flushed, the late-linker re-run in
|
|
265
282
|
* the flush that carries it. */ function heldLatest(e, t) {
|
|
266
|
-
const
|
|
267
|
-
if (
|
|
268
|
-
if (t
|
|
269
|
-
return
|
|
283
|
+
const r = unflushedValue(e);
|
|
284
|
+
if (r === NOT_PENDING) return staged(e);
|
|
285
|
+
if (t) markLateLinker(t);
|
|
286
|
+
return r;
|
|
270
287
|
}
|
|
271
288
|
|
|
272
289
|
/** The verdict windows' read — `latest(fn)` and `isPending(fn)` — in one
|
|
@@ -279,7 +296,9 @@ let probeFound = false;
|
|
|
279
296
|
* differs (A24, A18 provenance). A derivation: `latest` sees the lane's
|
|
280
297
|
* latest (a landing a blocked lane holds has answered its question — the
|
|
281
298
|
* checkout's shipping text updates independently of the tax in flight),
|
|
282
|
-
* `isPending` the screen; not final while its own flight is up
|
|
299
|
+
* `isPending` the screen; not final while its own flight is up. A
|
|
300
|
+
* derivation's first load in flight (nothing produced yet — an async memo
|
|
301
|
+
* over a verdict memo, F-6) reads as the flight below: loading (D-22);
|
|
283
302
|
* - a held node: the reader breaks out as the holder's verdict lane's and
|
|
284
303
|
* re-derives at the landing; `latest` serves the proposal (`heldLatest`),
|
|
285
304
|
* `isPending` answers `heldNotFinal`;
|
|
@@ -290,63 +309,76 @@ let probeFound = false;
|
|
|
290
309
|
* serves the committed value — below the async nothing newer exists; an
|
|
291
310
|
* uninitialized one throws NotReady: loading, not pending (A19 exc. 1);
|
|
292
311
|
* - an errored derivation throws for every reader (#2897). */ function verdictValue(e, t) {
|
|
293
|
-
const
|
|
294
|
-
const
|
|
295
|
-
const
|
|
296
|
-
|
|
312
|
+
const r = e;
|
|
313
|
+
const i = !!t && !(t.l & CONFIG_CHILDREN_FORBIDDEN);
|
|
314
|
+
const n = i && tracking;
|
|
315
|
+
// A31: the pulled memo's pass is its own, not the probe's — it reads
|
|
316
|
+
// outside the window, and the probe's read below answers for what the pass
|
|
317
|
+
// produced. So is a lazy or dormant memo's wake (an unowned memo with no
|
|
318
|
+
// reader left, #4366): woken inside the window, it read its sources as the
|
|
319
|
+
// probe does, the committed value under a landing. (A signal has no
|
|
320
|
+
// `_flags`: the wake is a no-op for it.)
|
|
321
|
+
setVerdict(null);
|
|
322
|
+
prepareComputed(r);
|
|
323
|
+
if (t && tracking) {
|
|
297
324
|
link(e, t);
|
|
298
|
-
if (
|
|
299
|
-
// A31: the pulled memo's pass is its own, not the probe's — it reads
|
|
300
|
-
// outside the window, and the probe's read below answers for what
|
|
301
|
-
// the pass produced.
|
|
302
|
-
setVerdict(null);
|
|
303
|
-
pullComputed(n, t);
|
|
304
|
-
setVerdict(verdictValue);
|
|
305
|
-
}
|
|
325
|
+
if (e.X) pullComputed(r, t);
|
|
306
326
|
}
|
|
327
|
+
setVerdict(verdictValue);
|
|
307
328
|
// A live `affects()` mark on the node or a dependency (affects.ts): not
|
|
308
329
|
// final by declaration — the value itself is read as below. The verdict is
|
|
309
330
|
// display-ahead like any: in a transaction's flush (the declaring action's
|
|
310
331
|
// body) the reader is its verdict lane's, not a staging the frame parks.
|
|
311
|
-
if (probing && GlobalQueue.p
|
|
332
|
+
if (probing && GlobalQueue.p?.(r)) {
|
|
312
333
|
probeFound = true;
|
|
313
|
-
if (
|
|
334
|
+
if (n && flushTransaction) verdictRead(t, flushTransaction);
|
|
314
335
|
}
|
|
315
|
-
if (e.l & CONFIG_OVERRIDE && !(
|
|
316
|
-
const
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
336
|
+
if (e.l & CONFIG_OVERRIDE && !(r.m & STATUS_ERROR && !(e.l & CONFIG_GUESS))) {
|
|
337
|
+
const i = txOf(e), o = (r.m & STATUS_PENDING) !== 0 && !quietPending(r), a = e.l & CONFIG_GUESS,
|
|
338
|
+
// NOT_PENDING: a node born in the lane with nothing in it yet has no
|
|
339
|
+
// value in either view — loading, not pending, and no verdict to read
|
|
340
|
+
// ahead: it is read as any uninitialized node, NotReady below (A7, A19
|
|
341
|
+
// exc. 1; #4363), its reader not moved into the verdict lane.
|
|
342
|
+
u = a ? 0 : latestActive && !o ? laneValueOf(e) : display(e);
|
|
343
|
+
if (u !== NOT_PENDING) {
|
|
344
|
+
if (n) verdictRead(t, i._parent ?? i);
|
|
345
|
+
if (a) {
|
|
346
|
+
if (probing && (o || e.ue !== NOT_PENDING && (!e.ye || !e.ye(e.T.P, e.ue)))) probeFound = true;
|
|
347
|
+
// A lane a correction folded under (D-34): `latest()` shows the hold's
|
|
348
|
+
// world whole — the truth beneath each guess, else what it covered.
|
|
349
|
+
if (latestActive && i.folded) return i.folded(null, e);
|
|
350
|
+
return e.T.P;
|
|
351
|
+
}
|
|
352
|
+
// A first load in flight with nothing produced yet: loading, for
|
|
353
|
+
// `latest` (D-22) as for `isPending` (A19 exc. 1) — unless an error
|
|
354
|
+
// answered it first: its re-ask is pending, the error its display
|
|
355
|
+
// (D-41, #4375).
|
|
356
|
+
if (o && u === e.le && r.m & STATUS_UNINITIALIZED && (latestActive || !r.T.Te)) throw r.T.U;
|
|
357
|
+
if (probing && o) probeFound = true;
|
|
358
|
+
return u;
|
|
325
359
|
}
|
|
326
|
-
if (probing && u) probeFound = true;
|
|
327
|
-
return latestActive && !u ? laneValueOf(e) : display(e);
|
|
328
360
|
}
|
|
329
|
-
const
|
|
361
|
+
const o = (r.m & STATUS_UNINITIALIZED) !== 0;
|
|
330
362
|
if (e.l & CONFIG_HELD) {
|
|
331
|
-
if (!
|
|
332
|
-
const
|
|
363
|
+
if (!o) {
|
|
364
|
+
const i = txOf(e);
|
|
333
365
|
// A render effect re-run (or mounted) outside the verdict lane's flush
|
|
334
366
|
// while the lane is blocked — its display held on its own derivation
|
|
335
367
|
// in flight — is a stale reader of the lane (#3460, as `laneRead`): the
|
|
336
368
|
// committed value now, re-derived at the reveal. Not inside a probe:
|
|
337
369
|
// `isPending` is answered below either way.
|
|
338
|
-
if (
|
|
339
|
-
staleReader(t,
|
|
370
|
+
if (n && !probing && t.i === EFFECT_RENDER && !passLane && i.Pe?.ln && flushTransaction !== i) {
|
|
371
|
+
staleReader(t, i.Pe);
|
|
340
372
|
return e.le;
|
|
341
373
|
}
|
|
342
|
-
if (
|
|
343
|
-
if (probing && heldNotFinal(
|
|
344
|
-
if (latestActive && e.
|
|
374
|
+
if (n) verdictRead(t, i);
|
|
375
|
+
if (probing && heldNotFinal(r)) probeFound = true;
|
|
376
|
+
if (latestActive && e.ue !== NOT_PENDING) {
|
|
345
377
|
// An action body reading another transaction's proposal derives
|
|
346
378
|
// from it: the two settle as one (A15; posture C, 2026-09-15). An
|
|
347
379
|
// untracked read elsewhere has no transaction to entangle.
|
|
348
|
-
if (!
|
|
349
|
-
return heldLatest(e,
|
|
380
|
+
if (!n && flushTransaction && !globalQueue.Y) joinFuture(txOf(e));
|
|
381
|
+
return heldLatest(e, n ? t : null);
|
|
350
382
|
}
|
|
351
383
|
return e.le;
|
|
352
384
|
}
|
|
@@ -354,46 +386,76 @@ let probeFound = false;
|
|
|
354
386
|
// committed value, so no verdict: `isPending` reads it as its read does —
|
|
355
387
|
// the owner joins the hold (held with it, or caught by a boundary that
|
|
356
388
|
// has not shown content) and answers for the commit, where it is final.
|
|
357
|
-
if (e.
|
|
358
|
-
if (probing &&
|
|
389
|
+
if (e.ue !== NOT_PENDING && !(r.m & STATUS_PENDING)) {
|
|
390
|
+
if (probing && i) joinPass(t, e);
|
|
359
391
|
return staged(e);
|
|
360
392
|
}
|
|
361
|
-
} else if (e.
|
|
362
|
-
if (
|
|
393
|
+
} else if (e.ue !== NOT_PENDING) {
|
|
394
|
+
if (r.m & STATUS_PENDING && !o) pendingVerdict(n ? t : null, r); else if (n && globalQueue.Y) provisionalVerdict(t, !latestActive && !o);
|
|
363
395
|
// Outside a flush, the staging is an unflushed write (A28): the probe
|
|
364
396
|
// answers for the flushed world, and watches the seam of the flush that
|
|
365
397
|
// carries the write — a memo of `isPending(x)` created after the write
|
|
366
398
|
// flips if that flush parks (#3078). (The write's own fan-out ran before
|
|
367
399
|
// the reader existed; nothing else would re-derive it.)
|
|
368
|
-
else if (
|
|
400
|
+
else if (n && probing) watchVerdict(t);
|
|
369
401
|
if (latestActive) {
|
|
370
402
|
// A28: an unflushed write is not what `latest` serves; a tracked
|
|
371
403
|
// reader derived from the flushed world runs again in the carrying
|
|
372
404
|
// flush.
|
|
373
|
-
if (globalQueue.
|
|
374
|
-
if (t
|
|
405
|
+
if (globalQueue.Y) return staged(e);
|
|
406
|
+
if (t) markLateLinker(t);
|
|
375
407
|
}
|
|
376
408
|
return e.le;
|
|
377
409
|
}
|
|
378
|
-
if (
|
|
379
|
-
if (!
|
|
380
|
-
pendingVerdict(
|
|
410
|
+
if (r.m & STATUS_PENDING) {
|
|
411
|
+
if (!o) {
|
|
412
|
+
pendingVerdict(n ? t : null, r);
|
|
381
413
|
return e.le;
|
|
382
414
|
}
|
|
383
415
|
// As `read()`: an untracked read of a pending node still re-runs its
|
|
384
416
|
// reader when the node settles (a projection's pull reads its firewall
|
|
385
417
|
// untracked, store/store.ts).
|
|
386
|
-
if (t
|
|
387
|
-
throw
|
|
418
|
+
if (t && !tracking && !spectating && e !== t) link(e, t);
|
|
419
|
+
throw r.T?.U;
|
|
388
420
|
}
|
|
389
|
-
if (
|
|
421
|
+
if (e.X && r.m & STATUS_ERROR) throw r.T.U;
|
|
390
422
|
return e.le;
|
|
391
423
|
}
|
|
392
424
|
|
|
425
|
+
/** D-25: a node whose fetch a hold is waiting on is that hold's work, not a
|
|
426
|
+
* verdict reader — a pass that re-runs it reads plainly — and a memo's
|
|
427
|
+
* posture is what it reads: one that reads a verdict reader's value is a
|
|
428
|
+
* verdict reader itself (#4050). An async memo with no verdict window of its
|
|
429
|
+
* own (REACTIVE_WINDOW: it read a verdict memo, it called neither `latest`
|
|
430
|
+
* nor `isPending`) is a verdict reader between its flights, and the hold's
|
|
431
|
+
* work while one is up or its hold re-runs it.
|
|
432
|
+
*
|
|
433
|
+
* At a pass's head (core.ts `recompute`): a pending node's pass — its
|
|
434
|
+
* flight is the transition's own work (#3884) — and a held one's re-run of
|
|
435
|
+
* such a memo read plainly: the write that re-ran it is its hold's, and
|
|
436
|
+
* served the screen it re-asked a question it had answered (A10, #4397).
|
|
437
|
+
* Only a memo that never asked: D-25's "a verdict posture outlives the pass
|
|
438
|
+
* that asked" is a pass that called `latest`/`isPending`, which clears
|
|
439
|
+
* CONFIG_ASYNC and stays a verdict reader whoever dirties it.
|
|
440
|
+
*
|
|
441
|
+
* On `source` going pending (`propagateStatus`): such a memo waits on it
|
|
442
|
+
* like any derivation (F-9) instead of re-deriving — what it read changed
|
|
443
|
+
* no value, so its re-run re-asked the question it was answering. Unless
|
|
444
|
+
* its own flight is up outside a lane on a new question of the source's:
|
|
445
|
+
* its re-run supersedes a flight asked of a value the source has moved past
|
|
446
|
+
* (re-asked by a `refresh()`, the source's question is the same one). */ function holdWork(e, t) {
|
|
447
|
+
// CONFIG_ASYNC records an async memo with no window of its own: its last
|
|
448
|
+
// answering pass registered a flight (`handleAsync`) and called neither
|
|
449
|
+
// `latest` nor `isPending`. A window (`markVerdictReader`), a sync answer or
|
|
450
|
+
// an error clears it; a pass left pending keeps the last answer's.
|
|
451
|
+
const r = e.l & CONFIG_ASYNC;
|
|
452
|
+
return r && (!(e.m & STATUS_PENDING) || e.T.Re?.P || t.R & REACTIVE_REASK);
|
|
453
|
+
}
|
|
454
|
+
|
|
393
455
|
// Installed at module evaluation — present exactly when something imports
|
|
394
456
|
// `latest` or `isPending`. (`read` dispatches to `verdictValue` through
|
|
395
457
|
// `verdict`, set while a window is open.)
|
|
396
|
-
installVerdictHooks(observeFlight);
|
|
458
|
+
installVerdictHooks(observeFlight, holdWork);
|
|
397
459
|
|
|
398
460
|
/** A store read inside an untracked `isPending` probe found a live mark on
|
|
399
461
|
* a record with no node to carry it (store/affects.ts): not final. */ GlobalQueue.rt = () => {
|
package/dist/prod/deferred.js
CHANGED
|
@@ -121,7 +121,7 @@ GlobalQueue.er = e => lagging.size !== 0 ? lagOf(e, new Set) : undefined;
|
|
|
121
121
|
* does not replace (D-40) — restaged as the committed value, the hold's
|
|
122
122
|
* readers would re-derive against the old input. */ const serve = e => {
|
|
123
123
|
const r = handleAsync(t, e);
|
|
124
|
-
return t.l & CONFIG_HELD && t.
|
|
124
|
+
return t.l & CONFIG_HELD && t.ue !== NOT_PENDING ? t.ue : r;
|
|
125
125
|
};
|
|
126
126
|
const end = () => t.R & REACTIVE_DISPOSED && land(o);
|
|
127
127
|
return accessor(computed(r => {
|
package/dist/prod/index.js
CHANGED
|
@@ -24,6 +24,8 @@ import "./core/effect.js";
|
|
|
24
24
|
|
|
25
25
|
export { configureClientErrors } from "./core/error-hooks.js";
|
|
26
26
|
|
|
27
|
+
export { checkForeignOwnerless, runAsSolidCopy } from "./core/copies.js";
|
|
28
|
+
|
|
27
29
|
export { storeName } from "./store/edges.js";
|
|
28
30
|
|
|
29
31
|
export { createEffect, createMemo, createOptimistic, createReaction, createRenderEffect, createSignal, createTrackedEffect, onCleanup, onFlush, onSettled, refresh, resolve, until } from "./signals.js";
|