@solidjs/signals 2.0.0-rc.17 → 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 +426 -241
- package/dist/dev.attribution.js +19 -16
- package/dist/dev.js +768 -409
- package/dist/observe/boundaries.js +88 -67
- package/dist/observe/core/action.js +8 -0
- package/dist/observe/core/async.js +183 -138
- package/dist/observe/core/attribution.js +30 -28
- package/dist/observe/core/constants.js +23 -1
- package/dist/observe/core/core.js +185 -157
- package/dist/observe/core/effect.js +34 -37
- package/dist/observe/core/graph.js +8 -8
- package/dist/observe/core/heap.js +5 -5
- package/dist/observe/core/lanes.js +104 -84
- package/dist/observe/core/owner.js +17 -16
- package/dist/observe/core/scheduler.js +61 -47
- package/dist/observe/core/truth.js +6 -6
- package/dist/observe/core/verdict.js +15 -15
- package/dist/observe/deferred.js +40 -38
- package/dist/observe/from.js +248 -0
- package/dist/observe/index.js +4 -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 +138 -122
- package/dist/observe/store/store.js +628 -641
- package/dist/observe/store/target.js +1 -5
- 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 +242 -197
- package/dist/prod/core/constants.js +16 -1
- package/dist/prod/core/core.js +166 -138
- package/dist/prod/core/effect.js +31 -34
- package/dist/prod/core/graph.js +5 -5
- 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 +64 -50
- package/dist/prod/core/truth.js +6 -6
- package/dist/prod/core/verdict.js +17 -17
- package/dist/prod/deferred.js +40 -38
- package/dist/prod/from.js +248 -0
- package/dist/prod/index.js +4 -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 +138 -122
- package/dist/prod/store/store.js +308 -331
- package/dist/prod/store/target.js +13 -17
- package/dist/prod/store/utils.js +2 -0
- package/dist/types/core/action.d.ts +8 -0
- package/dist/types/core/async.d.ts +12 -2
- package/dist/types/core/constants.d.ts +25 -0
- package/dist/types/core/core.d.ts +33 -4
- 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 +17 -3
- package/dist/types/from.d.ts +47 -0
- package/dist/types/index.d.ts +4 -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
|
@@ -12,7 +12,7 @@ import { insertIntoHeap } from "../core/heap.js";
|
|
|
12
12
|
|
|
13
13
|
import { txOf, flushTransaction, holdNode, joinFuture, insertSubs, schedule, passLane, globalQueue, queuePendingNode, resolveTx, GlobalQueue, installStoreHooks, joinPassTx, dirtyQueue } from "../core/scheduler.js";
|
|
14
14
|
|
|
15
|
-
import { lookupTarget, setLookup, $OWNER, isOwned, markDescendants
|
|
15
|
+
import { lookupTarget, setLookup, $OWNER, isOwned, markDescendants } from "./target.js";
|
|
16
16
|
|
|
17
17
|
import { optHooks, affectsHooks } from "./hooks.js";
|
|
18
18
|
|
|
@@ -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;
|
|
@@ -206,7 +206,7 @@ function sameKey(e, n) {
|
|
|
206
206
|
/** The container node's comparator: a staging is a backing (identity — a
|
|
207
207
|
* pending backing is never "equal" to the committed one); a lane value is
|
|
208
208
|
* an arrangement (`LaneView`), judged by the optimistic machinery. */ const containerEquals = function(e, n) {
|
|
209
|
-
return e === n || optHooks
|
|
209
|
+
return e === n || !!optHooks?.arrangement(this.O, e, n);
|
|
210
210
|
};
|
|
211
211
|
|
|
212
212
|
function sameLogicalSlot(e, n, t) {
|
|
@@ -225,10 +225,10 @@ function releaseSlot(e) {
|
|
|
225
225
|
if (n.k === e) n.k = null;
|
|
226
226
|
} else if (t === $DEEP) {
|
|
227
227
|
if (n.dk === e) n.dk = null;
|
|
228
|
-
} else if (n.n
|
|
228
|
+
} else if (n.n?.[t] === e) {
|
|
229
229
|
delete n.n[t];
|
|
230
230
|
n.nc--;
|
|
231
|
-
} else if (n.h
|
|
231
|
+
} else if (n.h?.[t] === e) delete n.h[t];
|
|
232
232
|
// The family's index keeps only targets that still carry a node.
|
|
233
233
|
if (n.fam !== null && n.nc === 0 && n.k === null && n.dk === null && (n.h === null || Reflect.ownKeys(n.h).length === 0)) n.fam.live.delete(n);
|
|
234
234
|
}
|
|
@@ -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 (
|
|
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;
|
|
@@ -479,29 +479,22 @@ const plainProto = e => {
|
|
|
479
479
|
/** An overlay with many adds (or any delete) rebuilds the committed
|
|
480
480
|
* container at flatten so its shape stays fast (#3689). */ function overlayRebuilds(e, n) {
|
|
481
481
|
if (e.kc > OVERLAY_REBUILD_MAX_KEYS) return false;
|
|
482
|
-
if (e.del
|
|
482
|
+
if (e.del?.size) return true;
|
|
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
|
|
|
491
491
|
/** Downgrade an overlay to a real clone (a consumer needs a container). */ function materializePB(e) {
|
|
492
492
|
const n = e.pb;
|
|
493
493
|
if (!e.ovl) return n;
|
|
494
|
-
const t = e.sc === 2 ? wideClone(e.v, e) : cloneRaw(e.v, e);
|
|
495
|
-
if (e.del !== null) {
|
|
496
|
-
for (const n of e.del) delete t[n];
|
|
497
|
-
e.kc -= e.del.size;
|
|
498
|
-
e.del = null;
|
|
499
|
-
}
|
|
500
|
-
for (const r of Reflect.ownKeys(n)) e.sc === 2 ? t[r] = n[r] : copyOwn(t, n, r);
|
|
494
|
+
const t = overlayOnto(e, e.sc === 2 ? wideClone(e.v, e) : cloneRaw(e.v, e), n);
|
|
501
495
|
e.pb = t;
|
|
502
|
-
e.ovl = false;
|
|
503
496
|
// The staging IS the pending backing: re-point the container node.
|
|
504
|
-
if (e.k
|
|
497
|
+
if (e.k?.ie === n) e.k.ie = t;
|
|
505
498
|
return t;
|
|
506
499
|
}
|
|
507
500
|
|
|
@@ -513,7 +506,7 @@ const plainProto = e => {
|
|
|
513
506
|
// An optimistic edit composes on the view the user saw and becomes
|
|
514
507
|
// guesses at the setter's exit: nothing is staged, nothing folds
|
|
515
508
|
// (optimistic.ts).
|
|
516
|
-
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);
|
|
517
510
|
if (n !== null && !isOwned(n)) {
|
|
518
511
|
// An adopted object awaiting its fold is the user's: the draft writes a
|
|
519
512
|
// clone of it. The clone is the batch's staging — unless the adoption is
|
|
@@ -522,7 +515,7 @@ const plainProto = e => {
|
|
|
522
515
|
// mainline setter mid-hold publishes mainline; the held keys stay held).
|
|
523
516
|
n = e.pb = cloneRaw(n, e);
|
|
524
517
|
const t = e.k;
|
|
525
|
-
if (t !== null && !(t.l & CONFIG_HELD)) t.
|
|
518
|
+
if (t !== null && !(t.l & CONFIG_HELD)) t.ie = n;
|
|
526
519
|
} else if (n === null) {
|
|
527
520
|
const t = e.v;
|
|
528
521
|
if (!directCommit) queueFold(e);
|
|
@@ -546,7 +539,6 @@ const plainProto = e => {
|
|
|
546
539
|
e.ch = false;
|
|
547
540
|
if (e.u) {
|
|
548
541
|
privatizeCommitted(e.u);
|
|
549
|
-
devAssertNeverUserMutation(e.u.v);
|
|
550
542
|
const t = e.u.v;
|
|
551
543
|
const r = parentSlotKey(e, n);
|
|
552
544
|
if (t[r] === n) t[r] = e.v;
|
|
@@ -561,26 +553,29 @@ const plainProto = e => {
|
|
|
561
553
|
const t = e.pk;
|
|
562
554
|
const r = e.u.v;
|
|
563
555
|
if (r[t] === n || r[t] === e.v || !Array.isArray(r)) return t;
|
|
564
|
-
const
|
|
565
|
-
if (
|
|
566
|
-
e.pk =
|
|
567
|
-
return
|
|
556
|
+
const o = r.indexOf(n);
|
|
557
|
+
if (o === -1) return t;
|
|
558
|
+
e.pk = o;
|
|
559
|
+
return o;
|
|
568
560
|
}
|
|
569
561
|
|
|
570
562
|
/** Overlay flatten (#3044): own keys onto the owned committed backing in
|
|
571
563
|
* place — the backing keeps its identity. */ function flattenOverlay(e, n) {
|
|
572
564
|
privatizeCommitted(e);
|
|
573
|
-
|
|
574
|
-
|
|
565
|
+
overlayOnto(e, e.v, n);
|
|
566
|
+
// the caller (`foldTarget`) closes the staging
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
/** An overlay's own keys and deletions onto `to` (the two are disjoint: a
|
|
570
|
+
* write un-deletes its key); the overlay is closed. */ function overlayOnto(e, n, t) {
|
|
571
|
+
for (const r of Reflect.ownKeys(t)) e.sc === 2 ? n[r] = t[r] : copyOwn(n, t, r);
|
|
575
572
|
if (e.del !== null) {
|
|
576
|
-
for (const
|
|
573
|
+
for (const t of e.del) delete n[t];
|
|
577
574
|
e.kc -= e.del.size;
|
|
578
575
|
e.del = null;
|
|
579
576
|
}
|
|
580
|
-
e.pb = null;
|
|
581
577
|
e.ovl = false;
|
|
582
|
-
|
|
583
|
-
// written-keys window closes with the commit
|
|
578
|
+
return n;
|
|
584
579
|
}
|
|
585
580
|
|
|
586
581
|
/** Adoption (a setter's returned replacement; reconcile and projection
|
|
@@ -601,7 +596,7 @@ const plainProto = e => {
|
|
|
601
596
|
} else r = e.v;
|
|
602
597
|
if (directCommit) {
|
|
603
598
|
e.pb = null;
|
|
604
|
-
if (e.k !== null) e.k.
|
|
599
|
+
if (e.k !== null) e.k.le = n;
|
|
605
600
|
} else {
|
|
606
601
|
// Eager (INTERNALS §3): the backing swaps now — handlers read the
|
|
607
602
|
// adopted object before the flush — while the container node, when
|
|
@@ -619,8 +614,8 @@ const plainProto = e => {
|
|
|
619
614
|
e.a = false;
|
|
620
615
|
e.wk = null;
|
|
621
616
|
// adoption supersedes staged trap writes
|
|
622
|
-
const
|
|
623
|
-
if (
|
|
617
|
+
const o = n[$OWNER];
|
|
618
|
+
if (o?.fam === e.fam) n[$OWNER] = e; else setLookup(n, e);
|
|
624
619
|
if (t && r !== n) notifyFold(e, r, n);
|
|
625
620
|
}
|
|
626
621
|
|
|
@@ -696,8 +691,8 @@ let foldIndex = null;
|
|
|
696
691
|
const r = e[t];
|
|
697
692
|
if (r.pb === null) continue;
|
|
698
693
|
// folded already (a direct commit)
|
|
699
|
-
const
|
|
700
|
-
if (
|
|
694
|
+
const o = r.k;
|
|
695
|
+
if (o !== null && o.ie !== NOT_PENDING) {
|
|
701
696
|
// held: commits with its hold
|
|
702
697
|
foldList.push(r);
|
|
703
698
|
foldOlds.push(n[t]);
|
|
@@ -721,7 +716,7 @@ let foldIndex = null;
|
|
|
721
716
|
* marks (an ambient `affects()` over a declared reload lives to the
|
|
722
717
|
* landing) read it. */ GlobalQueue.k = e => {
|
|
723
718
|
const n = e.O?.fam;
|
|
724
|
-
return
|
|
719
|
+
return (n?.node?.m & STATUS_PENDING) !== 0;
|
|
725
720
|
};
|
|
726
721
|
|
|
727
722
|
/** Core asks (lanes.ts `covered`): the value a slot node's guess covered.
|
|
@@ -732,9 +727,9 @@ let foldIndex = null;
|
|
|
732
727
|
if (n.ch) {
|
|
733
728
|
const t = e.ze;
|
|
734
729
|
const r = n.v;
|
|
735
|
-
if (n.h
|
|
730
|
+
if (n.h?.[t] === e) e.le = untrack(() => t in r); else if (n.n?.[t] === e) e.le = untrack(() => unwrapValue(r[t]));
|
|
736
731
|
}
|
|
737
|
-
return e.
|
|
732
|
+
return e.le;
|
|
738
733
|
};
|
|
739
734
|
|
|
740
735
|
installStoreHooks(storePark, () => {
|
|
@@ -768,12 +763,7 @@ function runDirect(e) {
|
|
|
768
763
|
const t = e.k;
|
|
769
764
|
const r = e.pb;
|
|
770
765
|
if (r !== null) {
|
|
771
|
-
if (r === e.v) {
|
|
772
|
-
// An eager adoption nothing wrote after: the backing is already
|
|
773
|
-
// the adopted object (shared ownership — never cloned).
|
|
774
|
-
e.pb = null;
|
|
775
|
-
e.wk = null;
|
|
776
|
-
} else if (e.ovl && (e.v !== n || !overlayRebuilds(e, r) && t?.T?.Pe !== n)) {
|
|
766
|
+
if (r === e.v) ; else if (e.ovl && (e.v !== n || !overlayRebuilds(e, r) && t?.T?.De !== n)) {
|
|
777
767
|
// Overlay flatten (#3044): the backing keeps its identity, so the
|
|
778
768
|
// `t.v === old` gate below skips path copying (the parent slot
|
|
779
769
|
// already points here) and the adopted-notify (setter
|
|
@@ -785,43 +775,38 @@ function runDirect(e) {
|
|
|
785
775
|
// owned backing takes the written keys.
|
|
786
776
|
privatizeCommitted(e);
|
|
787
777
|
const t = e.v;
|
|
788
|
-
const
|
|
789
|
-
if (
|
|
790
|
-
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) {
|
|
791
781
|
if (hasOwn.call(r, n)) copyOwn(t, r, n); else delete t[n];
|
|
792
782
|
}
|
|
793
783
|
} else {
|
|
794
|
-
for (const e of Reflect.ownKeys(r))
|
|
795
|
-
const i = Object.getOwnPropertyDescriptor(r, e);
|
|
796
|
-
if (i.get || i.set || !i.enumerable || !i.writable || !i.configurable) Object.defineProperty(t, e, i); else if (i.value !== n[e] || !hasOwn.call(n, e)) t[e] = i.value;
|
|
797
|
-
}
|
|
784
|
+
for (const e of Reflect.ownKeys(r)) if (e !== $OWNER) copyOwn(t, r, e);
|
|
798
785
|
for (const e of Reflect.ownKeys(n)) {
|
|
799
|
-
if (!hasOwn.call(r, e)) delete t[e];
|
|
786
|
+
if (e !== $OWNER && !hasOwn.call(r, e)) delete t[e];
|
|
800
787
|
}
|
|
801
788
|
}
|
|
802
|
-
e.pb = null;
|
|
803
|
-
e.wk = null;
|
|
804
789
|
} else {
|
|
805
790
|
// The clone (or adopted object) becomes the committed backing
|
|
806
791
|
// (path copy below).
|
|
807
792
|
e.v = e.ovl ? materializePB(e) : r;
|
|
808
793
|
e.ch = e.v[$TARGET] !== undefined;
|
|
809
|
-
e.pb = null;
|
|
810
|
-
e.wk = null;
|
|
811
794
|
}
|
|
812
|
-
|
|
795
|
+
e.pb = null;
|
|
796
|
+
e.wk = null;
|
|
797
|
+
// the written-keys window closes with the commit
|
|
798
|
+
}
|
|
813
799
|
if (t !== null) {
|
|
814
800
|
// The node's committed value is the backing. A container nobody
|
|
815
801
|
// subscribes to was a transient staging home (INTERNALS §5: an
|
|
816
802
|
// observer-less write holds a transient record until the fold,
|
|
817
803
|
// discarded with it) — gone with the batch.
|
|
818
|
-
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;
|
|
819
805
|
}
|
|
820
806
|
if (e.v !== n && e.u) {
|
|
821
807
|
const t = parentSlotKey(e, n);
|
|
822
808
|
if (e.u.v[t] === n) {
|
|
823
809
|
privatizeCommitted(e.u);
|
|
824
|
-
devAssertNeverUserMutation(e.u.v);
|
|
825
810
|
e.u.v[t] = e.v;
|
|
826
811
|
}
|
|
827
812
|
}
|
|
@@ -855,7 +840,7 @@ function heldDerivation(e, n, t) {
|
|
|
855
840
|
// Optimistic channel: a user's writes on an optimistic family become
|
|
856
841
|
// guesses on the nodes (lanes); the draft is discarded, the committed
|
|
857
842
|
// backing never touched.
|
|
858
|
-
if (userWrite && e.fam?.opt === true) {
|
|
843
|
+
if (optHooks && userWrite && e.fam?.opt === true) {
|
|
859
844
|
// The draft is discarded first: the diff reads the target (its nodes
|
|
860
845
|
// are born from the committed frame, not the draft).
|
|
861
846
|
e.pb = null;
|
|
@@ -878,63 +863,63 @@ function heldDerivation(e, n, t) {
|
|
|
878
863
|
// only (D-8, #3743): a key an earlier setter of the batch wrote and this
|
|
879
864
|
// one did not is no second proposal — its node was told then, and telling
|
|
880
865
|
// a held node its unchanged value again would join this tick to the hold.
|
|
881
|
-
const
|
|
882
|
-
const
|
|
883
|
-
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)) {
|
|
884
869
|
heldDerivationHit = true;
|
|
885
870
|
break;
|
|
886
871
|
}
|
|
887
872
|
if (r !== null) {
|
|
888
|
-
const
|
|
889
|
-
for (const
|
|
890
|
-
const
|
|
891
|
-
if (
|
|
892
|
-
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) {
|
|
893
878
|
// Accessor keys: the node is linked for shape-change notification,
|
|
894
879
|
// its value is never served (the getter runs with the proxy
|
|
895
880
|
// receiver on read) — FORCE wakes the readers. A data descriptor
|
|
896
881
|
// falls through so the cleared-acc hot read serves it (#3949);
|
|
897
882
|
// an own getter's descriptor has no `value`, so the compare below
|
|
898
883
|
// would otherwise keep the getter's result (or FORCE) for `undefined`.
|
|
899
|
-
|
|
900
|
-
const e = Object.getOwnPropertyDescriptor(t,
|
|
901
|
-
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);
|
|
902
887
|
if (!r || r.get || r.set) {
|
|
903
|
-
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);
|
|
904
889
|
continue;
|
|
905
890
|
}
|
|
906
|
-
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);
|
|
907
892
|
continue;
|
|
908
893
|
}
|
|
909
|
-
const l = e.del
|
|
910
|
-
setSignal(
|
|
894
|
+
const l = e.del?.has(i) ? undefined : n[i];
|
|
895
|
+
setSignal(o, () => l);
|
|
911
896
|
if (e.fam !== null) {
|
|
912
897
|
// The derive's write is a derivation; a user setter's is a proposal
|
|
913
898
|
// (A34 (3)'s discriminator).
|
|
914
899
|
if (!userWrite) {
|
|
915
|
-
|
|
916
|
-
holdWithDerive(e,
|
|
917
|
-
} else
|
|
900
|
+
o.l &= ~CONFIG_MANUAL_WRITE;
|
|
901
|
+
holdWithDerive(e, o);
|
|
902
|
+
} else o.l |= CONFIG_MANUAL_WRITE;
|
|
918
903
|
}
|
|
919
904
|
}
|
|
920
905
|
}
|
|
921
906
|
const l = e.h;
|
|
922
907
|
if (l !== null) {
|
|
923
|
-
const t =
|
|
908
|
+
const t = i ?? Reflect.ownKeys(l);
|
|
924
909
|
for (const r of t) {
|
|
925
910
|
const t = l[r];
|
|
926
911
|
if (t !== undefined) {
|
|
927
|
-
setSignal(t, r in n && !
|
|
912
|
+
setSignal(t, r in n && !e.del?.has(r));
|
|
928
913
|
if (e.fam !== null) holdWithDerive(e, t);
|
|
929
914
|
}
|
|
930
915
|
}
|
|
931
916
|
}
|
|
932
917
|
if (e.dk !== null) {
|
|
933
|
-
if (e.del
|
|
918
|
+
if (e.del?.size) bumpDeep(e); else for (const r of i ?? Reflect.ownKeys(n)) {
|
|
934
919
|
if (r === $OWNER) continue;
|
|
935
|
-
const
|
|
936
|
-
const
|
|
937
|
-
if (
|
|
920
|
+
const o = n[r];
|
|
921
|
+
const i = t[r];
|
|
922
|
+
if (o !== null && typeof o === "object" ? !targetsEqual(i, o) : !isEqual(i, o)) {
|
|
938
923
|
bumpDeep(e);
|
|
939
924
|
break;
|
|
940
925
|
}
|
|
@@ -948,7 +933,7 @@ function heldDerivation(e, n, t) {
|
|
|
948
933
|
if (u !== null && (u.o !== null || u.l & CONFIG_OVERRIDE)) {
|
|
949
934
|
let r;
|
|
950
935
|
if (e.ovl) {
|
|
951
|
-
r = e.del
|
|
936
|
+
r = !!e.del?.size;
|
|
952
937
|
if (!r) {
|
|
953
938
|
for (const e of Reflect.ownKeys(n)) {
|
|
954
939
|
if (!hasOwn.call(t, e)) {
|
|
@@ -976,8 +961,8 @@ function heldDerivation(e, n, t) {
|
|
|
976
961
|
if (e.length !== n.length) return true;
|
|
977
962
|
for (let t = 0; t < n.length; t++) {
|
|
978
963
|
const r = e[t];
|
|
979
|
-
const
|
|
980
|
-
if (!isEqual(r,
|
|
964
|
+
const o = n[t];
|
|
965
|
+
if (!isEqual(r, o) && !targetsEqual(r, o)) return true;
|
|
981
966
|
}
|
|
982
967
|
return false;
|
|
983
968
|
}
|
|
@@ -989,23 +974,23 @@ function membershipChanged(e, n) {
|
|
|
989
974
|
return false;
|
|
990
975
|
}
|
|
991
976
|
|
|
992
|
-
/** One leaf's notification for an adoption diff (descriptor-aware). */ function notifyKeyDiff(e, n, t, r,
|
|
993
|
-
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) {
|
|
994
979
|
e.acc = isOwnAccessor(r, n);
|
|
995
|
-
const
|
|
996
|
-
const
|
|
980
|
+
const o = Object.getOwnPropertyDescriptor(t, n);
|
|
981
|
+
const i = Object.getOwnPropertyDescriptor(r, n);
|
|
997
982
|
// Data descriptors fall through, as in notifyWrites (#3949).
|
|
998
|
-
if (!
|
|
999
|
-
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);
|
|
1000
985
|
return;
|
|
1001
986
|
}
|
|
1002
|
-
const l =
|
|
1003
|
-
const u =
|
|
1004
|
-
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);
|
|
1005
990
|
} else {
|
|
1006
|
-
const
|
|
1007
|
-
const
|
|
1008
|
-
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);
|
|
1009
994
|
}
|
|
1010
995
|
}
|
|
1011
996
|
|
|
@@ -1013,9 +998,9 @@ function hasAccessorFlag(e) {
|
|
|
1013
998
|
return e.acc === true;
|
|
1014
999
|
}
|
|
1015
1000
|
|
|
1016
|
-
/** 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) {
|
|
1017
1002
|
if (e.acc === true) {
|
|
1018
|
-
notifyKeyDiff(e, n,
|
|
1003
|
+
notifyKeyDiff(e, n, o, i, false);
|
|
1019
1004
|
return;
|
|
1020
1005
|
}
|
|
1021
1006
|
if (!isEqual(t, r) && !targetsEqual(t, r)) setSignal(e, typeof r === "function" ? () => r : r);
|
|
@@ -1044,12 +1029,12 @@ function hasAccessorFlag(e) {
|
|
|
1044
1029
|
const r = e.h;
|
|
1045
1030
|
if (r !== null) {
|
|
1046
1031
|
const e = n[$TARGET];
|
|
1047
|
-
for (const
|
|
1032
|
+
for (const o of Reflect.ownKeys(r)) if (e || o in n !== o in t) setSignal(r[o], o in t);
|
|
1048
1033
|
}
|
|
1049
|
-
const
|
|
1050
|
-
if (
|
|
1034
|
+
const o = e.k;
|
|
1035
|
+
if (o !== null && (o.o !== null || o.l & CONFIG_OVERRIDE)) {
|
|
1051
1036
|
const e = Array.isArray(t) && Array.isArray(n) ? arrayStructureChanged(n, t) : membershipChanged(n, t);
|
|
1052
|
-
if (e) notifyContainer(
|
|
1037
|
+
if (e) notifyContainer(o, t);
|
|
1053
1038
|
}
|
|
1054
1039
|
}
|
|
1055
1040
|
|
|
@@ -1094,7 +1079,7 @@ function inDraft(e) {
|
|
|
1094
1079
|
/** A child proxy served to a draft joins the draft's scope. */ function draftServe(e, n) {
|
|
1095
1080
|
if (writeScopes !== null && inDraft(e)) {
|
|
1096
1081
|
const e = n?.[$TARGET];
|
|
1097
|
-
if (e
|
|
1082
|
+
if (e?.v !== undefined) writeScopes.add(scopeKey(e));
|
|
1098
1083
|
}
|
|
1099
1084
|
return n;
|
|
1100
1085
|
}
|
|
@@ -1104,7 +1089,7 @@ function inDraft(e) {
|
|
|
1104
1089
|
* "adoption is eager by contract" — and the node keeps the frame committed
|
|
1105
1090
|
* readers under a hold still see), `t.v` otherwise. */ function committed(e) {
|
|
1106
1091
|
const n = e.k;
|
|
1107
|
-
if (n !== null) return n.
|
|
1092
|
+
if (n !== null) return n.ie !== NOT_PENDING ? asBacking(n.le) : e.v;
|
|
1108
1093
|
// A node-less staging (`stageOn`): the fold queue remembers the frame.
|
|
1109
1094
|
return e.pb !== null ? preBatch(e) : e.v;
|
|
1110
1095
|
}
|
|
@@ -1137,7 +1122,7 @@ function inDraft(e) {
|
|
|
1137
1122
|
// sees — the lanes' values and the tick's own guesses over the truth
|
|
1138
1123
|
// (#3665), never a staging awaiting its fold: the draft is born on the
|
|
1139
1124
|
// read (and notified at the setter's exit like any).
|
|
1140
|
-
if (userWrite && e.fam
|
|
1125
|
+
if (userWrite && e.fam?.opt === true && !pendingNotify.has(e) && inDraft(e)) {
|
|
1141
1126
|
const n = ensurePB(e);
|
|
1142
1127
|
pendingNotify.add(e);
|
|
1143
1128
|
return n;
|
|
@@ -1163,21 +1148,21 @@ function inDraft(e) {
|
|
|
1163
1148
|
}
|
|
1164
1149
|
return r;
|
|
1165
1150
|
}
|
|
1166
|
-
const
|
|
1151
|
+
const o = e.k;
|
|
1167
1152
|
// A key whose leaf carries a lane's value (a guess, S4): the leaf serves
|
|
1168
1153
|
// it — the container's frame is not consulted (a reader is not made a
|
|
1169
1154
|
// stale reader of the container's hold for a key it does not see through
|
|
1170
1155
|
// it).
|
|
1171
1156
|
if (n !== undefined) {
|
|
1172
1157
|
const t = e.n?.[n];
|
|
1173
|
-
if (t
|
|
1158
|
+
if (t?.l & CONFIG_OVERRIDE) return committed(e);
|
|
1174
1159
|
}
|
|
1175
|
-
const
|
|
1160
|
+
const i = o !== null && (o.l & CONFIG_HELD) !== 0;
|
|
1176
1161
|
// A held container: the hold's unit is the key (#3706). A key the HELD
|
|
1177
1162
|
// staging left unchanged reads the ambient view — a mainline layer's
|
|
1178
1163
|
// write above the hold publishes mainline (#3688, #3612); a key it
|
|
1179
1164
|
// changed reads the frame core serves this reader.
|
|
1180
|
-
if (
|
|
1165
|
+
if (i && n !== undefined && !heldKeyChanged(e, n, t)) return r;
|
|
1181
1166
|
const l = stagingReader();
|
|
1182
1167
|
if (l === null) {
|
|
1183
1168
|
if (getObserver() !== null) return r;
|
|
@@ -1190,8 +1175,8 @@ function inDraft(e) {
|
|
|
1190
1175
|
// probe) judges the container like any node — for a key the batch
|
|
1191
1176
|
// changed; an unchanged key is committed and final (A22: pending is per
|
|
1192
1177
|
// key). A held container's committed frame is the node's.
|
|
1193
|
-
if (verdict === null || !
|
|
1194
|
-
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));
|
|
1195
1180
|
}
|
|
1196
1181
|
// A pass reading a key the batch left unchanged: the same value in both
|
|
1197
1182
|
// frames — committed, holding no one. Otherwise the container's frame by
|
|
@@ -1200,7 +1185,7 @@ function inDraft(e) {
|
|
|
1200
1185
|
// sees committed and re-derives at the landing, a memo joins the future,
|
|
1201
1186
|
// a staging read is marked. The key's own leaf, when it has one, decides
|
|
1202
1187
|
// the value the same way.
|
|
1203
|
-
if (!
|
|
1188
|
+
if (!i) {
|
|
1204
1189
|
// A plain pass this flush already served a staging as the screen
|
|
1205
1190
|
// (REACTIVE_STAGED_READ — what `read()` would set again here) reads an
|
|
1206
1191
|
// unheld staging directly: an unchanged key is the same value in both
|
|
@@ -1212,18 +1197,18 @@ function inDraft(e) {
|
|
|
1212
1197
|
// A node-less staging (`stageOn`): what `read()` of its node would do
|
|
1213
1198
|
// for this pass — a verdict reader sees the screen, any other derives
|
|
1214
1199
|
// from the staging and is marked as having read it.
|
|
1215
|
-
if (
|
|
1200
|
+
if (o === null) {
|
|
1216
1201
|
if (l.l & CONFIG_VERDICT && stagedScreen(l)) return committed(e);
|
|
1217
1202
|
stagedRead(l);
|
|
1218
1203
|
return r;
|
|
1219
1204
|
}
|
|
1220
1205
|
}
|
|
1221
|
-
return asBacking(untrack(() => read(
|
|
1206
|
+
return asBacking(untrack(() => read(o)));
|
|
1222
1207
|
}
|
|
1223
1208
|
|
|
1224
1209
|
/** Did the HELD staging (the container node's, not a mainline layer above
|
|
1225
1210
|
* it) change `key`? */ function heldKeyChanged(e, n, t = true) {
|
|
1226
|
-
return changedBetween(e, e.k.
|
|
1211
|
+
return changedBetween(e, e.k.le, e.k.ie, n, t) && !adoptChild(e, n);
|
|
1227
1212
|
}
|
|
1228
1213
|
|
|
1229
1214
|
/** The values of a held frame, built once per frame: neither the committed
|
|
@@ -1250,25 +1235,25 @@ function rawsOf(e) {
|
|
|
1250
1235
|
* `version` holds. A record's keys pair by name; an array's by the family's
|
|
1251
1236
|
* key — without a family the pairing is not known here and the hold stands. */ function adoptChild(e, n) {
|
|
1252
1237
|
const t = e.k;
|
|
1253
|
-
const r = asBacking(t.
|
|
1254
|
-
const
|
|
1255
|
-
const
|
|
1238
|
+
const r = asBacking(t.le);
|
|
1239
|
+
const o = r[n];
|
|
1240
|
+
const i = t.ie[n];
|
|
1256
1241
|
const l = Array.isArray(r) ? e.fam?.key : null;
|
|
1257
|
-
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 ||
|
|
1258
1243
|
// A raw in both frames (the same objects swapped or reordered) is its
|
|
1259
1244
|
// own row: pairing it with another would alias the two after the commit.
|
|
1260
|
-
rawsOf(r).has(
|
|
1245
|
+
rawsOf(r).has(i) || rawsOf(t.ie).has(o)) return false;
|
|
1261
1246
|
// A raw-marked value wraps to itself, a proxy to its own target: neither
|
|
1262
1247
|
// is a fresh target around `ov`.
|
|
1263
|
-
const u = wrap(
|
|
1264
|
-
if (u
|
|
1265
|
-
adoptPB(u,
|
|
1248
|
+
const u = wrap(o, e, n)[$TARGET];
|
|
1249
|
+
if (u?.v !== o) return false;
|
|
1250
|
+
adoptPB(u, i, false);
|
|
1266
1251
|
holdNode(getContainerNode(u), txOf(t));
|
|
1267
1252
|
return true;
|
|
1268
1253
|
}
|
|
1269
1254
|
|
|
1270
1255
|
/** A family target's unheld staging, read with no pass (a handler). */ function familyAhead(e) {
|
|
1271
|
-
return e.fam !== null && context === null && !(e.k
|
|
1256
|
+
return e.fam !== null && context === null && !(e.k?.l & CONFIG_HELD);
|
|
1272
1257
|
}
|
|
1273
1258
|
|
|
1274
1259
|
/** Did this batch change `key` — value (slot equality), presence, and (for
|
|
@@ -1286,13 +1271,13 @@ function rawsOf(e) {
|
|
|
1286
1271
|
return changedBetween(e, committed(e), e.pb, n, t);
|
|
1287
1272
|
}
|
|
1288
1273
|
|
|
1289
|
-
function changedBetween(e, n, t, r,
|
|
1274
|
+
function changedBetween(e, n, t, r, o) {
|
|
1290
1275
|
if (e.ch || t[$TARGET] !== undefined || Object.getPrototypeOf(t) !== Object.getPrototypeOf(n) || !plainProto(n)) return true;
|
|
1291
|
-
if (e.del
|
|
1292
|
-
const
|
|
1293
|
-
if (
|
|
1294
|
-
if (!
|
|
1295
|
-
if ((
|
|
1276
|
+
if (e.del?.has(r)) return r in n;
|
|
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;
|
|
1296
1281
|
const l = t[r];
|
|
1297
1282
|
const u = n[r];
|
|
1298
1283
|
return !isEqual(u, l) && !sameLogicalSlot(e, u, l);
|
|
@@ -1302,12 +1287,12 @@ function changedBetween(e, n, t, r, i) {
|
|
|
1302
1287
|
* tracked or not, applies the hold and A28 rules a signal's read does. A
|
|
1303
1288
|
* projection's unheld staging is ahead for a handler (`familyAhead`). */ function nodeValue(e, n, t) {
|
|
1304
1289
|
let r = read(e);
|
|
1305
|
-
if (e.
|
|
1290
|
+
if (e.ie !== NOT_PENDING && !(e.l & CONFIG_HELD) && context === null && t.fam !== null) r = e.ie;
|
|
1306
1291
|
return r === FORCE ? n : r;
|
|
1307
1292
|
}
|
|
1308
1293
|
|
|
1309
1294
|
/** Serve a present data key: link the leaf for a tracked reader (creating it
|
|
1310
|
-
* 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) {
|
|
1311
1296
|
// Read-through (§7b): the inner store's node is the truth; the outer's is
|
|
1312
1297
|
// a subscription point only — unless it carries a guess (an optimistic
|
|
1313
1298
|
// store over a store: the guess is the outer's, shown over the inner).
|
|
@@ -1316,14 +1301,14 @@ function changedBetween(e, n, t, r, i) {
|
|
|
1316
1301
|
// A write-override read (a derive's draft) serves the backing: the derive
|
|
1317
1302
|
// composes on the truth, never on a lane's or a hold's frame.
|
|
1318
1303
|
if (!inDraft(e) && !writeOverride) {
|
|
1319
|
-
if (
|
|
1320
|
-
if (
|
|
1321
|
-
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);
|
|
1322
1307
|
if (l) {
|
|
1323
1308
|
// The link's committed value follows the inner store's (what a lane
|
|
1324
1309
|
// over it covers — its reveal and revert compare against it, S4).
|
|
1325
|
-
|
|
1326
|
-
if (
|
|
1310
|
+
o.le = t;
|
|
1311
|
+
if (o.l & CONFIG_OVERRIDE) u = n;
|
|
1327
1312
|
} else u = n;
|
|
1328
1313
|
}
|
|
1329
1314
|
}
|
|
@@ -1331,12 +1316,12 @@ function changedBetween(e, n, t, r, i) {
|
|
|
1331
1316
|
// A derive's draft wrapper answers `$TARGET` without being a proxy: the
|
|
1332
1317
|
// inner store's alias (#3767), resolved like a raw (#3859).
|
|
1333
1318
|
if (e.ch && !l && u !== null && typeof u === "object" && u[$TARGET]?.px !== u) u = resolveChainedRaw(e, n, u);
|
|
1334
|
-
if (
|
|
1335
|
-
if (
|
|
1319
|
+
if (o !== undefined) {
|
|
1320
|
+
if (o.pxv === u && u !== undefined) return draftServe(e, o.px);
|
|
1336
1321
|
if (!isWrappable(u)) return u;
|
|
1337
1322
|
const t = wrap(u, e, n);
|
|
1338
|
-
|
|
1339
|
-
|
|
1323
|
+
o.px = t;
|
|
1324
|
+
o.pxv = u;
|
|
1340
1325
|
return draftServe(e, t);
|
|
1341
1326
|
}
|
|
1342
1327
|
if (!isWrappable(u)) return u;
|
|
@@ -1395,7 +1380,7 @@ function changedBetween(e, n, t, r, i) {
|
|
|
1395
1380
|
* classification, as core reads it — `heldNotFinal`). */ function holdWithDerive(e, n) {
|
|
1396
1381
|
const t = e.fam?.node;
|
|
1397
1382
|
if (t !== undefined && t !== null && !userWrite && // the derive's own write (its draft or landing), not a user setter's
|
|
1398
|
-
t.l & CONFIG_HELD && n.
|
|
1383
|
+
t.l & CONFIG_HELD && n.ie !== NOT_PENDING &&
|
|
1399
1384
|
// A node carrying a guess is the lane's: its staging is the truth beneath
|
|
1400
1385
|
// the guess (`setSignal` → `laneWrite`), never re-homed by the store.
|
|
1401
1386
|
!(n.l & (CONFIG_HELD | CONFIG_OVERRIDE))) {
|
|
@@ -1413,8 +1398,8 @@ function changedBetween(e, n, t, r, i) {
|
|
|
1413
1398
|
const e = resolveChainedRaw(r, n, t);
|
|
1414
1399
|
return e === t ? t : wrap(e, r, n);
|
|
1415
1400
|
}
|
|
1416
|
-
const
|
|
1417
|
-
if (
|
|
1401
|
+
const o = lookupTarget(t, r.fam);
|
|
1402
|
+
if (o !== undefined) return o.px;
|
|
1418
1403
|
if ((r.v[n] === t || r.pb?.[n] === t) && isWrappable(t)) return wrap(t, r, n);
|
|
1419
1404
|
return t;
|
|
1420
1405
|
}
|
|
@@ -1427,16 +1412,16 @@ function changedBetween(e, n, t, r, i) {
|
|
|
1427
1412
|
// A container's arrangement guess is not a backing: the view composes
|
|
1428
1413
|
// over the base it is shown over.
|
|
1429
1414
|
const n = asBacking(read(getContainerNode(e)));
|
|
1430
|
-
return e.fam?.opt === true ? optHooks.view(e, n) : n;
|
|
1415
|
+
return optHooks && e.fam?.opt === true ? optHooks.view(e, n) : n;
|
|
1431
1416
|
}
|
|
1432
1417
|
const n = readSource(e);
|
|
1433
|
-
return optRead(e) ? optHooks.view(e, n) : n;
|
|
1418
|
+
return optHooks && optRead(e) ? optHooks.view(e, n) : n;
|
|
1434
1419
|
}
|
|
1435
1420
|
|
|
1436
1421
|
/** A read on an optimistic family that composes the lanes' values: not the
|
|
1437
1422
|
* draft's (it composed already), not a derive's write-override read (the
|
|
1438
1423
|
* derive composes on the truth). */ function optRead(e) {
|
|
1439
|
-
return e.fam
|
|
1424
|
+
return e.fam?.opt === true && !inDraft(e) && !writeOverride;
|
|
1440
1425
|
}
|
|
1441
1426
|
|
|
1442
1427
|
/** Pollution keys are never served from the prototype (core R30). */ const UNSAFE_KEYS = new Set([ "__proto__", "prototype", "constructor" ]);
|
|
@@ -1508,18 +1493,18 @@ const traps = {
|
|
|
1508
1493
|
if (e.s) return serveShallow(e, n, r);
|
|
1509
1494
|
if (t.pxv === r) return t.px;
|
|
1510
1495
|
if (isWrappable(r)) {
|
|
1511
|
-
const
|
|
1512
|
-
t.px =
|
|
1496
|
+
const o = wrap(r, e, n);
|
|
1497
|
+
t.px = o;
|
|
1513
1498
|
t.pxv = r;
|
|
1514
|
-
return
|
|
1499
|
+
return o;
|
|
1515
1500
|
}
|
|
1516
1501
|
return r;
|
|
1517
1502
|
}
|
|
1518
1503
|
}
|
|
1519
|
-
const
|
|
1504
|
+
const o = readSource(e, n);
|
|
1520
1505
|
// Overlay delete (#3044): a prototype overlay cannot shadow a delete, so
|
|
1521
1506
|
// deleted keys are tracked aside and read as absent in the pending view.
|
|
1522
|
-
if (
|
|
1507
|
+
if (o === e.pb && e.del?.has(n)) {
|
|
1523
1508
|
if (!inDraft(e) && getObserver() !== null) read(getNode(e, n));
|
|
1524
1509
|
return undefined;
|
|
1525
1510
|
}
|
|
@@ -1530,16 +1515,16 @@ const traps = {
|
|
|
1530
1515
|
// node) probes once — untracked node-less reads take the plain path,
|
|
1531
1516
|
// where a raw-receiver getter still returns correct committed values.
|
|
1532
1517
|
// Tracking suppression is PER-TARGET (inDraft), never global (#3037).
|
|
1533
|
-
let
|
|
1518
|
+
let i = -1;
|
|
1534
1519
|
{
|
|
1535
1520
|
let l;
|
|
1536
1521
|
if (r !== undefined) l = r.acc === true; else if (!inDraft(e) && getObserver() !== null) {
|
|
1537
|
-
l = isOwnAccessor(
|
|
1538
|
-
if (
|
|
1522
|
+
l = isOwnAccessor(o, n);
|
|
1523
|
+
if (o === (e.pb ?? e.v)) i = l ? 1 : 0;
|
|
1539
1524
|
} else l = false;
|
|
1540
1525
|
if (l) {
|
|
1541
|
-
if (!inDraft(e) && getObserver() !== null) read(r ?? getNode(e, n,
|
|
1542
|
-
const l = Reflect.get(
|
|
1526
|
+
if (!inDraft(e) && getObserver() !== null) read(r ?? getNode(e, n, i));
|
|
1527
|
+
const l = Reflect.get(o, n, t);
|
|
1543
1528
|
if (e.s) return serveShallow(e, n, l);
|
|
1544
1529
|
return isWrappable(l) ? draftServe(e, wrap(l, e, n)) : l;
|
|
1545
1530
|
}
|
|
@@ -1550,21 +1535,21 @@ const traps = {
|
|
|
1550
1535
|
// chain to the committed backing, so "own in the view" means own on
|
|
1551
1536
|
// either layer — a genuine prototype method is one that is own on
|
|
1552
1537
|
// NEITHER.
|
|
1553
|
-
const l = e.ovl &&
|
|
1554
|
-
if ((n === "constructor" || n === "__proto__" || n === "prototype") && !hasOwn.call(
|
|
1555
|
-
let u =
|
|
1556
|
-
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) {
|
|
1557
1542
|
// Inherited: prototype getters/methods run with the proxy receiver.
|
|
1558
|
-
u = Reflect.get(
|
|
1543
|
+
u = Reflect.get(o, n, t);
|
|
1559
1544
|
if (typeof u === "function") return u;
|
|
1560
1545
|
// proto methods untracked
|
|
1561
1546
|
// Read-through (§7b): the inner store answers an absent key too — the
|
|
1562
1547
|
// outer's node is a subscription point unless it carries a guess.
|
|
1563
|
-
if (e.ch &&
|
|
1548
|
+
if (e.ch && o === e.v) return serveDataKey(e, n, u, o, r, i);
|
|
1564
1549
|
// Reading a currently-absent own key subscribes to it (R12) — for any
|
|
1565
1550
|
// target OUTSIDE its own draft scope, even mid-setter (#3037, above).
|
|
1566
1551
|
if (u === undefined && !inDraft(e)) {
|
|
1567
|
-
if (getObserver() !== null) read(getNode(e, n,
|
|
1552
|
+
if (getObserver() !== null) read(getNode(e, n, i));
|
|
1568
1553
|
const t = e.n?.[n];
|
|
1569
1554
|
if (t) {
|
|
1570
1555
|
const r = nodeValue(t, undefined, e);
|
|
@@ -1575,9 +1560,9 @@ const traps = {
|
|
|
1575
1560
|
if (e.s) return serveShallow(e, n, u);
|
|
1576
1561
|
return isWrappable(u) ? draftServe(e, wrap(u, e, n)) : u;
|
|
1577
1562
|
}
|
|
1578
|
-
if (typeof u === "function" && !hasOwn.call(
|
|
1563
|
+
if (typeof u === "function" && !hasOwn.call(o, n) && !(l && hasOwn.call(e.v, n))) return u;
|
|
1579
1564
|
// proto method
|
|
1580
|
-
return serveDataKey(e, n, u,
|
|
1565
|
+
return serveDataKey(e, n, u, o, r, i);
|
|
1581
1566
|
},
|
|
1582
1567
|
has(e, n) {
|
|
1583
1568
|
if (n === $TARGET || n === $PROXY || n === $TRACK) return true;
|
|
@@ -1594,19 +1579,19 @@ const traps = {
|
|
|
1594
1579
|
if (!inDraft(e) && !writeOverride) {
|
|
1595
1580
|
if (getObserver() !== null) {
|
|
1596
1581
|
const r = getHasNode(e, n);
|
|
1597
|
-
const
|
|
1598
|
-
if (!e.ch || t !== e.v) return !!
|
|
1599
|
-
const
|
|
1600
|
-
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;
|
|
1601
1586
|
// the link follows the inner store (S4)
|
|
1602
|
-
if (r.l & CONFIG_OVERRIDE) return !!
|
|
1603
|
-
return
|
|
1604
|
-
} else if (optRead(e)) {
|
|
1587
|
+
if (r.l & CONFIG_OVERRIDE) return !!o;
|
|
1588
|
+
return i;
|
|
1589
|
+
} else if (optHooks && optRead(e)) {
|
|
1605
1590
|
const t = optHooks.has(e, n);
|
|
1606
1591
|
if (t !== undefined) return t;
|
|
1607
1592
|
}
|
|
1608
1593
|
}
|
|
1609
|
-
return n in t && !(
|
|
1594
|
+
return n in t && !(t === e.pb && e.del?.has(n));
|
|
1610
1595
|
},
|
|
1611
1596
|
ownKeys(e) {
|
|
1612
1597
|
if (verdict !== null && affectsHooks !== null && getObserver() === null) affectsHooks.ro(e, undefined);
|
|
@@ -1622,9 +1607,9 @@ const traps = {
|
|
|
1622
1607
|
// node and reads its frame; a descriptor read on its own tracks
|
|
1623
1608
|
// presence (R13).
|
|
1624
1609
|
const r = t !== null && !inDraft(e) && !writeOverride;
|
|
1625
|
-
const
|
|
1626
|
-
let
|
|
1627
|
-
if (
|
|
1610
|
+
const o = r && observerHoldsContainer(e, t);
|
|
1611
|
+
let i;
|
|
1612
|
+
if (o) i = enumerationSource(e); else if (r) {
|
|
1628
1613
|
// The presence node's frame (core decides which) is the one described
|
|
1629
1614
|
// (a chained target's inner store answers through the backing, §7b);
|
|
1630
1615
|
// the descriptor itself comes from the backing the container's frame
|
|
@@ -1633,30 +1618,29 @@ const traps = {
|
|
|
1633
1618
|
// the staging for a member; #3706 contrast).
|
|
1634
1619
|
const t = getHasNode(e, n);
|
|
1635
1620
|
const r = read(t);
|
|
1636
|
-
|
|
1637
|
-
if (!r && (!e.ch || t.l & CONFIG_OVERRIDE || !(n in
|
|
1638
|
-
} 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);
|
|
1639
1624
|
let l;
|
|
1640
|
-
if (!
|
|
1625
|
+
if (optHooks && !o && optRead(e)) {
|
|
1641
1626
|
const t = optHooks.descriptor(e, n);
|
|
1642
1627
|
if (t === null) return undefined;
|
|
1643
1628
|
l = t;
|
|
1644
1629
|
}
|
|
1645
|
-
l ??= visibleDescriptor(e,
|
|
1630
|
+
l ??= visibleDescriptor(e, i, n);
|
|
1646
1631
|
if (l === undefined) return undefined;
|
|
1647
1632
|
if (!(n === "length" && Array.isArray(e))) l.configurable = true;
|
|
1648
1633
|
return l;
|
|
1649
1634
|
},
|
|
1650
1635
|
set(e, n, t) {
|
|
1651
1636
|
const r = inDraft(e);
|
|
1652
|
-
|
|
1653
|
-
if (!r && !i) {
|
|
1637
|
+
if (!r && !writeOverride) {
|
|
1654
1638
|
return true;
|
|
1655
1639
|
}
|
|
1656
1640
|
if (n === "__proto__") return true;
|
|
1657
1641
|
// pollution guard (core R30)
|
|
1658
1642
|
const o = e.s ? t : unwrapValue(t);
|
|
1659
|
-
const
|
|
1643
|
+
const i = ensurePB(e);
|
|
1660
1644
|
// #4146 (R1: node existence is unobservable; #3706: the hold's unit is
|
|
1661
1645
|
// the key): a user setter writing a key a HELD container's staging left
|
|
1662
1646
|
// unchanged would write it into the held staging — read as the hold's
|
|
@@ -1668,40 +1652,32 @@ const traps = {
|
|
|
1668
1652
|
// A34) — as it would with a reader's leaf. Kept while the container is
|
|
1669
1653
|
// held (`deferredReleases`).
|
|
1670
1654
|
if (userWrite && e.k?.l & CONFIG_HELD) deferredReleases.add(getNode(e, n));
|
|
1671
|
-
if (Array.isArray(
|
|
1655
|
+
if (Array.isArray(i)) {
|
|
1672
1656
|
touch(e, n);
|
|
1673
1657
|
if (n === "length") e.wk = WK_ALL; else touch(e, "length");
|
|
1674
1658
|
} else {
|
|
1675
1659
|
touch(e, n);
|
|
1676
|
-
if (!(n in
|
|
1660
|
+
if (!(n in i)) e.kc++;
|
|
1677
1661
|
}
|
|
1678
|
-
|
|
1679
|
-
|
|
1662
|
+
const l = UNSAFE_KEYS.has(n);
|
|
1663
|
+
if (l || e.ovl && e.sc !== 2 && !hasOwn.call(i, n)) {
|
|
1664
|
+
Object.defineProperty(i, n, {
|
|
1680
1665
|
value: o,
|
|
1681
1666
|
writable: true,
|
|
1682
1667
|
enumerable: true,
|
|
1683
1668
|
configurable: true
|
|
1684
1669
|
});
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
if (e.ovl && e.sc !== 2 && !hasOwn.call(l, n)) {
|
|
1689
|
-
Object.defineProperty(l, n, {
|
|
1690
|
-
value: o,
|
|
1691
|
-
writable: true,
|
|
1692
|
-
enumerable: true,
|
|
1693
|
-
configurable: true
|
|
1694
|
-
});
|
|
1695
|
-
} else l[n] = o;
|
|
1696
|
-
if (e.del !== null) e.del.delete(n);
|
|
1670
|
+
} else i[n] = o;
|
|
1671
|
+
e.del?.delete(n);
|
|
1672
|
+
if (l) return true;
|
|
1697
1673
|
if (e.s && o !== null && typeof o === "object") markRawOne(o);
|
|
1698
|
-
if (
|
|
1699
|
-
|
|
1674
|
+
if (!r) notifyWrites(e);
|
|
1675
|
+
// a write-override write
|
|
1676
|
+
return true;
|
|
1700
1677
|
},
|
|
1701
1678
|
defineProperty(e, n, t) {
|
|
1702
1679
|
const r = inDraft(e);
|
|
1703
|
-
|
|
1704
|
-
if (!r && !i) {
|
|
1680
|
+
if (!r && !writeOverride) {
|
|
1705
1681
|
return true;
|
|
1706
1682
|
}
|
|
1707
1683
|
if (n === "__proto__") return true;
|
|
@@ -1714,17 +1690,17 @@ const traps = {
|
|
|
1714
1690
|
if (e.a || !(t.enumerable && t.writable && t.configurable)) e.sc = 1;
|
|
1715
1691
|
touch(e, n);
|
|
1716
1692
|
Object.defineProperty(o, n, t);
|
|
1717
|
-
|
|
1718
|
-
if (
|
|
1719
|
-
|
|
1693
|
+
e.del?.delete(n);
|
|
1694
|
+
if (!r) notifyWrites(e);
|
|
1695
|
+
// a write-override write
|
|
1696
|
+
return true;
|
|
1720
1697
|
},
|
|
1721
1698
|
deleteProperty(e, n) {
|
|
1722
1699
|
const t = inDraft(e);
|
|
1723
|
-
|
|
1724
|
-
if (!t && !r) {
|
|
1700
|
+
if (!t && !writeOverride) {
|
|
1725
1701
|
return true;
|
|
1726
1702
|
}
|
|
1727
|
-
const
|
|
1703
|
+
const r = ensurePB(e);
|
|
1728
1704
|
touch(e, n);
|
|
1729
1705
|
// The key count (`kc`, the overlay gate and the rebuild cap) follows a
|
|
1730
1706
|
// delete the way it follows an add: an own key of the draft leaving — a
|
|
@@ -1736,13 +1712,14 @@ const traps = {
|
|
|
1736
1712
|
// object crossed the overlay threshold and paid a rebuild on every
|
|
1737
1713
|
// commit after.
|
|
1738
1714
|
const o = e.ovl && hasOwn.call(e.v, n);
|
|
1739
|
-
if (hasOwn.call(
|
|
1740
|
-
delete
|
|
1715
|
+
if (hasOwn.call(r, n)) {
|
|
1716
|
+
delete r[n];
|
|
1741
1717
|
o || e.kc--;
|
|
1742
1718
|
}
|
|
1743
1719
|
if (o) (e.del ??= new Set).add(n);
|
|
1744
|
-
if (
|
|
1745
|
-
|
|
1720
|
+
if (!t) notifyWrites(e);
|
|
1721
|
+
// a write-override write
|
|
1722
|
+
return true;
|
|
1746
1723
|
}
|
|
1747
1724
|
};
|
|
1748
1725
|
|
|
@@ -1752,16 +1729,16 @@ const traps = {
|
|
|
1752
1729
|
const t = e.k;
|
|
1753
1730
|
if (t === null) return false;
|
|
1754
1731
|
const r = t.ve;
|
|
1755
|
-
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);
|
|
1756
1733
|
}
|
|
1757
1734
|
|
|
1758
1735
|
function storeSetter(e, n, t = true) {
|
|
1759
1736
|
if (writeHook !== null) writeHook(e);
|
|
1760
1737
|
const r = e[$TARGET];
|
|
1761
|
-
const
|
|
1738
|
+
const o = writeScopes;
|
|
1762
1739
|
writeScopes = new Set;
|
|
1763
1740
|
writeScopes.add(scopeKey(r));
|
|
1764
|
-
const
|
|
1741
|
+
const i = userWrite;
|
|
1765
1742
|
userWrite = t;
|
|
1766
1743
|
writing++;
|
|
1767
1744
|
let l;
|
|
@@ -1773,7 +1750,7 @@ function storeSetter(e, n, t = true) {
|
|
|
1773
1750
|
l = n(e);
|
|
1774
1751
|
} finally {
|
|
1775
1752
|
writing--;
|
|
1776
|
-
writeScopes =
|
|
1753
|
+
writeScopes = o;
|
|
1777
1754
|
// Outermost setter exit: emit write-time notifications (one node write
|
|
1778
1755
|
// per changed observed key) so holds and lanes engage now.
|
|
1779
1756
|
if (writing === 0 && pendingNotify.size) {
|
|
@@ -1784,13 +1761,13 @@ function storeSetter(e, n, t = true) {
|
|
|
1784
1761
|
// exit, unqueued: the backing is the pre-batch one (nothing swapped).
|
|
1785
1762
|
if (directCommit) for (const n of e) if (n.pb !== null) foldTarget(n, n.v);
|
|
1786
1763
|
}
|
|
1787
|
-
userWrite =
|
|
1764
|
+
userWrite = i;
|
|
1788
1765
|
}
|
|
1789
1766
|
if (l !== undefined && l !== e && isWrappable(l)) {
|
|
1790
1767
|
// A returned replacement: on an optimistic family a user's is itself an
|
|
1791
1768
|
// optimistic edit — diffed against the view as guesses (`next` parity);
|
|
1792
1769
|
// otherwise it is adopted as the incoming truth.
|
|
1793
|
-
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));
|
|
1794
1771
|
}
|
|
1795
1772
|
// A34 (3), #3612 — the derived store's twin of `setMemo`: a user write to
|
|
1796
1773
|
// a derivation another transaction holds is nobody's proposal; it becomes
|
|
@@ -1824,17 +1801,17 @@ function createStore(e, n) {
|
|
|
1824
1801
|
* replaced by reference — #2932). The list driver uses this to choose the
|
|
1825
1802
|
* slot-patch channel (collected row bodies) over per-record registration. */ function storeIsShallow(e) {
|
|
1826
1803
|
const n = e?.[$TARGET];
|
|
1827
|
-
return n
|
|
1804
|
+
return n?.s === true;
|
|
1828
1805
|
}
|
|
1829
1806
|
|
|
1830
1807
|
/** True when `proxy` belongs to a projection family (S3). */ function storeHasFamily(e) {
|
|
1831
1808
|
const n = e?.[$TARGET];
|
|
1832
|
-
return n
|
|
1809
|
+
return n?.fam != null;
|
|
1833
1810
|
}
|
|
1834
1811
|
|
|
1835
1812
|
/** True when `proxy` belongs to an OPTIMISTIC family (S4). */ function storeHasOptimisticFamily(e) {
|
|
1836
1813
|
const n = e?.[$TARGET];
|
|
1837
|
-
return n
|
|
1814
|
+
return n?.fam?.opt === true;
|
|
1838
1815
|
}
|
|
1839
1816
|
|
|
1840
1817
|
// ---------------------------------------------------------------------------
|
|
@@ -1844,7 +1821,7 @@ function visibleKeys(e, n) {
|
|
|
1844
1821
|
if (e.ovl && n === e.pb) {
|
|
1845
1822
|
t = Reflect.ownKeys(e.v);
|
|
1846
1823
|
const r = e.del;
|
|
1847
|
-
if (r
|
|
1824
|
+
if (r?.size) t = t.filter(e => !r.has(e));
|
|
1848
1825
|
for (const r of Reflect.ownKeys(n)) {
|
|
1849
1826
|
if (!hasOwn.call(e.v, r)) t.push(r);
|
|
1850
1827
|
}
|
|
@@ -1862,7 +1839,7 @@ function visibleKeys(e, n) {
|
|
|
1862
1839
|
function visibleDescriptor(e, n, t) {
|
|
1863
1840
|
let r = Object.getOwnPropertyDescriptor(n, t);
|
|
1864
1841
|
if (e.ovl && n === e.pb) {
|
|
1865
|
-
if (e.del
|
|
1842
|
+
if (e.del?.has(t)) return undefined;
|
|
1866
1843
|
if (r === undefined) r = Object.getOwnPropertyDescriptor(e.v, t);
|
|
1867
1844
|
}
|
|
1868
1845
|
return r;
|
|
@@ -1873,7 +1850,7 @@ function visibleDescriptor(e, n, t) {
|
|
|
1873
1850
|
/** Tracking snapshot: subscribes every reachable record's container and deep
|
|
1874
1851
|
* witness (one node per record, not one per path), then snapshots. */ function deep(e) {
|
|
1875
1852
|
const n = e?.[$TARGET];
|
|
1876
|
-
if (n
|
|
1853
|
+
if (n?.px !== e) return e;
|
|
1877
1854
|
const t = new Set;
|
|
1878
1855
|
const childTarget = (e, n, t) => {
|
|
1879
1856
|
let r = lookupTarget(n, e.fam);
|
|
@@ -1905,13 +1882,13 @@ function visibleDescriptor(e, n, t) {
|
|
|
1905
1882
|
continue;
|
|
1906
1883
|
// accessors track through their own reads when invoked
|
|
1907
1884
|
}
|
|
1908
|
-
let
|
|
1909
|
-
if (
|
|
1910
|
-
if (e.ch &&
|
|
1911
|
-
const
|
|
1912
|
-
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;
|
|
1913
1890
|
// raw-marked: leaf by contract
|
|
1914
|
-
walkT(
|
|
1891
|
+
walkT(i);
|
|
1915
1892
|
}
|
|
1916
1893
|
};
|
|
1917
1894
|
walkT(n);
|
|
@@ -1930,68 +1907,68 @@ function snapshotWalk(e, n, t) {
|
|
|
1930
1907
|
let r = e;
|
|
1931
1908
|
for (let e = true; ;e = false) {
|
|
1932
1909
|
const n = r?.[$TARGET]?.v !== undefined;
|
|
1933
|
-
let
|
|
1934
|
-
if (
|
|
1935
|
-
if (
|
|
1936
|
-
if (
|
|
1937
|
-
if (e && !n && t !== null &&
|
|
1938
|
-
const e = t.map.get(
|
|
1939
|
-
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;
|
|
1940
1917
|
}
|
|
1941
|
-
if (
|
|
1918
|
+
if (o.fam !== null) t = o.fam;
|
|
1942
1919
|
// R27: a snapshot sees the batch's pending backing — a held one (another
|
|
1943
1920
|
// transaction's future) only from its own draft.
|
|
1944
|
-
let
|
|
1945
|
-
if (
|
|
1946
|
-
if (
|
|
1947
|
-
|
|
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;
|
|
1948
1925
|
}
|
|
1949
|
-
if (optRead(
|
|
1950
|
-
if (
|
|
1951
|
-
r =
|
|
1926
|
+
if (optHooks && optRead(o)) i = optHooks.view(o, i);
|
|
1927
|
+
if (i === r) break;
|
|
1928
|
+
r = i;
|
|
1952
1929
|
}
|
|
1953
1930
|
if (!isWrappable(r)) return r;
|
|
1954
|
-
const
|
|
1955
|
-
if (
|
|
1931
|
+
const o = n.get(r);
|
|
1932
|
+
if (o !== undefined) return o;
|
|
1956
1933
|
if (isOwned(r)) {
|
|
1957
1934
|
const e = Array.isArray(r);
|
|
1958
|
-
const
|
|
1959
|
-
n.set(r,
|
|
1960
|
-
for (const
|
|
1961
|
-
if (e &&
|
|
1962
|
-
const l = Object.getOwnPropertyDescriptor(r,
|
|
1963
|
-
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;
|
|
1964
1941
|
if (l.get || l.set) {
|
|
1965
|
-
Object.defineProperty(
|
|
1942
|
+
Object.defineProperty(o, i, l);
|
|
1966
1943
|
continue;
|
|
1967
1944
|
}
|
|
1968
1945
|
const u = l.value;
|
|
1969
1946
|
const f = u !== null && typeof u === "object" ? snapshotWalk(u, n, t) : u;
|
|
1970
|
-
if (l.enumerable && l.writable && l.configurable) i
|
|
1947
|
+
if (l.enumerable && l.writable && l.configurable) o[i] = f; else Object.defineProperty(o, i, {
|
|
1971
1948
|
...l,
|
|
1972
1949
|
value: f
|
|
1973
1950
|
});
|
|
1974
1951
|
}
|
|
1975
|
-
if (e &&
|
|
1976
|
-
return
|
|
1952
|
+
if (e && o.length !== r.length) o.length = r.length;
|
|
1953
|
+
return o;
|
|
1977
1954
|
}
|
|
1978
1955
|
n.set(r, r);
|
|
1979
|
-
let
|
|
1956
|
+
let i = null;
|
|
1980
1957
|
for (const e of Reflect.ownKeys(r)) {
|
|
1981
|
-
const
|
|
1982
|
-
if (!
|
|
1983
|
-
const l =
|
|
1958
|
+
const o = Object.getOwnPropertyDescriptor(r, e);
|
|
1959
|
+
if (!o || o.get || o.set) continue;
|
|
1960
|
+
const l = o.value;
|
|
1984
1961
|
if (l === null || typeof l !== "object") continue;
|
|
1985
1962
|
const u = snapshotWalk(l, n, t);
|
|
1986
1963
|
if (u !== l) {
|
|
1987
|
-
if (
|
|
1988
|
-
|
|
1989
|
-
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);
|
|
1990
1967
|
}
|
|
1991
|
-
|
|
1968
|
+
i[e] = u;
|
|
1992
1969
|
}
|
|
1993
1970
|
}
|
|
1994
|
-
return
|
|
1971
|
+
return i ?? r;
|
|
1995
1972
|
}
|
|
1996
1973
|
|
|
1997
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 };
|