@solidjs/signals 2.0.0-rc.16 → 2.0.0-rc.18

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.
Files changed (56) hide show
  1. package/dist/dev-shared.js +1972 -1751
  2. package/dist/dev.attribution.js +16 -16
  3. package/dist/dev.js +672 -319
  4. package/dist/observe/boundaries.js +2 -2
  5. package/dist/observe/core/async.js +151 -116
  6. package/dist/observe/core/constants.js +3 -1
  7. package/dist/observe/core/context.js +2 -0
  8. package/dist/observe/core/core.js +51 -35
  9. package/dist/observe/core/effect.js +29 -30
  10. package/dist/observe/core/graph.js +13 -11
  11. package/dist/observe/core/lanes.js +25 -14
  12. package/dist/observe/core/owner.js +77 -51
  13. package/dist/observe/core/scheduler.js +202 -175
  14. package/dist/observe/core/verdict.js +5 -2
  15. package/dist/observe/deferred.js +16 -13
  16. package/dist/observe/from.js +248 -0
  17. package/dist/observe/index.js +2 -0
  18. package/dist/observe/map.js +2 -2
  19. package/dist/observe/signals.js +6 -1
  20. package/dist/observe/store/affects.js +13 -13
  21. package/dist/observe/store/optimistic.js +112 -71
  22. package/dist/observe/store/reconcile.js +137 -121
  23. package/dist/observe/store/store.js +612 -626
  24. package/dist/observe/store/target.js +1 -5
  25. package/dist/prod/boundaries.js +2 -2
  26. package/dist/prod/core/async.js +211 -176
  27. package/dist/prod/core/constants.js +3 -1
  28. package/dist/prod/core/context.js +2 -0
  29. package/dist/prod/core/core.js +63 -47
  30. package/dist/prod/core/effect.js +24 -25
  31. package/dist/prod/core/graph.js +12 -10
  32. package/dist/prod/core/heap.js +1 -1
  33. package/dist/prod/core/lanes.js +39 -28
  34. package/dist/prod/core/owner.js +70 -44
  35. package/dist/prod/core/scheduler.js +78 -51
  36. package/dist/prod/core/truth.js +4 -4
  37. package/dist/prod/core/verdict.js +11 -8
  38. package/dist/prod/deferred.js +17 -14
  39. package/dist/prod/from.js +248 -0
  40. package/dist/prod/index.js +2 -0
  41. package/dist/prod/map.js +2 -2
  42. package/dist/prod/signals.js +18 -13
  43. package/dist/prod/store/optimistic.js +112 -71
  44. package/dist/prod/store/reconcile.js +137 -121
  45. package/dist/prod/store/store.js +109 -121
  46. package/dist/prod/store/target.js +13 -17
  47. package/dist/types/core/async.d.ts +12 -2
  48. package/dist/types/core/constants.d.ts +5 -0
  49. package/dist/types/core/core.d.ts +29 -6
  50. package/dist/types/core/dev.d.ts +9 -1
  51. package/dist/types/core/error.d.ts +9 -1
  52. package/dist/types/core/owner.d.ts +4 -0
  53. package/dist/types/core/scheduler.d.ts +38 -7
  54. package/dist/types/from.d.ts +47 -0
  55. package/dist/types/index.d.ts +1 -0
  56. package/package.json +1 -1
@@ -10,9 +10,9 @@ import { getObserver } from "../core/owner.js";
10
10
 
11
11
  import { insertIntoHeap } from "../core/heap.js";
12
12
 
13
- import { txOf, flushTransaction, holdNode, joinFuture, insertSubs, schedule, passLane, globalQueue, queuePendingNode, GlobalQueue, installStoreHooks, joinPassTx, dirtyQueue } from "../core/scheduler.js";
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, devAssertNeverUserMutation } from "./target.js";
15
+ import { lookupTarget, setLookup, $OWNER, isOwned, markDescendants } from "./target.js";
16
16
 
17
17
  import { optHooks, affectsHooks } from "./hooks.js";
18
18
 
@@ -134,7 +134,7 @@ function wrap(e, n = null, t = null, r = n?.fam ?? null) {
134
134
  const i = lookupTarget(e, r);
135
135
  if (i !== undefined) return i.px;
136
136
  const o = e[$TARGET];
137
- if (o !== undefined && o.px === e) {
137
+ if (o?.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
140
  if (r === null || o.fam === r) return e;
@@ -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 !== null && optHooks.arrangement(this.O, e, n);
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 !== null && n.n[t] === e) {
228
+ } else if (n.n?.[t] === e) {
229
229
  delete n.n[t];
230
230
  n.nc--;
231
- } else if (n.h !== null && n.h[t] === e) delete n.h[t];
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.se !== NOT_PENDING || e.l & CONFIG_OVERRIDE || e.O.k?.l & CONFIG_HELD;
250
+ const slotKept = e => e.ue !== 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);
@@ -260,14 +260,19 @@ setSlotUnobserved(e => {
260
260
  * unchanged stages nothing and holds no one). */ function bornStaged(e, n, t, r) {
261
261
  if (n.xe && n.xe(n.Ie, t)) return;
262
262
  queuePendingNode(n);
263
- n.se = t;
263
+ n.ue = t;
264
264
  const i = e.k;
265
265
  if (i === 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
- // container carrying a guess is a lane's: the flush's park decides.)
270
- if ((i.l & (CONFIG_HELD | CONFIG_OVERRIDE)) === CONFIG_HELD && heldKeyChanged(e, r)) holdNode(n, txOf(i));
269
+ // container carrying a guess is a lane's: the flush's park decides —
270
+ // unless a correction folded under the guess, D-34: the key is that
271
+ // correction's hold's.)
272
+ if (i.l & CONFIG_HELD && heldKeyChanged(e, r)) {
273
+ const e = txOf(i);
274
+ if (!(i.l & CONFIG_OVERRIDE) || e.folded) holdNode(n, resolveTx(e._parent ?? e));
275
+ }
271
276
  // A28 (4): a batch written inside a creation-time pass is promoted — its
272
277
  // late-materialized leaf with it.
273
278
  if (i.l & CONFIG_PROMOTED) notePromotedWrite(n);
@@ -287,7 +292,7 @@ t = -1) {
287
292
  // receiver.
288
293
  const o = e.pb;
289
294
  const l = i = slotSignal(committed(e)[n], slotNodeEquals, e, n, t === -1 ? isOwnAccessor(o ?? e.v, n) : t === 1);
290
- if (o !== null && !l.acc) bornStaged(e, l, e.del !== null && e.del.has(n) ? undefined : o[n], n);
295
+ if (o !== null && !l.acc) bornStaged(e, l, e.del?.has(n) ? undefined : o[n], n);
291
296
  r[n] = i;
292
297
  e.nc++;
293
298
  noteNode(e, l, n);
@@ -301,7 +306,7 @@ function getHasNode(e, n) {
301
306
  if (r === undefined) {
302
307
  const i = r = slotSignal(n in committed(e), isEqual, e, n, false);
303
308
  const o = e.pb;
304
- if (o !== null) bornStaged(e, i, n in o && !(e.del !== null && e.del.has(n)), n);
309
+ if (o !== null) bornStaged(e, i, n in o && !e.del?.has(n), n);
305
310
  t[n] = r;
306
311
  noteNode(e, i, n);
307
312
  }
@@ -321,7 +326,7 @@ function getHasNode(e, n) {
321
326
  // would have read had the node been there from the write.
322
327
  if (e.pb !== null && !directCommit) {
323
328
  n.Ie = preBatch(e);
324
- n.se = e.pb;
329
+ n.ue = e.pb;
325
330
  queuePendingNode(n);
326
331
  }
327
332
  }
@@ -340,8 +345,8 @@ function getHasNode(e, n) {
340
345
  * (`storeParkHook`) — the one case the staging home exists for. */ function stageOn(e, n) {
341
346
  if (e.k === null && passLane === null && (context === null || globalQueue.q) && !deriveHolds(e)) return;
342
347
  const t = getContainerNode(e);
343
- if (t.se === NOT_PENDING) queuePendingNode(t);
344
- t.se = n;
348
+ if (t.ue === NOT_PENDING) queuePendingNode(t);
349
+ t.ue = n;
345
350
  // A28 (4): a write issued inside a pass outside a flush (a creation-time
346
351
  // derive) is promoted at the pass's end — the batch with it.
347
352
  if (context !== null) notePromotedWrite(t);
@@ -444,7 +449,7 @@ function copyOwn(e, n, t) {
444
449
  const t = Reflect.ownKeys(n);
445
450
  let r = Object.getPrototypeOf(n) === Object.prototype;
446
451
  for (const i of t) {
447
- if (lookupGetter.call(n, i) !== undefined || lookupSetter.call(n, i) !== undefined) {
452
+ if (isOwnAccessor(n, i)) {
448
453
  e.a = true;
449
454
  r = false;
450
455
  break;
@@ -474,7 +479,7 @@ const plainProto = e => {
474
479
  /** An overlay with many adds (or any delete) rebuilds the committed
475
480
  * container at flatten so its shape stays fast (#3689). */ function overlayRebuilds(e, n) {
476
481
  if (e.kc > OVERLAY_REBUILD_MAX_KEYS) return false;
477
- if (e.del !== null && e.del.size !== 0) return true;
482
+ if (e.del?.size) return true;
478
483
  const t = e.wk;
479
484
  if (t !== null && t !== WK_ALL && t.u === undefined && t.size <= OVERLAY_REBUILD_MIN_ADDS) return false;
480
485
  const r = e.v;
@@ -486,17 +491,10 @@ const plainProto = e => {
486
491
  /** Downgrade an overlay to a real clone (a consumer needs a container). */ function materializePB(e) {
487
492
  const n = e.pb;
488
493
  if (!e.ovl) return n;
489
- const t = e.sc === 2 ? wideClone(e.v, e) : cloneRaw(e.v, e);
490
- if (e.del !== null) {
491
- for (const n of e.del) delete t[n];
492
- e.kc -= e.del.size;
493
- e.del = null;
494
- }
495
- 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);
496
495
  e.pb = t;
497
- e.ovl = false;
498
496
  // The staging IS the pending backing: re-point the container node.
499
- if (e.k !== null && e.k.se === n) e.k.se = t;
497
+ if (e.k?.ue === n) e.k.ue = t;
500
498
  return t;
501
499
  }
502
500
 
@@ -517,7 +515,7 @@ const plainProto = e => {
517
515
  // mainline setter mid-hold publishes mainline; the held keys stay held).
518
516
  n = e.pb = cloneRaw(n, e);
519
517
  const t = e.k;
520
- if (t !== null && !(t.l & CONFIG_HELD)) t.se = n;
518
+ if (t !== null && !(t.l & CONFIG_HELD)) t.ue = n;
521
519
  } else if (n === null) {
522
520
  const t = e.v;
523
521
  if (!directCommit) queueFold(e);
@@ -541,7 +539,6 @@ const plainProto = e => {
541
539
  e.ch = false;
542
540
  if (e.u) {
543
541
  privatizeCommitted(e.u);
544
- devAssertNeverUserMutation(e.u.v);
545
542
  const t = e.u.v;
546
543
  const r = parentSlotKey(e, n);
547
544
  if (t[r] === n) t[r] = e.v;
@@ -565,17 +562,20 @@ const plainProto = e => {
565
562
  /** Overlay flatten (#3044): own keys onto the owned committed backing in
566
563
  * place — the backing keeps its identity. */ function flattenOverlay(e, n) {
567
564
  privatizeCommitted(e);
568
- const t = e.v;
569
- for (const r of Reflect.ownKeys(n)) e.sc === 2 ? t[r] = n[r] : copyOwn(t, n, r);
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);
570
572
  if (e.del !== null) {
571
- for (const n of e.del) delete t[n];
573
+ for (const t of e.del) delete n[t];
572
574
  e.kc -= e.del.size;
573
575
  e.del = null;
574
576
  }
575
- e.pb = null;
576
577
  e.ovl = false;
577
- e.wk = null;
578
- // written-keys window closes with the commit
578
+ return n;
579
579
  }
580
580
 
581
581
  /** Adoption (a setter's returned replacement; reconcile and projection
@@ -615,7 +615,7 @@ const plainProto = e => {
615
615
  e.wk = null;
616
616
  // adoption supersedes staged trap writes
617
617
  const i = n[$OWNER];
618
- if (i !== undefined && i.fam === e.fam) n[$OWNER] = e; else setLookup(n, e);
618
+ if (i?.fam === e.fam) n[$OWNER] = e; else setLookup(n, e);
619
619
  if (t && r !== n) notifyFold(e, r, n);
620
620
  }
621
621
 
@@ -692,7 +692,7 @@ let foldIndex = null;
692
692
  if (r.pb === null) continue;
693
693
  // folded already (a direct commit)
694
694
  const i = r.k;
695
- if (i !== null && i.se !== NOT_PENDING) {
695
+ if (i !== null && i.ue !== NOT_PENDING) {
696
696
  // held: commits with its hold
697
697
  foldList.push(r);
698
698
  foldOlds.push(n[t]);
@@ -716,7 +716,7 @@ let foldIndex = null;
716
716
  * marks (an ambient `affects()` over a declared reload lives to the
717
717
  * landing) read it. */ GlobalQueue.k = e => {
718
718
  const n = e.O?.fam;
719
- return n != null && n.node !== null && (n.node.m & STATUS_PENDING) !== 0;
719
+ return (n?.node?.m & STATUS_PENDING) !== 0;
720
720
  };
721
721
 
722
722
  /** Core asks (lanes.ts `covered`): the value a slot node's guess covered.
@@ -727,7 +727,7 @@ let foldIndex = null;
727
727
  if (n.ch) {
728
728
  const t = e.ze;
729
729
  const r = n.v;
730
- if (n.h !== null && n.h[t] === e) e.Ie = untrack(() => t in r); else if (n.n !== null && n.n[t] === e) e.Ie = untrack(() => unwrapValue(r[t]));
730
+ if (n.h?.[t] === e) e.Ie = untrack(() => t in r); else if (n.n?.[t] === e) e.Ie = untrack(() => unwrapValue(r[t]));
731
731
  }
732
732
  return e.Ie;
733
733
  };
@@ -763,12 +763,7 @@ function runDirect(e) {
763
763
  const t = e.k;
764
764
  const r = e.pb;
765
765
  if (r !== null) {
766
- if (r === e.v) {
767
- // An eager adoption nothing wrote after: the backing is already
768
- // the adopted object (shared ownership — never cloned).
769
- e.pb = null;
770
- e.wk = null;
771
- } 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?.Pe !== n)) {
772
767
  // Overlay flatten (#3044): the backing keeps its identity, so the
773
768
  // `t.v === old` gate below skips path copying (the parent slot
774
769
  // already points here) and the adopted-notify (setter
@@ -786,25 +781,21 @@ function runDirect(e) {
786
781
  if (hasOwn.call(r, n)) copyOwn(t, r, n); else delete t[n];
787
782
  }
788
783
  } else {
789
- for (const e of Reflect.ownKeys(r)) {
790
- const i = Object.getOwnPropertyDescriptor(r, e);
791
- 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;
792
- }
784
+ for (const e of Reflect.ownKeys(r)) copyOwn(t, r, e);
793
785
  for (const e of Reflect.ownKeys(n)) {
794
786
  if (!hasOwn.call(r, e)) delete t[e];
795
787
  }
796
788
  }
797
- e.pb = null;
798
- e.wk = null;
799
789
  } else {
800
790
  // The clone (or adopted object) becomes the committed backing
801
791
  // (path copy below).
802
792
  e.v = e.ovl ? materializePB(e) : r;
803
793
  e.ch = e.v[$TARGET] !== undefined;
804
- e.pb = null;
805
- e.wk = null;
806
794
  }
807
- }
795
+ e.pb = null;
796
+ e.wk = null;
797
+ // the written-keys window closes with the commit
798
+ }
808
799
  if (t !== null) {
809
800
  // The node's committed value is the backing. A container nobody
810
801
  // subscribes to was a transient staging home (INTERNALS §5: an
@@ -816,7 +807,6 @@ function runDirect(e) {
816
807
  const t = parentSlotKey(e, n);
817
808
  if (e.u.v[t] === n) {
818
809
  privatizeCommitted(e.u);
819
- devAssertNeverUserMutation(e.u.v);
820
810
  e.u.v[t] = e.v;
821
811
  }
822
812
  }
@@ -901,7 +891,7 @@ function heldDerivation(e, n, t) {
901
891
  if (e?.get || e?.set || !isEqual(e?.value, r.value)) setSignal(i, () => r.value);
902
892
  continue;
903
893
  }
904
- const l = e.del !== null && e.del.has(o) ? undefined : n[o];
894
+ const l = e.del?.has(o) ? undefined : n[o];
905
895
  setSignal(i, () => l);
906
896
  if (e.fam !== null) {
907
897
  // The derive's write is a derivation; a user setter's is a proposal
@@ -919,13 +909,13 @@ function heldDerivation(e, n, t) {
919
909
  for (const r of t) {
920
910
  const t = l[r];
921
911
  if (t !== undefined) {
922
- setSignal(t, r in n && !(e.del !== null && e.del.has(r)));
912
+ setSignal(t, r in n && !e.del?.has(r));
923
913
  if (e.fam !== null) holdWithDerive(e, t);
924
914
  }
925
915
  }
926
916
  }
927
917
  if (e.dk !== null) {
928
- if (e.del !== null && e.del.size !== 0) bumpDeep(e); else for (const r of o ?? Reflect.ownKeys(n)) {
918
+ if (e.del?.size) bumpDeep(e); else for (const r of o ?? Reflect.ownKeys(n)) {
929
919
  if (r === $OWNER) continue;
930
920
  const i = n[r];
931
921
  const o = t[r];
@@ -943,7 +933,7 @@ function heldDerivation(e, n, t) {
943
933
  if (u !== null && (u.o !== null || u.l & CONFIG_OVERRIDE)) {
944
934
  let r;
945
935
  if (e.ovl) {
946
- r = e.del !== null && e.del.size !== 0;
936
+ r = !!e.del?.size;
947
937
  if (!r) {
948
938
  for (const e of Reflect.ownKeys(n)) {
949
939
  if (!hasOwn.call(t, e)) {
@@ -1089,7 +1079,7 @@ function inDraft(e) {
1089
1079
  /** A child proxy served to a draft joins the draft's scope. */ function draftServe(e, n) {
1090
1080
  if (writeScopes !== null && inDraft(e)) {
1091
1081
  const e = n?.[$TARGET];
1092
- if (e !== undefined && e.v !== undefined) writeScopes.add(scopeKey(e));
1082
+ if (e?.v !== undefined) writeScopes.add(scopeKey(e));
1093
1083
  }
1094
1084
  return n;
1095
1085
  }
@@ -1099,7 +1089,7 @@ function inDraft(e) {
1099
1089
  * "adoption is eager by contract" — and the node keeps the frame committed
1100
1090
  * readers under a hold still see), `t.v` otherwise. */ function committed(e) {
1101
1091
  const n = e.k;
1102
- if (n !== null) return n.se !== NOT_PENDING ? asBacking(n.Ie) : e.v;
1092
+ if (n !== null) return n.ue !== NOT_PENDING ? asBacking(n.Ie) : e.v;
1103
1093
  // A node-less staging (`stageOn`): the fold queue remembers the frame.
1104
1094
  return e.pb !== null ? preBatch(e) : e.v;
1105
1095
  }
@@ -1111,7 +1101,7 @@ function inDraft(e) {
1111
1101
  * committed frame. */ function stagingReader() {
1112
1102
  let e = context;
1113
1103
  if (e === null) return null;
1114
- if (e.je) e = e.Ye ?? null;
1104
+ if (e.Qe) e = e.Ye ?? null;
1115
1105
  return e === null || e.l & CONFIG_CHILDREN_FORBIDDEN ? null : e;
1116
1106
  }
1117
1107
 
@@ -1132,7 +1122,7 @@ function inDraft(e) {
1132
1122
  // sees — the lanes' values and the tick's own guesses over the truth
1133
1123
  // (#3665), never a staging awaiting its fold: the draft is born on the
1134
1124
  // read (and notified at the setter's exit like any).
1135
- if (userWrite && e.fam !== null && e.fam.opt === true && !pendingNotify.has(e) && inDraft(e)) {
1125
+ if (userWrite && e.fam?.opt === true && !pendingNotify.has(e) && inDraft(e)) {
1136
1126
  const n = ensurePB(e);
1137
1127
  pendingNotify.add(e);
1138
1128
  return n;
@@ -1165,7 +1155,7 @@ function inDraft(e) {
1165
1155
  // it).
1166
1156
  if (n !== undefined) {
1167
1157
  const t = e.n?.[n];
1168
- if (t !== undefined && t.l & CONFIG_OVERRIDE) return committed(e);
1158
+ if (t?.l & CONFIG_OVERRIDE) return committed(e);
1169
1159
  }
1170
1160
  const o = i !== null && (i.l & CONFIG_HELD) !== 0;
1171
1161
  // A held container: the hold's unit is the key (#3706). A key the HELD
@@ -1218,7 +1208,7 @@ function inDraft(e) {
1218
1208
 
1219
1209
  /** Did the HELD staging (the container node's, not a mainline layer above
1220
1210
  * it) change `key`? */ function heldKeyChanged(e, n, t = true) {
1221
- return changedBetween(e, e.k.Ie, e.k.se, n, t) && !adoptChild(e, n);
1211
+ return changedBetween(e, e.k.Ie, e.k.ue, n, t) && !adoptChild(e, n);
1222
1212
  }
1223
1213
 
1224
1214
  /** The values of a held frame, built once per frame: neither the committed
@@ -1247,23 +1237,23 @@ function rawsOf(e) {
1247
1237
  const t = e.k;
1248
1238
  const r = asBacking(t.Ie);
1249
1239
  const i = r[n];
1250
- const o = t.se[n];
1240
+ const o = t.ue[n];
1251
1241
  const l = Array.isArray(r) ? e.fam?.key : null;
1252
1242
  if (e.s || l === undefined || !sameRow(i, o, l) || !isWrappable(i) || !isWrappable(o) || Array.isArray(i) !== Array.isArray(o) || lookupTarget(i, e.fam) !== undefined || lookupTarget(o, e.fam) !== undefined ||
1253
1243
  // A raw in both frames (the same objects swapped or reordered) is its
1254
1244
  // own row: pairing it with another would alias the two after the commit.
1255
- rawsOf(r).has(o) || rawsOf(t.se).has(i)) return false;
1245
+ rawsOf(r).has(o) || rawsOf(t.ue).has(i)) return false;
1256
1246
  // A raw-marked value wraps to itself, a proxy to its own target: neither
1257
1247
  // is a fresh target around `ov`.
1258
1248
  const u = wrap(i, e, n)[$TARGET];
1259
- if (u === undefined || u.v !== i) return false;
1249
+ if (u?.v !== i) return false;
1260
1250
  adoptPB(u, o, false);
1261
1251
  holdNode(getContainerNode(u), txOf(t));
1262
1252
  return true;
1263
1253
  }
1264
1254
 
1265
1255
  /** A family target's unheld staging, read with no pass (a handler). */ function familyAhead(e) {
1266
- return e.fam !== null && context === null && !(e.k !== null && e.k.l & CONFIG_HELD);
1256
+ return e.fam !== null && context === null && !(e.k?.l & CONFIG_HELD);
1267
1257
  }
1268
1258
 
1269
1259
  /** Did this batch change `key` — value (slot equality), presence, and (for
@@ -1283,7 +1273,7 @@ function rawsOf(e) {
1283
1273
 
1284
1274
  function changedBetween(e, n, t, r, i) {
1285
1275
  if (e.ch || t[$TARGET] !== undefined || Object.getPrototypeOf(t) !== Object.getPrototypeOf(n) || !plainProto(n)) return true;
1286
- if (e.del !== null && e.del.has(r)) return r in n;
1276
+ if (e.del?.has(r)) return r in n;
1287
1277
  const o = hasOwn.call(t, r) || e.ovl && hasOwn.call(e.v, r);
1288
1278
  if (o !== hasOwn.call(n, r)) return true;
1289
1279
  if (!o) return false;
@@ -1297,7 +1287,7 @@ function changedBetween(e, n, t, r, i) {
1297
1287
  * tracked or not, applies the hold and A28 rules a signal's read does. A
1298
1288
  * projection's unheld staging is ahead for a handler (`familyAhead`). */ function nodeValue(e, n, t) {
1299
1289
  let r = read(e);
1300
- if (e.se !== NOT_PENDING && !(e.l & CONFIG_HELD) && context === null && t.fam !== null) r = e.se;
1290
+ if (e.ue !== NOT_PENDING && !(e.l & CONFIG_HELD) && context === null && t.fam !== null) r = e.ue;
1301
1291
  return r === FORCE ? n : r;
1302
1292
  }
1303
1293
 
@@ -1390,7 +1380,7 @@ function changedBetween(e, n, t, r, i) {
1390
1380
  * classification, as core reads it — `heldNotFinal`). */ function holdWithDerive(e, n) {
1391
1381
  const t = e.fam?.node;
1392
1382
  if (t !== undefined && t !== null && !userWrite && // the derive's own write (its draft or landing), not a user setter's
1393
- t.l & CONFIG_HELD && n.se !== NOT_PENDING &&
1383
+ t.l & CONFIG_HELD && n.ue !== NOT_PENDING &&
1394
1384
  // A node carrying a guess is the lane's: its staging is the truth beneath
1395
1385
  // the guess (`setSignal` → `laneWrite`), never re-homed by the store.
1396
1386
  !(n.l & (CONFIG_HELD | CONFIG_OVERRIDE))) {
@@ -1431,7 +1421,7 @@ function changedBetween(e, n, t, r, i) {
1431
1421
  /** A read on an optimistic family that composes the lanes' values: not the
1432
1422
  * draft's (it composed already), not a derive's write-override read (the
1433
1423
  * derive composes on the truth). */ function optRead(e) {
1434
- return e.fam !== null && e.fam.opt === true && !inDraft(e) && !writeOverride;
1424
+ return e.fam?.opt === true && !inDraft(e) && !writeOverride;
1435
1425
  }
1436
1426
 
1437
1427
  /** Pollution keys are never served from the prototype (core R30). */ const UNSAFE_KEYS = new Set([ "__proto__", "prototype", "constructor" ]);
@@ -1514,7 +1504,7 @@ const traps = {
1514
1504
  const i = readSource(e, n);
1515
1505
  // Overlay delete (#3044): a prototype overlay cannot shadow a delete, so
1516
1506
  // deleted keys are tracked aside and read as absent in the pending view.
1517
- if (e.del !== null && i === e.pb && e.del.has(n)) {
1507
+ if (i === e.pb && e.del?.has(n)) {
1518
1508
  if (!inDraft(e) && getObserver() !== null) read(getNode(e, n));
1519
1509
  return undefined;
1520
1510
  }
@@ -1601,7 +1591,7 @@ const traps = {
1601
1591
  if (t !== undefined) return t;
1602
1592
  }
1603
1593
  }
1604
- return n in t && !(e.del !== null && t === e.pb && e.del.has(n));
1594
+ return n in t && !(t === e.pb && e.del?.has(n));
1605
1595
  },
1606
1596
  ownKeys(e) {
1607
1597
  if (verdict !== null && affectsHooks !== null && getObserver() === null) affectsHooks.ro(e, undefined);
@@ -1644,12 +1634,13 @@ const traps = {
1644
1634
  },
1645
1635
  set(e, n, t) {
1646
1636
  const r = inDraft(e);
1647
- const i = !r && writeOverride;
1648
- if (!r && !i) return true;
1637
+ if (!r && !writeOverride) {
1638
+ return true;
1639
+ }
1649
1640
  if (n === "__proto__") return true;
1650
1641
  // pollution guard (core R30)
1651
- const o = e.s ? t : unwrapValue(t);
1652
- const l = ensurePB(e);
1642
+ const i = e.s ? t : unwrapValue(t);
1643
+ const o = ensurePB(e);
1653
1644
  // #4146 (R1: node existence is unobservable; #3706: the hold's unit is
1654
1645
  // the key): a user setter writing a key a HELD container's staging left
1655
1646
  // unchanged would write it into the held staging — read as the hold's
@@ -1661,59 +1652,55 @@ const traps = {
1661
1652
  // A34) — as it would with a reader's leaf. Kept while the container is
1662
1653
  // held (`deferredReleases`).
1663
1654
  if (userWrite && e.k?.l & CONFIG_HELD) deferredReleases.add(getNode(e, n));
1664
- if (Array.isArray(l)) {
1655
+ if (Array.isArray(o)) {
1665
1656
  touch(e, n);
1666
1657
  if (n === "length") e.wk = WK_ALL; else touch(e, "length");
1667
1658
  } else {
1668
1659
  touch(e, n);
1669
- if (!(n in l)) e.kc++;
1670
- }
1671
- if (UNSAFE_KEYS.has(n)) {
1672
- Object.defineProperty(l, n, {
1673
- value: o,
1674
- writable: true,
1675
- enumerable: true,
1676
- configurable: true
1677
- });
1678
- if (e.del !== null) e.del.delete(n);
1679
- return true;
1660
+ if (!(n in o)) e.kc++;
1680
1661
  }
1681
- if (e.ovl && e.sc !== 2 && !hasOwn.call(l, n)) {
1682
- Object.defineProperty(l, n, {
1683
- value: o,
1662
+ const l = UNSAFE_KEYS.has(n);
1663
+ if (l || e.ovl && e.sc !== 2 && !hasOwn.call(o, n)) {
1664
+ Object.defineProperty(o, n, {
1665
+ value: i,
1684
1666
  writable: true,
1685
1667
  enumerable: true,
1686
1668
  configurable: true
1687
1669
  });
1688
- } else l[n] = o;
1689
- if (e.del !== null) e.del.delete(n);
1690
- if (e.s && o !== null && typeof o === "object") markRawOne(o);
1691
- if (i) notifyWrites(e);
1692
- return true;
1670
+ } else o[n] = i;
1671
+ e.del?.delete(n);
1672
+ if (l) return true;
1673
+ if (e.s && i !== null && typeof i === "object") markRawOne(i);
1674
+ if (!r) notifyWrites(e);
1675
+ // a write-override write
1676
+ return true;
1693
1677
  },
1694
1678
  defineProperty(e, n, t) {
1695
1679
  const r = inDraft(e);
1696
- const i = !r && writeOverride;
1697
- if (!r && !i) return true;
1680
+ if (!r && !writeOverride) {
1681
+ return true;
1682
+ }
1698
1683
  if (n === "__proto__") return true;
1699
1684
  if (t.get || t.set) e.a = true;
1700
1685
  if ("value" in t) t = {
1701
1686
  ...t,
1702
1687
  value: unwrapValue(t.value)
1703
1688
  };
1704
- const o = ensurePB(e);
1689
+ const i = ensurePB(e);
1705
1690
  if (e.a || !(t.enumerable && t.writable && t.configurable)) e.sc = 1;
1706
1691
  touch(e, n);
1707
- Object.defineProperty(o, n, t);
1708
- if (e.del !== null) e.del.delete(n);
1709
- if (i) notifyWrites(e);
1710
- return true;
1692
+ Object.defineProperty(i, n, t);
1693
+ e.del?.delete(n);
1694
+ if (!r) notifyWrites(e);
1695
+ // a write-override write
1696
+ return true;
1711
1697
  },
1712
1698
  deleteProperty(e, n) {
1713
1699
  const t = inDraft(e);
1714
- const r = !t && writeOverride;
1715
- if (!t && !r) return true;
1716
- const i = ensurePB(e);
1700
+ if (!t && !writeOverride) {
1701
+ return true;
1702
+ }
1703
+ const r = ensurePB(e);
1717
1704
  touch(e, n);
1718
1705
  // The key count (`kc`, the overlay gate and the rebuild cap) follows a
1719
1706
  // delete the way it follows an add: an own key of the draft leaving — a
@@ -1724,14 +1711,15 @@ const traps = {
1724
1711
  // one" shape drifted the count up by one per write until a three-key
1725
1712
  // object crossed the overlay threshold and paid a rebuild on every
1726
1713
  // commit after.
1727
- const o = e.ovl && hasOwn.call(e.v, n);
1728
- if (hasOwn.call(i, n)) {
1729
- delete i[n];
1730
- o || e.kc--;
1714
+ const i = e.ovl && hasOwn.call(e.v, n);
1715
+ if (hasOwn.call(r, n)) {
1716
+ delete r[n];
1717
+ i || e.kc--;
1731
1718
  }
1732
- if (o) (e.del ??= new Set).add(n);
1733
- if (r) notifyWrites(e);
1734
- return true;
1719
+ if (i) (e.del ??= new Set).add(n);
1720
+ if (!t) notifyWrites(e);
1721
+ // a write-override write
1722
+ return true;
1735
1723
  }
1736
1724
  };
1737
1725
 
@@ -1813,17 +1801,17 @@ function createStore(e, n) {
1813
1801
  * replaced by reference — #2932). The list driver uses this to choose the
1814
1802
  * slot-patch channel (collected row bodies) over per-record registration. */ function storeIsShallow(e) {
1815
1803
  const n = e?.[$TARGET];
1816
- return n !== undefined && n.s === true;
1804
+ return n?.s === true;
1817
1805
  }
1818
1806
 
1819
1807
  /** True when `proxy` belongs to a projection family (S3). */ function storeHasFamily(e) {
1820
1808
  const n = e?.[$TARGET];
1821
- return n !== undefined && n.fam !== null;
1809
+ return n?.fam != null;
1822
1810
  }
1823
1811
 
1824
1812
  /** True when `proxy` belongs to an OPTIMISTIC family (S4). */ function storeHasOptimisticFamily(e) {
1825
1813
  const n = e?.[$TARGET];
1826
- return n !== undefined && n.fam?.opt === true;
1814
+ return n?.fam?.opt === true;
1827
1815
  }
1828
1816
 
1829
1817
  // ---------------------------------------------------------------------------
@@ -1833,7 +1821,7 @@ function visibleKeys(e, n) {
1833
1821
  if (e.ovl && n === e.pb) {
1834
1822
  t = Reflect.ownKeys(e.v);
1835
1823
  const r = e.del;
1836
- if (r !== null && r.size !== 0) t = t.filter(e => !r.has(e));
1824
+ if (r?.size) t = t.filter(e => !r.has(e));
1837
1825
  for (const r of Reflect.ownKeys(n)) {
1838
1826
  if (!hasOwn.call(e.v, r)) t.push(r);
1839
1827
  }
@@ -1851,7 +1839,7 @@ function visibleKeys(e, n) {
1851
1839
  function visibleDescriptor(e, n, t) {
1852
1840
  let r = Object.getOwnPropertyDescriptor(n, t);
1853
1841
  if (e.ovl && n === e.pb) {
1854
- if (e.del !== null && e.del.has(t)) return undefined;
1842
+ if (e.del?.has(t)) return undefined;
1855
1843
  if (r === undefined) r = Object.getOwnPropertyDescriptor(e.v, t);
1856
1844
  }
1857
1845
  return r;
@@ -1862,7 +1850,7 @@ function visibleDescriptor(e, n, t) {
1862
1850
  /** Tracking snapshot: subscribes every reachable record's container and deep
1863
1851
  * witness (one node per record, not one per path), then snapshots. */ function deep(e) {
1864
1852
  const n = e?.[$TARGET];
1865
- if (n === undefined || n.px !== e) return e;
1853
+ if (n?.px !== e) return e;
1866
1854
  const t = new Set;
1867
1855
  const childTarget = (e, n, t) => {
1868
1856
  let r = lookupTarget(n, e.fam);
@@ -17,31 +17,27 @@ const $OWNER = Symbol(0);
17
17
  /** raw → target for plain (family-less) stores. Family stores use their own
18
18
  * map so one raw can wrap once per family (§7b). */ const storeLookup = new WeakMap;
19
19
 
20
- function setLookup(e, o) {
21
- (o.fam?.map ?? storeLookup).set(e, o);
20
+ function setLookup(o, e) {
21
+ (e.fam?.map ?? storeLookup).set(o, e);
22
22
  }
23
23
 
24
- function isOwned(e) {
25
- return e[$OWNER] !== undefined;
24
+ function isOwned(o) {
25
+ return o[$OWNER] !== undefined;
26
26
  }
27
27
 
28
28
  /** The target wrapping `raw` in `fam` (or the plain lookup). An owned raw
29
- * answers from its stamp; a user raw from the map. */ function lookupTarget(e, o) {
30
- const t = e[$OWNER];
31
- return t !== undefined && t.fam === o ? t : (o?.map ?? storeLookup).get(e);
32
- }
33
-
34
- function devAssertNeverUserMutation(e) {
35
- return;
29
+ * answers from its stamp; a user raw from the map. */ function lookupTarget(o, e) {
30
+ const n = o[$OWNER];
31
+ return n !== undefined && n.fam === e ? n : (e?.map ?? storeLookup).get(o);
36
32
  }
37
33
 
38
34
  /** Sticky descendants flag up the parent chain (§6d): adoption descends
39
- * into a changed child pair only where a target with nodes exists below. */ function markDescendants(e) {
40
- let o = e;
41
- while (o && !o.d) {
42
- o.d = true;
43
- o = o.u;
35
+ * into a changed child pair only where a target with nodes exists below. */ function markDescendants(o) {
36
+ let e = o;
37
+ while (e && !e.d) {
38
+ e.d = true;
39
+ e = e.u;
44
40
  }
45
41
  }
46
42
 
47
- export { $OWNER, devAssertNeverUserMutation, isOwned, lookupTarget, markDescendants, setLookup, storeLookup };
43
+ export { $OWNER, isOwned, lookupTarget, markDescendants, setLookup, storeLookup };