@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
package/dist/observe/reveal.js
CHANGED
|
@@ -106,7 +106,7 @@ class RevealController {
|
|
|
106
106
|
}
|
|
107
107
|
return t !== "natural";
|
|
108
108
|
}
|
|
109
|
-
|
|
109
|
+
te(t) {
|
|
110
110
|
if (this.Zt.includes(t)) return;
|
|
111
111
|
this.Zt.push(t);
|
|
112
112
|
// Gated from the start (collapsed in a collapsed sequential tail); the
|
|
@@ -124,7 +124,7 @@ class RevealController {
|
|
|
124
124
|
}
|
|
125
125
|
untrack(() => this.Bt());
|
|
126
126
|
}
|
|
127
|
-
|
|
127
|
+
oe(t) {
|
|
128
128
|
const e = this.Zt.indexOf(t);
|
|
129
129
|
if (e >= 0) this.Zt.splice(e, 1);
|
|
130
130
|
untrack(() => this.Bt());
|
|
@@ -194,8 +194,8 @@ class RevealController {
|
|
|
194
194
|
});
|
|
195
195
|
if (true) s._name = "reveal order";
|
|
196
196
|
if (r) {
|
|
197
|
-
r.
|
|
198
|
-
cleanup(() => r.
|
|
197
|
+
r.te(i);
|
|
198
|
+
cleanup(() => r.oe(i));
|
|
199
199
|
}
|
|
200
200
|
return e;
|
|
201
201
|
});
|
|
@@ -204,8 +204,8 @@ class RevealController {
|
|
|
204
204
|
// Installed at module evaluation — present exactly when something imports
|
|
205
205
|
// `createRevealOrder`; a Loading boundary without one pays a null check.
|
|
206
206
|
setRevealHooks({
|
|
207
|
-
oe: (t, e) => t.oe(e),
|
|
208
207
|
te: (t, e) => t.te(e),
|
|
208
|
+
oe: (t, e) => t.oe(e),
|
|
209
209
|
P: t => t.Bt()
|
|
210
210
|
});
|
|
211
211
|
|
package/dist/observe/signals.js
CHANGED
|
@@ -8,7 +8,7 @@ import { computed, signal, runWithOwner, setMemo, setSignal, markRefresh, read,
|
|
|
8
8
|
|
|
9
9
|
import { registerGraph } from "./core/dev.js";
|
|
10
10
|
|
|
11
|
-
import { globalQueue, flushTransaction, dirtyQueue, GlobalQueue, resolveTx, passTx, staleReader, joinFuture } from "./core/scheduler.js";
|
|
11
|
+
import { schedule, globalQueue, flushTransaction, dirtyQueue, GlobalQueue, resolveTx, passTx, staleReader, joinFuture } from "./core/scheduler.js";
|
|
12
12
|
|
|
13
13
|
import { cleanup, createRoot, getOwner, dispose } from "./core/owner.js";
|
|
14
14
|
|
|
@@ -343,14 +343,14 @@ function createMemo(e, t) {
|
|
|
343
343
|
// or an already-displayed guess would satisfy it in a later slice. (REDERIVE
|
|
344
344
|
// after: the first pass's own error is the promise's rejection.)
|
|
345
345
|
computed(() => {
|
|
346
|
-
let
|
|
346
|
+
let u, i = false;
|
|
347
347
|
try {
|
|
348
|
-
|
|
348
|
+
u = e();
|
|
349
349
|
} catch (e) {
|
|
350
350
|
if (e instanceof NotReadyError) throw e;
|
|
351
351
|
// An error is an answer (D-41): delivered by the same frame rule.
|
|
352
|
-
|
|
353
|
-
|
|
352
|
+
u = unwrapStatusError(e);
|
|
353
|
+
i = true;
|
|
354
354
|
}
|
|
355
355
|
const s = getOwner();
|
|
356
356
|
// A truth reader waits out a `createDeferred` flight its value derives
|
|
@@ -363,9 +363,9 @@ function createMemo(e, t) {
|
|
|
363
363
|
staleReader(s, resolveTx(a));
|
|
364
364
|
return;
|
|
365
365
|
}
|
|
366
|
-
if (
|
|
367
|
-
o?.(
|
|
368
|
-
queueMicrotask(() => t(
|
|
366
|
+
if (i) return void queueMicrotask(() => r(u));
|
|
367
|
+
o?.(u);
|
|
368
|
+
queueMicrotask(() => t(u));
|
|
369
369
|
}, {
|
|
370
370
|
St: n
|
|
371
371
|
}).l |= CONFIG_REDERIVE;
|
|
@@ -525,14 +525,14 @@ function createMemo(e, t) {
|
|
|
525
525
|
// (`saving=true` beside the confirmed `version=1` is a tear no timeline
|
|
526
526
|
// contains). Updates that do not flip the predicate reveal freely.
|
|
527
527
|
const c = flushTransaction;
|
|
528
|
-
createRoot(
|
|
529
|
-
let
|
|
528
|
+
createRoot(u => {
|
|
529
|
+
let i;
|
|
530
530
|
let s;
|
|
531
531
|
const settle = e => {
|
|
532
|
-
if (
|
|
532
|
+
if (i !== undefined) clearTimeout(i);
|
|
533
533
|
if (s !== undefined) o.removeEventListener("abort", s);
|
|
534
534
|
e();
|
|
535
|
-
|
|
535
|
+
u();
|
|
536
536
|
};
|
|
537
537
|
// Authoritative: the predicate sees the truth, never the action's own
|
|
538
538
|
// optimistic guess — a guess cannot satisfy the wait for its own
|
|
@@ -547,7 +547,7 @@ function createMemo(e, t) {
|
|
|
547
547
|
// revealed with the action.
|
|
548
548
|
if (e && c !== null && globalQueue.q && resolveTx(c).tt !== 0) joinFuture(c);
|
|
549
549
|
});
|
|
550
|
-
if (t?.timeout !== undefined)
|
|
550
|
+
if (t?.timeout !== undefined) i = setTimeout(() => settle(() => n(new TimeoutError)), t.timeout);
|
|
551
551
|
if (o !== undefined) {
|
|
552
552
|
s = () => settle(() => n(o.reason));
|
|
553
553
|
o.addEventListener("abort", s, {
|
|
@@ -663,7 +663,7 @@ function createMemo(e, t) {
|
|
|
663
663
|
// still holding the optimistic value — reads do not pull (#3411). Fall
|
|
664
664
|
// to the next pass while the heap has work; `run` swapped the queue,
|
|
665
665
|
// so this lands there, and `enqueue` keeps the drain alive.
|
|
666
|
-
if (dirtyQueue.jt >= dirtyQueue.
|
|
666
|
+
if (dirtyQueue.jt >= dirtyQueue.lt) return globalQueue.enqueue(EFFECT_USER, fire);
|
|
667
667
|
// Unowned, out-of-band fire (no owner, or a children-forbidden one this
|
|
668
668
|
// one-shot must not bind to): a returned cleanup has no lifecycle to
|
|
669
669
|
// attach to. Reject it in dev; in production the return is simply
|
|
@@ -672,4 +672,46 @@ function createMemo(e, t) {
|
|
|
672
672
|
});
|
|
673
673
|
}
|
|
674
674
|
|
|
675
|
-
|
|
675
|
+
/**
|
|
676
|
+
* Schedules `callback` to run **once**, right after the pending flush
|
|
677
|
+
* finishes, in the same microtask checkpoint (before the browser paints).
|
|
678
|
+
* Unlike `onSettled`, it never waits on async work: if that flush is held by
|
|
679
|
+
* a pending transition, the callback still runs.
|
|
680
|
+
*
|
|
681
|
+
* Its main use is keeping a write out of another update's hold. Writes made
|
|
682
|
+
* in the same synchronous frame are applied together, so when one of them
|
|
683
|
+
* starts async work (a route change, a fetch), the others are held with it
|
|
684
|
+
* until it resolves. A write made in `onFlush` happens after that flush, so
|
|
685
|
+
* it is its own update: it commits on its own unless something it changes
|
|
686
|
+
* also derives from the held work (a memo or `createEffect` reading both),
|
|
687
|
+
* in which case it joins that hold as any later write would.
|
|
688
|
+
*
|
|
689
|
+
* Call it from event handlers and effect callbacks (including
|
|
690
|
+
* `createTrackedEffect` and `onSettled` bodies). In an owned scope such as a
|
|
691
|
+
* component body or a computation it warns in dev: use `onSettled` there.
|
|
692
|
+
*
|
|
693
|
+
* - A write in the callback lands after any write made inline in the same
|
|
694
|
+
* frame. Don't write the same signal both inside and outside it; use a
|
|
695
|
+
* functional setter if the order matters.
|
|
696
|
+
* - Several `onFlush` callbacks run in call order and batch into one flush.
|
|
697
|
+
* - `queueMicrotask` is not a substitute: called before the frame's first
|
|
698
|
+
* write, it runs before that flush and its write joins it.
|
|
699
|
+
*
|
|
700
|
+
* @example
|
|
701
|
+
* ```tsx
|
|
702
|
+
* // A menu closes now even when the consumer's onSelect starts async work.
|
|
703
|
+
* const select = (id: string) => {
|
|
704
|
+
* onFlush(() => setOpen(false));
|
|
705
|
+
* props.onSelect?.(id);
|
|
706
|
+
* };
|
|
707
|
+
* ```
|
|
708
|
+
*
|
|
709
|
+
* @param callback Function to run once after the pending flush
|
|
710
|
+
*/ function onFlush(e) {
|
|
711
|
+
// The frame's flush is queued (or already draining) ahead of this
|
|
712
|
+
// microtask, so the callback's writes start a flush of their own.
|
|
713
|
+
schedule();
|
|
714
|
+
queueMicrotask(e);
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
export { accessor, createEffect, createMemo, createOptimistic, createReaction, createRenderEffect, createSignal, createTrackedEffect, onCleanup, onFlush, onSettled, refresh, resolve, until };
|
|
@@ -72,7 +72,7 @@ function scopeOf(e, o) {
|
|
|
72
72
|
if (f !== undefined) {
|
|
73
73
|
if (f.pb !== null) o.oo.add(f.v);
|
|
74
74
|
// The writer's view: the tick's own unflushed guesses are in motion too.
|
|
75
|
-
if (f.fam?.opt === true) r = optHooks.view(f, r, true);
|
|
75
|
+
if (optHooks && f.fam?.opt === true) r = optHooks.view(f, r, true);
|
|
76
76
|
const e = f.n;
|
|
77
77
|
if (e !== null) for (const o of Reflect.ownKeys(e))
|
|
78
78
|
// Another mark's carrier is its own channel: counting it here would
|
|
@@ -83,7 +83,7 @@ function notifyOptimisticWrites(e, n) {
|
|
|
83
83
|
// inner store's truth for its key before guessing over it.
|
|
84
84
|
const o = e.ch ? e.v : null;
|
|
85
85
|
const guess = (e, n, i, r) => {
|
|
86
|
-
if (o !== null) e.
|
|
86
|
+
if (o !== null) e.le = i ? n in t : unwrapValue(t[n]);
|
|
87
87
|
// By value: a function leaf is a value, not an updater (#3017).
|
|
88
88
|
optimisticWrite(e, () => r);
|
|
89
89
|
};
|
|
@@ -344,7 +344,7 @@ function arrangementEqual(e, n, t) {
|
|
|
344
344
|
// keyed arrangement guess's view carries its removed-keys set.
|
|
345
345
|
if (!i.It || !(t?.l & CONFIG_OVERRIDE) || !t.T.V?.removed) return false;
|
|
346
346
|
const r = e.T.V;
|
|
347
|
-
if ((!e.
|
|
347
|
+
if ((!e.je || !e.je(r, n)) && !GlobalQueue.sn(r, n)) {
|
|
348
348
|
i.folded = foldedRead;
|
|
349
349
|
insertSubs(e);
|
|
350
350
|
} else GlobalQueue.tn?.(i);
|
|
@@ -365,8 +365,8 @@ function arrangementEqual(e, n, t) {
|
|
|
365
365
|
const t = txOf(n);
|
|
366
366
|
joinPassAt(e, resolveTx(t._parent ?? t));
|
|
367
367
|
}
|
|
368
|
-
if (n.
|
|
369
|
-
return n.l & CONFIG_SLOT_NODE ? GlobalQueue.fn(n) : n.
|
|
368
|
+
if (n.ie !== NOT_PENDING) return n.ie;
|
|
369
|
+
return n.l & CONFIG_SLOT_NODE ? GlobalQueue.fn(n) : n.le;
|
|
370
370
|
}
|
|
371
371
|
|
|
372
372
|
function sameRow(e, n, t) {
|
|
@@ -430,7 +430,7 @@ function sweepOverlaid() {
|
|
|
430
430
|
// The container shows its backing again (a shown arrangement guess
|
|
431
431
|
// that ended without a landing left its `LaneView` as the value).
|
|
432
432
|
const t = e.k;
|
|
433
|
-
if (t !== null && t.
|
|
433
|
+
if (t !== null && t.le instanceof LaneView) t.le = t.le.base;
|
|
434
434
|
}
|
|
435
435
|
if (n.size === 0) overlaidFamilies.delete(e);
|
|
436
436
|
}
|
|
@@ -447,8 +447,8 @@ function sweepOverlaid() {
|
|
|
447
447
|
if (i !== null) for (const e of Reflect.ownKeys(i)) {
|
|
448
448
|
const r = i[e];
|
|
449
449
|
const o = untrack(() => unwrapValue(n[e]));
|
|
450
|
-
if (r.
|
|
451
|
-
r.
|
|
450
|
+
if (r.je && r.je(r.le, o)) continue;
|
|
451
|
+
r.le = o;
|
|
452
452
|
// (The lane's end notified it this epoch when the shown value and the
|
|
453
453
|
// covered one differed — its readers re-derive already.)
|
|
454
454
|
if (r.o !== null && r.Ot !== notifyEpoch) {
|
|
@@ -460,8 +460,8 @@ function sweepOverlaid() {
|
|
|
460
460
|
if (r !== null) for (const e of Reflect.ownKeys(r)) {
|
|
461
461
|
const i = r[e];
|
|
462
462
|
const o = untrack(() => e in n);
|
|
463
|
-
if (i.
|
|
464
|
-
i.
|
|
463
|
+
if (i.le === o) continue;
|
|
464
|
+
i.le = o;
|
|
465
465
|
if (i.o !== null && i.Ot !== notifyEpoch) {
|
|
466
466
|
insertSubs(i);
|
|
467
467
|
t = true;
|
|
@@ -470,9 +470,9 @@ function sweepOverlaid() {
|
|
|
470
470
|
// The arrangement the readers saw (the shown guess) against the inner's
|
|
471
471
|
// now: a structural reader re-derives when they differ.
|
|
472
472
|
const o = e.k;
|
|
473
|
-
if (o !== null && o.o !== null && o.
|
|
473
|
+
if (o !== null && o.o !== null && o.le instanceof LaneView && o.Ot !== notifyEpoch) {
|
|
474
474
|
const i = Array.isArray(n) ? untrack(() => n.map(unwrapValue)) : n;
|
|
475
|
-
if (!arrangementEqual(o.
|
|
475
|
+
if (!arrangementEqual(o.le.rows, i, e.fam?.key ?? null)) {
|
|
476
476
|
insertSubs(o);
|
|
477
477
|
t = true;
|
|
478
478
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { attrHooks } from "../core/attribution-hooks.js";
|
|
2
2
|
|
|
3
|
-
import { CONFIG_AUTO_DISPOSE, STATUS_PENDING, STATUS_UNINITIALIZED } from "../core/constants.js";
|
|
3
|
+
import { CONFIG_AUTO_DISPOSE, STATUS_PENDING, STATUS_ERROR, STATUS_UNINITIALIZED } from "../core/constants.js";
|
|
4
4
|
|
|
5
5
|
import { computed } from "../core/core.js";
|
|
6
6
|
|
|
@@ -80,8 +80,8 @@ import { $TARGET, markRawIngest, isWrappable, setWriteOverride } from "./types.j
|
|
|
80
80
|
};
|
|
81
81
|
const s = {
|
|
82
82
|
get(s, c) {
|
|
83
|
-
const
|
|
84
|
-
return !o && typeof
|
|
83
|
+
const a = read(() => e[c]);
|
|
84
|
+
return !o && typeof a === "object" && a !== null && c !== $TARGET ? wrapDraft(a, t, r, false, n, i) : a;
|
|
85
85
|
},
|
|
86
86
|
has: (t, r) => read(() => r in e),
|
|
87
87
|
set: (t, r, o) => mutate(() => {
|
|
@@ -103,8 +103,8 @@ import { $TARGET, markRawIngest, isWrappable, setWriteOverride } from "./types.j
|
|
|
103
103
|
const c = new Proxy(Array.isArray(e) ? [] : {}, s);
|
|
104
104
|
// The wrapper stands for its store proxy wherever the derive's result
|
|
105
105
|
// carries it (`wrap`, `unwrapValue`, reconcile's slot matching).
|
|
106
|
-
const
|
|
107
|
-
if (
|
|
106
|
+
const a = e[$TARGET];
|
|
107
|
+
if (a !== undefined) setLookup(c, a);
|
|
108
108
|
return c;
|
|
109
109
|
}
|
|
110
110
|
|
|
@@ -120,8 +120,14 @@ function cloneState(e, t) {
|
|
|
120
120
|
* (`notifyStatus`): a verdict or re-derive reader re-runs, any other is
|
|
121
121
|
* pending derivatively on the derive (its readers hold; it re-runs at the
|
|
122
122
|
* landing). The leaves do not subscribe to the derive, so the family does
|
|
123
|
-
* the walk. */ function wakeFamily(e
|
|
124
|
-
const
|
|
123
|
+
* the walk. */ function wakeFamily(e) {
|
|
124
|
+
const t = e.node;
|
|
125
|
+
// Pending on the derive itself, whatever source took it there (an upstream
|
|
126
|
+
// memo's flight reaches it as a NotReady of that memo, #4271): the leaves
|
|
127
|
+
// are not that source's dependents, so only the family's settle — which
|
|
128
|
+
// retires the derive (`settleFamily`) — reaches the readers parked here. A
|
|
129
|
+
// reader the landing leaves unchanged does not re-run to clear it (#4305).
|
|
130
|
+
const r = new NotReadyError(t);
|
|
125
131
|
e.woke = true;
|
|
126
132
|
forEachFamilyNode(e, e => {
|
|
127
133
|
if (e.o === null) return;
|
|
@@ -129,12 +135,12 @@ function cloneState(e, t) {
|
|
|
129
135
|
// between them would: a dependent recovering one branch stays pending
|
|
130
136
|
// through a leaf it still reads (core `retryReaches`), and the landing's
|
|
131
137
|
// walk retires the copy first (`settleFamily` → `settlePendingSource`).
|
|
132
|
-
addPendingSource(e,
|
|
138
|
+
addPendingSource(e, t);
|
|
133
139
|
// Its readers: core's propagation from the leaf — a verdict or re-derive
|
|
134
140
|
// reader re-runs, any other is pending derivatively on the derive and
|
|
135
141
|
// queued for the frame (held with it: the frame waits on the flight
|
|
136
142
|
// through them, `blocked`).
|
|
137
|
-
propagateStatus(e, STATUS_PENDING,
|
|
143
|
+
propagateStatus(e, STATUS_PENDING, r);
|
|
138
144
|
});
|
|
139
145
|
}
|
|
140
146
|
|
|
@@ -160,6 +166,12 @@ function cloneState(e, t) {
|
|
|
160
166
|
});
|
|
161
167
|
}
|
|
162
168
|
|
|
169
|
+
/** A source's status reached the derive by propagation (core
|
|
170
|
+
* `propagateStatus`), its pass not re-run: the family learns it as from the
|
|
171
|
+
* pass's own throw. */ function familyStatus(e) {
|
|
172
|
+
if (e & STATUS_PENDING) wakeFamily(this); else if (e & STATUS_ERROR) errorFamily(this);
|
|
173
|
+
}
|
|
174
|
+
|
|
163
175
|
function forEachFamilyNode(e, t) {
|
|
164
176
|
for (const r of e.live) {
|
|
165
177
|
const e = r.n;
|
|
@@ -179,18 +191,18 @@ function forEachFamilyNode(e, t) {
|
|
|
179
191
|
const i = getOwner();
|
|
180
192
|
const s = e[$TARGET];
|
|
181
193
|
const c = s.fam;
|
|
182
|
-
const
|
|
194
|
+
const a = c.run = (c.run || 0) + 1;
|
|
183
195
|
let l;
|
|
184
196
|
// Open loading window (seedLoadingValue): the observable store IS commit #0
|
|
185
197
|
// for the whole first flight — the derive works a detached shadow of the
|
|
186
198
|
// seed so draft writes cannot tear through to readers (#2988). Every
|
|
187
199
|
// commit point reconciles the shadow through the normal commit path.
|
|
188
|
-
const
|
|
200
|
+
const u = i.ce ? cloneState(s.v, s.s) : null;
|
|
189
201
|
// The question a write of this run answers: inside a slice, the slice's
|
|
190
202
|
// (the sync pass); in a continuation — the flight still registered — the
|
|
191
203
|
// flight's (`handleAsync` stamped it with the action that asked).
|
|
192
|
-
const asking = () => question || (i.T !== null && i.T.
|
|
193
|
-
const f = wrapDraft(e, () => c.run ===
|
|
204
|
+
const asking = () => question || (i.T !== null && i.T.Ee !== null ? i.T.de : 0);
|
|
205
|
+
const f = wrapDraft(e, () => c.run === a && !isDisposed(i), n, s.s,
|
|
194
206
|
// A write after the run returned (a continuation, a callback) arms the
|
|
195
207
|
// drain itself when no landing will.
|
|
196
208
|
() => {
|
|
@@ -199,14 +211,14 @@ function forEachFamilyNode(e, t) {
|
|
|
199
211
|
// The creation run commits directly (a memo's first value is its
|
|
200
212
|
// `_value`); every later run — a re-derive in a flush, an async landing
|
|
201
213
|
// — stages and commits with the flush like a memo's recompute.
|
|
202
|
-
const d =
|
|
214
|
+
const d = a === 1;
|
|
203
215
|
const pass = () => storeSetter(f, n => {
|
|
204
|
-
l = t(
|
|
216
|
+
l = t(u ?? n);
|
|
205
217
|
const commit = t => {
|
|
206
218
|
// Shadow run: commit a detached snapshot, never the shadow itself
|
|
207
219
|
// (adoption takes the value by identity — handing it the live
|
|
208
220
|
// shadow would fuse the draft to the observable store).
|
|
209
|
-
if (
|
|
221
|
+
if (u && (t === undefined || t === u)) t = cloneState(u, s.s);
|
|
210
222
|
if (t !== n && t !== undefined) {
|
|
211
223
|
const write = () => {
|
|
212
224
|
const o = question;
|
|
@@ -228,7 +240,7 @@ function forEachFamilyNode(e, t) {
|
|
|
228
240
|
// (a fallback value, not pending) re-runs too (#4070).
|
|
229
241
|
insertSubs(i);
|
|
230
242
|
};
|
|
231
|
-
const
|
|
243
|
+
const a = handleAsync(i, l, commit, (e, t) => {
|
|
232
244
|
// The flight rejected: the leaves' readers learn it from here —
|
|
233
245
|
// they do not subscribe to the derive. Pending again (a NotReady
|
|
234
246
|
// rejection): the wake, as for the pass. Errored: every live
|
|
@@ -236,9 +248,9 @@ function forEachFamilyNode(e, t) {
|
|
|
236
248
|
// #2897) — and the flush that runs them advances the clock, so a
|
|
237
249
|
// later tracked re-read may retry (core `read`).
|
|
238
250
|
if (d && i.m & STATUS_UNINITIALIZED) return;
|
|
239
|
-
if (t) wakeFamily(c
|
|
251
|
+
if (t) wakeFamily(c); else errorFamily(c);
|
|
240
252
|
});
|
|
241
|
-
if (!i.ce) commit(
|
|
253
|
+
if (!i.ce) commit(a);
|
|
242
254
|
}, false);
|
|
243
255
|
try {
|
|
244
256
|
d ? runDirect(pass) : pass();
|
|
@@ -248,14 +260,14 @@ function forEachFamilyNode(e, t) {
|
|
|
248
260
|
// they do not subscribe to the derive.
|
|
249
261
|
// A synchronous error the same way (#3956: a rerun that finds the
|
|
250
262
|
// entry failed throws): every live reader re-derives and meets it.
|
|
251
|
-
if (!d) e instanceof NotReadyError ? wakeFamily(c
|
|
263
|
+
if (!d) e instanceof NotReadyError ? wakeFamily(c) : errorFamily(c);
|
|
252
264
|
throw e;
|
|
253
265
|
}
|
|
254
266
|
// A pass that returned with a flight up (an iterator's sync first yield):
|
|
255
267
|
// the wake, as for the throw. Not a sync pass that superseded one — the
|
|
256
268
|
// status it reads is the dead flight's, cleared when this pass settles
|
|
257
269
|
// (#3181: a reader the settle walk had just released, re-parked for good).
|
|
258
|
-
if (i.m & STATUS_PENDING && i.T.
|
|
270
|
+
if (i.m & STATUS_PENDING && i.T.Ee !== null && !i.ce && !d) wakeFamily(c);
|
|
259
271
|
return i;
|
|
260
272
|
}
|
|
261
273
|
|
|
@@ -268,6 +280,7 @@ function createProjectionInternal(e, t, r) {
|
|
|
268
280
|
map: new WeakMap,
|
|
269
281
|
node: null,
|
|
270
282
|
live: new Set,
|
|
283
|
+
st: familyStatus,
|
|
271
284
|
shallow: !!r?.shallow,
|
|
272
285
|
// The row key, for a child paired after the adoption (store.ts
|
|
273
286
|
// `adoptChild`, #3712) as the adoption pairs them.
|
|
@@ -31,7 +31,7 @@ import { $TARGET, markRawIngest, isWrappable, rawValuesUsed, isRawValue } from "
|
|
|
31
31
|
// truth but an optimistic edit — the keyed diff is written into the draft
|
|
32
32
|
// (a matched row keeps its proxy, its changed leaves become its guesses),
|
|
33
33
|
// and the setter's exit turns the draft into guesses like any.
|
|
34
|
-
if (userWriting() && f.fam?.opt === true) {
|
|
34
|
+
if (optHooks && userWriting() && f.fam?.opt === true) {
|
|
35
35
|
optHooks.reconcile(n, unwrapValue(e), i);
|
|
36
36
|
return;
|
|
37
37
|
}
|
|
@@ -72,7 +72,7 @@ import { $TARGET, markRawIngest, isWrappable, rawValuesUsed, isRawValue } from "
|
|
|
72
72
|
// Q-D: a landing on an optimistic family is reconciled against the VIEW
|
|
73
73
|
// — key matching from the arrangement the guesses made (R28), so a row
|
|
74
74
|
// the guess added keeps its proxy when the server returns it.
|
|
75
|
-
const i = e.fam?.opt === true ? optHooks.view(e, f) : f;
|
|
75
|
+
const i = optHooks && e.fam?.opt === true ? optHooks.view(e, f) : f;
|
|
76
76
|
const l = Array.isArray(n);
|
|
77
77
|
const r = e.s === true;
|
|
78
78
|
adoptPB(e, n, false);
|