@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/core.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { notifyStatus, releaseFlightTeardown, handleAsync, clearStatus, parkLoadingWindow, stageError, settlePendingSource, releaseIfSettledUnobserved, settleErroredDependents } from "./async.js";
|
|
2
2
|
|
|
3
|
-
import { STATUS_UNINITIALIZED, REACTIVE_LAZY, REACTIVE_NONE, defaultContext, CONFIG_TRANSPARENT, CONFIG_OWNED_WRITE, CONFIG_AUTO_DISPOSE, CONFIG_SYNC, CONFIG_NO_SNAPSHOT, CONFIG_IN_SNAPSHOT_SCOPE, NOT_PENDING, CONFIG_HELD, REACTIVE_MANUAL_WRITE, STATUS_ERROR, REACTIVE_DIRTY, CONFIG_OVERRIDE, NO_SNAPSHOT, CONFIG_HAS_SNAPSHOT, REACTIVE_DISPOSED, REACTIVE_CHECK, REACTIVE_IN_HEAP, REACTIVE_REASK, REACTIVE_SNAPSHOT_STALE, CONFIG_CHILDREN_FORBIDDEN, CONFIG_VERDICT, STATUS_PENDING, REACTIVE_LANE_DIRTY, CONFIG_GUESS, REACTIVE_RECOMPUTING_DEPS, CONFIG_LAGS, EFFECT_RENDER, CONFIG_HELD_FRAME, EFFECT_TRACKED, CONFIG_STAGED,
|
|
3
|
+
import { STATUS_UNINITIALIZED, REACTIVE_LAZY, REACTIVE_NONE, defaultContext, CONFIG_TRANSPARENT, CONFIG_OWNED_WRITE, CONFIG_AUTO_DISPOSE, CONFIG_SYNC, CONFIG_NO_SNAPSHOT, CONFIG_IN_SNAPSHOT_SCOPE, NOT_PENDING, CONFIG_HELD, REACTIVE_MANUAL_WRITE, STATUS_ERROR, REACTIVE_DIRTY, CONFIG_OVERRIDE, NO_SNAPSHOT, CONFIG_HAS_SNAPSHOT, REACTIVE_DISPOSED, REACTIVE_CHECK, REACTIVE_IN_HEAP, REACTIVE_REASK, REACTIVE_SNAPSHOT_STALE, CONFIG_CHILDREN_FORBIDDEN, CONFIG_VERDICT, STATUS_PENDING, CONFIG_STAGED_ERROR, REACTIVE_LANE_DIRTY, CONFIG_GUESS, REACTIVE_RECOMPUTING_DEPS, CONFIG_ASYNC, CONFIG_LAGS, EFFECT_RENDER, CONFIG_HELD_FRAME, EFFECT_TRACKED, CONFIG_STAGED, REACTIVE_ZOMBIE, REACTIVE_MISSED_WAKE, REACTIVE_JOINED, REACTIVE_STAGED_READ, REACTIVE_PROBED, REACTIVE_FRAME_READ, REACTIVE_LANE_READ, REACTIVE_SCREEN_READ, REACTIVE_PROBE_UNANSWERED, CAUGHT_REARMED, CONFIG_PROMOTED, CONFIG_INPUTS_PUBLISHED, CONFIG_FRESH_READ, REACTIVE_IN_HEAP_HEIGHT, CONFIG_SLOT_NODE, EFFECT_USER, NewSet, STATUS_NONE } from "./constants.js";
|
|
4
4
|
|
|
5
5
|
import { NotReadyError } from "./error.js";
|
|
6
6
|
|
|
@@ -10,7 +10,7 @@ import { insertIntoHeap, deleteFromHeap, insertIntoHeapHeight, enqueueSub, markN
|
|
|
10
10
|
|
|
11
11
|
import { inheritId, linkChild, disposeChildren, markDisposal } from "./owner.js";
|
|
12
12
|
|
|
13
|
-
import { schedule, externalUntrackHook, clock, txOf, flushTransaction, laneWriteHook, joinFuture, queuePendingNode, globalQueue, notifyEpoch, insertSubs, dirtyQueue, observeFlightHook, laneStageHook, passLane, laneReadHook, wireExternalSourceHook, bumpNotifyEpoch, setPassLane, joinPassTx, freshHook, GlobalQueue, laneOutcomeHook, passTx, holdNode, laneDirty, heldTrim, staleReader,
|
|
13
|
+
import { schedule, externalUntrackHook, clock, txOf, flushTransaction, laneWriteHook, joinFuture, queuePendingNode, globalQueue, notifyEpoch, insertSubs, dirtyQueue, observeFlightHook, laneStageHook, passLane, laneReadHook, wireExternalSourceHook, bumpNotifyEpoch, setPassLane, joinPassTx, freshHook, guessing, holdWorkHook, GlobalQueue, laneOutcomeHook, passTx, holdNode, laneDirty, heldTrim, staleReader, laneServedHook, latestOpened, stagedReaders, laneSeamsHook, deferZombie } from "./scheduler.js";
|
|
14
14
|
|
|
15
15
|
// The heap's per-node step. A tracked effect's heap visit is its compute
|
|
16
16
|
// phase — empty, like a user effect whose compute reads nothing — and hands
|
|
@@ -161,20 +161,41 @@ function recompute(e, t = false) {
|
|
|
161
161
|
// Restored at the end, after this pass's staging and runs have been
|
|
162
162
|
// routed.
|
|
163
163
|
// Lanes exist only with the lane engine installed (`laneStageHook`): a
|
|
164
|
-
// bundle without it seats every pass on mainline
|
|
164
|
+
// bundle without it seats every pass on mainline (`passLane` is never set)
|
|
165
|
+
// and folds the seat, and its restores, away.
|
|
165
166
|
const E = passLane;
|
|
166
167
|
// The mount a first pass belongs to: its creator's lane, or the one its
|
|
167
168
|
// creator's own mount came from — a render effect a verdict lane's mount's
|
|
168
169
|
// content creates is that mount's too (#4166). Lanes only, like the seat.
|
|
169
170
|
const s = laneRoot;
|
|
170
171
|
const i = laneStageHook && (laneRoot = t && (E || s));
|
|
171
|
-
|
|
172
|
+
if (laneStageHook) setPassLane((e.R & REACTIVE_LANE_DIRTY || (e.l & (CONFIG_OVERRIDE | CONFIG_GUESS)) === CONFIG_OVERRIDE) && e.T?.Re?.P ? e.T.Re : // Loose `!=`: false with no creator lane (undefined == null).
|
|
172
173
|
t && E?._parent.Pe != E && creatorPass(context)?.R & REACTIVE_RECOMPUTING_DEPS ? E : null);
|
|
173
174
|
// CARVE 2: lane posture resolution (OPTIMISTIC_DIRTY, derived-override
|
|
174
175
|
// re-derivation, lane adoption through deps) went with the optimistic engine.
|
|
175
|
-
|
|
176
|
+
// An error a pass staged, which this pass replaces (`valueChanged`).
|
|
177
|
+
const l = e.l & CONFIG_STAGED_ERROR;
|
|
178
|
+
if (!t) {
|
|
176
179
|
deleteFromHeap(e, dirtyQueue);
|
|
180
|
+
// A pending flight is the transition's own work (#3884), and so is a
|
|
181
|
+
// held async memo's re-run with no verdict window of its own (D-25,
|
|
182
|
+
// `holdWork`): a pass that takes no verdict role this time. A probe on
|
|
183
|
+
// an earlier pass left CONFIG_VERDICT, and a frame read here would serve
|
|
184
|
+
// the committed screen, settle the flight and drop the hold — a
|
|
185
|
+
// superseding write's verdict would depend on that probe. Cleared for
|
|
186
|
+
// this pass, before the flight it judges by is superseded; a probe in
|
|
187
|
+
// the body re-stamps it after the plain reads. Not an effect: it has no
|
|
188
|
+
// flight of its own (its pending is a source's), and a verdict memo's
|
|
189
|
+
// change may have just made it a verdict reader (`laneDirty`). Only a
|
|
190
|
+
// build with the lane engine (`laneStageHook`; verdict.ts imports it)
|
|
191
|
+
// ever sets CONFIG_VERDICT: without it the line folds away.
|
|
192
|
+
if (laneStageHook && !n && (e.m & STATUS_PENDING || (e.l & (CONFIG_ASYNC | CONFIG_HELD)) === (CONFIG_ASYNC | CONFIG_HELD))) e.l &= ~CONFIG_VERDICT;
|
|
177
193
|
if (e.T !== null) {
|
|
194
|
+
// The seam's re-derive runs with the parked flight still current; any
|
|
195
|
+
// later pass asks its own question (`_parked`; only the lane engine
|
|
196
|
+
// parks one).
|
|
197
|
+
const t = laneStageHook && e.T.He;
|
|
198
|
+
if (t && t !== e.T.Ee) e.T.He = undefined;
|
|
178
199
|
e.T.Ee = null;
|
|
179
200
|
// Supersede is where an iterator flight dies (#3122): close it now.
|
|
180
201
|
// Idempotent with the cleanup-channel close.
|
|
@@ -193,13 +214,7 @@ function recompute(e, t = false) {
|
|
|
193
214
|
// A).
|
|
194
215
|
// A boundary's structure (CONFIG_FRAME) is the frame like a render
|
|
195
216
|
// effect: it publishes mainline outside its transaction's flush (#4283).
|
|
196
|
-
|
|
197
|
-
// earlier pass left CONFIG_VERDICT, and a frame read here would serve the
|
|
198
|
-
// committed screen, settle the flight and drop the hold — a superseding
|
|
199
|
-
// write's verdict would depend on that probe. Cleared for this pass; a
|
|
200
|
-
// probe in the body re-stamps it after the plain reads.
|
|
201
|
-
if (e.m & STATUS_PENDING) e.l &= ~CONFIG_VERDICT;
|
|
202
|
-
if (e.l & CONFIG_HELD) {
|
|
217
|
+
if (e.l & CONFIG_HELD) {
|
|
203
218
|
const t = txOf(e);
|
|
204
219
|
// Held by a blocked lane: the frame joins nothing — a lane never holds
|
|
205
220
|
// a sync write (#3460). The pass is the lane's if it reads the lane's
|
|
@@ -216,8 +231,12 @@ function recompute(e, t = false) {
|
|
|
216
231
|
// children die below (`disposeChildren`). The landing re-derives a
|
|
217
232
|
// fresh held frame for the reveal (`_reruns`).
|
|
218
233
|
// Not held any more, whichever frame reader it is: its readers read
|
|
219
|
-
// the value this pass publishes
|
|
220
|
-
|
|
234
|
+
// the value this pass publishes — those that read the staging it
|
|
235
|
+
// supersedes re-derive, even when it publishes the committed value
|
|
236
|
+
// back (no change to notify them by): their held runs carry the
|
|
237
|
+
// superseded frame, and the landing would apply them (#4378).
|
|
238
|
+
if (e.ue !== NOT_PENDING) insertSubs(e);
|
|
239
|
+
e.ue = NOT_PENDING;
|
|
221
240
|
e.l &= ~CONFIG_HELD;
|
|
222
241
|
}
|
|
223
242
|
}
|
|
@@ -235,57 +254,59 @@ function recompute(e, t = false) {
|
|
|
235
254
|
deferReleases(o = []);
|
|
236
255
|
disposeChildren(e);
|
|
237
256
|
deferReleases(t);
|
|
238
|
-
} else if (e.pe !== null || e.
|
|
257
|
+
} else if (e.pe !== null || e.ke !== null) parkChildren(e);
|
|
239
258
|
// An error a pass staged (D-41) is replaced by this pass's answer: a
|
|
240
259
|
// value, a flight, or an error of its own (#4109, #4145).
|
|
241
260
|
if (e.l & CONFIG_STAGED_ERROR) {
|
|
242
|
-
e.
|
|
261
|
+
e.ue = NOT_PENDING;
|
|
243
262
|
e.l ^= CONFIG_STAGED_ERROR;
|
|
244
263
|
}
|
|
245
264
|
}
|
|
246
|
-
const
|
|
265
|
+
const r = !!(e.m & STATUS_UNINITIALIZED);
|
|
247
266
|
// Capture both error and pending status before the compute clears them.
|
|
248
267
|
// A conditional can drop its pending source and recover to an unchanged
|
|
249
268
|
// value, leaving blocked dependents outside that source’s settle walk.
|
|
250
|
-
const
|
|
251
|
-
const
|
|
252
|
-
const
|
|
269
|
+
const a = e.m & STATUS_ERROR && e.T?.U;
|
|
270
|
+
const _ = (e.m & STATUS_PENDING) !== 0;
|
|
271
|
+
const u = _ && e.T?.se;
|
|
253
272
|
// Pending SOURCE-hood, captured before the compute clears status: a node
|
|
254
273
|
// whose own flight parked dependents self-registers in _pendingSources
|
|
255
274
|
// (notifyStatus, isSource). If this recompute supersedes that flight and
|
|
256
275
|
// settles synchronously, those dependents settle HERE — asyncWrite's
|
|
257
276
|
// settlePendingSource walk never runs for a landing that was preempted
|
|
258
277
|
// (#3181).
|
|
259
|
-
const
|
|
278
|
+
const I = e.T?.se?.has(e);
|
|
260
279
|
// D-41: this pass's error is staged, not published (`stageError`).
|
|
261
|
-
let
|
|
280
|
+
let N = false;
|
|
262
281
|
// A19 exc. 2: a `refresh()` re-asks the question already answered — quiet
|
|
263
282
|
// for the verdict — unless the question in flight is a new one, which the
|
|
264
283
|
// re-ask does not launder (a poll during a quiet confirm stays quiet).
|
|
265
|
-
|
|
266
|
-
|
|
284
|
+
// Nor a guess's new question whose answer is still held (#4336: an
|
|
285
|
+
// action's refresh after an outside input change has not committed it).
|
|
286
|
+
const f = (e.R & REACTIVE_REASK) !== 0 && !((e.m & STATUS_PENDING || guessing && e.ue !== NOT_PENDING) && e.T !== null && !e.T.Ve);
|
|
287
|
+
const T = context;
|
|
267
288
|
context = e;
|
|
268
289
|
e._ = null;
|
|
269
|
-
e.
|
|
290
|
+
e.de++;
|
|
270
291
|
// REACTIVE_ZOMBIE is position: it says the node sits on its owner's parked
|
|
271
292
|
// frame, and the splice/reawaken paths key off it. A zombie reruns for
|
|
272
293
|
// live writes until the commit that disposes it, so every per-pass wipe
|
|
273
294
|
// — here, the finally below, updateIfNecessary — carries it (#3543).
|
|
274
295
|
e.R = REACTIVE_RECOMPUTING_DEPS | e.R & (REACTIVE_ZOMBIE | REACTIVE_REASK);
|
|
275
|
-
e.
|
|
296
|
+
e.ie = clock;
|
|
276
297
|
// The pass's previous value: its staging, else a lane node's lane value
|
|
277
298
|
// when it has one (lanes.ts), else the committed one.
|
|
278
|
-
let
|
|
279
|
-
let
|
|
280
|
-
let
|
|
299
|
+
let S = e.ue !== NOT_PENDING ? e.ue : e.l & CONFIG_OVERRIDE && e.T.P !== NOT_PENDING ? e.T.P : e.le;
|
|
300
|
+
let c = e.he;
|
|
301
|
+
let A = false;
|
|
281
302
|
// L2: did this pass read the future (REACTIVE_JOINED, set by read) — or,
|
|
282
303
|
// a lane's mount, a staging of this flush (#3851, #4166)?
|
|
283
|
-
let
|
|
284
|
-
let
|
|
304
|
+
let R = false;
|
|
305
|
+
let C = tracking;
|
|
285
306
|
tracking = true;
|
|
286
307
|
try {
|
|
287
308
|
if (!false && e.l & CONFIG_SYNC) {
|
|
288
|
-
|
|
309
|
+
S = e.X(S);
|
|
289
310
|
if (e.T !== null) e.T.Ee = null;
|
|
290
311
|
e.ce = false;
|
|
291
312
|
} else {
|
|
@@ -293,12 +314,15 @@ function recompute(e, t = false) {
|
|
|
293
314
|
// (with the commit as setter): its undefined return is not a sync
|
|
294
315
|
// answer, and the outer handleAsync must not clobber the registration.
|
|
295
316
|
const t = e.T?.Ee;
|
|
296
|
-
const n = e.X(
|
|
317
|
+
const n = e.X(S);
|
|
297
318
|
const o = typeof n === "object" && n !== null;
|
|
298
319
|
const E = e.T?.Ee !== t;
|
|
299
|
-
|
|
320
|
+
S = E || !o ? n : handleAsync(e, n);
|
|
300
321
|
if (!E && !o) {
|
|
301
|
-
if (e.T !== null)
|
|
322
|
+
if (e.T !== null) {
|
|
323
|
+
e.T.Ee = null;
|
|
324
|
+
if (holdWorkHook) e.l &= ~CONFIG_ASYNC;
|
|
325
|
+
}
|
|
302
326
|
// A sync (non-object) return is the first real answer; async-shaped
|
|
303
327
|
// results clear inside handleAsync at their own landing points, and a
|
|
304
328
|
// self-registered flight clears when its own handleAsync lands.
|
|
@@ -312,6 +336,10 @@ function recompute(e, t = false) {
|
|
|
312
336
|
if (e.m !== 0 || e.T !== null) clearStatus(e, t);
|
|
313
337
|
} catch (t) {
|
|
314
338
|
const n = t instanceof NotReadyError;
|
|
339
|
+
// An error answers, and so does a loading window's unready read (D-25,
|
|
340
|
+
// verdict.ts `holdWork`): no flight is its own. A pass left pending
|
|
341
|
+
// keeps the last answer's. (Kept by the verdict engine alone.)
|
|
342
|
+
if (holdWorkHook && (!n || e.ce)) e.l &= ~CONFIG_ASYNC;
|
|
315
343
|
if (n && e.ce) {
|
|
316
344
|
// Loading window with an unready sync dependency: register for the
|
|
317
345
|
// source's settle (the settlePendingSource walk runs off
|
|
@@ -324,12 +352,12 @@ function recompute(e, t = false) {
|
|
|
324
352
|
} else {
|
|
325
353
|
// D-41: a pass of a held node, or one that read a staging of this
|
|
326
354
|
// flush, stages its error (`stageError`).
|
|
327
|
-
if (n || !(
|
|
328
|
-
if (n) ext(e).
|
|
355
|
+
if (n || !(N = stageError(e, t, true))) {
|
|
356
|
+
if (n) ext(e).fe = true;
|
|
329
357
|
notifyStatus(e, n ? STATUS_PENDING : STATUS_ERROR, t);
|
|
330
358
|
// The replacement source is fully propagated now. If no new flight
|
|
331
359
|
// re-owned self, retire the superseded flight and its dependent copies.
|
|
332
|
-
if (n &&
|
|
360
|
+
if (n && I && !e.T?.Ee) settlePendingSource(e);
|
|
333
361
|
}
|
|
334
362
|
// A re-park drops what the earlier pass carried (#3456): a source this
|
|
335
363
|
// pass no longer reaches — its branch switched, or a fresh flight
|
|
@@ -340,25 +368,29 @@ function recompute(e, t = false) {
|
|
|
340
368
|
// re-park twin of the unchanged-value recovery sweep below; dependents
|
|
341
369
|
// with another path keep the source (retryReaches). A staged error
|
|
342
370
|
// answered what the pass carried: the same.
|
|
343
|
-
if ((n ||
|
|
371
|
+
if ((n || N) && u) for (const t of u) if (t !== e && !e.T?.se?.has(t)) settlePendingSource(e, t);
|
|
344
372
|
}
|
|
345
373
|
} finally {
|
|
346
|
-
tracking =
|
|
374
|
+
tracking = C;
|
|
347
375
|
if (laneStageHook) laneRoot = s;
|
|
348
376
|
// Consume the missed-wake latch (#3037, set by insertSubs): a dep write
|
|
349
377
|
// landed beneath this pass on a link it had already validated. The wipe
|
|
350
378
|
// below must not key off DIRTY/CHECK — the read-time pull protocol
|
|
351
379
|
// (markNode(c) in read()) marks the running node as part of ordinary
|
|
352
380
|
// bookkeeping, and those marks are correctly discarded here.
|
|
353
|
-
|
|
381
|
+
A = (e.R & REACTIVE_MISSED_WAKE) !== 0;
|
|
354
382
|
// A mount's staged read joins it — except a nested derivation left
|
|
355
383
|
// pending: no render effect reaches it yet, so it holds nothing and
|
|
356
|
-
// reaches no boundary (Reader, #4203)
|
|
357
|
-
|
|
384
|
+
// reaches no boundary (Reader, #4203), whatever it read — a memo the
|
|
385
|
+
// mount bore held over the staging included, at any depth (#4340). A
|
|
386
|
+
// reader that does is caught.
|
|
387
|
+
R = !!(e.R & (i ? E || n || !(e.m & STATUS_PENDING) ? REACTIVE_JOINED | REACTIVE_STAGED_READ : 0 : REACTIVE_JOINED));
|
|
358
388
|
// A verdict reader is one for as long as it probes, or reads a memo
|
|
359
389
|
// that does (`read`): a pass that did neither (REACTIVE_PROBED, the same
|
|
360
|
-
// bit) is an ordinary derivation again.
|
|
361
|
-
|
|
390
|
+
// bit) is an ordinary derivation again. Its async posture is the
|
|
391
|
+
// verdict engine's to keep (CONFIG_ASYNC, verdict.ts `holdWork`, D-25).
|
|
392
|
+
// (Only the verdict engine probes: without it the line folds away.)
|
|
393
|
+
if (observeFlightHook) e.l = e.l & ~CONFIG_VERDICT | e.R & REACTIVE_PROBED;
|
|
362
394
|
// REACTIVE_DISPOSED survives too (#3621): the pass may have disposed its
|
|
363
395
|
// own owner (a memo calling its root's `dispose()`, a cleanup doing so
|
|
364
396
|
// #3601/#3606), and `disposeChildren` set the flag on this node
|
|
@@ -367,12 +399,12 @@ function recompute(e, t = false) {
|
|
|
367
399
|
// this pass's verdict for the landing; the next pass's wipe at the top
|
|
368
400
|
// clears it.
|
|
369
401
|
e.R = e.R & (REACTIVE_ZOMBIE | REACTIVE_DISPOSED | REACTIVE_FRAME_READ | REACTIVE_STAGED_READ | REACTIVE_LANE_READ | REACTIVE_SCREEN_READ | REACTIVE_PROBE_UNANSWERED) | (t ? e.R & REACTIVE_SNAPSHOT_STALE : 0);
|
|
370
|
-
context =
|
|
402
|
+
context = T;
|
|
371
403
|
if (o) for (const e of o) releaseIfSettledUnobserved(e);
|
|
372
404
|
// A19 exc. 2: a pass that went pending on a `refresh()` re-asks the
|
|
373
405
|
// question already answered — quiet for the verdict; any other pending
|
|
374
406
|
// pass is a new question. Settled, there is nothing to classify.
|
|
375
|
-
if (e.T !== null) e.T.Ve =
|
|
407
|
+
if (e.T !== null) e.T.Ve = f && (e.m & STATUS_PENDING) !== 0;
|
|
376
408
|
}
|
|
377
409
|
// A node that died during its own pass (#3621) is dead at the end of it,
|
|
378
410
|
// and the pass is void. Its owner's teardown already unlinked its deps,
|
|
@@ -388,7 +420,7 @@ function recompute(e, t = false) {
|
|
|
388
420
|
if (e.R & REACTIVE_DISPOSED) {
|
|
389
421
|
clearDeps(e);
|
|
390
422
|
if (e.T !== null) e.T.Ee = null;
|
|
391
|
-
setPassLane(E);
|
|
423
|
+
if (laneStageHook) setPassLane(E);
|
|
392
424
|
return;
|
|
393
425
|
}
|
|
394
426
|
// The lane this pass is work of, if any: its seat (the node's, its
|
|
@@ -396,21 +428,25 @@ function recompute(e, t = false) {
|
|
|
396
428
|
// seat that read none of the lane's world has left it: its result is the
|
|
397
429
|
// frame's (a derivation whose branch no longer reaches the guess). A
|
|
398
430
|
// guess is written, not derived — it never leaves this way.
|
|
399
|
-
let
|
|
431
|
+
let O = !laneStageHook ? null : passLane;
|
|
400
432
|
// Listed before its staging, a pending pass included (the lane's own
|
|
401
433
|
// flight is the lane's); false: the pass left the lane (lanes.ts).
|
|
402
|
-
const d = !!e.T?.U ||
|
|
403
|
-
if (laneStageHook &&
|
|
404
|
-
if (laneStageHook(e,
|
|
434
|
+
const d = !!e.T?.U || N;
|
|
435
|
+
if (laneStageHook && O !== null) {
|
|
436
|
+
if (laneStageHook(e, O, t, d)) setPassLane(O); else O = null;
|
|
405
437
|
}
|
|
406
438
|
if (!d) {
|
|
407
439
|
// INV-11 (#3330): the equality gate compares against the slot this run
|
|
408
440
|
// publishes to — the staged `_pendingValue` when staged; a lane node's
|
|
409
441
|
// lane value (a node entering the lane this pass has none yet — its
|
|
410
442
|
// committed value, `laneStage` having voided a frame staging).
|
|
411
|
-
const o = e.
|
|
443
|
+
const o = e.ue !== NOT_PENDING ? e.ue : e.l & CONFIG_OVERRIDE && e.T.P !== NOT_PENDING ? e.T.P : e.le;
|
|
412
444
|
// A throwing comparator is contained inside `isSame` (A3, #2837; #4111).
|
|
413
|
-
|
|
445
|
+
// A pass replacing an error this node staged is a new answer, even the
|
|
446
|
+
// committed value (D-41: a recovery equal to the last good value is a
|
|
447
|
+
// change): the slot it publishes to held the error, and the readers that
|
|
448
|
+
// derived from it — `latest()` throws it — re-derive (#4403).
|
|
449
|
+
const E = !n && r || !!e.T?.Te || !!l || !isSame(e, o, S);
|
|
414
450
|
// Effects use `_equals: false` (no per-effect closure). The side effects that
|
|
415
451
|
// the equals closure used to perform — flagging the effect dirty and enqueueing
|
|
416
452
|
// its runner — happen here instead. `!create` matches the previous `initialized`
|
|
@@ -419,16 +455,16 @@ function recompute(e, t = false) {
|
|
|
419
455
|
if (n && E &&
|
|
420
456
|
// A stale reader of a lane (REACTIVE_SCREEN_READ) that computed what it
|
|
421
457
|
// last applied owes no run (lanes.ts).
|
|
422
|
-
!(e.R & REACTIVE_SCREEN_READ && !e.Ae && Object.is(e.
|
|
458
|
+
!(e.R & REACTIVE_SCREEN_READ && !e.Ae && Object.is(e.ge, S)) &&
|
|
423
459
|
// A re-staging pass owes no run: the commit replays the effect (#3802).
|
|
424
|
-
e.
|
|
460
|
+
e.ue === NOT_PENDING) {
|
|
425
461
|
e.Ae = !e.T?.U;
|
|
426
462
|
// Reuse one bound runner per effect — runEffect no-ops on a stale
|
|
427
463
|
// `_modified`, so re-enqueueing the same function is harmless.
|
|
428
464
|
// Lane work's run is the lane's (released at its reveal) — a first
|
|
429
465
|
// pass under a lane too: `effect()` skips the synchronous first run of
|
|
430
466
|
// a lane's node.
|
|
431
|
-
if (!t ||
|
|
467
|
+
if (!t || O !== null) globalQueue.enqueue(n, e.W ??= GlobalQueue.q.bind(null, e), O);
|
|
432
468
|
}
|
|
433
469
|
// Lanes. A written guess's own pass from the frame: its source
|
|
434
470
|
// recomputed it — the truth (A18: "the source is whatever recomputes the
|
|
@@ -437,7 +473,7 @@ function recompute(e, t = false) {
|
|
|
437
473
|
// only a correction: an equal truth re-runs nothing (lanes.ts). (As the
|
|
438
474
|
// lane's own work the lane judged it — `laneStage`.)
|
|
439
475
|
// (The hook first: a build without lanes folds the arm away.)
|
|
440
|
-
if (laneOutcomeHook && !t &&
|
|
476
|
+
if (laneOutcomeHook && !t && O === null && e.l & CONFIG_GUESS && laneOutcomeHook(e, S, d)) ; else if (d) ; else if (E) {
|
|
441
477
|
// L2: a first pass is born held — staged, committed with the
|
|
442
478
|
// transaction, its effect's first run the landing's (A29; `effect()`
|
|
443
479
|
// skips the synchronous first run on a staged value) — when the flush
|
|
@@ -454,15 +490,15 @@ function recompute(e, t = false) {
|
|
|
454
490
|
// pass that runs before anything joins: the pass's input, not a verdict
|
|
455
491
|
// after it. An effect still carrying an uncommitted staged value
|
|
456
492
|
// re-stages: the commit applies the latest pass, not the born-held one.
|
|
457
|
-
if (
|
|
493
|
+
if (O !== null) {
|
|
458
494
|
// Lane work: the lane's value — into the slot while the lane has not
|
|
459
495
|
// revealed (its reveal shows it), as its staging once it has (the
|
|
460
496
|
// next reveal promotes it; the screen keeps the revealed value). An
|
|
461
497
|
// effect's value slot is private: the run the lane holds is what
|
|
462
498
|
// shows it — unless the effect was born held, whose first run is the
|
|
463
499
|
// commit's (A29): it re-stages, as below.
|
|
464
|
-
if (n && e.
|
|
465
|
-
} else if (t ? !((flushTransaction !== null || passTx !== null) && (
|
|
500
|
+
if (n && e.ue === NOT_PENDING) e.le = S; else if (n || O.Ue) e.ue = S; else e.T.P = S;
|
|
501
|
+
} else if (t ? !((flushTransaction !== null || passTx !== null) && (R || creatorPass(T)?.R & REACTIVE_JOINED)) : n && e.ue === NOT_PENDING) {
|
|
466
502
|
// A first pass publishes directly. So does an effect: its value slot
|
|
467
503
|
// is private (only its own run reads it), and the staging round-trip
|
|
468
504
|
// (queuePendingNode + commitPendingNodes) paid per effect on the
|
|
@@ -473,9 +509,13 @@ function recompute(e, t = false) {
|
|
|
473
509
|
// sources commit) must see the fresh value while PLAIN reads stay
|
|
474
510
|
// committed until flush (#3009 purity). The pending round-trip is
|
|
475
511
|
// that separation; it cannot be skipped on any path a pull can reach.
|
|
476
|
-
e.le =
|
|
512
|
+
e.le = S;
|
|
477
513
|
} else {
|
|
478
|
-
e.
|
|
514
|
+
e.ue = S;
|
|
515
|
+
// D-39: a staged recovery keeps the error it replaces the display
|
|
516
|
+
// until it commits (`commitPendingNode`), as a write over one does
|
|
517
|
+
// (`setMemo`).
|
|
518
|
+
if (a) e.T.Te = a;
|
|
479
519
|
// Born held: in the transaction from birth, so a read of it this
|
|
480
520
|
// tick is a read of its world (the mount-during-a-hold case), not
|
|
481
521
|
// only after the seam parks it.
|
|
@@ -501,9 +541,9 @@ function recompute(e, t = false) {
|
|
|
501
541
|
if (e.o !== null) {
|
|
502
542
|
insertSubs(e);
|
|
503
543
|
// Lane work re-staged: the lane's members re-derive as its work.
|
|
504
|
-
if (
|
|
544
|
+
if (O !== null) laneDirty(e, O);
|
|
505
545
|
}
|
|
506
|
-
} else if (e.he !=
|
|
546
|
+
} else if (e.he != c) {
|
|
507
547
|
for (let t = e.o; t !== null; t = t.t) insertIntoHeapHeight(t.u, dirtyQueue);
|
|
508
548
|
}
|
|
509
549
|
// Silent recovery: errored → unchanged value fires no notification, but
|
|
@@ -512,15 +552,15 @@ function recompute(e, t = false) {
|
|
|
512
552
|
// recoveries ride insertSubs above; a comparator throw re-errored the node
|
|
513
553
|
// (el._x?._error re-set), so this only runs on a genuinely clean recovery.
|
|
514
554
|
if (!E && !e.T?.U) {
|
|
515
|
-
if (
|
|
555
|
+
if (a) settleErroredDependents(e, a);
|
|
516
556
|
// Self-registration (this node's own superseded flight) is the #3181
|
|
517
557
|
// sweep's business below — retiring it here too would walk twice.
|
|
518
|
-
if (
|
|
558
|
+
if (u) for (const t of u) if (t !== e) settlePendingSource(e, t);
|
|
519
559
|
}
|
|
520
560
|
// #3181: a synchronous settle supersedes the old landing callback, so
|
|
521
561
|
// recompute owns its pending-source sweep. An uninitialized node without
|
|
522
562
|
// a replacement source still has no truth to reveal and must stay parked.
|
|
523
|
-
if (
|
|
563
|
+
if (I && !(e.m & (STATUS_PENDING | STATUS_UNINITIALIZED))) settlePendingSource(e);
|
|
524
564
|
}
|
|
525
565
|
// A first pass that went pending where the born-held arm would have held
|
|
526
566
|
// its value (it read a held node, or a verdict lane's mount read a staging,
|
|
@@ -530,7 +570,7 @@ function recompute(e, t = false) {
|
|
|
530
570
|
// hold's commit (D-12) — but the hold does not wait for it: its only
|
|
531
571
|
// readers are behind the fallback (`_hidden`; F-4, #3540). A boundary
|
|
532
572
|
// re-armed by `on` owns what it collects outright (D-14): not held.
|
|
533
|
-
if (t &&
|
|
573
|
+
if (t && O === null && R && e.m & STATUS_PENDING) {
|
|
534
574
|
const t = flushTransaction ?? passTx;
|
|
535
575
|
if (t && !t.P && freshHook?.(e) !== CAUGHT_REARMED) holdNode(e, t);
|
|
536
576
|
}
|
|
@@ -551,7 +591,7 @@ function recompute(e, t = false) {
|
|
|
551
591
|
// kept at a park — one spurious recompute at most). A creation pass and a
|
|
552
592
|
// tracked effect trim now: their frames are replaceable like a direct
|
|
553
593
|
// commit, and a tracked effect's spurious run would be user-visible.
|
|
554
|
-
if (!e.T?.U && e.
|
|
594
|
+
if (!e.T?.U && e.ue === NOT_PENDING && !(n && e.Ae)) {
|
|
555
595
|
if (t || n === EFFECT_TRACKED) trimStaleDeps(e); else heldTrim(e);
|
|
556
596
|
}
|
|
557
597
|
// A staged value, a parked frame (L2: the commit retires it), or status the
|
|
@@ -559,18 +599,18 @@ function recompute(e, t = false) {
|
|
|
559
599
|
// node for this flush's commit. A first pass queues only when pending or
|
|
560
600
|
// born held: otherwise its value published directly. A queued pass's
|
|
561
601
|
// children are uncommitted (CONFIG_STAGED) until that commit.
|
|
562
|
-
if (e.
|
|
602
|
+
if (e.ue !== NOT_PENDING || e.T !== null && (e.T.me !== null || e.T.Le !== null) || (e.m & (STATUS_PENDING | STATUS_UNINITIALIZED)) !== 0 && (!t || (e.m & STATUS_PENDING) !== 0)) {
|
|
563
603
|
e.l |= CONFIG_STAGED;
|
|
564
604
|
// Lane work is the lane's to reveal (its seam), not this flush's commit.
|
|
565
|
-
if (
|
|
605
|
+
if (O === null) queuePendingNode(e);
|
|
566
606
|
}
|
|
567
|
-
setPassLane(E);
|
|
607
|
+
if (laneStageHook) setPassLane(E);
|
|
568
608
|
// Missed-wake reschedule (see the finally above): values this pass read
|
|
569
609
|
// before the nested commit are stale, so run again now that the heap will
|
|
570
610
|
// accept the node. Equality gates stop same-value landings from cascading,
|
|
571
611
|
// and a re-run only latches again if another nested commit changes a dep
|
|
572
612
|
// beneath it — convergent unless deps genuinely keep changing.
|
|
573
|
-
if (
|
|
613
|
+
if (A) {
|
|
574
614
|
enqueueSub(e);
|
|
575
615
|
schedule();
|
|
576
616
|
}
|
|
@@ -595,7 +635,7 @@ function updateIfNecessary(e) {
|
|
|
595
635
|
}
|
|
596
636
|
}
|
|
597
637
|
}
|
|
598
|
-
if (e.R & REACTIVE_DIRTY || e.T?.U && e.
|
|
638
|
+
if (e.R & REACTIVE_DIRTY || e.T?.U && e.ie < clock && !e.T?.Ee) {
|
|
599
639
|
recompute(e);
|
|
600
640
|
}
|
|
601
641
|
// The guard above refused an already-disposed node; the recompute it just
|
|
@@ -625,30 +665,30 @@ function computed(e, t) {
|
|
|
625
665
|
// plus the slots.
|
|
626
666
|
const E = {
|
|
627
667
|
id: inheritId(t, n, context),
|
|
628
|
-
l: (n ? CONFIG_TRANSPARENT : 0) | (t?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (!context || t?.lazy ? CONFIG_AUTO_DISPOSE : 0) | (t?.sync ? CONFIG_SYNC : 0) | (t?.
|
|
629
|
-
|
|
630
|
-
|
|
668
|
+
l: (n ? CONFIG_TRANSPARENT : 0) | (t?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (!context || t?.lazy ? CONFIG_AUTO_DISPOSE : 0) | (t?.sync ? CONFIG_SYNC : 0) | (t?.ae ? CONFIG_NO_SNAPSHOT : 0) | (t?.xe ?? 0) | (snapshotCaptureActive && ownerInSnapshotScope(context) ? CONFIG_IN_SNAPSHOT_SCOPE : 0),
|
|
669
|
+
ye: t?.equals ?? isEqual,
|
|
670
|
+
ke: null,
|
|
631
671
|
A: context?.A ?? defaultContext,
|
|
632
|
-
|
|
672
|
+
be: 0,
|
|
633
673
|
X: e,
|
|
634
674
|
le: o ? t.loadingValue : undefined,
|
|
635
675
|
he: 0,
|
|
636
|
-
|
|
676
|
+
ve: undefined,
|
|
637
677
|
We: null,
|
|
638
678
|
C: null,
|
|
639
679
|
_: null,
|
|
640
|
-
|
|
680
|
+
de: 0,
|
|
641
681
|
o: null,
|
|
642
|
-
|
|
682
|
+
Ze: null,
|
|
643
683
|
_parent: context,
|
|
644
684
|
Ge: null,
|
|
645
|
-
|
|
685
|
+
we: null,
|
|
646
686
|
pe: null,
|
|
647
687
|
R: t?.lazy ? REACTIVE_LAZY : REACTIVE_NONE,
|
|
648
688
|
// A loadingValue node is born committed: commit #0 is already in _value.
|
|
649
689
|
m: o ? 0 : STATUS_UNINITIALIZED,
|
|
650
|
-
|
|
651
|
-
|
|
690
|
+
ie: clock,
|
|
691
|
+
ue: NOT_PENDING,
|
|
652
692
|
Me: -1,
|
|
653
693
|
ce: o,
|
|
654
694
|
// Cold machinery (async slots) lives one hop away in the lazily-allocated extension — the core literal MUST
|
|
@@ -656,7 +696,7 @@ function computed(e, t) {
|
|
|
656
696
|
// allocation spills to a backing store and creation cost ~4x's).
|
|
657
697
|
T: null
|
|
658
698
|
};
|
|
659
|
-
if (t?.unobserved) ext(E).
|
|
699
|
+
if (t?.unobserved) ext(E).Ye = t.unobserved;
|
|
660
700
|
setupComputedNode(E, t);
|
|
661
701
|
return E;
|
|
662
702
|
}
|
|
@@ -667,22 +707,22 @@ function computed(e, t) {
|
|
|
667
707
|
* Never call ext() just to store a field's default. */ function ext(e) {
|
|
668
708
|
return e.T ??= {
|
|
669
709
|
Ee: null,
|
|
670
|
-
|
|
710
|
+
Se: null,
|
|
671
711
|
U: undefined,
|
|
672
|
-
se: undefined,
|
|
673
712
|
fe: undefined,
|
|
674
|
-
|
|
713
|
+
se: undefined,
|
|
714
|
+
Ye: undefined,
|
|
675
715
|
De: undefined,
|
|
676
|
-
Ue: null,
|
|
677
716
|
me: null,
|
|
717
|
+
Le: null,
|
|
678
718
|
Re: null,
|
|
679
719
|
Ve: false,
|
|
680
720
|
je: NOT_PENDING,
|
|
681
721
|
Be: -1,
|
|
682
|
-
|
|
722
|
+
Ie: 0,
|
|
683
723
|
P: NOT_PENDING,
|
|
684
724
|
I: 0,
|
|
685
|
-
|
|
725
|
+
Te: null
|
|
686
726
|
};
|
|
687
727
|
}
|
|
688
728
|
|
|
@@ -762,6 +802,9 @@ function computed(e, t) {
|
|
|
762
802
|
// head), and the pass may then read a guess and become the lane's.
|
|
763
803
|
if (E === flushTransaction && !o && !n || bornInto(e, E)) return false;
|
|
764
804
|
staleReader(e, E);
|
|
805
|
+
// Lane work or a verdict reader no longer waits on `el`'s flight (lanes.ts
|
|
806
|
+
// `laneServed`, A15).
|
|
807
|
+
if (o || n) laneServedHook(e, t);
|
|
765
808
|
return true;
|
|
766
809
|
}
|
|
767
810
|
|
|
@@ -775,7 +818,14 @@ function computed(e, t) {
|
|
|
775
818
|
|
|
776
819
|
/** The computed whose pass a creation under `owner` belongs to (a root's is
|
|
777
820
|
* its nearest computed ancestor's), or null outside every pass. */ function creatorPass(e) {
|
|
778
|
-
return e !== null && e.Qe ? e.
|
|
821
|
+
return e !== null && e.Qe ? e.Ke : e;
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
/** What `born` and the passes still running around `p` read — its
|
|
825
|
+
* creator's, theirs — of the future or a staging (REACTIVE_JOINED |
|
|
826
|
+
* REACTIVE_STAGED_READ): a pass created by one that did has no screen; its
|
|
827
|
+
* branch exists only in that world (#4341). */ function creatorReads(e, t) {
|
|
828
|
+
return (e = creatorPass(e._parent))?.R & REACTIVE_RECOMPUTING_DEPS ? creatorReads(e, t | e.R) : t & (REACTIVE_JOINED | REACTIVE_STAGED_READ);
|
|
779
829
|
}
|
|
780
830
|
|
|
781
831
|
/** L2 — park the previous pass's frame for this node's commit: the children
|
|
@@ -784,11 +834,11 @@ function computed(e, t) {
|
|
|
784
834
|
* the frame that replaces them (`commitPendingNode`) or when the owner does. */ function parkChildren(e) {
|
|
785
835
|
markDisposal(e);
|
|
786
836
|
const t = ext(e);
|
|
787
|
-
t.
|
|
788
|
-
t.
|
|
789
|
-
e.
|
|
837
|
+
t.Le = e.ke;
|
|
838
|
+
t.me = e.pe;
|
|
839
|
+
e.ke = null;
|
|
790
840
|
e.pe = null;
|
|
791
|
-
e.
|
|
841
|
+
e.be = 0;
|
|
792
842
|
}
|
|
793
843
|
|
|
794
844
|
/**
|
|
@@ -808,36 +858,36 @@ function computed(e, t) {
|
|
|
808
858
|
l:
|
|
809
859
|
// CONFIG_FRAME for a render effect (EFFECT_RENDER = 1; a user
|
|
810
860
|
// effect's 1 << 24 is unused).
|
|
811
|
-
o << 23 | (s ? CONFIG_TRANSPARENT : 0) | (E?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (E?.sync ? CONFIG_SYNC : 0) | (E?.
|
|
812
|
-
|
|
813
|
-
|
|
861
|
+
o << 23 | (s ? CONFIG_TRANSPARENT : 0) | (E?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (E?.sync ? CONFIG_SYNC : 0) | (E?.xe ?? 0) | (snapshotCaptureActive && ownerInSnapshotScope(context) ? CONFIG_IN_SNAPSHOT_SCOPE : 0),
|
|
862
|
+
ye: false,
|
|
863
|
+
ke: null,
|
|
814
864
|
A: context?.A ?? defaultContext,
|
|
815
|
-
|
|
865
|
+
be: 0,
|
|
816
866
|
X: e,
|
|
817
867
|
le: undefined,
|
|
818
868
|
he: 0,
|
|
819
|
-
|
|
869
|
+
ve: undefined,
|
|
820
870
|
We: null,
|
|
821
871
|
C: null,
|
|
822
872
|
_: null,
|
|
823
|
-
|
|
873
|
+
de: 0,
|
|
824
874
|
o: null,
|
|
825
|
-
|
|
875
|
+
Ze: null,
|
|
826
876
|
_parent: context,
|
|
827
877
|
Ge: null,
|
|
828
|
-
|
|
878
|
+
we: null,
|
|
829
879
|
pe: null,
|
|
830
880
|
R: REACTIVE_LAZY,
|
|
831
881
|
m: STATUS_UNINITIALIZED,
|
|
832
|
-
|
|
833
|
-
|
|
882
|
+
ie: clock,
|
|
883
|
+
ue: NOT_PENDING,
|
|
834
884
|
Me: -1,
|
|
835
885
|
ce: false,
|
|
836
886
|
Ae: false,
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
887
|
+
ge: undefined,
|
|
888
|
+
qe: t,
|
|
889
|
+
Je: n,
|
|
890
|
+
ze: undefined,
|
|
841
891
|
i: o,
|
|
842
892
|
T: null
|
|
843
893
|
};
|
|
@@ -846,7 +896,7 @@ function computed(e, t) {
|
|
|
846
896
|
// allocation on EVERY effect at creation (an alloc + 19 field stores,
|
|
847
897
|
// +23% effect creation, caught by the creation benches). Only genuinely
|
|
848
898
|
// per-node channels (boundaries) live on _x.
|
|
849
|
-
if (E?.unobserved) ext(i).
|
|
899
|
+
if (E?.unobserved) ext(i).Ye = E.unobserved;
|
|
850
900
|
setupComputedNode(i, lazyOptions);
|
|
851
901
|
return i;
|
|
852
902
|
}
|
|
@@ -876,7 +926,7 @@ const lazyOptions = {
|
|
|
876
926
|
|
|
877
927
|
function setupComputedNode(e, t) {
|
|
878
928
|
e.We = e;
|
|
879
|
-
const n = context?.Qe ? context.
|
|
929
|
+
const n = context?.Qe ? context.Ke : context;
|
|
880
930
|
if (context) linkChild(context, e);
|
|
881
931
|
if (n) e.he = n.he + 1;
|
|
882
932
|
wireExternalSourceHook?.(e);
|
|
@@ -892,13 +942,13 @@ function signal(e, t) {
|
|
|
892
942
|
// createSignal nodes so ownerPath can locate signal subjects; null here,
|
|
893
943
|
// and staying null on internal signals — one shape either way).
|
|
894
944
|
const n = {
|
|
895
|
-
|
|
896
|
-
l: (t?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (t?.
|
|
945
|
+
ye: t?.equals ?? isEqual,
|
|
946
|
+
l: (t?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (t?.ae ? CONFIG_NO_SNAPSHOT : 0),
|
|
897
947
|
le: e,
|
|
898
948
|
o: null,
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
949
|
+
Ze: null,
|
|
950
|
+
ie: clock,
|
|
951
|
+
ue: NOT_PENDING,
|
|
902
952
|
// Signal-literal diet (§12e): NO _time/_fn/_statusFlags slots. Stores
|
|
903
953
|
// materialize one signal per touched leaf, so signal bytes are store
|
|
904
954
|
// bytes. _time is write-only on signals (every read site is computed-
|
|
@@ -907,7 +957,7 @@ function signal(e, t) {
|
|
|
907
957
|
Me: -1,
|
|
908
958
|
T: null
|
|
909
959
|
};
|
|
910
|
-
if (t?.unobserved) ext(n).
|
|
960
|
+
if (t?.unobserved) ext(n).Ye = t.unobserved;
|
|
911
961
|
if (snapshotCaptureActive && !(n.l & CONFIG_NO_SNAPSHOT)) takeSnapshot(n, e);
|
|
912
962
|
return n;
|
|
913
963
|
}
|
|
@@ -928,17 +978,17 @@ function isEqual(e, t) {
|
|
|
928
978
|
* and location slots (the store relabels `store.<key>` and stamps the
|
|
929
979
|
* store's `loc` when the engine is installed). */ function slotSignal(e, t, n, o, E) {
|
|
930
980
|
const s = {
|
|
931
|
-
|
|
981
|
+
ye: t,
|
|
932
982
|
l: CONFIG_OWNED_WRITE | CONFIG_SLOT_NODE,
|
|
933
983
|
le: e,
|
|
934
984
|
o: null,
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
985
|
+
Ze: null,
|
|
986
|
+
ie: clock,
|
|
987
|
+
ue: NOT_PENDING,
|
|
938
988
|
Me: -1,
|
|
939
989
|
T: null,
|
|
940
990
|
O: n,
|
|
941
|
-
|
|
991
|
+
Xe: o,
|
|
942
992
|
acc: E,
|
|
943
993
|
px: undefined,
|
|
944
994
|
pxv: undefined
|
|
@@ -1064,7 +1114,7 @@ function setVerdict(e) {
|
|
|
1064
1114
|
* never the graph — A32).
|
|
1065
1115
|
* False means the reader derives from the staged value.
|
|
1066
1116
|
*/ function readerSeesCommitted(e, t) {
|
|
1067
|
-
return !t || e.
|
|
1117
|
+
return !t || e.ue === NOT_PENDING || t.l & CONFIG_CHILDREN_FORBIDDEN;
|
|
1068
1118
|
}
|
|
1069
1119
|
|
|
1070
1120
|
/** A28 — set when a node is staged (queuePendingNode) OUTSIDE a flush;
|
|
@@ -1085,7 +1135,7 @@ function markUnflushedStaged() {
|
|
|
1085
1135
|
* is unflushed. Exempt: promoted writes (A28 (4): a write issued inside a
|
|
1086
1136
|
* recompute is promoted at that recompute's end — boundary and loading
|
|
1087
1137
|
* machinery, signals declared for in-computation writes). */ function unflushedValue(e) {
|
|
1088
|
-
if (globalQueue.
|
|
1138
|
+
if (globalQueue.Y || e.ue === NOT_PENDING || e.l & CONFIG_PROMOTED) return NOT_PENDING;
|
|
1089
1139
|
// A held node (L2) carries a staged value between flushes too, but it was
|
|
1090
1140
|
// flushed — and parked. Not an unflushed write — unless rewritten since:
|
|
1091
1141
|
// then the flushed staging is what the world sees until the next flush.
|
|
@@ -1098,7 +1148,7 @@ function markUnflushedStaged() {
|
|
|
1098
1148
|
* stash is stamped with the clock, which that flush advances. */ function stashFlushed(e) {
|
|
1099
1149
|
const t = e.T;
|
|
1100
1150
|
if (t.Be !== clock) {
|
|
1101
|
-
t.je = e.
|
|
1151
|
+
t.je = e.ue;
|
|
1102
1152
|
t.Be = clock;
|
|
1103
1153
|
unflushedStaged = true;
|
|
1104
1154
|
}
|
|
@@ -1146,18 +1196,19 @@ function resyncUnflushedCompanions() {
|
|
|
1146
1196
|
|
|
1147
1197
|
function read(e) {
|
|
1148
1198
|
let t = context;
|
|
1149
|
-
if (t?.Qe) t = t.
|
|
1199
|
+
if (t?.Qe) t = t.Ke;
|
|
1150
1200
|
const n = e;
|
|
1151
1201
|
// CARVE 1: `owner` was `el._firewall || el` — a store leaf's status,
|
|
1152
1202
|
// height and error were read off its projection computed. (Typed loosely
|
|
1153
1203
|
// as the `||` expression was: a signal's `_statusFlags`/`_height` read as
|
|
1154
1204
|
// undefined and mask to 0 on every site below.)
|
|
1155
1205
|
const o = e;
|
|
1156
|
-
if (typeof n.X === "function") prepareComputed(e);
|
|
1157
1206
|
// The verdict windows (`latest`, `isPending`; verdict.ts): one cold path,
|
|
1158
|
-
// off this one, present only while a window is open.
|
|
1207
|
+
// off this one, present only while a window is open. It wakes a lazy or
|
|
1208
|
+
// dormant memo itself, outside the window (#4366).
|
|
1159
1209
|
if (verdict !== null) return verdict(e, t);
|
|
1160
|
-
if (
|
|
1210
|
+
if (typeof n.X === "function") prepareComputed(e);
|
|
1211
|
+
if (!n.X && e.T?.De === undefined && !snapshotCaptureActive && (!unflushedStaged || e.ue === NOT_PENDING) && // A28, see readNodeFast
|
|
1161
1212
|
!(e.l & CONFIG_OVERRIDE) && // lanes: the slow path's one arm
|
|
1162
1213
|
true) {
|
|
1163
1214
|
if (t) {
|
|
@@ -1178,13 +1229,13 @@ function read(e) {
|
|
|
1178
1229
|
}
|
|
1179
1230
|
}
|
|
1180
1231
|
// Committed visibility for untracked and children-forbidden readers.
|
|
1181
|
-
if (!t || e.
|
|
1232
|
+
if (!t || e.ue === NOT_PENDING || t.l & CONFIG_CHILDREN_FORBIDDEN) return e.le;
|
|
1182
1233
|
// (A plain signal is never uninitialized — the carve-out is `serve`'s.)
|
|
1183
1234
|
// Lane work over a folded lane (D-34), once the frame has a
|
|
1184
1235
|
// transaction, reads the screen too.
|
|
1185
1236
|
if ((observeFlightHook && t.l & CONFIG_VERDICT || laneStageHook && passLane?.folded) && stagedScreen(t)) return e.le;
|
|
1186
1237
|
stagedRead(t);
|
|
1187
|
-
return e.
|
|
1238
|
+
return e.ue;
|
|
1188
1239
|
}
|
|
1189
1240
|
// Rule 3: this read serves the committed value to a render effect outside a
|
|
1190
1241
|
// parking flush (decided after the pull below — a pull can join).
|
|
@@ -1199,7 +1250,8 @@ function read(e) {
|
|
|
1199
1250
|
// it probed inline: it reads held values as the screen and shows the
|
|
1200
1251
|
// verdict now. Not an effect: a render effect is a frame reader
|
|
1201
1252
|
// already, and a user effect's posture is its own reads'.
|
|
1202
|
-
|
|
1253
|
+
// (A verdict memo exists only with the verdict engine installed.)
|
|
1254
|
+
if (observeFlightHook && !t.i) t.R |= o.l & CONFIG_VERDICT;
|
|
1203
1255
|
}
|
|
1204
1256
|
}
|
|
1205
1257
|
// L2, as in the fast block above (tracked or not). A node born into the
|
|
@@ -1225,7 +1277,7 @@ function read(e) {
|
|
|
1225
1277
|
const n = e.T?.De;
|
|
1226
1278
|
if (n !== undefined && !(o.m & STATUS_ERROR)) {
|
|
1227
1279
|
const o = n === NO_SNAPSHOT ? undefined : n;
|
|
1228
|
-
const E = e.
|
|
1280
|
+
const E = e.ue !== NOT_PENDING ? e.ue : e.le;
|
|
1229
1281
|
if (E !== o) t.R |= REACTIVE_SNAPSHOT_STALE;
|
|
1230
1282
|
return o;
|
|
1231
1283
|
}
|
|
@@ -1244,11 +1296,12 @@ function read(e) {
|
|
|
1244
1296
|
// — unless the flight committed beneath inputs already on screen
|
|
1245
1297
|
// (`observeFlight`), or the reader was born into the flight's transaction
|
|
1246
1298
|
// (#4010): it has no screen, and waits on the flight with its frame.
|
|
1247
|
-
|
|
1299
|
+
// (A lane, and a verdict reader, exist only with their engines installed —
|
|
1300
|
+
// the verdict engine imports the lane engine: without it the test folds.)
|
|
1301
|
+
if (laneStageHook && o.m & STATUS_PENDING && !E && !(e.l & CONFIG_OVERRIDE) && !(o.m & STATUS_UNINITIALIZED)) {
|
|
1248
1302
|
// A reader with no committed value yet sees the flight pending: a
|
|
1249
1303
|
// boundary a lane mounts shows its fallback (A29's boundary exemption).
|
|
1250
|
-
|
|
1251
|
-
if (laneStageHook && passLane !== null && !(t?.m & STATUS_UNINITIALIZED)) E = true; else if (observeFlightHook && t !== null && t.l & CONFIG_VERDICT) E = observeFlightHook(t, o);
|
|
1304
|
+
if (passLane !== null && !(t?.m & STATUS_UNINITIALIZED)) E = true; else if (t !== null && t.l & CONFIG_VERDICT) E = observeFlightHook(t, o);
|
|
1252
1305
|
}
|
|
1253
1306
|
if (o.m & STATUS_PENDING && !E) {
|
|
1254
1307
|
// A reader landing on a pending node throws; an untracked read of an
|
|
@@ -1274,16 +1327,24 @@ function read(e) {
|
|
|
1274
1327
|
// Only a genuine reactive re-read may retry an errored async source:
|
|
1275
1328
|
// - tracking: owned/tracked scope only (never events / `untrack` / effect side-effect phase)
|
|
1276
1329
|
// - owner._time < clock: only on a later cycle than the one the error was found
|
|
1277
|
-
if (tracking && o.
|
|
1330
|
+
if (tracking && o.ie < clock) {
|
|
1278
1331
|
recompute(o);
|
|
1279
1332
|
return read(e);
|
|
1280
|
-
}
|
|
1333
|
+
}
|
|
1334
|
+
// D-41: a staged error replacing the shown one is this flush's answer
|
|
1335
|
+
// (`stageError`): a reader served the staging (`serve`) throws it, as it
|
|
1336
|
+
// would read a staged value, and stages its own error with it; one
|
|
1337
|
+
// served the screen throws the shown error. Thrown the shown error, a
|
|
1338
|
+
// reader born this flush published it, and its readers' stale error
|
|
1339
|
+
// committed after the new one (#4404).
|
|
1340
|
+
if (!E && e.l & CONFIG_STAGED_ERROR) serve(e, t);
|
|
1341
|
+
throw o.T?.U;
|
|
1281
1342
|
}
|
|
1282
|
-
|
|
1283
|
-
//
|
|
1284
|
-
//
|
|
1285
|
-
if (!t
|
|
1286
|
-
const s = serve(e, t);
|
|
1343
|
+
// D-41: an untracked read reads the screen, and so does a frame reader
|
|
1344
|
+
// served the committed value — `serve` hands it that value as it does an
|
|
1345
|
+
// untracked read — a shown error included (`throwShown`).
|
|
1346
|
+
if (E || !t) throwShown(e);
|
|
1347
|
+
const s = serve(e, E ? null : t);
|
|
1287
1348
|
if (!t && typeof n.X === "function" && e.l & CONFIG_AUTO_DISPOSE && !(o.m & STATUS_PENDING) && !e.o) {
|
|
1288
1349
|
// Deferred, not inline (#3078): an inline unobserved() here made untracked
|
|
1289
1350
|
// reads destructive — dispose on this read, full revival recompute on the
|
|
@@ -1297,6 +1358,12 @@ function read(e) {
|
|
|
1297
1358
|
return s;
|
|
1298
1359
|
}
|
|
1299
1360
|
|
|
1361
|
+
/** D-41: a reader served the screen — an untracked read, a frame reader
|
|
1362
|
+
* served the committed value, a verdict reader (`serve`) — reads a shown
|
|
1363
|
+
* error there until the answer that replaces it commits. */ function throwShown(e) {
|
|
1364
|
+
if (e.T?.Te) throw e.T.Te;
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1300
1367
|
/**
|
|
1301
1368
|
* Rule 1, the one slow implementation (DESIGN-CONSOLIDATION move 3b, step
|
|
1302
1369
|
* 6c): the value a reader `c` (null = untracked, no pass) is served from
|
|
@@ -1311,18 +1378,17 @@ function read(e) {
|
|
|
1311
1378
|
// an untracked reader has nothing to serve and holds (A19 exception 1) — a
|
|
1312
1379
|
// bookkeeping read (`spectate`) likewise, and a children-forbidden reader
|
|
1313
1380
|
// (A32: the frame, which has nothing here).
|
|
1314
|
-
if (e.
|
|
1381
|
+
if (e.ue !== NOT_PENDING && e.m & STATUS_UNINITIALIZED && (!t || spectating || t.l & CONFIG_CHILDREN_FORBIDDEN)) throw new NotReadyError(null);
|
|
1315
1382
|
const n = t && unflushedStaged ? unflushedValue(e) : NOT_PENDING;
|
|
1316
1383
|
if (n !== NOT_PENDING) {
|
|
1317
1384
|
markLateLinker(t);
|
|
1318
1385
|
return n;
|
|
1319
1386
|
}
|
|
1320
|
-
if (readerSeesCommitted(e, t)) return e.le;
|
|
1321
|
-
if (observeFlightHook && t.l & CONFIG_VERDICT && !(e.m & STATUS_UNINITIALIZED) && stagedScreen(t)) return e.le;
|
|
1387
|
+
if (readerSeesCommitted(e, t) || observeFlightHook && t.l & CONFIG_VERDICT && !(e.m & STATUS_UNINITIALIZED) && stagedScreen(t) && !throwShown(e)) return e.le;
|
|
1322
1388
|
stagedRead(t, e);
|
|
1323
1389
|
// D-41: the staged answer is an error (`stageError`).
|
|
1324
|
-
if (e.l & CONFIG_STAGED_ERROR) throw e.
|
|
1325
|
-
return e.
|
|
1390
|
+
if (e.l & CONFIG_STAGED_ERROR) throw e.ue;
|
|
1391
|
+
return e.ue;
|
|
1326
1392
|
}
|
|
1327
1393
|
|
|
1328
1394
|
/** A pass read a staging of this flush: it derives from what the flush may
|
|
@@ -1342,7 +1408,13 @@ function read(e) {
|
|
|
1342
1408
|
* round (#3969: nor does it make a later lane read a re-derive, `enterLane`). */ function stagedRead(e, t) {
|
|
1343
1409
|
if (!(t?.m & STATUS_UNINITIALIZED)) {
|
|
1344
1410
|
e.R |= REACTIVE_STAGED_READ;
|
|
1345
|
-
|
|
1411
|
+
// A verdict reader's too when it is an effect, before the frame has a
|
|
1412
|
+
// transaction (after, `stagedScreen` serves it the screen): the staging
|
|
1413
|
+
// is the frame's read, and the pass re-derives once as a verdict reader
|
|
1414
|
+
// if the flush parks (D-22; D-25: the probe decides the posture in either
|
|
1415
|
+
// read order). A memo's is the frame's derivation either way: a memo is
|
|
1416
|
+
// not a leaf (`frameRead`).
|
|
1417
|
+
if (laneSeamsHook && (passLane !== null || e.i && e.l & CONFIG_VERDICT)) stagedReaders.push(e);
|
|
1346
1418
|
}
|
|
1347
1419
|
}
|
|
1348
1420
|
|
|
@@ -1356,6 +1428,14 @@ function read(e) {
|
|
|
1356
1428
|
* its only value (A29). Nor has a reader born into the flush's transaction
|
|
1357
1429
|
* (`bornInto`, #4010): its branch exists only there. */ function stagedScreen(e) {
|
|
1358
1430
|
if (flushTransaction === null || bornInto(e, flushTransaction)) return false;
|
|
1431
|
+
// A transaction only a `latest()` read opened holds nothing: the staging
|
|
1432
|
+
// is the frame's read for a pass in the frame's seat, as it is before the
|
|
1433
|
+
// frame has one, and the seam re-derives the pass once only if the flush
|
|
1434
|
+
// parks (D-22, F-10). Lane work sees the screen (D-37). Not a pass with no
|
|
1435
|
+
// value yet: its first answer is nobody's hold (D-6) and would commit the
|
|
1436
|
+
// staging whether or not the frame parks — it reads the screen, and runs
|
|
1437
|
+
// again at the landing.
|
|
1438
|
+
if (observeFlightHook && flushTransaction === latestOpened && passLane === null && e.l & CONFIG_VERDICT && !(e.m & STATUS_UNINITIALIZED)) return !stagedReaders.push(e);
|
|
1359
1439
|
staleReader(e, flushTransaction);
|
|
1360
1440
|
return true;
|
|
1361
1441
|
}
|
|
@@ -1363,7 +1443,7 @@ function read(e) {
|
|
|
1363
1443
|
/** A28 (4) — written inside a recompute that runs OUTSIDE a flush (a
|
|
1364
1444
|
* creation-time compute): promoted at that pass's end, visible to the rest of
|
|
1365
1445
|
* the block. Cold: only contextual writes reach here. */ function notePromotedWrite(e) {
|
|
1366
|
-
if (globalQueue.
|
|
1446
|
+
if (globalQueue.Y || e.l & CONFIG_PROMOTED) return;
|
|
1367
1447
|
e.l |= CONFIG_PROMOTED;
|
|
1368
1448
|
promotedWrites.push(e);
|
|
1369
1449
|
}
|
|
@@ -1411,9 +1491,9 @@ function takeSnapshot(e, t) {
|
|
|
1411
1491
|
* unwinding a flush or a setter; answered "same" so nothing commits.
|
|
1412
1492
|
* @internal
|
|
1413
1493
|
*/ function isSame(e, t, n) {
|
|
1414
|
-
if (e.
|
|
1494
|
+
if (e.ye === isEqual) return t === n;
|
|
1415
1495
|
try {
|
|
1416
|
-
return e.
|
|
1496
|
+
return e.ye && e.ye(t, n);
|
|
1417
1497
|
} catch (t) {
|
|
1418
1498
|
if (!(t instanceof NotReadyError)) return notifyStatus(e, STATUS_ERROR, t), true;
|
|
1419
1499
|
}
|
|
@@ -1421,7 +1501,7 @@ function takeSnapshot(e, t) {
|
|
|
1421
1501
|
|
|
1422
1502
|
function setSignal(e, t) {
|
|
1423
1503
|
if (writeHook !== null) writeHook(e);
|
|
1424
|
-
const n = e.
|
|
1504
|
+
const n = e.ue === NOT_PENDING ? e.le : e.ue;
|
|
1425
1505
|
if (typeof t === "function") t = t(n);
|
|
1426
1506
|
// Lanes: a write landing on a guess is its truth (A18 — an async guess's
|
|
1427
1507
|
// own landing), judged against the guess; one landing on a lane's
|
|
@@ -1436,7 +1516,7 @@ function setSignal(e, t) {
|
|
|
1436
1516
|
// user comparator must not run against `undefined` (matches recompute).
|
|
1437
1517
|
// D-41: a write over a shown error is a change whatever the last good
|
|
1438
1518
|
// value was — the error leaves at its commit (`commitPendingNode`).
|
|
1439
|
-
const o = !!(e.m & STATUS_UNINITIALIZED) || !!e.T?.
|
|
1519
|
+
const o = !!(e.m & STATUS_UNINITIALIZED) || !!e.T?.Te || !isSame(e, n, t);
|
|
1440
1520
|
if (!o) return t;
|
|
1441
1521
|
// A write during hydration's snapshot capture to a source that has no
|
|
1442
1522
|
// snapshot — created BEFORE capture began (module-level state: an identity
|
|
@@ -1448,16 +1528,16 @@ function setSignal(e, t) {
|
|
|
1448
1528
|
// pass reads a value the server never had. Store leaves written here are
|
|
1449
1529
|
// plain signals and qualify the same way.
|
|
1450
1530
|
if (snapshotCaptureActive) captureWriteSnapshot(e, n);
|
|
1451
|
-
const E = e.
|
|
1531
|
+
const E = e.ue !== NOT_PENDING;
|
|
1452
1532
|
if (!E) queuePendingNode(e);
|
|
1453
1533
|
// A28: a held node rewritten outside a flush keeps its flushed staging
|
|
1454
1534
|
// for every reader until the flush that carries the rewrite.
|
|
1455
|
-
else if (e.l & CONFIG_HELD && !globalQueue.
|
|
1456
|
-
e.
|
|
1535
|
+
else if (e.l & CONFIG_HELD && !globalQueue.Y) stashFlushed(e);
|
|
1536
|
+
e.ue = t;
|
|
1457
1537
|
if (context !== null) notePromotedWrite(e);
|
|
1458
1538
|
// _time is a computed-only slot (§12e): writing it on a signal would fork
|
|
1459
1539
|
// the lean shape. Every read site is computed-typed.
|
|
1460
|
-
if (e.X !== undefined) e.
|
|
1540
|
+
if (e.X !== undefined) e.ie = clock;
|
|
1461
1541
|
// Staged-rewrite fast path (§12d): a re-write to a node whose subscribers
|
|
1462
1542
|
// were already walked — and where nothing has recomputed or linked since
|
|
1463
1543
|
// (epoch) — re-stages the value and stops. The walk is idempotent (subs
|
|
@@ -1498,8 +1578,8 @@ function setSignal(e, t) {
|
|
|
1498
1578
|
// every later read keeps throwing the error the derivation left behind.
|
|
1499
1579
|
// The error stays the display until the write commits (D-41).
|
|
1500
1580
|
if (e.m & STATUS_ERROR) {
|
|
1501
|
-
e.T.
|
|
1502
|
-
notifyStatus(e, STATUS_NONE
|
|
1581
|
+
e.T.Te = e.T.U;
|
|
1582
|
+
notifyStatus(e, STATUS_NONE);
|
|
1503
1583
|
}
|
|
1504
1584
|
t = setSignal(e, t);
|
|
1505
1585
|
// A write replaces an error a pass staged (D-41): it is a value again.
|
|
@@ -1510,7 +1590,7 @@ function setSignal(e, t) {
|
|
|
1510
1590
|
e.R = e.R & ~REACTIVE_CHECK | REACTIVE_DIRTY;
|
|
1511
1591
|
insertIntoHeap(e, dirtyQueue);
|
|
1512
1592
|
schedule();
|
|
1513
|
-
} else if (e.
|
|
1593
|
+
} else if (e.ue !== NOT_PENDING) e.R |= REACTIVE_MANUAL_WRITE;
|
|
1514
1594
|
return t;
|
|
1515
1595
|
}
|
|
1516
1596
|
|
|
@@ -1571,4 +1651,4 @@ function staleValues(e, t = true) {
|
|
|
1571
1651
|
}
|
|
1572
1652
|
}
|
|
1573
1653
|
|
|
1574
|
-
export { bornInto, captureWriteSnapshot, clearSnapshots, computed, context, createEffectNode, effectStatusNotify, ext, isEqual, isSame, joinPass, joinPassAt, markLateLinker, markRefresh, markSnapshotScope, markUnflushedStaged, notePromotedWrite, prepareComputed, pullComputed, read, readerSeesCommitted, recompute, releaseSnapshotScope, resyncUnflushedCompanions, runWithOwner, serve, setEffectStatusNotify, setMemo, setSignal, setSnapshotCapture, setVerdict, setWriteHook, signal, slotSignal, snapshotCaptureActive, snapshotSources, spectating, stagedRead, stagedScreen, staleValues, stashFlushed, statusNotifierOf, tracking, unflushedStaged, unflushedValue, untrack, verdict, writeHook };
|
|
1654
|
+
export { bornInto, captureWriteSnapshot, clearSnapshots, computed, context, createEffectNode, creatorPass, creatorReads, effectStatusNotify, ext, isEqual, isSame, joinPass, joinPassAt, markLateLinker, markRefresh, markSnapshotScope, markUnflushedStaged, notePromotedWrite, prepareComputed, pullComputed, read, readerSeesCommitted, recompute, releaseSnapshotScope, resyncUnflushedCompanions, runWithOwner, serve, setEffectStatusNotify, setMemo, setSignal, setSnapshotCapture, setVerdict, setWriteHook, signal, slotSignal, snapshotCaptureActive, snapshotSources, spectating, stagedRead, stagedScreen, staleValues, stashFlushed, statusNotifierOf, tracking, unflushedStaged, unflushedValue, untrack, verdict, writeHook };
|