@solidjs/signals 2.0.0-rc.2 → 2.0.0-rc.20

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 (198) hide show
  1. package/dist/dev-shared.js +6505 -0
  2. package/dist/dev.attribution.js +3484 -0
  3. package/dist/dev.js +10227 -9508
  4. package/dist/observe/affects-marks.js +86 -0
  5. package/dist/observe/affects.js +112 -0
  6. package/dist/observe/attribution.js +7 -0
  7. package/dist/observe/boundaries.js +696 -0
  8. package/dist/observe/core/action.js +182 -0
  9. package/dist/observe/core/async.js +824 -0
  10. package/dist/observe/core/attribution-costs.js +66 -0
  11. package/dist/observe/core/attribution-feedback.js +280 -0
  12. package/dist/observe/core/attribution-hooks.js +83 -0
  13. package/dist/observe/core/attribution-queries.js +43 -0
  14. package/dist/observe/core/attribution.js +3079 -0
  15. package/dist/observe/core/constants.js +269 -0
  16. package/dist/observe/core/context.js +63 -0
  17. package/dist/observe/core/copies.js +10 -0
  18. package/dist/observe/core/core.js +1707 -0
  19. package/dist/observe/core/dev.js +394 -0
  20. package/dist/observe/core/effect.js +193 -0
  21. package/dist/observe/core/error-hooks.js +71 -0
  22. package/dist/observe/core/error.js +82 -0
  23. package/dist/observe/core/external.js +97 -0
  24. package/dist/observe/core/graph.js +162 -0
  25. package/dist/observe/core/heap.js +124 -0
  26. package/dist/observe/core/identities.js +62 -0
  27. package/dist/observe/core/invariants.js +12 -0
  28. package/dist/observe/core/lanes.js +972 -0
  29. package/dist/observe/core/owner.js +371 -0
  30. package/dist/observe/core/scheduler.js +1157 -0
  31. package/dist/observe/core/truth.js +47 -0
  32. package/dist/observe/core/verdict.js +470 -0
  33. package/dist/observe/deferred.js +186 -0
  34. package/dist/observe/flatten.js +79 -0
  35. package/dist/observe/from.js +248 -0
  36. package/dist/observe/index.js +71 -0
  37. package/dist/observe/map.js +593 -0
  38. package/dist/observe/reveal.js +212 -0
  39. package/dist/observe/signals.js +717 -0
  40. package/dist/observe/store/affects.js +142 -0
  41. package/dist/observe/store/edges.js +39 -0
  42. package/dist/observe/store/hooks.js +16 -0
  43. package/dist/observe/store/index.js +47 -0
  44. package/dist/observe/store/optimistic.js +713 -0
  45. package/dist/observe/store/projection.js +345 -0
  46. package/dist/observe/store/reconcile.js +281 -0
  47. package/dist/observe/store/store.js +2127 -0
  48. package/dist/observe/store/storePath.js +103 -0
  49. package/dist/observe/store/target.js +46 -0
  50. package/dist/observe/store/types.js +83 -0
  51. package/dist/observe/store/utils.js +1063 -0
  52. package/dist/prod/affects-marks.js +86 -0
  53. package/dist/prod/affects.js +98 -112
  54. package/dist/prod/attribution.js +45 -0
  55. package/dist/prod/boundaries.js +578 -468
  56. package/dist/prod/core/action.js +92 -59
  57. package/dist/prod/core/async.js +522 -336
  58. package/dist/prod/core/attribution-hooks.js +3 -0
  59. package/dist/prod/core/constants.js +168 -44
  60. package/dist/prod/core/context.js +12 -16
  61. package/dist/prod/core/copies.js +10 -0
  62. package/dist/prod/core/core.js +1345 -627
  63. package/dist/prod/core/dev.js +123 -1
  64. package/dist/prod/core/effect.js +113 -80
  65. package/dist/prod/core/error-hooks.js +71 -0
  66. package/dist/prod/core/error.js +18 -4
  67. package/dist/prod/core/external.js +6 -7
  68. package/dist/prod/core/graph.js +119 -72
  69. package/dist/prod/core/heap.js +85 -109
  70. package/dist/prod/core/identities.js +62 -0
  71. package/dist/prod/core/invariants.js +1 -32
  72. package/dist/prod/core/lanes.js +931 -132
  73. package/dist/prod/core/owner.js +192 -129
  74. package/dist/prod/core/scheduler.js +948 -642
  75. package/dist/prod/core/truth.js +47 -0
  76. package/dist/prod/core/verdict.js +409 -420
  77. package/dist/prod/deferred.js +184 -0
  78. package/dist/prod/flatten.js +77 -0
  79. package/dist/prod/from.js +248 -0
  80. package/dist/prod/index.js +40 -16
  81. package/dist/prod/map.js +481 -211
  82. package/dist/prod/reveal.js +212 -0
  83. package/dist/prod/signals.js +401 -84
  84. package/dist/prod/store/affects.js +142 -0
  85. package/dist/prod/store/edges.js +39 -0
  86. package/dist/prod/store/hooks.js +16 -0
  87. package/dist/prod/store/index.js +27 -18
  88. package/dist/prod/store/optimistic.js +707 -0
  89. package/dist/prod/store/projection.js +331 -0
  90. package/dist/prod/store/reconcile.js +281 -0
  91. package/dist/prod/store/store.js +1952 -267
  92. package/dist/prod/store/storePath.js +1 -1
  93. package/dist/prod/store/target.js +43 -0
  94. package/dist/prod/store/types.js +83 -0
  95. package/dist/prod/store/utils.js +997 -138
  96. package/dist/types/affects-marks.d.ts +14 -0
  97. package/dist/types/affects.d.ts +12 -30
  98. package/dist/types/attribution.d.ts +19 -0
  99. package/dist/types/attribution.prod.d.ts +22 -0
  100. package/dist/types/boundaries.d.ts +99 -124
  101. package/dist/types/carved.d.ts +1 -0
  102. package/dist/types/core/action.d.ts +23 -9
  103. package/dist/types/core/async.d.ts +34 -6
  104. package/dist/types/core/attribution-costs.d.ts +35 -0
  105. package/dist/types/core/attribution-feedback.d.ts +133 -0
  106. package/dist/types/core/attribution-hooks.d.ts +307 -8
  107. package/dist/types/core/attribution-queries.d.ts +24 -0
  108. package/dist/types/core/attribution.d.ts +802 -72
  109. package/dist/types/core/constants.d.ts +195 -38
  110. package/dist/types/core/copies.d.ts +54 -0
  111. package/dist/types/core/core.d.ts +295 -65
  112. package/dist/types/core/dev.d.ts +509 -22
  113. package/dist/types/core/effect.d.ts +1 -1
  114. package/dist/types/core/error-hooks.d.ts +71 -0
  115. package/dist/types/core/error.d.ts +18 -1
  116. package/dist/types/core/graph.d.ts +40 -1
  117. package/dist/types/core/heap.d.ts +5 -5
  118. package/dist/types/core/identities.d.ts +17 -0
  119. package/dist/types/core/index.d.ts +11 -7
  120. package/dist/types/core/invariants.d.ts +1 -26
  121. package/dist/types/core/lanes.d.ts +74 -43
  122. package/dist/types/core/owner.d.ts +27 -9
  123. package/dist/types/core/scheduler.d.ts +353 -102
  124. package/dist/types/core/truth.d.ts +18 -0
  125. package/dist/types/core/types.d.ts +97 -71
  126. package/dist/types/core/verdict.d.ts +35 -0
  127. package/dist/types/deferred.d.ts +28 -0
  128. package/dist/types/flatten.d.ts +8 -0
  129. package/dist/types/from.d.ts +47 -0
  130. package/dist/types/index.d.ts +33 -7
  131. package/dist/types/map.d.ts +4 -2
  132. package/dist/types/reveal.d.ts +19 -0
  133. package/dist/types/signals.d.ts +196 -45
  134. package/dist/types/store/affects.d.ts +12 -0
  135. package/dist/types/store/edges.d.ts +9 -0
  136. package/dist/types/store/hooks.d.ts +62 -0
  137. package/dist/types/store/index.d.ts +42 -15
  138. package/dist/types/store/optimistic.d.ts +24 -45
  139. package/dist/types/store/projection.d.ts +17 -68
  140. package/dist/types/store/reconcile.d.ts +3 -46
  141. package/dist/types/store/store.d.ts +133 -136
  142. package/dist/types/store/storePath.d.ts +1 -1
  143. package/dist/types/store/target.d.ts +166 -0
  144. package/dist/types/store/types.d.ts +105 -0
  145. package/dist/types/store/utils.d.ts +188 -0
  146. package/package.json +31 -26
  147. package/dist/node.cjs +0 -8745
  148. package/dist/prod/core/optimistic.js +0 -265
  149. package/dist/prod/store/next/optimistic.js +0 -385
  150. package/dist/prod/store/next/projection.js +0 -172
  151. package/dist/prod/store/next/reconcile.js +0 -331
  152. package/dist/prod/store/next/store.js +0 -1499
  153. package/dist/prod/store/next/target.js +0 -20
  154. package/dist/types/core/optimistic.d.ts +0 -6
  155. package/dist/types/store/next/optimistic.d.ts +0 -20
  156. package/dist/types/store/next/projection.d.ts +0 -8
  157. package/dist/types/store/next/reconcile.d.ts +0 -3
  158. package/dist/types/store/next/store.d.ts +0 -77
  159. package/dist/types/store/next/target.d.ts +0 -117
  160. package/dist/types-cjs/affects.d.cts +0 -47
  161. package/dist/types-cjs/boundaries.d.cts +0 -175
  162. package/dist/types-cjs/core/action.d.cts +0 -64
  163. package/dist/types-cjs/core/async.d.cts +0 -21
  164. package/dist/types-cjs/core/attribution-hooks.d.cts +0 -52
  165. package/dist/types-cjs/core/attribution.d.cts +0 -186
  166. package/dist/types-cjs/core/constants.d.cts +0 -97
  167. package/dist/types-cjs/core/context.d.cts +0 -36
  168. package/dist/types-cjs/core/core.d.cts +0 -163
  169. package/dist/types-cjs/core/dev.d.cts +0 -81
  170. package/dist/types-cjs/core/effect.d.cts +0 -30
  171. package/dist/types-cjs/core/error.d.cts +0 -47
  172. package/dist/types-cjs/core/external.d.cts +0 -15
  173. package/dist/types-cjs/core/graph.d.cts +0 -6
  174. package/dist/types-cjs/core/heap.d.cts +0 -22
  175. package/dist/types-cjs/core/index.d.cts +0 -13
  176. package/dist/types-cjs/core/invariants.d.cts +0 -59
  177. package/dist/types-cjs/core/lanes.d.cts +0 -44
  178. package/dist/types-cjs/core/optimistic.d.cts +0 -6
  179. package/dist/types-cjs/core/owner.d.cts +0 -124
  180. package/dist/types-cjs/core/scheduler.d.cts +0 -180
  181. package/dist/types-cjs/core/types.d.cts +0 -192
  182. package/dist/types-cjs/core/verdict.d.cts +0 -2
  183. package/dist/types-cjs/index.d.cts +0 -10
  184. package/dist/types-cjs/map.d.cts +0 -69
  185. package/dist/types-cjs/package.json +0 -3
  186. package/dist/types-cjs/signals.d.cts +0 -624
  187. package/dist/types-cjs/store/index.d.cts +0 -19
  188. package/dist/types-cjs/store/next/optimistic.d.cts +0 -20
  189. package/dist/types-cjs/store/next/projection.d.cts +0 -8
  190. package/dist/types-cjs/store/next/reconcile.d.cts +0 -3
  191. package/dist/types-cjs/store/next/store.d.cts +0 -77
  192. package/dist/types-cjs/store/next/target.d.cts +0 -117
  193. package/dist/types-cjs/store/optimistic.d.cts +0 -45
  194. package/dist/types-cjs/store/projection.d.cts +0 -70
  195. package/dist/types-cjs/store/reconcile.d.cts +0 -46
  196. package/dist/types-cjs/store/store.d.cts +0 -138
  197. package/dist/types-cjs/store/storePath.d.cts +0 -58
  198. package/dist/types-cjs/store/utils.d.cts +0 -74
@@ -0,0 +1,707 @@
1
+ import { CONFIG_GUESS, CONFIG_OVERRIDE, EFFECT_RENDER, CONFIG_CHILDREN_FORBIDDEN, NOT_PENDING, CONFIG_SLOT_NODE, CONFIG_AUTO_DISPOSE, REACTIVE_REASK } from "../core/constants.js";
2
+
3
+ import { computed, isEqual, joinPassAt, ext, untrack, read } from "../core/core.js";
4
+
5
+ import { take, pendingGuessOf, optimisticWrite } from "../core/lanes.js";
6
+
7
+ import { getOwner } from "../core/owner.js";
8
+
9
+ import { GlobalQueue, txOf, insertSubs, joinFuture, resolveTx, passLane, list, laneDirty, clock, merge, notifyEpoch, schedule } from "../core/scheduler.js";
10
+
11
+ import { runProjectionComputed } from "./projection.js";
12
+
13
+ import { reconcileState } from "./reconcile.js";
14
+
15
+ import { wrap, storeSetter, getContainerNode, getHasNode, getNode, LaneView, committed, unwrapValue, sameKey, resolveChainedRaw, targetsEqual, cloneRaw } from "./store.js";
16
+
17
+ import { installOptHooks } from "./hooks.js";
18
+
19
+ import { $OWNER, lookupTarget } from "./target.js";
20
+
21
+ import { $TARGET, markRawIngest, $TRACK, isWrappable } from "./types.js";
22
+
23
+ import { laneValueOf } from "../core/truth.js";
24
+
25
+ /**
26
+ * Store — optimistic stores on lanes (plan sec. 31, S4; INTERNALS §3/§7, RUL-3).
27
+ *
28
+ * No store-side layer, no backup snapshots, no retaining ledger: a user
29
+ * write to an optimistic store is a GUESS on the written key's node
30
+ * (`optimisticWrite` — the same write `createOptimistic`'s setter makes),
31
+ * a presence guess on its presence node, and, when membership or
32
+ * arrangement changed, an arrangement guess on the container node. Lanes
33
+ * do the rest: the guess shows under the action's hold, a landing beneath
34
+ * it stages as truth and confirms it when equal (A18/A24), the action's
35
+ * settle dissolves it (a revert to the value it covered, or the landed
36
+ * truth). The committed backing is never touched by a guess.
37
+ *
38
+ * Reads compose: a reader of an overlaid target sees the truth it is served
39
+ * with the lanes' values over it (`optimisticView` — per node, by the same
40
+ * rule a leaf read follows: what the lane shows).
41
+ *
42
+ * Landings (Q-D, plan sec. 31.7): the derive's output is reconciled against the
43
+ * optimistic VIEW — a row the guess added and the server returns with the
44
+ * same key in the same position keeps its proxy (the row target adopts the
45
+ * server object), its leaves write truth beneath their guesses, and the
46
+ * container's arrangement guess is confirmed silently (`LaneView`'s
47
+ * comparator) — `For` does not run. Retained-setter replay (the
48
+ * 2026-08-31b continuation half) is not built here; the matrix decides.
49
+ */ const hasOwn = Object.prototype.hasOwnProperty;
50
+
51
+ /** A user setter's writes on an optimistic family, as guesses: one per
52
+ * changed key's leaf, one per presence change, the container's arrangement
53
+ * when membership or order changed. `pb` is the draft (a clone of the view
54
+ * the user saw); `old` the view it composed on. */
55
+ /** An optimistic setter's targets whose staging was set aside (`draft`),
56
+ * restored when the setter's writes become guesses (`writes`). */ const optStaged = new Map;
57
+
58
+ // A chained backing is a proxy: reading it as a handler can expose a
59
+ // derived store's staging. Compose the writer's view on the committed
60
+ // backing of each link, retaining any optimistic guesses on that link.
61
+ function writerBacking(e) {
62
+ const n = committed(e);
63
+ const t = n[$TARGET];
64
+ return t === undefined ? n : optimisticView(t, writerBacking(t), laneValueOf, true);
65
+ }
66
+
67
+ /** The user's draft on an optimistic family: a clone of the view the user
68
+ * saw — the committed frame with the lanes' values and the tick's own
69
+ * unflushed guesses over it (#3665). A staging already on the target (a
70
+ * landing adopted this flush) is set aside for the setter's duration: the
71
+ * guesses go over it, it stays the truth beneath. */ function optimisticDraft(e) {
72
+ if (e.pb !== null) optStaged.set(e, e.pb);
73
+ return cloneRaw(optimisticView(e, writerBacking(e), laneValueOf, true), e);
74
+ }
75
+
76
+ function notifyOptimisticWrites(e, n) {
77
+ // The view the user saw: the committed frame (a staging adopted eagerly
78
+ // is not it) with the lanes' values and the tick's own guesses over it.
79
+ const t = writerBacking(e);
80
+ const i = optimisticView(e, t, laneValueOf, true);
81
+ const r = Array.isArray(n);
82
+ // A chained target's nodes are links (§7b): their committed value is
83
+ // never served and never learns the inner store's commits — yet a guess
84
+ // is judged against it, and reverts to it (#3672). Hand the node the
85
+ // inner store's truth for its key before guessing over it.
86
+ const o = e.ch ? e.v : null;
87
+ const guess = (e, n, i, r) => {
88
+ if (o !== null) e.le = i ? n in t : unwrapValue(t[n]);
89
+ // By value: a function leaf is a value, not an updater (#3017).
90
+ optimisticWrite(e, () => r);
91
+ };
92
+ let s = false;
93
+ for (const t of Reflect.ownKeys(n)) {
94
+ if (r && t === "length" || t === $OWNER) continue;
95
+ // A chained draft holds the inner store's raws; a raw is the inner slot it
96
+ // resolves to (as a read of it serves) — the row a held write staged is
97
+ // the same row, not a guess over the slot (#3796).
98
+ const f = n[t];
99
+ const a = unwrapValue(o && f ? resolveChainedRaw(e, t, f) : f);
100
+ if (!(t in i)) {
101
+ guess(getNode(e, t), t, false, a);
102
+ guess(getHasNode(e, t), t, true, true);
103
+ s = true;
104
+ } else {
105
+ const n = i[t];
106
+ const f = unwrapValue(o && n ? resolveChainedRaw(e, t, n) : n);
107
+ if (!isEqual(f, a) && !targetsEqual(f, a)) {
108
+ guess(getNode(e, t), t, false, a);
109
+ if (r) s = true;
110
+ }
111
+ }
112
+ }
113
+ for (const t of Reflect.ownKeys(i)) {
114
+ if (r && t === "length" || t === $OWNER) continue;
115
+ if (t in n) continue;
116
+ guess(getNode(e, t), t, false, undefined);
117
+ guess(getHasNode(e, t), t, true, false);
118
+ s = true;
119
+ }
120
+ if (r && i.length !== n.length) {
121
+ guess(getNode(e, "length"), "length", false, n.length);
122
+ s = true;
123
+ }
124
+ if (s) {
125
+ const o = r ? n.map(unwrapValue) : shallowKeys(n);
126
+ // The rows the setter removed from the view it saw, by key: a later
127
+ // re-base over another action's truth must not bring them back. A set
128
+ // (empty or not) marks a keyed arrangement guess (`fold`).
129
+ let s = null;
130
+ const f = e.fam.key;
131
+ if (r && f !== null && f !== undefined) {
132
+ s = new Set;
133
+ const e = new Set;
134
+ for (let n = 0; n < o.length; n++) {
135
+ const t = isWrappable(o[n]) ? f(o[n]) : undefined;
136
+ if (t !== undefined) e.add(t);
137
+ }
138
+ for (let n = 0; n < i.length; n++) {
139
+ const t = unwrapValue(i[n]);
140
+ const r = isWrappable(t) ? f(t) : undefined;
141
+ if (r !== undefined && !e.has(r)) s.add(r);
142
+ }
143
+ }
144
+ optimisticWrite(getContainerNode(e), new LaneView(o, t, s));
145
+ }
146
+ if (e.dk !== null) optimisticWrite(e.dk, {});
147
+ markOverlaid(e);
148
+ const f = optStaged.get(e);
149
+ if (f === undefined) return null;
150
+ optStaged.delete(e);
151
+ return f;
152
+ }
153
+
154
+ /** The container comparator's lane arm (store.ts `containerEquals`): an
155
+ * arrangement guess (`LaneView`) against a landing or another arrangement,
156
+ * by row identity — by key when the family has one. */ function arrangement(e, n, t) {
157
+ const i = n instanceof LaneView;
158
+ const r = t instanceof LaneView;
159
+ if (!i && !r) return false;
160
+ return arrangementEqual(i ? n.rows : n, r ? t.rows : t, e.fam);
161
+ }
162
+
163
+ function rowSame(e, n, t) {
164
+ if (isEqual(e, n) || targetsEqual(e, n)) return true;
165
+ const i = t.key;
166
+ if (!i || !isWrappable(e) || !isWrappable(n)) return false;
167
+ // A row the store already serves is its proxy's row: a reader (a list)
168
+ // holds that proxy, so another object at the index is another row, by key
169
+ // or contents alike — a guess's fresh object wraps a new proxy. A landing's
170
+ // object has been adopted by the row it pairs with, so it serves that
171
+ // row's proxy. Only rows no proxy serves yet pair by key, keyless rows by
172
+ // position — reconcile's fallback (#3898).
173
+ const r = lookupTarget(e = unwrapValue(e), t);
174
+ const o = lookupTarget(n = unwrapValue(n), t);
175
+ if (r || o) return r === o;
176
+ // (Two keyless rows: `undefined` is the same key.)
177
+ return sameKey(i(e), i(n));
178
+ }
179
+
180
+ /** Whether reconcile would write anything into `a` from `b`: wrappable
181
+ * pairs descend, leaves compare as its writes do. A key mismatch is a
182
+ * replacement, which a content difference already says. Plain data — the
183
+ * server's echo of a guessed row is a new object with the same contents. */ function echoes(e, n) {
184
+ if (e === n) return true;
185
+ if (!isWrappable(e) || !isWrappable(n)) return false;
186
+ e = unwrapValue(e);
187
+ n = unwrapValue(n);
188
+ const t = Object.keys(e);
189
+ if (Array.isArray(e) !== Array.isArray(n) || t.length !== Object.keys(n).length) return false;
190
+ for (const i of t) if (!hasOwn.call(n, i) || !echoes(e[i], n[i])) return false;
191
+ return true;
192
+ }
193
+
194
+ // A cycle (a row that references itself) is not plain data: no match, so
195
+ // the landing stays a correction.
196
+ GlobalQueue.nn = (e, n) => {
197
+ try {
198
+ return echoes(e, n);
199
+ } catch {
200
+ return false;
201
+ }
202
+ };
203
+
204
+ function arrangementEqual(e, n, t) {
205
+ if (Array.isArray(e) !== Array.isArray(n)) return false;
206
+ if (Array.isArray(e)) {
207
+ if (e.length !== n.length) return false;
208
+ for (let i = 0; i < e.length; i++) if (!rowSame(e[i], n[i], t)) return false;
209
+ return true;
210
+ }
211
+ const i = Reflect.ownKeys(e).filter(e => e !== $OWNER);
212
+ const r = Reflect.ownKeys(n).filter(e => e !== $OWNER);
213
+ if (i.length !== r.length) return false;
214
+ for (const e of i) if (!(e in n)) return false;
215
+ return true;
216
+ }
217
+
218
+ /** Write `incoming` into the draft `draft` (a store proxy inside a user's
219
+ * setter): arrays match rows by key (position when unkeyed) and recurse into
220
+ * the matched row's draft; objects recurse into a wrappable pair, assign
221
+ * otherwise; keys `incoming` lacks are deleted. */ function reconcileDraft(e, n, t) {
222
+ if (Array.isArray(n)) {
223
+ const i = e.length;
224
+ const r = new Array(i);
225
+ for (let n = 0; n < i; n++) r[n] = e[n];
226
+ let o = null;
227
+ if (t !== null) {
228
+ o = new Map;
229
+ for (let e = 0; e < i; e++) {
230
+ const n = unwrapValue(r[e]);
231
+ if (!isWrappable(n)) continue;
232
+ const i = t(n);
233
+ if (i !== undefined && !o.has(i)) o.set(i, r[e]);
234
+ }
235
+ }
236
+ for (let s = 0; s < n.length; s++) {
237
+ const f = n[s];
238
+ let a;
239
+ if (isWrappable(f)) {
240
+ if (o !== null) {
241
+ const e = t(f);
242
+ if (e !== undefined) a = o.get(e);
243
+ } else if (s < i && isWrappable(unwrapValue(r[s]))) a = r[s];
244
+ }
245
+ if (a !== undefined) {
246
+ if (unwrapValue(a) !== f) reconcileDraft(a, f, t);
247
+ if (e[s] !== a) e[s] = a;
248
+ } else if (unwrapValue(e[s]) !== f) e[s] = f;
249
+ }
250
+ if (e.length !== n.length) e.length = n.length;
251
+ return;
252
+ }
253
+ for (const i of Object.keys(n)) {
254
+ const r = n[i];
255
+ const o = e[i];
256
+ const s = unwrapValue(o);
257
+ if (isWrappable(r) && isWrappable(s) && Array.isArray(r) === Array.isArray(s) && (t === null || Array.isArray(r) || sameKey(t(r), t(s)))) {
258
+ if (s !== r) reconcileDraft(o, r, t);
259
+ } else if (s !== r) e[i] = r;
260
+ }
261
+ for (const t of Object.keys(e)) if (!(t in n)) delete e[t];
262
+ }
263
+
264
+ /** Core asks (lanes `laneWrite`): the family's derive, re-asking in a lane of
265
+ * another action than the one that guessed this slot, writes it — that
266
+ * lane's new question, which the guess (over the old one) does not answer:
267
+ * the slot is the lane's derivation from here (F-6, #4336; lanes
268
+ * `laneStage` for a node's own pass). */ GlobalQueue.fn = (e, n) => {
269
+ const t = e.O;
270
+ if (n) {
271
+ // The guess comes back (lanes `endLanes`): on the slot's node now — the
272
+ // node itself, or the one a read made after it was released.
273
+ const n = e.Xe;
274
+ markOverlaid(t);
275
+ return n === $TRACK ? getContainerNode(t) : e.ye === isEqual ? getHasNode(t, n) : getNode(t, n);
276
+ }
277
+ const i = t?.fam?.node?.T?.Re;
278
+ const r = txOf(e);
279
+ if (!i?.P || sameAction(i, r)) return false;
280
+ // The re-ask takes the target's guess whole: the slot is the lane's
281
+ // derivation; its other guessed slots show their truth in the lane's
282
+ // world (lanes `take`).
283
+ for (const n of nodesOf(t)) if (n?.l & CONFIG_GUESS && txOf(n) === r) take(n, i, n !== e);
284
+ return true;
285
+ };
286
+
287
+ /** Q-D (plan sec. 39): an OLDER question's truth landed beneath an arrangement
288
+ * guess (`laneWrite` held it — another action's landing is not this guess's
289
+ * answer). The guess is re-based over it: order from the guess, rows from
290
+ * the truth by key (a guessed row the truth has is the truth's object — the
291
+ * row target adopted it, its proxy survives), guessed rows the truth lacks
292
+ * kept (the guess's own landing judges them), truth rows the guess lacks
293
+ * appended. The composed arrangement becomes the lane's value on every
294
+ * index whose row the committed backing does not already show — compared
295
+ * BY KEY, never by raw identity: the same key's new object is the same row
296
+ * (its target adopted it) and the slot stays the committed backing's — (a
297
+ * node is born for it as the lane's derivation), on `length` only when the
298
+ * committed length differs, and as the `LaneView`'s base for structural
299
+ * reads. Unkeyed families compose
300
+ * positionally — the guess stands as written (the documented residue). */ GlobalQueue.Nn = (e, n, t) => {
301
+ if (!t) return fold(e, n);
302
+ const i = e.O;
303
+ if (i === undefined || e.Xe !== $TRACK) return;
304
+ const r = e.T.P;
305
+ if (!(r instanceof LaneView)) return;
306
+ if (!Array.isArray(n) || !Array.isArray(r.rows)) {
307
+ r.base = n;
308
+ return;
309
+ }
310
+ const o = i.fam?.key ?? null;
311
+ if (o === null) return;
312
+ const s = new Map;
313
+ for (let e = 0; e < n.length; e++) {
314
+ const t = n[e];
315
+ const i = isWrappable(t) ? o(t) : undefined;
316
+ if (i !== undefined && !s.has(i)) s.set(i, t);
317
+ }
318
+ const f = new Set;
319
+ const a = [];
320
+ const l = r.rows;
321
+ for (let e = 0; e < l.length; e++) {
322
+ const n = l[e];
323
+ const t = isWrappable(n) ? o(n) : undefined;
324
+ const i = t !== undefined ? s.get(t) : undefined;
325
+ if (i !== undefined) {
326
+ a.push(i);
327
+ f.add(t);
328
+ } else a.push(n);
329
+ }
330
+ const u = r.removed;
331
+ for (let e = 0; e < n.length; e++) {
332
+ const t = n[e];
333
+ const i = isWrappable(t) ? o(t) : undefined;
334
+ if (i !== undefined && !f.has(i) && (u === null || !u.has(i))) a.push(t);
335
+ }
336
+ r.rows = a;
337
+ r.base = a;
338
+ const c = txOf(e);
339
+ const d = committed(i);
340
+ const p = i.n;
341
+ for (let e = 0; e < a.length; e++) {
342
+ const n = p?.[e];
343
+ // A slot the lane does not own shows the committed row: it becomes the
344
+ // lane's only where the composed row is another row (by key — the same
345
+ // key's new object is the same row, its target adopted it).
346
+ if (n === undefined) {
347
+ if (!sameRow(d[e], a[e], o)) laneSet(getNode(i, e), a[e], c);
348
+ } else if (!sameRow(n.l & CONFIG_OVERRIDE ? n.T.P : d[e], a[e], o)) laneSet(n, a[e], c);
349
+ }
350
+ if (p !== null) {
351
+ for (let e = a.length; ;e++) {
352
+ const n = p[e];
353
+ if (n === undefined) break;
354
+ laneSet(n, undefined, c);
355
+ }
356
+ const e = p.length;
357
+ if (e !== undefined && (e.l & CONFIG_OVERRIDE || d.length !== a.length)) laneSet(e, a.length, c);
358
+ }
359
+ };
360
+
361
+ /** D-34 for a keyed arrangement guess: rows by key, not positions. A
362
+ * current truth that differs folds into the hold beneath it instead of
363
+ * voiding the lane: the guess stays the lane's value and the screen's until
364
+ * the hold commits, where rows match by key, and the graph outside the lane
365
+ * re-derives from the truth now (`foldedRead`). A confirmation is silent
366
+ * (A17): only truth readers are told. True: the lane stages the truth
367
+ * beneath (`laneWrite`). */ function fold(e, n) {
368
+ const t = e.O?.k;
369
+ const i = txOf(e);
370
+ // A guess the screen never showed is void at the correction (D-34); a
371
+ // keyed arrangement guess's view carries its removed-keys set.
372
+ if (!i.Ue || !(t?.l & CONFIG_OVERRIDE) || !t.T.P?.removed) return false;
373
+ const r = e.T.P;
374
+ if ((!e.ye || !e.ye(r, n)) && !GlobalQueue.nn(r, n)) {
375
+ i.folded = foldedRead;
376
+ insertSubs(e);
377
+ } else GlobalQueue.sn?.(i);
378
+ joinFuture(resolveTx(i._parent ?? i));
379
+ return true;
380
+ }
381
+
382
+ /** A folded lane's guess read by a deriving pass outside the lane, tracked
383
+ * or not (`untrack` is about dependencies, not about which world a pass
384
+ * derives from), or by `latest()` (`c` null): the hold's world — the truth
385
+ * staged beneath the guess, else the value it covered — and the pass joins
386
+ * the hold. Lane passes and the screen keep the guess: held truth is masked
387
+ * from lane passes only (#3164). The store's own derive reconciles its
388
+ * landings against the arrangement the guesses made: it is the author, not
389
+ * a reader. */ function foldedRead(e, n) {
390
+ if (e !== null) {
391
+ if (!(n.l & CONFIG_GUESS) || passLane !== null || e.i === EFFECT_RENDER || e.l & CONFIG_CHILDREN_FORBIDDEN || n.O?.fam?.node === e) return NOT_PENDING;
392
+ const t = txOf(n);
393
+ joinPassAt(e, resolveTx(t._parent ?? t));
394
+ }
395
+ if (n.ue !== NOT_PENDING) return n.ue;
396
+ return n.l & CONFIG_SLOT_NODE ? GlobalQueue.an(n) : n.le;
397
+ }
398
+
399
+ function sameRow(e, n, t) {
400
+ if (e === n) return true;
401
+ if (!isWrappable(e) || !isWrappable(n)) return false;
402
+ const i = t(unwrapValue(e));
403
+ return i !== undefined && sameKey(i, t(unwrapValue(n)));
404
+ }
405
+
406
+ /** A composed value becomes the lane's on `node`: a guess re-based, or a
407
+ * node that was not the lane's becomes its derivation (its committed value
408
+ * untouched beneath; the lane's end commits the latest). */ function laneSet(e, n, t) {
409
+ const i = ext(e);
410
+ if (!(e.l & CONFIG_OVERRIDE)) {
411
+ e.l |= CONFIG_OVERRIDE;
412
+ list(e, t);
413
+ } else if (i.P === n) return;
414
+ i.P = n;
415
+ if (e.o !== null) {
416
+ insertSubs(e);
417
+ laneDirty(e, t);
418
+ }
419
+ }
420
+
421
+ /** D-34 for a per-key guess (#4329): the derive's draft wrote new objects
422
+ * over a target holding guessed rows (`d.length = 0; d.push(...rows)`, or
423
+ * `d.issues = rows`). The container on the way down to each guessed row
424
+ * reconciles the new object at its slot — in a keyed list, the one with
425
+ * the row's key — exactly as a returned landing would: rows match by key,
426
+ * a guessed row keeps its target, and its leaves are judged against their
427
+ * guesses. Rows nothing guessed are left as the draft wrote them. */ function pairRows(e, n) {
428
+ const t = e.fam.key;
429
+ for (let i of e.fam.overlaid ?? []) {
430
+ // The guessed row, or its ancestor directly under `t` (none: skip).
431
+ while (i.u !== e) if ((i = i.u) === null) break;
432
+ if (i === null) continue;
433
+ const r = t?.(i.v);
434
+ const o = Array.isArray(n) ? r !== undefined && n.find(e => isWrappable(e) && sameKey(t(e), r)) : n[i.pk];
435
+ // A new object only: not `c`'s own, nor one another row serves
436
+ // (pairing it would alias the two).
437
+ if (isWrappable(o) && !lookupTarget(o, e.fam)) reconcileState(o, i.px, t, true);
438
+ }
439
+ }
440
+
441
+ installOptHooks({
442
+ pair: pairRows,
443
+ draft: optimisticDraft,
444
+ writes: notifyOptimisticWrites,
445
+ arrangement: arrangement,
446
+ reconcile: reconcileDraft,
447
+ view: (e, n, t = false) => t ? optimisticView(e, n, laneValueOf, true) : optimisticView(e, n),
448
+ has: optimisticHas,
449
+ descriptor: optimisticOwnDescriptor,
450
+ sweep: sweepOverlaid,
451
+ // A new question (not a `refresh()`) asked over guesses an earlier frame
452
+ // opened, which answer the old one (D-34, #4336). Stamped on `fam.asked`
453
+ // with this flush's `clock`, so it lapses when the flush ends: `clock + 1`
454
+ // from mainline over a live guess — a frame still reading a guess at the
455
+ // seam shows it beside the new input, so the flush holds with the guess's
456
+ // action (`park`); `~clock` from a lane with no guess of its own, or with
457
+ // no live guess left — the lane waits for its answer (F-6), as for a
458
+ // guessed `createOptimistic` (lanes `laneStage`). The guess's own lane
459
+ // asks nothing new and stamps nothing.
460
+ ask: e => {
461
+ if (e.node.R & REACTIVE_REASK || !e.overlaid?.size) return;
462
+ // Stamped with the flush (`clock`): it lapses when the flush ends.
463
+ let n = ~clock;
464
+ for (const t of e.overlaid) {
465
+ const e = laneNodeOf(t);
466
+ if (e) {
467
+ if (passLane === null) n = clock + 1; else if (sameAction(txOf(e), passLane)) return;
468
+ }
469
+ }
470
+ if ((e.asked = n) > 0) joinFuture(null);
471
+ },
472
+ // Over a new question the guesses do not answer (`asked`): from mainline
473
+ // only a target carrying a guess stands in — a read of one with none is an
474
+ // ordinary pending read (F-2), so a keyed store's other keys wait for their
475
+ // answer, not for the guess's action; in a lane with no guess of its own,
476
+ // or with no live guess left, none does (F-6).
477
+ stands: e => {
478
+ const n = e.fam.overlaid;
479
+ const t = e.fam.asked;
480
+ return !!n?.size && (t !== clock + 1 || passLane !== null || n.has(e)) && t !== ~clock;
481
+ },
482
+ // Mainline hold (`clock + 1`): the flush joins the action of each guess a
483
+ // reader still reads at the seam; a reader that moved off it (a keyed
484
+ // store's other key) holds nothing.
485
+ park: e => {
486
+ for (const n of overlaidFamilies) if (n.asked === clock + 1) for (const t of n.overlaid) {
487
+ const n = laneNodeOf(t, true);
488
+ if (n) merge(txOf(n)._parent, e);
489
+ }
490
+ }
491
+ });
492
+
493
+ /** Two lanes of one action (their parents resolved through merges). */ function sameAction(e, n) {
494
+ return resolveTx(e._parent) === resolveTx(n._parent);
495
+ }
496
+
497
+ function shallowKeys(e) {
498
+ const n = {};
499
+ for (const t of Reflect.ownKeys(e)) if (t !== $OWNER) n[t] = unwrapValue(e[t]);
500
+ return n;
501
+ }
502
+
503
+ /** Families with a target carrying a lane value — swept at the flush's
504
+ * commit (`sweepOverlaid`): a target none of whose nodes is a lane's any
505
+ * more leaves its family's `overlaid`. (Not on the read path: a guess is
506
+ * pending between the setter and the seam, and a read in between must not
507
+ * take the target for clean.) */ const overlaidFamilies = new Set;
508
+
509
+ function markOverlaid(e) {
510
+ const n = e.fam;
511
+ (n.overlaid ??= new Set).add(e);
512
+ overlaidFamilies.add(n);
513
+ }
514
+
515
+ function sweepOverlaid() {
516
+ if (overlaidFamilies.size === 0) return;
517
+ for (const e of overlaidFamilies) {
518
+ const n = e.overlaid;
519
+ for (const e of n) if (!laneNodeOf(e)) {
520
+ n.delete(e);
521
+ if (e.ch) rebaseChained(e);
522
+ // The container shows its backing again (a shown arrangement guess
523
+ // that ended without a landing left its `LaneView` as the value).
524
+ const t = e.k;
525
+ if (t !== null && t.le instanceof LaneView) t.le = t.le.base;
526
+ }
527
+ if (n.size === 0) overlaidFamilies.delete(e);
528
+ }
529
+ }
530
+
531
+ /** A chained view's lanes ended: its nodes are links (§7b) whose committed
532
+ * value is the inner store's at the guess, not now — the inner may have
533
+ * moved underneath the guess (the base committed while the view showed
534
+ * its arrangement, #3672/F1). Re-base each node on the inner's truth and
535
+ * re-derive the readers whose shown value it is not. */ function rebaseChained(e) {
536
+ const n = e.v;
537
+ let t = false;
538
+ const i = e.n;
539
+ if (i !== null) for (const e of Reflect.ownKeys(i)) {
540
+ const r = i[e];
541
+ const o = untrack(() => unwrapValue(n[e]));
542
+ if (r.ye && r.ye(r.le, o)) continue;
543
+ r.le = o;
544
+ // (The lane's end notified it this epoch when the shown value and the
545
+ // covered one differed — its readers re-derive already.)
546
+ if (r.o !== null && r.Me !== notifyEpoch) {
547
+ insertSubs(r);
548
+ t = true;
549
+ }
550
+ }
551
+ const r = e.h;
552
+ if (r !== null) for (const e of Reflect.ownKeys(r)) {
553
+ const i = r[e];
554
+ const o = untrack(() => e in n);
555
+ if (i.le === o) continue;
556
+ i.le = o;
557
+ if (i.o !== null && i.Me !== notifyEpoch) {
558
+ insertSubs(i);
559
+ t = true;
560
+ }
561
+ }
562
+ // The arrangement the readers saw (the shown guess) against the inner's
563
+ // now: a structural reader re-derives when they differ.
564
+ const o = e.k;
565
+ if (o !== null && o.o !== null && o.le instanceof LaneView && o.Me !== notifyEpoch) {
566
+ const i = Array.isArray(n) ? untrack(() => n.map(unwrapValue)) : n;
567
+ if (!arrangementEqual(o.le.rows, i, e.fam)) {
568
+ insertSubs(o);
569
+ t = true;
570
+ }
571
+ }
572
+ if (t) schedule();
573
+ }
574
+
575
+ /** `t`'s nodes (a missing container or deep node: null). */ function nodesOf(e) {
576
+ const n = [ e.k, e.dk ];
577
+ for (const t of [ e.n, e.h ]) if (t !== null) for (const e of Reflect.ownKeys(t)) n.push(t[e]);
578
+ return n;
579
+ }
580
+
581
+ /** A node of `t` carrying a lane value, if any (`read`: one a reader's
582
+ * last pass read). */ function laneNodeOf(e, n) {
583
+ for (const t of nodesOf(e)) if (t?.l & CONFIG_OVERRIDE) {
584
+ if (!n) return t;
585
+ for (let e = t.o; e !== null; e = e.t) if (e.Ne === e.u.de) return t;
586
+ }
587
+ }
588
+
589
+ function overlaid(e) {
590
+ const n = e.fam;
591
+ return n !== null && n.opt === true && n.overlaid !== undefined && n.overlaid.has(e);
592
+ }
593
+
594
+ /** What a lane node shows an untracked reader here: core's rule (`read`
595
+ * without a link — the lane's world inside its own pass, the screen
596
+ * outside, a verdict window's answer under one). */ const shown = e => untrack(() => read(e));
597
+
598
+ /** An untracked `key in store` on an optimistic family: the presence guess
599
+ * (what its lane shows) when the key carries one; `undefined` when not —
600
+ * the backing answers. */ function optimisticHas(e, n) {
601
+ if (!overlaid(e)) return undefined;
602
+ const t = e.h?.[n];
603
+ if (t !== undefined && t.l & CONFIG_OVERRIDE) return !!shown(t);
604
+ const i = e.n?.[n];
605
+ if (i !== undefined && i.l & CONFIG_OVERRIDE) return shown(i) !== undefined;
606
+ return undefined;
607
+ }
608
+
609
+ /** A descriptor read of a guessed key: synthesized from the lane's value
610
+ * (`null`: the guess removed the key; `undefined`: no guess — the backing
611
+ * describes it). */ function optimisticOwnDescriptor(e, n) {
612
+ const t = optimisticHas(e, n);
613
+ if (t === undefined) return undefined;
614
+ if (!t) return null;
615
+ const i = e.n?.[n];
616
+ const r = i !== undefined && i.l & CONFIG_OVERRIDE ? shown(i) : e.v[n];
617
+ // An array's `length` is reported as the array has it (non-configurable).
618
+ if (n === "length" && Array.isArray(e.v)) return {
619
+ value: r,
620
+ writable: true,
621
+ enumerable: false,
622
+ configurable: false
623
+ };
624
+ return {
625
+ value: r,
626
+ writable: true,
627
+ enumerable: true,
628
+ configurable: true
629
+ };
630
+ }
631
+
632
+ /** The truth `src` with the target's lane values over it: each overlaid
633
+ * leaf's value (`pick`: what the lane shows, or — for `latest` — the lane's
634
+ * latest), each presence guess as a key added or removed, the array
635
+ * length. Returns `src` itself when nothing is overlaid. */ function optimisticView(e, n, t = shown,
636
+ // The writer's view: the unflushed guesses too (on nodes that are no
637
+ // lane's yet) — what the next write composes on (#3665).
638
+ i = false) {
639
+ if (!i && !overlaid(e)) return n;
640
+ let r = null;
641
+ const ensure = () => r ??= Array.isArray(n) ? [ ...n ] : {
642
+ ...n
643
+ };
644
+ const o = e.n;
645
+ if (o !== null) {
646
+ for (const e of Reflect.ownKeys(o)) {
647
+ const r = o[e];
648
+ let s;
649
+ if (r.l & CONFIG_OVERRIDE) s = t(r); else if (!i || (s = pendingGuessOf(r)) === NOT_PENDING) continue;
650
+ if (e === "length" && Array.isArray(n)) {
651
+ if (n.length !== s) ensure().length = s;
652
+ } else if (!isEqual(n[e], s) || !hasOwn.call(n, e)) {
653
+ ensure()[e] = s;
654
+ }
655
+ }
656
+ }
657
+ const s = e.h;
658
+ if (s !== null) {
659
+ for (const e of Reflect.ownKeys(s)) {
660
+ const o = s[e];
661
+ let f;
662
+ if (o.l & CONFIG_OVERRIDE) f = t(o); else if (!i || (f = pendingGuessOf(o)) === NOT_PENDING) continue;
663
+ const a = !!f;
664
+ const l = r ?? n;
665
+ if (!a && e in l) delete ensure()[e];
666
+ }
667
+ }
668
+ return r ?? n;
669
+ }
670
+
671
+ function createOptimisticStore(e, n, t) {
672
+ const i = typeof e === "function";
673
+ const r = i ? t : n;
674
+ // Seedless derived form: the root starts as an empty record (see
675
+ // createProjectionInternal).
676
+ const o = i ? n || {} : e;
677
+ const s = r?.key === undefined ? "id" : r.key;
678
+ const f = {
679
+ map: new WeakMap,
680
+ node: null,
681
+ live: new Set,
682
+ shallow: !!r?.shallow,
683
+ opt: true,
684
+ key: typeof s === "function" ? s : s === null ? null : e => isWrappable(e) ? e[s] : undefined
685
+ };
686
+ const a = wrap(o, null, null, f);
687
+ if (f.shallow) {
688
+ a[$TARGET].s = true;
689
+ markRawIngest(o);
690
+ }
691
+ if (i) {
692
+ const n = e;
693
+ let t;
694
+ if (r?.seedLoadingValue) t = {
695
+ loadingValue: undefined
696
+ };
697
+ const i = computed(() => {
698
+ if (!f.node) f.node = getOwner();
699
+ runProjectionComputed(a, n, s);
700
+ }, t);
701
+ i.l &= ~CONFIG_AUTO_DISPOSE;
702
+ f.node = i;
703
+ }
704
+ return [ a, e => storeSetter(a, e) ];
705
+ }
706
+
707
+ export { createOptimisticStore, notifyOptimisticWrites, optimisticHas, optimisticOwnDescriptor, optimisticView, sweepOverlaid };