@solidjs/signals 2.0.0-rc.8 → 2.0.0-rc.9
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 +1399 -285
- package/dist/dev.attribution.js +459 -307
- package/dist/dev.js +1864 -435
- package/dist/observe/affects.js +3 -1
- package/dist/observe/attribution.js +7 -1
- package/dist/observe/boundaries.js +209 -154
- package/dist/observe/core/action.js +18 -8
- package/dist/observe/core/async.js +220 -110
- package/dist/observe/core/attribution-costs.js +66 -0
- package/dist/observe/core/attribution-feedback.js +282 -0
- package/dist/observe/core/attribution-hooks.js +23 -1
- package/dist/observe/core/attribution-queries.js +28 -0
- package/dist/observe/core/attribution.js +262 -485
- package/dist/observe/core/constants.js +34 -1
- package/dist/observe/core/context.js +3 -3
- package/dist/observe/core/core.js +867 -367
- package/dist/observe/core/dev.js +78 -17
- package/dist/observe/core/effect.js +67 -51
- package/dist/observe/core/error-hooks.js +71 -0
- package/dist/observe/core/external.js +4 -4
- package/dist/observe/core/graph.js +37 -37
- package/dist/observe/core/heap.js +45 -45
- package/dist/observe/core/invariants.js +2 -0
- package/dist/observe/core/lanes.js +86 -49
- package/dist/observe/core/optimistic.js +242 -95
- package/dist/observe/core/owner.js +98 -84
- package/dist/observe/core/scheduler.js +543 -305
- package/dist/observe/core/verdict.js +247 -129
- package/dist/observe/index.js +7 -3
- package/dist/observe/map.js +126 -124
- package/dist/observe/signals.js +33 -17
- package/dist/observe/store/index.js +2 -0
- package/dist/observe/store/next/optimistic.js +141 -132
- package/dist/observe/store/next/projection.js +34 -21
- package/dist/observe/store/next/reconcile.js +58 -56
- package/dist/observe/store/next/store.js +260 -146
- package/dist/observe/store/store.js +5 -3
- package/dist/observe/store/utils.js +948 -135
- package/dist/prod/attribution.js +26 -17
- package/dist/prod/boundaries.js +128 -76
- package/dist/prod/core/action.js +16 -8
- package/dist/prod/core/async.js +251 -143
- package/dist/prod/core/constants.js +34 -1
- package/dist/prod/core/context.js +3 -3
- package/dist/prod/core/core.js +843 -347
- package/dist/prod/core/dev.js +17 -1
- package/dist/prod/core/effect.js +48 -34
- package/dist/prod/core/error-hooks.js +71 -0
- package/dist/prod/core/external.js +4 -4
- package/dist/prod/core/graph.js +37 -37
- package/dist/prod/core/heap.js +45 -45
- package/dist/prod/core/lanes.js +90 -53
- package/dist/prod/core/optimistic.js +247 -100
- package/dist/prod/core/owner.js +57 -45
- package/dist/prod/core/scheduler.js +543 -305
- package/dist/prod/core/verdict.js +245 -127
- package/dist/prod/index.js +7 -3
- package/dist/prod/map.js +112 -112
- package/dist/prod/signals.js +28 -12
- package/dist/prod/store/next/optimistic.js +135 -128
- package/dist/prod/store/next/projection.js +31 -20
- package/dist/prod/store/next/store.js +325 -252
- package/dist/prod/store/store.js +2 -2
- package/dist/prod/store/utils.js +946 -135
- package/dist/types/attribution.d.ts +7 -2
- package/dist/types/attribution.prod.d.ts +10 -1
- package/dist/types/boundaries.d.ts +10 -1
- package/dist/types/core/action.d.ts +12 -5
- package/dist/types/core/attribution-costs.d.ts +35 -0
- package/dist/types/core/attribution-feedback.d.ts +133 -0
- package/dist/types/core/attribution-hooks.d.ts +28 -3
- package/dist/types/core/attribution-queries.d.ts +10 -0
- package/dist/types/core/attribution.d.ts +51 -172
- package/dist/types/core/constants.d.ts +33 -0
- package/dist/types/core/core.d.ts +186 -5
- package/dist/types/core/dev.d.ts +129 -9
- package/dist/types/core/error-hooks.d.ts +71 -0
- package/dist/types/core/index.d.ts +3 -1
- package/dist/types/core/invariants.d.ts +4 -0
- package/dist/types/core/lanes.d.ts +31 -4
- package/dist/types/core/scheduler.d.ts +95 -2
- package/dist/types/core/types.d.ts +3 -0
- package/dist/types/index.d.ts +2 -2
- package/dist/types/signals.d.ts +8 -0
- package/dist/types/store/index.d.ts +2 -1
- package/dist/types/store/next/optimistic.d.ts +1 -1
- package/dist/types/store/next/store.d.ts +6 -5
- package/dist/types/store/next/target.d.ts +1 -1
- package/dist/types/store/utils.d.ts +177 -6
- package/package.json +1 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { unwrapOverride, $REFRESH,
|
|
1
|
+
import { unwrapOverride, $REFRESH, CONFIG_CHILDREN_FORBIDDEN, CONFIG_OWNED_WRITE, NOT_PENDING, CONFIG_OPTIMISTIC, STATUS_UNINITIALIZED, STATUS_ERROR, CONFIG_AUTHORITATIVE_READ } from "../../core/constants.js";
|
|
2
2
|
|
|
3
|
-
import { setSlotUnobserved, setSignal, isEqual, read, pendingCheckActive, latestReadActive, readNodeFast, READ_SLOW, signal, unlinkFirewallChild, ext, setLatestReadActive, prepareComputed, slotSignal, context } from "../../core/core.js";
|
|
3
|
+
import { setSlotUnobserved, setSignal, isEqual, read, hasActiveOverride, pendingCheckActive, visibleOverride, latestReadActive, readNodeFast, READ_SLOW, signal, unlinkFirewallChild, ext, ownsHold, setLatestReadActive, prepareComputed, slotSignal, serve, stale, recordStaleReplay, enterStagedRead, context } from "../../core/core.js";
|
|
4
4
|
|
|
5
|
-
import { projectionWriteActive, setProjectionWriteActive, activeTransition, schedule, currentTransition, setStoreCommitHook } from "../../core/scheduler.js";
|
|
5
|
+
import { projectionWriteActive, setProjectionWriteActive, activeTransition, schedule, currentTransition, deferSlotRelease, setStoreCommitHook } from "../../core/scheduler.js";
|
|
6
6
|
|
|
7
7
|
import "../../core/invariants.js";
|
|
8
8
|
|
|
@@ -121,11 +121,11 @@ function wrapNext(e, t = null, n = null, r = t?.fam ?? null) {
|
|
|
121
121
|
if (rawValuesUsed && isRawValue(e)) return e;
|
|
122
122
|
const i = lookupTarget(e, r);
|
|
123
123
|
if (i !== undefined) return i.px;
|
|
124
|
-
const
|
|
125
|
-
if (
|
|
124
|
+
const l = e[$TARGET];
|
|
125
|
+
if (l !== undefined && l.px === e) {
|
|
126
126
|
// Foreign-family proxies re-wrap into THIS family (writes stay isolated);
|
|
127
127
|
// same-family and plain-store proxies pass through.
|
|
128
|
-
if (r === null ||
|
|
128
|
+
if (r === null || l.fam === r) return e;
|
|
129
129
|
return createTarget(e, t, n, r).px;
|
|
130
130
|
}
|
|
131
131
|
return createTarget(e, t, n, r).px;
|
|
@@ -153,7 +153,7 @@ function wrapNext(e, t = null, n = null, r = t?.fam ?? null) {
|
|
|
153
153
|
// (privatization/adoption swap raw identity without changing the logical
|
|
154
154
|
// value — only changed leaves notify, R9).
|
|
155
155
|
const slotNodeEquals = function(e, t) {
|
|
156
|
-
return isEqual(e, t) || sameLogicalSlot(this.
|
|
156
|
+
return isEqual(e, t) || sameLogicalSlot(this.Wt, e, t);
|
|
157
157
|
};
|
|
158
158
|
|
|
159
159
|
// Shared slot-node unobserved handler (create-floor diet): registered once;
|
|
@@ -162,8 +162,13 @@ const slotNodeEquals = function(e, t) {
|
|
|
162
162
|
setSlotUnobserved(e => {
|
|
163
163
|
// A live affects() mark keeps the node addressable (sweep parity).
|
|
164
164
|
if (e.o?.t) return;
|
|
165
|
-
|
|
166
|
-
|
|
165
|
+
// An active override or a staged write is state only the node holds (an
|
|
166
|
+
// optimistic signal keeps its override whether or not anything reads it —
|
|
167
|
+
// store parity, posture-store-parity S7): defer the release to the flush
|
|
168
|
+
// that resolves it (the scheduler's transient-node sweep).
|
|
169
|
+
if (hasActiveOverride(e) || e.ve !== NOT_PENDING) return deferSlotRelease(e);
|
|
170
|
+
const t = e.Wt;
|
|
171
|
+
const n = e.qt;
|
|
167
172
|
if (t.n && t.n[n] === e) {
|
|
168
173
|
delete t.n[n];
|
|
169
174
|
t.nc--;
|
|
@@ -181,8 +186,8 @@ function getNode(e, t, n,
|
|
|
181
186
|
// callers), 0/1 = probed.
|
|
182
187
|
r = -1) {
|
|
183
188
|
const i = e.n ??= Object.create(null);
|
|
184
|
-
let
|
|
185
|
-
if (
|
|
189
|
+
let l = i[t];
|
|
190
|
+
if (l === undefined) {
|
|
186
191
|
// Born holding (#3330 store twin): a key first read while a live
|
|
187
192
|
// transaction holds an ADOPTION on this target (adoptPB's `ht`) is
|
|
188
193
|
// created as if it had existed when the hold was notified — the adopted
|
|
@@ -191,11 +196,15 @@ r = -1) {
|
|
|
191
196
|
// (stageHeldKey). Its held-adoption notification (stageHeldAdoptions)
|
|
192
197
|
// ran before the node existed and the drain has nothing left to say.
|
|
193
198
|
// Without this the node was born from whichever view its first reader
|
|
194
|
-
// saw and never learned the other.
|
|
195
|
-
// write to an unobserved key
|
|
196
|
-
//
|
|
197
|
-
|
|
198
|
-
|
|
199
|
+
// saw and never learned the other. Two kinds of hold, one rule (#3336):
|
|
200
|
+
// - a held FOLD (pb): a setter's write to an unobserved key landed only
|
|
201
|
+
// in the pending backing; committed is `v[key]`, staged is `pb[key]`
|
|
202
|
+
// (undefined for a deleted key);
|
|
203
|
+
// - a held ADOPTION (ht): the adopted value already swapped into `v`;
|
|
204
|
+
// committed is the held view `hv[key]`, staged is `v[key]`.
|
|
205
|
+
const o = heldFoldTransition(e);
|
|
206
|
+
let f = heldAdoptionTransition(e);
|
|
207
|
+
if (f !== null) n = e.hv[t]; else if ((f = o) !== null) n = e.v[t];
|
|
199
208
|
// Create-floor diet: slotSignal bakes the whole node into one literal —
|
|
200
209
|
// no options object, no equals/unobserved closures, no NodeExtension,
|
|
201
210
|
// no post-construction expandos (acc + the wrap cache px/pxv are
|
|
@@ -206,7 +215,7 @@ r = -1) {
|
|
|
206
215
|
// notification machinery. Projection nodes carry the projection
|
|
207
216
|
// computed as their firewall: reads through them link the derive's
|
|
208
217
|
// status/lifecycle (§7b).
|
|
209
|
-
const
|
|
218
|
+
const s = l = slotSignal(n, slotNodeEquals, e, t,
|
|
210
219
|
// Accessor-ness resolved ONCE per node (no per-object descriptor
|
|
211
220
|
// scan on reads): accessor keys serve through Reflect.get with the
|
|
212
221
|
// proxy receiver.
|
|
@@ -214,25 +223,25 @@ r = -1) {
|
|
|
214
223
|
// Optimistic families: arm the override slot — setSignal routes armed
|
|
215
224
|
// nodes through the core engine (lanes, ownership, reverts all native).
|
|
216
225
|
if (e.fam?.opt) {
|
|
217
|
-
ext(
|
|
218
|
-
|
|
226
|
+
ext(s).Ce = NOT_PENDING;
|
|
227
|
+
s.T |= CONFIG_OPTIMISTIC;
|
|
219
228
|
}
|
|
220
229
|
// A node born inside a live mark's identity scope inherits the mark
|
|
221
230
|
// (the declaration walk could only cover nodes existing then).
|
|
222
|
-
if (t !== $AFFECTS && affectsScopesLive()) inheritAffectsMarks(
|
|
223
|
-
if (
|
|
224
|
-
i[t] =
|
|
231
|
+
if (t !== $AFFECTS && affectsScopesLive()) inheritAffectsMarks(s, e.v, t);
|
|
232
|
+
if (f !== null) stageHeldKey(s, o !== null ? e.del !== null && e.del.has(t) ? undefined : e.pb[t] : e.v[t], f);
|
|
233
|
+
i[t] = l;
|
|
225
234
|
e.nc++;
|
|
226
235
|
markDescendants(e);
|
|
227
236
|
}
|
|
228
|
-
return
|
|
237
|
+
return l;
|
|
229
238
|
}
|
|
230
239
|
|
|
231
240
|
/** The live transaction holding an adoption on `target` (adoptPB's `ht`;
|
|
232
241
|
* a latest()-pull PLAIN_HOLD is not a transaction), else null. */ function heldAdoptionTransition(e) {
|
|
233
242
|
if (e.ht === null || e.ht === PLAIN_HOLD || heldMaskView(e) === null) return null;
|
|
234
243
|
const t = currentTransition(e.ht);
|
|
235
|
-
return t.
|
|
244
|
+
return t.Tt === false ? t : null;
|
|
236
245
|
}
|
|
237
246
|
|
|
238
247
|
/**
|
|
@@ -248,11 +257,54 @@ r = -1) {
|
|
|
248
257
|
* setSignal: it is not a new write (it staged with the adoption's batch) and
|
|
249
258
|
* it walks no subscriber (the node has none yet). Transition-stamped now, as
|
|
250
259
|
* `runFolded` does — no parked-flush pass will stamp it.
|
|
251
|
-
*/
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
e.
|
|
255
|
-
|
|
260
|
+
*/
|
|
261
|
+
/** The live transaction holding `target`'s pending backing (the #3089
|
|
262
|
+
* write-time stamp, resolved through merges), else null. */ function liveFoldTransition(e) {
|
|
263
|
+
if (e.pb === null) return null;
|
|
264
|
+
const t = foldBatches.get(e);
|
|
265
|
+
if (t === undefined) return null;
|
|
266
|
+
const n = currentTransition(t);
|
|
267
|
+
return n.Tt === false ? n : null;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/** liveFoldTransition for node materialization (stageHeldKey). Inside the
|
|
271
|
+
* draft the backing is the setter's working copy, not a flushed hold — its
|
|
272
|
+
* nodes take their writes at setter exit (notifyWrites). Optimistic families
|
|
273
|
+
* hold at the backing: tentative writes are node overrides over a discarded
|
|
274
|
+
* clone, and a truth-staged landing is masked from ordinary readers by
|
|
275
|
+
* heldTruthMasked — neither is a plain staged write to mirror. Chained
|
|
276
|
+
* backings serve the inner store's live value, never a node value. */ function heldFoldTransition(e) {
|
|
277
|
+
if (e.ch || e.fam?.opt === true || inDraft(e)) return null;
|
|
278
|
+
return liveFoldTransition(e);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Rule 1 at the backing, the hold half (core serve()'s stale-of-foreign and
|
|
283
|
+
* A29 arms, for a container instead of a node): given the transaction
|
|
284
|
+
* holding what a reader `c` (a pass; callers serve context-free readers the
|
|
285
|
+
* committed container themselves) is about to be served, is the STAGED
|
|
286
|
+
* container its to see? Its own hold, or none — yes. A foreign hold — a
|
|
287
|
+
* stale pass (render effect) keeps the committed frame and is recorded for
|
|
288
|
+
* replay at the hold's commit (recordStaleReplay, A15 / A26); a deriving
|
|
289
|
+
* pass takes the staged world and enters the transaction (enterStagedRead,
|
|
290
|
+
* A29). Shared by both hold kinds: a setter's fold (committed `v`, staged
|
|
291
|
+
* `pb`, the write-time stamp) and an adoption under a transaction
|
|
292
|
+
* (committed = the held view `hv`, staged = the adopted `v`, #3074).
|
|
293
|
+
*/ function holdVisible(e, t) {
|
|
294
|
+
if (e === null || ownsHold(e)) return true;
|
|
295
|
+
if (stale) {
|
|
296
|
+
recordStaleReplay(e, t);
|
|
297
|
+
return false;
|
|
298
|
+
}
|
|
299
|
+
enterStagedRead(null, e);
|
|
300
|
+
return true;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
function stageHeldKey(e, t, n) {
|
|
304
|
+
if (slotNodeEquals.call(e, e.Qe, t)) return;
|
|
305
|
+
e.ve = t;
|
|
306
|
+
e.Ge = n;
|
|
307
|
+
n.Ot.push(e);
|
|
256
308
|
}
|
|
257
309
|
|
|
258
310
|
function sameLogicalSlot(e, t, n) {
|
|
@@ -265,22 +317,28 @@ function getHasNode(e, t, n) {
|
|
|
265
317
|
const r = e.h ??= Object.create(null);
|
|
266
318
|
let i = r[t];
|
|
267
319
|
if (i === undefined) {
|
|
268
|
-
const
|
|
320
|
+
const l = i = signal(n, {
|
|
269
321
|
equals: isEqual,
|
|
270
322
|
unobserved() {
|
|
271
|
-
if (
|
|
272
|
-
|
|
323
|
+
if (l.o?.t) return;
|
|
324
|
+
// The structural twin of the value slot's rule (setSlotUnobserved,
|
|
325
|
+
// S7): an optimistic add/delete lives on this presence node as its
|
|
326
|
+
// override — releasing it with the override on would let `in`,
|
|
327
|
+
// `Object.keys` and descriptors fall back to committed structure
|
|
328
|
+
// while the action is live. Defer to the flush that resolves it.
|
|
329
|
+
if (hasActiveOverride(l) || l.ve !== NOT_PENDING) return deferSlotRelease(l);
|
|
330
|
+
if (e.h && e.h[t] === l) {
|
|
273
331
|
delete e.h[t];
|
|
274
|
-
unlinkFirewallChild(
|
|
332
|
+
unlinkFirewallChild(l);
|
|
275
333
|
}
|
|
276
334
|
}
|
|
277
335
|
}, e.fam?.node ?? undefined);
|
|
278
|
-
|
|
336
|
+
l.T |= CONFIG_OWNED_WRITE;
|
|
279
337
|
if (e.fam?.opt) {
|
|
280
|
-
ext(
|
|
281
|
-
|
|
338
|
+
ext(l).Ce = NOT_PENDING;
|
|
339
|
+
l.T |= CONFIG_OPTIMISTIC;
|
|
282
340
|
}
|
|
283
|
-
if (affectsScopesLive()) inheritAffectsMarks(
|
|
341
|
+
if (affectsScopesLive()) inheritAffectsMarks(l, e.v, t);
|
|
284
342
|
r[t] = i;
|
|
285
343
|
markDescendants(e);
|
|
286
344
|
}
|
|
@@ -301,7 +359,7 @@ function getKeySetNode(e) {
|
|
|
301
359
|
}, e.fam?.node ?? undefined);
|
|
302
360
|
n.T |= CONFIG_OWNED_WRITE;
|
|
303
361
|
if (e.fam?.opt) {
|
|
304
|
-
ext(n).
|
|
362
|
+
ext(n).Ce = NOT_PENDING;
|
|
305
363
|
n.T |= CONFIG_OPTIMISTIC;
|
|
306
364
|
}
|
|
307
365
|
e.k = t;
|
|
@@ -324,7 +382,7 @@ function getDeepNode(e) {
|
|
|
324
382
|
}, e.fam?.node ?? undefined);
|
|
325
383
|
n.T |= CONFIG_OWNED_WRITE;
|
|
326
384
|
if (e.fam?.opt) {
|
|
327
|
-
ext(n).
|
|
385
|
+
ext(n).Ce = NOT_PENDING;
|
|
328
386
|
n.T |= CONFIG_OPTIMISTIC;
|
|
329
387
|
}
|
|
330
388
|
if (affectsScopesLive()) inheritAffectsMarks(n, e.v, $TRACK);
|
|
@@ -486,14 +544,14 @@ function ensurePB(e) {
|
|
|
486
544
|
if (n !== null) {
|
|
487
545
|
for (const e of Reflect.ownKeys(n)) {
|
|
488
546
|
const r = n[e];
|
|
489
|
-
if (hasActiveOverride(r)) t[e] = unwrapOverride(r.o?.
|
|
547
|
+
if (hasActiveOverride(r)) t[e] = unwrapOverride(r.o?.Ce);
|
|
490
548
|
}
|
|
491
549
|
}
|
|
492
550
|
const r = e.h;
|
|
493
551
|
if (r !== null) {
|
|
494
552
|
for (const e of Reflect.ownKeys(r)) {
|
|
495
553
|
const n = r[e];
|
|
496
|
-
if (hasActiveOverride(n) && !unwrapOverride(n.o?.
|
|
554
|
+
if (hasActiveOverride(n) && !unwrapOverride(n.o?.Ce)) delete t[e];
|
|
497
555
|
}
|
|
498
556
|
}
|
|
499
557
|
}
|
|
@@ -517,7 +575,7 @@ function ensurePB(e) {
|
|
|
517
575
|
* foldHeld's node stamps). */ function heldMaskView(e) {
|
|
518
576
|
const t = e.ht;
|
|
519
577
|
if (t === null) return null;
|
|
520
|
-
if (t !== PLAIN_HOLD && currentTransition(t)?.
|
|
578
|
+
if (t !== PLAIN_HOLD && currentTransition(t)?.Tt === true) return e.ht = e.hv = null;
|
|
521
579
|
return e.hv;
|
|
522
580
|
}
|
|
523
581
|
|
|
@@ -721,7 +779,7 @@ function drainFolds() {
|
|
|
721
779
|
// keys; observed keys also hit the pending-node held check below).
|
|
722
780
|
const e = foldBatches.get(t);
|
|
723
781
|
if (e !== undefined) {
|
|
724
|
-
if (currentTransition(e).
|
|
782
|
+
if (currentTransition(e).Tt === false) {
|
|
725
783
|
foldOlds.set(t, n);
|
|
726
784
|
continue;
|
|
727
785
|
}
|
|
@@ -733,8 +791,8 @@ function drainFolds() {
|
|
|
733
791
|
// node (transition-held) re-queues the target for the settling flush.
|
|
734
792
|
let r = false;
|
|
735
793
|
const i = t.pb;
|
|
736
|
-
const
|
|
737
|
-
if (
|
|
794
|
+
const l = t.n;
|
|
795
|
+
if (l !== null) {
|
|
738
796
|
// Only written keys can hold (their nodes took the setSignal); the
|
|
739
797
|
// wk bound keeps this O(written) — see notifyWrites. Same fallback
|
|
740
798
|
// rules as the notify (WK_ALL / accessors / non-plain prototypes).
|
|
@@ -742,10 +800,10 @@ function drainFolds() {
|
|
|
742
800
|
const n = e === null || e === WK_ALL || t.a === true ||
|
|
743
801
|
// Overlay pbs chain to the COMMITTED object (#3044) — plainness is
|
|
744
802
|
// the committed container's prototype, not the overlay's.
|
|
745
|
-
!plainProto(t.ovl ? t.v : i) ? Reflect.ownKeys(
|
|
803
|
+
!plainProto(t.ovl ? t.v : i) ? Reflect.ownKeys(l) : e;
|
|
746
804
|
for (const e of n) {
|
|
747
|
-
const t =
|
|
748
|
-
if (t !== undefined && t.
|
|
805
|
+
const t = l[e];
|
|
806
|
+
if (t !== undefined && t.ve !== NOT_PENDING) {
|
|
749
807
|
r = true;
|
|
750
808
|
break;
|
|
751
809
|
}
|
|
@@ -887,20 +945,20 @@ function drainFolds() {
|
|
|
887
945
|
// bound never engages for overlay writes (every plain-object setter batch
|
|
888
946
|
// would full-scan: the exact selection-map workload wk exists for; jf
|
|
889
947
|
// `select` regressed 2x on this).
|
|
890
|
-
const
|
|
948
|
+
const l = i === WK_ALL || e.a === true || !plainProto(e.ovl ? e.v : t) ? null : i;
|
|
891
949
|
if (r !== null) {
|
|
892
|
-
const i =
|
|
893
|
-
for (const
|
|
894
|
-
const i = r[
|
|
950
|
+
const i = l ?? Reflect.ownKeys(r);
|
|
951
|
+
for (const l of i) {
|
|
952
|
+
const i = r[l];
|
|
895
953
|
if (i === undefined) continue;
|
|
896
954
|
// Per-key accessor handling: the node's cached flag plus ONE getter
|
|
897
955
|
// probe on the incoming side (getters arriving via merge/adoption).
|
|
898
956
|
// Setter-only props read as data (value undefined) so lookupSetter is
|
|
899
957
|
// not consulted on this hot path; prototype getters never own nodes.
|
|
900
|
-
if (i.acc === true || hasOwn.call(t,
|
|
901
|
-
i.acc = isOwnAccessor(t,
|
|
902
|
-
const e = Object.getOwnPropertyDescriptor(n,
|
|
903
|
-
const r = Object.getOwnPropertyDescriptor(t,
|
|
958
|
+
if (i.acc === true || hasOwn.call(t, l) && lookupGetter.call(t, l) !== undefined) {
|
|
959
|
+
i.acc = isOwnAccessor(t, l);
|
|
960
|
+
const e = Object.getOwnPropertyDescriptor(n, l);
|
|
961
|
+
const r = Object.getOwnPropertyDescriptor(t, l);
|
|
904
962
|
if (e && (e.get || e.set) || r && (r.get || r.set)) {
|
|
905
963
|
if (e?.get !== r?.get || e?.set !== r?.set || e?.value !== r?.value) setSignal(i, () => FORCE);
|
|
906
964
|
continue;
|
|
@@ -912,26 +970,26 @@ function drainFolds() {
|
|
|
912
970
|
// projection recompute can run before the prior fold commits) — the
|
|
913
971
|
// node's OWN current value is the true old side, and setSignal's
|
|
914
972
|
// internal equality already checks exactly that.
|
|
915
|
-
const
|
|
916
|
-
setSignal(i, () =>
|
|
973
|
+
const o = e.del !== null && e.del.has(l) ? undefined : t[l];
|
|
974
|
+
setSignal(i, () => o);
|
|
917
975
|
}
|
|
918
976
|
}
|
|
919
|
-
const
|
|
920
|
-
if (
|
|
921
|
-
const n =
|
|
977
|
+
const o = e.h;
|
|
978
|
+
if (o !== null) {
|
|
979
|
+
const n = l ?? Reflect.ownKeys(o);
|
|
922
980
|
for (const r of n) {
|
|
923
|
-
const n =
|
|
981
|
+
const n = o[r];
|
|
924
982
|
if (n !== undefined) setSignal(n, r in t && !(e.del !== null && e.del.has(r)));
|
|
925
983
|
}
|
|
926
984
|
}
|
|
927
985
|
// Deep-witness (dk): setter writes must notify a deep() subscriber even on
|
|
928
986
|
// keys with no node. O(written/pb keys) equality only when a witness exists.
|
|
929
987
|
if (e.dk !== null) {
|
|
930
|
-
if (e.del !== null && e.del.size !== 0) bumpDeep(e); else for (const r of
|
|
988
|
+
if (e.del !== null && e.del.size !== 0) bumpDeep(e); else for (const r of l ?? Reflect.ownKeys(t)) {
|
|
931
989
|
if (r === $OWNER) continue;
|
|
932
990
|
const i = t[r];
|
|
933
|
-
const
|
|
934
|
-
if (i !== null && typeof i === "object" ? !targetsEqual(
|
|
991
|
+
const l = n[r];
|
|
992
|
+
if (i !== null && typeof i === "object" ? !targetsEqual(l, i) : !isEqual(l, i)) {
|
|
935
993
|
bumpDeep(e);
|
|
936
994
|
break;
|
|
937
995
|
}
|
|
@@ -1041,23 +1099,23 @@ i = true) {
|
|
|
1041
1099
|
if (e.acc === true || i && hasOwn.call(r, t) && lookupGetter.call(r, t) !== undefined) {
|
|
1042
1100
|
e.acc = isOwnAccessor(r, t);
|
|
1043
1101
|
const i = Object.getOwnPropertyDescriptor(n, t);
|
|
1044
|
-
const
|
|
1045
|
-
if (i && (i.get || i.set) ||
|
|
1102
|
+
const l = Object.getOwnPropertyDescriptor(r, t);
|
|
1103
|
+
if (i && (i.get || i.set) || l && (l.get || l.set)) {
|
|
1046
1104
|
// Accessor involved: never invoke; force-notify on shape change so
|
|
1047
1105
|
// subscribers re-read (and re-track) through the trap.
|
|
1048
|
-
if (i?.get !==
|
|
1106
|
+
if (i?.get !== l?.get || i?.set !== l?.set || i?.value !== l?.value) setSignal(e, () => FORCE);
|
|
1049
1107
|
return;
|
|
1050
1108
|
}
|
|
1051
|
-
const
|
|
1052
|
-
const f =
|
|
1053
|
-
if (!isEqual(
|
|
1109
|
+
const o = i?.value;
|
|
1110
|
+
const f = l?.value;
|
|
1111
|
+
if (!isEqual(o, f) && !targetsEqual(o, f)) setSignal(e, typeof f === "function" ? () => f : f);
|
|
1054
1112
|
} else {
|
|
1055
1113
|
const i = n[t];
|
|
1056
|
-
const
|
|
1114
|
+
const l = r[t];
|
|
1057
1115
|
// Direct value write when not a function (setSignal treats functions as
|
|
1058
1116
|
// updaters) — saves a closure allocation per changed key on the fold
|
|
1059
1117
|
// hot path.
|
|
1060
|
-
if (!isEqual(i,
|
|
1118
|
+
if (!isEqual(i, l) && !targetsEqual(i, l)) setSignal(e, typeof l === "function" ? () => l : l);
|
|
1061
1119
|
}
|
|
1062
1120
|
}
|
|
1063
1121
|
|
|
@@ -1069,9 +1127,9 @@ i = true) {
|
|
|
1069
1127
|
/** Fused-walk per-key notification with values already in hand: the caller
|
|
1070
1128
|
* fetched both sides and handled the identity skip; this applies the
|
|
1071
1129
|
* accessor branch (cached flag only — reconcile channel) or the plain
|
|
1072
|
-
* equality/identity-gated write. */ function notifyKeyValue(e, t, n, r, i,
|
|
1130
|
+
* equality/identity-gated write. */ function notifyKeyValue(e, t, n, r, i, l) {
|
|
1073
1131
|
if (e.acc === true) {
|
|
1074
|
-
notifyKeyDiff(e, t, i,
|
|
1132
|
+
notifyKeyDiff(e, t, i, l, false);
|
|
1075
1133
|
return;
|
|
1076
1134
|
}
|
|
1077
1135
|
// The pre-compare is NOT redundant with the node's equals: setSignal parks
|
|
@@ -1200,22 +1258,12 @@ const UNSAFE_KEYS = new Set([ "__proto__", "prototype", "constructor" ]);
|
|
|
1200
1258
|
* observer) decides pending visibility, with Roots resolving to their parent
|
|
1201
1259
|
* computed (#2687 — untracked reads inside mapArray Roots see in-flight
|
|
1202
1260
|
* values mid-flush). CHILDREN_FORBIDDEN execution scopes (createTrackedEffect
|
|
1203
|
-
* / onSettled callbacks) get COMMITTED visibility (#3006), same as core. */
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
return t != null && !(t.T & CONFIG_CHILDREN_FORBIDDEN);
|
|
1208
|
-
}
|
|
1209
|
-
|
|
1210
|
-
/** CHILDREN_FORBIDDEN execution scope (createTrackedEffect / onSettled
|
|
1211
|
-
* callbacks). Distinct from context-free: these scopes get committed
|
|
1212
|
-
* visibility even against a projection's authoritative-elect pending
|
|
1213
|
-
* backing (#3082) — parity with signals, where core read() serves
|
|
1214
|
-
* committed to them regardless of staged writes. */ function inForbiddenScope() {
|
|
1261
|
+
* / onSettled callbacks) get COMMITTED visibility (#3006), same as core. */
|
|
1262
|
+
/** Core read()'s reader: the current computation, a root reading as its
|
|
1263
|
+
* parent computed (`context` persists under untrack — an untracked read
|
|
1264
|
+
* inside an effect is still that effect's read). */ function readerContext() {
|
|
1215
1265
|
const e = getOwner();
|
|
1216
|
-
|
|
1217
|
-
const t = e.gt ? e.bt : e;
|
|
1218
|
-
return t != null && !!(t.T & CONFIG_CHILDREN_FORBIDDEN);
|
|
1266
|
+
return e === null ? null : e.xt ? e.Qt ?? null : e;
|
|
1219
1267
|
}
|
|
1220
1268
|
|
|
1221
1269
|
/** A pending fold is transition-held when any written node's parked value is
|
|
@@ -1225,19 +1273,24 @@ const UNSAFE_KEYS = new Set([ "__proto__", "prototype", "constructor" ]);
|
|
|
1225
1273
|
if (t === null) return false;
|
|
1226
1274
|
for (const e of Reflect.ownKeys(t)) {
|
|
1227
1275
|
const n = t[e];
|
|
1228
|
-
if (n.
|
|
1276
|
+
if (n.ve !== NOT_PENDING && n.Ge != null && n.Ge.Tt !== true) return true;
|
|
1229
1277
|
}
|
|
1230
1278
|
return false;
|
|
1231
1279
|
}
|
|
1232
1280
|
|
|
1233
1281
|
function readSource(e) {
|
|
1234
|
-
//
|
|
1235
|
-
// pre-hold committed
|
|
1236
|
-
// readers —
|
|
1237
|
-
//
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1282
|
+
// Adoption hold first (#3074): an adoption staged under a live transaction
|
|
1283
|
+
// (or a latest()-pull, PLAIN_HOLD) serves the pre-hold committed view to
|
|
1284
|
+
// committed-visibility readers — context-free and children-forbidden ones,
|
|
1285
|
+
// and stale passes off a foreign hold. Drafts, write-override and latest()
|
|
1286
|
+
// see the adopted backing.
|
|
1287
|
+
const t = e.ht;
|
|
1288
|
+
if (t !== null && !latestReadActive && !inDraft(e) && !getWriteOverride()) {
|
|
1289
|
+
const n = heldMaskView(e);
|
|
1290
|
+
if (n !== null) {
|
|
1291
|
+
const e = readerContext();
|
|
1292
|
+
if (e === null || e.T & CONFIG_CHILDREN_FORBIDDEN || !holdVisible(t === PLAIN_HOLD ? null : currentTransition(t), e)) return n;
|
|
1293
|
+
}
|
|
1241
1294
|
}
|
|
1242
1295
|
return pendingBackingVisible(e, false) ? e.pb : e.v;
|
|
1243
1296
|
}
|
|
@@ -1257,21 +1310,28 @@ function readSource(e) {
|
|
|
1257
1310
|
* ordinary pending staging regardless of owner context (the documented
|
|
1258
1311
|
* divergence from context-free per-key reads) — but never through a hold:
|
|
1259
1312
|
* held truth stays masked exactly as it is for per-key readers. */ function pendingBackingVisible(e, t) {
|
|
1260
|
-
|
|
1261
|
-
//
|
|
1262
|
-
|
|
1263
|
-
//
|
|
1264
|
-
//
|
|
1265
|
-
//
|
|
1266
|
-
//
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1313
|
+
if (e.pb === null) return false;
|
|
1314
|
+
// The writer's own channels compose on the pending backing regardless.
|
|
1315
|
+
if (inDraft(e) || getWriteOverride()) return true;
|
|
1316
|
+
// HELD truth on an optimistic family (#3164 fold) is masked from ordinary
|
|
1317
|
+
// readers until the transaction's reveal (the backing-level twin of core
|
|
1318
|
+
// serve()'s CONFIG_HELD_TRUTH arm; authoritative postures and latest()
|
|
1319
|
+
// tunnel through inside heldTruthMasked).
|
|
1320
|
+
if (heldTruthMasked(e)) return false;
|
|
1321
|
+
const n = readerContext();
|
|
1322
|
+
if (n === null || n.T & CONFIG_CHILDREN_FORBIDDEN) {
|
|
1323
|
+
// No pass, or a children-forbidden one: the committed frame (A32) —
|
|
1324
|
+
// except the speculative peek (deep()/snapshot()), which sees ordinary
|
|
1325
|
+
// pending staging but never through a live foreign hold, and a
|
|
1326
|
+
// projection's pending backing, authoritative-elect for context-free
|
|
1327
|
+
// readers UNLESS a transition holds the node commits (downstream async
|
|
1328
|
+
// hold — stale committed is the contract; the write-time stamp covers
|
|
1329
|
+
// keys with no node, #3336) or the scope is children-forbidden (#3082).
|
|
1330
|
+
const r = liveFoldTransition(e);
|
|
1331
|
+
if (t) return r === null || ownsHold(r);
|
|
1332
|
+
return e.fam !== null && n === null && !foldHeld(e) && r === null;
|
|
1333
|
+
}
|
|
1334
|
+
return holdVisible(liveFoldTransition(e), n);
|
|
1275
1335
|
}
|
|
1276
1336
|
|
|
1277
1337
|
/** #3164 fold: HELD truth on an optimistic family — a pending backing
|
|
@@ -1316,11 +1376,6 @@ function isOwnAccessor(e, t) {
|
|
|
1316
1376
|
}
|
|
1317
1377
|
}
|
|
1318
1378
|
|
|
1319
|
-
/** Active optimistic override on an armed node (armed slot idles at
|
|
1320
|
-
* NOT_PENDING; undefined = unarmed plain node). */ function hasActiveOverride(e) {
|
|
1321
|
-
return e.o?.be !== undefined && e.o?.be !== NOT_PENDING;
|
|
1322
|
-
}
|
|
1323
|
-
|
|
1324
1379
|
/** The reading computation is until()'s authoritative-view predicate — same
|
|
1325
1380
|
* source of truth as core read()'s A17 carve-out (`context`, which persists
|
|
1326
1381
|
* under untrack). optimisticView()'s composition gate consults exactly this:
|
|
@@ -1348,19 +1403,17 @@ function isOwnAccessor(e, t) {
|
|
|
1348
1403
|
* reader that forced it (backing commits eagerly; node values fold at flush).
|
|
1349
1404
|
* FORCE sentinels never surface (they only bump subscribers of accessor
|
|
1350
1405
|
* keys, which are served by the trap, not the node). */ function nodeValue(e, t) {
|
|
1351
|
-
//
|
|
1352
|
-
//
|
|
1353
|
-
//
|
|
1354
|
-
//
|
|
1355
|
-
//
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
//
|
|
1359
|
-
//
|
|
1360
|
-
//
|
|
1361
|
-
|
|
1362
|
-
// exempted by the leading arm above).
|
|
1363
|
-
(inOwnerContext() || authoritativeServe()) && !(e.T & CONFIG_HELD_TRUTH && !authoritativeServe())) ? e.Ge : t;
|
|
1406
|
+
// Store-only tunnels, ahead of Rule 1: truth authors (authoritativeServe —
|
|
1407
|
+
// the projection derive's draft, the write-override continuation) see
|
|
1408
|
+
// staged truth and never an override; latest() reaching this untracked
|
|
1409
|
+
// path for a store key sees the in-flight parked value like an
|
|
1410
|
+
// owner-context reader does (#3075), the visible override first.
|
|
1411
|
+
let n;
|
|
1412
|
+
if (authoritativeServe()) n = e.ve !== NOT_PENDING ? e.ve : t; else if (latestReadActive) n = visibleOverride(e) ? unwrapOverride(e.o?.Ce) : e.ve !== NOT_PENDING ? e.ve : t;
|
|
1413
|
+
// Otherwise the one slow selection core read() uses (serve): override,
|
|
1414
|
+
// lane gate, A28, readerSeesCommitted / A29 — with the BACKING as the
|
|
1415
|
+
// committed value (single-home rule, O6).
|
|
1416
|
+
else n = serve(e, readerContext(), e.Te || e, t);
|
|
1364
1417
|
return n === FORCE ? t : n;
|
|
1365
1418
|
}
|
|
1366
1419
|
|
|
@@ -1391,15 +1444,15 @@ function isOwnAccessor(e, t) {
|
|
|
1391
1444
|
* holds, lanes ride the node); backing otherwise. Chained backings (§7b: the
|
|
1392
1445
|
* backing IS another store's proxy) serve the read-through value — the outer
|
|
1393
1446
|
* node is linked only for adoption-swap notification, its value never
|
|
1394
|
-
* shadows the live chain. */ function serveDataKey(e, t, n, r, i,
|
|
1395
|
-
const
|
|
1447
|
+
* shadows the live chain. */ function serveDataKey(e, t, n, r, i, l = -1) {
|
|
1448
|
+
const o = e.ch && r === e.v;
|
|
1396
1449
|
let f = n;
|
|
1397
1450
|
// §6: on optimistic arrays LENGTH IS A VIEW, not a node value — one home
|
|
1398
1451
|
// (backing ± presence overrides) for both length and indices makes torn
|
|
1399
1452
|
// iteration impossible (a length node's value rides different visibility
|
|
1400
1453
|
// rails than index overrides mid-settle). The node still carries
|
|
1401
1454
|
// subscriptions; its value is never served here.
|
|
1402
|
-
if (t === "length" && e.fam?.opt === true && !
|
|
1455
|
+
if (t === "length" && e.fam?.opt === true && !o && Array.isArray(r)) {
|
|
1403
1456
|
if (!inDraft(e)) {
|
|
1404
1457
|
const r = e.n?.length;
|
|
1405
1458
|
if (r !== undefined) {
|
|
@@ -1411,7 +1464,7 @@ function isOwnAccessor(e, t) {
|
|
|
1411
1464
|
// Truth authors read the backing's own length — an optimistic row from
|
|
1412
1465
|
// the caller's transaction must not shift where the author's next write
|
|
1413
1466
|
// lands (#3108).
|
|
1414
|
-
return (authoritativeServe() ? r : optHooks.optimisticView(e, r)).length;
|
|
1467
|
+
return (authoritativeServe() ? r : optHooks.optimisticView(e, r, inDraft(e))).length;
|
|
1415
1468
|
}
|
|
1416
1469
|
if (inDraft(e)) {
|
|
1417
1470
|
// Optimistic drafts before their first write have no pending backing yet;
|
|
@@ -1421,31 +1474,31 @@ function isOwnAccessor(e, t) {
|
|
|
1421
1474
|
// seeding rule, applied to the read side (#3108).
|
|
1422
1475
|
if (e.fam?.opt && draftSeesOverrides(e) && !authoritativeServe()) {
|
|
1423
1476
|
const n = e.n?.[t];
|
|
1424
|
-
if (n !== undefined && hasActiveOverride(n)) f = unwrapOverride(n.o?.
|
|
1477
|
+
if (n !== undefined && hasActiveOverride(n)) f = unwrapOverride(n.o?.Ce);
|
|
1425
1478
|
}
|
|
1426
1479
|
} else {
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1480
|
+
// §7b: a lane value on the outer node SHADOWS read-through — an active
|
|
1481
|
+
// override pierces the chained gate; otherwise chained backings always
|
|
1482
|
+
// serve the live inner value.
|
|
1483
|
+
if (getObserver() !== null) {
|
|
1484
|
+
// First tracked read: create + link (the wrap-cache branch below
|
|
1485
|
+
// populates px/pxv so read #2 skips wrapNext, slice 2). The value is
|
|
1486
|
+
// served THROUGH the node from this read on — a node born under a held
|
|
1487
|
+
// fold carries the hold (getNode, #3336), and the backing it was read
|
|
1488
|
+
// from does not.
|
|
1489
|
+
if (i === undefined) i = getNode(e, t, n, l);
|
|
1490
|
+
// read()'s plain-signal fast path hoisted over the call (legacy trap
|
|
1491
|
+
// parity): READ_SLOW = a global read window or non-plain node.
|
|
1492
|
+
let r = readNodeFast(i);
|
|
1493
|
+
if (r === READ_SLOW) r = read(i);
|
|
1494
|
+
if (!o || hasActiveOverride(i)) f = r === FORCE ? n : r;
|
|
1495
|
+
} else if (i !== undefined && (!o || hasActiveOverride(i))) {
|
|
1496
|
+
f = nodeValue(i, n);
|
|
1444
1497
|
}
|
|
1445
1498
|
}
|
|
1446
1499
|
// Shallow stores serve data raw; store-proxy slots get boundary wrappers.
|
|
1447
1500
|
if (e.s) return serveShallow(e, t, f);
|
|
1448
|
-
if (e.ch && !
|
|
1501
|
+
if (e.ch && !o && f !== null && typeof f === "object" && f[$TARGET] === undefined) f = resolveChainedRaw(e, t, f);
|
|
1449
1502
|
if (i !== undefined) {
|
|
1450
1503
|
// Wrap cache (see getNode): only wrappables are ever cached, so a hit
|
|
1451
1504
|
// skips isWrappable too — pointer-compare replaces both checks.
|
|
@@ -1581,18 +1634,18 @@ const traps = {
|
|
|
1581
1634
|
// node creation downstream reuses it instead of re-scanning the
|
|
1582
1635
|
// descriptor, but only when the probed object IS the one getNode would
|
|
1583
1636
|
// scan (pb ?? v).
|
|
1584
|
-
let
|
|
1637
|
+
let l = -1;
|
|
1585
1638
|
{
|
|
1586
|
-
let
|
|
1587
|
-
if (i !== undefined)
|
|
1588
|
-
|
|
1589
|
-
if (r === (e.pb ?? e.v))
|
|
1590
|
-
} else
|
|
1591
|
-
if (
|
|
1592
|
-
if (!inDraft(e) && getObserver() !== null) read(i ?? getNode(e, t, undefined,
|
|
1593
|
-
const
|
|
1594
|
-
if (e.s) return serveShallow(e, t,
|
|
1595
|
-
return isWrappable(
|
|
1639
|
+
let o;
|
|
1640
|
+
if (i !== undefined) o = i.acc === true; else if (!inDraft(e) && getObserver() !== null) {
|
|
1641
|
+
o = isOwnAccessor(r, t);
|
|
1642
|
+
if (r === (e.pb ?? e.v)) l = o ? 1 : 0;
|
|
1643
|
+
} else o = false;
|
|
1644
|
+
if (o) {
|
|
1645
|
+
if (!inDraft(e) && getObserver() !== null) read(i ?? getNode(e, t, undefined, l));
|
|
1646
|
+
const o = Reflect.get(r, t, n);
|
|
1647
|
+
if (e.s) return serveShallow(e, t, o);
|
|
1648
|
+
return isWrappable(o) ? draftServe(e, wrapNext(o, e, t)) : o;
|
|
1596
1649
|
}
|
|
1597
1650
|
}
|
|
1598
1651
|
// Plain-data fast path: no descriptor allocation per read.
|
|
@@ -1602,10 +1655,10 @@ const traps = {
|
|
|
1602
1655
|
// backings chain to the committed backing, so "own in the view" means
|
|
1603
1656
|
// own on either layer (ownInView) — a genuine prototype method is one
|
|
1604
1657
|
// that is own on NEITHER.
|
|
1605
|
-
const
|
|
1606
|
-
if ((t === "constructor" || t === "__proto__" || t === "prototype") && !hasOwn.call(r, t) && !(
|
|
1658
|
+
const o = e.ovl && r === e.pb;
|
|
1659
|
+
if ((t === "constructor" || t === "__proto__" || t === "prototype") && !hasOwn.call(r, t) && !(o && hasOwn.call(e.v, t))) return undefined;
|
|
1607
1660
|
let f = r[t];
|
|
1608
|
-
if (f === undefined ? !hasOwn.call(r, t) && !(
|
|
1661
|
+
if (f === undefined ? !hasOwn.call(r, t) && !(o && hasOwn.call(e.v, t)) : false) {
|
|
1609
1662
|
// Inherited: prototype getters/methods run with the proxy receiver.
|
|
1610
1663
|
f = Reflect.get(r, t, n);
|
|
1611
1664
|
if (typeof f === "function") return f;
|
|
@@ -1613,7 +1666,7 @@ const traps = {
|
|
|
1613
1666
|
// Reading a currently-absent own key subscribes to it (R12) — for any
|
|
1614
1667
|
// target OUTSIDE its own draft scope, even mid-setter (#3037, above).
|
|
1615
1668
|
if (f === undefined && !inDraft(e)) {
|
|
1616
|
-
if (getObserver() !== null) read(getNode(e, t, undefined,
|
|
1669
|
+
if (getObserver() !== null) read(getNode(e, t, undefined, l));
|
|
1617
1670
|
const n = e.n?.[t];
|
|
1618
1671
|
if (n) {
|
|
1619
1672
|
const r = nodeValue(n, undefined);
|
|
@@ -1625,14 +1678,14 @@ const traps = {
|
|
|
1625
1678
|
// the caller's optimism is not truth (has-trap twin below).
|
|
1626
1679
|
!authoritativeServe()) {
|
|
1627
1680
|
const n = e.n?.[t];
|
|
1628
|
-
if (n !== undefined &&
|
|
1681
|
+
if (n !== undefined && visibleOverride(n)) f = unwrapOverride(n.o?.Ce);
|
|
1629
1682
|
}
|
|
1630
1683
|
if (e.s) return serveShallow(e, t, f);
|
|
1631
1684
|
return isWrappable(f) ? draftServe(e, wrapNext(f, e, t)) : f;
|
|
1632
1685
|
}
|
|
1633
|
-
if (typeof f === "function" && !hasOwn.call(r, t) && !(
|
|
1686
|
+
if (typeof f === "function" && !hasOwn.call(r, t) && !(o && hasOwn.call(e.v, t))) return f;
|
|
1634
1687
|
// proto method
|
|
1635
|
-
return serveDataKey(e, t, f, r, i,
|
|
1688
|
+
return serveDataKey(e, t, f, r, i, l);
|
|
1636
1689
|
},
|
|
1637
1690
|
has(e, t) {
|
|
1638
1691
|
if (t === $TARGET || t === $PROXY || t === $TRACK) return true;
|
|
@@ -1652,11 +1705,11 @@ const traps = {
|
|
|
1652
1705
|
if (hasActiveOverride(n)) r = !!i;
|
|
1653
1706
|
} else if (!authoritativeServe()) {
|
|
1654
1707
|
const n = e.h?.[t];
|
|
1655
|
-
if (n !== undefined &&
|
|
1708
|
+
if (n !== undefined && visibleOverride(n)) r = !!unwrapOverride(n.o?.Ce);
|
|
1656
1709
|
}
|
|
1657
1710
|
} else if (e.fam?.opt && draftSeesOverrides(e) && !authoritativeServe()) {
|
|
1658
1711
|
const n = e.h?.[t];
|
|
1659
|
-
if (n !== undefined && hasActiveOverride(n)) r = !!unwrapOverride(n.o?.
|
|
1712
|
+
if (n !== undefined && hasActiveOverride(n)) r = !!unwrapOverride(n.o?.Ce);
|
|
1660
1713
|
}
|
|
1661
1714
|
return r;
|
|
1662
1715
|
},
|
|
@@ -1668,13 +1721,30 @@ const traps = {
|
|
|
1668
1721
|
},
|
|
1669
1722
|
getOwnPropertyDescriptor(e, t) {
|
|
1670
1723
|
if (t === $OWNER) return undefined;
|
|
1671
|
-
|
|
1672
|
-
|
|
1724
|
+
// A descriptor read is a PRESENCE read: it subscribes to the key's
|
|
1725
|
+
// presence node and witnesses affects()/isPending() exactly as `in` does
|
|
1726
|
+
// (structural oracle, 2026-09-17 — the trap read no node before, so a
|
|
1727
|
+
// render effect inspecting a key through getOwnPropertyDescriptor never
|
|
1728
|
+
// re-ran for an optimistic add or delete, and an isPending() probe over
|
|
1729
|
+
// it witnessed nothing). The value it reports rides the value node's
|
|
1730
|
+
// view through visibleDescriptor.
|
|
1731
|
+
if (pendingCheckActive) witnessAffectsMark(e, t);
|
|
1732
|
+
if (e.fam !== null && getObserver() === null && !inDraft(e)) firewallGate(e);
|
|
1733
|
+
const n = readSource(e);
|
|
1734
|
+
const r = visibleDescriptor(e, n, t);
|
|
1735
|
+
if (!inDraft(e) && getObserver() !== null) {
|
|
1736
|
+
// The node is born from the source's presence (as `has` births it),
|
|
1737
|
+
// not the override-adjusted answer.
|
|
1738
|
+
let r = t in n;
|
|
1739
|
+
if (r && e.del !== null && n === e.pb && e.del.has(t)) r = false;
|
|
1740
|
+
read(getHasNode(e, t, r));
|
|
1741
|
+
}
|
|
1742
|
+
if (r === undefined) return undefined;
|
|
1673
1743
|
// Array targets carry a real non-configurable `length` the proxy
|
|
1674
1744
|
// invariant forces us to report faithfully; everything else reports
|
|
1675
1745
|
// configurable via target indirection (core R51).
|
|
1676
|
-
if (!(t === "length" && Array.isArray(e)))
|
|
1677
|
-
return
|
|
1746
|
+
if (!(t === "length" && Array.isArray(e))) r.configurable = true;
|
|
1747
|
+
return r;
|
|
1678
1748
|
},
|
|
1679
1749
|
set(e, t, n) {
|
|
1680
1750
|
// Writes require the target's draft scope OR the projection write
|
|
@@ -1691,13 +1761,13 @@ const traps = {
|
|
|
1691
1761
|
// Shallow slots store what was written VERBATIM — another store's proxy
|
|
1692
1762
|
// passes through by reference (#2932; markRawOne skips proxies), while
|
|
1693
1763
|
// deep stores unwrap to raw backings.
|
|
1694
|
-
const
|
|
1695
|
-
const
|
|
1764
|
+
const l = e.s ? n : unwrapValue(n);
|
|
1765
|
+
const o = ensurePB(e);
|
|
1696
1766
|
pendingNotify.add(e);
|
|
1697
1767
|
// Array length writes implicitly delete indices — the written-keys bound
|
|
1698
1768
|
// can't see them, so poison to the full scan for this batch. Index
|
|
1699
1769
|
// writes implicitly GROW length, so arrays always record it alongside.
|
|
1700
|
-
if (Array.isArray(
|
|
1770
|
+
if (Array.isArray(o)) {
|
|
1701
1771
|
if (t === "length") e.wk = WK_ALL; else if (e.wk !== WK_ALL) {
|
|
1702
1772
|
const n = e.wk ??= new Set;
|
|
1703
1773
|
n.add(t);
|
|
@@ -1709,13 +1779,13 @@ const traps = {
|
|
|
1709
1779
|
// sees through an overlay to the committed keys, so this counts keys
|
|
1710
1780
|
// NEW to the container. Deletes are not un-counted (a stale high
|
|
1711
1781
|
// count only picks the overlay a little early).
|
|
1712
|
-
if (!(t in
|
|
1782
|
+
if (!(t in o)) e.kc++;
|
|
1713
1783
|
}
|
|
1714
1784
|
// Own data keys literally named "prototype"/"constructor" land as data —
|
|
1715
1785
|
// defineProperty sidesteps a proto-chain setter named the same.
|
|
1716
1786
|
if (UNSAFE_KEYS.has(t)) {
|
|
1717
|
-
Object.defineProperty(
|
|
1718
|
-
value:
|
|
1787
|
+
Object.defineProperty(o, t, {
|
|
1788
|
+
value: l,
|
|
1719
1789
|
writable: true,
|
|
1720
1790
|
enumerable: true,
|
|
1721
1791
|
configurable: true
|
|
@@ -1728,18 +1798,18 @@ const traps = {
|
|
|
1728
1798
|
// path normalized descriptors for exactly this — R51 parity). A
|
|
1729
1799
|
// plain-data-graded backing (sc 2, owned: every slot writable) takes the
|
|
1730
1800
|
// bare assignment — it lands as an own key on the overlay all the same.
|
|
1731
|
-
if (e.ovl && e.sc !== 2 && !hasOwn.call(
|
|
1732
|
-
Object.defineProperty(
|
|
1733
|
-
value:
|
|
1801
|
+
if (e.ovl && e.sc !== 2 && !hasOwn.call(o, t)) {
|
|
1802
|
+
Object.defineProperty(o, t, {
|
|
1803
|
+
value: l,
|
|
1734
1804
|
writable: true,
|
|
1735
1805
|
enumerable: true,
|
|
1736
1806
|
configurable: true
|
|
1737
1807
|
});
|
|
1738
|
-
} else
|
|
1808
|
+
} else o[t] = l;
|
|
1739
1809
|
if (e.del !== null) e.del.delete(t);
|
|
1740
1810
|
// Shallow ingest: written records are sticky raw-marked (one entity is
|
|
1741
1811
|
// never both deep-wrapped and raw — R41/#2932, shared invariant).
|
|
1742
|
-
if (e.s &&
|
|
1812
|
+
if (e.s && l !== null && typeof l === "object") markRawOne(l);
|
|
1743
1813
|
// Override-mode (post-await draft) writes have no setter exit — notify
|
|
1744
1814
|
// per-op (setSignal equality-gates repeats).
|
|
1745
1815
|
if (i) notifyWrites(e);
|
|
@@ -1756,14 +1826,14 @@ const traps = {
|
|
|
1756
1826
|
...n,
|
|
1757
1827
|
value: unwrapValue(n.value)
|
|
1758
1828
|
};
|
|
1759
|
-
const
|
|
1829
|
+
const l = ensurePB(e);
|
|
1760
1830
|
// A non-default data descriptor (or an accessor) leaves the plain-data
|
|
1761
1831
|
// grade: the key reaches the committed backing as defined, so the spread
|
|
1762
1832
|
// clone and bare-assignment paths no longer describe it.
|
|
1763
1833
|
if (e.a || !(n.enumerable && n.writable && n.configurable)) e.sc = 1;
|
|
1764
1834
|
pendingNotify.add(e);
|
|
1765
1835
|
if (e.wk !== WK_ALL) (e.wk ??= new Set).add(t);
|
|
1766
|
-
Object.defineProperty(
|
|
1836
|
+
Object.defineProperty(l, t, n);
|
|
1767
1837
|
if (e.del !== null) e.del.delete(t);
|
|
1768
1838
|
if (i) notifyWrites(e);
|
|
1769
1839
|
return true;
|
|
@@ -1786,20 +1856,22 @@ const traps = {
|
|
|
1786
1856
|
|
|
1787
1857
|
/** Low-level setter primitive: opens write mode on a next proxy, runs `fn`,
|
|
1788
1858
|
* emits write-time notifications at outermost exit, applies returned
|
|
1789
|
-
* replacements as adoptions. `guard=false` skips the owned-scope
|
|
1790
|
-
* projection recomputes legitimately write from
|
|
1859
|
+
* replacements as adoptions. `guard=false` skips the dev guards (owned-scope
|
|
1860
|
+
* write, thenable result) — projection recomputes legitimately write from
|
|
1861
|
+
* inside their computed, and their async derive is handled by the recompute,
|
|
1862
|
+
* not returned through here. */ function storeSetterNext(e, t, n = true) {
|
|
1791
1863
|
const r = e[$TARGET];
|
|
1792
1864
|
const i = writeScopes;
|
|
1793
1865
|
writeScopes = new Set;
|
|
1794
1866
|
writeScopes.add(scopeKey(r));
|
|
1795
1867
|
writing++;
|
|
1796
|
-
let
|
|
1868
|
+
let l;
|
|
1797
1869
|
try {
|
|
1798
1870
|
// No untrack: the writing flag already disables store-node linking
|
|
1799
1871
|
// (draft reads never self-track, proj R2), while EXTERNAL reads (signals
|
|
1800
1872
|
// inside a projection derive) must keep tracking — they are the derive's
|
|
1801
1873
|
// dependencies.
|
|
1802
|
-
|
|
1874
|
+
l = t(e);
|
|
1803
1875
|
} finally {
|
|
1804
1876
|
writing--;
|
|
1805
1877
|
writeScopes = i;
|
|
@@ -1811,15 +1883,15 @@ const traps = {
|
|
|
1811
1883
|
for (const t of e) notifyWrites(t);
|
|
1812
1884
|
}
|
|
1813
1885
|
}
|
|
1814
|
-
if (
|
|
1886
|
+
if (l !== undefined && l !== e && isWrappable(l)) {
|
|
1815
1887
|
// Returned replacement: on an optimistic family (outside authoritative
|
|
1816
1888
|
// writes) the replacement is itself an optimistic edit — diff it against
|
|
1817
1889
|
// the visible view as engine writes (reverts at settle). Otherwise it is
|
|
1818
1890
|
// an adoption of the incoming object (unowned).
|
|
1819
1891
|
if (r.fam?.opt && !projectionWriteActive && !getWriteOverride()) {
|
|
1820
|
-
optHooks.notifyOptimisticWrites(r, unwrapValue(
|
|
1892
|
+
optHooks.notifyOptimisticWrites(r, unwrapValue(l));
|
|
1821
1893
|
} else {
|
|
1822
|
-
adoptPB(r, unwrapValue(
|
|
1894
|
+
adoptPB(r, unwrapValue(l));
|
|
1823
1895
|
}
|
|
1824
1896
|
}
|
|
1825
1897
|
if (writing === 0 && heldAdoptions.size) stageHeldAdoptions();
|
|
@@ -1906,11 +1978,12 @@ function createStoreNext(e, t = false) {
|
|
|
1906
1978
|
}
|
|
1907
1979
|
if (!authoritativeServe() && e.fam?.opt && e.h !== null && (!inDraft(e) || draftSeesOverrides(e))) {
|
|
1908
1980
|
let t = null;
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1981
|
+
const r = inDraft(e);
|
|
1982
|
+
for (const i of Reflect.ownKeys(e.h)) {
|
|
1983
|
+
const l = e.h[i];
|
|
1984
|
+
if (!(r ? hasActiveOverride(l) : visibleOverride(l))) continue;
|
|
1912
1985
|
t ??= new Set(n);
|
|
1913
|
-
if (unwrapOverride(
|
|
1986
|
+
if (unwrapOverride(l.o?.Ce)) t.add(i); else t.delete(i);
|
|
1914
1987
|
}
|
|
1915
1988
|
if (t !== null) return [ ...t ];
|
|
1916
1989
|
}
|
|
@@ -1929,8 +2002,8 @@ function createStoreNext(e, t = false) {
|
|
|
1929
2002
|
}
|
|
1930
2003
|
if (!authoritativeServe() && e.fam?.opt && !inDraft(e)) {
|
|
1931
2004
|
const t = e.h?.[n];
|
|
1932
|
-
if (t !== undefined &&
|
|
1933
|
-
if (!unwrapOverride(t.o?.
|
|
2005
|
+
if (t !== undefined && visibleOverride(t)) {
|
|
2006
|
+
if (!unwrapOverride(t.o?.Ce)) return undefined;
|
|
1934
2007
|
// opt delete
|
|
1935
2008
|
if (r === undefined) {
|
|
1936
2009
|
const t = e.n?.[n];
|
|
@@ -2003,23 +2076,23 @@ function createStoreNext(e, t = false) {
|
|
|
2003
2076
|
continue;
|
|
2004
2077
|
// accessors track through their own reads when invoked
|
|
2005
2078
|
}
|
|
2006
|
-
let
|
|
2079
|
+
let l = i.value;
|
|
2007
2080
|
// An active value override on an optimistic node shadows the backing's
|
|
2008
2081
|
// child (an optimistic replacement `d[i] = {...}`) — follow what reads
|
|
2009
2082
|
// serve, as nodeValue's leading arm does.
|
|
2010
2083
|
if (r) {
|
|
2011
2084
|
const t = e.n?.[n];
|
|
2012
|
-
if (t !== undefined && hasActiveOverride(t) && !authoritativeServe())
|
|
2085
|
+
if (t !== undefined && hasActiveOverride(t) && !authoritativeServe()) l = unwrapOverride(t.o.Ce);
|
|
2013
2086
|
}
|
|
2014
|
-
if (
|
|
2087
|
+
if (l === null || typeof l !== "object") continue;
|
|
2015
2088
|
// Through a chain the descriptor yields the INNERMOST raw: resolve it to
|
|
2016
2089
|
// the inner family's proxy so this level wraps the chained `view[i]` the
|
|
2017
2090
|
// get trap serves, never a fresh non-chained wrapper of the base raw.
|
|
2018
|
-
if (e.ch &&
|
|
2019
|
-
const
|
|
2020
|
-
if (
|
|
2091
|
+
if (e.ch && l[$TARGET] === undefined) l = resolveChainedRaw(e, n, l);
|
|
2092
|
+
const o = childTarget(e, l, n);
|
|
2093
|
+
if (o === undefined) continue;
|
|
2021
2094
|
// raw-marked: leaf by contract
|
|
2022
|
-
walkT(
|
|
2095
|
+
walkT(o);
|
|
2023
2096
|
}
|
|
2024
2097
|
};
|
|
2025
2098
|
walkT(t);
|
|
@@ -2051,31 +2124,31 @@ function snapshotWalk(e, t, n) {
|
|
|
2051
2124
|
let i = null;
|
|
2052
2125
|
for (let e = true; ;e = false) {
|
|
2053
2126
|
const t = r?.[$TARGET]?.v !== undefined;
|
|
2054
|
-
let
|
|
2055
|
-
if (
|
|
2056
|
-
if (
|
|
2057
|
-
if (
|
|
2127
|
+
let l = t ? r[$TARGET] : undefined;
|
|
2128
|
+
if (l === undefined && n !== null) l = lookupTarget(r, n);
|
|
2129
|
+
if (l === undefined) l = lookupTarget(r, null);
|
|
2130
|
+
if (l === undefined) break;
|
|
2058
2131
|
// Entering a level from a RAW below a chained family: the raw resolves to
|
|
2059
2132
|
// the INNER store's target, but this family's wrapper for it — keyed by
|
|
2060
2133
|
// the inner proxy, §7b — is where the outer overrides live. Start from
|
|
2061
2134
|
// the wrapper so they compose (#3323: a nested optimistic write on a view
|
|
2062
2135
|
// row was served by reads but missing from deep()/snapshot()). Entry only:
|
|
2063
2136
|
// the descent then runs wrapper → inner → raw and terminates.
|
|
2064
|
-
if (e && !t && n !== null &&
|
|
2065
|
-
const e = n.map.get(
|
|
2066
|
-
if (e !== undefined)
|
|
2137
|
+
if (e && !t && n !== null && l.fam !== n) {
|
|
2138
|
+
const e = n.map.get(l.px);
|
|
2139
|
+
if (e !== undefined) l = e;
|
|
2067
2140
|
}
|
|
2068
|
-
if (
|
|
2069
|
-
if (
|
|
2141
|
+
if (l.fam !== null) n = l.fam;
|
|
2142
|
+
if (l.fam?.opt === true) (i ??= []).push(l);
|
|
2070
2143
|
// The shared visibility decision (#3147): the speculative peek serves
|
|
2071
2144
|
// pending staging, but a HELD landing is masked to committed exactly as
|
|
2072
2145
|
// it is for per-key readers — the two families must answer alike while
|
|
2073
2146
|
// a transaction holds store landings.
|
|
2074
|
-
const
|
|
2147
|
+
const o = pendingBackingVisible(l, true);
|
|
2075
2148
|
// Snapshot runs mid-flush (tracked memos execute before commit), so a
|
|
2076
2149
|
// pending prototype overlay must present as a REAL merged container.
|
|
2077
|
-
if (
|
|
2078
|
-
const f =
|
|
2150
|
+
if (o && l.ovl) materializePB(l);
|
|
2151
|
+
const f = o ? l.pb : l.v;
|
|
2079
2152
|
if (f === r) break;
|
|
2080
2153
|
r = f;
|
|
2081
2154
|
}
|
|
@@ -2088,20 +2161,20 @@ function snapshotWalk(e, t, n) {
|
|
|
2088
2161
|
if (e !== r) {
|
|
2089
2162
|
const i = t.get(r);
|
|
2090
2163
|
if (i !== undefined) return i;
|
|
2091
|
-
const
|
|
2092
|
-
const
|
|
2093
|
-
t.set(r,
|
|
2164
|
+
const l = Array.isArray(e);
|
|
2165
|
+
const o = l ? [] : Object.create(Object.getPrototypeOf(e));
|
|
2166
|
+
t.set(r, o);
|
|
2094
2167
|
for (const r of Reflect.ownKeys(e)) {
|
|
2095
|
-
if (
|
|
2168
|
+
if (l && r === "length" || r === $OWNER) continue;
|
|
2096
2169
|
const i = e[r];
|
|
2097
|
-
|
|
2170
|
+
o[r] = i !== null && typeof i === "object" ? snapshotWalk(i, t, n) : i;
|
|
2098
2171
|
}
|
|
2099
|
-
if (
|
|
2100
|
-
return
|
|
2172
|
+
if (l) o.length = e.length;
|
|
2173
|
+
return o;
|
|
2101
2174
|
}
|
|
2102
2175
|
}
|
|
2103
|
-
const
|
|
2104
|
-
if (
|
|
2176
|
+
const l = t.get(r);
|
|
2177
|
+
if (l !== undefined) return l;
|
|
2105
2178
|
// OWNED (written) subtrees snapshot as copies (§7b: identity is only for
|
|
2106
2179
|
// subtrees "unmodified relative to source"): non-enumerable symbols are
|
|
2107
2180
|
// excluded (recon-snap R29), and the copy registers BEFORE descent so
|
|
@@ -2110,18 +2183,18 @@ function snapshotWalk(e, t, n) {
|
|
|
2110
2183
|
const e = Array.isArray(r);
|
|
2111
2184
|
const i = e ? [] : Object.create(Object.getPrototypeOf(r));
|
|
2112
2185
|
t.set(r, i);
|
|
2113
|
-
for (const
|
|
2114
|
-
if (e &&
|
|
2115
|
-
const
|
|
2116
|
-
if (typeof
|
|
2117
|
-
if (
|
|
2118
|
-
Object.defineProperty(i,
|
|
2186
|
+
for (const l of Reflect.ownKeys(r)) {
|
|
2187
|
+
if (e && l === "length" || l === $OWNER) continue;
|
|
2188
|
+
const o = Object.getOwnPropertyDescriptor(r, l);
|
|
2189
|
+
if (typeof l === "symbol" && !o.enumerable) continue;
|
|
2190
|
+
if (o.get || o.set) {
|
|
2191
|
+
Object.defineProperty(i, l, o);
|
|
2119
2192
|
continue;
|
|
2120
2193
|
}
|
|
2121
|
-
const f =
|
|
2194
|
+
const f = o.value;
|
|
2122
2195
|
const s = f !== null && typeof f === "object" ? snapshotWalk(f, t, n) : f;
|
|
2123
|
-
if (
|
|
2124
|
-
...
|
|
2196
|
+
if (o.enumerable && o.writable && o.configurable) i[l] = s; else Object.defineProperty(i, l, {
|
|
2197
|
+
...o,
|
|
2125
2198
|
value: s
|
|
2126
2199
|
});
|
|
2127
2200
|
}
|
|
@@ -2131,22 +2204,22 @@ function snapshotWalk(e, t, n) {
|
|
|
2131
2204
|
// UNOWNED (shared/user) subtrees keep identity unless a descendant
|
|
2132
2205
|
// substituted; copy-on-substitution preserves the documented CoW contract.
|
|
2133
2206
|
t.set(r, r);
|
|
2134
|
-
let
|
|
2207
|
+
let o = null;
|
|
2135
2208
|
for (const e of Reflect.ownKeys(r)) {
|
|
2136
2209
|
const i = Object.getOwnPropertyDescriptor(r, e);
|
|
2137
2210
|
if (!i || i.get || i.set) continue;
|
|
2138
|
-
const
|
|
2139
|
-
if (
|
|
2140
|
-
const f = snapshotWalk(
|
|
2141
|
-
if (f !==
|
|
2142
|
-
if (
|
|
2143
|
-
|
|
2144
|
-
t.set(r,
|
|
2211
|
+
const l = i.value;
|
|
2212
|
+
if (l === null || typeof l !== "object") continue;
|
|
2213
|
+
const f = snapshotWalk(l, t, n);
|
|
2214
|
+
if (f !== l) {
|
|
2215
|
+
if (o === null) {
|
|
2216
|
+
o = Array.isArray(r) ? [ ...r ] : Object.create(Object.getPrototypeOf(r), Object.getOwnPropertyDescriptors(r));
|
|
2217
|
+
t.set(r, o);
|
|
2145
2218
|
}
|
|
2146
|
-
|
|
2219
|
+
o[e] = f;
|
|
2147
2220
|
}
|
|
2148
2221
|
}
|
|
2149
|
-
return
|
|
2222
|
+
return o ?? r;
|
|
2150
2223
|
}
|
|
2151
2224
|
|
|
2152
|
-
export { adoptPB, arrayStructureChanged, authoritativeRead, authoritativeServe, bumpDeep, createStoreNext, deepNext, getHasNode, getKeySetNode, getNode, hasAccessorFlag, hasActiveOverride, heldMaskView, materializePB, membershipChanged, notifyFold, notifyFoldTail, notifyKeyDiff, notifyKeyValue, runAuthoritative, snapshotNext, stagedTruthPB, storeHasFamily, storeHasOptimisticFamily, storeIsShallow, storeSetterNext, targetsEqual, unwrapValue, wrapNext };
|
|
2225
|
+
export { adoptPB, arrayStructureChanged, authoritativeRead, authoritativeServe, bumpDeep, createStoreNext, deepNext, getHasNode, getKeySetNode, getNode, hasAccessorFlag, hasActiveOverride, heldMaskView, materializePB, membershipChanged, notifyFold, notifyFoldTail, notifyKeyDiff, notifyKeyValue, runAuthoritative, snapshotNext, stagedTruthPB, storeHasFamily, storeHasOptimisticFamily, storeIsShallow, storeSetterNext, targetsEqual, unwrapValue, visibleOverride, wrapNext };
|