@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
package/dist/prod/store/store.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { CONFIG_MANUAL_WRITE, CONFIG_OVERRIDE, CONFIG_HELD, $REFRESH, NOT_PENDING, STATUS_PENDING, STATUS_ERROR, EFFECT_RENDER, REACTIVE_RECOMPUTING_DEPS, REACTIVE_STAGED_READ, CONFIG_VERDICT, CONFIG_CHILDREN_FORBIDDEN, CONFIG_PROMOTED, REACTIVE_DIRTY, REACTIVE_CHECK } from "../core/constants.js";
|
|
2
2
|
|
|
3
|
-
import { setSignal, isEqual, read, verdict, snapshotCaptureActive, captureWriteSnapshot, context, notePromotedWrite, untrack, slotSignal, stagedScreen, stagedRead } from "../core/core.js";
|
|
3
|
+
import { writeHook, setSignal, isEqual, read, verdict, snapshotCaptureActive, captureWriteSnapshot, context, notePromotedWrite, untrack, slotSignal, stagedScreen, stagedRead } from "../core/core.js";
|
|
4
|
+
|
|
5
|
+
import { signalHook } from "../core/identities.js";
|
|
4
6
|
|
|
5
7
|
import { setSlotUnobserved } from "../core/graph.js";
|
|
6
8
|
|
|
@@ -8,7 +10,7 @@ import { getObserver } from "../core/owner.js";
|
|
|
8
10
|
|
|
9
11
|
import { insertIntoHeap } from "../core/heap.js";
|
|
10
12
|
|
|
11
|
-
import { txOf, flushTransaction, holdNode, joinFuture, insertSubs, schedule, passLane, globalQueue, queuePendingNode, GlobalQueue, joinPassTx, dirtyQueue } from "../core/scheduler.js";
|
|
13
|
+
import { txOf, flushTransaction, holdNode, joinFuture, insertSubs, schedule, passLane, globalQueue, queuePendingNode, GlobalQueue, installStoreHooks, joinPassTx, dirtyQueue } from "../core/scheduler.js";
|
|
12
14
|
|
|
13
15
|
import { lookupTarget, setLookup, $OWNER, isOwned, markDescendants, devAssertNeverUserMutation } from "./target.js";
|
|
14
16
|
|
|
@@ -166,7 +168,7 @@ function wrap(e, n = null, t = null, r = n?.fam ?? null) {
|
|
|
166
168
|
// adoption swap raw identity without changing the logical value — only
|
|
167
169
|
// changed leaves notify, R9).
|
|
168
170
|
const slotNodeEquals = function(e, n) {
|
|
169
|
-
return isEqual(e, n) || sameLogicalSlot(this.
|
|
171
|
+
return isEqual(e, n) || sameLogicalSlot(this.O, e, n);
|
|
170
172
|
};
|
|
171
173
|
|
|
172
174
|
/** The deep witness: the store decides when it notifies. */ const never = false;
|
|
@@ -204,7 +206,7 @@ function sameKey(e, n) {
|
|
|
204
206
|
/** The container node's comparator: a staging is a backing (identity — a
|
|
205
207
|
* pending backing is never "equal" to the committed one); a lane value is
|
|
206
208
|
* an arrangement (`LaneView`), judged by the optimistic machinery. */ const containerEquals = function(e, n) {
|
|
207
|
-
return e === n || optHooks !== null && optHooks.arrangement(this.
|
|
209
|
+
return e === n || optHooks !== null && optHooks.arrangement(this.O, e, n);
|
|
208
210
|
};
|
|
209
211
|
|
|
210
212
|
function sameLogicalSlot(e, n, t) {
|
|
@@ -217,8 +219,8 @@ function sameLogicalSlot(e, n, t) {
|
|
|
217
219
|
* released at the commit that resolves it (`drainFolds`). */ const deferredReleases = new Set;
|
|
218
220
|
|
|
219
221
|
function releaseSlot(e) {
|
|
220
|
-
const n = e.
|
|
221
|
-
const t = e.
|
|
222
|
+
const n = e.O;
|
|
223
|
+
const t = e.ze;
|
|
222
224
|
if (t === $TRACK) {
|
|
223
225
|
if (n.k === e) n.k = null;
|
|
224
226
|
} else if (t === $DEEP) {
|
|
@@ -241,10 +243,14 @@ function releaseSlot(e) {
|
|
|
241
243
|
// dispatches CONFIG_SLOT_NODE nodes here (graph.ts) instead of holding a
|
|
242
244
|
// per-node closure in a per-node NodeExtension. A dropped node is
|
|
243
245
|
// unreachable through the store — a fresh read makes a fresh node.
|
|
246
|
+
// A staged write — or a lane's value (a guess, S4) — is state only the node
|
|
247
|
+
// holds: its release waits for the commit that resolves it. So does a leaf of
|
|
248
|
+
// a held container (#4146): a mainline write it carried is in the held
|
|
249
|
+
// staging too, where it would read as the hold's until the landing.
|
|
250
|
+
const slotKept = e => e.se !== NOT_PENDING || e.l & CONFIG_OVERRIDE || e.O.k?.l & CONFIG_HELD;
|
|
251
|
+
|
|
244
252
|
setSlotUnobserved(e => {
|
|
245
|
-
|
|
246
|
-
// node holds: defer the release to the commit that resolves it.
|
|
247
|
-
if (e.Oe !== NOT_PENDING || e.i & CONFIG_OVERRIDE) deferredReleases.add(e); else releaseSlot(e);
|
|
253
|
+
if (slotKept(e)) deferredReleases.add(e); else releaseSlot(e);
|
|
248
254
|
});
|
|
249
255
|
|
|
250
256
|
/** A node born while its container has a staging is born from the two
|
|
@@ -252,19 +258,19 @@ setSlotUnobserved(e => {
|
|
|
252
258
|
* pending one — and held by the container's transaction when the container
|
|
253
259
|
* is held (#3706: the unit of the hold is the key — a key the batch left
|
|
254
260
|
* unchanged stages nothing and holds no one). */ function bornStaged(e, n, t, r) {
|
|
255
|
-
if (n.
|
|
261
|
+
if (n.xe && n.xe(n.Ie, t)) return;
|
|
256
262
|
queuePendingNode(n);
|
|
257
|
-
n.
|
|
263
|
+
n.se = t;
|
|
258
264
|
const i = e.k;
|
|
259
265
|
if (i === null) return;
|
|
260
266
|
// a node-less staging holds nothing (`stageOn`)
|
|
261
267
|
// Held by the container's transaction only for a key the HELD staging
|
|
262
268
|
// changed — a mainline layer's change above it stages mainline. (A
|
|
263
269
|
// container carrying a guess is a lane's: the flush's park decides.)
|
|
264
|
-
if ((i.
|
|
270
|
+
if ((i.l & (CONFIG_HELD | CONFIG_OVERRIDE)) === CONFIG_HELD && heldKeyChanged(e, r)) holdNode(n, txOf(i));
|
|
265
271
|
// A28 (4): a batch written inside a creation-time pass is promoted — its
|
|
266
272
|
// late-materialized leaf with it.
|
|
267
|
-
if (i.
|
|
273
|
+
if (i.l & CONFIG_PROMOTED) notePromotedWrite(n);
|
|
268
274
|
}
|
|
269
275
|
|
|
270
276
|
function getNode(e, n,
|
|
@@ -314,8 +320,8 @@ function getHasNode(e, n) {
|
|
|
314
320
|
// pending backing staged — so whoever asked for it reads the frame it
|
|
315
321
|
// would have read had the node been there from the write.
|
|
316
322
|
if (e.pb !== null && !directCommit) {
|
|
317
|
-
n.
|
|
318
|
-
n.
|
|
323
|
+
n.Ie = preBatch(e);
|
|
324
|
+
n.se = e.pb;
|
|
319
325
|
queuePendingNode(n);
|
|
320
326
|
}
|
|
321
327
|
}
|
|
@@ -331,11 +337,11 @@ function getHasNode(e, n) {
|
|
|
331
337
|
* staging: nothing allocates, nothing is swept at the commit (dbmon's tick
|
|
332
338
|
* re-created, queued, swept and dropped ~7000 container nodes). If the
|
|
333
339
|
* flush parks, the seam materializes and holds the node then
|
|
334
|
-
* (`
|
|
335
|
-
if (e.k === null && passLane === null && (context === null || globalQueue.
|
|
340
|
+
* (`storeParkHook`) — the one case the staging home exists for. */ function stageOn(e, n) {
|
|
341
|
+
if (e.k === null && passLane === null && (context === null || globalQueue.q) && !deriveHolds(e)) return;
|
|
336
342
|
const t = getContainerNode(e);
|
|
337
|
-
if (t.
|
|
338
|
-
t.
|
|
343
|
+
if (t.se === NOT_PENDING) queuePendingNode(t);
|
|
344
|
+
t.se = n;
|
|
339
345
|
// A28 (4): a write issued inside a pass outside a flush (a creation-time
|
|
340
346
|
// derive) is promoted at the pass's end — the batch with it.
|
|
341
347
|
if (context !== null) notePromotedWrite(t);
|
|
@@ -345,10 +351,10 @@ function getHasNode(e, n) {
|
|
|
345
351
|
/** The projection's derive is held by a transaction and this is its own
|
|
346
352
|
* write (not a user setter's): the staging is the derive's (`holdWithDerive`). */ function deriveHolds(e) {
|
|
347
353
|
const n = e.fam?.node;
|
|
348
|
-
return n != null && !userWrite && (n.
|
|
354
|
+
return n != null && !userWrite && (n.l & CONFIG_HELD) !== 0;
|
|
349
355
|
}
|
|
350
356
|
|
|
351
|
-
|
|
357
|
+
const storePark = e => {
|
|
352
358
|
for (let n = 0; n < foldList.length; n++) {
|
|
353
359
|
const t = foldList[n];
|
|
354
360
|
if (t.k === null && t.pb !== null) holdNode(getContainerNode(t), e);
|
|
@@ -376,9 +382,9 @@ function bumpDeep(e) {
|
|
|
376
382
|
// on the guess (`laneWrite` → `supersede`, judged by `containerEquals`);
|
|
377
383
|
// otherwise the structural readers are walked (the staging is already on
|
|
378
384
|
// the node; the comparator is the store's, done).
|
|
379
|
-
if (e.
|
|
380
|
-
if (e.
|
|
381
|
-
if (snapshotCaptureActive) captureWriteSnapshot(e, e.
|
|
385
|
+
if (e.l & CONFIG_OVERRIDE) setSignal(e, n); else {
|
|
386
|
+
if (e.l & CONFIG_HELD) joinFuture(txOf(e));
|
|
387
|
+
if (snapshotCaptureActive) captureWriteSnapshot(e, e.Ie);
|
|
382
388
|
insertSubs(e);
|
|
383
389
|
schedule();
|
|
384
390
|
}
|
|
@@ -470,7 +476,7 @@ const plainProto = e => {
|
|
|
470
476
|
if (e.kc > OVERLAY_REBUILD_MAX_KEYS) return false;
|
|
471
477
|
if (e.del !== null && e.del.size !== 0) return true;
|
|
472
478
|
const t = e.wk;
|
|
473
|
-
if (t !== null && t !== WK_ALL && t.size <= OVERLAY_REBUILD_MIN_ADDS) return false;
|
|
479
|
+
if (t !== null && t !== WK_ALL && t.u === undefined && t.size <= OVERLAY_REBUILD_MIN_ADDS) return false;
|
|
474
480
|
const r = e.v;
|
|
475
481
|
let i = 0;
|
|
476
482
|
for (const e of Reflect.ownKeys(n)) if (!hasOwn.call(r, e) && ++i > OVERLAY_REBUILD_MIN_ADDS) return true;
|
|
@@ -490,7 +496,7 @@ const plainProto = e => {
|
|
|
490
496
|
e.pb = t;
|
|
491
497
|
e.ovl = false;
|
|
492
498
|
// The staging IS the pending backing: re-point the container node.
|
|
493
|
-
if (e.k !== null && e.k.
|
|
499
|
+
if (e.k !== null && e.k.se === n) e.k.se = t;
|
|
494
500
|
return t;
|
|
495
501
|
}
|
|
496
502
|
|
|
@@ -511,7 +517,7 @@ const plainProto = e => {
|
|
|
511
517
|
// mainline setter mid-hold publishes mainline; the held keys stay held).
|
|
512
518
|
n = e.pb = cloneRaw(n, e);
|
|
513
519
|
const t = e.k;
|
|
514
|
-
if (t !== null && !(t.
|
|
520
|
+
if (t !== null && !(t.l & CONFIG_HELD)) t.se = n;
|
|
515
521
|
} else if (n === null) {
|
|
516
522
|
const t = e.v;
|
|
517
523
|
if (!directCommit) queueFold(e);
|
|
@@ -590,7 +596,7 @@ const plainProto = e => {
|
|
|
590
596
|
} else r = e.v;
|
|
591
597
|
if (directCommit) {
|
|
592
598
|
e.pb = null;
|
|
593
|
-
if (e.k !== null) e.k.
|
|
599
|
+
if (e.k !== null) e.k.Ie = n;
|
|
594
600
|
} else {
|
|
595
601
|
// Eager (INTERNALS §3): the backing swaps now — handlers read the
|
|
596
602
|
// adopted object before the flush — while the container node, when
|
|
@@ -686,7 +692,7 @@ let foldIndex = null;
|
|
|
686
692
|
if (r.pb === null) continue;
|
|
687
693
|
// folded already (a direct commit)
|
|
688
694
|
const i = r.k;
|
|
689
|
-
if (i !== null && i.
|
|
695
|
+
if (i !== null && i.se !== NOT_PENDING) {
|
|
690
696
|
// held: commits with its hold
|
|
691
697
|
foldList.push(r);
|
|
692
698
|
foldOlds.push(n[t]);
|
|
@@ -697,7 +703,7 @@ let foldIndex = null;
|
|
|
697
703
|
}
|
|
698
704
|
if (deferredReleases.size !== 0) {
|
|
699
705
|
for (const e of deferredReleases) {
|
|
700
|
-
if (e.
|
|
706
|
+
if (e.o === null && !slotKept(e)) {
|
|
701
707
|
deferredReleases.delete(e);
|
|
702
708
|
releaseSlot(e);
|
|
703
709
|
}
|
|
@@ -708,28 +714,28 @@ let foldIndex = null;
|
|
|
708
714
|
/** Core asks: is a slot node's truth in flight? Its family's derive is —
|
|
709
715
|
* lanes (A17, #2864: a guess mid-refetch stands in for the flight) and
|
|
710
716
|
* marks (an ambient `affects()` over a declared reload lives to the
|
|
711
|
-
* landing) read it. */ GlobalQueue.
|
|
712
|
-
const n = e.
|
|
713
|
-
return n != null && n.node !== null && (n.node.
|
|
717
|
+
* landing) read it. */ GlobalQueue.k = e => {
|
|
718
|
+
const n = e.O?.fam;
|
|
719
|
+
return n != null && n.node !== null && (n.node.m & STATUS_PENDING) !== 0;
|
|
714
720
|
};
|
|
715
721
|
|
|
716
722
|
/** Core asks (lanes.ts `covered`): the value a slot node's guess covered.
|
|
717
723
|
* A chained link's committed value is the inner store's at the last
|
|
718
724
|
* read-through — refreshed here, since a guess served the reads since
|
|
719
|
-
* (#3672: the revert compares against the base's live value). */ GlobalQueue.
|
|
720
|
-
const n = e.
|
|
725
|
+
* (#3672: the revert compares against the base's live value). */ GlobalQueue.fn = e => {
|
|
726
|
+
const n = e.O;
|
|
721
727
|
if (n.ch) {
|
|
722
|
-
const t = e.
|
|
728
|
+
const t = e.ze;
|
|
723
729
|
const r = n.v;
|
|
724
|
-
if (n.h !== null && n.h[t] === e) e.
|
|
730
|
+
if (n.h !== null && n.h[t] === e) e.Ie = untrack(() => t in r); else if (n.n !== null && n.n[t] === e) e.Ie = untrack(() => unwrapValue(r[t]));
|
|
725
731
|
}
|
|
726
|
-
return e.
|
|
732
|
+
return e.Ie;
|
|
727
733
|
};
|
|
728
734
|
|
|
729
|
-
|
|
735
|
+
installStoreHooks(storePark, () => {
|
|
730
736
|
drainFolds();
|
|
731
737
|
optHooks?.sweep();
|
|
732
|
-
};
|
|
738
|
+
});
|
|
733
739
|
|
|
734
740
|
/** The store half of `affects()` (store/affects.ts) makes its marks' nodes
|
|
735
741
|
* and walks records through these: it never imports the engine. */ GlobalQueue.no = getNode;
|
|
@@ -762,7 +768,7 @@ function runDirect(e) {
|
|
|
762
768
|
// the adopted object (shared ownership — never cloned).
|
|
763
769
|
e.pb = null;
|
|
764
770
|
e.wk = null;
|
|
765
|
-
} else if (e.ovl && (e.v !== n || !overlayRebuilds(e, r) && t?.
|
|
771
|
+
} else if (e.ovl && (e.v !== n || !overlayRebuilds(e, r) && t?.T?.Pe !== n)) {
|
|
766
772
|
// Overlay flatten (#3044): the backing keeps its identity, so the
|
|
767
773
|
// `t.v === old` gate below skips path copying (the parent slot
|
|
768
774
|
// already points here) and the adopted-notify (setter
|
|
@@ -776,8 +782,8 @@ function runDirect(e) {
|
|
|
776
782
|
const t = e.v;
|
|
777
783
|
const i = e.wk;
|
|
778
784
|
if (i !== null && i !== WK_ALL) {
|
|
779
|
-
for (
|
|
780
|
-
if (hasOwn.call(r,
|
|
785
|
+
for (let e = i; e !== undefined; e = e.u) for (const n of e) {
|
|
786
|
+
if (hasOwn.call(r, n)) copyOwn(t, r, n); else delete t[n];
|
|
781
787
|
}
|
|
782
788
|
} else {
|
|
783
789
|
for (const e of Reflect.ownKeys(r)) {
|
|
@@ -804,7 +810,7 @@ function runDirect(e) {
|
|
|
804
810
|
// subscribes to was a transient staging home (INTERNALS §5: an
|
|
805
811
|
// observer-less write holds a transient record until the fold,
|
|
806
812
|
// discarded with it) — gone with the batch.
|
|
807
|
-
if (t.
|
|
813
|
+
if (t.o === null) e.k = null; else if (t.Ie instanceof LaneView) t.Ie.base = e.v; else t.Ie = e.v;
|
|
808
814
|
}
|
|
809
815
|
if (e.v !== n && e.u) {
|
|
810
816
|
const t = parentSlotKey(e, n);
|
|
@@ -831,9 +837,9 @@ function runDirect(e) {
|
|
|
831
837
|
|
|
832
838
|
function heldDerivation(e, n, t) {
|
|
833
839
|
if (e.fam === null || !userWrite) return false;
|
|
834
|
-
if (n !== undefined) return (n.
|
|
840
|
+
if (n !== undefined) return (n.l & (CONFIG_HELD | CONFIG_MANUAL_WRITE)) === CONFIG_HELD && txOf(n) !== flushTransaction;
|
|
835
841
|
const r = e.k;
|
|
836
|
-
return r !== null && (r.
|
|
842
|
+
return r !== null && (r.l & CONFIG_HELD) !== 0 && txOf(r) !== flushTransaction && heldKeyChanged(e, t);
|
|
837
843
|
}
|
|
838
844
|
|
|
839
845
|
/** Setter exit: one node write per changed observed key (the leaves stage
|
|
@@ -863,7 +869,10 @@ function heldDerivation(e, n, t) {
|
|
|
863
869
|
// value can change when ANY key is written), or a non-plain prototype
|
|
864
870
|
// (class instances: prototype getters derive from arbitrary fields).
|
|
865
871
|
// Overlay pbs chain to the COMMITTED object (#3044) — plainness is the
|
|
866
|
-
// committed container's prototype, not the overlay's.
|
|
872
|
+
// committed container's prototype, not the overlay's. THIS setter's keys
|
|
873
|
+
// only (D-8, #3743): a key an earlier setter of the batch wrote and this
|
|
874
|
+
// one did not is no second proposal — its node was told then, and telling
|
|
875
|
+
// a held node its unchanged value again would join this tick to the hold.
|
|
867
876
|
const i = e.wk;
|
|
868
877
|
const o = i === WK_ALL || e.a === true || !plainProto(e.ovl ? e.v : n) ? null : i;
|
|
869
878
|
if (e.fam !== null && !heldDerivationHit && o !== null) for (const n of o) if (heldDerivation(e, r?.[n], n)) {
|
|
@@ -898,9 +907,9 @@ function heldDerivation(e, n, t) {
|
|
|
898
907
|
// The derive's write is a derivation; a user setter's is a proposal
|
|
899
908
|
// (A34 (3)'s discriminator).
|
|
900
909
|
if (!userWrite) {
|
|
901
|
-
i.
|
|
910
|
+
i.l &= ~CONFIG_MANUAL_WRITE;
|
|
902
911
|
holdWithDerive(e, i);
|
|
903
|
-
} else i.
|
|
912
|
+
} else i.l |= CONFIG_MANUAL_WRITE;
|
|
904
913
|
}
|
|
905
914
|
}
|
|
906
915
|
}
|
|
@@ -931,7 +940,7 @@ function heldDerivation(e, n, t) {
|
|
|
931
940
|
// container carrying an arrangement guess is told whether or not anyone
|
|
932
941
|
// subscribes: the write is a landing on the guess (`notifyContainer`).
|
|
933
942
|
const u = e.k;
|
|
934
|
-
if (u !== null && (u.
|
|
943
|
+
if (u !== null && (u.o !== null || u.l & CONFIG_OVERRIDE)) {
|
|
935
944
|
let r;
|
|
936
945
|
if (e.ovl) {
|
|
937
946
|
r = e.del !== null && e.del.size !== 0;
|
|
@@ -1033,7 +1042,7 @@ function hasAccessorFlag(e) {
|
|
|
1033
1042
|
for (const i of Reflect.ownKeys(r)) if (e || i in n !== i in t) setSignal(r[i], i in t);
|
|
1034
1043
|
}
|
|
1035
1044
|
const i = e.k;
|
|
1036
|
-
if (i !== null && (i.
|
|
1045
|
+
if (i !== null && (i.o !== null || i.l & CONFIG_OVERRIDE)) {
|
|
1037
1046
|
const e = Array.isArray(t) && Array.isArray(n) ? arrayStructureChanged(n, t) : membershipChanged(n, t);
|
|
1038
1047
|
if (e) notifyContainer(i, t);
|
|
1039
1048
|
}
|
|
@@ -1090,7 +1099,7 @@ function inDraft(e) {
|
|
|
1090
1099
|
* "adoption is eager by contract" — and the node keeps the frame committed
|
|
1091
1100
|
* readers under a hold still see), `t.v` otherwise. */ function committed(e) {
|
|
1092
1101
|
const n = e.k;
|
|
1093
|
-
if (n !== null) return n.
|
|
1102
|
+
if (n !== null) return n.se !== NOT_PENDING ? asBacking(n.Ie) : e.v;
|
|
1094
1103
|
// A node-less staging (`stageOn`): the fold queue remembers the frame.
|
|
1095
1104
|
return e.pb !== null ? preBatch(e) : e.v;
|
|
1096
1105
|
}
|
|
@@ -1102,8 +1111,8 @@ function inDraft(e) {
|
|
|
1102
1111
|
* committed frame. */ function stagingReader() {
|
|
1103
1112
|
let e = context;
|
|
1104
1113
|
if (e === null) return null;
|
|
1105
|
-
if (e
|
|
1106
|
-
return e === null || e.
|
|
1114
|
+
if (e.je) e = e.Ye ?? null;
|
|
1115
|
+
return e === null || e.l & CONFIG_CHILDREN_FORBIDDEN ? null : e;
|
|
1107
1116
|
}
|
|
1108
1117
|
|
|
1109
1118
|
/** The backing a read serves (RUL-1, signal parity): the draft and the write
|
|
@@ -1141,10 +1150,10 @@ function inDraft(e) {
|
|
|
1141
1150
|
if (writeOverride && !userWrite) {
|
|
1142
1151
|
const t = n !== undefined ? e.n?.[n] : undefined;
|
|
1143
1152
|
if (t !== undefined) {
|
|
1144
|
-
if ((t.
|
|
1153
|
+
if ((t.l & (CONFIG_HELD | CONFIG_OVERRIDE)) === CONFIG_HELD) joinPassTx(txOf(t));
|
|
1145
1154
|
} else {
|
|
1146
1155
|
const t = e.k;
|
|
1147
|
-
if (t !== null && (t.
|
|
1156
|
+
if (t !== null && (t.l & (CONFIG_HELD | CONFIG_OVERRIDE)) === CONFIG_HELD && (n === undefined || heldKeyChanged(e, n))) joinPassTx(txOf(t));
|
|
1148
1157
|
}
|
|
1149
1158
|
}
|
|
1150
1159
|
return r;
|
|
@@ -1156,9 +1165,9 @@ function inDraft(e) {
|
|
|
1156
1165
|
// it).
|
|
1157
1166
|
if (n !== undefined) {
|
|
1158
1167
|
const t = e.n?.[n];
|
|
1159
|
-
if (t !== undefined && t.
|
|
1168
|
+
if (t !== undefined && t.l & CONFIG_OVERRIDE) return committed(e);
|
|
1160
1169
|
}
|
|
1161
|
-
const o = i !== null && (i.
|
|
1170
|
+
const o = i !== null && (i.l & CONFIG_HELD) !== 0;
|
|
1162
1171
|
// A held container: the hold's unit is the key (#3706). A key the HELD
|
|
1163
1172
|
// staging left unchanged reads the ambient view — a mainline layer's
|
|
1164
1173
|
// write above the hold publishes mainline (#3688, #3612); a key it
|
|
@@ -1176,7 +1185,7 @@ function inDraft(e) {
|
|
|
1176
1185
|
// probe) judges the container like any node — for a key the batch
|
|
1177
1186
|
// changed; an unchanged key is committed and final (A22: pending is per
|
|
1178
1187
|
// key). A held container's committed frame is the node's.
|
|
1179
|
-
if (verdict === null || !o && n !== undefined && !keyChanged(e, n, t)) return o ? asBacking(i.
|
|
1188
|
+
if (verdict === null || !o && n !== undefined && !keyChanged(e, n, t)) return o ? asBacking(i.Ie) : e.v;
|
|
1180
1189
|
return i === null ? committed(e) : asBacking(read(i));
|
|
1181
1190
|
}
|
|
1182
1191
|
// A pass reading a key the batch left unchanged: the same value in both
|
|
@@ -1193,13 +1202,13 @@ function inDraft(e) {
|
|
|
1193
1202
|
// frames, a changed one is what the mark already stands for. The
|
|
1194
1203
|
// per-key question is asked once per pass, not once per key (a
|
|
1195
1204
|
// `mapArray` over 1k shifted rows asked it 1k times).
|
|
1196
|
-
if (l.R & REACTIVE_STAGED_READ && !(l.
|
|
1205
|
+
if (l.R & REACTIVE_STAGED_READ && !(l.l & (CONFIG_VERDICT | CONFIG_CHILDREN_FORBIDDEN))) return r;
|
|
1197
1206
|
if (n !== undefined && !keyChanged(e, n, t)) return committed(e);
|
|
1198
1207
|
// A node-less staging (`stageOn`): what `read()` of its node would do
|
|
1199
1208
|
// for this pass — a verdict reader sees the screen, any other derives
|
|
1200
1209
|
// from the staging and is marked as having read it.
|
|
1201
1210
|
if (i === null) {
|
|
1202
|
-
if (l.
|
|
1211
|
+
if (l.l & CONFIG_VERDICT && stagedScreen(l)) return committed(e);
|
|
1203
1212
|
stagedRead(l);
|
|
1204
1213
|
return r;
|
|
1205
1214
|
}
|
|
@@ -1209,7 +1218,7 @@ function inDraft(e) {
|
|
|
1209
1218
|
|
|
1210
1219
|
/** Did the HELD staging (the container node's, not a mainline layer above
|
|
1211
1220
|
* it) change `key`? */ function heldKeyChanged(e, n, t = true) {
|
|
1212
|
-
return changedBetween(e, e.k.
|
|
1221
|
+
return changedBetween(e, e.k.Ie, e.k.se, n, t) && !adoptChild(e, n);
|
|
1213
1222
|
}
|
|
1214
1223
|
|
|
1215
1224
|
/** The values of a held frame, built once per frame: neither the committed
|
|
@@ -1236,14 +1245,14 @@ function rawsOf(e) {
|
|
|
1236
1245
|
* `version` holds. A record's keys pair by name; an array's by the family's
|
|
1237
1246
|
* key — without a family the pairing is not known here and the hold stands. */ function adoptChild(e, n) {
|
|
1238
1247
|
const t = e.k;
|
|
1239
|
-
const r = asBacking(t.
|
|
1248
|
+
const r = asBacking(t.Ie);
|
|
1240
1249
|
const i = r[n];
|
|
1241
|
-
const o = t.
|
|
1250
|
+
const o = t.se[n];
|
|
1242
1251
|
const l = Array.isArray(r) ? e.fam?.key : null;
|
|
1243
1252
|
if (e.s || l === undefined || !sameRow(i, o, l) || !isWrappable(i) || !isWrappable(o) || Array.isArray(i) !== Array.isArray(o) || lookupTarget(i, e.fam) !== undefined || lookupTarget(o, e.fam) !== undefined ||
|
|
1244
1253
|
// A raw in both frames (the same objects swapped or reordered) is its
|
|
1245
1254
|
// own row: pairing it with another would alias the two after the commit.
|
|
1246
|
-
rawsOf(r).has(o) || rawsOf(t.
|
|
1255
|
+
rawsOf(r).has(o) || rawsOf(t.se).has(i)) return false;
|
|
1247
1256
|
// A raw-marked value wraps to itself, a proxy to its own target: neither
|
|
1248
1257
|
// is a fresh target around `ov`.
|
|
1249
1258
|
const u = wrap(i, e, n)[$TARGET];
|
|
@@ -1254,7 +1263,7 @@ function rawsOf(e) {
|
|
|
1254
1263
|
}
|
|
1255
1264
|
|
|
1256
1265
|
/** A family target's unheld staging, read with no pass (a handler). */ function familyAhead(e) {
|
|
1257
|
-
return e.fam !== null && context === null && !(e.k !== null && e.k.
|
|
1266
|
+
return e.fam !== null && context === null && !(e.k !== null && e.k.l & CONFIG_HELD);
|
|
1258
1267
|
}
|
|
1259
1268
|
|
|
1260
1269
|
/** Did this batch change `key` — value (slot equality), presence, and (for
|
|
@@ -1288,7 +1297,7 @@ function changedBetween(e, n, t, r, i) {
|
|
|
1288
1297
|
* tracked or not, applies the hold and A28 rules a signal's read does. A
|
|
1289
1298
|
* projection's unheld staging is ahead for a handler (`familyAhead`). */ function nodeValue(e, n, t) {
|
|
1290
1299
|
let r = read(e);
|
|
1291
|
-
if (e.
|
|
1300
|
+
if (e.se !== NOT_PENDING && !(e.l & CONFIG_HELD) && context === null && t.fam !== null) r = e.se;
|
|
1292
1301
|
return r === FORCE ? n : r;
|
|
1293
1302
|
}
|
|
1294
1303
|
|
|
@@ -1308,8 +1317,8 @@ function changedBetween(e, n, t, r, i) {
|
|
|
1308
1317
|
if (l) {
|
|
1309
1318
|
// The link's committed value follows the inner store's (what a lane
|
|
1310
1319
|
// over it covers — its reveal and revert compare against it, S4).
|
|
1311
|
-
i.
|
|
1312
|
-
if (i.
|
|
1320
|
+
i.Ie = t;
|
|
1321
|
+
if (i.l & CONFIG_OVERRIDE) u = n;
|
|
1313
1322
|
} else u = n;
|
|
1314
1323
|
}
|
|
1315
1324
|
}
|
|
@@ -1330,7 +1339,7 @@ function changedBetween(e, n, t, r, i) {
|
|
|
1330
1339
|
}
|
|
1331
1340
|
|
|
1332
1341
|
/** Is `n` among `c`'s dependencies (any pass's — a kept tail included)? */ function linkedTo(e, n) {
|
|
1333
|
-
for (let t = e.
|
|
1342
|
+
for (let t = e.C; t !== null; t = t.G) if (t.S === n) return true;
|
|
1334
1343
|
return false;
|
|
1335
1344
|
}
|
|
1336
1345
|
|
|
@@ -1349,7 +1358,7 @@ function changedBetween(e, n, t, r, i) {
|
|
|
1349
1358
|
// reader of a memo would — linked, so it re-runs at the landing (the
|
|
1350
1359
|
// next settled pass pulls without linking and the stale link trims), a
|
|
1351
1360
|
// verdict reader registered, a tracked pass suspended.
|
|
1352
|
-
if (n.
|
|
1361
|
+
if (n.m & (STATUS_PENDING | STATUS_ERROR)) {
|
|
1353
1362
|
// A render effect outside the flight's own flush is the frame, not a
|
|
1354
1363
|
// derivation: it keeps what it shows and learns of the landing from the
|
|
1355
1364
|
// leaves the landing changes (unchanged leaves say nothing — it is not a
|
|
@@ -1360,7 +1369,7 @@ function changedBetween(e, n, t, r, i) {
|
|
|
1360
1369
|
// release the hold with the flight still up. An errored derive has no
|
|
1361
1370
|
// landing to learn of: the error is what the frame shows.
|
|
1362
1371
|
const t = context;
|
|
1363
|
-
if (t !== null && t.
|
|
1372
|
+
if (t !== null && t.i === EFFECT_RENDER && !(n.m & STATUS_ERROR) && n.l & CONFIG_HELD && flushTransaction !== txOf(n) && !linkedTo(t, n)) return;
|
|
1364
1373
|
// An optimistic family carrying guesses that stand in for the flight
|
|
1365
1374
|
// (A17): the guesses are the display — a reader is served the leaves
|
|
1366
1375
|
// (committed plus the guesses) and does not suspend on the derive; a
|
|
@@ -1368,7 +1377,7 @@ function changedBetween(e, n, t, r, i) {
|
|
|
1368
1377
|
// up). The family's, not the target's: the edit stands in for the one
|
|
1369
1378
|
// flight the family has.
|
|
1370
1379
|
const r = e.fam.overlaid;
|
|
1371
|
-
if (verdict === null && n.
|
|
1380
|
+
if (verdict === null && n.m & STATUS_PENDING && r !== undefined && r.size !== 0) return;
|
|
1372
1381
|
read(n);
|
|
1373
1382
|
} else untrack(() => read(n));
|
|
1374
1383
|
}
|
|
@@ -1381,12 +1390,12 @@ function changedBetween(e, n, t, r, i) {
|
|
|
1381
1390
|
* classification, as core reads it — `heldNotFinal`). */ function holdWithDerive(e, n) {
|
|
1382
1391
|
const t = e.fam?.node;
|
|
1383
1392
|
if (t !== undefined && t !== null && !userWrite && // the derive's own write (its draft or landing), not a user setter's
|
|
1384
|
-
t.
|
|
1393
|
+
t.l & CONFIG_HELD && n.se !== NOT_PENDING &&
|
|
1385
1394
|
// A node carrying a guess is the lane's: its staging is the truth beneath
|
|
1386
1395
|
// the guess (`setSignal` → `laneWrite`), never re-homed by the store.
|
|
1387
|
-
!(n.
|
|
1396
|
+
!(n.l & (CONFIG_HELD | CONFIG_OVERRIDE))) {
|
|
1388
1397
|
holdNode(n, txOf(t));
|
|
1389
|
-
n.
|
|
1398
|
+
n.T.Ve = t.T.Ve;
|
|
1390
1399
|
}
|
|
1391
1400
|
}
|
|
1392
1401
|
|
|
@@ -1429,6 +1438,22 @@ function changedBetween(e, n, t, r, i) {
|
|
|
1429
1438
|
|
|
1430
1439
|
// ---------------------------------------------------------------------------
|
|
1431
1440
|
// traps
|
|
1441
|
+
/** A trap write: the target is told at the setter's exit, the key recorded
|
|
1442
|
+
* in this setter's `wk`. A setter's first write to a target still staged by
|
|
1443
|
+
* an earlier setter of the batch opens a set of its own (the notify visits
|
|
1444
|
+
* it, D-8) and chains the earlier one behind for the fold's union. */ function touch(e, n) {
|
|
1445
|
+
let t = e.wk;
|
|
1446
|
+
if (!pendingNotify.has(e)) {
|
|
1447
|
+
pendingNotify.add(e);
|
|
1448
|
+
if (t !== null && t !== WK_ALL) {
|
|
1449
|
+
t = new Set;
|
|
1450
|
+
t.u = e.wk;
|
|
1451
|
+
e.wk = t;
|
|
1452
|
+
}
|
|
1453
|
+
}
|
|
1454
|
+
if (t !== WK_ALL) (e.wk ??= new Set).add(n);
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1432
1457
|
const traps = {
|
|
1433
1458
|
get(e, n, t) {
|
|
1434
1459
|
// One typeof gates every brand-symbol compare off the hot string path.
|
|
@@ -1472,7 +1497,7 @@ const traps = {
|
|
|
1472
1497
|
const r = e.n?.[n];
|
|
1473
1498
|
if (writeScopes === null && !writeOverride) {
|
|
1474
1499
|
const t = r;
|
|
1475
|
-
if (t !== undefined && t.acc !== true && (!e.ch || t.
|
|
1500
|
+
if (t !== undefined && t.acc !== true && (!e.ch || t.l & CONFIG_OVERRIDE)) {
|
|
1476
1501
|
const r = nodeValue(t, undefined, e);
|
|
1477
1502
|
if (r === null || typeof r !== "object") return r;
|
|
1478
1503
|
if (e.s) return serveShallow(e, n, r);
|
|
@@ -1567,9 +1592,9 @@ const traps = {
|
|
|
1567
1592
|
const i = read(r);
|
|
1568
1593
|
if (!e.ch || t !== e.v) return !!i;
|
|
1569
1594
|
const o = n in t;
|
|
1570
|
-
r.
|
|
1595
|
+
r.Ie = o;
|
|
1571
1596
|
// the link follows the inner store (S4)
|
|
1572
|
-
if (r.
|
|
1597
|
+
if (r.l & CONFIG_OVERRIDE) return !!i;
|
|
1573
1598
|
return o;
|
|
1574
1599
|
} else if (optRead(e)) {
|
|
1575
1600
|
const t = optHooks.has(e, n);
|
|
@@ -1604,7 +1629,7 @@ const traps = {
|
|
|
1604
1629
|
const t = getHasNode(e, n);
|
|
1605
1630
|
const r = read(t);
|
|
1606
1631
|
o = readSource(e, n, true);
|
|
1607
|
-
if (!r && (!e.ch || t.
|
|
1632
|
+
if (!r && (!e.ch || t.l & CONFIG_OVERRIDE || !(n in o))) return undefined;
|
|
1608
1633
|
} else o = readSource(e, n, true);
|
|
1609
1634
|
let l;
|
|
1610
1635
|
if (!i && optRead(e)) {
|
|
@@ -1625,15 +1650,22 @@ const traps = {
|
|
|
1625
1650
|
// pollution guard (core R30)
|
|
1626
1651
|
const o = e.s ? t : unwrapValue(t);
|
|
1627
1652
|
const l = ensurePB(e);
|
|
1628
|
-
|
|
1653
|
+
// #4146 (R1: node existence is unobservable; #3706: the hold's unit is
|
|
1654
|
+
// the key): a user setter writing a key a HELD container's staging left
|
|
1655
|
+
// unchanged would write it into the held staging — read as the hold's
|
|
1656
|
+
// until its landing, while the same key with a leaf (a live reader)
|
|
1657
|
+
// publishes at the flush. The key gets its leaf first, born from the two
|
|
1658
|
+
// frames (`bornStaged`: a key the hold left unchanged — or added — is
|
|
1659
|
+
// unstaged and held by no one; a key the hold changed is born held, A34
|
|
1660
|
+
// (1)), and the write stages on it (A28; a write by the holder joins it,
|
|
1661
|
+
// A34) — as it would with a reader's leaf. Kept while the container is
|
|
1662
|
+
// held (`deferredReleases`).
|
|
1663
|
+
if (userWrite && e.k?.l & CONFIG_HELD) deferredReleases.add(getNode(e, n));
|
|
1629
1664
|
if (Array.isArray(l)) {
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
t.add(n);
|
|
1633
|
-
t.add("length");
|
|
1634
|
-
}
|
|
1665
|
+
touch(e, n);
|
|
1666
|
+
if (n === "length") e.wk = WK_ALL; else touch(e, "length");
|
|
1635
1667
|
} else {
|
|
1636
|
-
|
|
1668
|
+
touch(e, n);
|
|
1637
1669
|
if (!(n in l)) e.kc++;
|
|
1638
1670
|
}
|
|
1639
1671
|
if (UNSAFE_KEYS.has(n)) {
|
|
@@ -1671,8 +1703,7 @@ const traps = {
|
|
|
1671
1703
|
};
|
|
1672
1704
|
const o = ensurePB(e);
|
|
1673
1705
|
if (e.a || !(t.enumerable && t.writable && t.configurable)) e.sc = 1;
|
|
1674
|
-
|
|
1675
|
-
if (e.wk !== WK_ALL) (e.wk ??= new Set).add(n);
|
|
1706
|
+
touch(e, n);
|
|
1676
1707
|
Object.defineProperty(o, n, t);
|
|
1677
1708
|
if (e.del !== null) e.del.delete(n);
|
|
1678
1709
|
if (i) notifyWrites(e);
|
|
@@ -1683,10 +1714,22 @@ const traps = {
|
|
|
1683
1714
|
const r = !t && writeOverride;
|
|
1684
1715
|
if (!t && !r) return true;
|
|
1685
1716
|
const i = ensurePB(e);
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
delete
|
|
1689
|
-
|
|
1717
|
+
touch(e, n);
|
|
1718
|
+
// The key count (`kc`, the overlay gate and the rebuild cap) follows a
|
|
1719
|
+
// delete the way it follows an add: an own key of the draft leaving — a
|
|
1720
|
+
// clone's key, or an overlay's own add — is one fewer now. An overlay's
|
|
1721
|
+
// override of a committed key is the exception: the committed key's
|
|
1722
|
+
// deletion is recorded in `del` and counted at the rebuild, as before.
|
|
1723
|
+
// Without the decrement the natural "delete the old key, set the new
|
|
1724
|
+
// one" shape drifted the count up by one per write until a three-key
|
|
1725
|
+
// object crossed the overlay threshold and paid a rebuild on every
|
|
1726
|
+
// commit after.
|
|
1727
|
+
const o = e.ovl && hasOwn.call(e.v, n);
|
|
1728
|
+
if (hasOwn.call(i, n)) {
|
|
1729
|
+
delete i[n];
|
|
1730
|
+
o || e.kc--;
|
|
1731
|
+
}
|
|
1732
|
+
if (o) (e.del ??= new Set).add(n);
|
|
1690
1733
|
if (r) notifyWrites(e);
|
|
1691
1734
|
return true;
|
|
1692
1735
|
}
|
|
@@ -1697,11 +1740,12 @@ const traps = {
|
|
|
1697
1740
|
* to the key's presence node or a later add never re-runs it. */ function observerHoldsContainer(e, n) {
|
|
1698
1741
|
const t = e.k;
|
|
1699
1742
|
if (t === null) return false;
|
|
1700
|
-
const r = t.
|
|
1701
|
-
return r !== null && r.
|
|
1743
|
+
const r = t.ve;
|
|
1744
|
+
return r !== null && r.u === n && (!(n.R & REACTIVE_RECOMPUTING_DEPS) || r.Te === n.Ne);
|
|
1702
1745
|
}
|
|
1703
1746
|
|
|
1704
1747
|
function storeSetter(e, n, t = true) {
|
|
1748
|
+
if (writeHook !== null) writeHook(e);
|
|
1705
1749
|
const r = e[$TARGET];
|
|
1706
1750
|
const i = writeScopes;
|
|
1707
1751
|
writeScopes = new Set;
|
|
@@ -1755,6 +1799,8 @@ function storeSetter(e, n, t = true) {
|
|
|
1755
1799
|
function createStore(e, n) {
|
|
1756
1800
|
const t = n?.shallow === true;
|
|
1757
1801
|
const r = wrap(e);
|
|
1802
|
+
// Dependency edges (store/edges.ts): the root is named like a plain signal.
|
|
1803
|
+
if (signalHook !== null) signalHook(r[$TARGET]);
|
|
1758
1804
|
if (t) {
|
|
1759
1805
|
r[$TARGET].s = true;
|
|
1760
1806
|
markRawIngest(e);
|
|
@@ -1885,7 +1931,7 @@ function snapshotWalk(e, n, t) {
|
|
|
1885
1931
|
// R27: a snapshot sees the batch's pending backing — a held one (another
|
|
1886
1932
|
// transaction's future) only from its own draft.
|
|
1887
1933
|
let o = i.v;
|
|
1888
|
-
if (i.pb !== null && (inDraft(i) || writeOverride || i.k === null || !(i.k.
|
|
1934
|
+
if (i.pb !== null && (inDraft(i) || writeOverride || i.k === null || !(i.k.l & CONFIG_HELD))) {
|
|
1889
1935
|
if (i.ovl) materializePB(i);
|
|
1890
1936
|
o = i.pb;
|
|
1891
1937
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Computed, Signal } from "./core/types.js";
|
|
2
|
+
export type Marked = Signal<any> | Computed<any>;
|
|
3
|
+
/** The verdict readers downstream of `node` — through derivations, stopping
|
|
4
|
+
* at effects — re-derive: the mark's one notification (a probe's answer
|
|
5
|
+
* changed with no value notifying anyone). Truth readers (`until`, the
|
|
6
|
+
* `refresh` waiter) too, which a lagging flight parked (deferred.ts) — but
|
|
7
|
+
* not through a derived store, whose leaves change only once its derive
|
|
8
|
+
* re-runs: they re-derive at that write. */
|
|
9
|
+
export declare function repoll(node: Marked, seen?: Set<Computed<any>>, readers?: number): void;
|
|
10
|
+
/** One mark on `node`. The declarer repolls once its bookkeeping is done. */
|
|
11
|
+
export declare function mark(node: Marked): void;
|
|
12
|
+
/** Drops one mark from `node`: true when it was the last — the node's
|
|
13
|
+
* verdict readers have re-derived. */
|
|
14
|
+
export declare function unmark(node: Marked): boolean;
|