@solidjs/signals 2.0.0-rc.17 → 2.0.0-rc.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/dist/dev-shared.js +426 -241
  2. package/dist/dev.attribution.js +19 -16
  3. package/dist/dev.js +768 -409
  4. package/dist/observe/boundaries.js +88 -67
  5. package/dist/observe/core/action.js +8 -0
  6. package/dist/observe/core/async.js +183 -138
  7. package/dist/observe/core/attribution.js +30 -28
  8. package/dist/observe/core/constants.js +23 -1
  9. package/dist/observe/core/core.js +185 -157
  10. package/dist/observe/core/effect.js +34 -37
  11. package/dist/observe/core/graph.js +8 -8
  12. package/dist/observe/core/heap.js +5 -5
  13. package/dist/observe/core/lanes.js +104 -84
  14. package/dist/observe/core/owner.js +17 -16
  15. package/dist/observe/core/scheduler.js +61 -47
  16. package/dist/observe/core/truth.js +6 -6
  17. package/dist/observe/core/verdict.js +15 -15
  18. package/dist/observe/deferred.js +40 -38
  19. package/dist/observe/from.js +248 -0
  20. package/dist/observe/index.js +4 -2
  21. package/dist/observe/map.js +22 -22
  22. package/dist/observe/reveal.js +5 -5
  23. package/dist/observe/signals.js +57 -15
  24. package/dist/observe/store/affects.js +1 -1
  25. package/dist/observe/store/hooks.js +3 -0
  26. package/dist/observe/store/optimistic.js +11 -11
  27. package/dist/observe/store/projection.js +34 -21
  28. package/dist/observe/store/reconcile.js +138 -122
  29. package/dist/observe/store/store.js +628 -641
  30. package/dist/observe/store/target.js +1 -5
  31. package/dist/observe/store/utils.js +7 -2
  32. package/dist/prod/boundaries.js +153 -132
  33. package/dist/prod/core/action.js +8 -0
  34. package/dist/prod/core/async.js +242 -197
  35. package/dist/prod/core/constants.js +16 -1
  36. package/dist/prod/core/core.js +166 -138
  37. package/dist/prod/core/effect.js +31 -34
  38. package/dist/prod/core/graph.js +5 -5
  39. package/dist/prod/core/heap.js +12 -12
  40. package/dist/prod/core/lanes.js +98 -78
  41. package/dist/prod/core/owner.js +15 -14
  42. package/dist/prod/core/scheduler.js +64 -50
  43. package/dist/prod/core/truth.js +6 -6
  44. package/dist/prod/core/verdict.js +17 -17
  45. package/dist/prod/deferred.js +40 -38
  46. package/dist/prod/from.js +248 -0
  47. package/dist/prod/index.js +4 -2
  48. package/dist/prod/map.js +14 -14
  49. package/dist/prod/reveal.js +8 -8
  50. package/dist/prod/signals.js +46 -4
  51. package/dist/prod/store/affects.js +1 -1
  52. package/dist/prod/store/hooks.js +3 -0
  53. package/dist/prod/store/optimistic.js +16 -16
  54. package/dist/prod/store/projection.js +22 -9
  55. package/dist/prod/store/reconcile.js +138 -122
  56. package/dist/prod/store/store.js +308 -331
  57. package/dist/prod/store/target.js +13 -17
  58. package/dist/prod/store/utils.js +2 -0
  59. package/dist/types/core/action.d.ts +8 -0
  60. package/dist/types/core/async.d.ts +12 -2
  61. package/dist/types/core/constants.d.ts +25 -0
  62. package/dist/types/core/core.d.ts +33 -4
  63. package/dist/types/core/dev.d.ts +1 -1
  64. package/dist/types/core/index.d.ts +1 -1
  65. package/dist/types/core/lanes.d.ts +5 -1
  66. package/dist/types/core/scheduler.d.ts +17 -3
  67. package/dist/types/from.d.ts +47 -0
  68. package/dist/types/index.d.ts +4 -1
  69. package/dist/types/signals.d.ts +37 -0
  70. package/dist/types/store/target.d.ts +2 -0
  71. package/package.json +1 -1
@@ -83,7 +83,7 @@ function notifyOptimisticWrites(e, n) {
83
83
  // inner store's truth for its key before guessing over it.
84
84
  const o = e.ch ? e.v : null;
85
85
  const guess = (e, n, i, r) => {
86
- if (o !== null) e.Ie = i ? n in t : unwrapValue(t[n]);
86
+ if (o !== null) e.le = i ? n in t : unwrapValue(t[n]);
87
87
  // By value: a function leaf is a value, not an updater (#3017).
88
88
  optimisticWrite(e, () => r);
89
89
  };
@@ -344,7 +344,7 @@ function arrangementEqual(e, n, t) {
344
344
  // keyed arrangement guess's view carries its removed-keys set.
345
345
  if (!i.It || !(t?.l & CONFIG_OVERRIDE) || !t.T.V?.removed) return false;
346
346
  const r = e.T.V;
347
- if ((!e.Ye || !e.Ye(r, n)) && !GlobalQueue.sn(r, n)) {
347
+ if ((!e.je || !e.je(r, n)) && !GlobalQueue.sn(r, n)) {
348
348
  i.folded = foldedRead;
349
349
  insertSubs(e);
350
350
  } else GlobalQueue.tn?.(i);
@@ -365,8 +365,8 @@ function arrangementEqual(e, n, t) {
365
365
  const t = txOf(n);
366
366
  joinPassAt(e, resolveTx(t._parent ?? t));
367
367
  }
368
- if (n.ue !== NOT_PENDING) return n.ue;
369
- return n.l & CONFIG_SLOT_NODE ? GlobalQueue.fn(n) : n.Ie;
368
+ if (n.ie !== NOT_PENDING) return n.ie;
369
+ return n.l & CONFIG_SLOT_NODE ? GlobalQueue.fn(n) : n.le;
370
370
  }
371
371
 
372
372
  function sameRow(e, n, t) {
@@ -430,7 +430,7 @@ function sweepOverlaid() {
430
430
  // The container shows its backing again (a shown arrangement guess
431
431
  // that ended without a landing left its `LaneView` as the value).
432
432
  const t = e.k;
433
- if (t !== null && t.Ie instanceof LaneView) t.Ie = t.Ie.base;
433
+ if (t !== null && t.le instanceof LaneView) t.le = t.le.base;
434
434
  }
435
435
  if (n.size === 0) overlaidFamilies.delete(e);
436
436
  }
@@ -447,8 +447,8 @@ function sweepOverlaid() {
447
447
  if (i !== null) for (const e of Reflect.ownKeys(i)) {
448
448
  const r = i[e];
449
449
  const o = untrack(() => unwrapValue(n[e]));
450
- if (r.Ye && r.Ye(r.Ie, o)) continue;
451
- r.Ie = o;
450
+ if (r.je && r.je(r.le, o)) continue;
451
+ r.le = o;
452
452
  // (The lane's end notified it this epoch when the shown value and the
453
453
  // covered one differed — its readers re-derive already.)
454
454
  if (r.o !== null && r.Ot !== notifyEpoch) {
@@ -460,8 +460,8 @@ function sweepOverlaid() {
460
460
  if (r !== null) for (const e of Reflect.ownKeys(r)) {
461
461
  const i = r[e];
462
462
  const o = untrack(() => e in n);
463
- if (i.Ie === o) continue;
464
- i.Ie = o;
463
+ if (i.le === o) continue;
464
+ i.le = o;
465
465
  if (i.o !== null && i.Ot !== notifyEpoch) {
466
466
  insertSubs(i);
467
467
  t = true;
@@ -470,9 +470,9 @@ function sweepOverlaid() {
470
470
  // The arrangement the readers saw (the shown guess) against the inner's
471
471
  // now: a structural reader re-derives when they differ.
472
472
  const o = e.k;
473
- if (o !== null && o.o !== null && o.Ie instanceof LaneView && o.Ot !== notifyEpoch) {
473
+ if (o !== null && o.o !== null && o.le instanceof LaneView && o.Ot !== notifyEpoch) {
474
474
  const i = Array.isArray(n) ? untrack(() => n.map(unwrapValue)) : n;
475
- if (!arrangementEqual(o.Ie.rows, i, e.fam?.key ?? null)) {
475
+ if (!arrangementEqual(o.le.rows, i, e.fam?.key ?? null)) {
476
476
  insertSubs(o);
477
477
  t = true;
478
478
  }
@@ -1,6 +1,6 @@
1
1
  import { attrHooks } from "../core/attribution-hooks.js";
2
2
 
3
- import { CONFIG_AUTO_DISPOSE, STATUS_PENDING, STATUS_UNINITIALIZED } from "../core/constants.js";
3
+ import { CONFIG_AUTO_DISPOSE, STATUS_PENDING, STATUS_ERROR, STATUS_UNINITIALIZED } from "../core/constants.js";
4
4
 
5
5
  import { computed } from "../core/core.js";
6
6
 
@@ -80,8 +80,8 @@ import { $TARGET, markRawIngest, isWrappable, setWriteOverride } from "./types.j
80
80
  };
81
81
  const s = {
82
82
  get(s, c) {
83
- const u = read(() => e[c]);
84
- return !o && typeof u === "object" && u !== null && c !== $TARGET ? wrapDraft(u, t, r, false, n, i) : u;
83
+ const a = read(() => e[c]);
84
+ return !o && typeof a === "object" && a !== null && c !== $TARGET ? wrapDraft(a, t, r, false, n, i) : a;
85
85
  },
86
86
  has: (t, r) => read(() => r in e),
87
87
  set: (t, r, o) => mutate(() => {
@@ -103,8 +103,8 @@ import { $TARGET, markRawIngest, isWrappable, setWriteOverride } from "./types.j
103
103
  const c = new Proxy(Array.isArray(e) ? [] : {}, s);
104
104
  // The wrapper stands for its store proxy wherever the derive's result
105
105
  // carries it (`wrap`, `unwrapValue`, reconcile's slot matching).
106
- const u = e[$TARGET];
107
- if (u !== undefined) setLookup(c, u);
106
+ const a = e[$TARGET];
107
+ if (a !== undefined) setLookup(c, a);
108
108
  return c;
109
109
  }
110
110
 
@@ -120,8 +120,14 @@ function cloneState(e, t) {
120
120
  * (`notifyStatus`): a verdict or re-derive reader re-runs, any other is
121
121
  * pending derivatively on the derive (its readers hold; it re-runs at the
122
122
  * landing). The leaves do not subscribe to the derive, so the family does
123
- * the walk. */ function wakeFamily(e, t) {
124
- const r = e.node;
123
+ * the walk. */ function wakeFamily(e) {
124
+ const t = e.node;
125
+ // Pending on the derive itself, whatever source took it there (an upstream
126
+ // memo's flight reaches it as a NotReady of that memo, #4271): the leaves
127
+ // are not that source's dependents, so only the family's settle — which
128
+ // retires the derive (`settleFamily`) — reaches the readers parked here. A
129
+ // reader the landing leaves unchanged does not re-run to clear it (#4305).
130
+ const r = new NotReadyError(t);
125
131
  e.woke = true;
126
132
  forEachFamilyNode(e, e => {
127
133
  if (e.o === null) return;
@@ -129,12 +135,12 @@ function cloneState(e, t) {
129
135
  // between them would: a dependent recovering one branch stays pending
130
136
  // through a leaf it still reads (core `retryReaches`), and the landing's
131
137
  // walk retires the copy first (`settleFamily` → `settlePendingSource`).
132
- addPendingSource(e, r);
138
+ addPendingSource(e, t);
133
139
  // Its readers: core's propagation from the leaf — a verdict or re-derive
134
140
  // reader re-runs, any other is pending derivatively on the derive and
135
141
  // queued for the frame (held with it: the frame waits on the flight
136
142
  // through them, `blocked`).
137
- propagateStatus(e, STATUS_PENDING, t);
143
+ propagateStatus(e, STATUS_PENDING, r);
138
144
  });
139
145
  }
140
146
 
@@ -160,6 +166,12 @@ function cloneState(e, t) {
160
166
  });
161
167
  }
162
168
 
169
+ /** A source's status reached the derive by propagation (core
170
+ * `propagateStatus`), its pass not re-run: the family learns it as from the
171
+ * pass's own throw. */ function familyStatus(e) {
172
+ if (e & STATUS_PENDING) wakeFamily(this); else if (e & STATUS_ERROR) errorFamily(this);
173
+ }
174
+
163
175
  function forEachFamilyNode(e, t) {
164
176
  for (const r of e.live) {
165
177
  const e = r.n;
@@ -179,18 +191,18 @@ function forEachFamilyNode(e, t) {
179
191
  const i = getOwner();
180
192
  const s = e[$TARGET];
181
193
  const c = s.fam;
182
- const u = c.run = (c.run || 0) + 1;
194
+ const a = c.run = (c.run || 0) + 1;
183
195
  let l;
184
196
  // Open loading window (seedLoadingValue): the observable store IS commit #0
185
197
  // for the whole first flight — the derive works a detached shadow of the
186
198
  // seed so draft writes cannot tear through to readers (#2988). Every
187
199
  // commit point reconciles the shadow through the normal commit path.
188
- const a = i.ce ? cloneState(s.v, s.s) : null;
200
+ const u = i.ce ? cloneState(s.v, s.s) : null;
189
201
  // The question a write of this run answers: inside a slice, the slice's
190
202
  // (the sync pass); in a continuation — the flight still registered — the
191
203
  // flight's (`handleAsync` stamped it with the action that asked).
192
- const asking = () => question || (i.T !== null && i.T.Se !== null ? i.T.Ee : 0);
193
- const f = wrapDraft(e, () => c.run === u && !isDisposed(i), n, s.s,
204
+ const asking = () => question || (i.T !== null && i.T.Ee !== null ? i.T.de : 0);
205
+ const f = wrapDraft(e, () => c.run === a && !isDisposed(i), n, s.s,
194
206
  // A write after the run returned (a continuation, a callback) arms the
195
207
  // drain itself when no landing will.
196
208
  () => {
@@ -199,14 +211,14 @@ function forEachFamilyNode(e, t) {
199
211
  // The creation run commits directly (a memo's first value is its
200
212
  // `_value`); every later run — a re-derive in a flush, an async landing
201
213
  // — stages and commits with the flush like a memo's recompute.
202
- const d = u === 1;
214
+ const d = a === 1;
203
215
  const pass = () => storeSetter(f, n => {
204
- l = t(a ?? n);
216
+ l = t(u ?? n);
205
217
  const commit = t => {
206
218
  // Shadow run: commit a detached snapshot, never the shadow itself
207
219
  // (adoption takes the value by identity — handing it the live
208
220
  // shadow would fuse the draft to the observable store).
209
- if (a && (t === undefined || t === a)) t = cloneState(a, s.s);
221
+ if (u && (t === undefined || t === u)) t = cloneState(u, s.s);
210
222
  if (t !== n && t !== undefined) {
211
223
  const write = () => {
212
224
  const o = question;
@@ -228,7 +240,7 @@ function forEachFamilyNode(e, t) {
228
240
  // (a fallback value, not pending) re-runs too (#4070).
229
241
  insertSubs(i);
230
242
  };
231
- const u = handleAsync(i, l, commit, (e, t) => {
243
+ const a = handleAsync(i, l, commit, (e, t) => {
232
244
  // The flight rejected: the leaves' readers learn it from here —
233
245
  // they do not subscribe to the derive. Pending again (a NotReady
234
246
  // rejection): the wake, as for the pass. Errored: every live
@@ -236,9 +248,9 @@ function forEachFamilyNode(e, t) {
236
248
  // #2897) — and the flush that runs them advances the clock, so a
237
249
  // later tracked re-read may retry (core `read`).
238
250
  if (d && i.m & STATUS_UNINITIALIZED) return;
239
- if (t) wakeFamily(c, e); else errorFamily(c);
251
+ if (t) wakeFamily(c); else errorFamily(c);
240
252
  });
241
- if (!i.ce) commit(u);
253
+ if (!i.ce) commit(a);
242
254
  }, false);
243
255
  try {
244
256
  d ? runDirect(pass) : pass();
@@ -248,14 +260,14 @@ function forEachFamilyNode(e, t) {
248
260
  // they do not subscribe to the derive.
249
261
  // A synchronous error the same way (#3956: a rerun that finds the
250
262
  // entry failed throws): every live reader re-derives and meets it.
251
- if (!d) e instanceof NotReadyError ? wakeFamily(c, e) : errorFamily(c);
263
+ if (!d) e instanceof NotReadyError ? wakeFamily(c) : errorFamily(c);
252
264
  throw e;
253
265
  }
254
266
  // A pass that returned with a flight up (an iterator's sync first yield):
255
267
  // the wake, as for the throw. Not a sync pass that superseded one — the
256
268
  // status it reads is the dead flight's, cleared when this pass settles
257
269
  // (#3181: a reader the settle walk had just released, re-parked for good).
258
- if (i.m & STATUS_PENDING && i.T.Se !== null && !i.ce && !d) wakeFamily(c, i.T?.F);
270
+ if (i.m & STATUS_PENDING && i.T.Ee !== null && !i.ce && !d) wakeFamily(c);
259
271
  return i;
260
272
  }
261
273
 
@@ -268,6 +280,7 @@ function createProjectionInternal(e, t, r) {
268
280
  map: new WeakMap,
269
281
  node: null,
270
282
  live: new Set,
283
+ st: familyStatus,
271
284
  shallow: !!r?.shallow,
272
285
  // The row key, for a child paired after the adoption (store.ts
273
286
  // `adoptChild`, #3712) as the adoption pairs them.
@@ -24,15 +24,15 @@ import { $TARGET, markRawIngest, isWrappable, rawValuesUsed, isRawValue } from "
24
24
  * identity), unkeyed items fall back to position.
25
25
  */ function reconcileState(e, n, t, o = false) {
26
26
  if (n == null) throw new Error("");
27
- const f = n?.[$TARGET];
28
- if (f === undefined || f.px !== n) throw new Error("");
29
- const l = t === null ? null : typeof t === "string" ? e => e?.[t] : t;
27
+ const f = n[$TARGET];
28
+ if (f?.px !== n) throw new Error("");
29
+ const i = t === null ? null : typeof t === "string" ? e => e?.[t] : t;
30
30
  // A user's reconcile on an optimistic family (S4): not an adoption of
31
31
  // truth but an optimistic edit — the keyed diff is written into the draft
32
32
  // (a matched row keeps its proxy, its changed leaves become its guesses),
33
33
  // and the setter's exit turns the draft into guesses like any.
34
- if (userWriting() && f.fam?.opt === true) {
35
- optHooks.reconcile(n, unwrapValue(e), l);
34
+ if (optHooks && userWriting() && f.fam?.opt === true) {
35
+ optHooks.reconcile(n, unwrapValue(e), i);
36
36
  return;
37
37
  }
38
38
  // Replace-mode root handed another store's proxy: chain to it (§7b).
@@ -43,21 +43,20 @@ import { $TARGET, markRawIngest, isWrappable, rawValuesUsed, isRawValue } from "
43
43
  adoptPB(f, e);
44
44
  return;
45
45
  }
46
- const i = unwrapValue(e);
47
- if (l) {
46
+ const l = unwrapValue(e);
47
+ if (i) {
48
48
  const e = f.pb ?? f.v;
49
- const n = l(e);
50
- if (n !== undefined && !sameKey(l(i), n)) {
49
+ const n = i(e);
50
+ if (n !== undefined && !sameKey(i(l), n)) {
51
51
  if (!o) throw new Error("");
52
52
  // A different entity at the root: the old backing is disowned (wraps
53
53
  // fresh if re-handed) and the new one adopted whole.
54
- const e = f.pb ?? f.v;
55
- if (isOwned(e)) delete e[$OWNER]; else (f.fam?.map ?? storeLookup).delete(e);
56
- adoptPB(f, i);
54
+ if (isOwned(e)) delete e[$OWNER]; else (f.fam?.map ?? storeLookup).delete(e);
55
+ adoptPB(f, l);
57
56
  return;
58
57
  }
59
58
  }
60
- applyAdopt(f, i, l, o);
59
+ applyAdopt(f, l, i, o);
61
60
  }
62
61
 
63
62
  /** Adopt `incoming` at `t` and notify its nodes — one leaf write per
@@ -70,190 +69,207 @@ import { $TARGET, markRawIngest, isWrappable, rawValuesUsed, isRawValue } from "
70
69
  // a deletion here (#3743: the presence and value diffs both read `old`).
71
70
  const f = e.ovl ? materializePB(e) : e.pb ?? e.v;
72
71
  if (n === f && !isOwned(f)) return;
73
- const l = e.fam;
74
72
  // Q-D: a landing on an optimistic family is reconciled against the VIEW
75
73
  // — key matching from the arrangement the guesses made (R28), so a row
76
74
  // the guess added keeps its proxy when the server returns it.
77
- const i = l?.opt === true ? optHooks.view(e, f) : f;
78
- const s = Array.isArray(n);
79
- const u = e.s === true;
80
- const r = f;
75
+ const i = optHooks && e.fam?.opt === true ? optHooks.view(e, f) : f;
76
+ const l = Array.isArray(n);
77
+ const r = e.s === true;
81
78
  adoptPB(e, n, false);
82
- if (u) markRawIngest(n);
83
- if (Array.isArray(i) !== s) {
84
- notifyFold(e, r, n);
79
+ if (r) markRawIngest(n);
80
+ // The deep witness is bumped once per adoption (none to bump: done).
81
+ let u = e.dk === null;
82
+ if (Array.isArray(i) !== l) {
83
+ notifyFold(e, f, n);
85
84
  return;
86
85
  }
87
- if (s) {
88
- const f = i;
89
- const s = n;
90
- const a = e.n;
91
- let c = 0;
92
- if (t && !u) {
93
- const i = f.length;
94
- const u = s.length;
95
- let d = false;
96
- let p = 0;
86
+ if (l) {
87
+ const l = e.n;
88
+ let s = 0;
89
+ if (t && !r) {
90
+ const r = i.length;
91
+ const a = n.length;
92
+ let c = 0;
97
93
  // Aligned prefix: same row (by reference or key) at the same index.
98
- for (const y = Math.min(i, u); p < y; p++) {
99
- const i = s[p];
100
- const u = f[p];
101
- if (u !== i && !sameRow(u, i, t)) break;
94
+ for (const d = Math.min(r, a); c < d; c++) {
95
+ const r = n[c];
96
+ const a = i[c];
97
+ if (a !== r && !sameRow(a, r, t)) break;
102
98
  // misaligned: fall to the keyed remainder below
103
- if ((u !== i || i !== null && typeof i === "object" && isOwned(i)) && i !== null && typeof i === "object") descend(unwrapValue(u), i, t, l, o);
104
- if (e.dk !== null && !d && !(i !== null && typeof i === "object" ? targetsEqual(u, i) : isEqual(u, i))) {
99
+ if (r !== null && typeof r === "object" && (a !== r || isOwned(r))) descend(unwrapValue(a), r, t, o, e, c);
100
+ if (!u && !(r !== null && typeof r === "object" ? targetsEqual(a, r) : isEqual(a, r))) {
105
101
  bumpDeep(e);
106
- d = true;
102
+ u = true;
107
103
  }
108
- if (a !== null) {
109
- const e = a[p];
104
+ if (l !== null) {
105
+ const e = l[c];
110
106
  if (e !== undefined) {
111
- c++;
112
- notifyKeyValue(e, p, r[p], i, r, n);
107
+ s++;
108
+ notifyKeyValue(e, c, f[c], r, f, n);
113
109
  }
114
110
  }
115
111
  }
116
- if (e.dk !== null && !d && p < s.length) bumpDeep(e);
117
- const y = p;
112
+ if (!u && c < n.length) bumpDeep(e);
113
+ const d = c;
118
114
  // misalignment point (== nlen on aligned ticks)
119
- let w = null;
120
- for (;p < s.length; p++) {
121
- const e = s[p];
122
- if (e !== null && typeof e === "object") {
123
- const n = t(e);
124
- let i;
115
+ let p = null;
116
+ for (;c < n.length; c++) {
117
+ const r = n[c];
118
+ if (r !== null && typeof r === "object") {
119
+ const n = t(r);
120
+ let f;
125
121
  if (n !== undefined) {
126
- if (w === null) {
127
- w = new Map;
128
- for (let e = y; e < f.length; e++) {
129
- const n = unwrapValue(f[e]);
122
+ if (p === null) {
123
+ p = new Map;
124
+ for (let e = d; e < i.length; e++) {
125
+ const n = unwrapValue(i[e]);
130
126
  if (n !== null && typeof n === "object") {
131
127
  const o = t(n);
132
128
  if (o === undefined) continue;
133
- const f = w.get(o);
134
- if (f === undefined) w.set(o, e); else if (Array.isArray(f)) f.push(e); else w.set(o, [ f, e ]);
129
+ const f = p.get(o);
130
+ if (f === undefined) p.set(o, e); else if (Array.isArray(f)) f.push(e); else p.set(o, [ f, e ]);
135
131
  }
136
132
  }
137
133
  }
138
- const e = w.get(n);
139
- if (e === undefined) i = undefined; else if (Array.isArray(e)) {
140
- i = unwrapValue(f[e.shift()]);
141
- if (e.length === 1) w.set(n, e[0]);
134
+ const e = p.get(n);
135
+ if (e === undefined) f = undefined; else if (Array.isArray(e)) {
136
+ f = unwrapValue(i[e.shift()]);
137
+ if (e.length === 1) p.set(n, e[0]);
142
138
  } else {
143
- i = unwrapValue(f[e]);
144
- w.delete(n);
139
+ f = unwrapValue(i[e]);
140
+ p.delete(n);
145
141
  }
146
142
  } else {
147
- i = unwrapValue(f[p]);
143
+ f = unwrapValue(i[c]);
148
144
  // keyless item: positional fallback
149
145
  }
150
- descend(i, e, t, l, o);
146
+ descend(f, r, t, o, e, c);
151
147
  }
152
- if (a !== null) {
153
- const e = a[p];
148
+ if (l !== null) {
149
+ const e = l[c];
154
150
  if (e !== undefined) {
155
- c++;
156
- notifyKeyDiff(e, p, r, n, false);
151
+ s++;
152
+ notifyKeyDiff(e, c, f, n, false);
157
153
  }
158
154
  }
159
155
  }
160
156
  } else {
161
- const i = Math.min(f.length, s.length);
162
- const d = s.length;
163
- let p = false;
164
- for (let y = 0; y < d; y++) {
165
- const d = s[y];
166
- if (!u && y < i && d !== null && typeof d === "object") descend(unwrapValue(f[y]), d, t, l, o);
167
- if (e.dk !== null && !p && !(d !== null && typeof d === "object" ? targetsEqual(f[y], d) : isEqual(f[y], d))) {
157
+ const a = Math.min(i.length, n.length);
158
+ const c = n.length;
159
+ for (let d = 0; d < c; d++) {
160
+ const c = n[d];
161
+ if (!r && d < a && c !== null && typeof c === "object") descend(unwrapValue(i[d]), c, t, o, e, d);
162
+ if (!u && !(c !== null && typeof c === "object" ? targetsEqual(i[d], c) : isEqual(i[d], c))) {
168
163
  bumpDeep(e);
169
- p = true;
164
+ u = true;
170
165
  }
171
- if (a !== null) {
172
- const e = a[y];
166
+ if (l !== null) {
167
+ const e = l[d];
173
168
  if (e !== undefined) {
174
- c++;
175
- notifyKeyDiff(e, y, r, n, false);
169
+ s++;
170
+ notifyKeyDiff(e, d, f, n, false);
176
171
  }
177
172
  }
178
173
  }
179
174
  }
180
175
  // Indices past the new length (and `length` itself) still have nodes.
181
- if (a !== null && c < e.nc) {
182
- for (const e of Reflect.ownKeys(a)) {
176
+ if (l !== null && s < e.nc) {
177
+ for (const e of Reflect.ownKeys(l)) {
183
178
  const t = typeof e === "string" ? +e : NaN;
184
- if (!(t >= 0 && t < s.length)) notifyKeyDiff(a[e], e, r, n, false);
179
+ if (!(t >= 0 && t < n.length)) notifyKeyDiff(l[e], e, f, n, false);
185
180
  }
186
181
  }
187
- notifyFoldTail(e, r, n);
182
+ notifyFoldTail(e, f, n);
188
183
  return;
189
184
  }
190
- const a = e.n;
191
- let c = 0;
192
- let d = false;
193
- for (const f in n) {
194
- const s = n[f];
195
- const p = r[f];
196
- const y = s !== null && typeof s === "object";
197
- if (p === s && (!y || !isOwned(s)) && (a === null || a[f] === undefined || !hasAccessorFlag(a[f]))) {
198
- if (a !== null && a[f] !== undefined) c++;
185
+ const s = e.n;
186
+ let a = 0;
187
+ for (const l in n) {
188
+ const c = n[l];
189
+ const d = f[l];
190
+ const p = c !== null && typeof c === "object";
191
+ if (d === c && (!p || !isOwned(c)) && (s === null || s[l] === undefined || !hasAccessorFlag(s[l]))) {
192
+ if (s?.[l] !== undefined) a++;
199
193
  continue;
200
194
  }
201
- if (y && !u) descend(unwrapValue(i[f]), s, t, l, o);
202
- if (e.dk !== null && !d && !(y ? targetsEqual(p, s) : isEqual(p, s))) {
195
+ if (p && !r) descend(unwrapValue(i[l]), c, t, o, e, l);
196
+ if (!u && !(p ? targetsEqual(d, c) : isEqual(d, c))) {
203
197
  bumpDeep(e);
204
- d = true;
198
+ u = true;
205
199
  }
206
- if (a !== null) {
207
- const e = a[f];
200
+ if (s !== null) {
201
+ const e = s[l];
208
202
  if (e !== undefined) {
209
- c++;
210
- notifyKeyValue(e, f, p, s, r, n);
203
+ a++;
204
+ notifyKeyValue(e, l, d, c, f, n);
211
205
  }
212
206
  }
213
207
  }
214
- const p = Object.getOwnPropertySymbols(n);
215
- for (let e = 0; e < p.length; e++) {
216
- const f = p[e];
217
- if (f === $OWNER) continue;
218
- const i = n[f];
219
- if (!u && i !== null && typeof i === "object") descend(unwrapValue(r[f]), i, t, l, o);
220
- if (a !== null) {
221
- const e = a[f];
208
+ const c = Object.getOwnPropertySymbols(n);
209
+ for (let i = 0; i < c.length; i++) {
210
+ const l = c[i];
211
+ if (l === $OWNER) continue;
212
+ const u = n[l];
213
+ if (!r && u !== null && typeof u === "object") descend(unwrapValue(f[l]), u, t, o, e, l);
214
+ if (s !== null) {
215
+ const e = s[l];
222
216
  if (e !== undefined) {
223
- c++;
224
- notifyKeyValue(e, f, r[f], i, r, n);
217
+ a++;
218
+ notifyKeyValue(e, l, f[l], u, f, n);
225
219
  }
226
220
  }
227
221
  }
228
222
  // Keys the incoming object no longer has still have nodes.
229
- if (a !== null && c < e.nc) {
230
- for (const e of Reflect.ownKeys(a)) {
231
- if (!hasOwnP.call(n, e)) notifyKeyDiff(a[e], e, r, n, false);
223
+ if (s !== null && a < e.nc) {
224
+ for (const e of Reflect.ownKeys(s)) {
225
+ if (!hasOwnP.call(n, e)) notifyKeyDiff(s[e], e, f, n, false);
232
226
  }
233
227
  }
234
- notifyFoldTail(e, r, n);
228
+ notifyFoldTail(e, f, n);
235
229
  }
236
230
 
237
231
  const hasOwnP = Object.prototype.hasOwnProperty;
238
232
 
239
233
  /** Descend into a changed child pair — only where something is proxied
240
234
  * below (§6d), never into a raw-marked leaf, never across array/object or a
241
- * key mismatch (that is a replacement, handled by the parent's slot). */ function descend(e, n, t, o, f = false) {
242
- if (e === null || typeof e !== "object" || n === null || typeof n !== "object") return;
243
- const l = lookupTarget(e, o);
244
- if (l === undefined) return;
235
+ * key mismatch (that is a replacement, handled by the parent's slot).
236
+ *
237
+ * A raw in both frames (the same objects swapped, reordered or shifted,
238
+ * #4001) must not leave two slots on one row. A raw already a live row keeps
239
+ * it at the slot it moved to; a row's `pk` follows the slot it sits at (a
240
+ * move or a pairing writes it), so a row whose raw is at that slot of the
241
+ * incoming frame is spoken for and not paired again here; a raw still
242
+ * resolving to a row that moved on drops the lookup (it wraps fresh, or is
243
+ * paired here). One lookup of `nv` on the common path, no allocation. */ function descend(e, n, t, o, f, i) {
244
+ // `nv` is an object at every call site.
245
+ if (e === null || typeof e !== "object") return;
246
+ const l = f.fam;
247
+ n = unwrapValue(n);
248
+ let r = lookupTarget(e, l);
249
+ const u = lookupTarget(n, l);
250
+ if (r !== undefined && r.pk !== i) {
251
+ if (r.pk != i && f.v[r.pk] === r.v) r = undefined; else if (r.u === f) r.pk = i;
252
+ }
253
+ if (u !== undefined && u !== r) {
254
+ if (u.v === n) {
255
+ if (u.u === f) u.pk = i;
256
+ return;
257
+ }
258
+ (l?.map ?? storeLookup).delete(n);
259
+ }
260
+ if (r === undefined) return;
245
261
  // nothing proxied below this pair
246
262
  if (!isWrappable(n)) return;
247
263
  if (rawValuesUsed && isRawValue(n)) return;
248
- n = unwrapValue(n);
249
264
  if (Array.isArray(e) !== Array.isArray(n)) return;
250
- if (t) {
265
+ // An array slot was paired by key already (or both rows are keyless).
266
+ if (typeof i !== "number" && t) {
251
267
  const o = t(e);
252
268
  const f = t(n);
253
269
  if (o !== undefined && f !== undefined && !sameKey(o, f)) return;
254
270
  }
255
- if (!f && t !== null && !l.d) return;
256
- applyAdopt(l, n, t, f);
271
+ if (!o && t !== null && !r.d) return;
272
+ applyAdopt(r, n, t, o);
257
273
  }
258
274
 
259
275
  export { reconcileState };