@solidjs/signals 2.0.0-rc.13 → 2.0.0-rc.15

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 (121) hide show
  1. package/dist/dev-shared.js +2059 -3768
  2. package/dist/dev.attribution.js +237 -101
  3. package/dist/dev.js +7466 -8497
  4. package/dist/observe/affects.js +128 -104
  5. package/dist/observe/boundaries.js +492 -665
  6. package/dist/observe/core/action.js +63 -66
  7. package/dist/observe/core/async.js +243 -379
  8. package/dist/observe/core/attribution-queries.js +1 -1
  9. package/dist/observe/core/attribution.js +394 -253
  10. package/dist/observe/core/constants.js +120 -187
  11. package/dist/observe/core/context.js +3 -3
  12. package/dist/observe/core/core.js +874 -1440
  13. package/dist/observe/core/dev.js +3 -3
  14. package/dist/observe/core/effect.js +73 -84
  15. package/dist/observe/core/external.js +5 -5
  16. package/dist/observe/core/graph.js +62 -71
  17. package/dist/observe/core/heap.js +75 -98
  18. package/dist/observe/core/invariants.js +1 -34
  19. package/dist/observe/core/lanes.js +750 -181
  20. package/dist/observe/core/owner.js +80 -101
  21. package/dist/observe/core/scheduler.js +719 -1356
  22. package/dist/observe/core/verdict.js +314 -621
  23. package/dist/observe/flatten.js +79 -0
  24. package/dist/observe/index.js +15 -13
  25. package/dist/observe/map.js +232 -235
  26. package/dist/observe/reveal.js +212 -0
  27. package/dist/observe/signals.js +144 -216
  28. package/dist/observe/store/affects.js +142 -0
  29. package/dist/observe/store/hooks.js +13 -0
  30. package/dist/observe/store/index.js +27 -24
  31. package/dist/observe/store/optimistic.js +571 -0
  32. package/dist/observe/store/projection.js +308 -0
  33. package/dist/observe/store/reconcile.js +259 -0
  34. package/dist/observe/store/store.js +1988 -277
  35. package/dist/observe/store/storePath.js +1 -1
  36. package/dist/{prod/store/next → observe/store}/target.js +17 -18
  37. package/dist/observe/store/types.js +73 -0
  38. package/dist/observe/store/utils.js +1 -13
  39. package/dist/prod/affects.js +130 -106
  40. package/dist/prod/boundaries.js +476 -654
  41. package/dist/prod/core/action.js +71 -74
  42. package/dist/prod/core/async.js +306 -444
  43. package/dist/prod/core/constants.js +117 -186
  44. package/dist/prod/core/context.js +3 -3
  45. package/dist/prod/core/core.js +888 -1462
  46. package/dist/prod/core/effect.js +88 -99
  47. package/dist/prod/core/external.js +5 -5
  48. package/dist/prod/core/graph.js +62 -71
  49. package/dist/prod/core/heap.js +75 -98
  50. package/dist/prod/core/invariants.js +1 -32
  51. package/dist/prod/core/lanes.js +712 -181
  52. package/dist/prod/core/owner.js +75 -96
  53. package/dist/prod/core/scheduler.js +686 -1335
  54. package/dist/prod/core/verdict.js +309 -621
  55. package/dist/prod/flatten.js +77 -0
  56. package/dist/prod/index.js +15 -13
  57. package/dist/prod/map.js +142 -145
  58. package/dist/prod/reveal.js +212 -0
  59. package/dist/prod/signals.js +155 -227
  60. package/dist/prod/store/affects.js +142 -0
  61. package/dist/prod/store/hooks.js +13 -0
  62. package/dist/prod/store/index.js +26 -19
  63. package/dist/prod/store/optimistic.js +566 -0
  64. package/dist/prod/store/projection.js +301 -0
  65. package/dist/prod/store/reconcile.js +259 -0
  66. package/dist/prod/store/store.js +1883 -272
  67. package/dist/prod/store/storePath.js +1 -1
  68. package/dist/{observe/store/next → prod/store}/target.js +13 -17
  69. package/dist/prod/store/types.js +73 -0
  70. package/dist/prod/store/utils.js +1 -11
  71. package/dist/types/affects.d.ts +11 -30
  72. package/dist/types/boundaries.d.ts +66 -176
  73. package/dist/types/carved.d.ts +1 -0
  74. package/dist/types/core/action.d.ts +5 -6
  75. package/dist/types/core/async.d.ts +10 -5
  76. package/dist/types/core/attribution-hooks.d.ts +20 -1
  77. package/dist/types/core/attribution.d.ts +26 -11
  78. package/dist/types/core/constants.d.ts +130 -180
  79. package/dist/types/core/core.d.ts +134 -264
  80. package/dist/types/core/dev.d.ts +2 -2
  81. package/dist/types/core/effect.d.ts +0 -7
  82. package/dist/types/core/graph.d.ts +7 -1
  83. package/dist/types/core/heap.d.ts +5 -7
  84. package/dist/types/core/index.d.ts +5 -5
  85. package/dist/types/core/invariants.d.ts +0 -29
  86. package/dist/types/core/lanes.d.ts +74 -86
  87. package/dist/types/core/owner.d.ts +3 -3
  88. package/dist/types/core/scheduler.d.ts +255 -331
  89. package/dist/types/core/types.d.ts +45 -85
  90. package/dist/types/core/verdict.d.ts +3 -0
  91. package/dist/types/flatten.d.ts +8 -0
  92. package/dist/types/index.d.ts +6 -4
  93. package/dist/types/reveal.d.ts +19 -0
  94. package/dist/types/signals.d.ts +35 -91
  95. package/dist/types/store/affects.d.ts +12 -0
  96. package/dist/types/store/hooks.d.ts +48 -0
  97. package/dist/types/store/index.d.ts +34 -15
  98. package/dist/types/store/optimistic.d.ts +23 -0
  99. package/dist/types/store/projection.d.ts +18 -0
  100. package/dist/types/store/reconcile.d.ts +3 -0
  101. package/dist/types/store/store.d.ts +132 -145
  102. package/dist/types/store/storePath.d.ts +1 -1
  103. package/dist/types/store/target.d.ts +151 -0
  104. package/dist/types/store/types.d.ts +84 -0
  105. package/package.json +1 -1
  106. package/dist/observe/core/optimistic.js +0 -669
  107. package/dist/observe/store/next/optimistic.js +0 -717
  108. package/dist/observe/store/next/projection.js +0 -266
  109. package/dist/observe/store/next/reconcile.js +0 -375
  110. package/dist/observe/store/next/store.js +0 -2608
  111. package/dist/prod/core/optimistic.js +0 -658
  112. package/dist/prod/store/next/optimistic.js +0 -710
  113. package/dist/prod/store/next/projection.js +0 -257
  114. package/dist/prod/store/next/reconcile.js +0 -373
  115. package/dist/prod/store/next/store.js +0 -2484
  116. package/dist/types/core/optimistic.d.ts +0 -6
  117. package/dist/types/store/next/optimistic.d.ts +0 -25
  118. package/dist/types/store/next/projection.d.ts +0 -27
  119. package/dist/types/store/next/reconcile.d.ts +0 -10
  120. package/dist/types/store/next/store.d.ts +0 -145
  121. package/dist/types/store/next/target.d.ts +0 -196
@@ -1,44 +1,47 @@
1
- import "../core/core.js";
1
+ import { createStore as createStore$1, deep as deep$1, snapshot as snapshot$1 } from "./store.js";
2
2
 
3
- import "../core/dev.js";
3
+ export { storeHasFamily, storeHasOptimisticFamily, storeIsShallow } from "./store.js";
4
4
 
5
- import "../core/scheduler.js";
5
+ export { createOptimisticStore } from "./optimistic.js";
6
6
 
7
- import "../core/invariants.js";
7
+ import { createStoreDerived } from "./projection.js";
8
8
 
9
- import "../core/verdict.js";
9
+ export { createProjection } from "./projection.js";
10
10
 
11
- import "../core/effect.js";
11
+ import { reconcileState } from "./reconcile.js";
12
12
 
13
- import { createStoreNext, nameStore, deepNext, snapshotNext } from "./next/store.js";
13
+ import "../core/verdict.js";
14
14
 
15
- export { storeHasFamily, storeHasOptimisticFamily, storeIsShallow } from "./next/store.js";
15
+ import "../core/core.js";
16
16
 
17
- import { reconcileNextState } from "./next/reconcile.js";
17
+ import "../core/dev.js";
18
18
 
19
- import { createStoreDerivedNext } from "./next/projection.js";
19
+ import "../core/scheduler.js";
20
+
21
+ import "../core/effect.js";
20
22
 
21
- export { createProjectionNext as createProjection } from "./next/projection.js";
23
+ import "../core/lanes.js";
22
24
 
23
- function createStore(e, t, r) {
24
- if (typeof e === "function") return createStoreDerivedNext(e, t, r);
25
- {
26
- const r = createStoreNext(e, !!t?.shallow);
27
- if (t?.name) nameStore(r[0], t.name);
28
- return r;
29
- }
25
+ function createStore(e, r, t) {
26
+ if (typeof e === "function") return createStoreDerived(e, r, t);
27
+ return createStore$1(e, r);
30
28
  }
31
29
 
32
- function reconcile(e, t = "id") {
33
- return r => reconcileNextState(e, r, t);
30
+ /**
31
+ * A setter transform that reconciles `value` into the store by key
32
+ * (`"id"` by default; `null` positional), preserving store identity for
33
+ * surviving rows.
34
+ */ function reconcile(e, r = "id") {
35
+ return t => reconcileState(e, t, r);
34
36
  }
35
37
 
36
- function snapshot(e) {
37
- return snapshotNext(e);
38
+ /** Non-tracking snapshot of a store's current value (source identity for
39
+ * unmodified subtrees). */ function snapshot(e) {
40
+ return snapshot$1(e);
38
41
  }
39
42
 
40
- function deep(e) {
41
- return deepNext(e);
43
+ /** Tracking snapshot: subscribes to every reachable record. */ function deep(e) {
44
+ return deep$1(e);
42
45
  }
43
46
 
44
47
  export { createStore, deep, reconcile, snapshot };
@@ -0,0 +1,571 @@
1
+ import { CONFIG_OVERRIDE, CONFIG_AUTO_DISPOSE, NOT_PENDING } from "../core/constants.js";
2
+
3
+ import { computed, ext, untrack, read, isEqual } from "../core/core.js";
4
+
5
+ import { pendingGuessOf, laneValueOf, optimisticWrite } from "../core/lanes.js";
6
+
7
+ import { getOwner } from "../core/owner.js";
8
+
9
+ import { GlobalQueue, txOf, list, insertSubs, laneDirty, notifyEpoch, schedule } from "../core/scheduler.js";
10
+
11
+ import { runProjectionComputed } from "./projection.js";
12
+
13
+ import { wrap, nameStore, storeSetter, LaneView, committed, getNode, unwrapValue, sameKey, resolveChainedRaw, getHasNode, targetsEqual, getContainerNode, cloneRaw } from "./store.js";
14
+
15
+ import { installOptHooks } from "./hooks.js";
16
+
17
+ import { $OWNER } from "./target.js";
18
+
19
+ import { $TARGET, markRawIngest, $TRACK, isWrappable } from "./types.js";
20
+
21
+ /**
22
+ * Store — optimistic stores on lanes (plan sec. 31, S4; INTERNALS §3/§7, RUL-3).
23
+ *
24
+ * No store-side layer, no backup snapshots, no retaining ledger: a user
25
+ * write to an optimistic store is a GUESS on the written key's node
26
+ * (`optimisticWrite` — the same write `createOptimistic`'s setter makes),
27
+ * a presence guess on its presence node, and, when membership or
28
+ * arrangement changed, an arrangement guess on the container node. Lanes
29
+ * do the rest: the guess shows under the action's hold, a landing beneath
30
+ * it stages as truth and confirms it when equal (A18/A24), the action's
31
+ * settle dissolves it (a revert to the value it covered, or the landed
32
+ * truth). The committed backing is never touched by a guess.
33
+ *
34
+ * Reads compose: a reader of an overlaid target sees the truth it is served
35
+ * with the lanes' values over it (`optimisticView` — per node, by the same
36
+ * rule a leaf read follows: what the lane shows).
37
+ *
38
+ * Landings (Q-D, plan sec. 31.7): the derive's output is reconciled against the
39
+ * optimistic VIEW — a row the guess added and the server returns with the
40
+ * same key in the same position keeps its proxy (the row target adopts the
41
+ * server object), its leaves write truth beneath their guesses, and the
42
+ * container's arrangement guess is confirmed silently (`LaneView`'s
43
+ * comparator) — `For` does not run. Retained-setter replay (the
44
+ * 2026-08-31b continuation half) is not built here; the matrix decides.
45
+ */ const hasOwn = Object.prototype.hasOwnProperty;
46
+
47
+ /** A user setter's writes on an optimistic family, as guesses: one per
48
+ * changed key's leaf, one per presence change, the container's arrangement
49
+ * when membership or order changed. `pb` is the draft (a clone of the view
50
+ * the user saw); `old` the view it composed on. */
51
+ /** An optimistic setter's targets whose staging was set aside (`draft`),
52
+ * restored when the setter's writes become guesses (`writes`). */ const optStaged = new Map;
53
+
54
+ // A chained backing is a proxy: reading it as a handler can expose a
55
+ // derived store's staging. Compose the writer's view on the committed
56
+ // backing of each link, retaining any optimistic guesses on that link.
57
+ function writerBacking(e) {
58
+ const n = committed(e);
59
+ const t = n[$TARGET];
60
+ return t === undefined ? n : optimisticView(t, writerBacking(t), laneValueOf, true);
61
+ }
62
+
63
+ /** The user's draft on an optimistic family: a clone of the view the user
64
+ * saw — the committed frame with the lanes' values and the tick's own
65
+ * unflushed guesses over it (#3665). A staging already on the target (a
66
+ * landing adopted this flush) is set aside for the setter's duration: the
67
+ * guesses go over it, it stays the truth beneath. */ function optimisticDraft(e) {
68
+ if (e.pb !== null) optStaged.set(e, e.pb);
69
+ return cloneRaw(optimisticView(e, writerBacking(e), laneValueOf, true), e);
70
+ }
71
+
72
+ function notifyOptimisticWrites(e, n) {
73
+ // The view the user saw: the committed frame (a staging adopted eagerly
74
+ // is not it) with the lanes' values and the tick's own guesses over it.
75
+ const t = writerBacking(e);
76
+ const i = optimisticView(e, t, laneValueOf, true);
77
+ const r = Array.isArray(n);
78
+ // A chained target's nodes are links (§7b): their committed value is
79
+ // never served and never learns the inner store's commits — yet a guess
80
+ // is judged against it, and reverts to it (#3672). Hand the node the
81
+ // inner store's truth for its key before guessing over it.
82
+ const o = e.ch ? e.v : null;
83
+ const guess = (e, n, i, r) => {
84
+ if (o !== null) e.Ae = i ? n in t : unwrapValue(t[n]);
85
+ // By value: a function leaf is a value, not an updater (#3017).
86
+ optimisticWrite(e, () => r);
87
+ };
88
+ let s = false;
89
+ for (const t of Reflect.ownKeys(n)) {
90
+ if (r && t === "length" || t === $OWNER) continue;
91
+ // A chained draft holds the inner store's raws; a raw is the inner slot it
92
+ // resolves to (as a read of it serves) — the row a held write staged is
93
+ // the same row, not a guess over the slot (#3796).
94
+ const a = n[t];
95
+ const f = unwrapValue(o && a ? resolveChainedRaw(e, t, a) : a);
96
+ if (!(t in i)) {
97
+ guess(getNode(e, t), t, false, f);
98
+ guess(getHasNode(e, t), t, true, true);
99
+ s = true;
100
+ } else {
101
+ const n = i[t];
102
+ const a = unwrapValue(o && n ? resolveChainedRaw(e, t, n) : n);
103
+ if (!isEqual(a, f) && !targetsEqual(a, f)) {
104
+ guess(getNode(e, t), t, false, f);
105
+ if (r) s = true;
106
+ }
107
+ }
108
+ }
109
+ for (const t of Reflect.ownKeys(i)) {
110
+ if (r && t === "length" || t === $OWNER) continue;
111
+ if (t in n) continue;
112
+ guess(getNode(e, t), t, false, undefined);
113
+ guess(getHasNode(e, t), t, true, false);
114
+ s = true;
115
+ }
116
+ if (r && i.length !== n.length) {
117
+ guess(getNode(e, "length"), "length", false, n.length);
118
+ s = true;
119
+ }
120
+ if (s) {
121
+ const o = r ? n.map(unwrapValue) : shallowKeys(n);
122
+ // The rows the setter removed from the view it saw, by key: a later
123
+ // re-base over another action's truth must not bring them back.
124
+ let s = null;
125
+ const a = e.fam.key;
126
+ if (r && a !== null && a !== undefined) {
127
+ const e = new Set;
128
+ for (let n = 0; n < o.length; n++) {
129
+ const t = isWrappable(o[n]) ? a(o[n]) : undefined;
130
+ if (t !== undefined) e.add(t);
131
+ }
132
+ for (let n = 0; n < i.length; n++) {
133
+ const t = unwrapValue(i[n]);
134
+ const r = isWrappable(t) ? a(t) : undefined;
135
+ if (r !== undefined && !e.has(r)) (s ??= new Set).add(r);
136
+ }
137
+ }
138
+ optimisticWrite(getContainerNode(e), new LaneView(o, t, s));
139
+ }
140
+ if (e.dk !== null) optimisticWrite(e.dk, {});
141
+ markOverlaid(e);
142
+ const a = optStaged.get(e);
143
+ if (a === undefined) return null;
144
+ optStaged.delete(e);
145
+ return a;
146
+ }
147
+
148
+ /** The container comparator's lane arm (store.ts `containerEquals`): an
149
+ * arrangement guess (`LaneView`) against a landing or another arrangement,
150
+ * by row identity — by key when the family has one. */ function arrangement(e, n, t) {
151
+ const i = n instanceof LaneView;
152
+ const r = t instanceof LaneView;
153
+ if (!i && !r) return false;
154
+ return arrangementEqual(i ? n.rows : n, r ? t.rows : t, e.fam?.key ?? null);
155
+ }
156
+
157
+ function rowSame(e, n, t) {
158
+ if (isEqual(e, n) || targetsEqual(e, n)) return true;
159
+ if (t === null || !isWrappable(e) || !isWrappable(n)) return false;
160
+ const i = t(unwrapValue(e));
161
+ const r = t(unwrapValue(n));
162
+ // Keyless rows are identified by position — reconcile's fallback when the
163
+ // key is missing. The caller already paired these by index, so two keyless
164
+ // rows are the same row and the landing confirms the arrangement instead of
165
+ // dissolving it. Dissolving held an external echo under the action, and a
166
+ // mainline `until` then timed out on a source that already contained it
167
+ // (#3898). Keyed rows still match only on the key.
168
+ if (i === undefined && r === undefined) return true;
169
+ return i !== undefined && sameKey(i, r);
170
+ }
171
+
172
+ /** Whether reconcile would write anything into `a` from `b`: wrappable
173
+ * pairs descend, leaves compare as its writes do. A key mismatch is a
174
+ * replacement, which a content difference already says. Plain data — the
175
+ * server's echo of a guessed row is a new object with the same contents. */ function echoes(e, n) {
176
+ if (e === n) return true;
177
+ if (!isWrappable(e) || !isWrappable(n)) return false;
178
+ e = unwrapValue(e);
179
+ n = unwrapValue(n);
180
+ const t = Object.keys(e);
181
+ if (Array.isArray(e) !== Array.isArray(n) || t.length !== Object.keys(n).length) return false;
182
+ for (const i of t) if (!hasOwn.call(n, i) || !echoes(e[i], n[i])) return false;
183
+ return true;
184
+ }
185
+
186
+ // A cycle (a row that references itself) is not plain data: no match, so
187
+ // the landing stays a correction.
188
+ GlobalQueue.sn = (e, n) => {
189
+ try {
190
+ return echoes(e, n);
191
+ } catch {
192
+ return false;
193
+ }
194
+ };
195
+
196
+ function arrangementEqual(e, n, t) {
197
+ if (Array.isArray(e) !== Array.isArray(n)) return false;
198
+ if (Array.isArray(e)) {
199
+ if (e.length !== n.length) return false;
200
+ for (let i = 0; i < e.length; i++) if (!rowSame(e[i], n[i], t)) return false;
201
+ return true;
202
+ }
203
+ const i = Reflect.ownKeys(e).filter(e => e !== $OWNER);
204
+ const r = Reflect.ownKeys(n).filter(e => e !== $OWNER);
205
+ if (i.length !== r.length) return false;
206
+ for (const e of i) if (!(e in n)) return false;
207
+ return true;
208
+ }
209
+
210
+ /** Write `incoming` into the draft `draft` (a store proxy inside a user's
211
+ * setter): arrays match rows by key (position when unkeyed) and recurse into
212
+ * the matched row's draft; objects recurse into a wrappable pair, assign
213
+ * otherwise; keys `incoming` lacks are deleted. */ function reconcileDraft(e, n, t) {
214
+ if (Array.isArray(n)) {
215
+ const i = e.length;
216
+ const r = new Array(i);
217
+ for (let n = 0; n < i; n++) r[n] = e[n];
218
+ let o = null;
219
+ if (t !== null) {
220
+ o = new Map;
221
+ for (let e = 0; e < i; e++) {
222
+ const n = unwrapValue(r[e]);
223
+ if (!isWrappable(n)) continue;
224
+ const i = t(n);
225
+ if (i !== undefined && !o.has(i)) o.set(i, r[e]);
226
+ }
227
+ }
228
+ for (let s = 0; s < n.length; s++) {
229
+ const a = n[s];
230
+ let f;
231
+ if (isWrappable(a)) {
232
+ if (o !== null) {
233
+ const e = t(a);
234
+ if (e !== undefined) f = o.get(e);
235
+ } else if (s < i && isWrappable(unwrapValue(r[s]))) f = r[s];
236
+ }
237
+ if (f !== undefined) {
238
+ if (unwrapValue(f) !== a) reconcileDraft(f, a, t);
239
+ if (e[s] !== f) e[s] = f;
240
+ } else if (unwrapValue(e[s]) !== a) e[s] = a;
241
+ }
242
+ if (e.length !== n.length) e.length = n.length;
243
+ return;
244
+ }
245
+ for (const i of Object.keys(n)) {
246
+ const r = n[i];
247
+ const o = e[i];
248
+ const s = unwrapValue(o);
249
+ if (isWrappable(r) && isWrappable(s) && Array.isArray(r) === Array.isArray(s) && (t === null || Array.isArray(r) || sameKey(t(r), t(s)))) {
250
+ if (s !== r) reconcileDraft(o, r, t);
251
+ } else if (s !== r) e[i] = r;
252
+ }
253
+ for (const t of Object.keys(e)) if (!(t in n)) delete e[t];
254
+ }
255
+
256
+ /** Q-D (plan sec. 39): an OLDER question's truth landed beneath an arrangement
257
+ * guess (`laneWrite` held it — another action's landing is not this guess's
258
+ * answer). The guess is re-based over it: order from the guess, rows from
259
+ * the truth by key (a guessed row the truth has is the truth's object — the
260
+ * row target adopted it, its proxy survives), guessed rows the truth lacks
261
+ * kept (the guess's own landing judges them), truth rows the guess lacks
262
+ * appended. The composed arrangement becomes the lane's value on every
263
+ * index whose row the committed backing does not already show — compared
264
+ * BY KEY, never by raw identity: the same key's new object is the same row
265
+ * (its target adopted it) and the slot stays the committed backing's — (a
266
+ * node is born for it as the lane's derivation), on `length` only when the
267
+ * committed length differs, and as the `LaneView`'s base for structural
268
+ * reads. Unkeyed families compose
269
+ * positionally — the guess stands as written (the documented residue). */ GlobalQueue._n = (e, n) => {
270
+ const t = e.yt;
271
+ if (t === undefined || e.bt !== $TRACK) return;
272
+ const i = e.m.B;
273
+ if (!(i instanceof LaneView)) return;
274
+ if (!Array.isArray(n) || !Array.isArray(i.rows)) {
275
+ i.base = n;
276
+ return;
277
+ }
278
+ const r = t.fam?.key ?? null;
279
+ if (r === null) return;
280
+ const o = new Map;
281
+ for (let e = 0; e < n.length; e++) {
282
+ const t = n[e];
283
+ const i = isWrappable(t) ? r(t) : undefined;
284
+ if (i !== undefined && !o.has(i)) o.set(i, t);
285
+ }
286
+ const s = new Set;
287
+ const a = [];
288
+ const f = i.rows;
289
+ for (let e = 0; e < f.length; e++) {
290
+ const n = f[e];
291
+ const t = isWrappable(n) ? r(n) : undefined;
292
+ const i = t !== undefined ? o.get(t) : undefined;
293
+ if (i !== undefined) {
294
+ a.push(i);
295
+ s.add(t);
296
+ } else a.push(n);
297
+ }
298
+ const u = i.removed;
299
+ for (let e = 0; e < n.length; e++) {
300
+ const t = n[e];
301
+ const i = isWrappable(t) ? r(t) : undefined;
302
+ if (i !== undefined && !s.has(i) && (u === null || !u.has(i))) a.push(t);
303
+ }
304
+ i.rows = a;
305
+ i.base = a;
306
+ const l = txOf(e);
307
+ const c = committed(t);
308
+ const d = t.n;
309
+ for (let e = 0; e < a.length; e++) {
310
+ const n = d?.[e];
311
+ // A slot the lane does not own shows the committed row: it becomes the
312
+ // lane's only where the composed row is another row (by key — the same
313
+ // key's new object is the same row, its target adopted it).
314
+ if (n === undefined) {
315
+ if (!sameRow(c[e], a[e], r)) laneSet(getNode(t, e), a[e], l);
316
+ } else if (!sameRow(n.i & CONFIG_OVERRIDE ? n.m.B : c[e], a[e], r)) laneSet(n, a[e], l);
317
+ }
318
+ if (d !== null) {
319
+ for (let e = a.length; ;e++) {
320
+ const n = d[e];
321
+ if (n === undefined) break;
322
+ laneSet(n, undefined, l);
323
+ }
324
+ const e = d.length;
325
+ if (e !== undefined && (e.i & CONFIG_OVERRIDE || c.length !== a.length)) laneSet(e, a.length, l);
326
+ }
327
+ };
328
+
329
+ function sameRow(e, n, t) {
330
+ if (e === n) return true;
331
+ if (!isWrappable(e) || !isWrappable(n)) return false;
332
+ const i = t(unwrapValue(e));
333
+ return i !== undefined && sameKey(i, t(unwrapValue(n)));
334
+ }
335
+
336
+ /** A composed value becomes the lane's on `node`: a guess re-based, or a
337
+ * node that was not the lane's becomes its derivation (its committed value
338
+ * untouched beneath; the lane's end commits the latest). */ function laneSet(e, n, t) {
339
+ const i = ext(e);
340
+ if (!(e.i & CONFIG_OVERRIDE)) {
341
+ e.i |= CONFIG_OVERRIDE;
342
+ list(e, t);
343
+ } else if (i.B === n) return;
344
+ i.B = n;
345
+ if (e.t !== null) {
346
+ insertSubs(e);
347
+ laneDirty(e, t);
348
+ }
349
+ }
350
+
351
+ installOptHooks({
352
+ draft: optimisticDraft,
353
+ writes: notifyOptimisticWrites,
354
+ arrangement: arrangement,
355
+ reconcile: reconcileDraft,
356
+ view: (e, n, t = false) => t ? optimisticView(e, n, laneValueOf, true) : optimisticView(e, n),
357
+ has: optimisticHas,
358
+ descriptor: optimisticOwnDescriptor,
359
+ sweep: sweepOverlaid
360
+ });
361
+
362
+ function shallowKeys(e) {
363
+ const n = {};
364
+ for (const t of Reflect.ownKeys(e)) if (t !== $OWNER) n[t] = unwrapValue(e[t]);
365
+ return n;
366
+ }
367
+
368
+ /** Families with a target carrying a lane value — swept at the flush's
369
+ * commit (`sweepOverlaid`): a target none of whose nodes is a lane's any
370
+ * more leaves its family's `overlaid`. (Not on the read path: a guess is
371
+ * pending between the setter and the seam, and a read in between must not
372
+ * take the target for clean.) */ const overlaidFamilies = new Set;
373
+
374
+ function markOverlaid(e) {
375
+ const n = e.fam;
376
+ (n.overlaid ??= new Set).add(e);
377
+ overlaidFamilies.add(n);
378
+ }
379
+
380
+ function sweepOverlaid() {
381
+ if (overlaidFamilies.size === 0) return;
382
+ for (const e of overlaidFamilies) {
383
+ const n = e.overlaid;
384
+ for (const e of n) if (!carriesLane(e)) {
385
+ n.delete(e);
386
+ if (e.ch) rebaseChained(e);
387
+ // The container shows its backing again (a shown arrangement guess
388
+ // that ended without a landing left its `LaneView` as the value).
389
+ const t = e.k;
390
+ if (t !== null && t.Ae instanceof LaneView) t.Ae = t.Ae.base;
391
+ }
392
+ if (n.size === 0) overlaidFamilies.delete(e);
393
+ }
394
+ }
395
+
396
+ /** A chained view's lanes ended: its nodes are links (§7b) whose committed
397
+ * value is the inner store's at the guess, not now — the inner may have
398
+ * moved underneath the guess (the base committed while the view showed
399
+ * its arrangement, #3672/F1). Re-base each node on the inner's truth and
400
+ * re-derive the readers whose shown value it is not. */ function rebaseChained(e) {
401
+ const n = e.v;
402
+ let t = false;
403
+ const i = e.n;
404
+ if (i !== null) for (const e of Reflect.ownKeys(i)) {
405
+ const r = i[e];
406
+ const o = untrack(() => unwrapValue(n[e]));
407
+ if (r.en && r.en(r.Ae, o)) continue;
408
+ r.Ae = o;
409
+ // (The lane's end notified it this epoch when the shown value and the
410
+ // covered one differed — its readers re-derive already.)
411
+ if (r.t !== null && r.Pt !== notifyEpoch) {
412
+ insertSubs(r);
413
+ t = true;
414
+ }
415
+ }
416
+ const r = e.h;
417
+ if (r !== null) for (const e of Reflect.ownKeys(r)) {
418
+ const i = r[e];
419
+ const o = untrack(() => e in n);
420
+ if (i.Ae === o) continue;
421
+ i.Ae = o;
422
+ if (i.t !== null && i.Pt !== notifyEpoch) {
423
+ insertSubs(i);
424
+ t = true;
425
+ }
426
+ }
427
+ // The arrangement the readers saw (the shown guess) against the inner's
428
+ // now: a structural reader re-derives when they differ.
429
+ const o = e.k;
430
+ if (o !== null && o.t !== null && o.Ae instanceof LaneView && o.Pt !== notifyEpoch) {
431
+ const i = Array.isArray(n) ? untrack(() => n.map(unwrapValue)) : n;
432
+ if (!arrangementEqual(o.Ae.rows, i, e.fam?.key ?? null)) {
433
+ insertSubs(o);
434
+ t = true;
435
+ }
436
+ }
437
+ if (t) schedule();
438
+ }
439
+
440
+ function carriesLane(e) {
441
+ if (e.k !== null && e.k.i & CONFIG_OVERRIDE) return true;
442
+ if (e.dk !== null && e.dk.i & CONFIG_OVERRIDE) return true;
443
+ const n = e.n;
444
+ if (n !== null) for (const e of Reflect.ownKeys(n)) if (n[e].i & CONFIG_OVERRIDE) return true;
445
+ const t = e.h;
446
+ if (t !== null) for (const e of Reflect.ownKeys(t)) if (t[e].i & CONFIG_OVERRIDE) return true;
447
+ return false;
448
+ }
449
+
450
+ function overlaid(e) {
451
+ const n = e.fam;
452
+ return n !== null && n.opt === true && n.overlaid !== undefined && n.overlaid.has(e);
453
+ }
454
+
455
+ /** What a lane node shows an untracked reader here: core's rule (`read`
456
+ * without a link — the lane's world inside its own pass, the screen
457
+ * outside, a verdict window's answer under one). */ const shown = e => untrack(() => read(e));
458
+
459
+ /** An untracked `key in store` on an optimistic family: the presence guess
460
+ * (what its lane shows) when the key carries one; `undefined` when not —
461
+ * the backing answers. */ function optimisticHas(e, n) {
462
+ if (!overlaid(e)) return undefined;
463
+ const t = e.h?.[n];
464
+ if (t !== undefined && t.i & CONFIG_OVERRIDE) return !!shown(t);
465
+ const i = e.n?.[n];
466
+ if (i !== undefined && i.i & CONFIG_OVERRIDE) return shown(i) !== undefined;
467
+ return undefined;
468
+ }
469
+
470
+ /** A descriptor read of a guessed key: synthesized from the lane's value
471
+ * (`null`: the guess removed the key; `undefined`: no guess — the backing
472
+ * describes it). */ function optimisticOwnDescriptor(e, n) {
473
+ const t = optimisticHas(e, n);
474
+ if (t === undefined) return undefined;
475
+ if (!t) return null;
476
+ const i = e.n?.[n];
477
+ const r = i !== undefined && i.i & CONFIG_OVERRIDE ? shown(i) : e.v[n];
478
+ // An array's `length` is reported as the array has it (non-configurable).
479
+ if (n === "length" && Array.isArray(e.v)) return {
480
+ value: r,
481
+ writable: true,
482
+ enumerable: false,
483
+ configurable: false
484
+ };
485
+ return {
486
+ value: r,
487
+ writable: true,
488
+ enumerable: true,
489
+ configurable: true
490
+ };
491
+ }
492
+
493
+ /** The truth `src` with the target's lane values over it: each overlaid
494
+ * leaf's value (`pick`: what the lane shows, or — for `latest` — the lane's
495
+ * latest), each presence guess as a key added or removed, the array
496
+ * length. Returns `src` itself when nothing is overlaid. */ function optimisticView(e, n, t = shown,
497
+ // The writer's view: the unflushed guesses too (on nodes that are no
498
+ // lane's yet) — what the next write composes on (#3665).
499
+ i = false) {
500
+ if (!i && !overlaid(e)) return n;
501
+ let r = null;
502
+ const ensure = () => r ??= Array.isArray(n) ? [ ...n ] : {
503
+ ...n
504
+ };
505
+ const o = e.n;
506
+ if (o !== null) {
507
+ for (const e of Reflect.ownKeys(o)) {
508
+ const r = o[e];
509
+ let s;
510
+ if (r.i & CONFIG_OVERRIDE) s = t(r); else if (!i || (s = pendingGuessOf(r)) === NOT_PENDING) continue;
511
+ if (e === "length" && Array.isArray(n)) {
512
+ if (n.length !== s) ensure().length = s;
513
+ } else if (!isEqual(n[e], s) || !hasOwn.call(n, e)) {
514
+ ensure()[e] = s;
515
+ }
516
+ }
517
+ }
518
+ const s = e.h;
519
+ if (s !== null) {
520
+ for (const e of Reflect.ownKeys(s)) {
521
+ const o = s[e];
522
+ let a;
523
+ if (o.i & CONFIG_OVERRIDE) a = t(o); else if (!i || (a = pendingGuessOf(o)) === NOT_PENDING) continue;
524
+ const f = !!a;
525
+ const u = r ?? n;
526
+ if (!f && e in u) delete ensure()[e];
527
+ }
528
+ }
529
+ return r ?? n;
530
+ }
531
+
532
+ function createOptimisticStore(e, n, t) {
533
+ const i = typeof e === "function";
534
+ const r = i ? t : n;
535
+ const o = i ? n : e;
536
+ const s = r?.key === undefined ? "id" : r.key;
537
+ const a = {
538
+ map: new WeakMap,
539
+ node: null,
540
+ live: new Set,
541
+ shallow: !!r?.shallow,
542
+ opt: true,
543
+ key: typeof s === "function" ? s : s === null ? null : e => isWrappable(e) ? e[s] : undefined
544
+ };
545
+ const f = wrap(o, null, null, a);
546
+ nameStore(f, r?.name);
547
+ if (a.shallow) {
548
+ f[$TARGET].s = true;
549
+ markRawIngest(o);
550
+ }
551
+ if (i) {
552
+ const n = e;
553
+ let t;
554
+ if (r?.seedLoadingValue) t = {
555
+ loadingValue: undefined
556
+ };
557
+ if (r?.name) t = {
558
+ ...t,
559
+ name: r.name
560
+ };
561
+ const i = computed(() => {
562
+ if (!a.node) a.node = getOwner();
563
+ runProjectionComputed(f, n, s);
564
+ }, t);
565
+ i.i &= ~CONFIG_AUTO_DISPOSE;
566
+ a.node = i;
567
+ }
568
+ return [ f, e => storeSetter(f, e) ];
569
+ }
570
+
571
+ export { createOptimisticStore, notifyOptimisticWrites, optimisticHas, optimisticOwnDescriptor, optimisticView, sweepOverlaid };