@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/async.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { STATUS_ERROR, STATUS_PENDING, STATUS_NO_VALUE, STATUS_UNINITIALIZED, CONFIG_GUESS, REACTIVE_RECOMPUTING_DEPS, CONFIG_HELD, REACTIVE_STAGED_READ, CONFIG_STAGED, CONFIG_STAGED_ERROR, CONFIG_AUTO_DISPOSE, REACTIVE_ZOMBIE, NewSet, REACTIVE_DIRTY, CONFIG_INPUTS_PUBLISHED, NOT_PENDING, REACTIVE_DISPOSED, CONFIG_REDERIVE, CONFIG_VERDICT, CONFIG_OVERRIDE } from "./constants.js";
|
|
1
|
+
import { STATUS_ERROR, STATUS_PENDING, STATUS_NO_VALUE, STATUS_UNINITIALIZED, CONFIG_GUESS, REACTIVE_REASK, REACTIVE_RECOMPUTING_DEPS, CONFIG_ASYNC, REACTIVE_WINDOW, CONFIG_HELD, REACTIVE_STAGED_READ, CONFIG_STAGED, CONFIG_STAGED_ERROR, CONFIG_AUTO_DISPOSE, REACTIVE_ZOMBIE, NewSet, REACTIVE_DIRTY, CONFIG_INPUTS_PUBLISHED, NOT_PENDING, REACTIVE_DISPOSED, CONFIG_REDERIVE, CONFIG_VERDICT, CONFIG_OVERRIDE } from "./constants.js";
|
|
2
2
|
|
|
3
3
|
import { ext, statusNotifierOf, context, untrack, setSignal } from "./core.js";
|
|
4
4
|
|
|
@@ -10,30 +10,30 @@ import { enqueueSub } from "./heap.js";
|
|
|
10
10
|
|
|
11
11
|
import { disposeChildren, cleanup } from "./owner.js";
|
|
12
12
|
|
|
13
|
-
import { passLane, joinFuture, question, MAINLINE_QUESTION, globalQueue, schedule, clock, flush, freshHook,
|
|
13
|
+
import { guessing, passLane, joinFuture, txOf, holdWorkHook, question, MAINLINE_QUESTION, globalQueue, schedule, clock, flush, freshHook, laneStageHook, queuePendingNode } from "./scheduler.js";
|
|
14
14
|
|
|
15
15
|
// The lazily-created Set is the ONE container for pending sources. Its
|
|
16
16
|
// predecessor — a singular slot promoted to a Set on the second source —
|
|
17
17
|
// created dual state whose migration invariant was easy to break: a third
|
|
18
18
|
// overlapping source landed beside the Set and removePendingSource refused
|
|
19
19
|
// to clear it, stranding the Set members' pending forever (#2893).
|
|
20
|
-
function addPendingSource(e,
|
|
21
|
-
if (e.T?.
|
|
22
|
-
(ext(e).
|
|
20
|
+
function addPendingSource(e, t) {
|
|
21
|
+
if (e.T?.se?.has(t)) return false;
|
|
22
|
+
(ext(e).se ??= new NewSet).add(t);
|
|
23
23
|
return true;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
function removePendingSource(e,
|
|
27
|
-
const
|
|
28
|
-
if (!
|
|
29
|
-
if (!
|
|
26
|
+
function removePendingSource(e, t) {
|
|
27
|
+
const n = e.T?.se;
|
|
28
|
+
if (!n?.delete(t)) return false;
|
|
29
|
+
if (!n.size) e.T.se = undefined;
|
|
30
30
|
return true;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
function clearPendingSources(e) {
|
|
34
34
|
// This set is node-owned and never shared; dropping the sole reference
|
|
35
35
|
// releases the set and every entry without a redundant clear() walk.
|
|
36
|
-
if (e.T !== null) e.T.
|
|
36
|
+
if (e.T !== null) e.T.se = undefined;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
// A rejection-pending only resolves through the settle sweep over the
|
|
@@ -41,10 +41,10 @@ function clearPendingSources(e) {
|
|
|
41
41
|
// edge: a dep that IS the source, or one whose own pending chain carries it
|
|
42
42
|
// (pending sources propagate the origin node, so this covers any depth).
|
|
43
43
|
// Also guards branch-local recovery: another dependency may still need the source.
|
|
44
|
-
function retryReaches(e,
|
|
45
|
-
for (let
|
|
46
|
-
const e =
|
|
47
|
-
if (e ===
|
|
44
|
+
function retryReaches(e, t) {
|
|
45
|
+
for (let n = e.C; n; n = n.G) {
|
|
46
|
+
const e = n.S;
|
|
47
|
+
if (e === t || e.T?.se?.has(t)) return true;
|
|
48
48
|
}
|
|
49
49
|
return false;
|
|
50
50
|
}
|
|
@@ -55,33 +55,33 @@ function retryReaches(e, n) {
|
|
|
55
55
|
* settlePendingSource walk runs off `_pendingSources` + `_blocked` alone —
|
|
56
56
|
* with NO read-visible pending status and no downstream propagation. Commit
|
|
57
57
|
* #0 keeps serving.
|
|
58
|
-
*/ function parkLoadingWindow(e,
|
|
59
|
-
ext(e).
|
|
60
|
-
if (
|
|
58
|
+
*/ function parkLoadingWindow(e, t) {
|
|
59
|
+
ext(e).fe = true;
|
|
60
|
+
if (t.source) addPendingSource(e, t.source);
|
|
61
61
|
// A settled error is the node's answer ("the error stays the answer until
|
|
62
62
|
// this retry can actually run") — the park must not replace it: reads
|
|
63
63
|
// throw `_error` while STATUS_ERROR is set, and overwriting it here leaks
|
|
64
64
|
// a pending-class NotReadyError from a read-invisible park (#2989).
|
|
65
|
-
if (!(e.m & STATUS_ERROR)) setPendingError(e,
|
|
65
|
+
if (!(e.m & STATUS_ERROR)) setPendingError(e, t.source, t);
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
function setPendingError(e,
|
|
69
|
-
if (!
|
|
68
|
+
function setPendingError(e, t, n) {
|
|
69
|
+
if (!t) {
|
|
70
70
|
if (e.T !== null) e.T.U = null;
|
|
71
71
|
return;
|
|
72
72
|
}
|
|
73
|
-
if (
|
|
74
|
-
ext(e).U =
|
|
73
|
+
if (n instanceof NotReadyError && n.source === t) {
|
|
74
|
+
ext(e).U = n;
|
|
75
75
|
return;
|
|
76
76
|
}
|
|
77
77
|
const r = e.T?.U;
|
|
78
|
-
if (!(r instanceof NotReadyError) || r.source !==
|
|
79
|
-
ext(e).U = new NotReadyError(
|
|
78
|
+
if (!(r instanceof NotReadyError) || r.source !== t) {
|
|
79
|
+
ext(e).U = new NotReadyError(t);
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
function forEachDependent(e,
|
|
84
|
-
for (let
|
|
83
|
+
function forEachDependent(e, t) {
|
|
84
|
+
for (let n = e.o; n !== null; n = n.t) t(n.u, n);
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
// Queue a node to re-run on the next flush (used both when a pending source
|
|
@@ -103,16 +103,16 @@ function releaseIfSettledUnobserved(e) {
|
|
|
103
103
|
// the propagation completes, walk the same graph for stranded lazy nodes.
|
|
104
104
|
// Collect-then-release so unobserved() never unlinks under the walk.
|
|
105
105
|
function releaseSettledDependents(e) {
|
|
106
|
-
let
|
|
107
|
-
const
|
|
106
|
+
let t;
|
|
107
|
+
const n = new NewSet;
|
|
108
108
|
const visit = e => {
|
|
109
|
-
if (
|
|
110
|
-
|
|
111
|
-
if (!e.o && e.l & CONFIG_AUTO_DISPOSE) (
|
|
109
|
+
if (n.has(e)) return;
|
|
110
|
+
n.add(e);
|
|
111
|
+
if (!e.o && e.l & CONFIG_AUTO_DISPOSE) (t ??= []).push(e);
|
|
112
112
|
forEachDependent(e, visit);
|
|
113
113
|
};
|
|
114
114
|
forEachDependent(e, visit);
|
|
115
|
-
if (
|
|
115
|
+
if (t) for (const e of t) releaseIfSettledUnobserved(e);
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
// Error-dimension twin of settlePendingSource's blocked re-enqueue (#2949):
|
|
@@ -137,7 +137,7 @@ function releaseSettledDependents(e) {
|
|
|
137
137
|
* it through the ordinary error path (`commitPendingNode` → `notifyStatus`),
|
|
138
138
|
* dependents included. Not for a lane pass, nor a node with no shown value
|
|
139
139
|
* (born held — its error has no frame to wait behind): those publish now,
|
|
140
|
-
* as before. Returns whether the error was staged. */ function stageError(e,
|
|
140
|
+
* as before. Returns whether the error was staged. */ function stageError(e, t, n) {
|
|
141
141
|
// Held, or — for a pass's own throw — derived from a staging of a flush
|
|
142
142
|
// (REACTIVE_STAGED_READ is this pass's; a landing after the pass cannot
|
|
143
143
|
// read it, the flush it read a staging of has committed or parked since).
|
|
@@ -146,13 +146,13 @@ function releaseSettledDependents(e) {
|
|
|
146
146
|
// (#4109). A flush that parks nothing publishes it at its commit (S-38).
|
|
147
147
|
// Not a projection's derive: its readers learn its error through the
|
|
148
148
|
// family, which the commit's publish never reaches (#4189).
|
|
149
|
-
if (!(e.l & CONFIG_HELD ||
|
|
149
|
+
if (!(e.l & CONFIG_HELD || n && e.R & REACTIVE_STAGED_READ && globalQueue.Y && !e.fam) || passLane) return false;
|
|
150
150
|
// The node answered (an error ends the wait — no longer pending, nor
|
|
151
151
|
// blocked); a shown error stays its display until the commit.
|
|
152
152
|
clearPendingSources(e);
|
|
153
|
-
if (e.T) e.T.
|
|
153
|
+
if (e.T) e.T.fe = false;
|
|
154
154
|
if (!((e.m &= STATUS_ERROR | STATUS_UNINITIALIZED) & STATUS_ERROR)) setPendingError(e);
|
|
155
|
-
e.
|
|
155
|
+
e.ue = t instanceof StatusError ? t : new StatusError(e, t);
|
|
156
156
|
e.l |= CONFIG_STAGED | CONFIG_STAGED_ERROR;
|
|
157
157
|
// Readers parked on the flight re-run and derive from the staging; the
|
|
158
158
|
// verdict readers the walk wakes need a flush (#4106).
|
|
@@ -161,84 +161,85 @@ function releaseSettledDependents(e) {
|
|
|
161
161
|
return true;
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
-
function settleErroredDependents(e,
|
|
165
|
-
let
|
|
164
|
+
function settleErroredDependents(e, t) {
|
|
165
|
+
let n = false;
|
|
166
166
|
const r = new NewSet;
|
|
167
167
|
const visit = e => {
|
|
168
168
|
if (r.has(e)) return;
|
|
169
169
|
r.add(e);
|
|
170
|
-
if (e.T?.U ===
|
|
170
|
+
if (e.T?.U === t) {
|
|
171
171
|
enqueueSub(e);
|
|
172
|
-
|
|
172
|
+
n = true;
|
|
173
173
|
}
|
|
174
174
|
forEachDependent(e, visit);
|
|
175
175
|
};
|
|
176
176
|
forEachDependent(e, visit);
|
|
177
|
-
if (
|
|
177
|
+
if (n) schedule();
|
|
178
178
|
}
|
|
179
179
|
|
|
180
180
|
// Retire `source` from pending state along the dependent graph rooted at `el`.
|
|
181
181
|
// By default, `el` is the source whose flight settled or was superseded.
|
|
182
182
|
// With a distinct `source`, `el` is a recovered computation that dropped it:
|
|
183
183
|
// the source may still be pending, so dependents with another path to it stay pending.
|
|
184
|
-
function settlePendingSource(e,
|
|
184
|
+
function settlePendingSource(e, t = e) {
|
|
185
185
|
// Landing and branch recovery already cleared el's own set. Superseded
|
|
186
186
|
// re-parks can retain an abandoned self entry (source === el), which must
|
|
187
187
|
// retire in the same walk as its propagated copies.
|
|
188
|
-
removePendingSource(e,
|
|
189
|
-
let
|
|
188
|
+
removePendingSource(e, t);
|
|
189
|
+
let n = false;
|
|
190
190
|
let r;
|
|
191
191
|
const o = new NewSet;
|
|
192
|
-
const settle =
|
|
193
|
-
if (o.has(
|
|
192
|
+
const settle = s => {
|
|
193
|
+
if (o.has(s) ||
|
|
194
194
|
// A conditional dropped this source, but another dependency can still
|
|
195
195
|
// carry it. Only retire pending state inherited through the recovered
|
|
196
196
|
// branch. Deliberately NOT marked visited on this early return: the
|
|
197
197
|
// carrying dependency may itself be a later branch of this same walk
|
|
198
198
|
// (two unchanged memos converging), and its visit must be free to
|
|
199
199
|
// re-examine this node once that branch has retired the source.
|
|
200
|
-
|
|
200
|
+
t !== e && retryReaches(s, t) || !removePendingSource(s, t))
|
|
201
201
|
// A19: a verdict reader holds no pending of its own (it was re-derived
|
|
202
202
|
// when the source went pending, `propagateStatus`), and a landing
|
|
203
203
|
// equal to the committed value notifies nobody — the source settling
|
|
204
|
-
// is its verdict changing: it runs again.
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
204
|
+
// is its verdict changing: it runs again. (Verdict readers exist only
|
|
205
|
+
// with the verdict engine installed.)
|
|
206
|
+
return holdWorkHook && s.l & CONFIG_VERDICT && enqueueSub(s);
|
|
207
|
+
o.add(s);
|
|
208
|
+
s.ie = clock;
|
|
209
|
+
const f = s.T?.se?.values().next().value;
|
|
209
210
|
// STATUS_ERROR + pending sources only coexist via an errored loading
|
|
210
211
|
// window's park (notifyStatus(STATUS_ERROR) clears pending sources
|
|
211
212
|
// otherwise): the settled error stays the answer through the settle —
|
|
212
213
|
// nulling it here would have reads throw `null` until the re-enqueued
|
|
213
214
|
// retry lands, or lose it entirely if that retry parks again (#2989).
|
|
214
|
-
const u =
|
|
215
|
-
if (
|
|
216
|
-
if (!u) setPendingError(
|
|
215
|
+
const u = s.m & STATUS_ERROR;
|
|
216
|
+
if (f) {
|
|
217
|
+
if (!u) setPendingError(s, f);
|
|
217
218
|
} else {
|
|
218
|
-
|
|
219
|
-
if (!u) setPendingError(
|
|
219
|
+
s.m &= ~STATUS_PENDING;
|
|
220
|
+
if (!u) setPendingError(s);
|
|
220
221
|
// L2: a landing resumes the transaction waiting on it (maintainer: "it
|
|
221
222
|
// resumes the sync frame") — a held reader's re-pass over the landed
|
|
222
223
|
// value is that transaction's work, and the flush that carries it
|
|
223
224
|
// parks into it.
|
|
224
|
-
if (
|
|
225
|
-
if (
|
|
226
|
-
enqueueSub(
|
|
227
|
-
|
|
225
|
+
if (s.l & CONFIG_HELD) joinFuture(txOf(s));
|
|
226
|
+
if (s.T?.fe) {
|
|
227
|
+
enqueueSub(s);
|
|
228
|
+
n = true;
|
|
228
229
|
}
|
|
229
|
-
if (
|
|
230
|
+
if (s.T !== null) s.T.fe = false;
|
|
230
231
|
// Fully settled with nobody watching: release candidate (#2934). Checked
|
|
231
232
|
// again at release time — deferred so unobserved() can't unlink subs
|
|
232
233
|
// lists this walk is still iterating.
|
|
233
|
-
if (!
|
|
234
|
+
if (!s.o && s.l & CONFIG_AUTO_DISPOSE) (r ??= []).push(s);
|
|
234
235
|
}
|
|
235
|
-
forEachDependent(
|
|
236
|
+
forEachDependent(s, settle);
|
|
236
237
|
};
|
|
237
238
|
forEachDependent(e, settle);
|
|
238
239
|
// Release before the flush schedule below: unobserved() pulls the node back
|
|
239
240
|
// out of the heap, so the enqueueSub above never recomputes a released node.
|
|
240
241
|
if (r) for (const e of r) releaseIfSettledUnobserved(e);
|
|
241
|
-
if (
|
|
242
|
+
if (n) schedule();
|
|
242
243
|
}
|
|
243
244
|
|
|
244
245
|
// Object-thenable detection (Promises/A+ shape).
|
|
@@ -247,10 +248,10 @@ function isThenable(e) {
|
|
|
247
248
|
}
|
|
248
249
|
|
|
249
250
|
/** Fire and clear a node's iterator-flight cancellation hook (#3122). */ function releaseFlightTeardown(e) {
|
|
250
|
-
const
|
|
251
|
-
if (
|
|
252
|
-
e.T.
|
|
253
|
-
|
|
251
|
+
const t = e.T?.Se;
|
|
252
|
+
if (t != null) {
|
|
253
|
+
e.T.Se = null;
|
|
254
|
+
t();
|
|
254
255
|
}
|
|
255
256
|
}
|
|
256
257
|
|
|
@@ -263,17 +264,17 @@ function isThenable(e) {
|
|
|
263
264
|
* before its first pull, so a source opened in an async generator's body
|
|
264
265
|
* (`for await`) composes after the generator's close.
|
|
265
266
|
*/ function onSupersede(e) {
|
|
266
|
-
const
|
|
267
|
-
if (
|
|
268
|
-
const
|
|
269
|
-
const r = ext(
|
|
267
|
+
const t = context;
|
|
268
|
+
if (t === null || t.X === undefined || !(t.R & REACTIVE_RECOMPUTING_DEPS)) return;
|
|
269
|
+
const n = t.T === null;
|
|
270
|
+
const r = ext(t);
|
|
270
271
|
// Allocating the extension mid-run turns `_x?._inFlight` from undefined into
|
|
271
272
|
// null, which recompute would read as a flight this body registered itself.
|
|
272
273
|
// Restore undefined here, so the fix costs nothing for code that never
|
|
273
274
|
// calls onSupersede.
|
|
274
|
-
if (
|
|
275
|
-
const o = r.
|
|
276
|
-
r.
|
|
275
|
+
if (n) r.Ee = undefined;
|
|
276
|
+
const o = r.Se;
|
|
277
|
+
r.Se = o === null ? e : () => {
|
|
277
278
|
try {
|
|
278
279
|
o();
|
|
279
280
|
} finally {
|
|
@@ -282,90 +283,98 @@ function isThenable(e) {
|
|
|
282
283
|
};
|
|
283
284
|
}
|
|
284
285
|
|
|
285
|
-
function handleAsync(e,
|
|
286
|
+
function handleAsync(e, t, n,
|
|
286
287
|
// The flight rejected (after the node's status is set): a projection
|
|
287
288
|
// tells its leaves' readers, who are not the node's dependents
|
|
288
289
|
// (store/projection.ts). `pending`: a NotReady rejection — the node is
|
|
289
290
|
// pending on another source, not errored.
|
|
290
291
|
r) {
|
|
291
292
|
let o = false;
|
|
292
|
-
let
|
|
293
|
-
if (typeof
|
|
293
|
+
let s = false;
|
|
294
|
+
if (typeof t === "object" && t !== null) {
|
|
294
295
|
untrack(() => {
|
|
295
|
-
o =
|
|
296
|
-
|
|
296
|
+
o = t[Symbol.asyncIterator];
|
|
297
|
+
s = !o && isThenable(t);
|
|
297
298
|
});
|
|
298
299
|
}
|
|
299
|
-
if (!
|
|
300
|
-
if (e.T !== null)
|
|
300
|
+
if (!s && !o) {
|
|
301
|
+
if (e.T !== null) {
|
|
302
|
+
e.T.Ee = null;
|
|
303
|
+
if (holdWorkHook) e.l &= ~CONFIG_ASYNC;
|
|
304
|
+
}
|
|
301
305
|
// A sync landing is the first real answer for a loadingValue node.
|
|
302
306
|
e.ce = false;
|
|
303
|
-
return
|
|
307
|
+
return t;
|
|
304
308
|
}
|
|
305
309
|
// Flight replacement relies on recompute's supersede release for iterator
|
|
306
310
|
// teardown (#3122): every handleAsync call — including the projection
|
|
307
311
|
// self-registration — runs during a recompute of `el`, which has already
|
|
308
312
|
// fired _flightTeardown. A future non-recompute registration path must
|
|
309
313
|
// release it here before overwriting _inFlight.
|
|
310
|
-
ext(e).Ee =
|
|
314
|
+
ext(e).Ee = t;
|
|
315
|
+
// D-25 (verdict.ts `holdWork`): an async memo whose answering pass opened
|
|
316
|
+
// no verdict window of its own (`markVerdictReader` clears the bit).
|
|
317
|
+
// Kept by the verdict engine alone (`holdWorkHook`): a build without it
|
|
318
|
+
// folds the bit's upkeep away.
|
|
319
|
+
if (holdWorkHook && !(e.R & REACTIVE_WINDOW)) e.l |= CONFIG_ASYNC;
|
|
311
320
|
// The question this flight answers (A18 provenance, lanes.ts): the action
|
|
312
321
|
// whose slice asked it; mainline is always the current question.
|
|
313
|
-
e.T.
|
|
322
|
+
e.T.Ie = question || MAINLINE_QUESTION;
|
|
314
323
|
// The run that asked this flight read every input without throwing: an
|
|
315
324
|
// input still in flight was masked for it (an active override, A17), so
|
|
316
325
|
// pending state those inputs propagated onto the node earlier does not
|
|
317
326
|
// describe this answer. Drop it — the flight is the node's pending now.
|
|
318
327
|
// The landing retires only the flight's own entry (landStatus, #3373), so
|
|
319
328
|
// an entry that survived here would hold the node past its own answer.
|
|
320
|
-
e.T.
|
|
321
|
-
let
|
|
329
|
+
e.T.se = undefined;
|
|
330
|
+
let f;
|
|
322
331
|
const handleError = o => {
|
|
323
|
-
if (e.T?.Ee !==
|
|
332
|
+
if (e.T?.Ee !== t) return;
|
|
324
333
|
// NotReadyError from rejected promises should be treated as pending, not error
|
|
325
|
-
let
|
|
326
|
-
if (
|
|
334
|
+
let s = o instanceof NotReadyError;
|
|
335
|
+
if (s && e.ce) {
|
|
327
336
|
// Loading window: the flight died waiting on an unready source. Keep
|
|
328
337
|
// serving commit #0 — same parking as recompute's catch for sync
|
|
329
338
|
// dependency throws. The dead flight is released so the clock-gated
|
|
330
339
|
// error-retry pull (updateIfNecessary) can also re-ask.
|
|
331
340
|
if (e.T !== null) e.T.Ee = null;
|
|
332
341
|
parkLoadingWindow(e, o);
|
|
333
|
-
e.
|
|
342
|
+
e.ie = clock;
|
|
334
343
|
return;
|
|
335
344
|
}
|
|
336
345
|
// D-41: a held node's error is staged (`stageError`). A derived store's
|
|
337
346
|
// readers learn its error through the family, not the derive's
|
|
338
347
|
// dependents: it publishes now.
|
|
339
|
-
if (
|
|
340
|
-
notifyStatus(e,
|
|
348
|
+
if (s || n || !stageError(e, o)) {
|
|
349
|
+
notifyStatus(e, s ? STATUS_PENDING : STATUS_ERROR, o);
|
|
341
350
|
// The error is this pass's answer, published now: it replaces the shown
|
|
342
351
|
// frame as a value's commit would (`commitPendingNode`), so the frame
|
|
343
352
|
// the pass parked goes instead of waiting for a later success. A no-op
|
|
344
353
|
// when nothing is parked.
|
|
345
|
-
if (!
|
|
354
|
+
if (!s) disposeChildren(e, false, true);
|
|
346
355
|
}
|
|
347
356
|
// A NotReady rejection is a landing into another pending source. The
|
|
348
357
|
// rejected flight will never settle its self entry, so transfer ownership
|
|
349
358
|
// after notifyStatus has propagated the replacement source.
|
|
350
|
-
if (
|
|
351
|
-
e.
|
|
359
|
+
if (s) settlePendingSource(e);
|
|
360
|
+
e.ie = clock;
|
|
352
361
|
// A real error settles derivatively-pending dependents (notifyStatus
|
|
353
362
|
// cleared their pending sources), so stranded lazy ones release here —
|
|
354
363
|
// the error twin of settlePendingSource's release (#2934).
|
|
355
|
-
if (!
|
|
356
|
-
r?.(o,
|
|
364
|
+
if (!s) releaseSettledDependents(e);
|
|
365
|
+
r?.(o, s);
|
|
357
366
|
};
|
|
358
367
|
const asyncWrite = (r, o) => {
|
|
359
|
-
if (e.T?.Ee !==
|
|
368
|
+
if (e.T?.Ee !== t) return;
|
|
360
369
|
// If the node was dirtied by a newer write (optimistic override or regular),
|
|
361
370
|
// skip this stale async result — the upcoming flush will recompute the node
|
|
362
371
|
// with the new value, creating a fresh Promise that supersedes this one.
|
|
363
372
|
if (e.R & REACTIVE_DIRTY) return;
|
|
364
|
-
const
|
|
373
|
+
const s = e.m & STATUS_UNINITIALIZED;
|
|
365
374
|
landStatus(e);
|
|
366
|
-
if (
|
|
375
|
+
if (n) {
|
|
367
376
|
try {
|
|
368
|
-
|
|
377
|
+
n(r);
|
|
369
378
|
} catch (e) {
|
|
370
379
|
handleError(e);
|
|
371
380
|
return;
|
|
@@ -376,10 +385,10 @@ r) {
|
|
|
376
385
|
// a verdict reader of the next flight would suspend instead of being
|
|
377
386
|
// served the screen; held, both at the derive's commit.
|
|
378
387
|
if (!(e.l & CONFIG_HELD)) {
|
|
379
|
-
e.T.
|
|
388
|
+
e.T.Te = null;
|
|
380
389
|
e.l &= ~CONFIG_INPUTS_PUBLISHED;
|
|
381
390
|
}
|
|
382
|
-
if (
|
|
391
|
+
if (s) landStatus(e, true);
|
|
383
392
|
} else {
|
|
384
393
|
// CARVE 2: the override-covered landing (hold + A18 supersession) and the
|
|
385
394
|
// lane-routed landing (derived override, lane effect queue) went with
|
|
@@ -393,7 +402,7 @@ r) {
|
|
|
393
402
|
// (`_pendingValue` set inside setSignal) is not — commitPendingNode closes
|
|
394
403
|
// the window when the flush commits it, so no one-frame pulse can leak to
|
|
395
404
|
// observers between the landing and its commit (#2990).
|
|
396
|
-
if (e.
|
|
405
|
+
if (e.ue === NOT_PENDING) {
|
|
397
406
|
e.ce = false;
|
|
398
407
|
// The landing published: the dependency tail the flight's pass left
|
|
399
408
|
// linked goes now (A30, #3410). A staged landing has not replaced the
|
|
@@ -429,9 +438,9 @@ r) {
|
|
|
429
438
|
// write through asyncWrite, and close registration targets `owner` (el
|
|
430
439
|
// itself) directly. Returns whether a sync answer landed (first yield or
|
|
431
440
|
// empty completion) — meaningful only in the live posture.
|
|
432
|
-
const consumeIterator = (
|
|
433
|
-
const o =
|
|
434
|
-
let
|
|
441
|
+
const consumeIterator = (n, r) => {
|
|
442
|
+
const o = n[Symbol.asyncIterator]();
|
|
443
|
+
let s = false;
|
|
435
444
|
let u = false;
|
|
436
445
|
let i = !r;
|
|
437
446
|
const close = () => {
|
|
@@ -450,7 +459,7 @@ r) {
|
|
|
450
459
|
// `onSupersede` teardown this run registered earlier, which then falls
|
|
451
460
|
// back to the owner-cleanup channel. A returned `from()` is unaffected:
|
|
452
461
|
// `close` calls its `return()`, which runs its own teardown.
|
|
453
|
-
ext(e).
|
|
462
|
+
ext(e).Se = close;
|
|
454
463
|
// Release check before each next pull: an unobserved lazy node must tear
|
|
455
464
|
// down (its close above runs via disposal, closing the iterator) instead
|
|
456
465
|
// of pumping the stream forever with zero subscribers (#2935).
|
|
@@ -465,7 +474,7 @@ r) {
|
|
|
465
474
|
}
|
|
466
475
|
};
|
|
467
476
|
const iterate = () => {
|
|
468
|
-
let
|
|
477
|
+
let n, r, l = false, S = false, a = true;
|
|
469
478
|
// Protocol tolerance, matching `for await`: `await` unwraps whatever
|
|
470
479
|
// next() returns — a thenable OR a bare IteratorResult. Real producers
|
|
471
480
|
// use the bare form as a promise-free fast path when a value is already
|
|
@@ -484,17 +493,17 @@ r) {
|
|
|
484
493
|
// silently dropped. (The deferred posture never has a caller, so
|
|
485
494
|
// initialRead starts false there and everything writes through.)
|
|
486
495
|
if (a && i) {
|
|
487
|
-
|
|
496
|
+
n = r;
|
|
488
497
|
l = true;
|
|
489
498
|
if (r.done) u = true;
|
|
490
|
-
} else if (e.T?.Ee !==
|
|
499
|
+
} else if (e.T?.Ee !== t) {
|
|
491
500
|
return;
|
|
492
501
|
} else if (!r.done) {
|
|
493
|
-
|
|
502
|
+
s = true;
|
|
494
503
|
asyncWrite(r.value, iterateOrRelease);
|
|
495
504
|
} else {
|
|
496
505
|
u = true;
|
|
497
|
-
if (
|
|
506
|
+
if (s) {
|
|
498
507
|
schedule();
|
|
499
508
|
flush();
|
|
500
509
|
} else {
|
|
@@ -503,13 +512,13 @@ r) {
|
|
|
503
512
|
}
|
|
504
513
|
settleAutodispose();
|
|
505
514
|
}
|
|
506
|
-
},
|
|
515
|
+
}, n => {
|
|
507
516
|
if (a && i) {
|
|
508
|
-
r =
|
|
517
|
+
r = n;
|
|
509
518
|
S = true;
|
|
510
|
-
} else if (e.T?.Ee ===
|
|
519
|
+
} else if (e.T?.Ee === t) {
|
|
511
520
|
u = true;
|
|
512
|
-
handleError(
|
|
521
|
+
handleError(n);
|
|
513
522
|
settleAutodispose();
|
|
514
523
|
}
|
|
515
524
|
});
|
|
@@ -521,17 +530,17 @@ r) {
|
|
|
521
530
|
if (i) throw r;
|
|
522
531
|
return true;
|
|
523
532
|
}
|
|
524
|
-
if (l && !
|
|
525
|
-
|
|
526
|
-
|
|
533
|
+
if (l && !n.done) {
|
|
534
|
+
f = n.value;
|
|
535
|
+
s = true;
|
|
527
536
|
return iterate();
|
|
528
537
|
}
|
|
529
|
-
return l &&
|
|
538
|
+
return l && n.done;
|
|
530
539
|
};
|
|
531
540
|
const l = iterate();
|
|
532
541
|
// Later iterate() calls run from asyncWrite, where rethrowing would be unhandled.
|
|
533
542
|
i = false;
|
|
534
|
-
return
|
|
543
|
+
return s || l;
|
|
535
544
|
};
|
|
536
545
|
// Landed-synchronously verdict for a LIVE iterator drain; null when no live
|
|
537
546
|
// drain ran (plain promise flight, or a deferred flatten). Drives the
|
|
@@ -542,25 +551,25 @@ r) {
|
|
|
542
551
|
// stream itself rather than settling on the iterable object. One level
|
|
543
552
|
// only: A+ `then` already collapses nested thenables, so the resolved
|
|
544
553
|
// value is never itself a thenable.
|
|
545
|
-
const flattenIfIterable = (e,
|
|
546
|
-
let
|
|
554
|
+
const flattenIfIterable = (e, t) => {
|
|
555
|
+
let n = false;
|
|
547
556
|
if (typeof e === "object" && e !== null) {
|
|
548
557
|
untrack(() => {
|
|
549
|
-
|
|
558
|
+
n = e[Symbol.asyncIterator];
|
|
550
559
|
});
|
|
551
560
|
}
|
|
552
|
-
if (!
|
|
553
|
-
|
|
554
|
-
const r = consumeIterator(e,
|
|
555
|
-
if (!
|
|
561
|
+
if (!n) return false;
|
|
562
|
+
f = undefined;
|
|
563
|
+
const r = consumeIterator(e, t);
|
|
564
|
+
if (!t) u = r;
|
|
556
565
|
return true;
|
|
557
566
|
};
|
|
558
|
-
if (
|
|
559
|
-
let
|
|
560
|
-
|
|
561
|
-
if (
|
|
562
|
-
|
|
563
|
-
|
|
567
|
+
if (s) {
|
|
568
|
+
let n = false, r = false, o, s = true;
|
|
569
|
+
t.then(r => {
|
|
570
|
+
if (s) {
|
|
571
|
+
f = r;
|
|
572
|
+
n = true;
|
|
564
573
|
} else {
|
|
565
574
|
// Flattening consumes the stream as the value: each yield lands
|
|
566
575
|
// through asyncWrite under this flight's identity; the first one
|
|
@@ -572,7 +581,7 @@ r) {
|
|
|
572
581
|
// compute catch above it: a protocol throw settles as this
|
|
573
582
|
// flight's error (#4112).
|
|
574
583
|
try {
|
|
575
|
-
if (e.T?.Ee ===
|
|
584
|
+
if (e.T?.Ee === t && !(e.R & REACTIVE_DISPOSED) && flattenIfIterable(r, e)) return;
|
|
576
585
|
asyncWrite(r);
|
|
577
586
|
} catch (e) {
|
|
578
587
|
handleError(e);
|
|
@@ -580,7 +589,7 @@ r) {
|
|
|
580
589
|
settleAutodispose();
|
|
581
590
|
}
|
|
582
591
|
}, e => {
|
|
583
|
-
if (
|
|
592
|
+
if (s) {
|
|
584
593
|
o = e;
|
|
585
594
|
r = true;
|
|
586
595
|
} else {
|
|
@@ -588,21 +597,21 @@ r) {
|
|
|
588
597
|
settleAutodispose();
|
|
589
598
|
}
|
|
590
599
|
});
|
|
591
|
-
|
|
600
|
+
s = false;
|
|
592
601
|
if (r) {
|
|
593
602
|
// Settle through the same status path an async rejection uses, then
|
|
594
603
|
// unwind the in-progress synchronous read so the errored node isn't
|
|
595
604
|
// momentarily read as `undefined`.
|
|
596
605
|
handleError(o);
|
|
597
606
|
throw o;
|
|
598
|
-
} else if (!
|
|
607
|
+
} else if (!n) {
|
|
599
608
|
// Not landed: the shared tail below suspends, or — loading window —
|
|
600
609
|
// serves commit #0 (first-flight work on a loadingValue node is
|
|
601
610
|
// loading-class, invisible to boundaries; the flight itself is already
|
|
602
611
|
// registered in _inFlight and lands through asyncWrite). A promise is
|
|
603
612
|
// never an iterator, so nothing between here and there runs.
|
|
604
613
|
u = false;
|
|
605
|
-
} else if (!flattenIfIterable(
|
|
614
|
+
} else if (!flattenIfIterable(f)) {
|
|
606
615
|
// Synchronously-resolved promise: the first real answer landed.
|
|
607
616
|
e.ce = false;
|
|
608
617
|
}
|
|
@@ -610,7 +619,7 @@ r) {
|
|
|
610
619
|
// are still inside the synchronous read): full initial-drain semantics
|
|
611
620
|
// apply and the shared tail below settles the verdict.
|
|
612
621
|
}
|
|
613
|
-
if (o) flattenIfIterable(
|
|
622
|
+
if (o) flattenIfIterable(t);
|
|
614
623
|
if (u !== null) {
|
|
615
624
|
if (!u) {
|
|
616
625
|
// Loading window: serve commit #0 instead of suspending.
|
|
@@ -621,16 +630,16 @@ r) {
|
|
|
621
630
|
// answer; async yields clear inside asyncWrite.
|
|
622
631
|
e.ce = false;
|
|
623
632
|
}
|
|
624
|
-
return
|
|
633
|
+
return f;
|
|
625
634
|
}
|
|
626
635
|
|
|
627
|
-
function clearStatus(e,
|
|
628
|
-
if (e.T?.
|
|
629
|
-
if (e.T?.
|
|
630
|
-
e.m =
|
|
636
|
+
function clearStatus(e, t = false) {
|
|
637
|
+
if (e.T?.se) clearPendingSources(e);
|
|
638
|
+
if (e.T?.fe) e.T.fe = false;
|
|
639
|
+
e.m = t ? 0 : e.m & STATUS_UNINITIALIZED;
|
|
631
640
|
if (e.T?.U) setPendingError(e);
|
|
632
|
-
const
|
|
633
|
-
if (
|
|
641
|
+
const n = statusNotifierOf(e);
|
|
642
|
+
if (n) n.call(e);
|
|
634
643
|
}
|
|
635
644
|
|
|
636
645
|
/**
|
|
@@ -657,45 +666,50 @@ function clearStatus(e, n = false) {
|
|
|
657
666
|
* the first landing retires UNINITIALIZED. `_error` must move off self: a
|
|
658
667
|
* reader thrown NotReady(self) would park on a retired entry. Companions
|
|
659
668
|
* keep their verdict (pending before and after; the write re-syncs them).
|
|
660
|
-
*/ function landStatus(e,
|
|
661
|
-
const
|
|
669
|
+
*/ function landStatus(e, t = false) {
|
|
670
|
+
const n = e.T?.se;
|
|
662
671
|
// (The full clear below drops the set whether or not self was retired first.)
|
|
663
|
-
if (
|
|
664
|
-
e.T.
|
|
665
|
-
if (
|
|
666
|
-
setPendingError(e,
|
|
667
|
-
} else clearStatus(e,
|
|
672
|
+
if (n && (n.delete(e), n.size)) {
|
|
673
|
+
e.T.fe = false;
|
|
674
|
+
if (t) e.m = STATUS_PENDING;
|
|
675
|
+
setPendingError(e, n.values().next().value);
|
|
676
|
+
} else clearStatus(e, t);
|
|
668
677
|
}
|
|
669
678
|
|
|
670
|
-
function notifyStatus(e,
|
|
679
|
+
function notifyStatus(e, t, n) {
|
|
671
680
|
// Wrap regular errors to track source node
|
|
672
|
-
if (
|
|
673
|
-
const r =
|
|
681
|
+
if (t === STATUS_ERROR && !(n instanceof StatusError) && !(n instanceof NotReadyError)) n = new StatusError(e, n);
|
|
682
|
+
const r = t === STATUS_PENDING && n instanceof NotReadyError && n.source;
|
|
674
683
|
// (CARVE 2: the lane assignment went with the engine.)
|
|
675
|
-
if (
|
|
684
|
+
if (t === STATUS_PENDING && r) {
|
|
676
685
|
// D-41: a re-ask of a shown error keeps it the display (`_shownError`).
|
|
677
|
-
if (e.m & STATUS_ERROR) e.T.
|
|
686
|
+
if (e.m & STATUS_ERROR) e.T.Te = e.T.U;
|
|
678
687
|
addPendingSource(e, r);
|
|
679
688
|
// A re-ask of an error that answered the first read: still no value.
|
|
680
689
|
e.m = STATUS_PENDING | (e.m & STATUS_NO_VALUE ? STATUS_UNINITIALIZED : e.m & STATUS_UNINITIALIZED);
|
|
681
690
|
// Preserve the current source on this propagation so readers park on
|
|
682
691
|
// the distinct pending source.
|
|
683
|
-
setPendingError(e, r,
|
|
692
|
+
setPendingError(e, r, n);
|
|
684
693
|
} else {
|
|
685
694
|
clearPendingSources(e);
|
|
686
695
|
// An error answering a node with no value marks it so; a re-ask of it
|
|
687
696
|
// (pending) is uninitialized again; a write (STATUS_NONE) gives it one.
|
|
688
|
-
e.m =
|
|
689
|
-
ext(e).U =
|
|
697
|
+
e.m = t | (t === STATUS_ERROR ? e.m & (STATUS_UNINITIALIZED | STATUS_NO_VALUE) ? STATUS_NO_VALUE : 0 : t === STATUS_PENDING && e.m & STATUS_NO_VALUE ? STATUS_UNINITIALIZED : e.m & STATUS_UNINITIALIZED);
|
|
698
|
+
ext(e).U = n;
|
|
690
699
|
}
|
|
691
700
|
// Lanes: a written guess is an optimistic boundary (A17 — "the optimistic
|
|
692
701
|
// future value until we know otherwise"). Its own source in flight is its
|
|
693
702
|
// status, not its readers': they read the guess. The flight is the parent
|
|
694
703
|
// transition's to wait on — the frame it was asked in holds (A17: "a
|
|
695
704
|
// transition whose optimistic node is still pending on its own fetch is
|
|
696
|
-
// not complete"), through the node itself (`blocked`).
|
|
697
|
-
|
|
698
|
-
|
|
705
|
+
// not complete"), through the node itself (`blocked`). An input changed
|
|
706
|
+
// from outside the guess's hold asks a new question: the frame that
|
|
707
|
+
// changed it is held with that hold (D-34, #4336) — it shows beside the
|
|
708
|
+
// guess's truth, which reveals at that hold's commit (F-1). A `refresh()`
|
|
709
|
+
// re-asks the same question: its frame is its own.
|
|
710
|
+
// (No guess written, no arm.)
|
|
711
|
+
if (guessing && t === STATUS_PENDING && e.l & CONFIG_GUESS) {
|
|
712
|
+
if (passLane === null) joinFuture(e.R & REACTIVE_REASK ? null : txOf(e)._parent);
|
|
699
713
|
return;
|
|
700
714
|
}
|
|
701
715
|
const o = statusNotifierOf(e);
|
|
@@ -703,17 +717,17 @@ function notifyStatus(e, n, t) {
|
|
|
703
717
|
o.call(e);
|
|
704
718
|
return;
|
|
705
719
|
}
|
|
706
|
-
propagateStatus(e,
|
|
720
|
+
propagateStatus(e, t, n);
|
|
707
721
|
}
|
|
708
722
|
|
|
709
723
|
/** The dependents' half of `notifyStatus`: `el`'s status reaches each
|
|
710
724
|
* subscriber as a propagated mark (or a re-derive). On its own for a store
|
|
711
725
|
* family's leaves, which are not the derive's dependents — the family
|
|
712
726
|
* propagates the derive's status from each leaf to the leaf's readers
|
|
713
|
-
* (store/projection.ts `wakeFamily`), exactly as a memo's would reach its. */ function propagateStatus(e,
|
|
714
|
-
const r =
|
|
715
|
-
forEachDependent(e, (o,
|
|
716
|
-
o.
|
|
727
|
+
* (store/projection.ts `wakeFamily`), exactly as a memo's would reach its. */ function propagateStatus(e, t, n) {
|
|
728
|
+
const r = t === STATUS_PENDING && n instanceof NotReadyError && n.source;
|
|
729
|
+
forEachDependent(e, (o, s) => {
|
|
730
|
+
o.ie = clock;
|
|
717
731
|
// A pending mark on a kept-tail link re-derives the subscriber instead of
|
|
718
732
|
// marking it (A30, #3494 review; fuzzer latest-1 #2141; #3519 review).
|
|
719
733
|
// Past `_depsTail` lie the committed frame's deps, kept by A30 because
|
|
@@ -733,7 +747,13 @@ function notifyStatus(e, n, t) {
|
|
|
733
747
|
// Inheriting the error would make a probe's reader errored. A boundary's
|
|
734
748
|
// output (CONFIG_REDERIVE, boundaries.ts) the same: content or fallback
|
|
735
749
|
// is its pass's call.
|
|
736
|
-
|
|
750
|
+
// Not one D-25 makes the hold's work (verdict.ts `holdWork`): an async
|
|
751
|
+
// memo with no verdict window of its own reads a verdict memo's value,
|
|
752
|
+
// and that source going pending changes none of its reads — re-derived,
|
|
753
|
+
// it is served the committed value it already derived from (A10) and
|
|
754
|
+
// asks that question again. It waits on the source like any derivation
|
|
755
|
+
// (F-9), and asks its next question once, at the landing (#4397).
|
|
756
|
+
if (o.l & CONFIG_REDERIVE || holdWorkHook && o.l & CONFIG_VERDICT && !(r && holdWorkHook(o, e)) || t === STATUS_PENDING && s.Ne !== o.de) {
|
|
737
757
|
enqueueSub(o);
|
|
738
758
|
schedule();
|
|
739
759
|
return;
|
|
@@ -745,11 +765,11 @@ function notifyStatus(e, n, t) {
|
|
|
745
765
|
// frame still passes through — its pass is the frame's (#3372, compiled
|
|
746
766
|
// shape: the unmount it stages makes the observer a zombie whose say is
|
|
747
767
|
// moot for this transaction, A15 #3463).
|
|
748
|
-
if (
|
|
749
|
-
if (passLane === null && (o.l & (CONFIG_HELD | CONFIG_OVERRIDE)) === CONFIG_HELD && globalQueue.
|
|
768
|
+
if (t === STATUS_PENDING && r && o.T?.se?.has(r)) {
|
|
769
|
+
if (passLane === null && (o.l & (CONFIG_HELD | CONFIG_OVERRIDE)) === CONFIG_HELD && globalQueue.Y && !freshHook?.(o, r.ie === clock)) joinFuture(txOf(o));
|
|
750
770
|
return;
|
|
751
771
|
}
|
|
752
|
-
if (
|
|
772
|
+
if (t === STATUS_PENDING && r || t !== STATUS_PENDING && (o.T?.U !== n || o.T?.se)) {
|
|
753
773
|
// The marked subscriber is queued for the commit sweep so its status
|
|
754
774
|
// bookkeeping (loading window, uninitialized clear) runs with the flush
|
|
755
775
|
// — with the lane, when the pass propagating is the lane's work and
|
|
@@ -762,14 +782,14 @@ function notifyStatus(e, n, t) {
|
|
|
762
782
|
// transaction — the flight flows into a memo that transaction
|
|
763
783
|
// holds, so the write that started it is held with it. A render
|
|
764
784
|
// effect's membership is its pass's (`notify`), never sticky.
|
|
765
|
-
if (
|
|
785
|
+
if (t === STATUS_PENDING && (o.l & (CONFIG_HELD | CONFIG_OVERRIDE)) === CONFIG_HELD && !o.i) joinFuture(txOf(o));
|
|
766
786
|
}
|
|
767
|
-
notifyStatus(o,
|
|
787
|
+
notifyStatus(o, t, n);
|
|
768
788
|
// A derived store's derive (store/projection.ts): marked, not re-run —
|
|
769
789
|
// its leaves' readers are not its dependents, so the family walks them.
|
|
770
|
-
o.fam?.st(
|
|
790
|
+
o.fam?.st(t);
|
|
771
791
|
}
|
|
772
792
|
});
|
|
773
793
|
}
|
|
774
794
|
|
|
775
|
-
export { addPendingSource, clearStatus, forEachDependent, handleAsync, isThenable, notifyStatus, onSupersede, parkLoadingWindow, propagateStatus, releaseFlightTeardown, releaseIfSettledUnobserved, releaseSettledDependents, setPendingError, settleErroredDependents, settlePendingSource, stageError };
|
|
795
|
+
export { addPendingSource, clearStatus, forEachDependent, handleAsync, isThenable, notifyStatus, onSupersede, parkLoadingWindow, propagateStatus, releaseFlightTeardown, releaseIfSettledUnobserved, releaseSettledDependents, removePendingSource, setPendingError, settleErroredDependents, settlePendingSource, stageError };
|