@solidjs/signals 2.0.0-rc.15 → 2.0.0-rc.16
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 +785 -367
- package/dist/dev.attribution.js +75 -52
- package/dist/dev.js +1120 -567
- package/dist/observe/affects-marks.js +86 -0
- package/dist/observe/affects.js +22 -73
- package/dist/observe/boundaries.js +191 -189
- package/dist/observe/core/async.js +175 -131
- package/dist/observe/core/attribution-queries.js +1 -1
- package/dist/observe/core/attribution.js +176 -159
- package/dist/observe/core/constants.js +17 -3
- package/dist/observe/core/context.js +3 -3
- package/dist/observe/core/core.js +503 -363
- package/dist/observe/core/dev.js +66 -38
- package/dist/observe/core/effect.js +48 -48
- package/dist/observe/core/error.js +5 -3
- package/dist/observe/core/external.js +5 -6
- package/dist/observe/core/graph.js +57 -43
- package/dist/observe/core/heap.js +33 -33
- package/dist/observe/core/identities.js +62 -0
- package/dist/observe/core/lanes.js +226 -259
- package/dist/observe/core/owner.js +62 -50
- package/dist/observe/core/scheduler.js +319 -171
- package/dist/observe/core/truth.js +45 -0
- package/dist/observe/core/verdict.js +88 -50
- package/dist/observe/deferred.js +184 -0
- package/dist/observe/index.js +7 -1
- package/dist/observe/map.js +345 -260
- package/dist/observe/reveal.js +76 -76
- package/dist/observe/signals.js +41 -30
- package/dist/observe/store/affects.js +6 -6
- package/dist/observe/store/edges.js +39 -0
- package/dist/observe/store/optimistic.js +41 -36
- package/dist/observe/store/projection.js +68 -55
- package/dist/observe/store/store.js +157 -104
- package/dist/prod/affects-marks.js +86 -0
- package/dist/prod/affects.js +23 -72
- package/dist/prod/boundaries.js +155 -153
- package/dist/prod/core/async.js +171 -127
- package/dist/prod/core/constants.js +17 -3
- package/dist/prod/core/context.js +3 -3
- package/dist/prod/core/core.js +478 -342
- package/dist/prod/core/effect.js +68 -68
- package/dist/prod/core/error.js +5 -3
- package/dist/prod/core/external.js +5 -6
- package/dist/prod/core/graph.js +57 -43
- package/dist/prod/core/heap.js +38 -38
- package/dist/prod/core/identities.js +62 -0
- package/dist/prod/core/lanes.js +217 -250
- package/dist/prod/core/owner.js +62 -51
- package/dist/prod/core/scheduler.js +310 -162
- package/dist/prod/core/truth.js +45 -0
- package/dist/prod/core/verdict.js +87 -49
- package/dist/prod/deferred.js +182 -0
- package/dist/prod/index.js +7 -1
- package/dist/prod/map.js +360 -275
- package/dist/prod/reveal.js +76 -76
- package/dist/prod/signals.js +41 -30
- package/dist/prod/store/affects.js +6 -6
- package/dist/prod/store/edges.js +39 -0
- package/dist/prod/store/optimistic.js +37 -33
- package/dist/prod/store/projection.js +25 -19
- package/dist/prod/store/store.js +142 -96
- package/dist/types/affects-marks.d.ts +14 -0
- package/dist/types/boundaries.d.ts +1 -1
- package/dist/types/core/async.d.ts +10 -0
- package/dist/types/core/constants.d.ts +13 -1
- package/dist/types/core/core.d.ts +44 -2
- package/dist/types/core/dev.d.ts +43 -13
- package/dist/types/core/graph.d.ts +11 -0
- package/dist/types/core/identities.d.ts +17 -0
- package/dist/types/core/index.d.ts +2 -1
- package/dist/types/core/lanes.d.ts +2 -14
- package/dist/types/core/owner.d.ts +5 -3
- package/dist/types/core/scheduler.d.ts +47 -28
- package/dist/types/core/truth.d.ts +16 -0
- package/dist/types/core/types.d.ts +21 -0
- package/dist/types/core/verdict.d.ts +32 -0
- package/dist/types/deferred.d.ts +28 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types/map.d.ts +2 -2
- package/dist/types/signals.d.ts +28 -7
- package/dist/types/store/edges.d.ts +9 -0
- package/dist/types/store/index.d.ts +10 -3
- package/dist/types/store/optimistic.d.ts +3 -2
- package/dist/types/store/projection.d.ts +4 -3
- package/dist/types/store/store.d.ts +1 -1
- package/dist/types/store/target.d.ts +16 -8
- package/dist/types/store/types.d.ts +14 -0
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@ import { CONFIG_OVERRIDE, CONFIG_AUTO_DISPOSE, NOT_PENDING } from "../core/const
|
|
|
2
2
|
|
|
3
3
|
import { computed, ext, untrack, read, isEqual } from "../core/core.js";
|
|
4
4
|
|
|
5
|
-
import { pendingGuessOf,
|
|
5
|
+
import { pendingGuessOf, optimisticWrite } from "../core/lanes.js";
|
|
6
6
|
|
|
7
7
|
import { getOwner } from "../core/owner.js";
|
|
8
8
|
|
|
@@ -18,6 +18,8 @@ import { $OWNER } from "./target.js";
|
|
|
18
18
|
|
|
19
19
|
import { $TARGET, markRawIngest, $TRACK, isWrappable } from "./types.js";
|
|
20
20
|
|
|
21
|
+
import { laneValueOf } from "../core/truth.js";
|
|
22
|
+
|
|
21
23
|
/**
|
|
22
24
|
* Store — optimistic stores on lanes (plan sec. 31, S4; INTERNALS §3/§7, RUL-3).
|
|
23
25
|
*
|
|
@@ -81,7 +83,7 @@ function notifyOptimisticWrites(e, n) {
|
|
|
81
83
|
// inner store's truth for its key before guessing over it.
|
|
82
84
|
const o = e.ch ? e.v : null;
|
|
83
85
|
const guess = (e, n, i, r) => {
|
|
84
|
-
if (o !== null) e.
|
|
86
|
+
if (o !== null) e.Ie = i ? n in t : unwrapValue(t[n]);
|
|
85
87
|
// By value: a function leaf is a value, not an updater (#3017).
|
|
86
88
|
optimisticWrite(e, () => r);
|
|
87
89
|
};
|
|
@@ -266,10 +268,10 @@ function arrangementEqual(e, n, t) {
|
|
|
266
268
|
* node is born for it as the lane's derivation), on `length` only when the
|
|
267
269
|
* committed length differs, and as the `LaneView`'s base for structural
|
|
268
270
|
* reads. Unkeyed families compose
|
|
269
|
-
* positionally — the guess stands as written (the documented residue). */ GlobalQueue.
|
|
270
|
-
const t = e.
|
|
271
|
-
if (t === undefined || e.
|
|
272
|
-
const i = e.
|
|
271
|
+
* positionally — the guess stands as written (the documented residue). */ GlobalQueue.an = (e, n) => {
|
|
272
|
+
const t = e.O;
|
|
273
|
+
if (t === undefined || e.Vt !== $TRACK) return;
|
|
274
|
+
const i = e.T.V;
|
|
273
275
|
if (!(i instanceof LaneView)) return;
|
|
274
276
|
if (!Array.isArray(n) || !Array.isArray(i.rows)) {
|
|
275
277
|
i.base = n;
|
|
@@ -313,7 +315,7 @@ function arrangementEqual(e, n, t) {
|
|
|
313
315
|
// key's new object is the same row, its target adopted it).
|
|
314
316
|
if (n === undefined) {
|
|
315
317
|
if (!sameRow(c[e], a[e], r)) laneSet(getNode(t, e), a[e], l);
|
|
316
|
-
} else if (!sameRow(n.
|
|
318
|
+
} else if (!sameRow(n.l & CONFIG_OVERRIDE ? n.T.V : c[e], a[e], r)) laneSet(n, a[e], l);
|
|
317
319
|
}
|
|
318
320
|
if (d !== null) {
|
|
319
321
|
for (let e = a.length; ;e++) {
|
|
@@ -322,7 +324,7 @@ function arrangementEqual(e, n, t) {
|
|
|
322
324
|
laneSet(n, undefined, l);
|
|
323
325
|
}
|
|
324
326
|
const e = d.length;
|
|
325
|
-
if (e !== undefined && (e.
|
|
327
|
+
if (e !== undefined && (e.l & CONFIG_OVERRIDE || c.length !== a.length)) laneSet(e, a.length, l);
|
|
326
328
|
}
|
|
327
329
|
};
|
|
328
330
|
|
|
@@ -337,12 +339,12 @@ function sameRow(e, n, t) {
|
|
|
337
339
|
* node that was not the lane's becomes its derivation (its committed value
|
|
338
340
|
* untouched beneath; the lane's end commits the latest). */ function laneSet(e, n, t) {
|
|
339
341
|
const i = ext(e);
|
|
340
|
-
if (!(e.
|
|
341
|
-
e.
|
|
342
|
+
if (!(e.l & CONFIG_OVERRIDE)) {
|
|
343
|
+
e.l |= CONFIG_OVERRIDE;
|
|
342
344
|
list(e, t);
|
|
343
|
-
} else if (i.
|
|
344
|
-
i.
|
|
345
|
-
if (e.
|
|
345
|
+
} else if (i.V === n) return;
|
|
346
|
+
i.V = n;
|
|
347
|
+
if (e.o !== null) {
|
|
346
348
|
insertSubs(e);
|
|
347
349
|
laneDirty(e, t);
|
|
348
350
|
}
|
|
@@ -387,7 +389,7 @@ function sweepOverlaid() {
|
|
|
387
389
|
// The container shows its backing again (a shown arrangement guess
|
|
388
390
|
// that ended without a landing left its `LaneView` as the value).
|
|
389
391
|
const t = e.k;
|
|
390
|
-
if (t !== null && t.
|
|
392
|
+
if (t !== null && t.Ie instanceof LaneView) t.Ie = t.Ie.base;
|
|
391
393
|
}
|
|
392
394
|
if (n.size === 0) overlaidFamilies.delete(e);
|
|
393
395
|
}
|
|
@@ -404,11 +406,11 @@ function sweepOverlaid() {
|
|
|
404
406
|
if (i !== null) for (const e of Reflect.ownKeys(i)) {
|
|
405
407
|
const r = i[e];
|
|
406
408
|
const o = untrack(() => unwrapValue(n[e]));
|
|
407
|
-
if (r.
|
|
408
|
-
r.
|
|
409
|
+
if (r.Ye && r.Ye(r.Ie, o)) continue;
|
|
410
|
+
r.Ie = o;
|
|
409
411
|
// (The lane's end notified it this epoch when the shown value and the
|
|
410
412
|
// covered one differed — its readers re-derive already.)
|
|
411
|
-
if (r.
|
|
413
|
+
if (r.o !== null && r.Ot !== notifyEpoch) {
|
|
412
414
|
insertSubs(r);
|
|
413
415
|
t = true;
|
|
414
416
|
}
|
|
@@ -417,9 +419,9 @@ function sweepOverlaid() {
|
|
|
417
419
|
if (r !== null) for (const e of Reflect.ownKeys(r)) {
|
|
418
420
|
const i = r[e];
|
|
419
421
|
const o = untrack(() => e in n);
|
|
420
|
-
if (i.
|
|
421
|
-
i.
|
|
422
|
-
if (i.
|
|
422
|
+
if (i.Ie === o) continue;
|
|
423
|
+
i.Ie = o;
|
|
424
|
+
if (i.o !== null && i.Ot !== notifyEpoch) {
|
|
423
425
|
insertSubs(i);
|
|
424
426
|
t = true;
|
|
425
427
|
}
|
|
@@ -427,9 +429,9 @@ function sweepOverlaid() {
|
|
|
427
429
|
// The arrangement the readers saw (the shown guess) against the inner's
|
|
428
430
|
// now: a structural reader re-derives when they differ.
|
|
429
431
|
const o = e.k;
|
|
430
|
-
if (o !== null && o.
|
|
432
|
+
if (o !== null && o.o !== null && o.Ie instanceof LaneView && o.Ot !== notifyEpoch) {
|
|
431
433
|
const i = Array.isArray(n) ? untrack(() => n.map(unwrapValue)) : n;
|
|
432
|
-
if (!arrangementEqual(o.
|
|
434
|
+
if (!arrangementEqual(o.Ie.rows, i, e.fam?.key ?? null)) {
|
|
433
435
|
insertSubs(o);
|
|
434
436
|
t = true;
|
|
435
437
|
}
|
|
@@ -438,12 +440,12 @@ function sweepOverlaid() {
|
|
|
438
440
|
}
|
|
439
441
|
|
|
440
442
|
function carriesLane(e) {
|
|
441
|
-
if (e.k !== null && e.k.
|
|
442
|
-
if (e.dk !== null && e.dk.
|
|
443
|
+
if (e.k !== null && e.k.l & CONFIG_OVERRIDE) return true;
|
|
444
|
+
if (e.dk !== null && e.dk.l & CONFIG_OVERRIDE) return true;
|
|
443
445
|
const n = e.n;
|
|
444
|
-
if (n !== null) for (const e of Reflect.ownKeys(n)) if (n[e].
|
|
446
|
+
if (n !== null) for (const e of Reflect.ownKeys(n)) if (n[e].l & CONFIG_OVERRIDE) return true;
|
|
445
447
|
const t = e.h;
|
|
446
|
-
if (t !== null) for (const e of Reflect.ownKeys(t)) if (t[e].
|
|
448
|
+
if (t !== null) for (const e of Reflect.ownKeys(t)) if (t[e].l & CONFIG_OVERRIDE) return true;
|
|
447
449
|
return false;
|
|
448
450
|
}
|
|
449
451
|
|
|
@@ -461,9 +463,9 @@ function overlaid(e) {
|
|
|
461
463
|
* the backing answers. */ function optimisticHas(e, n) {
|
|
462
464
|
if (!overlaid(e)) return undefined;
|
|
463
465
|
const t = e.h?.[n];
|
|
464
|
-
if (t !== undefined && t.
|
|
466
|
+
if (t !== undefined && t.l & CONFIG_OVERRIDE) return !!shown(t);
|
|
465
467
|
const i = e.n?.[n];
|
|
466
|
-
if (i !== undefined && i.
|
|
468
|
+
if (i !== undefined && i.l & CONFIG_OVERRIDE) return shown(i) !== undefined;
|
|
467
469
|
return undefined;
|
|
468
470
|
}
|
|
469
471
|
|
|
@@ -474,7 +476,7 @@ function overlaid(e) {
|
|
|
474
476
|
if (t === undefined) return undefined;
|
|
475
477
|
if (!t) return null;
|
|
476
478
|
const i = e.n?.[n];
|
|
477
|
-
const r = i !== undefined && i.
|
|
479
|
+
const r = i !== undefined && i.l & CONFIG_OVERRIDE ? shown(i) : e.v[n];
|
|
478
480
|
// An array's `length` is reported as the array has it (non-configurable).
|
|
479
481
|
if (n === "length" && Array.isArray(e.v)) return {
|
|
480
482
|
value: r,
|
|
@@ -507,7 +509,7 @@ i = false) {
|
|
|
507
509
|
for (const e of Reflect.ownKeys(o)) {
|
|
508
510
|
const r = o[e];
|
|
509
511
|
let s;
|
|
510
|
-
if (r.
|
|
512
|
+
if (r.l & CONFIG_OVERRIDE) s = t(r); else if (!i || (s = pendingGuessOf(r)) === NOT_PENDING) continue;
|
|
511
513
|
if (e === "length" && Array.isArray(n)) {
|
|
512
514
|
if (n.length !== s) ensure().length = s;
|
|
513
515
|
} else if (!isEqual(n[e], s) || !hasOwn.call(n, e)) {
|
|
@@ -520,7 +522,7 @@ i = false) {
|
|
|
520
522
|
for (const e of Reflect.ownKeys(s)) {
|
|
521
523
|
const o = s[e];
|
|
522
524
|
let a;
|
|
523
|
-
if (o.
|
|
525
|
+
if (o.l & CONFIG_OVERRIDE) a = t(o); else if (!i || (a = pendingGuessOf(o)) === NOT_PENDING) continue;
|
|
524
526
|
const f = !!a;
|
|
525
527
|
const u = r ?? n;
|
|
526
528
|
if (!f && e in u) delete ensure()[e];
|
|
@@ -532,7 +534,9 @@ i = false) {
|
|
|
532
534
|
function createOptimisticStore(e, n, t) {
|
|
533
535
|
const i = typeof e === "function";
|
|
534
536
|
const r = i ? t : n;
|
|
535
|
-
|
|
537
|
+
// Seedless derived form: the root starts as an empty record (see
|
|
538
|
+
// createProjectionInternal).
|
|
539
|
+
const o = i ? n || {} : e;
|
|
536
540
|
const s = r?.key === undefined ? "id" : r.key;
|
|
537
541
|
const a = {
|
|
538
542
|
map: new WeakMap,
|
|
@@ -543,7 +547,7 @@ function createOptimisticStore(e, n, t) {
|
|
|
543
547
|
key: typeof s === "function" ? s : s === null ? null : e => isWrappable(e) ? e[s] : undefined
|
|
544
548
|
};
|
|
545
549
|
const f = wrap(o, null, null, a);
|
|
546
|
-
nameStore(f, r?.name);
|
|
550
|
+
nameStore(f, r?.name, r?.loc);
|
|
547
551
|
if (a.shallow) {
|
|
548
552
|
f[$TARGET].s = true;
|
|
549
553
|
markRawIngest(o);
|
|
@@ -554,15 +558,16 @@ function createOptimisticStore(e, n, t) {
|
|
|
554
558
|
if (r?.seedLoadingValue) t = {
|
|
555
559
|
loadingValue: undefined
|
|
556
560
|
};
|
|
557
|
-
if (r?.name) t = {
|
|
561
|
+
if (r?.name || r?.loc) t = {
|
|
558
562
|
...t,
|
|
559
|
-
name: r.name
|
|
563
|
+
name: r.name,
|
|
564
|
+
loc: r.loc
|
|
560
565
|
};
|
|
561
566
|
const i = computed(() => {
|
|
562
567
|
if (!a.node) a.node = getOwner();
|
|
563
568
|
runProjectionComputed(f, n, s);
|
|
564
569
|
}, t);
|
|
565
|
-
i.
|
|
570
|
+
i.l &= ~CONFIG_AUTO_DISPOSE;
|
|
566
571
|
a.node = i;
|
|
567
572
|
}
|
|
568
573
|
return [ f, e => storeSetter(f, e) ];
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { attrHooks } from "../core/attribution-hooks.js";
|
|
2
|
+
|
|
1
3
|
import { CONFIG_AUTO_DISPOSE, STATUS_PENDING, STATUS_UNINITIALIZED } from "../core/constants.js";
|
|
2
4
|
|
|
3
5
|
import { computed } from "../core/core.js";
|
|
@@ -10,15 +12,15 @@ import { enqueueSub } from "../core/heap.js";
|
|
|
10
12
|
|
|
11
13
|
import { getOwner, isDisposed } from "../core/owner.js";
|
|
12
14
|
|
|
13
|
-
import { question, setQuestion, schedule } from "../core/scheduler.js";
|
|
15
|
+
import { question, setQuestion, insertSubs, schedule } from "../core/scheduler.js";
|
|
14
16
|
|
|
15
17
|
import { reconcileState } from "./reconcile.js";
|
|
16
18
|
|
|
17
19
|
import { wrap, nameStore, storeSetter, runDirect } from "./store.js";
|
|
18
20
|
|
|
19
|
-
import { setLookup } from "./target.js";
|
|
21
|
+
import { storeOwners, setLookup } from "./target.js";
|
|
20
22
|
|
|
21
|
-
import { $TARGET, markRawIngest,
|
|
23
|
+
import { $TARGET, markRawIngest, isWrappable, setWriteOverride } from "./types.js";
|
|
22
24
|
|
|
23
25
|
/**
|
|
24
26
|
* Store — projections (plan sec. 31, S3; INTERNALS §7/§7b).
|
|
@@ -50,22 +52,22 @@ import { $TARGET, markRawIngest, setWriteOverride, isWrappable } from "./types.j
|
|
|
50
52
|
* set/getOwnPropertyDescriptor/defineProperty. With the store proxy as
|
|
51
53
|
* target those checks re-enter the store's traps OUTSIDE the override
|
|
52
54
|
* bracket, so `Object.keys(state)` in a derive continuation fired the gate.
|
|
53
|
-
*/ function wrapDraft(e, t, r,
|
|
55
|
+
*/ function wrapDraft(e, t, r, o, n, i) {
|
|
54
56
|
const mutate = e => {
|
|
55
57
|
if (!t()) return true;
|
|
56
58
|
setWriteOverride(true);
|
|
57
59
|
// A continuation's write is the flight's answer: it asks the flight's
|
|
58
60
|
// question (A18 provenance — a landing beneath a newer guess is held,
|
|
59
61
|
// not a correction; lanes.ts `laneWrite`).
|
|
60
|
-
const
|
|
62
|
+
const o = question;
|
|
61
63
|
if (i !== undefined) setQuestion(i());
|
|
62
64
|
try {
|
|
63
65
|
r ? r(e) : e();
|
|
64
66
|
} finally {
|
|
65
67
|
setWriteOverride(false);
|
|
66
|
-
setQuestion(
|
|
68
|
+
setQuestion(o);
|
|
67
69
|
}
|
|
68
|
-
if (
|
|
70
|
+
if (n) n();
|
|
69
71
|
return true;
|
|
70
72
|
};
|
|
71
73
|
const read = e => {
|
|
@@ -79,23 +81,23 @@ import { $TARGET, markRawIngest, setWriteOverride, isWrappable } from "./types.j
|
|
|
79
81
|
const s = {
|
|
80
82
|
get(s, c) {
|
|
81
83
|
const u = read(() => e[c]);
|
|
82
|
-
return !
|
|
84
|
+
return !o && typeof u === "object" && u !== null && c !== $TARGET ? wrapDraft(u, t, r, false, n, i) : u;
|
|
83
85
|
},
|
|
84
86
|
has: (t, r) => read(() => r in e),
|
|
85
|
-
set: (t, r,
|
|
86
|
-
e[r] =
|
|
87
|
+
set: (t, r, o) => mutate(() => {
|
|
88
|
+
e[r] = o;
|
|
87
89
|
}),
|
|
88
90
|
deleteProperty: (t, r) => mutate(() => {
|
|
89
91
|
delete e[r];
|
|
90
92
|
}),
|
|
91
93
|
ownKeys: () => read(() => Reflect.ownKeys(e)),
|
|
92
94
|
getOwnPropertyDescriptor(t, r) {
|
|
93
|
-
const
|
|
94
|
-
if (
|
|
95
|
-
return
|
|
95
|
+
const o = read(() => Reflect.getOwnPropertyDescriptor(e, r));
|
|
96
|
+
if (o) o.configurable = true;
|
|
97
|
+
return o;
|
|
96
98
|
},
|
|
97
|
-
defineProperty: (t, r,
|
|
98
|
-
Reflect.defineProperty(e, r,
|
|
99
|
+
defineProperty: (t, r, o) => mutate(() => {
|
|
100
|
+
Reflect.defineProperty(e, r, o);
|
|
99
101
|
})
|
|
100
102
|
};
|
|
101
103
|
const c = new Proxy(Array.isArray(e) ? [] : {}, s);
|
|
@@ -122,7 +124,7 @@ function cloneState(e, t) {
|
|
|
122
124
|
const r = e.node;
|
|
123
125
|
e.woke = true;
|
|
124
126
|
forEachFamilyNode(e, e => {
|
|
125
|
-
if (e.
|
|
127
|
+
if (e.o === null) return;
|
|
126
128
|
// The leaf carries the derive's pending as a propagated copy, as a memo
|
|
127
129
|
// between them would: a dependent recovering one branch stays pending
|
|
128
130
|
// through a leaf it still reads (core `retryReaches`), and the landing's
|
|
@@ -139,7 +141,7 @@ function cloneState(e, t) {
|
|
|
139
141
|
/** The derive's flight rejected: every live reader of the family
|
|
140
142
|
* re-derives (its pull throws the derive's error). */ function errorFamily(e) {
|
|
141
143
|
forEachFamilyNode(e, e => {
|
|
142
|
-
if (e.
|
|
144
|
+
if (e.o === null) return;
|
|
143
145
|
forEachDependent(e, e => {
|
|
144
146
|
enqueueSub(e);
|
|
145
147
|
});
|
|
@@ -154,7 +156,7 @@ function cloneState(e, t) {
|
|
|
154
156
|
e.woke = false;
|
|
155
157
|
const t = e.node;
|
|
156
158
|
forEachFamilyNode(e, e => {
|
|
157
|
-
if (e.
|
|
159
|
+
if (e.o !== null) settlePendingSource(e, t);
|
|
158
160
|
});
|
|
159
161
|
}
|
|
160
162
|
|
|
@@ -162,8 +164,8 @@ function forEachFamilyNode(e, t) {
|
|
|
162
164
|
for (const r of e.live) {
|
|
163
165
|
const e = r.n;
|
|
164
166
|
if (e !== null) for (const r of Reflect.ownKeys(e)) t(e[r]);
|
|
165
|
-
const
|
|
166
|
-
if (
|
|
167
|
+
const o = r.h;
|
|
168
|
+
if (o !== null) for (const e of Reflect.ownKeys(o)) t(o[e]);
|
|
167
169
|
if (r.k !== null) t(r.k);
|
|
168
170
|
if (r.dk !== null) t(r.dk);
|
|
169
171
|
}
|
|
@@ -173,7 +175,7 @@ function forEachFamilyNode(e, t) {
|
|
|
173
175
|
* result (sync, or each async landing) through the reconcile channel.
|
|
174
176
|
* Draft validity is per run (R37): live from here until the NEXT run starts
|
|
175
177
|
* — a sync derive that subscribes to an external source and pushes into
|
|
176
|
-
* the draft from the callback (#3585) is the model use. */ function runProjectionComputed(e, t, r,
|
|
178
|
+
* the draft from the callback (#3585) is the model use. */ function runProjectionComputed(e, t, r, o, n) {
|
|
177
179
|
const i = getOwner();
|
|
178
180
|
const s = e[$TARGET];
|
|
179
181
|
const c = s.fam;
|
|
@@ -183,43 +185,48 @@ function forEachFamilyNode(e, t) {
|
|
|
183
185
|
// for the whole first flight — the derive works a detached shadow of the
|
|
184
186
|
// seed so draft writes cannot tear through to readers (#2988). Every
|
|
185
187
|
// commit point reconciles the shadow through the normal commit path.
|
|
186
|
-
const a = i.
|
|
188
|
+
const a = i.ce ? cloneState(s.v, s.s) : null;
|
|
187
189
|
// The question a write of this run answers: inside a slice, the slice's
|
|
188
190
|
// (the sync pass); in a continuation — the flight still registered — the
|
|
189
191
|
// flight's (`handleAsync` stamped it with the action that asked).
|
|
190
|
-
const asking = () => question || (i.
|
|
191
|
-
const f = wrapDraft(e, () => c.run === u && !isDisposed(i),
|
|
192
|
+
const asking = () => question || (i.T !== null && i.T.Se !== null ? i.T.Ee : 0);
|
|
193
|
+
const f = wrapDraft(e, () => c.run === u && !isDisposed(i), n, s.s,
|
|
192
194
|
// A write after the run returned (a continuation, a callback) arms the
|
|
193
195
|
// drain itself when no landing will.
|
|
194
196
|
() => {
|
|
195
|
-
if (!(i.
|
|
197
|
+
if (!(i.m & STATUS_PENDING) && !i.ce) schedule();
|
|
196
198
|
}, asking);
|
|
197
199
|
// The creation run commits directly (a memo's first value is its
|
|
198
200
|
// `_value`); every later run — a re-derive in a flush, an async landing
|
|
199
201
|
// — stages and commits with the flush like a memo's recompute.
|
|
200
202
|
const d = u === 1;
|
|
201
|
-
const pass = () => storeSetter(f,
|
|
202
|
-
l = t(a ??
|
|
203
|
+
const pass = () => storeSetter(f, n => {
|
|
204
|
+
l = t(a ?? n);
|
|
203
205
|
const commit = t => {
|
|
204
206
|
// Shadow run: commit a detached snapshot, never the shadow itself
|
|
205
207
|
// (adoption takes the value by identity — handing it the live
|
|
206
208
|
// shadow would fuse the draft to the observable store).
|
|
207
209
|
if (a && (t === undefined || t === a)) t = cloneState(a, s.s);
|
|
208
|
-
if (t !==
|
|
210
|
+
if (t !== n && t !== undefined) {
|
|
209
211
|
const write = () => {
|
|
210
|
-
const
|
|
212
|
+
const o = question;
|
|
211
213
|
setQuestion(asking());
|
|
212
214
|
try {
|
|
213
215
|
storeSetter(e, e => reconcileState(t, e, r, true), false);
|
|
214
216
|
} finally {
|
|
215
|
-
setQuestion(
|
|
217
|
+
setQuestion(o);
|
|
216
218
|
}
|
|
217
219
|
};
|
|
218
|
-
|
|
220
|
+
o ? o(write, t) : write();
|
|
219
221
|
}
|
|
220
222
|
// A landing (not the sync pass's own commit): the readers held
|
|
221
223
|
// pending on the derive settle.
|
|
222
|
-
if (!d || !(i.
|
|
224
|
+
if (!d || !(i.m & STATUS_UNINITIALIZED)) settleFamily(c);
|
|
225
|
+
// A commit is the derive's change for the readers that observed its
|
|
226
|
+
// flight (linked by `pullFamily`; a settled pull does not link), as
|
|
227
|
+
// a memo's landing is for its readers: one that caught the NotReady
|
|
228
|
+
// (a fallback value, not pending) re-runs too (#4070).
|
|
229
|
+
insertSubs(i);
|
|
223
230
|
};
|
|
224
231
|
const u = handleAsync(i, l, commit, (e, t) => {
|
|
225
232
|
// The flight rejected: the leaves' readers learn it from here —
|
|
@@ -228,10 +235,10 @@ function forEachFamilyNode(e, t) {
|
|
|
228
235
|
// reader re-derives and meets the error at its pull (memo parity,
|
|
229
236
|
// #2897) — and the flush that runs them advances the clock, so a
|
|
230
237
|
// later tracked re-read may retry (core `read`).
|
|
231
|
-
if (d && i.
|
|
238
|
+
if (d && i.m & STATUS_UNINITIALIZED) return;
|
|
232
239
|
if (t) wakeFamily(c, e); else errorFamily(c);
|
|
233
240
|
});
|
|
234
|
-
if (!i.
|
|
241
|
+
if (!i.ce) commit(u);
|
|
235
242
|
}, false);
|
|
236
243
|
try {
|
|
237
244
|
d ? runDirect(pass) : pass();
|
|
@@ -248,23 +255,26 @@ function forEachFamilyNode(e, t) {
|
|
|
248
255
|
// the wake, as for the throw. Not a sync pass that superseded one — the
|
|
249
256
|
// status it reads is the dead flight's, cleared when this pass settles
|
|
250
257
|
// (#3181: a reader the settle walk had just released, re-parked for good).
|
|
251
|
-
if (i.
|
|
258
|
+
if (i.m & STATUS_PENDING && i.T.Se !== null && !i.ce && !d) wakeFamily(c, i.T?.F);
|
|
252
259
|
return i;
|
|
253
260
|
}
|
|
254
261
|
|
|
255
262
|
function createProjectionInternal(e, t, r) {
|
|
256
|
-
|
|
257
|
-
|
|
263
|
+
// Seedless (`fn` takes no draft): the root starts as an empty record. It is
|
|
264
|
+
// a draft like any seed, never observable before the first landing (A25).
|
|
265
|
+
t ||= {};
|
|
266
|
+
const o = r?.key === undefined ? "id" : r.key;
|
|
267
|
+
const n = {
|
|
258
268
|
map: new WeakMap,
|
|
259
269
|
node: null,
|
|
260
270
|
live: new Set,
|
|
261
271
|
shallow: !!r?.shallow,
|
|
262
272
|
// The row key, for a child paired after the adoption (store.ts
|
|
263
273
|
// `adoptChild`, #3712) as the adoption pairs them.
|
|
264
|
-
key: typeof
|
|
274
|
+
key: typeof o === "function" ? o : o === null ? null : e => isWrappable(e) ? e[o] : undefined
|
|
265
275
|
};
|
|
266
|
-
const i = wrap(t, null, null,
|
|
267
|
-
if (
|
|
276
|
+
const i = wrap(t, null, null, n);
|
|
277
|
+
if (n.shallow) {
|
|
268
278
|
i[$TARGET].s = true;
|
|
269
279
|
markRawIngest(t);
|
|
270
280
|
}
|
|
@@ -272,37 +282,40 @@ function createProjectionInternal(e, t, r) {
|
|
|
272
282
|
if (r?.seedLoadingValue) s = {
|
|
273
283
|
loadingValue: undefined
|
|
274
284
|
};
|
|
275
|
-
if (
|
|
285
|
+
if (attrHooks !== null)
|
|
286
|
+
// As createStore: the owner in scope stamps the projection's property
|
|
287
|
+
// nodes, so attribution places them under it (#4035).
|
|
288
|
+
storeOwners.set(i[$TARGET], getOwner());
|
|
289
|
+
if (r?.name || r?.loc) {
|
|
276
290
|
s = {
|
|
277
291
|
...s,
|
|
278
|
-
name: r.name
|
|
292
|
+
name: r.name,
|
|
293
|
+
loc: r.loc
|
|
279
294
|
};
|
|
280
|
-
nameStore(i, r.name);
|
|
295
|
+
nameStore(i, r.name, r.loc);
|
|
281
296
|
}
|
|
282
297
|
const c = computed(() => {
|
|
283
|
-
if (!
|
|
284
|
-
runProjectionComputed(i, e,
|
|
298
|
+
if (!n.node) n.node = getOwner();
|
|
299
|
+
runProjectionComputed(i, e, o);
|
|
285
300
|
}, s);
|
|
286
|
-
c.
|
|
287
|
-
|
|
301
|
+
c.l &= ~CONFIG_AUTO_DISPOSE;
|
|
302
|
+
n.node = c;
|
|
303
|
+
// The derive's leaves are not its dependents: a mark's repoll
|
|
304
|
+
// (affects-marks.ts) reaches their readers through this.
|
|
305
|
+
c.fam = n;
|
|
288
306
|
return {
|
|
289
307
|
store: i,
|
|
290
308
|
node: c
|
|
291
309
|
};
|
|
292
310
|
}
|
|
293
311
|
|
|
294
|
-
|
|
295
|
-
* A derived store: `fn` runs in a computed and writes its draft; readers of
|
|
296
|
-
* the store's keys re-run only when the keys they read change (the
|
|
297
|
-
* firewall). `fn` may be async or an async iterator; the seed is a draft,
|
|
298
|
-
* never an observable value, until the first landing (A25).
|
|
299
|
-
*/ function createProjection(e, t, r) {
|
|
312
|
+
function createProjection(e, t, r) {
|
|
300
313
|
return createProjectionInternal(e, t, r).store;
|
|
301
314
|
}
|
|
302
315
|
|
|
303
316
|
/** `createStore(fn, seed, options)`: a projection with a user setter. */ function createStoreDerived(e, t, r) {
|
|
304
|
-
const {store:
|
|
305
|
-
return [
|
|
317
|
+
const {store: o} = createProjectionInternal(e, t, r);
|
|
318
|
+
return [ o, e => storeSetter(o, e) ];
|
|
306
319
|
}
|
|
307
320
|
|
|
308
321
|
export { createProjection, createStoreDerived, runProjectionComputed };
|