@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/prod/store/store.js
CHANGED
|
@@ -99,45 +99,45 @@ function createTarget(e, n, t, r = n?.fam ?? null) {
|
|
|
99
99
|
// Direct field assignment in one fixed order (no Object.assign literal
|
|
100
100
|
// copy): every target shares a hidden-class transition chain — createTarget
|
|
101
101
|
// was the #2 store cost in the uibench creation profile.
|
|
102
|
-
const
|
|
103
|
-
|
|
102
|
+
const o = Array.isArray(e) ? [] : new TargetShape;
|
|
103
|
+
o.v = e;
|
|
104
104
|
// Chained-backing flag (backing IS another store's proxy, §7b) — cached so
|
|
105
105
|
// the hot read path never does a per-read symbol lookup on the backing.
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
setLookup(e,
|
|
127
|
-
return
|
|
106
|
+
o.ch = e[$TARGET] !== undefined;
|
|
107
|
+
o.pb = null;
|
|
108
|
+
o.n = null;
|
|
109
|
+
o.h = null;
|
|
110
|
+
o.k = null;
|
|
111
|
+
o.dk = null;
|
|
112
|
+
o.wk = null;
|
|
113
|
+
o.u = n;
|
|
114
|
+
o.pk = t;
|
|
115
|
+
o.px = null;
|
|
116
|
+
o.d = false;
|
|
117
|
+
o.a = false;
|
|
118
|
+
o.sc = 0;
|
|
119
|
+
o.kc = 0;
|
|
120
|
+
o.nc = 0;
|
|
121
|
+
o.fam = r;
|
|
122
|
+
o.s = false;
|
|
123
|
+
o.ovl = false;
|
|
124
|
+
o.del = null;
|
|
125
|
+
o.px = new Proxy(o, traps);
|
|
126
|
+
setLookup(e, o);
|
|
127
|
+
return o;
|
|
128
128
|
}
|
|
129
129
|
|
|
130
130
|
function wrap(e, n = null, t = null, r = n?.fam ?? null) {
|
|
131
131
|
// markRaw'd values never wrap through ANY store (R42; sticky raw-marking
|
|
132
132
|
// is one half of the never-both-wrapped-and-raw invariant, RUL-12).
|
|
133
133
|
if (rawValuesUsed && isRawValue(e)) return e;
|
|
134
|
-
const
|
|
135
|
-
if (
|
|
136
|
-
const
|
|
137
|
-
if (
|
|
134
|
+
const o = lookupTarget(e, r);
|
|
135
|
+
if (o !== undefined) return o.px;
|
|
136
|
+
const i = e[$TARGET];
|
|
137
|
+
if (i?.px === e) {
|
|
138
138
|
// Foreign-family proxies re-wrap into THIS family (writes stay isolated);
|
|
139
139
|
// same-family and plain-store proxies pass through.
|
|
140
|
-
if (r === null ||
|
|
140
|
+
if (r === null || i.fam === r) return e;
|
|
141
141
|
return createTarget(e, n, t, r).px;
|
|
142
142
|
}
|
|
143
143
|
return createTarget(e, n, t, r).px;
|
|
@@ -247,7 +247,7 @@ function releaseSlot(e) {
|
|
|
247
247
|
// holds: its release waits for the commit that resolves it. So does a leaf of
|
|
248
248
|
// a held container (#4146): a mainline write it carried is in the held
|
|
249
249
|
// staging too, where it would read as the hold's until the landing.
|
|
250
|
-
const slotKept = e => e.
|
|
250
|
+
const slotKept = e => e.ie !== NOT_PENDING || e.l & CONFIG_OVERRIDE || e.O.k?.l & CONFIG_HELD;
|
|
251
251
|
|
|
252
252
|
setSlotUnobserved(e => {
|
|
253
253
|
if (slotKept(e)) deferredReleases.add(e); else releaseSlot(e);
|
|
@@ -258,24 +258,24 @@ setSlotUnobserved(e => {
|
|
|
258
258
|
* pending one — and held by the container's transaction when the container
|
|
259
259
|
* is held (#3706: the unit of the hold is the key — a key the batch left
|
|
260
260
|
* unchanged stages nothing and holds no one). */ function bornStaged(e, n, t, r) {
|
|
261
|
-
if (n.xe && n.xe(n.
|
|
261
|
+
if (n.xe && n.xe(n.le, t)) return;
|
|
262
262
|
queuePendingNode(n);
|
|
263
|
-
n.
|
|
264
|
-
const
|
|
265
|
-
if (
|
|
263
|
+
n.ie = t;
|
|
264
|
+
const o = e.k;
|
|
265
|
+
if (o === null) return;
|
|
266
266
|
// a node-less staging holds nothing (`stageOn`)
|
|
267
267
|
// Held by the container's transaction only for a key the HELD staging
|
|
268
268
|
// changed — a mainline layer's change above it stages mainline. (A
|
|
269
269
|
// container carrying a guess is a lane's: the flush's park decides —
|
|
270
270
|
// unless a correction folded under the guess, D-34: the key is that
|
|
271
271
|
// correction's hold's.)
|
|
272
|
-
if (
|
|
273
|
-
const e = txOf(
|
|
274
|
-
if (!(
|
|
272
|
+
if (o.l & CONFIG_HELD && heldKeyChanged(e, r)) {
|
|
273
|
+
const e = txOf(o);
|
|
274
|
+
if (!(o.l & CONFIG_OVERRIDE) || e.folded) holdNode(n, resolveTx(e._parent ?? e));
|
|
275
275
|
}
|
|
276
276
|
// A28 (4): a batch written inside a creation-time pass is promoted — its
|
|
277
277
|
// late-materialized leaf with it.
|
|
278
|
-
if (
|
|
278
|
+
if (o.l & CONFIG_PROMOTED) notePromotedWrite(n);
|
|
279
279
|
}
|
|
280
280
|
|
|
281
281
|
function getNode(e, n,
|
|
@@ -285,30 +285,30 @@ function getNode(e, n,
|
|
|
285
285
|
// callers), 0/1 = probed.
|
|
286
286
|
t = -1) {
|
|
287
287
|
const r = e.n ??= Object.create(null);
|
|
288
|
-
let
|
|
289
|
-
if (
|
|
288
|
+
let o = r[n];
|
|
289
|
+
if (o === undefined) {
|
|
290
290
|
// Accessor-ness resolved ONCE per node (no per-object descriptor scan
|
|
291
291
|
// on reads): accessor keys serve through Reflect.get with the proxy
|
|
292
292
|
// receiver.
|
|
293
|
-
const
|
|
294
|
-
const l =
|
|
295
|
-
if (
|
|
296
|
-
r[n] =
|
|
293
|
+
const i = e.pb;
|
|
294
|
+
const l = o = slotSignal(committed(e)[n], slotNodeEquals, e, n, t === -1 ? isOwnAccessor(i ?? e.v, n) : t === 1);
|
|
295
|
+
if (i !== null && !l.acc) bornStaged(e, l, e.del?.has(n) ? undefined : i[n], n);
|
|
296
|
+
r[n] = o;
|
|
297
297
|
e.nc++;
|
|
298
298
|
noteNode(e, l, n);
|
|
299
299
|
}
|
|
300
|
-
return
|
|
300
|
+
return o;
|
|
301
301
|
}
|
|
302
302
|
|
|
303
303
|
function getHasNode(e, n) {
|
|
304
304
|
const t = e.h ??= Object.create(null);
|
|
305
305
|
let r = t[n];
|
|
306
306
|
if (r === undefined) {
|
|
307
|
-
const
|
|
308
|
-
const
|
|
309
|
-
if (
|
|
307
|
+
const o = r = slotSignal(n in committed(e), isEqual, e, n, false);
|
|
308
|
+
const i = e.pb;
|
|
309
|
+
if (i !== null) bornStaged(e, o, n in i && !e.del?.has(n), n);
|
|
310
310
|
t[n] = r;
|
|
311
|
-
noteNode(e,
|
|
311
|
+
noteNode(e, o, n);
|
|
312
312
|
}
|
|
313
313
|
return r;
|
|
314
314
|
}
|
|
@@ -325,8 +325,8 @@ function getHasNode(e, n) {
|
|
|
325
325
|
// pending backing staged — so whoever asked for it reads the frame it
|
|
326
326
|
// would have read had the node been there from the write.
|
|
327
327
|
if (e.pb !== null && !directCommit) {
|
|
328
|
-
n.
|
|
329
|
-
n.
|
|
328
|
+
n.le = preBatch(e);
|
|
329
|
+
n.ie = e.pb;
|
|
330
330
|
queuePendingNode(n);
|
|
331
331
|
}
|
|
332
332
|
}
|
|
@@ -345,8 +345,8 @@ function getHasNode(e, n) {
|
|
|
345
345
|
* (`storeParkHook`) — the one case the staging home exists for. */ function stageOn(e, n) {
|
|
346
346
|
if (e.k === null && passLane === null && (context === null || globalQueue.q) && !deriveHolds(e)) return;
|
|
347
347
|
const t = getContainerNode(e);
|
|
348
|
-
if (t.
|
|
349
|
-
t.
|
|
348
|
+
if (t.ie === NOT_PENDING) queuePendingNode(t);
|
|
349
|
+
t.ie = n;
|
|
350
350
|
// A28 (4): a write issued inside a pass outside a flush (a creation-time
|
|
351
351
|
// derive) is promoted at the pass's end — the batch with it.
|
|
352
352
|
if (context !== null) notePromotedWrite(t);
|
|
@@ -389,7 +389,7 @@ function bumpDeep(e) {
|
|
|
389
389
|
// the node; the comparator is the store's, done).
|
|
390
390
|
if (e.l & CONFIG_OVERRIDE) setSignal(e, n); else {
|
|
391
391
|
if (e.l & CONFIG_HELD) joinFuture(txOf(e));
|
|
392
|
-
if (snapshotCaptureActive) captureWriteSnapshot(e, e.
|
|
392
|
+
if (snapshotCaptureActive) captureWriteSnapshot(e, e.le);
|
|
393
393
|
insertSubs(e);
|
|
394
394
|
schedule();
|
|
395
395
|
}
|
|
@@ -421,10 +421,10 @@ function isOwnAccessor(e, n) {
|
|
|
421
421
|
}
|
|
422
422
|
const t = Object.getOwnPropertyDescriptors(e);
|
|
423
423
|
for (const r of Reflect.ownKeys(t)) {
|
|
424
|
-
const
|
|
424
|
+
const o = t[r];
|
|
425
425
|
if (r === "length" && Array.isArray(e)) continue;
|
|
426
|
-
|
|
427
|
-
if (!
|
|
426
|
+
o.configurable = true;
|
|
427
|
+
if (!o.get && !o.set) o.writable = true; else n.a = true;
|
|
428
428
|
}
|
|
429
429
|
const r = Array.isArray(e) ? Object.defineProperties([], t) : Object.create(Object.getPrototypeOf(e), t);
|
|
430
430
|
r[$OWNER] = n;
|
|
@@ -448,13 +448,13 @@ function copyOwn(e, n, t) {
|
|
|
448
448
|
const n = e.v;
|
|
449
449
|
const t = Reflect.ownKeys(n);
|
|
450
450
|
let r = Object.getPrototypeOf(n) === Object.prototype;
|
|
451
|
-
for (const
|
|
452
|
-
if (isOwnAccessor(n,
|
|
451
|
+
for (const o of t) {
|
|
452
|
+
if (isOwnAccessor(n, o)) {
|
|
453
453
|
e.a = true;
|
|
454
454
|
r = false;
|
|
455
455
|
break;
|
|
456
456
|
}
|
|
457
|
-
if (r && !propertyIsEnumerable.call(n,
|
|
457
|
+
if (r && !propertyIsEnumerable.call(n, o)) r = false;
|
|
458
458
|
}
|
|
459
459
|
e.sc = r ? 2 : 1;
|
|
460
460
|
e.kc = t.length;
|
|
@@ -483,8 +483,8 @@ const plainProto = e => {
|
|
|
483
483
|
const t = e.wk;
|
|
484
484
|
if (t !== null && t !== WK_ALL && t.u === undefined && t.size <= OVERLAY_REBUILD_MIN_ADDS) return false;
|
|
485
485
|
const r = e.v;
|
|
486
|
-
let
|
|
487
|
-
for (const e of Reflect.ownKeys(n)) if (!hasOwn.call(r, e) && ++
|
|
486
|
+
let o = 0;
|
|
487
|
+
for (const e of Reflect.ownKeys(n)) if (!hasOwn.call(r, e) && ++o > OVERLAY_REBUILD_MIN_ADDS) return true;
|
|
488
488
|
return false;
|
|
489
489
|
}
|
|
490
490
|
|
|
@@ -494,7 +494,7 @@ const plainProto = e => {
|
|
|
494
494
|
const t = overlayOnto(e, e.sc === 2 ? wideClone(e.v, e) : cloneRaw(e.v, e), n);
|
|
495
495
|
e.pb = t;
|
|
496
496
|
// The staging IS the pending backing: re-point the container node.
|
|
497
|
-
if (e.k?.
|
|
497
|
+
if (e.k?.ie === n) e.k.ie = t;
|
|
498
498
|
return t;
|
|
499
499
|
}
|
|
500
500
|
|
|
@@ -506,7 +506,7 @@ const plainProto = e => {
|
|
|
506
506
|
// An optimistic edit composes on the view the user saw and becomes
|
|
507
507
|
// guesses at the setter's exit: nothing is staged, nothing folds
|
|
508
508
|
// (optimistic.ts).
|
|
509
|
-
if (userWrite && e.fam?.opt === true && !pendingNotify.has(e)) return e.pb = optHooks.draft(e);
|
|
509
|
+
if (optHooks && userWrite && e.fam?.opt === true && !pendingNotify.has(e)) return e.pb = optHooks.draft(e);
|
|
510
510
|
if (n !== null && !isOwned(n)) {
|
|
511
511
|
// An adopted object awaiting its fold is the user's: the draft writes a
|
|
512
512
|
// clone of it. The clone is the batch's staging — unless the adoption is
|
|
@@ -515,7 +515,7 @@ const plainProto = e => {
|
|
|
515
515
|
// mainline setter mid-hold publishes mainline; the held keys stay held).
|
|
516
516
|
n = e.pb = cloneRaw(n, e);
|
|
517
517
|
const t = e.k;
|
|
518
|
-
if (t !== null && !(t.l & CONFIG_HELD)) t.
|
|
518
|
+
if (t !== null && !(t.l & CONFIG_HELD)) t.ie = n;
|
|
519
519
|
} else if (n === null) {
|
|
520
520
|
const t = e.v;
|
|
521
521
|
if (!directCommit) queueFold(e);
|
|
@@ -553,10 +553,10 @@ const plainProto = e => {
|
|
|
553
553
|
const t = e.pk;
|
|
554
554
|
const r = e.u.v;
|
|
555
555
|
if (r[t] === n || r[t] === e.v || !Array.isArray(r)) return t;
|
|
556
|
-
const
|
|
557
|
-
if (
|
|
558
|
-
e.pk =
|
|
559
|
-
return
|
|
556
|
+
const o = r.indexOf(n);
|
|
557
|
+
if (o === -1) return t;
|
|
558
|
+
e.pk = o;
|
|
559
|
+
return o;
|
|
560
560
|
}
|
|
561
561
|
|
|
562
562
|
/** Overlay flatten (#3044): own keys onto the owned committed backing in
|
|
@@ -596,7 +596,7 @@ const plainProto = e => {
|
|
|
596
596
|
} else r = e.v;
|
|
597
597
|
if (directCommit) {
|
|
598
598
|
e.pb = null;
|
|
599
|
-
if (e.k !== null) e.k.
|
|
599
|
+
if (e.k !== null) e.k.le = n;
|
|
600
600
|
} else {
|
|
601
601
|
// Eager (INTERNALS §3): the backing swaps now — handlers read the
|
|
602
602
|
// adopted object before the flush — while the container node, when
|
|
@@ -614,8 +614,8 @@ const plainProto = e => {
|
|
|
614
614
|
e.a = false;
|
|
615
615
|
e.wk = null;
|
|
616
616
|
// adoption supersedes staged trap writes
|
|
617
|
-
const
|
|
618
|
-
if (
|
|
617
|
+
const o = n[$OWNER];
|
|
618
|
+
if (o?.fam === e.fam) n[$OWNER] = e; else setLookup(n, e);
|
|
619
619
|
if (t && r !== n) notifyFold(e, r, n);
|
|
620
620
|
}
|
|
621
621
|
|
|
@@ -691,8 +691,8 @@ let foldIndex = null;
|
|
|
691
691
|
const r = e[t];
|
|
692
692
|
if (r.pb === null) continue;
|
|
693
693
|
// folded already (a direct commit)
|
|
694
|
-
const
|
|
695
|
-
if (
|
|
694
|
+
const o = r.k;
|
|
695
|
+
if (o !== null && o.ie !== NOT_PENDING) {
|
|
696
696
|
// held: commits with its hold
|
|
697
697
|
foldList.push(r);
|
|
698
698
|
foldOlds.push(n[t]);
|
|
@@ -727,9 +727,9 @@ let foldIndex = null;
|
|
|
727
727
|
if (n.ch) {
|
|
728
728
|
const t = e.ze;
|
|
729
729
|
const r = n.v;
|
|
730
|
-
if (n.h?.[t] === e) e.
|
|
730
|
+
if (n.h?.[t] === e) e.le = untrack(() => t in r); else if (n.n?.[t] === e) e.le = untrack(() => unwrapValue(r[t]));
|
|
731
731
|
}
|
|
732
|
-
return e.
|
|
732
|
+
return e.le;
|
|
733
733
|
};
|
|
734
734
|
|
|
735
735
|
installStoreHooks(storePark, () => {
|
|
@@ -763,7 +763,7 @@ function runDirect(e) {
|
|
|
763
763
|
const t = e.k;
|
|
764
764
|
const r = e.pb;
|
|
765
765
|
if (r !== null) {
|
|
766
|
-
if (r === e.v) ; else if (e.ovl && (e.v !== n || !overlayRebuilds(e, r) && t?.T?.
|
|
766
|
+
if (r === e.v) ; else if (e.ovl && (e.v !== n || !overlayRebuilds(e, r) && t?.T?.De !== n)) {
|
|
767
767
|
// Overlay flatten (#3044): the backing keeps its identity, so the
|
|
768
768
|
// `t.v === old` gate below skips path copying (the parent slot
|
|
769
769
|
// already points here) and the adopted-notify (setter
|
|
@@ -775,15 +775,15 @@ function runDirect(e) {
|
|
|
775
775
|
// owned backing takes the written keys.
|
|
776
776
|
privatizeCommitted(e);
|
|
777
777
|
const t = e.v;
|
|
778
|
-
const
|
|
779
|
-
if (
|
|
780
|
-
for (let e =
|
|
778
|
+
const o = e.wk;
|
|
779
|
+
if (o !== null && o !== WK_ALL) {
|
|
780
|
+
for (let e = o; e !== undefined; e = e.u) for (const n of e) {
|
|
781
781
|
if (hasOwn.call(r, n)) copyOwn(t, r, n); else delete t[n];
|
|
782
782
|
}
|
|
783
783
|
} else {
|
|
784
|
-
for (const e of Reflect.ownKeys(r)) copyOwn(t, r, e);
|
|
784
|
+
for (const e of Reflect.ownKeys(r)) if (e !== $OWNER) copyOwn(t, r, e);
|
|
785
785
|
for (const e of Reflect.ownKeys(n)) {
|
|
786
|
-
if (!hasOwn.call(r, e)) delete t[e];
|
|
786
|
+
if (e !== $OWNER && !hasOwn.call(r, e)) delete t[e];
|
|
787
787
|
}
|
|
788
788
|
}
|
|
789
789
|
} else {
|
|
@@ -801,7 +801,7 @@ function runDirect(e) {
|
|
|
801
801
|
// subscribes to was a transient staging home (INTERNALS §5: an
|
|
802
802
|
// observer-less write holds a transient record until the fold,
|
|
803
803
|
// discarded with it) — gone with the batch.
|
|
804
|
-
if (t.o === null) e.k = null; else if (t.
|
|
804
|
+
if (t.o === null) e.k = null; else if (t.le instanceof LaneView) t.le.base = e.v; else t.le = e.v;
|
|
805
805
|
}
|
|
806
806
|
if (e.v !== n && e.u) {
|
|
807
807
|
const t = parentSlotKey(e, n);
|
|
@@ -840,7 +840,7 @@ function heldDerivation(e, n, t) {
|
|
|
840
840
|
// Optimistic channel: a user's writes on an optimistic family become
|
|
841
841
|
// guesses on the nodes (lanes); the draft is discarded, the committed
|
|
842
842
|
// backing never touched.
|
|
843
|
-
if (userWrite && e.fam?.opt === true) {
|
|
843
|
+
if (optHooks && userWrite && e.fam?.opt === true) {
|
|
844
844
|
// The draft is discarded first: the diff reads the target (its nodes
|
|
845
845
|
// are born from the committed frame, not the draft).
|
|
846
846
|
e.pb = null;
|
|
@@ -863,49 +863,49 @@ function heldDerivation(e, n, t) {
|
|
|
863
863
|
// only (D-8, #3743): a key an earlier setter of the batch wrote and this
|
|
864
864
|
// one did not is no second proposal — its node was told then, and telling
|
|
865
865
|
// a held node its unchanged value again would join this tick to the hold.
|
|
866
|
-
const
|
|
867
|
-
const
|
|
868
|
-
if (e.fam !== null && !heldDerivationHit &&
|
|
866
|
+
const o = e.wk;
|
|
867
|
+
const i = o === WK_ALL || e.a === true || !plainProto(e.ovl ? e.v : n) ? null : o;
|
|
868
|
+
if (e.fam !== null && !heldDerivationHit && i !== null) for (const n of i) if (heldDerivation(e, r?.[n], n)) {
|
|
869
869
|
heldDerivationHit = true;
|
|
870
870
|
break;
|
|
871
871
|
}
|
|
872
872
|
if (r !== null) {
|
|
873
|
-
const
|
|
874
|
-
for (const
|
|
875
|
-
const
|
|
876
|
-
if (
|
|
877
|
-
if (
|
|
873
|
+
const o = i ?? Reflect.ownKeys(r);
|
|
874
|
+
for (const i of o) {
|
|
875
|
+
const o = r[i];
|
|
876
|
+
if (o === undefined) continue;
|
|
877
|
+
if (o.acc === true || hasOwn.call(n, i) && lookupGetter.call(n, i) !== undefined) {
|
|
878
878
|
// Accessor keys: the node is linked for shape-change notification,
|
|
879
879
|
// its value is never served (the getter runs with the proxy
|
|
880
880
|
// receiver on read) — FORCE wakes the readers. A data descriptor
|
|
881
881
|
// falls through so the cleared-acc hot read serves it (#3949);
|
|
882
882
|
// an own getter's descriptor has no `value`, so the compare below
|
|
883
883
|
// would otherwise keep the getter's result (or FORCE) for `undefined`.
|
|
884
|
-
|
|
885
|
-
const e = Object.getOwnPropertyDescriptor(t,
|
|
886
|
-
const r = Object.getOwnPropertyDescriptor(n,
|
|
884
|
+
o.acc = isOwnAccessor(n, i);
|
|
885
|
+
const e = Object.getOwnPropertyDescriptor(t, i);
|
|
886
|
+
const r = Object.getOwnPropertyDescriptor(n, i);
|
|
887
887
|
if (!r || r.get || r.set) {
|
|
888
|
-
if (e?.get !== r?.get || e?.set !== r?.set || e?.value !== r?.value) setSignal(
|
|
888
|
+
if (e?.get !== r?.get || e?.set !== r?.set || e?.value !== r?.value) setSignal(o, () => FORCE);
|
|
889
889
|
continue;
|
|
890
890
|
}
|
|
891
|
-
if (e?.get || e?.set || !isEqual(e?.value, r.value)) setSignal(
|
|
891
|
+
if (e?.get || e?.set || !isEqual(e?.value, r.value)) setSignal(o, () => r.value);
|
|
892
892
|
continue;
|
|
893
893
|
}
|
|
894
|
-
const l = e.del?.has(
|
|
895
|
-
setSignal(
|
|
894
|
+
const l = e.del?.has(i) ? undefined : n[i];
|
|
895
|
+
setSignal(o, () => l);
|
|
896
896
|
if (e.fam !== null) {
|
|
897
897
|
// The derive's write is a derivation; a user setter's is a proposal
|
|
898
898
|
// (A34 (3)'s discriminator).
|
|
899
899
|
if (!userWrite) {
|
|
900
|
-
|
|
901
|
-
holdWithDerive(e,
|
|
902
|
-
} else
|
|
900
|
+
o.l &= ~CONFIG_MANUAL_WRITE;
|
|
901
|
+
holdWithDerive(e, o);
|
|
902
|
+
} else o.l |= CONFIG_MANUAL_WRITE;
|
|
903
903
|
}
|
|
904
904
|
}
|
|
905
905
|
}
|
|
906
906
|
const l = e.h;
|
|
907
907
|
if (l !== null) {
|
|
908
|
-
const t =
|
|
908
|
+
const t = i ?? Reflect.ownKeys(l);
|
|
909
909
|
for (const r of t) {
|
|
910
910
|
const t = l[r];
|
|
911
911
|
if (t !== undefined) {
|
|
@@ -915,11 +915,11 @@ function heldDerivation(e, n, t) {
|
|
|
915
915
|
}
|
|
916
916
|
}
|
|
917
917
|
if (e.dk !== null) {
|
|
918
|
-
if (e.del?.size) bumpDeep(e); else for (const r of
|
|
918
|
+
if (e.del?.size) bumpDeep(e); else for (const r of i ?? Reflect.ownKeys(n)) {
|
|
919
919
|
if (r === $OWNER) continue;
|
|
920
|
-
const
|
|
921
|
-
const
|
|
922
|
-
if (
|
|
920
|
+
const o = n[r];
|
|
921
|
+
const i = t[r];
|
|
922
|
+
if (o !== null && typeof o === "object" ? !targetsEqual(i, o) : !isEqual(i, o)) {
|
|
923
923
|
bumpDeep(e);
|
|
924
924
|
break;
|
|
925
925
|
}
|
|
@@ -961,8 +961,8 @@ function heldDerivation(e, n, t) {
|
|
|
961
961
|
if (e.length !== n.length) return true;
|
|
962
962
|
for (let t = 0; t < n.length; t++) {
|
|
963
963
|
const r = e[t];
|
|
964
|
-
const
|
|
965
|
-
if (!isEqual(r,
|
|
964
|
+
const o = n[t];
|
|
965
|
+
if (!isEqual(r, o) && !targetsEqual(r, o)) return true;
|
|
966
966
|
}
|
|
967
967
|
return false;
|
|
968
968
|
}
|
|
@@ -974,23 +974,23 @@ function membershipChanged(e, n) {
|
|
|
974
974
|
return false;
|
|
975
975
|
}
|
|
976
976
|
|
|
977
|
-
/** One leaf's notification for an adoption diff (descriptor-aware). */ function notifyKeyDiff(e, n, t, r,
|
|
978
|
-
if (e.acc === true ||
|
|
977
|
+
/** One leaf's notification for an adoption diff (descriptor-aware). */ function notifyKeyDiff(e, n, t, r, o = true) {
|
|
978
|
+
if (e.acc === true || o && hasOwn.call(r, n) && lookupGetter.call(r, n) !== undefined) {
|
|
979
979
|
e.acc = isOwnAccessor(r, n);
|
|
980
|
-
const
|
|
981
|
-
const
|
|
980
|
+
const o = Object.getOwnPropertyDescriptor(t, n);
|
|
981
|
+
const i = Object.getOwnPropertyDescriptor(r, n);
|
|
982
982
|
// Data descriptors fall through, as in notifyWrites (#3949).
|
|
983
|
-
if (!
|
|
984
|
-
if (
|
|
983
|
+
if (!i || i.get || i.set) {
|
|
984
|
+
if (o?.get !== i?.get || o?.set !== i?.set || o?.value !== i?.value) setSignal(e, () => FORCE);
|
|
985
985
|
return;
|
|
986
986
|
}
|
|
987
|
-
const l =
|
|
988
|
-
const u =
|
|
989
|
-
if (
|
|
987
|
+
const l = o?.value;
|
|
988
|
+
const u = i?.value;
|
|
989
|
+
if (o?.get || o?.set || !isEqual(l, u) && !targetsEqual(l, u)) setSignal(e, typeof u === "function" ? () => u : u);
|
|
990
990
|
} else {
|
|
991
|
-
const
|
|
992
|
-
const
|
|
993
|
-
if (!isEqual(
|
|
991
|
+
const o = t[n];
|
|
992
|
+
const i = r[n];
|
|
993
|
+
if (!isEqual(o, i) && !targetsEqual(o, i)) setSignal(e, typeof i === "function" ? () => i : i);
|
|
994
994
|
}
|
|
995
995
|
}
|
|
996
996
|
|
|
@@ -998,9 +998,9 @@ function hasAccessorFlag(e) {
|
|
|
998
998
|
return e.acc === true;
|
|
999
999
|
}
|
|
1000
1000
|
|
|
1001
|
-
/** One leaf's notification when the caller already has both values. */ function notifyKeyValue(e, n, t, r,
|
|
1001
|
+
/** One leaf's notification when the caller already has both values. */ function notifyKeyValue(e, n, t, r, o, i) {
|
|
1002
1002
|
if (e.acc === true) {
|
|
1003
|
-
notifyKeyDiff(e, n,
|
|
1003
|
+
notifyKeyDiff(e, n, o, i, false);
|
|
1004
1004
|
return;
|
|
1005
1005
|
}
|
|
1006
1006
|
if (!isEqual(t, r) && !targetsEqual(t, r)) setSignal(e, typeof r === "function" ? () => r : r);
|
|
@@ -1029,12 +1029,12 @@ function hasAccessorFlag(e) {
|
|
|
1029
1029
|
const r = e.h;
|
|
1030
1030
|
if (r !== null) {
|
|
1031
1031
|
const e = n[$TARGET];
|
|
1032
|
-
for (const
|
|
1032
|
+
for (const o of Reflect.ownKeys(r)) if (e || o in n !== o in t) setSignal(r[o], o in t);
|
|
1033
1033
|
}
|
|
1034
|
-
const
|
|
1035
|
-
if (
|
|
1034
|
+
const o = e.k;
|
|
1035
|
+
if (o !== null && (o.o !== null || o.l & CONFIG_OVERRIDE)) {
|
|
1036
1036
|
const e = Array.isArray(t) && Array.isArray(n) ? arrayStructureChanged(n, t) : membershipChanged(n, t);
|
|
1037
|
-
if (e) notifyContainer(
|
|
1037
|
+
if (e) notifyContainer(o, t);
|
|
1038
1038
|
}
|
|
1039
1039
|
}
|
|
1040
1040
|
|
|
@@ -1089,7 +1089,7 @@ function inDraft(e) {
|
|
|
1089
1089
|
* "adoption is eager by contract" — and the node keeps the frame committed
|
|
1090
1090
|
* readers under a hold still see), `t.v` otherwise. */ function committed(e) {
|
|
1091
1091
|
const n = e.k;
|
|
1092
|
-
if (n !== null) return n.
|
|
1092
|
+
if (n !== null) return n.ie !== NOT_PENDING ? asBacking(n.le) : e.v;
|
|
1093
1093
|
// A node-less staging (`stageOn`): the fold queue remembers the frame.
|
|
1094
1094
|
return e.pb !== null ? preBatch(e) : e.v;
|
|
1095
1095
|
}
|
|
@@ -1148,7 +1148,7 @@ function inDraft(e) {
|
|
|
1148
1148
|
}
|
|
1149
1149
|
return r;
|
|
1150
1150
|
}
|
|
1151
|
-
const
|
|
1151
|
+
const o = e.k;
|
|
1152
1152
|
// A key whose leaf carries a lane's value (a guess, S4): the leaf serves
|
|
1153
1153
|
// it — the container's frame is not consulted (a reader is not made a
|
|
1154
1154
|
// stale reader of the container's hold for a key it does not see through
|
|
@@ -1157,12 +1157,12 @@ function inDraft(e) {
|
|
|
1157
1157
|
const t = e.n?.[n];
|
|
1158
1158
|
if (t?.l & CONFIG_OVERRIDE) return committed(e);
|
|
1159
1159
|
}
|
|
1160
|
-
const
|
|
1160
|
+
const i = o !== null && (o.l & CONFIG_HELD) !== 0;
|
|
1161
1161
|
// A held container: the hold's unit is the key (#3706). A key the HELD
|
|
1162
1162
|
// staging left unchanged reads the ambient view — a mainline layer's
|
|
1163
1163
|
// write above the hold publishes mainline (#3688, #3612); a key it
|
|
1164
1164
|
// changed reads the frame core serves this reader.
|
|
1165
|
-
if (
|
|
1165
|
+
if (i && n !== undefined && !heldKeyChanged(e, n, t)) return r;
|
|
1166
1166
|
const l = stagingReader();
|
|
1167
1167
|
if (l === null) {
|
|
1168
1168
|
if (getObserver() !== null) return r;
|
|
@@ -1175,8 +1175,8 @@ function inDraft(e) {
|
|
|
1175
1175
|
// probe) judges the container like any node — for a key the batch
|
|
1176
1176
|
// changed; an unchanged key is committed and final (A22: pending is per
|
|
1177
1177
|
// key). A held container's committed frame is the node's.
|
|
1178
|
-
if (verdict === null || !
|
|
1179
|
-
return
|
|
1178
|
+
if (verdict === null || !i && n !== undefined && !keyChanged(e, n, t)) return i ? asBacking(o.le) : e.v;
|
|
1179
|
+
return o === null ? committed(e) : asBacking(read(o));
|
|
1180
1180
|
}
|
|
1181
1181
|
// A pass reading a key the batch left unchanged: the same value in both
|
|
1182
1182
|
// frames — committed, holding no one. Otherwise the container's frame by
|
|
@@ -1185,7 +1185,7 @@ function inDraft(e) {
|
|
|
1185
1185
|
// sees committed and re-derives at the landing, a memo joins the future,
|
|
1186
1186
|
// a staging read is marked. The key's own leaf, when it has one, decides
|
|
1187
1187
|
// the value the same way.
|
|
1188
|
-
if (!
|
|
1188
|
+
if (!i) {
|
|
1189
1189
|
// A plain pass this flush already served a staging as the screen
|
|
1190
1190
|
// (REACTIVE_STAGED_READ — what `read()` would set again here) reads an
|
|
1191
1191
|
// unheld staging directly: an unchanged key is the same value in both
|
|
@@ -1197,18 +1197,18 @@ function inDraft(e) {
|
|
|
1197
1197
|
// A node-less staging (`stageOn`): what `read()` of its node would do
|
|
1198
1198
|
// for this pass — a verdict reader sees the screen, any other derives
|
|
1199
1199
|
// from the staging and is marked as having read it.
|
|
1200
|
-
if (
|
|
1200
|
+
if (o === null) {
|
|
1201
1201
|
if (l.l & CONFIG_VERDICT && stagedScreen(l)) return committed(e);
|
|
1202
1202
|
stagedRead(l);
|
|
1203
1203
|
return r;
|
|
1204
1204
|
}
|
|
1205
1205
|
}
|
|
1206
|
-
return asBacking(untrack(() => read(
|
|
1206
|
+
return asBacking(untrack(() => read(o)));
|
|
1207
1207
|
}
|
|
1208
1208
|
|
|
1209
1209
|
/** Did the HELD staging (the container node's, not a mainline layer above
|
|
1210
1210
|
* it) change `key`? */ function heldKeyChanged(e, n, t = true) {
|
|
1211
|
-
return changedBetween(e, e.k.
|
|
1211
|
+
return changedBetween(e, e.k.le, e.k.ie, n, t) && !adoptChild(e, n);
|
|
1212
1212
|
}
|
|
1213
1213
|
|
|
1214
1214
|
/** The values of a held frame, built once per frame: neither the committed
|
|
@@ -1235,19 +1235,19 @@ function rawsOf(e) {
|
|
|
1235
1235
|
* `version` holds. A record's keys pair by name; an array's by the family's
|
|
1236
1236
|
* key — without a family the pairing is not known here and the hold stands. */ function adoptChild(e, n) {
|
|
1237
1237
|
const t = e.k;
|
|
1238
|
-
const r = asBacking(t.
|
|
1239
|
-
const
|
|
1240
|
-
const
|
|
1238
|
+
const r = asBacking(t.le);
|
|
1239
|
+
const o = r[n];
|
|
1240
|
+
const i = t.ie[n];
|
|
1241
1241
|
const l = Array.isArray(r) ? e.fam?.key : null;
|
|
1242
|
-
if (e.s || l === undefined || !sameRow(
|
|
1242
|
+
if (e.s || l === undefined || !sameRow(o, i, l) || !isWrappable(o) || !isWrappable(i) || Array.isArray(o) !== Array.isArray(i) || lookupTarget(o, e.fam) !== undefined || lookupTarget(i, e.fam) !== undefined ||
|
|
1243
1243
|
// A raw in both frames (the same objects swapped or reordered) is its
|
|
1244
1244
|
// own row: pairing it with another would alias the two after the commit.
|
|
1245
|
-
rawsOf(r).has(
|
|
1245
|
+
rawsOf(r).has(i) || rawsOf(t.ie).has(o)) return false;
|
|
1246
1246
|
// A raw-marked value wraps to itself, a proxy to its own target: neither
|
|
1247
1247
|
// is a fresh target around `ov`.
|
|
1248
|
-
const u = wrap(
|
|
1249
|
-
if (u?.v !==
|
|
1250
|
-
adoptPB(u,
|
|
1248
|
+
const u = wrap(o, e, n)[$TARGET];
|
|
1249
|
+
if (u?.v !== o) return false;
|
|
1250
|
+
adoptPB(u, i, false);
|
|
1251
1251
|
holdNode(getContainerNode(u), txOf(t));
|
|
1252
1252
|
return true;
|
|
1253
1253
|
}
|
|
@@ -1271,13 +1271,13 @@ function rawsOf(e) {
|
|
|
1271
1271
|
return changedBetween(e, committed(e), e.pb, n, t);
|
|
1272
1272
|
}
|
|
1273
1273
|
|
|
1274
|
-
function changedBetween(e, n, t, r,
|
|
1274
|
+
function changedBetween(e, n, t, r, o) {
|
|
1275
1275
|
if (e.ch || t[$TARGET] !== undefined || Object.getPrototypeOf(t) !== Object.getPrototypeOf(n) || !plainProto(n)) return true;
|
|
1276
1276
|
if (e.del?.has(r)) return r in n;
|
|
1277
|
-
const
|
|
1278
|
-
if (
|
|
1279
|
-
if (!
|
|
1280
|
-
if ((
|
|
1277
|
+
const i = hasOwn.call(t, r) || e.ovl && hasOwn.call(e.v, r);
|
|
1278
|
+
if (i !== hasOwn.call(n, r)) return true;
|
|
1279
|
+
if (!i) return false;
|
|
1280
|
+
if ((o || e.a) && (isOwnAccessor(n, r) || isOwnAccessor(t, r) || propertyIsEnumerable.call(n, r) !== propertyIsEnumerable.call(t, r))) return true;
|
|
1281
1281
|
const l = t[r];
|
|
1282
1282
|
const u = n[r];
|
|
1283
1283
|
return !isEqual(u, l) && !sameLogicalSlot(e, u, l);
|
|
@@ -1287,12 +1287,12 @@ function changedBetween(e, n, t, r, i) {
|
|
|
1287
1287
|
* tracked or not, applies the hold and A28 rules a signal's read does. A
|
|
1288
1288
|
* projection's unheld staging is ahead for a handler (`familyAhead`). */ function nodeValue(e, n, t) {
|
|
1289
1289
|
let r = read(e);
|
|
1290
|
-
if (e.
|
|
1290
|
+
if (e.ie !== NOT_PENDING && !(e.l & CONFIG_HELD) && context === null && t.fam !== null) r = e.ie;
|
|
1291
1291
|
return r === FORCE ? n : r;
|
|
1292
1292
|
}
|
|
1293
1293
|
|
|
1294
1294
|
/** Serve a present data key: link the leaf for a tracked reader (creating it
|
|
1295
|
-
* on first read), wrap a wrappable child through the per-node wrap cache. */ function serveDataKey(e, n, t, r,
|
|
1295
|
+
* on first read), wrap a wrappable child through the per-node wrap cache. */ function serveDataKey(e, n, t, r, o, i = -1) {
|
|
1296
1296
|
// Read-through (§7b): the inner store's node is the truth; the outer's is
|
|
1297
1297
|
// a subscription point only — unless it carries a guess (an optimistic
|
|
1298
1298
|
// store over a store: the guess is the outer's, shown over the inner).
|
|
@@ -1301,14 +1301,14 @@ function changedBetween(e, n, t, r, i) {
|
|
|
1301
1301
|
// A write-override read (a derive's draft) serves the backing: the derive
|
|
1302
1302
|
// composes on the truth, never on a lane's or a hold's frame.
|
|
1303
1303
|
if (!inDraft(e) && !writeOverride) {
|
|
1304
|
-
if (
|
|
1305
|
-
if (
|
|
1306
|
-
const n = nodeValue(
|
|
1304
|
+
if (o === undefined && getObserver() !== null) o = getNode(e, n, i);
|
|
1305
|
+
if (o !== undefined) {
|
|
1306
|
+
const n = nodeValue(o, t, e);
|
|
1307
1307
|
if (l) {
|
|
1308
1308
|
// The link's committed value follows the inner store's (what a lane
|
|
1309
1309
|
// over it covers — its reveal and revert compare against it, S4).
|
|
1310
|
-
|
|
1311
|
-
if (
|
|
1310
|
+
o.le = t;
|
|
1311
|
+
if (o.l & CONFIG_OVERRIDE) u = n;
|
|
1312
1312
|
} else u = n;
|
|
1313
1313
|
}
|
|
1314
1314
|
}
|
|
@@ -1316,12 +1316,12 @@ function changedBetween(e, n, t, r, i) {
|
|
|
1316
1316
|
// A derive's draft wrapper answers `$TARGET` without being a proxy: the
|
|
1317
1317
|
// inner store's alias (#3767), resolved like a raw (#3859).
|
|
1318
1318
|
if (e.ch && !l && u !== null && typeof u === "object" && u[$TARGET]?.px !== u) u = resolveChainedRaw(e, n, u);
|
|
1319
|
-
if (
|
|
1320
|
-
if (
|
|
1319
|
+
if (o !== undefined) {
|
|
1320
|
+
if (o.pxv === u && u !== undefined) return draftServe(e, o.px);
|
|
1321
1321
|
if (!isWrappable(u)) return u;
|
|
1322
1322
|
const t = wrap(u, e, n);
|
|
1323
|
-
|
|
1324
|
-
|
|
1323
|
+
o.px = t;
|
|
1324
|
+
o.pxv = u;
|
|
1325
1325
|
return draftServe(e, t);
|
|
1326
1326
|
}
|
|
1327
1327
|
if (!isWrappable(u)) return u;
|
|
@@ -1380,7 +1380,7 @@ function changedBetween(e, n, t, r, i) {
|
|
|
1380
1380
|
* classification, as core reads it — `heldNotFinal`). */ function holdWithDerive(e, n) {
|
|
1381
1381
|
const t = e.fam?.node;
|
|
1382
1382
|
if (t !== undefined && t !== null && !userWrite && // the derive's own write (its draft or landing), not a user setter's
|
|
1383
|
-
t.l & CONFIG_HELD && n.
|
|
1383
|
+
t.l & CONFIG_HELD && n.ie !== NOT_PENDING &&
|
|
1384
1384
|
// A node carrying a guess is the lane's: its staging is the truth beneath
|
|
1385
1385
|
// the guess (`setSignal` → `laneWrite`), never re-homed by the store.
|
|
1386
1386
|
!(n.l & (CONFIG_HELD | CONFIG_OVERRIDE))) {
|
|
@@ -1398,8 +1398,8 @@ function changedBetween(e, n, t, r, i) {
|
|
|
1398
1398
|
const e = resolveChainedRaw(r, n, t);
|
|
1399
1399
|
return e === t ? t : wrap(e, r, n);
|
|
1400
1400
|
}
|
|
1401
|
-
const
|
|
1402
|
-
if (
|
|
1401
|
+
const o = lookupTarget(t, r.fam);
|
|
1402
|
+
if (o !== undefined) return o.px;
|
|
1403
1403
|
if ((r.v[n] === t || r.pb?.[n] === t) && isWrappable(t)) return wrap(t, r, n);
|
|
1404
1404
|
return t;
|
|
1405
1405
|
}
|
|
@@ -1412,10 +1412,10 @@ function changedBetween(e, n, t, r, i) {
|
|
|
1412
1412
|
// A container's arrangement guess is not a backing: the view composes
|
|
1413
1413
|
// over the base it is shown over.
|
|
1414
1414
|
const n = asBacking(read(getContainerNode(e)));
|
|
1415
|
-
return e.fam?.opt === true ? optHooks.view(e, n) : n;
|
|
1415
|
+
return optHooks && e.fam?.opt === true ? optHooks.view(e, n) : n;
|
|
1416
1416
|
}
|
|
1417
1417
|
const n = readSource(e);
|
|
1418
|
-
return optRead(e) ? optHooks.view(e, n) : n;
|
|
1418
|
+
return optHooks && optRead(e) ? optHooks.view(e, n) : n;
|
|
1419
1419
|
}
|
|
1420
1420
|
|
|
1421
1421
|
/** A read on an optimistic family that composes the lanes' values: not the
|
|
@@ -1493,18 +1493,18 @@ const traps = {
|
|
|
1493
1493
|
if (e.s) return serveShallow(e, n, r);
|
|
1494
1494
|
if (t.pxv === r) return t.px;
|
|
1495
1495
|
if (isWrappable(r)) {
|
|
1496
|
-
const
|
|
1497
|
-
t.px =
|
|
1496
|
+
const o = wrap(r, e, n);
|
|
1497
|
+
t.px = o;
|
|
1498
1498
|
t.pxv = r;
|
|
1499
|
-
return
|
|
1499
|
+
return o;
|
|
1500
1500
|
}
|
|
1501
1501
|
return r;
|
|
1502
1502
|
}
|
|
1503
1503
|
}
|
|
1504
|
-
const
|
|
1504
|
+
const o = readSource(e, n);
|
|
1505
1505
|
// Overlay delete (#3044): a prototype overlay cannot shadow a delete, so
|
|
1506
1506
|
// deleted keys are tracked aside and read as absent in the pending view.
|
|
1507
|
-
if (
|
|
1507
|
+
if (o === e.pb && e.del?.has(n)) {
|
|
1508
1508
|
if (!inDraft(e) && getObserver() !== null) read(getNode(e, n));
|
|
1509
1509
|
return undefined;
|
|
1510
1510
|
}
|
|
@@ -1515,16 +1515,16 @@ const traps = {
|
|
|
1515
1515
|
// node) probes once — untracked node-less reads take the plain path,
|
|
1516
1516
|
// where a raw-receiver getter still returns correct committed values.
|
|
1517
1517
|
// Tracking suppression is PER-TARGET (inDraft), never global (#3037).
|
|
1518
|
-
let
|
|
1518
|
+
let i = -1;
|
|
1519
1519
|
{
|
|
1520
1520
|
let l;
|
|
1521
1521
|
if (r !== undefined) l = r.acc === true; else if (!inDraft(e) && getObserver() !== null) {
|
|
1522
|
-
l = isOwnAccessor(
|
|
1523
|
-
if (
|
|
1522
|
+
l = isOwnAccessor(o, n);
|
|
1523
|
+
if (o === (e.pb ?? e.v)) i = l ? 1 : 0;
|
|
1524
1524
|
} else l = false;
|
|
1525
1525
|
if (l) {
|
|
1526
|
-
if (!inDraft(e) && getObserver() !== null) read(r ?? getNode(e, n,
|
|
1527
|
-
const l = Reflect.get(
|
|
1526
|
+
if (!inDraft(e) && getObserver() !== null) read(r ?? getNode(e, n, i));
|
|
1527
|
+
const l = Reflect.get(o, n, t);
|
|
1528
1528
|
if (e.s) return serveShallow(e, n, l);
|
|
1529
1529
|
return isWrappable(l) ? draftServe(e, wrap(l, e, n)) : l;
|
|
1530
1530
|
}
|
|
@@ -1535,21 +1535,21 @@ const traps = {
|
|
|
1535
1535
|
// chain to the committed backing, so "own in the view" means own on
|
|
1536
1536
|
// either layer — a genuine prototype method is one that is own on
|
|
1537
1537
|
// NEITHER.
|
|
1538
|
-
const l = e.ovl &&
|
|
1539
|
-
if ((n === "constructor" || n === "__proto__" || n === "prototype") && !hasOwn.call(
|
|
1540
|
-
let u =
|
|
1541
|
-
if (u === undefined ? !hasOwn.call(
|
|
1538
|
+
const l = e.ovl && o === e.pb;
|
|
1539
|
+
if ((n === "constructor" || n === "__proto__" || n === "prototype") && !hasOwn.call(o, n) && !(l && hasOwn.call(e.v, n))) return undefined;
|
|
1540
|
+
let u = o[n];
|
|
1541
|
+
if (u === undefined ? !hasOwn.call(o, n) && !(l && hasOwn.call(e.v, n)) : false) {
|
|
1542
1542
|
// Inherited: prototype getters/methods run with the proxy receiver.
|
|
1543
|
-
u = Reflect.get(
|
|
1543
|
+
u = Reflect.get(o, n, t);
|
|
1544
1544
|
if (typeof u === "function") return u;
|
|
1545
1545
|
// proto methods untracked
|
|
1546
1546
|
// Read-through (§7b): the inner store answers an absent key too — the
|
|
1547
1547
|
// outer's node is a subscription point unless it carries a guess.
|
|
1548
|
-
if (e.ch &&
|
|
1548
|
+
if (e.ch && o === e.v) return serveDataKey(e, n, u, o, r, i);
|
|
1549
1549
|
// Reading a currently-absent own key subscribes to it (R12) — for any
|
|
1550
1550
|
// target OUTSIDE its own draft scope, even mid-setter (#3037, above).
|
|
1551
1551
|
if (u === undefined && !inDraft(e)) {
|
|
1552
|
-
if (getObserver() !== null) read(getNode(e, n,
|
|
1552
|
+
if (getObserver() !== null) read(getNode(e, n, i));
|
|
1553
1553
|
const t = e.n?.[n];
|
|
1554
1554
|
if (t) {
|
|
1555
1555
|
const r = nodeValue(t, undefined, e);
|
|
@@ -1560,9 +1560,9 @@ const traps = {
|
|
|
1560
1560
|
if (e.s) return serveShallow(e, n, u);
|
|
1561
1561
|
return isWrappable(u) ? draftServe(e, wrap(u, e, n)) : u;
|
|
1562
1562
|
}
|
|
1563
|
-
if (typeof u === "function" && !hasOwn.call(
|
|
1563
|
+
if (typeof u === "function" && !hasOwn.call(o, n) && !(l && hasOwn.call(e.v, n))) return u;
|
|
1564
1564
|
// proto method
|
|
1565
|
-
return serveDataKey(e, n, u,
|
|
1565
|
+
return serveDataKey(e, n, u, o, r, i);
|
|
1566
1566
|
},
|
|
1567
1567
|
has(e, n) {
|
|
1568
1568
|
if (n === $TARGET || n === $PROXY || n === $TRACK) return true;
|
|
@@ -1579,14 +1579,14 @@ const traps = {
|
|
|
1579
1579
|
if (!inDraft(e) && !writeOverride) {
|
|
1580
1580
|
if (getObserver() !== null) {
|
|
1581
1581
|
const r = getHasNode(e, n);
|
|
1582
|
-
const
|
|
1583
|
-
if (!e.ch || t !== e.v) return !!
|
|
1584
|
-
const
|
|
1585
|
-
r.
|
|
1582
|
+
const o = read(r);
|
|
1583
|
+
if (!e.ch || t !== e.v) return !!o;
|
|
1584
|
+
const i = n in t;
|
|
1585
|
+
r.le = i;
|
|
1586
1586
|
// the link follows the inner store (S4)
|
|
1587
|
-
if (r.l & CONFIG_OVERRIDE) return !!
|
|
1588
|
-
return
|
|
1589
|
-
} else if (optRead(e)) {
|
|
1587
|
+
if (r.l & CONFIG_OVERRIDE) return !!o;
|
|
1588
|
+
return i;
|
|
1589
|
+
} else if (optHooks && optRead(e)) {
|
|
1590
1590
|
const t = optHooks.has(e, n);
|
|
1591
1591
|
if (t !== undefined) return t;
|
|
1592
1592
|
}
|
|
@@ -1607,9 +1607,9 @@ const traps = {
|
|
|
1607
1607
|
// node and reads its frame; a descriptor read on its own tracks
|
|
1608
1608
|
// presence (R13).
|
|
1609
1609
|
const r = t !== null && !inDraft(e) && !writeOverride;
|
|
1610
|
-
const
|
|
1611
|
-
let
|
|
1612
|
-
if (
|
|
1610
|
+
const o = r && observerHoldsContainer(e, t);
|
|
1611
|
+
let i;
|
|
1612
|
+
if (o) i = enumerationSource(e); else if (r) {
|
|
1613
1613
|
// The presence node's frame (core decides which) is the one described
|
|
1614
1614
|
// (a chained target's inner store answers through the backing, §7b);
|
|
1615
1615
|
// the descriptor itself comes from the backing the container's frame
|
|
@@ -1618,16 +1618,16 @@ const traps = {
|
|
|
1618
1618
|
// the staging for a member; #3706 contrast).
|
|
1619
1619
|
const t = getHasNode(e, n);
|
|
1620
1620
|
const r = read(t);
|
|
1621
|
-
|
|
1622
|
-
if (!r && (!e.ch || t.l & CONFIG_OVERRIDE || !(n in
|
|
1623
|
-
} else
|
|
1621
|
+
i = readSource(e, n, true);
|
|
1622
|
+
if (!r && (!e.ch || t.l & CONFIG_OVERRIDE || !(n in i))) return undefined;
|
|
1623
|
+
} else i = readSource(e, n, true);
|
|
1624
1624
|
let l;
|
|
1625
|
-
if (!
|
|
1625
|
+
if (optHooks && !o && optRead(e)) {
|
|
1626
1626
|
const t = optHooks.descriptor(e, n);
|
|
1627
1627
|
if (t === null) return undefined;
|
|
1628
1628
|
l = t;
|
|
1629
1629
|
}
|
|
1630
|
-
l ??= visibleDescriptor(e,
|
|
1630
|
+
l ??= visibleDescriptor(e, i, n);
|
|
1631
1631
|
if (l === undefined) return undefined;
|
|
1632
1632
|
if (!(n === "length" && Array.isArray(e))) l.configurable = true;
|
|
1633
1633
|
return l;
|
|
@@ -1639,8 +1639,8 @@ const traps = {
|
|
|
1639
1639
|
}
|
|
1640
1640
|
if (n === "__proto__") return true;
|
|
1641
1641
|
// pollution guard (core R30)
|
|
1642
|
-
const
|
|
1643
|
-
const
|
|
1642
|
+
const o = e.s ? t : unwrapValue(t);
|
|
1643
|
+
const i = ensurePB(e);
|
|
1644
1644
|
// #4146 (R1: node existence is unobservable; #3706: the hold's unit is
|
|
1645
1645
|
// the key): a user setter writing a key a HELD container's staging left
|
|
1646
1646
|
// unchanged would write it into the held staging — read as the hold's
|
|
@@ -1652,25 +1652,25 @@ const traps = {
|
|
|
1652
1652
|
// A34) — as it would with a reader's leaf. Kept while the container is
|
|
1653
1653
|
// held (`deferredReleases`).
|
|
1654
1654
|
if (userWrite && e.k?.l & CONFIG_HELD) deferredReleases.add(getNode(e, n));
|
|
1655
|
-
if (Array.isArray(
|
|
1655
|
+
if (Array.isArray(i)) {
|
|
1656
1656
|
touch(e, n);
|
|
1657
1657
|
if (n === "length") e.wk = WK_ALL; else touch(e, "length");
|
|
1658
1658
|
} else {
|
|
1659
1659
|
touch(e, n);
|
|
1660
|
-
if (!(n in
|
|
1660
|
+
if (!(n in i)) e.kc++;
|
|
1661
1661
|
}
|
|
1662
1662
|
const l = UNSAFE_KEYS.has(n);
|
|
1663
|
-
if (l || e.ovl && e.sc !== 2 && !hasOwn.call(
|
|
1664
|
-
Object.defineProperty(
|
|
1665
|
-
value:
|
|
1663
|
+
if (l || e.ovl && e.sc !== 2 && !hasOwn.call(i, n)) {
|
|
1664
|
+
Object.defineProperty(i, n, {
|
|
1665
|
+
value: o,
|
|
1666
1666
|
writable: true,
|
|
1667
1667
|
enumerable: true,
|
|
1668
1668
|
configurable: true
|
|
1669
1669
|
});
|
|
1670
|
-
} else
|
|
1670
|
+
} else i[n] = o;
|
|
1671
1671
|
e.del?.delete(n);
|
|
1672
1672
|
if (l) return true;
|
|
1673
|
-
if (e.s &&
|
|
1673
|
+
if (e.s && o !== null && typeof o === "object") markRawOne(o);
|
|
1674
1674
|
if (!r) notifyWrites(e);
|
|
1675
1675
|
// a write-override write
|
|
1676
1676
|
return true;
|
|
@@ -1686,10 +1686,10 @@ const traps = {
|
|
|
1686
1686
|
...t,
|
|
1687
1687
|
value: unwrapValue(t.value)
|
|
1688
1688
|
};
|
|
1689
|
-
const
|
|
1689
|
+
const o = ensurePB(e);
|
|
1690
1690
|
if (e.a || !(t.enumerable && t.writable && t.configurable)) e.sc = 1;
|
|
1691
1691
|
touch(e, n);
|
|
1692
|
-
Object.defineProperty(
|
|
1692
|
+
Object.defineProperty(o, n, t);
|
|
1693
1693
|
e.del?.delete(n);
|
|
1694
1694
|
if (!r) notifyWrites(e);
|
|
1695
1695
|
// a write-override write
|
|
@@ -1711,12 +1711,12 @@ const traps = {
|
|
|
1711
1711
|
// one" shape drifted the count up by one per write until a three-key
|
|
1712
1712
|
// object crossed the overlay threshold and paid a rebuild on every
|
|
1713
1713
|
// commit after.
|
|
1714
|
-
const
|
|
1714
|
+
const o = e.ovl && hasOwn.call(e.v, n);
|
|
1715
1715
|
if (hasOwn.call(r, n)) {
|
|
1716
1716
|
delete r[n];
|
|
1717
|
-
|
|
1717
|
+
o || e.kc--;
|
|
1718
1718
|
}
|
|
1719
|
-
if (
|
|
1719
|
+
if (o) (e.del ??= new Set).add(n);
|
|
1720
1720
|
if (!t) notifyWrites(e);
|
|
1721
1721
|
// a write-override write
|
|
1722
1722
|
return true;
|
|
@@ -1729,16 +1729,16 @@ const traps = {
|
|
|
1729
1729
|
const t = e.k;
|
|
1730
1730
|
if (t === null) return false;
|
|
1731
1731
|
const r = t.ve;
|
|
1732
|
-
return r !== null && r.u === n && (!(n.R & REACTIVE_RECOMPUTING_DEPS) || r.
|
|
1732
|
+
return r !== null && r.u === n && (!(n.R & REACTIVE_RECOMPUTING_DEPS) || r.de === n.Ne);
|
|
1733
1733
|
}
|
|
1734
1734
|
|
|
1735
1735
|
function storeSetter(e, n, t = true) {
|
|
1736
1736
|
if (writeHook !== null) writeHook(e);
|
|
1737
1737
|
const r = e[$TARGET];
|
|
1738
|
-
const
|
|
1738
|
+
const o = writeScopes;
|
|
1739
1739
|
writeScopes = new Set;
|
|
1740
1740
|
writeScopes.add(scopeKey(r));
|
|
1741
|
-
const
|
|
1741
|
+
const i = userWrite;
|
|
1742
1742
|
userWrite = t;
|
|
1743
1743
|
writing++;
|
|
1744
1744
|
let l;
|
|
@@ -1750,7 +1750,7 @@ function storeSetter(e, n, t = true) {
|
|
|
1750
1750
|
l = n(e);
|
|
1751
1751
|
} finally {
|
|
1752
1752
|
writing--;
|
|
1753
|
-
writeScopes =
|
|
1753
|
+
writeScopes = o;
|
|
1754
1754
|
// Outermost setter exit: emit write-time notifications (one node write
|
|
1755
1755
|
// per changed observed key) so holds and lanes engage now.
|
|
1756
1756
|
if (writing === 0 && pendingNotify.size) {
|
|
@@ -1761,13 +1761,13 @@ function storeSetter(e, n, t = true) {
|
|
|
1761
1761
|
// exit, unqueued: the backing is the pre-batch one (nothing swapped).
|
|
1762
1762
|
if (directCommit) for (const n of e) if (n.pb !== null) foldTarget(n, n.v);
|
|
1763
1763
|
}
|
|
1764
|
-
userWrite =
|
|
1764
|
+
userWrite = i;
|
|
1765
1765
|
}
|
|
1766
1766
|
if (l !== undefined && l !== e && isWrappable(l)) {
|
|
1767
1767
|
// A returned replacement: on an optimistic family a user's is itself an
|
|
1768
1768
|
// optimistic edit — diffed against the view as guesses (`next` parity);
|
|
1769
1769
|
// otherwise it is adopted as the incoming truth.
|
|
1770
|
-
if (t && r.fam?.opt === true && !writeOverride) optHooks.writes(r, unwrapValue(l)); else adoptPB(r, unwrapValue(l));
|
|
1770
|
+
if (optHooks && t && r.fam?.opt === true && !writeOverride) optHooks.writes(r, unwrapValue(l)); else adoptPB(r, unwrapValue(l));
|
|
1771
1771
|
}
|
|
1772
1772
|
// A34 (3), #3612 — the derived store's twin of `setMemo`: a user write to
|
|
1773
1773
|
// a derivation another transaction holds is nobody's proposal; it becomes
|
|
@@ -1882,13 +1882,13 @@ function visibleDescriptor(e, n, t) {
|
|
|
1882
1882
|
continue;
|
|
1883
1883
|
// accessors track through their own reads when invoked
|
|
1884
1884
|
}
|
|
1885
|
-
let
|
|
1886
|
-
if (
|
|
1887
|
-
if (e.ch &&
|
|
1888
|
-
const
|
|
1889
|
-
if (
|
|
1885
|
+
let o = r.value;
|
|
1886
|
+
if (o === null || typeof o !== "object") continue;
|
|
1887
|
+
if (e.ch && o[$TARGET] === undefined) o = resolveChainedRaw(e, t, o);
|
|
1888
|
+
const i = childTarget(e, o, t);
|
|
1889
|
+
if (i === undefined) continue;
|
|
1890
1890
|
// raw-marked: leaf by contract
|
|
1891
|
-
walkT(
|
|
1891
|
+
walkT(i);
|
|
1892
1892
|
}
|
|
1893
1893
|
};
|
|
1894
1894
|
walkT(n);
|
|
@@ -1907,68 +1907,68 @@ function snapshotWalk(e, n, t) {
|
|
|
1907
1907
|
let r = e;
|
|
1908
1908
|
for (let e = true; ;e = false) {
|
|
1909
1909
|
const n = r?.[$TARGET]?.v !== undefined;
|
|
1910
|
-
let
|
|
1911
|
-
if (
|
|
1912
|
-
if (
|
|
1913
|
-
if (
|
|
1914
|
-
if (e && !n && t !== null &&
|
|
1915
|
-
const e = t.map.get(
|
|
1916
|
-
if (e !== undefined)
|
|
1910
|
+
let o = n ? r[$TARGET] : undefined;
|
|
1911
|
+
if (o === undefined && t !== null) o = lookupTarget(r, t);
|
|
1912
|
+
if (o === undefined) o = lookupTarget(r, null);
|
|
1913
|
+
if (o === undefined) break;
|
|
1914
|
+
if (e && !n && t !== null && o.fam !== t) {
|
|
1915
|
+
const e = t.map.get(o.px);
|
|
1916
|
+
if (e !== undefined) o = e;
|
|
1917
1917
|
}
|
|
1918
|
-
if (
|
|
1918
|
+
if (o.fam !== null) t = o.fam;
|
|
1919
1919
|
// R27: a snapshot sees the batch's pending backing — a held one (another
|
|
1920
1920
|
// transaction's future) only from its own draft.
|
|
1921
|
-
let
|
|
1922
|
-
if (
|
|
1923
|
-
if (
|
|
1924
|
-
|
|
1921
|
+
let i = o.v;
|
|
1922
|
+
if (o.pb !== null && (inDraft(o) || writeOverride || o.k === null || !(o.k.l & CONFIG_HELD))) {
|
|
1923
|
+
if (o.ovl) materializePB(o);
|
|
1924
|
+
i = o.pb;
|
|
1925
1925
|
}
|
|
1926
|
-
if (optRead(
|
|
1927
|
-
if (
|
|
1928
|
-
r =
|
|
1926
|
+
if (optHooks && optRead(o)) i = optHooks.view(o, i);
|
|
1927
|
+
if (i === r) break;
|
|
1928
|
+
r = i;
|
|
1929
1929
|
}
|
|
1930
1930
|
if (!isWrappable(r)) return r;
|
|
1931
|
-
const
|
|
1932
|
-
if (
|
|
1931
|
+
const o = n.get(r);
|
|
1932
|
+
if (o !== undefined) return o;
|
|
1933
1933
|
if (isOwned(r)) {
|
|
1934
1934
|
const e = Array.isArray(r);
|
|
1935
|
-
const
|
|
1936
|
-
n.set(r,
|
|
1937
|
-
for (const
|
|
1938
|
-
if (e &&
|
|
1939
|
-
const l = Object.getOwnPropertyDescriptor(r,
|
|
1940
|
-
if (typeof
|
|
1935
|
+
const o = e ? [] : Object.create(Object.getPrototypeOf(r));
|
|
1936
|
+
n.set(r, o);
|
|
1937
|
+
for (const i of Reflect.ownKeys(r)) {
|
|
1938
|
+
if (e && i === "length" || i === $OWNER) continue;
|
|
1939
|
+
const l = Object.getOwnPropertyDescriptor(r, i);
|
|
1940
|
+
if (typeof i === "symbol" && !l.enumerable) continue;
|
|
1941
1941
|
if (l.get || l.set) {
|
|
1942
|
-
Object.defineProperty(
|
|
1942
|
+
Object.defineProperty(o, i, l);
|
|
1943
1943
|
continue;
|
|
1944
1944
|
}
|
|
1945
1945
|
const u = l.value;
|
|
1946
1946
|
const f = u !== null && typeof u === "object" ? snapshotWalk(u, n, t) : u;
|
|
1947
|
-
if (l.enumerable && l.writable && l.configurable) i
|
|
1947
|
+
if (l.enumerable && l.writable && l.configurable) o[i] = f; else Object.defineProperty(o, i, {
|
|
1948
1948
|
...l,
|
|
1949
1949
|
value: f
|
|
1950
1950
|
});
|
|
1951
1951
|
}
|
|
1952
|
-
if (e &&
|
|
1953
|
-
return
|
|
1952
|
+
if (e && o.length !== r.length) o.length = r.length;
|
|
1953
|
+
return o;
|
|
1954
1954
|
}
|
|
1955
1955
|
n.set(r, r);
|
|
1956
|
-
let
|
|
1956
|
+
let i = null;
|
|
1957
1957
|
for (const e of Reflect.ownKeys(r)) {
|
|
1958
|
-
const
|
|
1959
|
-
if (!
|
|
1960
|
-
const l =
|
|
1958
|
+
const o = Object.getOwnPropertyDescriptor(r, e);
|
|
1959
|
+
if (!o || o.get || o.set) continue;
|
|
1960
|
+
const l = o.value;
|
|
1961
1961
|
if (l === null || typeof l !== "object") continue;
|
|
1962
1962
|
const u = snapshotWalk(l, n, t);
|
|
1963
1963
|
if (u !== l) {
|
|
1964
|
-
if (
|
|
1965
|
-
|
|
1966
|
-
n.set(r,
|
|
1964
|
+
if (i === null) {
|
|
1965
|
+
i = Array.isArray(r) ? [ ...r ] : Object.create(Object.getPrototypeOf(r), Object.getOwnPropertyDescriptors(r));
|
|
1966
|
+
n.set(r, i);
|
|
1967
1967
|
}
|
|
1968
|
-
|
|
1968
|
+
i[e] = u;
|
|
1969
1969
|
}
|
|
1970
1970
|
}
|
|
1971
|
-
return
|
|
1971
|
+
return i ?? r;
|
|
1972
1972
|
}
|
|
1973
1973
|
|
|
1974
1974
|
export { $PROXY, $TARGET, $TRACK, LaneView, adoptPB, arrayStructureChanged, asBacking, bumpDeep, cloneRaw, committed, containerEquals, createStore, deep, getContainerNode, getHasNode, getNode, hasAccessorFlag, materializePB, membershipChanged, notifyFold, notifyFoldTail, notifyKeyDiff, notifyKeyValue, resolveChainedRaw, runDirect, sameKey, sameRow, snapshot, storeHasFamily, storeHasOptimisticFamily, storeIsShallow, storeSetter, targetsEqual, unwrapValue, userWriting, wrap };
|