@solidjs/signals 2.0.0-rc.17 → 2.0.0-rc.19
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 +426 -241
- package/dist/dev.attribution.js +19 -16
- package/dist/dev.js +768 -409
- package/dist/observe/boundaries.js +88 -67
- package/dist/observe/core/action.js +8 -0
- package/dist/observe/core/async.js +183 -138
- package/dist/observe/core/attribution.js +30 -28
- package/dist/observe/core/constants.js +23 -1
- package/dist/observe/core/core.js +185 -157
- package/dist/observe/core/effect.js +34 -37
- package/dist/observe/core/graph.js +8 -8
- package/dist/observe/core/heap.js +5 -5
- package/dist/observe/core/lanes.js +104 -84
- package/dist/observe/core/owner.js +17 -16
- package/dist/observe/core/scheduler.js +61 -47
- package/dist/observe/core/truth.js +6 -6
- package/dist/observe/core/verdict.js +15 -15
- package/dist/observe/deferred.js +40 -38
- package/dist/observe/from.js +248 -0
- package/dist/observe/index.js +4 -2
- package/dist/observe/map.js +22 -22
- package/dist/observe/reveal.js +5 -5
- package/dist/observe/signals.js +57 -15
- package/dist/observe/store/affects.js +1 -1
- package/dist/observe/store/hooks.js +3 -0
- package/dist/observe/store/optimistic.js +11 -11
- package/dist/observe/store/projection.js +34 -21
- package/dist/observe/store/reconcile.js +138 -122
- package/dist/observe/store/store.js +628 -641
- package/dist/observe/store/target.js +1 -5
- package/dist/observe/store/utils.js +7 -2
- package/dist/prod/boundaries.js +153 -132
- package/dist/prod/core/action.js +8 -0
- package/dist/prod/core/async.js +242 -197
- package/dist/prod/core/constants.js +16 -1
- package/dist/prod/core/core.js +166 -138
- package/dist/prod/core/effect.js +31 -34
- package/dist/prod/core/graph.js +5 -5
- package/dist/prod/core/heap.js +12 -12
- package/dist/prod/core/lanes.js +98 -78
- package/dist/prod/core/owner.js +15 -14
- package/dist/prod/core/scheduler.js +64 -50
- package/dist/prod/core/truth.js +6 -6
- package/dist/prod/core/verdict.js +17 -17
- package/dist/prod/deferred.js +40 -38
- package/dist/prod/from.js +248 -0
- package/dist/prod/index.js +4 -2
- package/dist/prod/map.js +14 -14
- package/dist/prod/reveal.js +8 -8
- package/dist/prod/signals.js +46 -4
- package/dist/prod/store/affects.js +1 -1
- package/dist/prod/store/hooks.js +3 -0
- package/dist/prod/store/optimistic.js +16 -16
- package/dist/prod/store/projection.js +22 -9
- package/dist/prod/store/reconcile.js +138 -122
- package/dist/prod/store/store.js +308 -331
- package/dist/prod/store/target.js +13 -17
- package/dist/prod/store/utils.js +2 -0
- package/dist/types/core/action.d.ts +8 -0
- package/dist/types/core/async.d.ts +12 -2
- package/dist/types/core/constants.d.ts +25 -0
- package/dist/types/core/core.d.ts +33 -4
- package/dist/types/core/dev.d.ts +1 -1
- package/dist/types/core/index.d.ts +1 -1
- package/dist/types/core/lanes.d.ts +5 -1
- package/dist/types/core/scheduler.d.ts +17 -3
- package/dist/types/from.d.ts +47 -0
- package/dist/types/index.d.ts +4 -1
- package/dist/types/signals.d.ts +37 -0
- package/dist/types/store/target.d.ts +2 -0
- package/package.json +1 -1
package/dist/dev-shared.js
CHANGED
|
@@ -283,10 +283,30 @@ const CONFIG_WIDE = 1 << 26;
|
|
|
283
283
|
* creation by dev builds only (the observe artifact mangles the option name,
|
|
284
284
|
* as it does `_wide`). */
|
|
285
285
|
const CONFIG_SUPERSEDES = 1 << 27;
|
|
286
|
+
/** Observe tiers only: the memo `merge()` creates for a function source — a
|
|
287
|
+
* key bag readers consume key by key, built by the framework (a compiled
|
|
288
|
+
* component spread) with options no user can reach. The attribution engine's
|
|
289
|
+
* UNSTABLE_MEMO_OUTPUT skips it: a fresh-but-equal bag is the idiom
|
|
290
|
+
* (`{...(on() ? { a } : {})}`), and the advice (`equals`) cannot be applied
|
|
291
|
+
* (#4256). Set through `_extraConfig` by observe builds only. */
|
|
292
|
+
const CONFIG_KEY_BAG = 1 << 28;
|
|
293
|
+
/** The frame (rule 3, D-3): a render effect (set at creation, as
|
|
294
|
+
* `EFFECT_RENDER << 23` — keep the two in step), and a boundary's tree and
|
|
295
|
+
* output (boundaries.ts) — structure between the content and the render
|
|
296
|
+
* effect that shows it, not a user derivation of the content. Outside a
|
|
297
|
+
* hold's own flush it reads that hold's values as committed and is
|
|
298
|
+
* re-derived at its landing, and a re-pass of it publishes mainline: it
|
|
299
|
+
* joins nothing, so two mounts under one boundary made in separate flushes
|
|
300
|
+
* keep their holds apart (D-4, S-5 rows 1′–3′, #4283). */
|
|
301
|
+
const CONFIG_FRAME = 1 << 23;
|
|
286
302
|
const STATUS_NONE = 0;
|
|
287
303
|
const STATUS_PENDING = 1 << 0;
|
|
288
304
|
const STATUS_ERROR = 1 << 1;
|
|
289
305
|
const STATUS_UNINITIALIZED = 1 << 2;
|
|
306
|
+
/** An error that answered a node's first read (no value has ever landed):
|
|
307
|
+
* the error, not UNINITIALIZED, is its status while shown, but a re-ask
|
|
308
|
+
* makes it uninitialized-pending again — it still has no value (#4244). */
|
|
309
|
+
const STATUS_NO_VALUE = 1 << 3;
|
|
290
310
|
/** `catchHook`'s answer when the catcher is a boundary re-armed by
|
|
291
311
|
* `on` (truthy, as any catch): what it collects is its own, not the hold's. */
|
|
292
312
|
const CAUGHT_REARMED = 2;
|
|
@@ -306,6 +326,8 @@ const defaultContext = {};
|
|
|
306
326
|
*/
|
|
307
327
|
const $REFRESH = Symbol("refresh");
|
|
308
328
|
|
|
329
|
+
const NewSet = Set;
|
|
330
|
+
|
|
309
331
|
let attrHooks = null;
|
|
310
332
|
/**
|
|
311
333
|
* The installed engine, registered on `globalThis` as well (the records
|
|
@@ -1212,10 +1234,12 @@ function disposeChildren(node, self = false, zombie) {
|
|
|
1212
1234
|
// A death that can unblock the future (L2, `futureBlocked`): a held
|
|
1213
1235
|
// flight's — a transaction's or a lane's (its `_x._transaction`) — or a
|
|
1214
1236
|
// stale reader's (REACTIVE_FRAME_READ — a frame that derived from one).
|
|
1237
|
+
// An idle pending queue would also pin it until an unrelated flush.
|
|
1215
1238
|
// Nothing else re-examines a dead node, so make sure a seam comes.
|
|
1216
1239
|
if (
|
|
1217
1240
|
(node._statusFlags & STATUS_PENDING && node._x?._transaction != null) ||
|
|
1218
|
-
flags & REACTIVE_FRAME_READ
|
|
1241
|
+
flags & REACTIVE_FRAME_READ ||
|
|
1242
|
+
pendingNodes.length
|
|
1219
1243
|
)
|
|
1220
1244
|
schedule();
|
|
1221
1245
|
}
|
|
@@ -2032,8 +2056,18 @@ function nextQuestion() {
|
|
|
2032
2056
|
}
|
|
2033
2057
|
const MAINLINE_QUESTION = 0x7fffffff;
|
|
2034
2058
|
let inEffectCallback = false;
|
|
2035
|
-
|
|
2036
|
-
|
|
2059
|
+
/** Dev-only: matches no event, so a window or phase holding it applies
|
|
2060
|
+
* whatever event is current (see `strictReadEvent`, core.ts). */
|
|
2061
|
+
const ANY_EVENT = {};
|
|
2062
|
+
/** Dev-only: the DOM event current when the effect phase was entered. A
|
|
2063
|
+
* handler dispatched synchronously from that phase (`el.focus()`) runs under
|
|
2064
|
+
* a different event and is not in it (#4235). */
|
|
2065
|
+
let effectCallbackEvent = ANY_EVENT;
|
|
2066
|
+
function setEffectCallback(value, event = ANY_EVENT) {
|
|
2067
|
+
{
|
|
2068
|
+
inEffectCallback = value;
|
|
2069
|
+
effectCallbackEvent = event;
|
|
2070
|
+
}
|
|
2037
2071
|
}
|
|
2038
2072
|
function schedule() {
|
|
2039
2073
|
if (halted) {
|
|
@@ -2059,12 +2093,13 @@ function schedule() {
|
|
|
2059
2093
|
* hook machinery (pay-for-use).
|
|
2060
2094
|
*/
|
|
2061
2095
|
const ROOT_ERROR_HOOK = Symbol.for("solid-js/root-error-hook");
|
|
2096
|
+
const HALTED = "[REACTIVITY_HALTED]";
|
|
2062
2097
|
function haltReactivity(cause) {
|
|
2063
2098
|
if (halted) return;
|
|
2064
2099
|
halted = true;
|
|
2065
2100
|
// A cleanup error collected before the halt is dropped (owner.ts).
|
|
2066
2101
|
rethrowCleanupError(true);
|
|
2067
|
-
let message =
|
|
2102
|
+
let message = HALTED;
|
|
2068
2103
|
{
|
|
2069
2104
|
message +=
|
|
2070
2105
|
" An uncaught error halted the reactive system. No further updates will be processed. Handle errors with <Errored> or treat this as a crash.";
|
|
@@ -2290,11 +2325,12 @@ class GlobalQueue {
|
|
|
2290
2325
|
// This flush's own runs, the lanes' reveals, and the landings' held runs
|
|
2291
2326
|
// are collected apart and ordered below.
|
|
2292
2327
|
const own = this._queues;
|
|
2293
|
-
const lanes =
|
|
2328
|
+
const lanes = [[], []];
|
|
2294
2329
|
// The passes that read this frame's stagings as the screen read held
|
|
2295
2330
|
// writes if it parked: the lane seam re-derives them on the committed
|
|
2296
2331
|
// world (a lane's runs wait this round).
|
|
2297
2332
|
if (laneSeamsHook) {
|
|
2333
|
+
this._queues = lanes;
|
|
2298
2334
|
laneSeamsHook(t !== null ? stagedReaders : null);
|
|
2299
2335
|
if (stagedReaders.length) stagedReaders.length = 0;
|
|
2300
2336
|
}
|
|
@@ -2421,8 +2457,9 @@ class GlobalQueue {
|
|
|
2421
2457
|
* or without the held read) owes nothing. A run this transaction stashed
|
|
2422
2458
|
* for it is void (#3322: an effect has one value slot, and the stale pass
|
|
2423
2459
|
* overwrote the value that run was for) — the re-derivation's run replaces
|
|
2424
|
-
* it. */
|
|
2460
|
+
* it. Truthy when an effect re-derives (`land`). */
|
|
2425
2461
|
function reruns(u) {
|
|
2462
|
+
let frame;
|
|
2426
2463
|
for (let i = 0; i < u._reruns.length; i++) {
|
|
2427
2464
|
const r = u._reruns[i];
|
|
2428
2465
|
// An errored reader's display is its error (D-39): the landing gives it
|
|
@@ -2430,6 +2467,7 @@ function reruns(u) {
|
|
|
2430
2467
|
// errored source (#3945).
|
|
2431
2468
|
if (r._flags & REACTIVE_DISPOSED || r._statusFlags & STATUS_ERROR) continue;
|
|
2432
2469
|
if (r._flags & REACTIVE_FRAME_READ || r._config & CONFIG_VERDICT) {
|
|
2470
|
+
frame ||= r._type;
|
|
2433
2471
|
r._flags &= ~REACTIVE_FRAME_READ;
|
|
2434
2472
|
r._modified = false;
|
|
2435
2473
|
// Its frame is replaced by the re-derivation: a run one of its
|
|
@@ -2440,14 +2478,15 @@ function reruns(u) {
|
|
|
2440
2478
|
}
|
|
2441
2479
|
}
|
|
2442
2480
|
u._reruns.length = 0;
|
|
2481
|
+
return frame;
|
|
2443
2482
|
}
|
|
2444
2483
|
/** The landing: the held frame becomes the frame. */
|
|
2445
2484
|
function land(u) {
|
|
2446
2485
|
// Attribution hook: judged complete — its held writes commit next
|
|
2447
2486
|
// (`_nodes` still lists them).
|
|
2448
2487
|
if (attrHooks !== null) attrHooks.transitionSettled(u);
|
|
2449
|
-
reruns(u);
|
|
2450
|
-
if (u._marks !== null) releaseMarksHook(u._marks);
|
|
2488
|
+
const frame = reruns(u);
|
|
2489
|
+
if (releaseMarksHook && u._marks !== null) releaseMarksHook(u._marks);
|
|
2451
2490
|
// Old children die in the commits (cleanups first), then the stashed
|
|
2452
2491
|
// effects run ahead of this flush's own. A node a lane took over since
|
|
2453
2492
|
// (a guess written over the staged truth) is the lane's to land.
|
|
@@ -2461,7 +2500,16 @@ function land(u) {
|
|
|
2461
2500
|
// `u`, which has left `transactions`: the write is this landing's, and
|
|
2462
2501
|
// the next flush must not park in it (#4089).
|
|
2463
2502
|
if (flushTransaction === u) flushTransaction = null;
|
|
2464
|
-
|
|
2503
|
+
// An effect re-derives next round (`reruns`): the held runs wait for it
|
|
2504
|
+
// (D-9, the A15 reveal corollary, #4071). Its re-derivation can discover a
|
|
2505
|
+
// flight — a stale reader whose mainline pass stopped reading it, now
|
|
2506
|
+
// reading the landed world — and a landing that showed its runs first
|
|
2507
|
+
// would reveal the held write beside a frame that can only show its old
|
|
2508
|
+
// value. Queued last in this effect phase, the release hands them to the
|
|
2509
|
+
// next round's own runs, ahead of the re-derivation's: they show with it,
|
|
2510
|
+
// or park with it in the hold its pending opens. The commits stand.
|
|
2511
|
+
if (frame) globalQueue._queues[1].push(() => releaseQueues(u));
|
|
2512
|
+
else releaseQueues(u);
|
|
2465
2513
|
}
|
|
2466
2514
|
/** The held runs join this flush's effect phase after its own runs (the
|
|
2467
2515
|
* landing's re-passes, in height order): the frame's effects run as one
|
|
@@ -2720,8 +2768,22 @@ function flush(fn) {
|
|
|
2720
2768
|
// (owner.ts).
|
|
2721
2769
|
rethrowCleanupError();
|
|
2722
2770
|
}
|
|
2771
|
+
/** Dev-only: the DOM event current when the running effect queue started,
|
|
2772
|
+
* or `ANY_EVENT` outside one. Read once per queue rather than once per
|
|
2773
|
+
* effect (the getter is costly under jsdom); no event starts or ends between
|
|
2774
|
+
* two effects of one synchronous queue (#4235). */
|
|
2775
|
+
let queueEvent = ANY_EVENT;
|
|
2723
2776
|
function runQueue(queue, type) {
|
|
2724
|
-
|
|
2777
|
+
{
|
|
2778
|
+
const prev = queueEvent;
|
|
2779
|
+
queueEvent = dispatchingEvent();
|
|
2780
|
+
try {
|
|
2781
|
+
for (let i = 0; i < queue.length; i++) queue[i](type);
|
|
2782
|
+
} finally {
|
|
2783
|
+
queueEvent = prev;
|
|
2784
|
+
}
|
|
2785
|
+
return;
|
|
2786
|
+
}
|
|
2725
2787
|
}
|
|
2726
2788
|
|
|
2727
2789
|
/**
|
|
@@ -2943,7 +3005,7 @@ function unobserved(el) {
|
|
|
2943
3005
|
* reclamation still happens within one microtask — the enqueue site arms
|
|
2944
3006
|
* schedule(), so a flush is guaranteed even when no other work is queued.
|
|
2945
3007
|
*/
|
|
2946
|
-
const dormantNodes = new
|
|
3008
|
+
const dormantNodes = new NewSet();
|
|
2947
3009
|
function sweepDormant() {
|
|
2948
3010
|
if (dormantNodes.size === 0) return;
|
|
2949
3011
|
for (const el of dormantNodes) {
|
|
@@ -3011,7 +3073,7 @@ function link(dep, sub) {
|
|
|
3011
3073
|
// to clear it, stranding the Set members' pending forever (#2893).
|
|
3012
3074
|
function addPendingSource(el, source) {
|
|
3013
3075
|
if (el._x?._pendingSources?.has(source)) return false;
|
|
3014
|
-
(ext(el)._pendingSources ??= new
|
|
3076
|
+
(ext(el)._pendingSources ??= new NewSet()).add(source);
|
|
3015
3077
|
return true;
|
|
3016
3078
|
}
|
|
3017
3079
|
function removePendingSource(el, source) {
|
|
@@ -3094,7 +3156,7 @@ function releaseIfSettledUnobserved(node) {
|
|
|
3094
3156
|
// Collect-then-release so unobserved() never unlinks under the walk.
|
|
3095
3157
|
function releaseSettledDependents(el) {
|
|
3096
3158
|
let candidates;
|
|
3097
|
-
const visited = new
|
|
3159
|
+
const visited = new NewSet();
|
|
3098
3160
|
const visit = node => {
|
|
3099
3161
|
if (visited.has(node)) return;
|
|
3100
3162
|
visited.add(node);
|
|
@@ -3160,7 +3222,7 @@ function stageError(el, error, inPass) {
|
|
|
3160
3222
|
}
|
|
3161
3223
|
function settleErroredDependents(el, error) {
|
|
3162
3224
|
let scheduled = false;
|
|
3163
|
-
const visited = new
|
|
3225
|
+
const visited = new NewSet();
|
|
3164
3226
|
const visit = node => {
|
|
3165
3227
|
if (visited.has(node)) return;
|
|
3166
3228
|
visited.add(node);
|
|
@@ -3237,7 +3299,7 @@ function settlePendingSource(el, source = el) {
|
|
|
3237
3299
|
removePendingSource(el, source);
|
|
3238
3300
|
let scheduled = false;
|
|
3239
3301
|
let released;
|
|
3240
|
-
const visited = new
|
|
3302
|
+
const visited = new NewSet();
|
|
3241
3303
|
const settle = node => {
|
|
3242
3304
|
if (
|
|
3243
3305
|
visited.has(node) ||
|
|
@@ -3304,6 +3366,37 @@ function releaseFlightTeardown(el) {
|
|
|
3304
3366
|
teardown();
|
|
3305
3367
|
}
|
|
3306
3368
|
}
|
|
3369
|
+
/**
|
|
3370
|
+
* Internal (not a package export): run `fn` when the current pass's flight
|
|
3371
|
+
* is superseded, at the same instant as the iterator close above, instead of
|
|
3372
|
+
* when the replacing pass commits (owner cleanups wait for that). Chains onto
|
|
3373
|
+
* the node's teardown slot; fires once with it. A no-op unless the ambient
|
|
3374
|
+
* owner is a computed in its own pass. `consumeIterator` fills the slot
|
|
3375
|
+
* before its first pull, so a source opened in an async generator's body
|
|
3376
|
+
* (`for await`) composes after the generator's close.
|
|
3377
|
+
*/
|
|
3378
|
+
function onSupersede(fn) {
|
|
3379
|
+
const el = context;
|
|
3380
|
+
if (el === null || el._fn === undefined || !(el._flags & REACTIVE_RECOMPUTING_DEPS)) return;
|
|
3381
|
+
const fresh = el._x === null;
|
|
3382
|
+
const x = ext(el);
|
|
3383
|
+
// Allocating the extension mid-run turns `_x?._inFlight` from undefined into
|
|
3384
|
+
// null, which recompute would read as a flight this body registered itself.
|
|
3385
|
+
// Restore undefined here, so the fix costs nothing for code that never
|
|
3386
|
+
// calls onSupersede.
|
|
3387
|
+
if (fresh) x._inFlight = undefined;
|
|
3388
|
+
const prev = x._flightTeardown;
|
|
3389
|
+
x._flightTeardown =
|
|
3390
|
+
prev === null
|
|
3391
|
+
? fn
|
|
3392
|
+
: () => {
|
|
3393
|
+
try {
|
|
3394
|
+
prev();
|
|
3395
|
+
} finally {
|
|
3396
|
+
fn();
|
|
3397
|
+
}
|
|
3398
|
+
};
|
|
3399
|
+
}
|
|
3307
3400
|
function handleAsync(
|
|
3308
3401
|
el,
|
|
3309
3402
|
result,
|
|
@@ -3407,8 +3500,14 @@ function handleAsync(
|
|
|
3407
3500
|
// D-41: a held node's error is staged (`stageError`). A derived store's
|
|
3408
3501
|
// readers learn its error through the family, not the derive's
|
|
3409
3502
|
// dependents: it publishes now.
|
|
3410
|
-
if (stillPending || setter || !stageError(el, error))
|
|
3503
|
+
if (stillPending || setter || !stageError(el, error)) {
|
|
3411
3504
|
notifyStatus(el, stillPending ? STATUS_PENDING : STATUS_ERROR, error);
|
|
3505
|
+
// The error is this pass's answer, published now: it replaces the shown
|
|
3506
|
+
// frame as a value's commit would (`commitPendingNode`), so the frame
|
|
3507
|
+
// the pass parked goes instead of waiting for a later success. A no-op
|
|
3508
|
+
// when nothing is parked.
|
|
3509
|
+
if (!stillPending) disposeChildren(el, false, true);
|
|
3510
|
+
}
|
|
3412
3511
|
// A NotReady rejection is a landing into another pending source. The
|
|
3413
3512
|
// rejected flight will never settle its self entry, so transfer ownership
|
|
3414
3513
|
// after notifyStatus has propagated the replacement source.
|
|
@@ -3440,8 +3539,14 @@ function handleAsync(
|
|
|
3440
3539
|
return;
|
|
3441
3540
|
}
|
|
3442
3541
|
// A store derive's landing commits through its setter: unheld, the
|
|
3443
|
-
// shown error leaves now
|
|
3444
|
-
|
|
3542
|
+
// shown error leaves now, and so does a commit-beneath-a-flight's
|
|
3543
|
+
// CONFIG_INPUTS_PUBLISHED (its first flight's, #4269) — left standing,
|
|
3544
|
+
// a verdict reader of the next flight would suspend instead of being
|
|
3545
|
+
// served the screen; held, both at the derive's commit.
|
|
3546
|
+
if (!(el._config & CONFIG_HELD)) {
|
|
3547
|
+
el._x._shownError = undefined;
|
|
3548
|
+
el._config &= ~CONFIG_INPUTS_PUBLISHED;
|
|
3549
|
+
}
|
|
3445
3550
|
if (wasUninitialized) landStatus(el, true);
|
|
3446
3551
|
// Attribution hook: this path landed through the setter (derived
|
|
3447
3552
|
// stores, projections), which does not go through setSignal, so the
|
|
@@ -3523,7 +3628,11 @@ function handleAsync(
|
|
|
3523
3628
|
cleanup(close, owner);
|
|
3524
3629
|
// Flight-identity cancellation (#3122): the registration above is the
|
|
3525
3630
|
// owner-death backstop; the teardown slot fires at the _inFlight release
|
|
3526
|
-
// sites so supersede stops this stream immediately.
|
|
3631
|
+
// sites so supersede stops this stream immediately. Assigned, not
|
|
3632
|
+
// chained (chaining here costs every app bytes): it replaces any
|
|
3633
|
+
// `onSupersede` teardown this run registered earlier, which then falls
|
|
3634
|
+
// back to the owner-cleanup channel. A returned `from()` is unaffected:
|
|
3635
|
+
// `close` calls its `return()`, which runs its own teardown.
|
|
3527
3636
|
ext(el)._flightTeardown = close;
|
|
3528
3637
|
// Release check before each next pull: an unobserved lazy node must tear
|
|
3529
3638
|
// down (its close above runs via disposal, closing the iterator) instead
|
|
@@ -3686,12 +3795,12 @@ function handleAsync(
|
|
|
3686
3795
|
handleError(syncError);
|
|
3687
3796
|
throw syncError;
|
|
3688
3797
|
} else if (!resolved) {
|
|
3689
|
-
//
|
|
3690
|
-
// work on a loadingValue node is
|
|
3691
|
-
// boundaries
|
|
3692
|
-
// lands through asyncWrite.
|
|
3693
|
-
|
|
3694
|
-
|
|
3798
|
+
// Not landed: the shared tail below suspends, or — loading window —
|
|
3799
|
+
// serves commit #0 (first-flight work on a loadingValue node is
|
|
3800
|
+
// loading-class, invisible to boundaries; the flight itself is already
|
|
3801
|
+
// registered in _inFlight and lands through asyncWrite). A promise is
|
|
3802
|
+
// never an iterator, so nothing between here and there runs.
|
|
3803
|
+
liveLanded = false;
|
|
3695
3804
|
} else if (!flattenIfIterable(syncValue)) {
|
|
3696
3805
|
// Synchronously-resolved promise: the first real answer landed.
|
|
3697
3806
|
el._loading = false;
|
|
@@ -3703,7 +3812,7 @@ function handleAsync(
|
|
|
3703
3812
|
if (iterator) flattenIfIterable(result);
|
|
3704
3813
|
if (liveLanded !== null) {
|
|
3705
3814
|
if (!liveLanded) {
|
|
3706
|
-
// Loading window: serve commit #0
|
|
3815
|
+
// Loading window: serve commit #0 instead of suspending.
|
|
3707
3816
|
if (el._loading) return el._value;
|
|
3708
3817
|
throw new NotReadyError(context);
|
|
3709
3818
|
}
|
|
@@ -3715,7 +3824,7 @@ function handleAsync(
|
|
|
3715
3824
|
}
|
|
3716
3825
|
function clearStatus(el, clearUninitialized = false) {
|
|
3717
3826
|
if (el._x?._pendingSources) clearPendingSources(el);
|
|
3718
|
-
if (el._x?._blocked)
|
|
3827
|
+
if (el._x?._blocked) el._x._blocked = false;
|
|
3719
3828
|
el._statusFlags = clearUninitialized ? 0 : el._statusFlags & STATUS_UNINITIALIZED;
|
|
3720
3829
|
if (el._x?._error) setPendingError(el);
|
|
3721
3830
|
const notify = statusNotifierOf(el);
|
|
@@ -3755,7 +3864,7 @@ function landStatus(el, clearUninitialized = false) {
|
|
|
3755
3864
|
setPendingError(el, sources.values().next().value);
|
|
3756
3865
|
} else clearStatus(el, clearUninitialized);
|
|
3757
3866
|
}
|
|
3758
|
-
function notifyStatus(el, status, error
|
|
3867
|
+
function notifyStatus(el, status, error) {
|
|
3759
3868
|
// Wrap regular errors to track source node
|
|
3760
3869
|
if (
|
|
3761
3870
|
status === STATUS_ERROR &&
|
|
@@ -3766,21 +3875,33 @@ function notifyStatus(el, status, error, blockStatus) {
|
|
|
3766
3875
|
const pendingSource =
|
|
3767
3876
|
status === STATUS_PENDING && error instanceof NotReadyError ? error.source : undefined;
|
|
3768
3877
|
// (CARVE 2: the lane assignment went with the engine.)
|
|
3769
|
-
{
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
|
|
3783
|
-
|
|
3878
|
+
if (status === STATUS_PENDING && pendingSource) {
|
|
3879
|
+
// D-41: a re-ask of a shown error keeps it the display (`_shownError`).
|
|
3880
|
+
if (el._statusFlags & STATUS_ERROR) el._x._shownError = el._x._error;
|
|
3881
|
+
addPendingSource(el, pendingSource);
|
|
3882
|
+
// A re-ask of an error that answered the first read: still no value.
|
|
3883
|
+
el._statusFlags =
|
|
3884
|
+
STATUS_PENDING |
|
|
3885
|
+
(el._statusFlags & STATUS_NO_VALUE
|
|
3886
|
+
? STATUS_UNINITIALIZED
|
|
3887
|
+
: el._statusFlags & STATUS_UNINITIALIZED);
|
|
3888
|
+
// Preserve the current source on this propagation so readers park on
|
|
3889
|
+
// the distinct pending source.
|
|
3890
|
+
setPendingError(el, pendingSource, error);
|
|
3891
|
+
} else {
|
|
3892
|
+
clearPendingSources(el);
|
|
3893
|
+
// An error answering a node with no value marks it so; a re-ask of it
|
|
3894
|
+
// (pending) is uninitialized again; a write (STATUS_NONE) gives it one.
|
|
3895
|
+
el._statusFlags =
|
|
3896
|
+
status |
|
|
3897
|
+
(status === STATUS_ERROR
|
|
3898
|
+
? el._statusFlags & (STATUS_UNINITIALIZED | STATUS_NO_VALUE)
|
|
3899
|
+
? STATUS_NO_VALUE
|
|
3900
|
+
: 0
|
|
3901
|
+
: status === STATUS_PENDING && el._statusFlags & STATUS_NO_VALUE
|
|
3902
|
+
? STATUS_UNINITIALIZED
|
|
3903
|
+
: el._statusFlags & STATUS_UNINITIALIZED);
|
|
3904
|
+
ext(el)._error = error;
|
|
3784
3905
|
}
|
|
3785
3906
|
// Lanes: a written guess is an optimistic boundary (A17 — "the optimistic
|
|
3786
3907
|
// future value until we know otherwise"). Its own source in flight is its
|
|
@@ -3794,9 +3915,7 @@ function notifyStatus(el, status, error, blockStatus) {
|
|
|
3794
3915
|
}
|
|
3795
3916
|
const elNotify = statusNotifierOf(el);
|
|
3796
3917
|
if (elNotify) {
|
|
3797
|
-
|
|
3798
|
-
elNotify.call(el);
|
|
3799
|
-
}
|
|
3918
|
+
elNotify.call(el);
|
|
3800
3919
|
return;
|
|
3801
3920
|
}
|
|
3802
3921
|
propagateStatus(el, status, error);
|
|
@@ -3806,7 +3925,7 @@ function notifyStatus(el, status, error, blockStatus) {
|
|
|
3806
3925
|
* family's leaves, which are not the derive's dependents — the family
|
|
3807
3926
|
* propagates the derive's status from each leaf to the leaf's readers
|
|
3808
3927
|
* (store/projection.ts `wakeFamily`), exactly as a memo's would reach its. */
|
|
3809
|
-
function propagateStatus(el, status, error
|
|
3928
|
+
function propagateStatus(el, status, error) {
|
|
3810
3929
|
const pendingSource =
|
|
3811
3930
|
status === STATUS_PENDING && error instanceof NotReadyError ? error.source : undefined;
|
|
3812
3931
|
forEachDependent(el, (sub, link) => {
|
|
@@ -3863,25 +3982,26 @@ function propagateStatus(el, status, error, downstreamBlockStatus) {
|
|
|
3863
3982
|
// bookkeeping (loading window, uninitialized clear) runs with the flush
|
|
3864
3983
|
// — with the lane, when the pass propagating is the lane's work and
|
|
3865
3984
|
// the dependent's pending is the lane's own flight (`laneStage`).
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
)
|
|
3881
|
-
joinFuture(txOf(sub));
|
|
3882
|
-
}
|
|
3985
|
+
// (No answer: a pending propagation leaves a written guess a guess.)
|
|
3986
|
+
if (laneStageHook && passLane !== null) laneStageHook(sub, passLane, true, el);
|
|
3987
|
+
else {
|
|
3988
|
+
queuePendingNode(sub);
|
|
3989
|
+
// A15 (#3443): pending propagates onto a held memo without
|
|
3990
|
+
// recomputing it, and the propagation itself enters the memo's
|
|
3991
|
+
// transaction — the flight flows into a memo that transaction
|
|
3992
|
+
// holds, so the write that started it is held with it. A render
|
|
3993
|
+
// effect's membership is its pass's (`notify`), never sticky.
|
|
3994
|
+
if (
|
|
3995
|
+
status === STATUS_PENDING &&
|
|
3996
|
+
(sub._config & (CONFIG_HELD | CONFIG_OVERRIDE)) === CONFIG_HELD &&
|
|
3997
|
+
!sub._type
|
|
3998
|
+
)
|
|
3999
|
+
joinFuture(txOf(sub));
|
|
3883
4000
|
}
|
|
3884
4001
|
notifyStatus(sub, status, error);
|
|
4002
|
+
// A derived store's derive (store/projection.ts): marked, not re-run —
|
|
4003
|
+
// its leaves' readers are not its dependents, so the family walks them.
|
|
4004
|
+
sub.fam?.st(status);
|
|
3885
4005
|
}
|
|
3886
4006
|
});
|
|
3887
4007
|
}
|
|
@@ -3945,7 +4065,11 @@ const PRIMITIVE_IN_EFFECT_CALLBACK_MESSAGE =
|
|
|
3945
4065
|
* created there is inert and harmless. Tracked effects and onSettled are
|
|
3946
4066
|
* children-forbidden and refuse through PRIMITIVE_IN_FORBIDDEN_SCOPE. */
|
|
3947
4067
|
function assertNotInEffectCallback() {
|
|
3948
|
-
if (
|
|
4068
|
+
if (
|
|
4069
|
+
inEffectCallback &&
|
|
4070
|
+
context === null &&
|
|
4071
|
+
(effectCallbackEvent === ANY_EVENT || dispatchingEvent() === effectCallbackEvent)
|
|
4072
|
+
) {
|
|
3949
4073
|
emitDiagnostic({
|
|
3950
4074
|
code: "PRIMITIVE_IN_EFFECT_CALLBACK",
|
|
3951
4075
|
kind: "lifecycle",
|
|
@@ -3978,10 +4102,25 @@ function ownerInSnapshotScope(owner) {
|
|
|
3978
4102
|
}
|
|
3979
4103
|
function setSnapshotCapture(active) {
|
|
3980
4104
|
snapshotCaptureActive = active;
|
|
3981
|
-
if (active && !snapshotSources) snapshotSources = new
|
|
4105
|
+
if (active && !snapshotSources) snapshotSources = new NewSet();
|
|
3982
4106
|
}
|
|
3983
|
-
|
|
3984
|
-
|
|
4107
|
+
/**
|
|
4108
|
+
* Marks `owner` a snapshot scope: while capture is on, the readers created
|
|
4109
|
+
* under it serve each source's snapshot (the value it had when hydration
|
|
4110
|
+
* began) and replay at `releaseSnapshotScope`.
|
|
4111
|
+
*
|
|
4112
|
+
* With `served` (hydration), `owner` is instead a hydrated computed and
|
|
4113
|
+
* `served` its server answer — what the server rendered every reader of the
|
|
4114
|
+
* node with — landing after the node was created pending (so the creation
|
|
4115
|
+
* arm skipped it). It becomes the node's snapshot when it has none, whether
|
|
4116
|
+
* the node committed the answer or a client write had already taken its
|
|
4117
|
+
* compute over. A claim made later reads the value its markup shows, and
|
|
4118
|
+
* replays the node's own value at its release, as for a written signal.
|
|
4119
|
+
*/
|
|
4120
|
+
function markSnapshotScope(owner, served) {
|
|
4121
|
+
if (arguments.length < 2) owner._snapshotScope = true;
|
|
4122
|
+
else if (snapshotCaptureActive && owner._x?._snapshotValue === undefined)
|
|
4123
|
+
takeSnapshot(owner, served);
|
|
3985
4124
|
}
|
|
3986
4125
|
function releaseSnapshotScope(owner) {
|
|
3987
4126
|
owner._snapshotScope = false;
|
|
@@ -4094,6 +4233,8 @@ function recompute(el, create = false) {
|
|
|
4094
4233
|
// A29, or mounted by a pass of it still awaiting its commit, #4010) keeps
|
|
4095
4234
|
// staging: live writes keep it current, it effects at the swap (ruling
|
|
4096
4235
|
// A).
|
|
4236
|
+
// A boundary's structure (CONFIG_FRAME) is the frame like a render
|
|
4237
|
+
// effect: it publishes mainline outside its transaction's flush (#4283).
|
|
4097
4238
|
// A pending flight is the transition's own work (#3884). A probe on an
|
|
4098
4239
|
// earlier pass left CONFIG_VERDICT, and a frame read here would serve the
|
|
4099
4240
|
// committed screen, settle the flight and drop the hold — a superseding
|
|
@@ -4107,8 +4248,10 @@ function recompute(el, create = false) {
|
|
|
4107
4248
|
// world (`read`), and has left it otherwise.
|
|
4108
4249
|
// An answered deferred node's re-pass is a lagging question (D-40):
|
|
4109
4250
|
// it joins nothing, so the write that reached it commits mainline.
|
|
4251
|
+
// `EFFECT_RENDER << 23` is CONFIG_FRAME (a render effect, a boundary's
|
|
4252
|
+
// tree and output), spelled from the effect type as at creation.
|
|
4110
4253
|
if (tx._lane || el._config & CONFIG_LAGS);
|
|
4111
|
-
else if (
|
|
4254
|
+
else if (!(el._config & (CONFIG_VERDICT | (EFFECT_RENDER << 23))))
|
|
4112
4255
|
joinPassTx(tx, freshHook?.(el, el._statusFlags & STATUS_UNINITIALIZED));
|
|
4113
4256
|
else if (
|
|
4114
4257
|
tx !== flushTransaction &&
|
|
@@ -4120,8 +4263,10 @@ function recompute(el, create = false) {
|
|
|
4120
4263
|
// after the new frame's first runs, and the held pass's own
|
|
4121
4264
|
// children die below (`disposeChildren`). The landing re-derives a
|
|
4122
4265
|
// fresh held frame for the reveal (`_reruns`).
|
|
4266
|
+
// Not held any more, whichever frame reader it is: its readers read
|
|
4267
|
+
// the value this pass publishes.
|
|
4123
4268
|
el._pendingValue = NOT_PENDING;
|
|
4124
|
-
|
|
4269
|
+
el._config &= ~CONFIG_HELD;
|
|
4125
4270
|
}
|
|
4126
4271
|
}
|
|
4127
4272
|
// The previous pass's frame. If that pass is still awaiting its commit
|
|
@@ -4405,7 +4550,9 @@ function recompute(el, create = false) {
|
|
|
4405
4550
|
// confirm is a landing too — the lane's end commits it) and notifies
|
|
4406
4551
|
// only a correction: an equal truth re-runs nothing (lanes.ts). (As the
|
|
4407
4552
|
// lane's own work the lane judged it — `laneStage`.)
|
|
4553
|
+
// (The hook first: a build without lanes folds the arm away.)
|
|
4408
4554
|
if (
|
|
4555
|
+
laneOutcomeHook &&
|
|
4409
4556
|
!create &&
|
|
4410
4557
|
lane === null &&
|
|
4411
4558
|
el._config & CONFIG_GUESS &&
|
|
@@ -4776,13 +4923,18 @@ function frameRead(c, el) {
|
|
|
4776
4923
|
// read the screen. Lane work with no committed value yet reads a flight
|
|
4777
4924
|
// as a mount's memo does: it enters, and the boundary it mounts catches
|
|
4778
4925
|
// the pending (#3540).
|
|
4926
|
+
// A boundary's tree and output (CONFIG_FRAME) read as a render effect
|
|
4927
|
+
// does: structure, not a derivation of what it shows (#4283). A mount
|
|
4928
|
+
// under a hold still enters it: the content memo it reads is born held,
|
|
4929
|
+
// with no committed value to serve.
|
|
4779
4930
|
// (Verdict readers and lanes exist only with their engines installed.)
|
|
4780
4931
|
const verdict = observeFlightHook && c._config & CONFIG_VERDICT;
|
|
4781
4932
|
const lane = laneStageHook && passLane !== null;
|
|
4782
4933
|
if (
|
|
4783
4934
|
(!lane || (c._statusFlags & STATUS_UNINITIALIZED && el._statusFlags & STATUS_PENDING)) &&
|
|
4784
4935
|
!verdict &&
|
|
4785
|
-
|
|
4936
|
+
// CONFIG_FRAME, spelled as at the effect's creation.
|
|
4937
|
+
(!(c._config & (EFFECT_RENDER << 23)) || el._config & CONFIG_INPUTS_PUBLISHED)
|
|
4786
4938
|
)
|
|
4787
4939
|
return false;
|
|
4788
4940
|
const t = txOf(el);
|
|
@@ -4839,6 +4991,9 @@ function createEffectNode(fn, effectFn, errorFn, type, options) {
|
|
|
4839
4991
|
const self = {
|
|
4840
4992
|
id: inheritId(options, transparent, context),
|
|
4841
4993
|
_config:
|
|
4994
|
+
// CONFIG_FRAME for a render effect (EFFECT_RENDER = 1; a user
|
|
4995
|
+
// effect's 1 << 24 is unused).
|
|
4996
|
+
(type << 23) |
|
|
4842
4997
|
(transparent ? CONFIG_TRANSPARENT : 0) |
|
|
4843
4998
|
(options?.ownedWrite ? CONFIG_OWNED_WRITE : 0) |
|
|
4844
4999
|
(options?.sync ? CONFIG_SYNC : 0) |
|
|
@@ -4907,7 +5062,7 @@ function setEffectStatusNotify(fn) {
|
|
|
4907
5062
|
* Presence doubles as the "display consumer" membership test in the status
|
|
4908
5063
|
* walks, exactly as the per-node field did when every effect carried one. */
|
|
4909
5064
|
function statusNotifierOf(el) {
|
|
4910
|
-
return el._type ?
|
|
5065
|
+
return el._type ? effectStatusNotify : null;
|
|
4911
5066
|
}
|
|
4912
5067
|
const lazyOptions = { lazy: true };
|
|
4913
5068
|
function setupComputedNode(self, options) {
|
|
@@ -4931,11 +5086,8 @@ function setupComputedNode(self, options) {
|
|
|
4931
5086
|
wireExternalSourceHook?.(self);
|
|
4932
5087
|
!options?.lazy && recompute(self, true);
|
|
4933
5088
|
if (snapshotCaptureActive && !options?.lazy) {
|
|
4934
|
-
if (!(self._statusFlags & STATUS_PENDING) && !(self._config & CONFIG_NO_SNAPSHOT))
|
|
4935
|
-
|
|
4936
|
-
self._config |= CONFIG_HAS_SNAPSHOT;
|
|
4937
|
-
snapshotSources.add(self);
|
|
4938
|
-
}
|
|
5089
|
+
if (!(self._statusFlags & STATUS_PENDING) && !(self._config & CONFIG_NO_SNAPSHOT))
|
|
5090
|
+
takeSnapshot(self, self._value);
|
|
4939
5091
|
}
|
|
4940
5092
|
}
|
|
4941
5093
|
function signal(v, options) {
|
|
@@ -4961,11 +5113,7 @@ function signal(v, options) {
|
|
|
4961
5113
|
};
|
|
4962
5114
|
s._internal = false;
|
|
4963
5115
|
if (options?.unobserved) ext(s)._unobserved = options.unobserved;
|
|
4964
|
-
if (snapshotCaptureActive && !(s._config & CONFIG_NO_SNAPSHOT))
|
|
4965
|
-
ext(s)._snapshotValue = v === undefined ? NO_SNAPSHOT : v;
|
|
4966
|
-
s._config |= CONFIG_HAS_SNAPSHOT;
|
|
4967
|
-
snapshotSources.add(s);
|
|
4968
|
-
}
|
|
5116
|
+
if (snapshotCaptureActive && !(s._config & CONFIG_NO_SNAPSHOT)) takeSnapshot(s, v);
|
|
4969
5117
|
return s;
|
|
4970
5118
|
}
|
|
4971
5119
|
function isEqual(a, b) {
|
|
@@ -5056,11 +5204,31 @@ function exitDisposal() {
|
|
|
5056
5204
|
function resetDisposalDepth() {
|
|
5057
5205
|
disposalDepth = 0;
|
|
5058
5206
|
}
|
|
5059
|
-
|
|
5207
|
+
/**
|
|
5208
|
+
* Dev-only: the DOM event being dispatched when the open strict-read window
|
|
5209
|
+
* opened (`globalThis.event`; null between dispatches and off the main
|
|
5210
|
+
* thread's Window), or `ANY_EVENT` when the window did not record one. A DOM
|
|
5211
|
+
* call made in an effect callback that dispatches events synchronously
|
|
5212
|
+
* (`el.focus()`, `el.click()`, `dialog.showModal()`) runs that event's
|
|
5213
|
+
* handlers inside the window; a handler is a one-shot snapshot whoever
|
|
5214
|
+
* dispatched the event, so a read made while a different event is current is
|
|
5215
|
+
* outside the window (#4235). Only queued effect runs record the event, read
|
|
5216
|
+
* once per queue (the getter is costly under jsdom); `strictReadActive` is
|
|
5217
|
+
* the check.
|
|
5218
|
+
*/
|
|
5219
|
+
let strictReadEvent;
|
|
5220
|
+
// `?? null`: no current event must not read as a missing argument below.
|
|
5221
|
+
const dispatchingEvent = () => globalThis.event ?? null;
|
|
5222
|
+
function setStrictRead(v, event = ANY_EVENT) {
|
|
5060
5223
|
const prev = strictRead;
|
|
5061
5224
|
strictRead = v;
|
|
5225
|
+
strictReadEvent = event;
|
|
5062
5226
|
return prev;
|
|
5063
5227
|
}
|
|
5228
|
+
/** Dev-only: is the strict-read window open for a read made now? */
|
|
5229
|
+
function strictReadActive() {
|
|
5230
|
+
return !!strictRead && (strictReadEvent === ANY_EVENT || dispatchingEvent() === strictReadEvent);
|
|
5231
|
+
}
|
|
5064
5232
|
/**
|
|
5065
5233
|
* Runs `fn` outside of any reactive tracking — reads inside `fn` will not
|
|
5066
5234
|
* subscribe the current scope. Returns whatever `fn` returns.
|
|
@@ -5099,9 +5267,11 @@ function setStrictRead(v) {
|
|
|
5099
5267
|
function untrack(fn, strictReadLabel) {
|
|
5100
5268
|
const prevTracking = tracking;
|
|
5101
5269
|
const prevStrictRead = strictRead;
|
|
5270
|
+
const prevStrictReadEvent = strictReadEvent;
|
|
5102
5271
|
tracking = false;
|
|
5103
5272
|
{
|
|
5104
5273
|
strictRead = strictReadLabel || false;
|
|
5274
|
+
strictReadEvent = ANY_EVENT;
|
|
5105
5275
|
untrackDepth++;
|
|
5106
5276
|
}
|
|
5107
5277
|
try {
|
|
@@ -5111,6 +5281,7 @@ function untrack(fn, strictReadLabel) {
|
|
|
5111
5281
|
tracking = prevTracking;
|
|
5112
5282
|
{
|
|
5113
5283
|
strictRead = prevStrictRead;
|
|
5284
|
+
strictReadEvent = prevStrictReadEvent;
|
|
5114
5285
|
untrackDepth--;
|
|
5115
5286
|
}
|
|
5116
5287
|
}
|
|
@@ -5317,7 +5488,7 @@ function read(el) {
|
|
|
5317
5488
|
stagedRead(c);
|
|
5318
5489
|
return el._pendingValue;
|
|
5319
5490
|
}
|
|
5320
|
-
if (strictRead && owner._statusFlags & STATUS_PENDING)
|
|
5491
|
+
if (strictRead && owner._statusFlags & STATUS_PENDING && strictReadActive())
|
|
5321
5492
|
throwPendingUntrackedRead(strictRead, {
|
|
5322
5493
|
ownerId: c?.id,
|
|
5323
5494
|
ownerName: c?._name,
|
|
@@ -5359,6 +5530,28 @@ function read(el) {
|
|
|
5359
5530
|
const v = laneReadHook(c, el);
|
|
5360
5531
|
if (v !== NOT_PENDING) return v;
|
|
5361
5532
|
}
|
|
5533
|
+
// Ahead of the snapshot serve below: a component body's direct read is
|
|
5534
|
+
// wrong in the same way whether the pass is hydrating or not, and the
|
|
5535
|
+
// hydration pass is the console nobody is watching (#3675).
|
|
5536
|
+
if (strictRead && strictReadActive())
|
|
5537
|
+
warnStrictReadUntracked(strictRead, {
|
|
5538
|
+
ownerId: c?.id,
|
|
5539
|
+
ownerName: c?._name,
|
|
5540
|
+
nodeName: owner?._name
|
|
5541
|
+
});
|
|
5542
|
+
// A reader in a snapshot scope (a hydration claim) is served the value the
|
|
5543
|
+
// server rendered with: a client write's recompute still in flight does
|
|
5544
|
+
// not pull the claim off the markup it adopts — the reader replays at the
|
|
5545
|
+
// scope's release. An errored node throws below as for any reader.
|
|
5546
|
+
if (snapshotCaptureActive && c && c._config & CONFIG_IN_SNAPSHOT_SCOPE) {
|
|
5547
|
+
const sv = el._x?._snapshotValue;
|
|
5548
|
+
if (sv !== undefined && !(owner._statusFlags & STATUS_ERROR)) {
|
|
5549
|
+
const snapshot = sv === NO_SNAPSHOT ? undefined : sv;
|
|
5550
|
+
const current = el._pendingValue !== NOT_PENDING ? el._pendingValue : el._value;
|
|
5551
|
+
if (current !== snapshot) c._flags |= REACTIVE_SNAPSHOT_STALE;
|
|
5552
|
+
return snapshot;
|
|
5553
|
+
}
|
|
5554
|
+
}
|
|
5362
5555
|
// A stale reader of a held flight (rule 3, A15's reveal corollary) is served
|
|
5363
5556
|
// the committed value — coherent with the frame, whose inputs are the
|
|
5364
5557
|
// committed ones too — and does not go pending on it. So is lane work
|
|
@@ -5435,24 +5628,6 @@ function read(el) {
|
|
|
5435
5628
|
return read(el);
|
|
5436
5629
|
} else throw owner._x?._error;
|
|
5437
5630
|
}
|
|
5438
|
-
// Ahead of the snapshot serve below: a component body's direct read is
|
|
5439
|
-
// wrong in the same way whether the pass is hydrating or not, and the
|
|
5440
|
-
// hydration pass is the console nobody is watching (#3675).
|
|
5441
|
-
if (strictRead)
|
|
5442
|
-
warnStrictReadUntracked(strictRead, {
|
|
5443
|
-
ownerId: c?.id,
|
|
5444
|
-
ownerName: c?._name,
|
|
5445
|
-
nodeName: owner?._name
|
|
5446
|
-
});
|
|
5447
|
-
if (snapshotCaptureActive && c && c._config & CONFIG_IN_SNAPSHOT_SCOPE) {
|
|
5448
|
-
const sv = el._x?._snapshotValue;
|
|
5449
|
-
if (sv !== undefined) {
|
|
5450
|
-
const snapshot = sv === NO_SNAPSHOT ? undefined : sv;
|
|
5451
|
-
const current = el._pendingValue !== NOT_PENDING ? el._pendingValue : el._value;
|
|
5452
|
-
if (current !== snapshot) c._flags |= REACTIVE_SNAPSHOT_STALE;
|
|
5453
|
-
return snapshot;
|
|
5454
|
-
}
|
|
5455
|
-
}
|
|
5456
5631
|
if (committed) return el._value;
|
|
5457
5632
|
// D-41: an untracked read reads the screen, and a shown error is on it
|
|
5458
5633
|
// until the answer that replaces it commits.
|
|
@@ -5579,7 +5754,10 @@ function captureWriteSnapshot(el, current) {
|
|
|
5579
5754
|
el._x?._snapshotValue !== undefined
|
|
5580
5755
|
)
|
|
5581
5756
|
return;
|
|
5582
|
-
|
|
5757
|
+
takeSnapshot(el, current);
|
|
5758
|
+
}
|
|
5759
|
+
function takeSnapshot(el, value) {
|
|
5760
|
+
ext(el)._snapshotValue = value === undefined ? NO_SNAPSHOT : value;
|
|
5583
5761
|
el._config |= CONFIG_HAS_SNAPSHOT;
|
|
5584
5762
|
snapshotSources.add(el);
|
|
5585
5763
|
}
|
|
@@ -5836,13 +6014,13 @@ function markRefresh(node) {
|
|
|
5836
6014
|
}
|
|
5837
6015
|
|
|
5838
6016
|
export {
|
|
5839
|
-
|
|
6017
|
+
merge as $,
|
|
5840
6018
|
tracking as A,
|
|
5841
6019
|
CONFIG_CHILDREN_FORBIDDEN as B,
|
|
5842
6020
|
CONFIG_GUESS as C,
|
|
5843
6021
|
passLane as D,
|
|
5844
|
-
|
|
5845
|
-
|
|
6022
|
+
EFFECT_RENDER as E,
|
|
6023
|
+
setPassLane as F,
|
|
5846
6024
|
GlobalQueue as G,
|
|
5847
6025
|
sameLane as H,
|
|
5848
6026
|
flushTransaction as I,
|
|
@@ -5856,16 +6034,16 @@ export {
|
|
|
5856
6034
|
REACTIVE_CHECK as Q,
|
|
5857
6035
|
REACTIVE_DISPOSED as R,
|
|
5858
6036
|
STATUS_UNINITIALIZED as S,
|
|
5859
|
-
|
|
5860
|
-
|
|
5861
|
-
|
|
5862
|
-
|
|
5863
|
-
|
|
5864
|
-
|
|
5865
|
-
|
|
5866
|
-
|
|
6037
|
+
STATUS_PENDING as T,
|
|
6038
|
+
CONFIG_INPUTS_PUBLISHED as U,
|
|
6039
|
+
releaseQueues as V,
|
|
6040
|
+
CONFIG_SLOT_NODE as W,
|
|
6041
|
+
holdNode as X,
|
|
6042
|
+
joinFuture as Y,
|
|
6043
|
+
reruns as Z,
|
|
6044
|
+
CONFIG_STAGED as _,
|
|
5867
6045
|
NotReadyError as a,
|
|
5868
|
-
|
|
6046
|
+
resetUnhandledAsync as a$,
|
|
5869
6047
|
REACTIVE_JOINED as a0,
|
|
5870
6048
|
REACTIVE_STAGED_READ as a1,
|
|
5871
6049
|
stagedRead as a2,
|
|
@@ -5876,135 +6054,142 @@ export {
|
|
|
5876
6054
|
verdict as a7,
|
|
5877
6055
|
link as a8,
|
|
5878
6056
|
pullComputed as a9,
|
|
5879
|
-
|
|
5880
|
-
|
|
5881
|
-
|
|
5882
|
-
|
|
5883
|
-
|
|
5884
|
-
|
|
5885
|
-
|
|
5886
|
-
|
|
5887
|
-
|
|
5888
|
-
|
|
5889
|
-
|
|
5890
|
-
|
|
5891
|
-
|
|
5892
|
-
|
|
5893
|
-
|
|
5894
|
-
|
|
5895
|
-
|
|
5896
|
-
|
|
5897
|
-
|
|
5898
|
-
|
|
5899
|
-
|
|
5900
|
-
|
|
5901
|
-
|
|
5902
|
-
|
|
5903
|
-
|
|
5904
|
-
|
|
5905
|
-
|
|
6057
|
+
signal as aA,
|
|
6058
|
+
setSignal as aB,
|
|
6059
|
+
cleanup as aC,
|
|
6060
|
+
read as aD,
|
|
6061
|
+
DEV as aE,
|
|
6062
|
+
CONFIG_TRANSPARENT as aF,
|
|
6063
|
+
NoOwnerError as aG,
|
|
6064
|
+
ContextNotFoundError as aH,
|
|
6065
|
+
createEffectNode as aI,
|
|
6066
|
+
recompute as aJ,
|
|
6067
|
+
EFFECT_USER as aK,
|
|
6068
|
+
reportDiagnostic as aL,
|
|
6069
|
+
computed as aM,
|
|
6070
|
+
staleValues as aN,
|
|
6071
|
+
CONFIG_AUTO_DISPOSE as aO,
|
|
6072
|
+
EFFECT_TRACKED as aP,
|
|
6073
|
+
heldRunHook as aQ,
|
|
6074
|
+
unwrapStatusError as aR,
|
|
6075
|
+
setStrictRead as aS,
|
|
6076
|
+
queueEvent as aT,
|
|
6077
|
+
StatusError as aU,
|
|
6078
|
+
trimStaleDeps as aV,
|
|
6079
|
+
haltReactivityAt as aW,
|
|
6080
|
+
strictReadEvent as aX,
|
|
6081
|
+
setTrackedQueueCallback as aY,
|
|
6082
|
+
setEffectStatusNotify as aZ,
|
|
6083
|
+
_hitUnhandledAsync as a_,
|
|
5906
6084
|
strictRead as aa,
|
|
5907
|
-
|
|
5908
|
-
|
|
5909
|
-
|
|
5910
|
-
|
|
5911
|
-
|
|
5912
|
-
|
|
5913
|
-
|
|
5914
|
-
|
|
5915
|
-
|
|
5916
|
-
|
|
5917
|
-
|
|
5918
|
-
|
|
5919
|
-
|
|
5920
|
-
|
|
5921
|
-
|
|
5922
|
-
|
|
5923
|
-
|
|
5924
|
-
|
|
5925
|
-
|
|
5926
|
-
|
|
5927
|
-
|
|
5928
|
-
|
|
5929
|
-
|
|
5930
|
-
|
|
5931
|
-
|
|
6085
|
+
strictReadActive as ab,
|
|
6086
|
+
warnStrictReadUntracked as ac,
|
|
6087
|
+
staleReader as ad,
|
|
6088
|
+
globalQueue as ae,
|
|
6089
|
+
joinPass as af,
|
|
6090
|
+
markLateLinker as ag,
|
|
6091
|
+
spectating as ah,
|
|
6092
|
+
unflushedValue as ai,
|
|
6093
|
+
CONFIG_STAGED_ERROR as aj,
|
|
6094
|
+
stagedReaders as ak,
|
|
6095
|
+
bornInto as al,
|
|
6096
|
+
enterAction as am,
|
|
6097
|
+
setEffectCallback as an,
|
|
6098
|
+
exitAction as ao,
|
|
6099
|
+
isThenable as ap,
|
|
6100
|
+
actionDepth as aq,
|
|
6101
|
+
flush as ar,
|
|
6102
|
+
setQuestion as as,
|
|
6103
|
+
emitDiagnostic as at,
|
|
6104
|
+
enterCallback as au,
|
|
6105
|
+
exitCallback as av,
|
|
6106
|
+
getOwner as aw,
|
|
6107
|
+
inEffectCallback as ax,
|
|
6108
|
+
effectCallbackEvent as ay,
|
|
6109
|
+
setExternalHooks as az,
|
|
5932
6110
|
CONFIG_AUTHORITATIVE as b,
|
|
5933
|
-
|
|
5934
|
-
|
|
5935
|
-
|
|
5936
|
-
|
|
5937
|
-
|
|
5938
|
-
|
|
5939
|
-
|
|
5940
|
-
|
|
5941
|
-
|
|
5942
|
-
|
|
5943
|
-
|
|
5944
|
-
|
|
5945
|
-
|
|
5946
|
-
|
|
5947
|
-
|
|
5948
|
-
|
|
5949
|
-
|
|
5950
|
-
|
|
5951
|
-
|
|
5952
|
-
|
|
5953
|
-
|
|
5954
|
-
|
|
5955
|
-
|
|
5956
|
-
|
|
5957
|
-
|
|
5958
|
-
|
|
5959
|
-
|
|
5960
|
-
|
|
5961
|
-
|
|
5962
|
-
|
|
5963
|
-
|
|
5964
|
-
|
|
5965
|
-
|
|
5966
|
-
|
|
5967
|
-
|
|
5968
|
-
|
|
5969
|
-
|
|
5970
|
-
|
|
5971
|
-
|
|
5972
|
-
|
|
5973
|
-
|
|
5974
|
-
|
|
5975
|
-
|
|
5976
|
-
|
|
5977
|
-
|
|
5978
|
-
|
|
5979
|
-
|
|
5980
|
-
|
|
5981
|
-
|
|
5982
|
-
|
|
5983
|
-
|
|
5984
|
-
|
|
5985
|
-
|
|
5986
|
-
|
|
5987
|
-
|
|
5988
|
-
|
|
5989
|
-
|
|
5990
|
-
|
|
5991
|
-
|
|
5992
|
-
|
|
5993
|
-
|
|
5994
|
-
|
|
5995
|
-
|
|
5996
|
-
|
|
6111
|
+
peekNextChildId as b$,
|
|
6112
|
+
ROOT_ERROR_HOOK as b0,
|
|
6113
|
+
registerGraph as b1,
|
|
6114
|
+
runWithOwner as b2,
|
|
6115
|
+
setMemo as b3,
|
|
6116
|
+
$REFRESH as b4,
|
|
6117
|
+
markRefresh as b5,
|
|
6118
|
+
createRoot as b6,
|
|
6119
|
+
getObserver as b7,
|
|
6120
|
+
dispose as b8,
|
|
6121
|
+
TimeoutError as b9,
|
|
6122
|
+
handleAsync as bA,
|
|
6123
|
+
addPendingSource as bB,
|
|
6124
|
+
propagateStatus as bC,
|
|
6125
|
+
forEachDependent as bD,
|
|
6126
|
+
settlePendingSource as bE,
|
|
6127
|
+
joinPassAt as bF,
|
|
6128
|
+
notifyEpoch as bG,
|
|
6129
|
+
SUPPORTS_PROXY as bH,
|
|
6130
|
+
CONFIG_KEY_BAG as bI,
|
|
6131
|
+
releaseMarksHook as bJ,
|
|
6132
|
+
installMarkHooks as bK,
|
|
6133
|
+
CONFIG_LAGS as bL,
|
|
6134
|
+
REACTIVE_REASK as bM,
|
|
6135
|
+
onSupersede as bN,
|
|
6136
|
+
haltReactivity as bO,
|
|
6137
|
+
CONFIG_FRAME as bP,
|
|
6138
|
+
heldUnder as bQ,
|
|
6139
|
+
unhold as bR,
|
|
6140
|
+
laneStageHook as bS,
|
|
6141
|
+
REACTIVE_ZOMBIE as bT,
|
|
6142
|
+
installBoundaryHooks as bU,
|
|
6143
|
+
CAUGHT_REARMED as bV,
|
|
6144
|
+
OBSERVE as bW,
|
|
6145
|
+
clearSnapshots as bX,
|
|
6146
|
+
enforceLoadingBoundary as bY,
|
|
6147
|
+
getNextChildId as bZ,
|
|
6148
|
+
markSnapshotScope as b_,
|
|
6149
|
+
untrack as ba,
|
|
6150
|
+
dirtyQueue as bb,
|
|
6151
|
+
CONFIG_REDERIVE as bc,
|
|
6152
|
+
passTx as bd,
|
|
6153
|
+
CONFIG_FRESH_READ as be,
|
|
6154
|
+
createOwner as bf,
|
|
6155
|
+
writeHook as bg,
|
|
6156
|
+
REACTIVE_WRITE_IN_OWNED_SCOPE_SIGNAL_MESSAGE as bh,
|
|
6157
|
+
ownedScopeWriteMessage as bi,
|
|
6158
|
+
isEqual as bj,
|
|
6159
|
+
CONFIG_MANUAL_WRITE as bk,
|
|
6160
|
+
snapshotCaptureActive as bl,
|
|
6161
|
+
captureWriteSnapshot as bm,
|
|
6162
|
+
notePromotedWrite as bn,
|
|
6163
|
+
slotSignal as bo,
|
|
6164
|
+
stagedScreen as bp,
|
|
6165
|
+
CONFIG_PROMOTED as bq,
|
|
6166
|
+
setSlotUnobserved as br,
|
|
6167
|
+
installStoreHooks as bs,
|
|
6168
|
+
joinPassTx as bt,
|
|
6169
|
+
asyncTailFlights as bu,
|
|
6170
|
+
untrackDepth as bv,
|
|
6171
|
+
checkPostAwaitRead as bw,
|
|
6172
|
+
disposalDepth as bx,
|
|
6173
|
+
insertIntoHeap as by,
|
|
6174
|
+
isDisposed as bz,
|
|
5997
6175
|
CONFIG_OVERRIDE as c,
|
|
5998
|
-
|
|
5999
|
-
|
|
6000
|
-
|
|
6001
|
-
|
|
6002
|
-
|
|
6003
|
-
|
|
6004
|
-
|
|
6005
|
-
|
|
6006
|
-
|
|
6007
|
-
|
|
6176
|
+
releaseSnapshotScope as c0,
|
|
6177
|
+
resetErrorHalt as c1,
|
|
6178
|
+
setConsoleFooter as c2,
|
|
6179
|
+
setSnapshotCapture as c3,
|
|
6180
|
+
setWriteHook as c4,
|
|
6181
|
+
setAttributionHooks as c5,
|
|
6182
|
+
liveRootOwners as c6,
|
|
6183
|
+
ownerPath as c7,
|
|
6184
|
+
isSuppressed as c8,
|
|
6185
|
+
blockersOf as c9,
|
|
6186
|
+
CONFIG_PLUMBING as ca,
|
|
6187
|
+
anyExcluded as cb,
|
|
6188
|
+
isExcluded as cc,
|
|
6189
|
+
CONFIG_WIDE as cd,
|
|
6190
|
+
GRAPH_SIZE_WARN_AT as ce,
|
|
6191
|
+
noteFanOut as cf,
|
|
6192
|
+
CONFIG_SUPERSEDES as cg,
|
|
6008
6193
|
newTransaction as d,
|
|
6009
6194
|
enqueueSub as e,
|
|
6010
6195
|
CONFIG_VERDICT as f,
|