@solidjs/signals 2.0.0-rc.18 → 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 +168 -88
- package/dist/dev.attribution.js +16 -13
- package/dist/dev.js +272 -129
- package/dist/observe/boundaries.js +88 -67
- package/dist/observe/core/action.js +8 -0
- package/dist/observe/core/async.js +46 -34
- package/dist/observe/core/attribution.js +30 -28
- package/dist/observe/core/constants.js +21 -1
- package/dist/observe/core/core.js +164 -136
- package/dist/observe/core/effect.js +6 -6
- package/dist/observe/core/graph.js +3 -3
- package/dist/observe/core/heap.js +5 -5
- package/dist/observe/core/lanes.js +104 -84
- package/dist/observe/core/owner.js +10 -9
- package/dist/observe/core/scheduler.js +38 -35
- package/dist/observe/core/truth.js +6 -6
- package/dist/observe/core/verdict.js +13 -13
- package/dist/observe/deferred.js +39 -40
- package/dist/observe/index.js +2 -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 +2 -2
- package/dist/observe/store/store.js +63 -53
- 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 +55 -43
- package/dist/prod/core/constants.js +14 -1
- package/dist/prod/core/core.js +162 -134
- package/dist/prod/core/effect.js +9 -9
- package/dist/prod/core/graph.js +3 -3
- 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 +43 -40
- package/dist/prod/core/truth.js +6 -6
- package/dist/prod/core/verdict.js +17 -17
- package/dist/prod/deferred.js +39 -40
- package/dist/prod/index.js +2 -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 +2 -2
- package/dist/prod/store/store.js +262 -262
- package/dist/prod/store/utils.js +2 -0
- package/dist/types/core/action.d.ts +8 -0
- package/dist/types/core/constants.d.ts +20 -0
- package/dist/types/core/core.d.ts +14 -1
- 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 +2 -0
- package/dist/types/index.d.ts +3 -1
- package/dist/types/signals.d.ts +37 -0
- package/dist/types/store/target.d.ts +2 -0
- package/package.json +1 -1
|
@@ -130,7 +130,7 @@ function setExternalHooks(e, o) {
|
|
|
130
130
|
|
|
131
131
|
/** A transaction (listed here) or a lane (lanes.ts lists its own). */ function newTransaction(e, o = null) {
|
|
132
132
|
const n = {
|
|
133
|
-
|
|
133
|
+
Ye: [],
|
|
134
134
|
un: [ [], [] ],
|
|
135
135
|
En: [],
|
|
136
136
|
eo: null,
|
|
@@ -232,7 +232,7 @@ function resolveTx(e) {
|
|
|
232
232
|
e.eo = o;
|
|
233
233
|
o.tt += e.tt;
|
|
234
234
|
o.nt ||= e.nt;
|
|
235
|
-
append(o.
|
|
235
|
+
append(o.Ye, e.Ye);
|
|
236
236
|
append(o.un[0], e.un[0]);
|
|
237
237
|
append(o.un[1], e.un[1]);
|
|
238
238
|
append(o.En, e.En);
|
|
@@ -262,7 +262,7 @@ function resolveTx(e) {
|
|
|
262
262
|
judge ??= e;
|
|
263
263
|
// An action still running in it holds it open (action.ts). Its lanes
|
|
264
264
|
// (lanes.ts): a lane under `t` blocks it while blocked itself.
|
|
265
|
-
const n = e.tt !== 0 || blockedBy(e.
|
|
265
|
+
const n = e.tt !== 0 || blockedBy(e.Ye, e) || !!lanesBlockedHook?.(e);
|
|
266
266
|
judge = o;
|
|
267
267
|
return n;
|
|
268
268
|
}
|
|
@@ -273,8 +273,8 @@ let judge = null;
|
|
|
273
273
|
* frame reader observes (`blockedBy`'s predicate, collected; the readers
|
|
274
274
|
* themselves are not sources). */ function blockersOf(e) {
|
|
275
275
|
const o = [];
|
|
276
|
-
for (let n = 0; n < e.
|
|
277
|
-
const t = e.
|
|
276
|
+
for (let n = 0; n < e.Ye.length; n++) {
|
|
277
|
+
const t = e.Ye[n];
|
|
278
278
|
if (!t.i && t.m & STATUS_PENDING && !(t.R & REACTIVE_DISPOSED) && (t.T.Je === null || txOf(t) === e) && blockedBy([ t ], e)) o.push(t);
|
|
279
279
|
}
|
|
280
280
|
return o;
|
|
@@ -285,7 +285,7 @@ let judge = null;
|
|
|
285
285
|
* not (lanes.ts, the body-end corollary). A pending reader counts only if
|
|
286
286
|
* one of the sources it waits on is `t`'s (a render effect marked pending
|
|
287
287
|
* by a lane flight, never re-run, is the lane's wait, not the frame's). */ function ownFlights(e) {
|
|
288
|
-
return blockedBy(e.
|
|
288
|
+
return blockedBy(e.Ye, e, true);
|
|
289
289
|
}
|
|
290
290
|
|
|
291
291
|
/** A source the pending node waits on that is `t`'s (held by it, or by no
|
|
@@ -323,7 +323,7 @@ function blockedBy(e, o, n = false) {
|
|
|
323
323
|
// lane-membership ruling, 2026-10-05). An output that never committed
|
|
324
324
|
// shows nothing — a mount the frame has not revealed — and holds
|
|
325
325
|
// nothing.
|
|
326
|
-
if ((n.i === EFFECT_RENDER && n.m & STATUS_PENDING || n.R & REACTIVE_FRAME_READ || n.l & CONFIG_REDERIVE && n.m === STATUS_PENDING) && (e.
|
|
326
|
+
if ((n.i === EFFECT_RENDER && n.m & STATUS_PENDING || n.R & REACTIVE_FRAME_READ || n.l & CONFIG_REDERIVE && n.m === STATUS_PENDING) && (e.Ie === n.Ne || n.T?.F != null) && !(n.R & REACTIVE_DISPOSED) && onScreen(n, judge ?? o)) return true;
|
|
327
327
|
}
|
|
328
328
|
}
|
|
329
329
|
return false;
|
|
@@ -385,7 +385,7 @@ function deferZombie(e) {
|
|
|
385
385
|
const n = ext(e);
|
|
386
386
|
if (n.Je === o) return;
|
|
387
387
|
n.Je = o;
|
|
388
|
-
o.
|
|
388
|
+
o.Ye.push(e);
|
|
389
389
|
}
|
|
390
390
|
|
|
391
391
|
/** Hold the (uncommitted) frame under a held pass: every computed in the
|
|
@@ -427,7 +427,7 @@ function deferZombie(e) {
|
|
|
427
427
|
const dirtyQueue = {
|
|
428
428
|
gt: new Array(2e3).fill(undefined),
|
|
429
429
|
p: false,
|
|
430
|
-
|
|
430
|
+
lt: 0,
|
|
431
431
|
jt: 0
|
|
432
432
|
};
|
|
433
433
|
|
|
@@ -509,12 +509,14 @@ function schedule() {
|
|
|
509
509
|
* hook machinery (pay-for-use).
|
|
510
510
|
*/ const ROOT_ERROR_HOOK = Symbol.for("solid-js/root-error-hook");
|
|
511
511
|
|
|
512
|
+
const HALTED = "[REACTIVITY_HALTED]";
|
|
513
|
+
|
|
512
514
|
function haltReactivity(e) {
|
|
513
515
|
if (halted) return;
|
|
514
516
|
halted = true;
|
|
515
517
|
// A cleanup error collected before the halt is dropped (owner.ts).
|
|
516
518
|
rethrowCleanupError(true);
|
|
517
|
-
let o =
|
|
519
|
+
let o = HALTED;
|
|
518
520
|
// Surface the cause here too: callers rethrow it, but a creation-time throw
|
|
519
521
|
// unwinds through ancestor recomputes that convert it to status instead of
|
|
520
522
|
// surfacing it (#2884), so the rethrow alone cannot guarantee visibility.
|
|
@@ -542,7 +544,7 @@ function haltReactivity(e) {
|
|
|
542
544
|
function notifyHalted() {
|
|
543
545
|
if (haltNotified) return;
|
|
544
546
|
haltNotified = true;
|
|
545
|
-
console.error(
|
|
547
|
+
console.error(HALTED);
|
|
546
548
|
}
|
|
547
549
|
|
|
548
550
|
/** @internal Test/dev-reload hook. Revives scheduling after a halt. */ function resetErrorHalt() {
|
|
@@ -573,7 +575,7 @@ class GlobalQueue {
|
|
|
573
575
|
clock++;
|
|
574
576
|
// A write the commit sweep staged with no subscriber to dirty is work
|
|
575
577
|
// too — the next round commits it.
|
|
576
|
-
scheduled = dirtyQueue.jt >= dirtyQueue.
|
|
578
|
+
scheduled = dirtyQueue.jt >= dirtyQueue.lt || pendingNodes.length !== 0;
|
|
577
579
|
this.run(EFFECT_RENDER);
|
|
578
580
|
this.run(EFFECT_USER);
|
|
579
581
|
if (true && holding) {
|
|
@@ -627,18 +629,18 @@ class GlobalQueue {
|
|
|
627
629
|
// stale stamp was the bridge that entangled unrelated updates
|
|
628
630
|
// with a never-resolving flight). Its observers are held and
|
|
629
631
|
// wait on its flight (`blocked`).
|
|
630
|
-
if (e.
|
|
632
|
+
if (e.ie === NOT_PENDING && e.m & STATUS_UNINITIALIZED && e.i !== EFFECT_RENDER) continue;
|
|
631
633
|
// A34 (2): a tick whose writes net to the committed value made no
|
|
632
634
|
// proposal (`setShow(false); setShow(true)` on a committed true) —
|
|
633
635
|
// not staged, not held, pends nothing; a later write to it is
|
|
634
636
|
// plain mainline. (A node already held stays held when written
|
|
635
637
|
// back: A34 (1).)
|
|
636
|
-
if (e.
|
|
638
|
+
if (e.ie !== NOT_PENDING && !(e.m & (STATUS_PENDING | STATUS_UNINITIALIZED)) && e.T?.ft == null && e.T?.Nt == null &&
|
|
637
639
|
// The comparator last: a pass that created children (an object
|
|
638
640
|
// owning a fresh async memo, #4111) must not have it read them.
|
|
639
641
|
// A NotReady read there is a change (`isSame`).
|
|
640
|
-
isSame(e, e.
|
|
641
|
-
e.
|
|
642
|
+
isSame(e, e.le, e.ie)) {
|
|
643
|
+
e.ie = NOT_PENDING;
|
|
642
644
|
e.l &= ~CONFIG_STAGED;
|
|
643
645
|
continue;
|
|
644
646
|
}
|
|
@@ -692,11 +694,12 @@ class GlobalQueue {
|
|
|
692
694
|
// This flush's own runs, the lanes' reveals, and the landings' held runs
|
|
693
695
|
// are collected apart and ordered below.
|
|
694
696
|
const n = this.un;
|
|
695
|
-
const t =
|
|
697
|
+
const t = [ [], [] ];
|
|
696
698
|
// The passes that read this frame's stagings as the screen read held
|
|
697
699
|
// writes if it parked: the lane seam re-derives them on the committed
|
|
698
700
|
// world (a lane's runs wait this round).
|
|
699
701
|
if (laneSeamsHook) {
|
|
702
|
+
this.un = t;
|
|
700
703
|
laneSeamsHook(o !== null ? stagedReaders : null);
|
|
701
704
|
if (stagedReaders.length) stagedReaders.length = 0;
|
|
702
705
|
}
|
|
@@ -847,12 +850,12 @@ class GlobalQueue {
|
|
|
847
850
|
// (`_nodes` still lists them).
|
|
848
851
|
if (attrHooks !== null) attrHooks.transitionSettled(e);
|
|
849
852
|
const o = reruns(e);
|
|
850
|
-
if (e.I !== null) releaseMarksHook(e.I);
|
|
853
|
+
if (releaseMarksHook && e.I !== null) releaseMarksHook(e.I);
|
|
851
854
|
// Old children die in the commits (cleanups first), then the stashed
|
|
852
855
|
// effects run ahead of this flush's own. A node a lane took over since
|
|
853
856
|
// (a guess written over the staged truth) is the lane's to land.
|
|
854
|
-
for (let o = 0; o < e.
|
|
855
|
-
const n = e.
|
|
857
|
+
for (let o = 0; o < e.Ye.length; o++) {
|
|
858
|
+
const n = e.Ye[o];
|
|
856
859
|
if (n.T.Je === null || txOf(n) !== e) continue;
|
|
857
860
|
n.T.Je = null;
|
|
858
861
|
commitPendingNode(n);
|
|
@@ -925,7 +928,7 @@ function insertSubs(e) {
|
|
|
925
928
|
// masked read of the always-present _config instead of missing-property
|
|
926
929
|
// lookups in the hottest notify loop.
|
|
927
930
|
const o = e.l;
|
|
928
|
-
const n = (o & CONFIG_HAS_SNAPSHOT) !== 0 && e.T?.
|
|
931
|
+
const n = (o & CONFIG_HAS_SNAPSHOT) !== 0 && e.T?.st !== undefined;
|
|
929
932
|
// Observe-tier fan-out: this walk visits every subscriber edge anyway, so
|
|
930
933
|
// the graph-size count is one local increment here and no field anywhere.
|
|
931
934
|
let t = 0;
|
|
@@ -940,7 +943,7 @@ function insertSubs(e) {
|
|
|
940
943
|
// pass either re-reads them fresh or trims them), and neither does the
|
|
941
944
|
// tail link: it is the read IN FLIGHT — read() links before it pulls, so
|
|
942
945
|
// this very commit is what that read returns.
|
|
943
|
-
if (e.R & REACTIVE_RECOMPUTING_DEPS && o.
|
|
946
|
+
if (e.R & REACTIVE_RECOMPUTING_DEPS && o.Ie === e.Ne && o !== e._) e.R |= REACTIVE_MISSED_WAKE;
|
|
944
947
|
if (n && e.l & CONFIG_IN_SNAPSHOT_SCOPE) {
|
|
945
948
|
e.R |= REACTIVE_SNAPSHOT_STALE;
|
|
946
949
|
continue;
|
|
@@ -977,32 +980,32 @@ function commitPendingNode(e) {
|
|
|
977
980
|
// commits a value.
|
|
978
981
|
if (!o.X) {
|
|
979
982
|
e.l &= -385;
|
|
980
|
-
if (e.
|
|
981
|
-
e.
|
|
982
|
-
e.
|
|
983
|
+
if (e.ie !== NOT_PENDING) {
|
|
984
|
+
e.le = e.ie;
|
|
985
|
+
e.ie = NOT_PENDING;
|
|
983
986
|
}
|
|
984
987
|
return;
|
|
985
988
|
}
|
|
986
989
|
// Computeds only from here (`_statusFlags` is not a signal field). A
|
|
987
990
|
// commit beneath a flight publishes its inputs (A15 reveal corollary,
|
|
988
991
|
// #3305): a reveal of it must observe, not show the pre-flight value.
|
|
989
|
-
const n = e.
|
|
992
|
+
const n = e.ie === NOT_PENDING && (o.m & STATUS_PENDING) !== 0;
|
|
990
993
|
const t = e.l & CONFIG_STAGED_ERROR;
|
|
991
994
|
// An answer commits: the error it replaces leaves the display (D-41).
|
|
992
|
-
if (!n && o.T) o.T.
|
|
995
|
+
if (!n && o.T) o.T.Te = undefined;
|
|
993
996
|
e.l = n ? e.l & -1048833 | CONFIG_INPUTS_PUBLISHED : e.l & -3147137;
|
|
994
997
|
// D-41: the staged answer is an error — published now, when a value would
|
|
995
998
|
// show, through the ordinary error path (`stageError`). Its readers first
|
|
996
999
|
// see it in the cycle after this seam: a tracked re-read there is not a
|
|
997
1000
|
// retry (`read`), or a boundary re-derived by it would retry it forever.
|
|
998
1001
|
if (t) {
|
|
999
|
-
const n = e.
|
|
1000
|
-
e.
|
|
1001
|
-
e.
|
|
1002
|
+
const n = e.ie;
|
|
1003
|
+
e.ie = NOT_PENDING;
|
|
1004
|
+
e.ae = clock + 1;
|
|
1002
1005
|
notifyStatus(o, STATUS_ERROR, n);
|
|
1003
|
-
} else if (e.
|
|
1004
|
-
e.
|
|
1005
|
-
e.
|
|
1006
|
+
} else if (e.ie !== NOT_PENDING) {
|
|
1007
|
+
e.le = e.ie;
|
|
1008
|
+
e.ie = NOT_PENDING;
|
|
1006
1009
|
// A node born staged (recompute) initializes at this commit.
|
|
1007
1010
|
o.m &= ~STATUS_UNINITIALIZED;
|
|
1008
1011
|
// A quiet re-ask's classification survives its landing and dies with
|
|
@@ -1032,7 +1035,7 @@ function commitPendingNode(e) {
|
|
|
1032
1035
|
if (!(o.m & STATUS_PENDING)) o.m &= ~STATUS_UNINITIALIZED;
|
|
1033
1036
|
// L2: the children this commit publishes are the frame's now — the frame
|
|
1034
1037
|
// they replace, parked by the pass (`recompute`), goes.
|
|
1035
|
-
if (!n && o.T != null && (o.T.
|
|
1038
|
+
if (!n && o.T != null && (o.T.ft !== null || o.T.Nt !== null)) GlobalQueue.et(o, false, true);
|
|
1036
1039
|
}
|
|
1037
1040
|
|
|
1038
1041
|
function commitPendingNodes() {
|
|
@@ -1096,4 +1099,4 @@ function runQueue(e, o) {
|
|
|
1096
1099
|
for (let n = 0; n < e.length; n++) e[n](o);
|
|
1097
1100
|
}
|
|
1098
1101
|
|
|
1099
|
-
export { GlobalQueue, MAINLINE_QUESTION, ROOT_ERROR_HOOK, actionDepth, applyGuessesHook, blocked, blockersOf, boundarySeamHook, bumpNotifyEpoch, catchHook, clock, commitPendingNode, deferZombie, dirtyQueue, endLanesHook, enforceLoadingBoundary, enterAction, exitAction, externalUntrackHook, flush, flushTransaction, freshHook, globalQueue, haltReactivity, haltReactivityAt, heldRunHook, heldTrim, heldUnder, hiddenHook, holdNode, insertSubs, installBoundaryHooks, installLaneHooks, installMarkHooks, installStoreHooks, installVerdictHooks, joinFuture, joinPassTx, laneCorrectionsHook, laneDirty, laneOutcomeHook, laneReadHook, laneSeamsHook, laneStageHook, laneWriteHook, lanesBlockedHook, list, liveTx, merge, newTransaction, nextQuestion, notifyEpoch, observeFlightHook, ownFlights, passLane, passTx, question, queuePendingNode, releaseAmbientMarksHook, releaseMarksHook, releaseQueues, reruns, resetErrorHalt, resolveTx, sameLane, schedule, setExternalHooks, setPassLane, setQuestion, stagedReaders, staleReader, storeCommitHook, storeParkHook, txOf, unhold, wireExternalSourceHook };
|
|
1102
|
+
export { GlobalQueue, MAINLINE_QUESTION, ROOT_ERROR_HOOK, actionDepth, applyGuessesHook, blocked, blockersOf, boundarySeamHook, bumpNotifyEpoch, catchHook, clock, commitPendingNode, deferZombie, dirtyQueue, endLanesHook, enforceLoadingBoundary, enterAction, exitAction, externalUntrackHook, flush, flushTransaction, freshHook, globalQueue, haltReactivity, haltReactivityAt, heldRunHook, heldTrim, heldUnder, hiddenHook, holdNode, insertSubs, installBoundaryHooks, installLaneHooks, installMarkHooks, installStoreHooks, installVerdictHooks, joinFuture, joinPassTx, laneCorrectionsHook, laneDirty, laneOutcomeHook, laneReadHook, laneSeamsHook, laneStageHook, laneWriteHook, lanesBlockedHook, list, liveTx, merge, newTransaction, nextQuestion, notifyEpoch, observeFlightHook, ownFlights, passLane, passTx, pendingNodes, question, queuePendingNode, releaseAmbientMarksHook, releaseMarksHook, releaseQueues, reruns, resetErrorHalt, resolveTx, sameLane, schedule, setExternalHooks, setPassLane, setQuestion, stagedReaders, staleReader, storeCommitHook, storeParkHook, txOf, unhold, wireExternalSourceHook };
|
|
@@ -12,9 +12,9 @@ import { enqueueSub } from "./heap.js";
|
|
|
12
12
|
* staging a shown lane holds for its next reveal, else its slot; the
|
|
13
13
|
* committed value while it has none (its first lane pass in flight). */
|
|
14
14
|
function laneValueOf(r) {
|
|
15
|
-
if (!(r.l & CONFIG_GUESS) && r.
|
|
15
|
+
if (!(r.l & CONFIG_GUESS) && r.ie !== NOT_PENDING) return r.ie;
|
|
16
16
|
const t = r.T.V;
|
|
17
|
-
return t !== NOT_PENDING ? t : r.
|
|
17
|
+
return t !== NOT_PENDING ? t : r.le;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
/** Truth readers (`until`, `refresh`; CONFIG_AUTHORITATIVE) — pay-for-use:
|
|
@@ -25,19 +25,19 @@ function laneValueOf(r) {
|
|
|
25
25
|
* value. */ function truthRead(r) {
|
|
26
26
|
if (truth(r)) return laneValueOf(r);
|
|
27
27
|
if (!(r.l & CONFIG_GUESS)) throw new NotReadyError(null);
|
|
28
|
-
return r.
|
|
28
|
+
return r.ie !== NOT_PENDING ? r.ie : r.le;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
/** A guess confirmed: its lane's truth readers re-read — of the lane's
|
|
32
32
|
* derivations too, which may be the truth now (#3943). */ function truthConfirmed(r) {
|
|
33
|
-
for (let t = 0; t < r.
|
|
33
|
+
for (let t = 0; t < r.Ye.length; t++) for (let e = r.Ye[t].o; e !== null; e = e.t) if (e.u.l & CONFIG_AUTHORITATIVE) enqueueSub(e.u);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
/** A lane node's value is the truth when every guess beneath it is
|
|
37
37
|
* confirmed — its source staged a value equal to the guess — and nothing
|
|
38
38
|
* beneath it is held in the parent: same inputs, same value. */ function truth(r) {
|
|
39
|
-
if (r.l & CONFIG_GUESS) return r.
|
|
40
|
-
if (r.
|
|
39
|
+
if (r.l & CONFIG_GUESS) return r.ie !== NOT_PENDING && r.je && r.je(r.T.V, r.ie);
|
|
40
|
+
if (r.ie !== NOT_PENDING) return;
|
|
41
41
|
if (r.l & CONFIG_OVERRIDE) for (let t = r.C; t; t = t.G) if (!truth(t.S)) return;
|
|
42
42
|
return 1;
|
|
43
43
|
}
|
|
@@ -159,7 +159,7 @@ let probeFound = false;
|
|
|
159
159
|
* flight — a staging equal to what is displayed changes nothing when it
|
|
160
160
|
* lands: final now (maintainer, 2026-10-02). */ function heldNotFinal(e) {
|
|
161
161
|
if ((e.m & STATUS_PENDING) !== 0 && !quietPending(e)) return true;
|
|
162
|
-
return e.
|
|
162
|
+
return e.ie !== NOT_PENDING && !latestActive && !e.T.ut && !(e.m & STATUS_UNINITIALIZED) && (!!e.T.Te || !e.je || !e.je(e.le, e.ie));
|
|
163
163
|
}
|
|
164
164
|
|
|
165
165
|
/** `isPending`'s answer for an unheld node whose flight is up (cause ii). */ function pendingVerdict(e, t) {
|
|
@@ -177,7 +177,7 @@ let probeFound = false;
|
|
|
177
177
|
* a router's link claim probing inside the computation that creates the
|
|
178
178
|
* anchor). A throw still reaches the pass through `untrack`. */ function markVerdictReader(e) {
|
|
179
179
|
let t = context;
|
|
180
|
-
if (t?.Pt) t = t.
|
|
180
|
+
if (t?.Pt) t = t.ht;
|
|
181
181
|
if (t !== null && tracking) {
|
|
182
182
|
t.l |= CONFIG_VERDICT;
|
|
183
183
|
t.R |= REACTIVE_PROBED;
|
|
@@ -261,8 +261,8 @@ let probeFound = false;
|
|
|
261
261
|
}
|
|
262
262
|
|
|
263
263
|
/** The staging, or the staged error thrown (D-41). */ function staged(e) {
|
|
264
|
-
if (e.l & CONFIG_STAGED_ERROR) throw e.
|
|
265
|
-
return e.
|
|
264
|
+
if (e.l & CONFIG_STAGED_ERROR) throw e.ie;
|
|
265
|
+
return e.ie;
|
|
266
266
|
}
|
|
267
267
|
|
|
268
268
|
/** `latest()` of a held node: the flushed staging — the proposal — and, for
|
|
@@ -322,7 +322,7 @@ let probeFound = false;
|
|
|
322
322
|
if (i) verdictRead(t, r._parent ?? r);
|
|
323
323
|
const u = (n.m & STATUS_PENDING) !== 0 && !quietPending(n);
|
|
324
324
|
if (e.l & CONFIG_GUESS) {
|
|
325
|
-
if (probing && (u || e.
|
|
325
|
+
if (probing && (u || e.ie !== NOT_PENDING && (!e.je || !e.je(e.T.V, e.ie)))) probeFound = true;
|
|
326
326
|
// A lane a correction folded under (D-34): `latest()` shows the hold's
|
|
327
327
|
// world whole — the truth beneath each guess, else what it covered.
|
|
328
328
|
if (latestActive && r.folded) return r.folded(null, e);
|
|
@@ -342,28 +342,28 @@ let probeFound = false;
|
|
|
342
342
|
// `isPending` is answered below either way.
|
|
343
343
|
if (i && !probing && t.i === EFFECT_RENDER && passLane === null && r.it !== null && r.it.ln && flushTransaction !== r) {
|
|
344
344
|
staleReader(t, r.it);
|
|
345
|
-
return e.
|
|
345
|
+
return e.le;
|
|
346
346
|
}
|
|
347
347
|
if (i) verdictRead(t, r);
|
|
348
348
|
if (probing && heldNotFinal(n)) probeFound = true;
|
|
349
|
-
if (latestActive && e.
|
|
349
|
+
if (latestActive && e.ie !== NOT_PENDING) {
|
|
350
350
|
// An action body reading another transaction's proposal derives
|
|
351
351
|
// from it: the two settle as one (A15; posture C, 2026-09-15). An
|
|
352
352
|
// untracked read elsewhere has no transaction to entangle.
|
|
353
353
|
if (!i && flushTransaction !== null && !globalQueue.q) joinFuture(txOf(e));
|
|
354
354
|
return heldLatest(e, i ? t : null);
|
|
355
355
|
}
|
|
356
|
-
return e.
|
|
356
|
+
return e.le;
|
|
357
357
|
}
|
|
358
358
|
// Born into the future: its staging is its only value. It has no
|
|
359
359
|
// committed value, so no verdict: `isPending` reads it as its read does —
|
|
360
360
|
// the owner joins the hold (held with it, or caught by a boundary that
|
|
361
361
|
// has not shown content) and answers for the commit, where it is final.
|
|
362
|
-
if (e.
|
|
362
|
+
if (e.ie !== NOT_PENDING && !(n.m & STATUS_PENDING)) {
|
|
363
363
|
if (probing && r) joinPass(t, e);
|
|
364
364
|
return staged(e);
|
|
365
365
|
}
|
|
366
|
-
} else if (e.
|
|
366
|
+
} else if (e.ie !== NOT_PENDING) {
|
|
367
367
|
if (n.m & STATUS_PENDING && !u) pendingVerdict(i ? t : null, n); else if (i && globalQueue.q) provisionalVerdict(t, !latestActive && !u);
|
|
368
368
|
// Outside a flush, the staging is an unflushed write (A28): the probe
|
|
369
369
|
// answers for the flushed world, and watches the seam of the flush that
|
|
@@ -378,12 +378,12 @@ let probeFound = false;
|
|
|
378
378
|
if (globalQueue.q) return staged(e);
|
|
379
379
|
if (t !== null) markLateLinker(t);
|
|
380
380
|
}
|
|
381
|
-
return e.
|
|
381
|
+
return e.le;
|
|
382
382
|
}
|
|
383
383
|
if (n.m & STATUS_PENDING) {
|
|
384
384
|
if (!u) {
|
|
385
385
|
pendingVerdict(i ? t : null, n);
|
|
386
|
-
return e.
|
|
386
|
+
return e.le;
|
|
387
387
|
}
|
|
388
388
|
// As `read()`: an untracked read of a pending node still re-runs its
|
|
389
389
|
// reader when the node settles (a projection's pull reads its firewall
|
|
@@ -392,7 +392,7 @@ let probeFound = false;
|
|
|
392
392
|
throw n.T?.F;
|
|
393
393
|
}
|
|
394
394
|
if (n.X !== undefined && n.m & STATUS_ERROR) throw n.T.F;
|
|
395
|
-
return e.
|
|
395
|
+
return e.le;
|
|
396
396
|
}
|
|
397
397
|
|
|
398
398
|
// Installed at module evaluation — present exactly when something imports
|
package/dist/observe/deferred.js
CHANGED
|
@@ -123,7 +123,7 @@ GlobalQueue.er = e => lagging.size !== 0 ? lagOf(e, new Set) : undefined;
|
|
|
123
123
|
* does not replace (D-40) — restaged as the committed value, the hold's
|
|
124
124
|
* readers would re-derive against the old input. */ const serve = e => {
|
|
125
125
|
const r = handleAsync(t, e);
|
|
126
|
-
return t.l & CONFIG_HELD && t.
|
|
126
|
+
return t.l & CONFIG_HELD && t.ie !== NOT_PENDING ? t.ie : r;
|
|
127
127
|
};
|
|
128
128
|
const end = () => t.R & REACTIVE_DISPOSED && land(o);
|
|
129
129
|
return accessor(computed(r => {
|
|
@@ -135,52 +135,51 @@ GlobalQueue.er = e => lagging.size !== 0 ? lagOf(e, new Set) : undefined;
|
|
|
135
135
|
// Sticky, and read before this wrapper ever opens the window itself.
|
|
136
136
|
const n = l ||= !(t.m & STATUS_UNINITIALIZED) && !t.ce;
|
|
137
137
|
if (n) t.ce = true, t.l |= CONFIG_LAGS;
|
|
138
|
-
let s;
|
|
139
138
|
try {
|
|
140
|
-
|
|
139
|
+
const t = e(r);
|
|
140
|
+
if (n && typeof t === "object" && t !== null) {
|
|
141
|
+
if (isThenable(t)) {
|
|
142
|
+
ask(t);
|
|
143
|
+
const done = () => land(t, true);
|
|
144
|
+
t.then(done, done);
|
|
145
|
+
return serve(t);
|
|
146
|
+
}
|
|
147
|
+
const e = t[Symbol.asyncIterator];
|
|
148
|
+
if (e) {
|
|
149
|
+
// A stream's flight ends at its first yield (or its end).
|
|
150
|
+
const r = e.call(t);
|
|
151
|
+
let o = true;
|
|
152
|
+
const done = () => land(n, true);
|
|
153
|
+
const n = {
|
|
154
|
+
// Registered ahead of the engine's own reaction to the same
|
|
155
|
+
// promise, as for a plain flight: verdict and value in one flush.
|
|
156
|
+
next: e => {
|
|
157
|
+
const t = r.next(e);
|
|
158
|
+
if (o) {
|
|
159
|
+
o = false;
|
|
160
|
+
if (isThenable(t)) t.then(done, done); else done();
|
|
161
|
+
}
|
|
162
|
+
return t;
|
|
163
|
+
},
|
|
164
|
+
return: e => r.return?.(e) ?? Promise.resolve({
|
|
165
|
+
done: true,
|
|
166
|
+
value: e
|
|
167
|
+
})
|
|
168
|
+
};
|
|
169
|
+
ask(n);
|
|
170
|
+
return serve({
|
|
171
|
+
[Symbol.asyncIterator]: () => n
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
land(o);
|
|
176
|
+
return t;
|
|
141
177
|
} catch (e) {
|
|
142
178
|
// The wrapping form: an unready source parks the node in the window,
|
|
143
179
|
// and the wait is its flight until the source's settle re-runs it.
|
|
144
180
|
if (n && e instanceof NotReadyError) ask(e); else land(o);
|
|
145
181
|
throw e;
|
|
146
182
|
}
|
|
147
|
-
if (n && typeof s === "object" && s !== null) {
|
|
148
|
-
if (isThenable(s)) {
|
|
149
|
-
ask(s);
|
|
150
|
-
const done = () => land(s, true);
|
|
151
|
-
s.then(done, done);
|
|
152
|
-
return serve(s);
|
|
153
|
-
}
|
|
154
|
-
const e = s[Symbol.asyncIterator];
|
|
155
|
-
if (e) {
|
|
156
|
-
// A stream's flight ends at its first yield (or its end).
|
|
157
|
-
const r = e.call(s);
|
|
158
|
-
let t = true;
|
|
159
|
-
const done = () => land(o, true);
|
|
160
|
-
const o = {
|
|
161
|
-
// Registered ahead of the engine's own reaction to the same
|
|
162
|
-
// promise, as for a plain flight: verdict and value in one flush.
|
|
163
|
-
next: e => {
|
|
164
|
-
const o = r.next(e);
|
|
165
|
-
if (t) {
|
|
166
|
-
t = false;
|
|
167
|
-
if (isThenable(o)) o.then(done, done); else done();
|
|
168
|
-
}
|
|
169
|
-
return o;
|
|
170
|
-
},
|
|
171
|
-
return: e => r.return?.(e) ?? Promise.resolve({
|
|
172
|
-
done: true,
|
|
173
|
-
value: e
|
|
174
|
-
})
|
|
175
|
-
};
|
|
176
|
-
ask(o);
|
|
177
|
-
return serve({
|
|
178
|
-
[Symbol.asyncIterator]: () => o
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
land(o);
|
|
183
|
-
return s;
|
|
184
183
|
}, r));
|
|
185
184
|
}
|
|
186
185
|
|
package/dist/observe/index.js
CHANGED
|
@@ -20,7 +20,7 @@ import { OBSERVE as OBSERVE$1 } from "./core/dev.js";
|
|
|
20
20
|
|
|
21
21
|
export { setConsoleFooter } from "./core/dev.js";
|
|
22
22
|
|
|
23
|
-
export { ROOT_ERROR_HOOK, enforceLoadingBoundary, flush, resetErrorHalt } from "./core/scheduler.js";
|
|
23
|
+
export { ROOT_ERROR_HOOK, clock, enforceLoadingBoundary, flush, resetErrorHalt } from "./core/scheduler.js";
|
|
24
24
|
|
|
25
25
|
import "./core/effect.js";
|
|
26
26
|
|
|
@@ -28,7 +28,7 @@ export { configureClientErrors } from "./core/error-hooks.js";
|
|
|
28
28
|
|
|
29
29
|
export { storeName } from "./store/edges.js";
|
|
30
30
|
|
|
31
|
-
export { createEffect, createMemo, createOptimistic, createReaction, createRenderEffect, createSignal, createTrackedEffect, onCleanup, onSettled, refresh, resolve, until } from "./signals.js";
|
|
31
|
+
export { createEffect, createMemo, createOptimistic, createReaction, createRenderEffect, createSignal, createTrackedEffect, onCleanup, onFlush, onSettled, refresh, resolve, until } from "./signals.js";
|
|
32
32
|
|
|
33
33
|
export { mapArray, repeat } from "./map.js";
|
|
34
34
|
|
package/dist/observe/map.js
CHANGED
|
@@ -29,7 +29,7 @@ function mapArray(t, e, i) {
|
|
|
29
29
|
Mt: [],
|
|
30
30
|
Wt: r,
|
|
31
31
|
vt: [],
|
|
32
|
-
|
|
32
|
+
Ye: [],
|
|
33
33
|
Vt: s,
|
|
34
34
|
Kt: s || i?.keyed === false ? [] : undefined,
|
|
35
35
|
xt: n && i?.keyed !== false ? [] : undefined,
|
|
@@ -157,7 +157,7 @@ function trySmallMove(t, e, i, s) {
|
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
159
|
const a = t.vt;
|
|
160
|
-
const l = t.
|
|
160
|
+
const l = t.Ye;
|
|
161
161
|
const u = a.slice(0, i);
|
|
162
162
|
const d = l.slice(0, i);
|
|
163
163
|
for (let t = 0; t < r.length; t += 3) {
|
|
@@ -177,7 +177,7 @@ function trySmallMove(t, e, i, s) {
|
|
|
177
177
|
d[t] = l[e];
|
|
178
178
|
}
|
|
179
179
|
t.vt = u;
|
|
180
|
-
t.
|
|
180
|
+
t.Ye = d;
|
|
181
181
|
t.wt = i;
|
|
182
182
|
t.Mt = e.slice(0);
|
|
183
183
|
// Dispose unmatched sources LAST (general-path ordering).
|
|
@@ -197,7 +197,7 @@ function trySmallMove(t, e, i, s) {
|
|
|
197
197
|
* needs the reset). The stage arrays are scratch — nothing live is touched. */ function stageRemoval(t, e, i, s, n, r, o, f, h) {
|
|
198
198
|
const c = t.Vt;
|
|
199
199
|
const a = t.Mt;
|
|
200
|
-
const l = t.
|
|
200
|
+
const l = t.Ye;
|
|
201
201
|
const u = [];
|
|
202
202
|
let d = i;
|
|
203
203
|
for (let p = i; p <= n; d++, p++) {
|
|
@@ -222,7 +222,7 @@ function trySmallMove(t, e, i, s) {
|
|
|
222
222
|
* index signals. Its own function so the general path's body stays under
|
|
223
223
|
* the JIT's optimization budget — the inlined commit measured ~10% slower on
|
|
224
224
|
* full-window reorders (the small-move note has the same finding). */ function commitWindow(t, e, i, s, n, r, o, f, h) {
|
|
225
|
-
const c = t.
|
|
225
|
+
const c = t.Ye;
|
|
226
226
|
const a = t.Kt;
|
|
227
227
|
const l = t.xt;
|
|
228
228
|
const u = t.wt;
|
|
@@ -267,7 +267,7 @@ function updateKeyedMap() {
|
|
|
267
267
|
// the flight's reader (pending tracking + post-settle retry) instead of
|
|
268
268
|
// vanishing. Set per pass: the first pass runs inside `computed()`, before
|
|
269
269
|
// the node exists to the caller.
|
|
270
|
-
this.H.
|
|
270
|
+
this.H.ht = getOwner();
|
|
271
271
|
const t = this.yt() || [], e = t.length;
|
|
272
272
|
t[$TRACK];
|
|
273
273
|
// top level tracking (a store array's container node)
|
|
@@ -298,7 +298,7 @@ function updateKeyedMap() {
|
|
|
298
298
|
if (e === 0) {
|
|
299
299
|
if (this.wt !== 0) {
|
|
300
300
|
this.H.dispose(false);
|
|
301
|
-
this.
|
|
301
|
+
this.Ye = [];
|
|
302
302
|
this.Mt = [];
|
|
303
303
|
this.vt = [];
|
|
304
304
|
this.wt = 0;
|
|
@@ -308,8 +308,8 @@ function updateKeyedMap() {
|
|
|
308
308
|
if (this.L && !this.vt.length) {
|
|
309
309
|
// an aborted fallback attempt leaves an owner without a mapping;
|
|
310
310
|
// dispose it before re-creating
|
|
311
|
-
this.
|
|
312
|
-
this.vt[0] = runWithOwner(this.
|
|
311
|
+
this.Ye[0]?.dispose();
|
|
312
|
+
this.vt[0] = runWithOwner(this.Ye[0] = createOwner(), this.L);
|
|
313
313
|
}
|
|
314
314
|
}
|
|
315
315
|
// fast path for new create
|
|
@@ -328,10 +328,10 @@ function updateKeyedMap() {
|
|
|
328
328
|
throw t;
|
|
329
329
|
}
|
|
330
330
|
// commit
|
|
331
|
-
if (this.
|
|
331
|
+
if (this.Ye[0]) this.Ye[0].dispose();
|
|
332
332
|
// previous fallback
|
|
333
333
|
this.vt = h;
|
|
334
|
-
this.
|
|
334
|
+
this.Ye = c;
|
|
335
335
|
r && (this.Kt = r);
|
|
336
336
|
o && (this.xt = o);
|
|
337
337
|
this.Mt = t.slice(0);
|
|
@@ -447,13 +447,13 @@ function updateKeyedMap() {
|
|
|
447
447
|
s = d.get(u);
|
|
448
448
|
if (s !== undefined && s !== -1) {
|
|
449
449
|
S[s] = this.vt[i];
|
|
450
|
-
M[s - h] = this.
|
|
450
|
+
M[s - h] = this.Ye[i];
|
|
451
451
|
r && (r[s - h] = this.Kt[i]);
|
|
452
452
|
o && (o[s - h] = this.xt[i]);
|
|
453
453
|
s = p[s - h];
|
|
454
454
|
d.set(u, s);
|
|
455
455
|
} else {
|
|
456
|
-
(w ??= []).push(this.
|
|
456
|
+
(w ??= []).push(this.Ye[i]);
|
|
457
457
|
if (true && attrHooks !== null) (O ??= []).push(l);
|
|
458
458
|
}
|
|
459
459
|
}
|
|
@@ -483,7 +483,7 @@ function updateKeyedMap() {
|
|
|
483
483
|
// save a copy of the mapped items for the next update
|
|
484
484
|
this.Mt = t.slice(0);
|
|
485
485
|
if (w) for (i = 0; i < w.length; i++) w[i].dispose();
|
|
486
|
-
if (true && attrHooks !== null && O !== undefined && _ !== undefined) attrHooks.listChurn(this.H.
|
|
486
|
+
if (true && attrHooks !== null && O !== undefined && _ !== undefined) attrHooks.listChurn(this.H.ht, O, _, e, this.Vt !== undefined);
|
|
487
487
|
}
|
|
488
488
|
});
|
|
489
489
|
return this.vt;
|
|
@@ -511,7 +511,7 @@ function updateKeyedMap() {
|
|
|
511
511
|
$t: 0,
|
|
512
512
|
qt: t,
|
|
513
513
|
Wt: s,
|
|
514
|
-
|
|
514
|
+
Ye: [],
|
|
515
515
|
vt: [],
|
|
516
516
|
zt: i?.from,
|
|
517
517
|
L: i?.fallback
|
|
@@ -530,14 +530,14 @@ function updateKeyedMap() {
|
|
|
530
530
|
// disjoint-window/front-clear/end-clear/shift special cases.
|
|
531
531
|
function updateRepeat() {
|
|
532
532
|
// As in updateKeyedMap: the node is the row callbacks' reader, per pass.
|
|
533
|
-
this.H.
|
|
533
|
+
this.H.ht = getOwner();
|
|
534
534
|
const t = this.qt();
|
|
535
535
|
const e = this.zt?.() || 0;
|
|
536
536
|
runWithOwner(this.H, () => {
|
|
537
537
|
if (t === 0) {
|
|
538
538
|
if (this.wt !== 0) {
|
|
539
539
|
this.H.dispose(false);
|
|
540
|
-
this.
|
|
540
|
+
this.Ye = [];
|
|
541
541
|
this.vt = [];
|
|
542
542
|
this.wt = 0;
|
|
543
543
|
// Reset offset to match the cleared data (#2767, repro 2).
|
|
@@ -546,8 +546,8 @@ function updateRepeat() {
|
|
|
546
546
|
if (this.L && !this.vt.length) {
|
|
547
547
|
// an aborted fallback attempt leaves an owner without a mapping;
|
|
548
548
|
// dispose it before re-creating
|
|
549
|
-
this.
|
|
550
|
-
this.vt[0] = runWithOwner(this.
|
|
549
|
+
this.Ye[0]?.dispose();
|
|
550
|
+
this.vt[0] = runWithOwner(this.Ye[0] = createOwner(), this.L);
|
|
551
551
|
}
|
|
552
552
|
return;
|
|
553
553
|
}
|
|
@@ -560,7 +560,7 @@ function updateRepeat() {
|
|
|
560
560
|
const o = new Array(t);
|
|
561
561
|
const f = new Array(t);
|
|
562
562
|
for (let t = n; t < r; t++) {
|
|
563
|
-
f[t - e] = this.
|
|
563
|
+
f[t - e] = this.Ye[t - this.$t];
|
|
564
564
|
o[t - e] = this.vt[t - this.$t];
|
|
565
565
|
}
|
|
566
566
|
try {
|
|
@@ -573,9 +573,9 @@ function updateRepeat() {
|
|
|
573
573
|
throw t;
|
|
574
574
|
}
|
|
575
575
|
// commit: dispose the previous fallback or the rows leaving the window
|
|
576
|
-
if (this.wt === 0) this.
|
|
576
|
+
if (this.wt === 0) this.Ye[0]?.dispose(); else for (let t = this.$t; t < s; t++) if (t < e || t >= i) this.Ye[t - this.$t].dispose();
|
|
577
577
|
this.vt = o;
|
|
578
|
-
this.
|
|
578
|
+
this.Ye = f;
|
|
579
579
|
this.$t = e;
|
|
580
580
|
this.wt = t;
|
|
581
581
|
});
|