@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,593 @@
1
+ import { computed, runWithOwner, signal, setSignal } from "./core/core.js";
2
+
3
+ import "./core/verdict.js";
4
+
5
+ import { CONFIG_AUTO_DISPOSE } from "./core/constants.js";
6
+
7
+ import { attrHooks } from "./core/attribution-hooks.js";
8
+
9
+ import "./core/dev.js";
10
+
11
+ import "./core/scheduler.js";
12
+
13
+ import { createOwner, getOwner } from "./core/owner.js";
14
+
15
+ import "./core/effect.js";
16
+
17
+ import { accessor } from "./signals.js";
18
+
19
+ import { $TRACK, shallowView, $TARGET } from "./store/types.js";
20
+
21
+ function mapArray(t, e, i) {
22
+ const s = typeof i?.keyed === "function" ? i.keyed : undefined;
23
+ const n = e.length > 1;
24
+ const r = e;
25
+ const o = {
26
+ H: createOwner(),
27
+ wt: 0,
28
+ Mt: t,
29
+ Wt: [],
30
+ vt: r,
31
+ Kt: [],
32
+ Ye: [],
33
+ gt: s,
34
+ $t: s || i?.keyed === false ? [] : undefined,
35
+ xt: n && i?.keyed !== false ? [] : undefined,
36
+ Ut: i?.keyed === false,
37
+ L: i?.fallback
38
+ };
39
+ const f = computed(updateKeyedMap.bind(o), i?.name ? {
40
+ name: i.name
41
+ } : undefined);
42
+ f.l &= ~CONFIG_AUTO_DISPOSE;
43
+ return accessor(f);
44
+ }
45
+
46
+ const pureOptions = {
47
+ ownedWrite: true
48
+ };
49
+
50
+ function trySmallMove(t, e, i, s) {
51
+ const n = t.Wt;
52
+ const r = t.wt - 1;
53
+ const o = [];
54
+ const f = [];
55
+ const h = [];
56
+ // flat triples: oldStart, newStart, length
57
+ let c = 256;
58
+ let a = s;
59
+ let l = s;
60
+ let u = false;
61
+ while (a <= r && l <= i - 1) {
62
+ const t = n[a];
63
+ const s = e[l];
64
+ if (t === s) {
65
+ if (!u) {
66
+ h.push(a, l, 0);
67
+ u = true;
68
+ }
69
+ h[h.length - 1]++;
70
+ a++;
71
+ l++;
72
+ continue;
73
+ }
74
+ u = false;
75
+ // Bounded realignment lookahead, shorter distance wins.
76
+ let d = -1;
77
+ let w = Math.min(32 - o.length, r - a, c);
78
+ for (let t = 1; t <= w; t++) {
79
+ if (n[a + t] === s) {
80
+ d = t;
81
+ break;
82
+ }
83
+ }
84
+ c -= d === -1 ? w : d;
85
+ let p = -1;
86
+ w = Math.min(32 - f.length, i - 1 - l, c);
87
+ for (let i = 1; i <= w; i++) {
88
+ if (e[l + i] === t) {
89
+ p = i;
90
+ break;
91
+ }
92
+ }
93
+ c -= p === -1 ? w : p;
94
+ if (d !== -1 && (p === -1 || d <= p)) {
95
+ while (d-- > 0) o.push(a++);
96
+ continue;
97
+ }
98
+ if (p !== -1) {
99
+ while (p-- > 0) f.push(l++);
100
+ continue;
101
+ }
102
+ if (c <= 0 || o.length === 32 || f.length === 32) return false;
103
+ o.push(a++);
104
+ f.push(l++);
105
+ }
106
+ for (;a <= r; a++) {
107
+ if (o.length === 32) return false;
108
+ o.push(a);
109
+ }
110
+ for (;l <= i - 1; l++) {
111
+ if (f.length === 32) return false;
112
+ f.push(l);
113
+ }
114
+ return commitSmallMove(t, e, i, o, f, h);
115
+ }
116
+
117
+ /** PHASE 2 of the small-move path, in its OWN function so that a pass which
118
+ * only SCANS and bails (a full replace: the first structural pass of a page,
119
+ * typically) compiles nothing but the scan — V8 parses and compiles lazily
120
+ * per function, and cold `replace` measured +0.5 ms with both phases in one
121
+ * body. Pairs displaced sources with destinations (an unmatched destination
122
+ * is a replacement/insertion → general path), then commits: slice() the live
123
+ * arrays, copy shifted runs, patch displaced pairs, dispose leftovers. */ function commitSmallMove(t, e, i, s, n, r) {
124
+ const o = t.Wt;
125
+ let f;
126
+ let h;
127
+ let c;
128
+ if (n.length !== 0) {
129
+ c = new Array(s.length);
130
+ for (h = 0; h < n.length; h++) {
131
+ let t = -1;
132
+ for (f = 0; f < s.length; f++) {
133
+ if (!c[f] && o[s[f]] === e[n[h]]) {
134
+ t = f;
135
+ break;
136
+ }
137
+ }
138
+ if (t === -1) return false;
139
+ c[t] = true;
140
+ n[h] = n[h] << 6 | t;
141
+ // pack pairing (found < 32)
142
+ }
143
+ }
144
+ // DUPLICATES: the general path pairs equal identities by OCCURRENCE ORDER
145
+ // (the chained index map). Displaced↔displaced pairing above is ascending
146
+ // on both sides, so it agrees; but an aligned run was matched by POSITION,
147
+ // and if a displaced identity also occurs inside a run the two algorithms
148
+ // can hand different occurrences different owners (row-local state moves;
149
+ // a shrink could dispose the wrong one). Decline that case — general path.
150
+ if (s.length !== 0 || n.length !== 0) {
151
+ const t = new Set;
152
+ for (f = 0; f < s.length; f++) t.add(o[s[f]]);
153
+ for (h = 0; h < n.length; h++) t.add(e[n[h] >> 6]);
154
+ for (let e = 0; e < r.length; e += 3) {
155
+ const i = r[e];
156
+ for (let s = 0, n = r[e + 2]; s < n; s++) if (t.has(o[i + s])) return false;
157
+ }
158
+ }
159
+ const a = t.Kt;
160
+ const l = t.Ye;
161
+ const u = a.slice(0, i);
162
+ const d = l.slice(0, i);
163
+ for (let t = 0; t < r.length; t += 3) {
164
+ const e = r[t];
165
+ const i = r[t + 1];
166
+ if (e !== i) {
167
+ for (let s = 0; s < r[t + 2]; s++) {
168
+ u[i + s] = a[e + s];
169
+ d[i + s] = l[e + s];
170
+ }
171
+ }
172
+ }
173
+ for (h = 0; h < n.length; h++) {
174
+ const t = n[h] >> 6;
175
+ const e = s[n[h] & 63];
176
+ u[t] = a[e];
177
+ d[t] = l[e];
178
+ }
179
+ t.Kt = u;
180
+ t.Ye = d;
181
+ t.wt = i;
182
+ t.Wt = e.slice(0);
183
+ // Dispose unmatched sources LAST (general-path ordering).
184
+ for (f = 0; f < s.length; f++) {
185
+ if (c === undefined || !c[f]) l[s[f]].dispose();
186
+ }
187
+ return true;
188
+ }
189
+
190
+ /** Stage a PURE REMOVAL without the key map: when the new window is the old
191
+ * window with items dropped, in order (one-item removals, every-nth, the
192
+ * table filters), a two-pointer walk lands every survivor in the window
193
+ * stage with one key call per item and returns the leavers; a shape that is
194
+ * not an ordered subsequence returns null with the node stage cleared, and
195
+ * the map path below starts from scratch (it rewrites every window slot of
196
+ * `temp` / `rows` / `indexes`, so only `tempNodes`' `!== undefined` probe
197
+ * needs the reset). The stage arrays are scratch — nothing live is touched. */ function stageRemoval(t, e, i, s, n, r, o, f, h) {
198
+ const c = t.gt;
199
+ const a = t.Wt;
200
+ const l = t.Ye;
201
+ const u = [];
202
+ let d = i;
203
+ for (let w = i; w <= n; d++, w++) {
204
+ const n = c ? c(e[w]) : e[w];
205
+ while (d <= s && (c ? c(a[d]) : a[d]) !== n) u.push(l[d++]);
206
+ if (d > s) {
207
+ o.fill(undefined);
208
+ return null;
209
+ }
210
+ r[w] = t.Kt[d];
211
+ o[w - i] = l[d];
212
+ if (f) f[w - i] = t.$t[d];
213
+ if (h) h[w - i] = t.xt[d];
214
+ }
215
+ for (;d <= s; d++) u.push(l[d]);
216
+ return u;
217
+ }
218
+
219
+ /** Land a staged window into the live bookkeeping arrays in place: shift the
220
+ * suffix by `dif` (a loop walked from the side that never overwrites an
221
+ * unread slot), take the window from the stage, write survivors' row and
222
+ * index signals. Its own function so the general path's body stays under
223
+ * the JIT's optimization budget — the inlined commit measured ~10% slower on
224
+ * full-window reorders (the small-move note has the same finding). */ function commitWindow(t, e, i, s, n, r, o, f, h) {
225
+ const c = t.Ye;
226
+ const a = t.$t;
227
+ const l = t.xt;
228
+ const u = t.wt;
229
+ const d = i - u;
230
+ let w, p;
231
+ if (d > 0) {
232
+ // Grow first: a store past the end from the top is a third slower than
233
+ // filling a pre-sized tail (measured on 1k refs, 2026-10-15).
234
+ c.length = i;
235
+ if (a) a.length = i;
236
+ if (l) l.length = i;
237
+ for (w = u - 1, p = i - 1; w > n; w--, p--) {
238
+ c[p] = c[w];
239
+ if (a) a[p] = a[w];
240
+ if (l) l[p] = l[w];
241
+ }
242
+ } else if (d < 0) {
243
+ for (w = n + 1, p = r + 1; w < u; w++, p++) {
244
+ c[p] = c[w];
245
+ if (a) a[p] = a[w];
246
+ if (l) l[p] = l[w];
247
+ }
248
+ c.length = i;
249
+ if (a) a.length = i;
250
+ if (l) l.length = i;
251
+ }
252
+ for (p = s; p <= r; p++) {
253
+ c[p] = o[p - s];
254
+ if (a) setSignal(a[p] = f[p - s], e[p]);
255
+ if (l) setSignal(l[p] = h[p - s], p);
256
+ }
257
+ for (p = r + 1; p < i; p++) {
258
+ if (a) setSignal(a[p], e[p]);
259
+ if (l && d !== 0) setSignal(l[p], p);
260
+ }
261
+ }
262
+
263
+ function updateKeyedMap() {
264
+ // Untracked reads inside the internal owner resolve via _parentComputed:
265
+ // routed through the node, a store-proxy lookup sees pending writes (not a
266
+ // stale _value) and an async read in a row callback registers the node as
267
+ // the flight's reader (pending tracking + post-settle retry) instead of
268
+ // vanishing. Set per pass: the first pass runs inside `computed()`, before
269
+ // the node exists to the caller.
270
+ this.H.Ht = getOwner();
271
+ let t = this.Mt() || [];
272
+ t[$TRACK];
273
+ // top level tracking (a store array's container node)
274
+ // A shallow store array diffs its backing: its slots are raw records, and
275
+ // a trap per slot read was most of a one-row write on a 1k-row list.
276
+ t = shallowView?.(t[$TARGET]) ?? t;
277
+ const e = t.length;
278
+ runWithOwner(this.H, () => {
279
+ let i, s,
280
+ // The stage slot a mapper writes its row/index signal into: `j` on the
281
+ // create-all path, `j - start` on the general path, whose stage arrays
282
+ // are sized to the changed WINDOW, not the list.
283
+ n, r, o,
284
+ // Mappers write freshly-created row/index signals into the STAGE
285
+ // arrays (`rows`/`indexes`), never into `this._rows`/`this._indexes`.
286
+ f = this.$t ? this.Ut ? () => {
287
+ r[n] = signal(t[s], pureOptions);
288
+ return this.vt(accessor(r[n]), s);
289
+ } : () => {
290
+ r[n] = signal(t[s], pureOptions);
291
+ o && (o[n] = signal(s, pureOptions));
292
+ return this.vt(accessor(r[n]), o ? accessor(o[n]) : undefined);
293
+ } : this.xt ? () => {
294
+ const e = t[s];
295
+ o[n] = signal(s, pureOptions);
296
+ return this.vt(e, accessor(o[n]));
297
+ } : () => {
298
+ const e = t[s];
299
+ return this.vt(e);
300
+ };
301
+ // fast path for empty arrays
302
+ if (e === 0) {
303
+ if (this.wt !== 0) {
304
+ this.H.dispose(false);
305
+ this.Ye = [];
306
+ this.Wt = [];
307
+ this.Kt = [];
308
+ this.wt = 0;
309
+ this.$t && (this.$t = []);
310
+ this.xt && (this.xt = []);
311
+ }
312
+ if (this.L && !this.Kt.length) {
313
+ // an aborted fallback attempt leaves an owner without a mapping;
314
+ // dispose it before re-creating
315
+ this.Ye[0]?.dispose();
316
+ this.Kt[0] = runWithOwner(this.Ye[0] = createOwner(), this.L);
317
+ }
318
+ }
319
+ // fast path for new create
320
+ else if (this.wt === 0) {
321
+ const h = new Array(e);
322
+ const c = new Array(e);
323
+ r = this.$t && new Array(e);
324
+ o = this.xt && new Array(e);
325
+ try {
326
+ for (s = 0; s < e; s++) {
327
+ n = s;
328
+ h[s] = runWithOwner(c[s] = createOwner(), f);
329
+ }
330
+ } catch (t) {
331
+ for (i = 0; i <= s; i++) c[i]?.dispose();
332
+ throw t;
333
+ }
334
+ // commit
335
+ if (this.Ye[0]) this.Ye[0].dispose();
336
+ // previous fallback
337
+ this.Kt = h;
338
+ this.Ye = c;
339
+ r && (this.$t = r);
340
+ o && (this.xt = o);
341
+ this.Wt = t.slice(0);
342
+ this.wt = e;
343
+ } else {
344
+ let h, c, a, l, u, d, w, p, m,
345
+ // Dev (attribution engine installed): the items behind the exited and
346
+ // entered rows, for the list-identity census.
347
+ O, _;
348
+ // The pass's write to a per-slot signal (a row accessor in index mode,
349
+ // an index accessor in keyed mode). The list's frame lives in these
350
+ // writes as much as in the computed's result, so under a LANE pass they
351
+ // are the lane's frame too (F1): a plain `setSignal` staged them into
352
+ // the action's transaction and the row readers were served the
353
+ // committed value until the action landed — `<For>` without `keyed`
354
+ // showed the pre-action list for the whole action while the keyed modes
355
+ // showed the optimistic one. The engine publishes the write as a
356
+ // derived override on the slot (lanes stage, A17) and lands or
357
+ // supersedes it when a plain pass later writes a slot still carrying
358
+ // one (A18) — `landOnOverride`'s slot arm. Decided once per pass, not
359
+ // per slot: a lane pass marks the map (`_laneSlots`: its slots may
360
+ // carry overrides), a marked map routes every slot write through the
361
+ // engine while any lane is live — a slot's override resolves with its
362
+ // lane's transaction, or with the batch for an orphan lane
363
+ // (resolveOptimisticNodes, then cleanupCompletedLanes, both before the
364
+ // completion wakes any recompute), so a pass that finds no lane live
365
+ // knows the slots are clean and drops the mark — and an unmarked map
366
+ // takes `setSignal` directly. The engine is installed whenever a lane
367
+ // is active.
368
+ // CARVE 2: the lane-slot arm (`_landOnOverride`, F1) went with the engine.
369
+ const y = setSignal;
370
+ // skip common prefix
371
+ for (h = 0, c = Math.min(this.wt, e); h < c && (this.Wt[h] === t[h] || this.$t && compare(this.gt, this.Wt[h], t[h])); h++) {
372
+ if (this.$t) y(this.$t[h], t[h]);
373
+ }
374
+ // skip common suffix — counted only; retained entries land in one pass
375
+ // at commit instead of being staged and copied twice
376
+ for (c = this.wt - 1, a = e - 1; c >= h && a >= h && (this.Wt[c] === t[a] || this.$t && compare(this.gt, this.Wt[c], t[a])); c--,
377
+ a--) ;
378
+ // no structural change (every position matched in place at equal
379
+ // length — the common post-reconcile shape): keep the same mapped
380
+ // array identity so downstream consumers don't re-run at all
381
+ if (h === e && this.wt === e) {
382
+ this.Wt = t.slice(0);
383
+ return;
384
+ }
385
+ // SMALL-MOVE FAST PATH: extracted to its own function — inlining it
386
+ // here bloats updateKeyedMap past the JIT's optimization budget and
387
+ // deoptimizes the GENERAL path (measured 2x on reverse). Gated to
388
+ // LARGE trimmed windows: when the trims already shrank the window
389
+ // (plain removals, tail edits), the general path is window-
390
+ // proportional and cheap — the fast path would only re-walk what the
391
+ // trims proved.
392
+ if (e <= this.wt && c - h > 64 && this.$t === undefined && this.xt === undefined) {
393
+ // PROBE before the scan: a small move keeps a mid-window item within
394
+ // ±32 of its old position; a REPLACE (all fresh items — the shape
395
+ // every page's first structural pass usually is) has it nowhere.
396
+ // ~65 compares, no allocation, and the scan function is never
397
+ // compiled for a replace (its cold first-call compile was the cost).
398
+ const i = h + (a - h >> 1);
399
+ const s = t[i];
400
+ const n = Math.min(c, i + 32);
401
+ let r = Math.max(h, i - 32);
402
+ while (r <= n && this.Wt[r] !== s) r++;
403
+ if (r <= n && trySmallMove(this, t, e, h)) return;
404
+ }
405
+ const A = e - this.wt;
406
+ // WINDOW-SIZED STAGING, IN-PLACE COMMIT (2026-10-15). The strong-abort
407
+ // contract (#2903) only needs the pass to touch nothing live before
408
+ // every mapper has succeeded; it never needed four fresh newLen-sized
409
+ // arrays. Only the changed window [start, newEnd] is staged — the
410
+ // prefix and suffix are, by construction, the rows that did not move
411
+ // relative to each other — and at commit the bookkeeping arrays
412
+ // (`_nodes`, `_rows`, `_indexes`) take the window in place with the
413
+ // suffix shifted by a plain loop (`copyWithin` is a generic
414
+ // per-element builtin in V8 — 30× slower than the loop on 1k refs,
415
+ // measured 2026-10-15). `_mappings` alone is
416
+ // rebuilt: its fresh identity is the change signal downstream relies
417
+ // on. A one-row edit on a 500-row list used to allocate ~20 KB of
418
+ // staging plus a position-sized chain array per commit (uibench's
419
+ // one-item tree ops at 4–6× Octane, jfb-reorder `removefirst` at
420
+ // 2.5×); now it stages one slot.
421
+ const g = a - h + 1;
422
+ const S = new Array(e);
423
+ const M = new Array(g);
424
+ r = this.$t ? new Array(g) : undefined;
425
+ o = this.xt ? new Array(g) : undefined;
426
+ // A shrinking pass is tried as a pure removal first (stageRemoval: no
427
+ // key map, one key call per item); anything else takes the map path.
428
+ const k = A < 0 ? stageRemoval(this, t, h, c, a, S, M, r, o) : null;
429
+ if (k !== null) {
430
+ // (The list-churn census below wants removals AND creations in one
431
+ // pass; a pure removal has none, so no item ledger is kept here.)
432
+ if (k.length !== 0) p = k;
433
+ } else {
434
+ // 0) prepare a map of all indices in the changed window of newItems,
435
+ // scanning backwards so we encounter them in natural order
436
+ d = new Map;
437
+ w = new Array(g);
438
+ for (s = a; s >= h; s--) {
439
+ l = t[s];
440
+ u = this.gt ? this.gt(l) : l;
441
+ i = d.get(u);
442
+ w[s - h] = i === undefined ? -1 : i;
443
+ d.set(u, s);
444
+ }
445
+ // 1) step through the old changed window and see if items can be found
446
+ // in the new set; if so, stage them at their new positions; if not,
447
+ // queue them for disposal at commit
448
+ for (i = h; i <= c; i++) {
449
+ l = this.Wt[i];
450
+ u = this.gt ? this.gt(l) : l;
451
+ s = d.get(u);
452
+ if (s !== undefined && s !== -1) {
453
+ S[s] = this.Kt[i];
454
+ M[s - h] = this.Ye[i];
455
+ r && (r[s - h] = this.$t[i]);
456
+ o && (o[s - h] = this.xt[i]);
457
+ s = w[s - h];
458
+ d.set(u, s);
459
+ } else {
460
+ (p ??= []).push(this.Ye[i]);
461
+ if (true && attrHooks !== null) (O ??= []).push(l);
462
+ }
463
+ }
464
+ // 2) create new rows into the window stage; an abort disposes only these
465
+ try {
466
+ for (s = h; s <= a; s++) {
467
+ if (M[s - h] !== undefined) continue;
468
+ (m ??= []).push(M[s - h] = createOwner());
469
+ if (true && attrHooks !== null) (_ ??= []).push(t[s]);
470
+ n = s - h;
471
+ S[s] = runWithOwner(M[s - h], f);
472
+ }
473
+ } catch (t) {
474
+ if (m) for (i = 0; i < m.length; i++) m[i].dispose();
475
+ throw t;
476
+ }
477
+ }
478
+ // 3) commit: the retained prefix and suffix land in the fresh mapped
479
+ // array; the bookkeeping arrays take the staged window IN PLACE (own
480
+ // function: kept out of this body on purpose, see commitWindow); then
481
+ // the exited rows dispose
482
+ for (i = 0; i < h; i++) S[i] = this.Kt[i];
483
+ for (s = a + 1; s < e; s++) S[s] = this.Kt[s - A];
484
+ commitWindow(this, t, e, h, c, a, M, r, o);
485
+ this.Kt = S;
486
+ this.wt = e;
487
+ // save a copy of the mapped items for the next update
488
+ this.Wt = t.slice(0);
489
+ if (p) for (i = 0; i < p.length; i++) p[i].dispose();
490
+ if (true && attrHooks !== null && O !== undefined && _ !== undefined) attrHooks.listChurn(this.H.Ht, O, _, e, this.gt !== undefined);
491
+ }
492
+ });
493
+ return this.Kt;
494
+ }
495
+
496
+ /**
497
+ * Reactively renders a callback `count` times, reusing previously-rendered
498
+ * entries when only the count changes. Underlying helper for `<Repeat>`.
499
+ *
500
+ * - `options.from` — start index (default `0`); useful for offset/windowed
501
+ * rendering.
502
+ * - `options.fallback` — accessor returning a value to show when count is `0`.
503
+ *
504
+ * @example
505
+ * ```ts
506
+ * const view = repeat(count, i => `Item ${i}`, { fallback: () => "empty" });
507
+ * ```
508
+ *
509
+ * @description https://v2.solidjs.com/reference/solid-js/advanced/jsx-component-primitives/repeat
510
+ */ function repeat(t, e, i) {
511
+ const s = e;
512
+ const n = {
513
+ H: createOwner(),
514
+ wt: 0,
515
+ qt: 0,
516
+ zt: t,
517
+ vt: s,
518
+ Ye: [],
519
+ Kt: [],
520
+ Bt: i?.from,
521
+ L: i?.fallback
522
+ };
523
+ const r = computed(updateRepeat.bind(n));
524
+ r.l &= ~CONFIG_AUTO_DISPOSE;
525
+ return accessor(r);
526
+ }
527
+
528
+ // Same staged-commit discipline as `updateKeyedMap` (#2903): the retained
529
+ // window overlap is copied into fresh arrays, missing indexes are created
530
+ // into them, and `this` is only touched — including disposal of rows leaving
531
+ // the window — after every `_map` call succeeded. A NotReadyError mid-pass
532
+ // disposes only the owners this pass created and leaves prior state intact
533
+ // for the post-settle retry. The overlap math also subsumes the previous
534
+ // disjoint-window/front-clear/end-clear/shift special cases.
535
+ function updateRepeat() {
536
+ // As in updateKeyedMap: the node is the row callbacks' reader, per pass.
537
+ this.H.Ht = getOwner();
538
+ const t = this.zt();
539
+ const e = this.Bt?.() || 0;
540
+ runWithOwner(this.H, () => {
541
+ if (t === 0) {
542
+ if (this.wt !== 0) {
543
+ this.H.dispose(false);
544
+ this.Ye = [];
545
+ this.Kt = [];
546
+ this.wt = 0;
547
+ // Reset offset to match the cleared data (#2767, repro 2).
548
+ this.qt = 0;
549
+ }
550
+ if (this.L && !this.Kt.length) {
551
+ // an aborted fallback attempt leaves an owner without a mapping;
552
+ // dispose it before re-creating
553
+ this.Ye[0]?.dispose();
554
+ this.Kt[0] = runWithOwner(this.Ye[0] = createOwner(), this.L);
555
+ }
556
+ return;
557
+ }
558
+ const i = e + t;
559
+ const s = this.qt + this.wt;
560
+ // Retained overlap [keepStart, keepEnd) in global indexes; empty when the
561
+ // windows are disjoint or when coming from empty/fallback.
562
+ const n = Math.max(e, this.qt);
563
+ const r = Math.min(i, s);
564
+ const o = new Array(t);
565
+ const f = new Array(t);
566
+ for (let t = n; t < r; t++) {
567
+ f[t - e] = this.Ye[t - this.qt];
568
+ o[t - e] = this.Kt[t - this.qt];
569
+ }
570
+ try {
571
+ for (let t = e; t < i; t++) {
572
+ if (t >= n && t < r) continue;
573
+ o[t - e] = runWithOwner(f[t - e] = createOwner(), () => this.vt(t));
574
+ }
575
+ } catch (t) {
576
+ for (let t = e; t < i; t++) if ((t < n || t >= r) && f[t - e]) f[t - e].dispose();
577
+ throw t;
578
+ }
579
+ // commit: dispose the previous fallback or the rows leaving the window
580
+ if (this.wt === 0) this.Ye[0]?.dispose(); else for (let t = this.qt; t < s; t++) if (t < e || t >= i) this.Ye[t - this.qt].dispose();
581
+ this.Kt = o;
582
+ this.Ye = f;
583
+ this.qt = e;
584
+ this.wt = t;
585
+ });
586
+ return this.Kt;
587
+ }
588
+
589
+ function compare(t, e, i) {
590
+ return t ? t(e) === t(i) : true;
591
+ }
592
+
593
+ export { mapArray, repeat };