@solidjs/signals 2.0.0-rc.6 → 2.0.0-rc.8

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 (131) hide show
  1. package/dist/dev-shared.js +5243 -0
  2. package/dist/dev.attribution.js +2333 -0
  3. package/dist/dev.js +1758 -6621
  4. package/dist/observe/affects.js +127 -0
  5. package/dist/observe/attribution.js +1 -0
  6. package/dist/observe/boundaries.js +586 -0
  7. package/dist/observe/core/action.js +167 -0
  8. package/dist/observe/core/async.js +736 -0
  9. package/dist/observe/core/attribution-hooks.js +60 -0
  10. package/dist/observe/core/attribution.js +2318 -0
  11. package/dist/{types-cjs/core/constants.d.cts → observe/core/constants.js} +135 -71
  12. package/dist/{types-cjs/core/context.d.cts → observe/core/context.js} +37 -12
  13. package/dist/observe/core/core.js +1289 -0
  14. package/dist/observe/core/dev.js +232 -0
  15. package/dist/observe/core/effect.js +179 -0
  16. package/dist/observe/core/error.js +80 -0
  17. package/dist/observe/core/external.js +98 -0
  18. package/dist/observe/core/graph.js +155 -0
  19. package/dist/observe/core/heap.js +147 -0
  20. package/dist/observe/core/invariants.js +43 -0
  21. package/dist/observe/core/lanes.js +168 -0
  22. package/dist/observe/core/optimistic.js +438 -0
  23. package/dist/observe/core/owner.js +308 -0
  24. package/dist/observe/core/scheduler.js +1190 -0
  25. package/dist/observe/core/verdict.js +551 -0
  26. package/dist/observe/index.js +55 -0
  27. package/dist/observe/map.js +482 -0
  28. package/dist/{types-cjs/signals.d.cts → observe/signals.js} +305 -317
  29. package/dist/observe/store/index.js +38 -0
  30. package/dist/observe/store/next/optimistic.js +651 -0
  31. package/dist/observe/store/next/projection.js +242 -0
  32. package/dist/observe/store/next/reconcile.js +373 -0
  33. package/dist/observe/store/next/store.js +2213 -0
  34. package/dist/observe/store/next/target.js +51 -0
  35. package/dist/observe/store/store.js +323 -0
  36. package/dist/observe/store/storePath.js +103 -0
  37. package/dist/observe/store/utils.js +210 -0
  38. package/dist/prod/attribution.js +32 -0
  39. package/dist/prod/boundaries.js +3 -1
  40. package/dist/prod/core/action.js +52 -32
  41. package/dist/prod/core/async.js +177 -128
  42. package/dist/prod/core/attribution-hooks.js +3 -0
  43. package/dist/prod/core/constants.js +32 -1
  44. package/dist/prod/core/context.js +10 -16
  45. package/dist/prod/core/core.js +505 -286
  46. package/dist/prod/core/dev.js +2 -0
  47. package/dist/prod/core/effect.js +72 -43
  48. package/dist/prod/core/external.js +2 -2
  49. package/dist/prod/core/graph.js +40 -36
  50. package/dist/prod/core/heap.js +50 -51
  51. package/dist/prod/core/lanes.js +43 -22
  52. package/dist/prod/core/optimistic.js +224 -80
  53. package/dist/prod/core/owner.js +43 -39
  54. package/dist/prod/core/scheduler.js +347 -232
  55. package/dist/prod/core/verdict.js +71 -74
  56. package/dist/prod/index.js +9 -5
  57. package/dist/prod/map.js +311 -150
  58. package/dist/prod/signals.js +52 -38
  59. package/dist/prod/store/next/optimistic.js +127 -131
  60. package/dist/prod/store/next/projection.js +3 -3
  61. package/dist/prod/store/next/reconcile.js +149 -294
  62. package/dist/prod/store/next/store.js +694 -380
  63. package/dist/prod/store/next/target.js +32 -10
  64. package/dist/prod/store/store.js +12 -14
  65. package/dist/prod/store/utils.js +36 -27
  66. package/dist/types/attribution.d.ts +15 -0
  67. package/dist/types/attribution.prod.d.ts +13 -0
  68. package/dist/types/core/async.d.ts +1 -1
  69. package/dist/types/core/attribution-hooks.d.ts +183 -6
  70. package/dist/types/core/attribution.d.ts +435 -24
  71. package/dist/types/core/constants.d.ts +31 -0
  72. package/dist/types/core/core.d.ts +19 -3
  73. package/dist/types/core/dev.d.ts +165 -26
  74. package/dist/types/core/effect.d.ts +8 -1
  75. package/dist/types/core/heap.d.ts +5 -3
  76. package/dist/types/core/index.d.ts +2 -1
  77. package/dist/types/core/invariants.d.ts +1 -1
  78. package/dist/types/core/lanes.d.ts +17 -0
  79. package/dist/types/core/scheduler.d.ts +69 -4
  80. package/dist/types/core/types.d.ts +29 -9
  81. package/dist/types/index.d.ts +9 -2
  82. package/dist/types/map.d.ts +2 -0
  83. package/dist/types/signals.d.ts +10 -0
  84. package/dist/types/store/index.d.ts +4 -6
  85. package/dist/types/store/next/optimistic.d.ts +4 -2
  86. package/dist/types/store/next/reconcile.d.ts +5 -12
  87. package/dist/types/store/next/store.d.ts +8 -9
  88. package/dist/types/store/next/target.d.ts +56 -55
  89. package/dist/types/store/store.d.ts +14 -9
  90. package/dist/types/store/utils.d.ts +7 -0
  91. package/package.json +21 -16
  92. package/dist/node.cjs +0 -11121
  93. package/dist/prod/store/next/patch-hooks.js +0 -13
  94. package/dist/prod/store/next/patch.js +0 -614
  95. package/dist/types/store/next/patch-hooks.d.ts +0 -41
  96. package/dist/types/store/next/patch.d.ts +0 -91
  97. package/dist/types-cjs/affects.d.cts +0 -47
  98. package/dist/types-cjs/boundaries.d.cts +0 -175
  99. package/dist/types-cjs/core/action.d.cts +0 -64
  100. package/dist/types-cjs/core/async.d.cts +0 -23
  101. package/dist/types-cjs/core/attribution-hooks.d.cts +0 -63
  102. package/dist/types-cjs/core/attribution.d.cts +0 -239
  103. package/dist/types-cjs/core/core.d.cts +0 -176
  104. package/dist/types-cjs/core/dev.d.cts +0 -95
  105. package/dist/types-cjs/core/effect.d.cts +0 -30
  106. package/dist/types-cjs/core/error.d.cts +0 -56
  107. package/dist/types-cjs/core/external.d.cts +0 -15
  108. package/dist/types-cjs/core/graph.d.cts +0 -28
  109. package/dist/types-cjs/core/heap.d.cts +0 -22
  110. package/dist/types-cjs/core/index.d.cts +0 -13
  111. package/dist/types-cjs/core/invariants.d.cts +0 -59
  112. package/dist/types-cjs/core/lanes.d.cts +0 -44
  113. package/dist/types-cjs/core/optimistic.d.cts +0 -6
  114. package/dist/types-cjs/core/owner.d.cts +0 -124
  115. package/dist/types-cjs/core/scheduler.d.cts +0 -231
  116. package/dist/types-cjs/core/types.d.cts +0 -204
  117. package/dist/types-cjs/core/verdict.d.cts +0 -2
  118. package/dist/types-cjs/index.d.cts +0 -10
  119. package/dist/types-cjs/map.d.cts +0 -69
  120. package/dist/types-cjs/package.json +0 -3
  121. package/dist/types-cjs/store/index.d.cts +0 -21
  122. package/dist/types-cjs/store/next/optimistic.d.cts +0 -23
  123. package/dist/types-cjs/store/next/patch-hooks.d.cts +0 -41
  124. package/dist/types-cjs/store/next/patch.d.cts +0 -91
  125. package/dist/types-cjs/store/next/projection.d.cts +0 -8
  126. package/dist/types-cjs/store/next/reconcile.d.cts +0 -17
  127. package/dist/types-cjs/store/next/store.d.cts +0 -127
  128. package/dist/types-cjs/store/next/target.d.cts +0 -192
  129. package/dist/types-cjs/store/store.d.cts +0 -138
  130. package/dist/types-cjs/store/storePath.d.cts +0 -58
  131. package/dist/types-cjs/store/utils.d.cts +0 -74
@@ -1,4 +1,4 @@
1
- import { CONFIG_AUTO_DISPOSE, STATUS_PENDING, NOT_PENDING, CONFIG_OPTIMISTIC, CONFIG_HELD_TRUTH, unwrapOverride } from "../../core/constants.js";
1
+ import { CONFIG_AUTO_DISPOSE, STATUS_PENDING, STATUS_UNINITIALIZED, NOT_PENDING, CONFIG_OPTIMISTIC, CONFIG_HELD_TRUTH, unwrapOverride } from "../../core/constants.js";
2
2
 
3
3
  import { computed, setSignal, isEqual } from "../../core/core.js";
4
4
 
@@ -18,13 +18,11 @@ import { $TARGET, markRawIngest, setNextOptimisticViewResolver, isWrappable, raw
18
18
 
19
19
  import { runProjectionComputedNext } from "./projection.js";
20
20
 
21
- import { wrapNext, runAuthoritative, storeSetterNext, hasActiveOverride, unwrapValue, targetsEqual, getNode, getHasNode, getKeySetNode, bumpDeep, stagedTruthPB, authoritativeRead } from "./store.js";
21
+ import { wrapNext, runAuthoritative, storeSetterNext, hasActiveOverride, unwrapValue, targetsEqual, heldMaskView, getNode, getHasNode, getKeySetNode, bumpDeep, stagedTruthPB, authoritativeRead } from "./store.js";
22
22
 
23
- import { patchHooks, rowHooks } from "./patch-hooks.js";
23
+ import { sameKey } from "./reconcile.js";
24
24
 
25
- import { sameKey, buildIdentityRowOps } from "./reconcile.js";
26
-
27
- import { setOptHooks } from "./target.js";
25
+ import { setOptHooks, $OWNER, lookupTarget } from "./target.js";
28
26
 
29
27
  /**
30
28
  * Store rewrite — optimistic stores (§3/§7, RUL-3): no store-side layer, no
@@ -57,7 +55,7 @@ import { setOptHooks } from "./target.js";
57
55
  * staged values to converge (normal speculation). Resolves merges first:
58
56
  * merge unions optimistic nodes/stores into the target. */ function transitionHoldsOptimism(e) {
59
57
  const t = currentTransition(e);
60
- return t.sn !== true && (t.ze.length !== 0 || t.En.size !== 0);
58
+ return t.ft !== true && (t.it.length !== 0 || t.En.size !== 0);
61
59
  }
62
60
 
63
61
  let blockedInstalled = false;
@@ -78,37 +76,28 @@ function installNextBlockedHalf() {
78
76
  // Scheduler flush tails call _clearOptimisticStores whenever tracked
79
77
  // stores exist; next has no layer to clear — reverts are engine-native —
80
78
  // so the hook only empties the batch set.
81
- if (!GlobalQueue.qt) {
82
- GlobalQueue.qt = e => {
83
- // Patch channel (revert site): engine-native reverts flip node values
84
- // back to committed; patched records need a forced DOM re-apply from
85
- // the post-revert view. Emission only — next keeps no layer to clear.
79
+ if (!GlobalQueue.ni) {
80
+ GlobalQueue.ni = e => {
86
81
  for (const t of e) {
87
82
  const e = t?.[$TARGET];
88
83
  const n = e?.fam?.overlaid;
89
84
  if (n !== undefined) {
90
85
  for (const e of n) {
91
- if (e.pc !== null && e.pc.p !== null) patchHooks.emitPatchOptimistic(e, null, null);
92
- // Row-ops resync (family increment 2): reverts flip node values
93
- // back engine-natively; a driven list must rebuild retention by
94
- // row identity against the post-revert view (resolved from the
95
- // target at drain — overrides are gone by then).
96
- if (e.pc !== null && e.pc.ro !== null) rowHooks.emitRowOpsOptimistic(e, null, null);
97
86
  // Keyset resync (classic channel twin): the keyset node's own
98
87
  // revert can compare EQUAL (a landing's bump matched the
99
88
  // tentative bump) while the arrangement underneath changed —
100
89
  // mapArray/ownKeys subscribers must re-read the post-revert
101
90
  // view. Authoritative bump: never re-arm the node we are
102
91
  // clearing.
103
- if (e.k !== null) runAuthoritative(() => setSignal(e.k, e => e + 1));
92
+ if (e.k !== null) runAuthoritative(() => setSignal(e.k, e => e + 1));
104
93
  }
105
94
  }
106
95
  }
107
96
  e.clear();
108
97
  };
109
98
  }
110
- const e = GlobalQueue.dn;
111
- GlobalQueue.dn = t => {
99
+ const e = GlobalQueue.cn;
100
+ GlobalQueue.cn = t => {
112
101
  for (const e of t.En) {
113
102
  const n = e?.[$TARGET];
114
103
  const i = n?.fam;
@@ -139,10 +128,10 @@ function familyHasLiveOverrides(e) {
139
128
  if (t === null) continue;
140
129
  for (const e of Reflect.ownKeys(t)) {
141
130
  const n = t[e];
142
- if (n.o?.Pe !== undefined && n.o?.Pe !== NOT_PENDING) return true;
131
+ if (n.o?.be !== undefined && n.o?.be !== NOT_PENDING) return true;
143
132
  }
144
133
  }
145
- if (e.k !== null && e.k.o?.Pe !== undefined && e.k.o?.Pe !== NOT_PENDING) return true;
134
+ if (e.k !== null && e.k.o?.be !== undefined && e.k.o?.be !== NOT_PENDING) return true;
146
135
  }
147
136
  t.clear();
148
137
  // nothing live — drop the bookkeeping
@@ -155,23 +144,23 @@ function createOptimisticStoreNext(e, t, n) {
155
144
  installOptimisticEngine();
156
145
  installNextBlockedHalf();
157
146
  const i = typeof e === "function";
158
- if (!i && n === undefined) n = t;
159
- const o = i ? t : e;
160
- const r = {
147
+ const o = i ? n : t;
148
+ const r = i ? t : e;
149
+ const s = {
161
150
  map: new WeakMap,
162
151
  node: null,
163
- shallow: !!n?.shallow,
152
+ shallow: !!o?.shallow,
164
153
  opt: true
165
154
  };
166
- const l = wrapNext(o, null, null, r);
167
- r.px = l;
155
+ const l = wrapNext(r, null, null, s);
156
+ s.px = l;
168
157
  // Same key resolution the projection channels use ("id" default) — replay's
169
158
  // satisfaction rule reads it off the family.
170
- const s = n?.key === undefined ? "id" : n.key;
171
- r.key = typeof s === "function" ? s : s === null ? null : e => isWrappable(e) ? e[s] : undefined;
172
- if (r.shallow) {
159
+ const u = o?.key === undefined ? "id" : o.key;
160
+ s.key = typeof u === "function" ? u : u === null ? null : e => isWrappable(e) ? e[u] : undefined;
161
+ if (s.shallow) {
173
162
  l[$TARGET].s = true;
174
- markRawIngest(o);
163
+ markRawIngest(r);
175
164
  }
176
165
  if (i) {
177
166
  const t = e;
@@ -185,11 +174,11 @@ function createOptimisticStoreNext(e, t, n) {
185
174
  // flight (loading window) keeps the ambient reveal (#2933: the loading
186
175
  // rail is transaction-invisible).
187
176
  const enterFlightTransition = () => {
188
- const e = r.ft;
177
+ const e = s.ft;
189
178
  if (e == null) return;
190
179
  let t = liveTransition(e);
191
- if (t === null) r.ft = t = createTransition();
192
- r.node.Ae = t;
180
+ if (t === null) s.ft = t = createTransition();
181
+ s.node.ge = t;
193
182
  globalQueue.initTransition(t);
194
183
  };
195
184
  // Landing router (#3164 fold ruling): while a transaction retains
@@ -200,9 +189,9 @@ function createOptimisticStoreNext(e, t, n) {
200
189
  // flight-owned transaction (#3146). Sync commits (the derive's body,
201
190
  // owner is the firewall itself) reveal with their own recompute's flush.
202
191
  const wrapCommit = (e, t) => {
203
- const n = retainingTransition(r);
204
- if (n !== null) return void stageLanding(r, n, t);
205
- if (getOwner() !== r.node) enterFlightTransition();
192
+ const n = retainingTransition(s);
193
+ if (n !== null) return void stageLanding(s, n, t);
194
+ if (getOwner() !== s.node) enterFlightTransition();
206
195
  runAuthoritative(e);
207
196
  };
208
197
  // Draft writes (the derive mutating its draft, sync body and post-await
@@ -212,7 +201,7 @@ function createOptimisticStoreNext(e, t, n) {
212
201
  // batch; the write-override eager-commit branch in notifyWrites yields
213
202
  // to any active transaction).
214
203
  const aroundDraftWrite = e => {
215
- const t = retainingTransition(r);
204
+ const t = retainingTransition(s);
216
205
  if (t === null) e(); else runFolded(t, e);
217
206
  };
218
207
  // Flight declaration (#3146): a recompute that registered a truth-flight
@@ -234,33 +223,42 @@ function createOptimisticStoreNext(e, t, n) {
234
223
  // (#2933: the loading rail is transaction-invisible); a sync run clears
235
224
  // the declaration.
236
225
  const declareFlight = e => {
237
- if (e.o?.Ie == null) {
238
- if (!e.Ne) r.ft = null;
226
+ if (e.o?.Pe == null) {
227
+ if (!e.Ae) s.ft = null;
239
228
  return;
240
229
  }
241
- if (e.Ne) return;
230
+ // First flight (#3146 carve-out): nothing has ever committed, so there
231
+ // is no truth to keep on screen and no optimistic state to protect. An
232
+ // uninitialized ask suspends its readers into their Loading boundary
233
+ // exactly like a plain derived store's first flight — declaring a
234
+ // transaction here instead held the ROOT MOUNT (render()'s scheduled
235
+ // insert rides transitions) until the fetch landed, so the boundary's
236
+ // fallback never showed and the whole page stayed blank. The loading
237
+ // window (#2933) already declares nothing for the same reason; once
238
+ // the first truth lands, every refetch flight declares as before.
239
+ if (e.Ae || e.S & STATUS_UNINITIALIZED) return;
242
240
  let t = activeTransition;
243
241
  if (t === null) globalQueue.initTransition(t = createTransition());
244
- r.ft = t;
245
- e.Ae = t;
246
- let n = t._e.get(e);
247
- if (n === undefined) t._e.set(e, n = new Set);
242
+ s.ft = t;
243
+ e.ge = t;
244
+ let n = t.Re.get(e);
245
+ if (n === undefined) t.Re.set(e, n = new Set);
248
246
  n.add(e);
249
247
  };
250
- let i;
251
- if (n?.seedLoadingValue) i = {
248
+ let n;
249
+ if (o?.seedLoadingValue) n = {
252
250
  loadingValue: undefined
253
251
  };
254
- const o = computed(() => {
252
+ const i = computed(() => {
255
253
  const e = getOwner();
256
254
  try {
257
- runAuthoritative(() => runProjectionComputedNext(l, t, n?.key === undefined ? "id" : n.key, wrapCommit, aroundDraftWrite));
255
+ runAuthoritative(() => runProjectionComputedNext(l, t, o?.key === undefined ? "id" : o.key, wrapCommit, aroundDraftWrite));
258
256
  } finally {
259
257
  declareFlight(e);
260
258
  }
261
- }, i);
262
- o.T &= ~CONFIG_AUTO_DISPOSE;
263
- r.node = o;
259
+ }, n);
260
+ i.T &= ~CONFIG_AUTO_DISPOSE;
261
+ s.node = i;
264
262
  }
265
263
  return [ l, e => {
266
264
  // Retention ledger (#3164): record the owning transaction so landings
@@ -270,14 +268,14 @@ function createOptimisticStoreNext(e, t, n) {
270
268
  // per #2951 and dies with it).
271
269
  const t = activeTransition;
272
270
  storeSetterNext(l, e);
273
- if (t !== null) (r.rt ??= new Set).add(t);
271
+ if (t !== null) (s.rt ??= new Set).add(t);
274
272
  } ];
275
273
  }
276
274
 
277
275
  /** Resolve a retained transition through its merge chain (`_done` holds the
278
276
  * merge target while merged, `true` once settled). Null = dead. */ function liveTransition(e) {
279
- while (typeof e.sn === "object") e = e.sn;
280
- return e.sn === true ? null : e;
277
+ while (typeof e.ft === "object") e = e.ft;
278
+ return e.ft === true ? null : e;
281
279
  }
282
280
 
283
281
  /** The transaction truth landings fold into: the first live member of the
@@ -322,10 +320,10 @@ function createOptimisticStoreNext(e, t, n) {
322
320
  * stay unarmed — the override is their display and its revert their
323
321
  * notification, A17). */ function runFolded(e, t) {
324
322
  runAsTransitionBatch(e, t);
325
- const n = e.Lt;
323
+ const n = e.$t;
326
324
  for (let t = 0; t < n.length; t++) {
327
325
  const i = n[t];
328
- i.Ae = e;
326
+ i.ge = e;
329
327
  if (i.T & CONFIG_OPTIMISTIC && !hasActiveOverride(i)) i.T |= CONFIG_HELD_TRUTH;
330
328
  }
331
329
  }
@@ -349,8 +347,8 @@ function createOptimisticStoreNext(e, t, n) {
349
347
  if (!isWrappable(i)) continue;
350
348
  const r = n(i);
351
349
  if (r === undefined) continue;
352
- const l = (o ??= new Map).get(r);
353
- if (l === undefined) o.set(r, [ i ]); else l.push(i);
350
+ const s = (o ??= new Map).get(r);
351
+ if (s === undefined) o.set(r, [ i ]); else s.push(i);
354
352
  }
355
353
  // Echo adoption: an optimistic structural add whose key the landing
356
354
  // confirms must keep its raw (and so its proxy — list drivers keep the
@@ -360,35 +358,35 @@ function createOptimisticStoreNext(e, t, n) {
360
358
  // keys; overlay rows only extend coverage. Adopted raws enter staged
361
359
  // truth; at settle the override reverts and the reveal re-seats the
362
360
  // same raw.
363
- const l = e[$TARGET]?.n;
364
- if (l != null) {
365
- for (const e of Reflect.ownKeys(l)) {
366
- const t = l[e];
361
+ const s = e[$TARGET]?.n;
362
+ if (s != null) {
363
+ for (const e of Reflect.ownKeys(s)) {
364
+ const t = s[e];
367
365
  if (!hasActiveOverride(t)) continue;
368
- const i = unwrapValue(unwrapOverride(t.o.Pe));
366
+ const i = unwrapValue(unwrapOverride(t.o.be));
369
367
  if (!isWrappable(i)) continue;
370
368
  const r = n(i);
371
369
  if (r === undefined) continue;
372
- const s = (o ??= new Map).get(r);
373
- if (s === undefined) o.set(r, [ i ]); else s.push(i);
370
+ const l = (o ??= new Map).get(r);
371
+ if (l === undefined) o.set(r, [ i ]); else l.push(i);
374
372
  }
375
373
  }
376
374
  for (let r = 0; r < i; r++) {
377
375
  const i = t[r];
378
- let l;
376
+ let s;
379
377
  if (isWrappable(i) && o !== null) {
380
378
  const e = n(i);
381
379
  if (e !== undefined) {
382
380
  for (const [t, n] of o) {
383
381
  if (!sameKey(t, e)) continue;
384
- l = n.shift();
382
+ s = n.shift();
385
383
  if (n.length === 0) o.delete(t);
386
384
  break;
387
385
  }
388
386
  }
389
387
  }
390
- if (l !== undefined) {
391
- if (unwrapValue(e[r]) !== l) e[r] = l;
388
+ if (s !== undefined) {
389
+ if (unwrapValue(e[r]) !== s) e[r] = s;
392
390
  stagedApply(e[r], i, n);
393
391
  } else {
394
392
  const t = unwrapValue(e[r]);
@@ -409,15 +407,15 @@ function createOptimisticStoreNext(e, t, n) {
409
407
  // Object merge; also the degenerate root-kind-change shape (arrays accept
410
408
  // keyed writes/deletes, so a wholesale restatement still lands staged).
411
409
  for (const o of Reflect.ownKeys(t)) {
412
- if (i && o === "length") continue;
410
+ if (i && o === "length" || o === $OWNER) continue;
413
411
  const r = t[o];
414
- const l = unwrapValue(e[o]);
415
- if (l === r) continue;
416
- if (isWrappable(r) && isWrappable(l) && Array.isArray(r) === Array.isArray(l)) {
412
+ const s = unwrapValue(e[o]);
413
+ if (s === r) continue;
414
+ if (isWrappable(r) && isWrappable(s) && Array.isArray(r) === Array.isArray(s)) {
417
415
  // Different-keyed entities never merge (tentative-channel parity):
418
416
  // the incoming object replaces the slot wholesale.
419
417
  if (n !== null) {
420
- const t = n(l);
418
+ const t = n(s);
421
419
  const i = n(r);
422
420
  if (t !== undefined && i !== undefined && !sameKey(t, i)) {
423
421
  e[o] = r;
@@ -425,12 +423,12 @@ function createOptimisticStoreNext(e, t, n) {
425
423
  }
426
424
  }
427
425
  stagedApply(e[o], r, n);
428
- } else if (!isEqual(l, r) && !targetsEqual(l, r)) {
426
+ } else if (!isEqual(s, r) && !targetsEqual(s, r)) {
429
427
  e[o] = r;
430
428
  }
431
429
  }
432
430
  for (const n of Reflect.ownKeys(e)) {
433
- if (i && n === "length" || n in t) continue;
431
+ if (i && n === "length" || n === $OWNER || n in t) continue;
434
432
  delete e[n];
435
433
  }
436
434
  }
@@ -453,50 +451,49 @@ function createOptimisticStoreNext(e, t, n) {
453
451
  const e = liveTransition(n);
454
452
  if (e !== null) globalQueue.initTransition(e);
455
453
  }
456
- const i = e.v;
457
- // Patch channel (override-application site): the draft IS the intended
458
- // visible state; prev is the view before these overrides apply. Bypasses
459
- // the transition stashoptimism is visible in flight.
460
- if (e.pc !== null && e.pc.p !== null) patchHooks.emitPatchOptimistic(e, t, optimisticView(e, i));
461
- // Row-ops channel (family increment 2): optimistic STRUCTURE on an array
462
- // rides node overrides it never enters the reconcile walk so a driven
463
- // list must get its structural ops here, lane-timed. Identity diff of the
464
- // pre-write optimistic view against the draft; aligned writes emit nothing.
465
- if (e.pc !== null && e.pc.ro !== null && Array.isArray(t)) {
466
- const n = optimisticView(e, i);
467
- if (Array.isArray(n)) {
468
- const i = buildIdentityRowOps(n, t);
469
- if (i !== null) rowHooks.emitRowOpsOptimistic(e, t, i);
470
- }
471
- }
472
- const visible = (t, n) => {
454
+ // The write is judged against what ordinary readers SEE, not against the
455
+ // committed backing slot: under an adoption hold (#3074) `t.v` is already
456
+ // the truth a live transaction is holding, and an optimistic write equal
457
+ // to it compared as a no-op no override, no lane, and the screen kept
458
+ // the pre-hold value until the transaction committed (#3330's store
459
+ // twin: `s.v = 1` after a `yield` while the derive had already staged
460
+ // `v: 1`). Signal parity: the override reveals on its lane now, with its
461
+ // derivations; the held truth reveals on the transaction's schedule.
462
+ const i = heldMaskView(e) ?? e.v;
463
+ // Compare RAWS on both sides (`nv` below is unwrapped already). A chained
464
+ // target's `old` is the inner store's proxy, whose reads hand back inner
465
+ // child PROXIES; the draft's clone holds the inner raws. Comparing the two
466
+ // as-is marked every untouched row changed, and the overlay then served
467
+ // each from an override as a fresh non-chained target — row identities
468
+ // churned for the life of the action and snapped back at settle (#3323).
469
+ const visible = (t, n) => {
473
470
  const i = e.n?.[t];
474
- return i !== undefined && hasActiveOverride(i) ? unwrapOverride(i.o?.Pe) : n;
471
+ return unwrapValue(i !== undefined && hasActiveOverride(i) ? unwrapOverride(i.o?.be) : n);
475
472
  };
476
473
  const visiblePresent = t => {
477
474
  const n = e.h?.[t];
478
- return n !== undefined && hasActiveOverride(n) ? !!unwrapOverride(n.o?.Pe) : t in i;
475
+ return n !== undefined && hasActiveOverride(n) ? !!unwrapOverride(n.o?.be) : t in i;
479
476
  };
480
477
  let o = false;
481
478
  const r = Array.isArray(t);
482
479
  for (const n of Reflect.ownKeys(t)) {
483
- if (r && n === "length") continue;
484
- const l = unwrapValue(t[n]);
480
+ if (r && n === "length" || n === $OWNER) continue;
481
+ const s = unwrapValue(t[n]);
485
482
  if (!visiblePresent(n)) {
486
483
  // Optimistic add: value node + presence node + membership bump.
487
- setSignal(getNode(e, n, i[n]), () => l);
484
+ setSignal(getNode(e, n, i[n]), () => s);
488
485
  setSignal(getHasNode(e, n, n in i), true);
489
486
  o = true;
490
487
  } else {
491
488
  const t = visible(n, i[n]);
492
- if (!isEqual(t, l) && !targetsEqual(t, l)) {
493
- setSignal(getNode(e, n, t), () => l);
489
+ if (!isEqual(t, s) && !targetsEqual(t, s)) {
490
+ setSignal(getNode(e, n, t), () => s);
494
491
  if (r) o = true;
495
492
  }
496
493
  }
497
494
  }
498
495
  for (const n of Reflect.ownKeys(i)) {
499
- if (r && n === "length") continue;
496
+ if (r && n === "length" || n === $OWNER) continue;
500
497
  if (n in t || !visiblePresent(n)) continue;
501
498
  // Optimistic delete: node reads undefined, presence flips, membership bumps.
502
499
  setSignal(getNode(e, n, i[n]), () => undefined);
@@ -521,7 +518,7 @@ function createOptimisticStoreNext(e, t, n) {
521
518
  e.pb = stagedTruthPB.get(e) ?? null;
522
519
  if (e.pb !== null) stagedTruthPB.delete(e);
523
520
  (e.fam.overlaid ??= new Set).add(e);
524
- GlobalQueue._n?.(e.fam.px ?? e.px);
521
+ GlobalQueue.Nn?.(e.fam.px ?? e.px);
525
522
  }
526
523
 
527
524
  /** Optimistic-view composition for snapshot/deep (O1: snapshot is the CURRENT
@@ -540,7 +537,7 @@ function createOptimisticStoreNext(e, t, n) {
540
537
  for (const e of Reflect.ownKeys(i)) {
541
538
  const n = i[e];
542
539
  if (!hasActiveOverride(n)) continue;
543
- const o = unwrapOverride(n.o?.Pe);
540
+ const o = unwrapOverride(n.o?.be);
544
541
  if (e === "length" && Array.isArray(t)) {
545
542
  if (t.length !== o) ensure().length = o;
546
543
  } else if (!isEqual(t[e], o)) ensure()[e] = o;
@@ -551,7 +548,7 @@ function createOptimisticStoreNext(e, t, n) {
551
548
  for (const e of Reflect.ownKeys(o)) {
552
549
  const i = o[e];
553
550
  if (!hasActiveOverride(i)) continue;
554
- const r = !!unwrapOverride(i.o?.Pe);
551
+ const r = !!unwrapOverride(i.o?.be);
555
552
  if (!r && e in (n ?? t)) delete ensure()[e];
556
553
  }
557
554
  }
@@ -561,12 +558,16 @@ function createOptimisticStoreNext(e, t, n) {
561
558
  function applyTentative(e, t, n) {
562
559
  const i = e.pb ?? e.v;
563
560
  const o = optimisticView(e, i);
564
- const r = e.fam.map;
565
- const l = Array.isArray(t);
566
- if (Array.isArray(o) !== l) return;
561
+ const r = e.fam;
562
+ const s = Array.isArray(t);
563
+ if (Array.isArray(o) !== s) return;
567
564
  // kind change at root: flat overrides below
568
- const s = [];
569
- const u = l ? [ ...t ] : shallowWithSymbols(t);
565
+ const l = [];
566
+ let u;
567
+ if (s) u = [ ...t ]; else {
568
+ u = {};
569
+ for (const e of Reflect.ownKeys(t)) if (e !== $OWNER) u[e] = t[e];
570
+ }
570
571
  const match = (e, t) => {
571
572
  if (!isWrappable(e) || !isWrappable(t)) return null;
572
573
  if (rawValuesUsed && (isRawValue(e) || isRawValue(t))) return null;
@@ -578,15 +579,15 @@ function applyTentative(e, t, n) {
578
579
  // channel — NaN keys are self-equal.
579
580
  if (i !== undefined && o !== undefined && !sameKey(i, o)) return null;
580
581
  }
581
- return r.get(unwrapValue(e)) ?? null;
582
+ return lookupTarget(unwrapValue(e), r) ?? null;
582
583
  };
583
- if (l) {
584
+ if (s) {
584
585
  const e = o;
585
586
  let i = null;
586
587
  for (let o = 0; o < t.length; o++) {
587
588
  const r = t[o];
588
589
  if (!isWrappable(r)) continue;
589
- let l;
590
+ let s;
590
591
  if (n) {
591
592
  const t = n(r);
592
593
  if (t !== undefined) {
@@ -606,30 +607,31 @@ function applyTentative(e, t, n) {
606
607
  }
607
608
  }
608
609
  const o = i.get(t);
609
- if (o === undefined) l = undefined; else if (Array.isArray(o)) {
610
- l = unwrapValue(e[o.shift()]);
610
+ if (o === undefined) s = undefined; else if (Array.isArray(o)) {
611
+ s = unwrapValue(e[o.shift()]);
611
612
  if (o.length === 1) i.set(t, o[0]);
612
613
  } else {
613
- l = unwrapValue(e[o]);
614
+ s = unwrapValue(e[o]);
614
615
  i.delete(t);
615
616
  }
616
- } else l = unwrapValue(e[o]);
617
- } else l = unwrapValue(e[o]);
618
- const a = match(l, r);
617
+ } else s = unwrapValue(e[o]);
618
+ } else s = unwrapValue(e[o]);
619
+ const a = match(s, r);
619
620
  if (a !== null) {
620
621
  // Keep the existing row in the slot (identity preserved); recurse.
621
- u[o] = unwrapValue(l);
622
- s.push([ a, r ]);
622
+ u[o] = unwrapValue(s);
623
+ l.push([ a, r ]);
623
624
  }
624
625
  }
625
626
  } else {
626
627
  for (const e of Reflect.ownKeys(t)) {
628
+ if (e === $OWNER) continue;
627
629
  const n = unwrapValue(o[e]);
628
630
  const i = t[e];
629
631
  const r = match(n, i);
630
632
  if (r !== null) {
631
633
  u[e] = n;
632
- s.push([ r, i ]);
634
+ l.push([ r, i ]);
633
635
  }
634
636
  }
635
637
  }
@@ -639,13 +641,7 @@ function applyTentative(e, t, n) {
639
641
  e.pb = null;
640
642
  notifyOptimisticWrites(e, u);
641
643
  e.pb = a;
642
- for (let e = 0; e < s.length; e++) applyTentative(s[e][0], unwrapValue(s[e][1]), n);
643
- }
644
-
645
- function shallowWithSymbols(e) {
646
- const t = {};
647
- for (const n of Reflect.ownKeys(e)) t[n] = e[n];
648
- return t;
644
+ for (let e = 0; e < l.length; e++) applyTentative(l[e][0], unwrapValue(l[e][1]), n);
649
645
  }
650
646
 
651
647
  export { createOptimisticStoreNext, notifyOptimisticWrites, optimisticView, transitionHoldsOptimism };
@@ -215,8 +215,8 @@ function runProjectionComputedNext(e, t, r, i, o) {
215
215
  // for the whole first flight — the derive works a detached shadow of the
216
216
  // seed so draft writes cannot tear through to readers (#2988). Every commit
217
217
  // point reconciles the shadow through the normal commit path.
218
- const u = n.Ne ? JSON.parse(JSON.stringify(e[$TARGET][STORE_VALUE])) : null;
219
- const l = wrapDraft(e, () => !c || n.o?.Ie === s, o);
218
+ const u = n.Ae ? JSON.parse(JSON.stringify(e[$TARGET][STORE_VALUE])) : null;
219
+ const l = wrapDraft(e, () => !c || n.o?.Pe === s, o);
220
220
  storeSetterNext(l, o => {
221
221
  s = t(u ?? o);
222
222
  c = true;
@@ -230,7 +230,7 @@ function runProjectionComputedNext(e, t, r, i, o) {
230
230
  i ? i(write, t) : write();
231
231
  };
232
232
  const l = handleAsync(n, s, commit);
233
- if (!n.Ne) commit(l);
233
+ if (!n.Ae) commit(l);
234
234
  }, false);
235
235
  return n;
236
236
  }