@solidjs/signals 2.0.0-rc.1 → 2.0.0-rc.11

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 (150) hide show
  1. package/dist/dev-shared.js +7155 -0
  2. package/dist/dev.attribution.js +3307 -0
  3. package/dist/dev.js +5765 -4496
  4. package/dist/observe/affects.js +129 -0
  5. package/dist/observe/attribution.js +7 -0
  6. package/dist/observe/boundaries.js +793 -0
  7. package/dist/observe/core/action.js +177 -0
  8. package/dist/observe/core/async.js +849 -0
  9. package/dist/observe/core/attribution-costs.js +66 -0
  10. package/dist/observe/core/attribution-feedback.js +280 -0
  11. package/dist/observe/core/attribution-hooks.js +83 -0
  12. package/dist/observe/core/attribution-queries.js +43 -0
  13. package/dist/observe/core/attribution.js +2904 -0
  14. package/dist/observe/core/constants.js +283 -0
  15. package/dist/{types-cjs/core/context.d.cts → observe/core/context.js} +37 -12
  16. package/dist/observe/core/core.js +1999 -0
  17. package/dist/observe/core/dev.js +343 -0
  18. package/dist/observe/core/effect.js +200 -0
  19. package/dist/observe/core/error-hooks.js +71 -0
  20. package/dist/observe/core/error.js +80 -0
  21. package/dist/observe/core/external.js +98 -0
  22. package/dist/observe/core/graph.js +155 -0
  23. package/dist/observe/core/heap.js +147 -0
  24. package/dist/observe/core/invariants.js +45 -0
  25. package/dist/observe/core/lanes.js +205 -0
  26. package/dist/observe/core/optimistic.js +669 -0
  27. package/dist/observe/core/owner.js +353 -0
  28. package/dist/observe/core/scheduler.js +1561 -0
  29. package/dist/observe/core/verdict.js +674 -0
  30. package/dist/observe/index.js +59 -0
  31. package/dist/observe/map.js +507 -0
  32. package/dist/observe/signals.js +731 -0
  33. package/dist/observe/store/index.js +44 -0
  34. package/dist/observe/store/next/optimistic.js +717 -0
  35. package/dist/observe/store/next/projection.js +266 -0
  36. package/dist/observe/store/next/reconcile.js +375 -0
  37. package/dist/observe/store/next/store.js +2480 -0
  38. package/dist/observe/store/next/target.js +51 -0
  39. package/dist/observe/store/store.js +331 -0
  40. package/dist/observe/store/storePath.js +103 -0
  41. package/dist/observe/store/utils.js +1070 -0
  42. package/dist/prod/affects.js +10 -9
  43. package/dist/prod/attribution.js +45 -0
  44. package/dist/prod/boundaries.js +388 -178
  45. package/dist/prod/core/action.js +65 -37
  46. package/dist/prod/core/async.js +378 -163
  47. package/dist/prod/core/attribution-hooks.js +3 -0
  48. package/dist/prod/core/constants.js +186 -1
  49. package/dist/prod/core/context.js +10 -16
  50. package/dist/prod/core/core.js +1546 -416
  51. package/dist/prod/core/dev.js +18 -1
  52. package/dist/prod/core/effect.js +119 -79
  53. package/dist/prod/core/error-hooks.js +71 -0
  54. package/dist/prod/core/error.js +13 -1
  55. package/dist/prod/core/external.js +4 -4
  56. package/dist/prod/core/graph.js +105 -54
  57. package/dist/prod/core/heap.js +72 -65
  58. package/dist/prod/core/invariants.js +3 -2
  59. package/dist/prod/core/lanes.js +117 -52
  60. package/dist/prod/core/optimistic.js +500 -104
  61. package/dist/prod/core/owner.js +131 -84
  62. package/dist/prod/core/scheduler.js +1012 -241
  63. package/dist/prod/core/verdict.js +417 -112
  64. package/dist/prod/index.js +20 -8
  65. package/dist/prod/map.js +355 -171
  66. package/dist/prod/signals.js +363 -32
  67. package/dist/prod/store/index.js +2 -0
  68. package/dist/prod/store/next/optimistic.js +530 -197
  69. package/dist/prod/store/next/projection.js +142 -57
  70. package/dist/prod/store/next/reconcile.js +149 -103
  71. package/dist/prod/store/next/store.js +1470 -346
  72. package/dist/prod/store/next/target.js +40 -9
  73. package/dist/prod/store/store.js +23 -19
  74. package/dist/prod/store/utils.js +997 -130
  75. package/dist/types/attribution.d.ts +19 -0
  76. package/dist/types/attribution.prod.d.ts +22 -0
  77. package/dist/types/boundaries.d.ts +78 -5
  78. package/dist/types/core/action.d.ts +12 -5
  79. package/dist/types/core/async.d.ts +3 -1
  80. package/dist/types/core/attribution-costs.d.ts +35 -0
  81. package/dist/types/core/attribution-feedback.d.ts +133 -0
  82. package/dist/types/core/attribution-hooks.d.ts +304 -0
  83. package/dist/types/core/attribution-queries.d.ts +24 -0
  84. package/dist/types/core/attribution.d.ts +892 -0
  85. package/dist/types/core/constants.d.ts +179 -0
  86. package/dist/types/core/core.d.ts +299 -25
  87. package/dist/types/core/dev.d.ts +421 -8
  88. package/dist/types/core/effect.d.ts +8 -1
  89. package/dist/types/core/error-hooks.d.ts +71 -0
  90. package/dist/types/core/error.d.ts +9 -0
  91. package/dist/types/core/graph.d.ts +23 -0
  92. package/dist/types/core/heap.d.ts +5 -3
  93. package/dist/types/core/index.d.ts +6 -3
  94. package/dist/types/core/invariants.d.ts +5 -1
  95. package/dist/types/core/lanes.d.ts +51 -19
  96. package/dist/types/core/owner.d.ts +15 -3
  97. package/dist/types/core/scheduler.d.ts +252 -1
  98. package/dist/types/core/types.d.ts +124 -41
  99. package/dist/types/index.d.ts +18 -5
  100. package/dist/types/map.d.ts +2 -0
  101. package/dist/types/signals.d.ts +145 -13
  102. package/dist/types/store/index.d.ts +7 -6
  103. package/dist/types/store/next/optimistic.d.ts +18 -13
  104. package/dist/types/store/next/projection.d.ts +5 -2
  105. package/dist/types/store/next/reconcile.d.ts +7 -0
  106. package/dist/types/store/next/store.d.ts +83 -11
  107. package/dist/types/store/next/target.d.ts +108 -11
  108. package/dist/types/store/store.d.ts +20 -11
  109. package/dist/types/store/utils.d.ts +188 -0
  110. package/package.json +31 -26
  111. package/dist/node.cjs +0 -8137
  112. package/dist/types/store/optimistic.d.ts +0 -45
  113. package/dist/types/store/projection.d.ts +0 -70
  114. package/dist/types/store/reconcile.d.ts +0 -46
  115. package/dist/types-cjs/affects.d.cts +0 -47
  116. package/dist/types-cjs/boundaries.d.cts +0 -175
  117. package/dist/types-cjs/core/action.d.cts +0 -64
  118. package/dist/types-cjs/core/async.d.cts +0 -21
  119. package/dist/types-cjs/core/constants.d.cts +0 -71
  120. package/dist/types-cjs/core/core.d.cts +0 -156
  121. package/dist/types-cjs/core/dev.d.cts +0 -64
  122. package/dist/types-cjs/core/effect.d.cts +0 -30
  123. package/dist/types-cjs/core/error.d.cts +0 -47
  124. package/dist/types-cjs/core/external.d.cts +0 -15
  125. package/dist/types-cjs/core/graph.d.cts +0 -5
  126. package/dist/types-cjs/core/heap.d.cts +0 -22
  127. package/dist/types-cjs/core/index.d.cts +0 -13
  128. package/dist/types-cjs/core/invariants.d.cts +0 -59
  129. package/dist/types-cjs/core/lanes.d.cts +0 -56
  130. package/dist/types-cjs/core/optimistic.d.cts +0 -6
  131. package/dist/types-cjs/core/owner.d.cts +0 -124
  132. package/dist/types-cjs/core/scheduler.d.cts +0 -172
  133. package/dist/types-cjs/core/types.d.cts +0 -148
  134. package/dist/types-cjs/core/verdict.d.cts +0 -2
  135. package/dist/types-cjs/index.d.cts +0 -10
  136. package/dist/types-cjs/map.d.cts +0 -69
  137. package/dist/types-cjs/package.json +0 -3
  138. package/dist/types-cjs/signals.d.cts +0 -624
  139. package/dist/types-cjs/store/index.d.cts +0 -19
  140. package/dist/types-cjs/store/next/optimistic.d.cts +0 -20
  141. package/dist/types-cjs/store/next/projection.d.cts +0 -24
  142. package/dist/types-cjs/store/next/reconcile.d.cts +0 -3
  143. package/dist/types-cjs/store/next/store.d.cts +0 -71
  144. package/dist/types-cjs/store/next/target.d.cts +0 -99
  145. package/dist/types-cjs/store/optimistic.d.cts +0 -45
  146. package/dist/types-cjs/store/projection.d.cts +0 -70
  147. package/dist/types-cjs/store/reconcile.d.cts +0 -46
  148. package/dist/types-cjs/store/store.d.cts +0 -138
  149. package/dist/types-cjs/store/storePath.d.cts +0 -58
  150. package/dist/types-cjs/store/utils.d.cts +0 -74
package/dist/prod/map.js CHANGED
@@ -1,11 +1,15 @@
1
- import { computed, runWithOwner, signal, setSignal } from "./core/core.js";
1
+ import { computed, runWithOwner, signal, currentOptimisticLane, setSignal } from "./core/core.js";
2
+
3
+ import { activeLanes } from "./core/lanes.js";
2
4
 
3
5
  import { createOwner } from "./core/owner.js";
4
6
 
5
- import "./core/scheduler.js";
7
+ import { GlobalQueue } from "./core/scheduler.js";
6
8
 
7
9
  import { CONFIG_AUTO_DISPOSE } from "./core/constants.js";
8
10
 
11
+ import { attrHooks } from "./core/attribution-hooks.js";
12
+
9
13
  import "./core/invariants.js";
10
14
 
11
15
  import "./core/verdict.js";
@@ -18,203 +22,383 @@ import { $TRACK } from "./store/store.js";
18
22
 
19
23
  import "./store/next/store.js";
20
24
 
21
- function mapArray(t, s, i) {
22
- const e = typeof i?.keyed === "function" ? i.keyed : undefined;
25
+ function mapArray(t, s, e) {
26
+ const i = typeof e?.keyed === "function" ? e.keyed : undefined;
23
27
  const r = s.length > 1;
24
28
  const n = s;
25
- const h = {
26
- wt: createOwner(),
27
- jt: 0,
28
- Wt: t,
29
+ const o = {
30
+ ie: createOwner(),
31
+ wt: 0,
32
+ Ot: t,
33
+ yt: [],
34
+ At: n,
29
35
  Mt: [],
30
- xt: n,
31
- Kt: [],
32
- Ft: [],
33
- Ut: e,
34
- $t: e || i?.keyed === false ? [] : undefined,
35
- qt: r && i?.keyed !== false ? [] : undefined,
36
- zt: i?.keyed === false,
37
- Bt: i?.fallback
36
+ St: [],
37
+ Kn: i,
38
+ jt: i || e?.keyed === false ? [] : undefined,
39
+ kt: r && e?.keyed !== false ? [] : undefined,
40
+ gt: e?.keyed === false,
41
+ bt: e?.fallback
38
42
  };
39
- const o = computed(updateKeyedMap.bind(h));
43
+ const h = computed(updateKeyedMap.bind(o), undefined);
40
44
  // Untracked reads inside the internal owner resolve via _parentComputed; routing
41
45
  // them through node lets store-proxy lookups see pending writes (not stale _value).
42
- h.wt.It = o;
43
- o.T &= ~CONFIG_AUTO_DISPOSE;
44
- return accessor(o);
46
+ o.ie.qn = h;
47
+ h.C &= ~CONFIG_AUTO_DISPOSE;
48
+ return accessor(h);
45
49
  }
46
50
 
47
51
  const pureOptions = {
48
52
  ownedWrite: true
49
53
  };
50
54
 
51
- // Exception safety (#2903): a map callback can throw NotReadyError mid-pass
52
- // (async read), and the computed re-runs the whole pass after settle. Every
53
- // pass therefore STAGES its work — new rows are created into temp arrays and
54
- // removals are deferred — and commits to `this` only after every mapper
55
- // succeeded. An aborted pass disposes just the owners it created and leaves
56
- // `_items`/`_mappings`/`_nodes`/`_rows`/`_indexes`/`_len` exactly as they
57
- // were, so the retry diffs against uncorrupted state. Consequence of the
58
- // strong-abort ordering: removed rows now dispose AFTER the pass's new rows
59
- // are created (you cannot destroy state before knowing the pass will land).
55
+ function trySmallMove(t, s, e, i) {
56
+ const r = t.yt;
57
+ const n = t.wt - 1;
58
+ const o = [];
59
+ const h = [];
60
+ const f = [];
61
+ // flat triples: oldStart, newStart, length
62
+ let c = 256;
63
+ let a = i;
64
+ let u = i;
65
+ let l = false;
66
+ while (a <= n && u <= e - 1) {
67
+ const t = r[a];
68
+ const i = s[u];
69
+ if (t === i) {
70
+ if (!l) {
71
+ f.push(a, u, 0);
72
+ l = true;
73
+ }
74
+ f[f.length - 1]++;
75
+ a++;
76
+ u++;
77
+ continue;
78
+ }
79
+ l = false;
80
+ // Bounded realignment lookahead, shorter distance wins.
81
+ let p = -1;
82
+ let d = Math.min(32 - o.length, n - a, c);
83
+ for (let t = 1; t <= d; t++) {
84
+ if (r[a + t] === i) {
85
+ p = t;
86
+ break;
87
+ }
88
+ }
89
+ c -= p === -1 ? d : p;
90
+ let m = -1;
91
+ d = Math.min(32 - h.length, e - 1 - u, c);
92
+ for (let e = 1; e <= d; e++) {
93
+ if (s[u + e] === t) {
94
+ m = e;
95
+ break;
96
+ }
97
+ }
98
+ c -= m === -1 ? d : m;
99
+ if (p !== -1 && (m === -1 || p <= m)) {
100
+ while (p-- > 0) o.push(a++);
101
+ continue;
102
+ }
103
+ if (m !== -1) {
104
+ while (m-- > 0) h.push(u++);
105
+ continue;
106
+ }
107
+ if (c <= 0 || o.length === 32 || h.length === 32) return false;
108
+ o.push(a++);
109
+ h.push(u++);
110
+ }
111
+ for (;a <= n; a++) {
112
+ if (o.length === 32) return false;
113
+ o.push(a);
114
+ }
115
+ for (;u <= e - 1; u++) {
116
+ if (h.length === 32) return false;
117
+ h.push(u);
118
+ }
119
+ return commitSmallMove(t, s, e, o, h, f);
120
+ }
121
+
122
+ /** PHASE 2 of the small-move path, in its OWN function so that a pass which
123
+ * only SCANS and bails (a full replace: the first structural pass of a page,
124
+ * typically) compiles nothing but the scan — V8 parses and compiles lazily
125
+ * per function, and cold `replace` measured +0.5 ms with both phases in one
126
+ * body. Pairs displaced sources with destinations (an unmatched destination
127
+ * is a replacement/insertion → general path), then commits: slice() the live
128
+ * arrays, copy shifted runs, patch displaced pairs, dispose leftovers. */ function commitSmallMove(t, s, e, i, r, n) {
129
+ const o = t.yt;
130
+ let h;
131
+ let f;
132
+ let c;
133
+ if (r.length !== 0) {
134
+ c = new Array(i.length);
135
+ for (f = 0; f < r.length; f++) {
136
+ let t = -1;
137
+ for (h = 0; h < i.length; h++) {
138
+ if (!c[h] && o[i[h]] === s[r[f]]) {
139
+ t = h;
140
+ break;
141
+ }
142
+ }
143
+ if (t === -1) return false;
144
+ c[t] = true;
145
+ r[f] = r[f] << 6 | t;
146
+ // pack pairing (found < 32)
147
+ }
148
+ }
149
+ // DUPLICATES: the general path pairs equal identities by OCCURRENCE ORDER
150
+ // (the chained index map). Displaced↔displaced pairing above is ascending
151
+ // on both sides, so it agrees; but an aligned run was matched by POSITION,
152
+ // and if a displaced identity also occurs inside a run the two algorithms
153
+ // can hand different occurrences different owners (row-local state moves;
154
+ // a shrink could dispose the wrong one). Decline that case — general path.
155
+ if (i.length !== 0 || r.length !== 0) {
156
+ const t = new Set;
157
+ for (h = 0; h < i.length; h++) t.add(o[i[h]]);
158
+ for (f = 0; f < r.length; f++) t.add(s[r[f] >> 6]);
159
+ for (let s = 0; s < n.length; s += 3) {
160
+ const e = n[s];
161
+ for (let i = 0, r = n[s + 2]; i < r; i++) if (t.has(o[e + i])) return false;
162
+ }
163
+ }
164
+ const a = t.Mt;
165
+ const u = t.St;
166
+ const l = a.slice(0, e);
167
+ const p = u.slice(0, e);
168
+ for (let t = 0; t < n.length; t += 3) {
169
+ const s = n[t];
170
+ const e = n[t + 1];
171
+ if (s !== e) {
172
+ for (let i = 0; i < n[t + 2]; i++) {
173
+ l[e + i] = a[s + i];
174
+ p[e + i] = u[s + i];
175
+ }
176
+ }
177
+ }
178
+ for (f = 0; f < r.length; f++) {
179
+ const t = r[f] >> 6;
180
+ const s = i[r[f] & 63];
181
+ l[t] = a[s];
182
+ p[t] = u[s];
183
+ }
184
+ t.Mt = l;
185
+ t.St = p;
186
+ t.wt = e;
187
+ t.yt = s.slice(0);
188
+ // Dispose unmatched sources LAST (general-path ordering).
189
+ for (h = 0; h < i.length; h++) {
190
+ if (c === undefined || !c[h]) u[i[h]].dispose();
191
+ }
192
+ return true;
193
+ }
194
+
60
195
  function updateKeyedMap() {
61
- const t = this.Wt() || [], s = t.length;
196
+ const t = this.Ot() || [], s = t.length;
62
197
  t[$TRACK];
63
198
  // top level tracking
64
- runWithOwner(this.wt, () => {
65
- let i, e, r, n,
199
+ runWithOwner(this.ie, () => {
200
+ let e, i, r, n,
66
201
  // Mappers write freshly-created row/index signals into the STAGE
67
202
  // arrays (`rows`/`indexes`), never into `this._rows`/`this._indexes`.
68
- h = this.$t ? this.zt ? () => {
69
- r[e] = signal(t[e], pureOptions);
70
- return this.xt(accessor(r[e]), e);
203
+ o = this.jt ? this.gt ? () => {
204
+ r[i] = signal(t[i], pureOptions);
205
+ return this.At(accessor(r[i]), i);
71
206
  } : () => {
72
- r[e] = signal(t[e], pureOptions);
73
- n && (n[e] = signal(e, pureOptions));
74
- return this.xt(accessor(r[e]), n ? accessor(n[e]) : undefined);
75
- } : this.qt ? () => {
76
- const s = t[e];
77
- n[e] = signal(e, pureOptions);
78
- return this.xt(s, accessor(n[e]));
207
+ r[i] = signal(t[i], pureOptions);
208
+ n && (n[i] = signal(i, pureOptions));
209
+ return this.At(accessor(r[i]), n ? accessor(n[i]) : undefined);
210
+ } : this.kt ? () => {
211
+ const s = t[i];
212
+ n[i] = signal(i, pureOptions);
213
+ return this.At(s, accessor(n[i]));
79
214
  } : () => {
80
- const s = t[e];
81
- return this.xt(s);
215
+ const s = t[i];
216
+ return this.At(s);
82
217
  };
83
218
  // fast path for empty arrays
84
219
  if (s === 0) {
85
- if (this.jt !== 0) {
86
- this.wt.dispose(false);
87
- this.Ft = [];
220
+ if (this.wt !== 0) {
221
+ this.ie.dispose(false);
222
+ this.St = [];
223
+ this.yt = [];
88
224
  this.Mt = [];
89
- this.Kt = [];
90
- this.jt = 0;
91
- this.$t && (this.$t = []);
92
- this.qt && (this.qt = []);
225
+ this.wt = 0;
226
+ this.jt && (this.jt = []);
227
+ this.kt && (this.kt = []);
93
228
  }
94
- if (this.Bt && !this.Kt[0]) {
229
+ if (this.bt && !this.Mt[0]) {
95
230
  // an aborted fallback attempt leaves an owner without a mapping;
96
231
  // dispose it before re-creating
97
- this.Ft[0]?.dispose();
98
- this.Kt[0] = runWithOwner(this.Ft[0] = createOwner(), this.Bt);
232
+ this.St[0]?.dispose();
233
+ this.Mt[0] = runWithOwner(this.St[0] = createOwner(), this.bt);
99
234
  }
100
235
  }
101
236
  // fast path for new create
102
- else if (this.jt === 0) {
103
- const o = new Array(s);
104
- const c = new Array(s);
105
- r = this.$t && new Array(s);
106
- n = this.qt && new Array(s);
237
+ else if (this.wt === 0) {
238
+ const h = new Array(s);
239
+ const f = new Array(s);
240
+ r = this.jt && new Array(s);
241
+ n = this.kt && new Array(s);
107
242
  try {
108
- for (e = 0; e < s; e++) o[e] = runWithOwner(c[e] = createOwner(), h);
243
+ for (i = 0; i < s; i++) h[i] = runWithOwner(f[i] = createOwner(), o);
109
244
  } catch (t) {
110
- for (i = 0; i <= e; i++) c[i]?.dispose();
245
+ for (e = 0; e <= i; e++) f[e]?.dispose();
111
246
  throw t;
112
247
  }
113
248
  // commit
114
- if (this.Ft[0]) this.Ft[0].dispose();
249
+ if (this.St[0]) this.St[0].dispose();
115
250
  // previous fallback
116
- this.Kt = o;
117
- this.Ft = c;
118
- r && (this.$t = r);
119
- n && (this.qt = n);
120
- this.Mt = t.slice(0);
121
- this.jt = s;
251
+ this.Mt = h;
252
+ this.St = f;
253
+ r && (this.jt = r);
254
+ n && (this.kt = n);
255
+ this.yt = t.slice(0);
256
+ this.wt = s;
122
257
  } else {
123
- let o, c, a, f, u, p, w, l, d;
258
+ let h, f, c, a, u, l, p, d, m,
259
+ // Dev (attribution engine installed): the items behind the exited and
260
+ // entered rows, for the list-identity census.
261
+ w, O;
262
+ // The pass's write to a per-slot signal (a row accessor in index mode,
263
+ // an index accessor in keyed mode). The list's frame lives in these
264
+ // writes as much as in the computed's result, so under a LANE pass they
265
+ // are the lane's frame too (F1): a plain `setSignal` staged them into
266
+ // the action's transaction and the row readers were served the
267
+ // committed value until the action landed — `<For>` without `keyed`
268
+ // showed the pre-action list for the whole action while the keyed modes
269
+ // showed the optimistic one. The engine publishes the write as a
270
+ // derived override on the slot (lanes stage, A17) and lands or
271
+ // supersedes it when a plain pass later writes a slot still carrying
272
+ // one (A18) — `landOnOverride`'s slot arm. Decided once per pass, not
273
+ // per slot: a lane pass marks the map (`_laneSlots`: its slots may
274
+ // carry overrides), a marked map routes every slot write through the
275
+ // engine while any lane is live — a slot's override resolves with its
276
+ // lane's transaction, or with the batch for an orphan lane
277
+ // (resolveOptimisticNodes, then cleanupCompletedLanes, both before the
278
+ // completion wakes any recompute), so a pass that finds no lane live
279
+ // knows the slots are clean and drops the mark — and an unmarked map
280
+ // takes `setSignal` directly. The engine is installed whenever a lane
281
+ // is active.
282
+ const _ = (this.Wt = currentOptimisticLane !== null || this.Wt && activeLanes.size !== 0) ? GlobalQueue.st : setSignal;
124
283
  // skip common prefix
125
- for (o = 0, c = Math.min(this.jt, s); o < c && (this.Mt[o] === t[o] || this.$t && compare(this.Ut, this.Mt[o], t[o])); o++) {
126
- if (this.$t) setSignal(this.$t[o], t[o]);
284
+ for (h = 0, f = Math.min(this.wt, s); h < f && (this.yt[h] === t[h] || this.jt && compare(this.Kn, this.yt[h], t[h])); h++) {
285
+ if (this.jt) _(this.jt[h], t[h]);
127
286
  }
128
287
  // skip common suffix — counted only; retained entries land in one pass
129
288
  // at commit instead of being staged and copied twice
130
- for (c = this.jt - 1, a = s - 1; c >= o && a >= o && (this.Mt[c] === t[a] || this.$t && compare(this.Ut, this.Mt[c], t[a])); c--,
131
- a--) ;
289
+ for (f = this.wt - 1, c = s - 1; f >= h && c >= h && (this.yt[f] === t[c] || this.jt && compare(this.Kn, this.yt[f], t[c])); f--,
290
+ c--) ;
132
291
  // no structural change (every position matched in place at equal
133
292
  // length — the common post-reconcile shape): keep the same mapped
134
293
  // array identity so downstream consumers don't re-run at all
135
- if (o === s && this.jt === s) {
136
- this.Mt = t.slice(0);
294
+ if (h === s && this.wt === s) {
295
+ this.yt = t.slice(0);
137
296
  return;
138
297
  }
139
- const O = s - this.jt;
140
- const m = new Array(s);
141
- const _ = new Array(s);
142
- r = this.$t ? new Array(s) : undefined;
143
- n = this.qt ? new Array(s) : undefined;
298
+ // SMALL-MOVE FAST PATH: extracted to its own function — inlining it
299
+ // here bloats updateKeyedMap past the JIT's optimization budget and
300
+ // deoptimizes the GENERAL path (measured 2x on reverse). Gated to
301
+ // LARGE trimmed windows: when the trims already shrank the window
302
+ // (plain removals, tail edits), the general path is window-
303
+ // proportional and cheap — the fast path would only re-walk what the
304
+ // trims proved.
305
+ if (s <= this.wt && f - h > 64 && this.jt === undefined && this.kt === undefined) {
306
+ // PROBE before the scan: a small move keeps a mid-window item within
307
+ // ±32 of its old position; a REPLACE (all fresh items — the shape
308
+ // every page's first structural pass usually is) has it nowhere.
309
+ // ~65 compares, no allocation, and the scan function is never
310
+ // compiled for a replace (its cold first-call compile was the cost).
311
+ const e = h + (c - h >> 1);
312
+ const i = t[e];
313
+ const r = Math.min(f, e + 32);
314
+ let n = Math.max(h, e - 32);
315
+ while (n <= r && this.yt[n] !== i) n++;
316
+ if (n <= r && trySmallMove(this, t, s, h)) return;
317
+ }
318
+ const y = s - this.wt;
319
+ const A = new Array(s);
320
+ const M = new Array(s);
321
+ r = this.jt ? new Array(s) : undefined;
322
+ n = this.kt ? new Array(s) : undefined;
144
323
  // 0) prepare a map of all indices in the changed window of newItems,
145
324
  // scanning backwards so we encounter them in natural order
146
- p = new Map;
147
- w = new Array(a + 1);
148
- for (e = a; e >= o; e--) {
149
- f = t[e];
150
- u = this.Ut ? this.Ut(f) : f;
151
- i = p.get(u);
152
- w[e] = i === undefined ? -1 : i;
153
- p.set(u, e);
325
+ l = new Map;
326
+ p = new Array(c + 1);
327
+ for (i = c; i >= h; i--) {
328
+ a = t[i];
329
+ u = this.Kn ? this.Kn(a) : a;
330
+ e = l.get(u);
331
+ p[i] = e === undefined ? -1 : e;
332
+ l.set(u, i);
154
333
  }
155
334
  // 1) step through the old changed window and see if items can be found
156
335
  // in the new set; if so, stage them at their new positions; if not,
157
336
  // queue them for disposal at commit
158
- for (i = o; i <= c; i++) {
159
- f = this.Mt[i];
160
- u = this.Ut ? this.Ut(f) : f;
161
- e = p.get(u);
162
- if (e !== undefined && e !== -1) {
163
- m[e] = this.Kt[i];
164
- _[e] = this.Ft[i];
165
- r && (r[e] = this.$t[i]);
166
- n && (n[e] = this.qt[i]);
167
- e = w[e];
168
- p.set(u, e);
169
- } else (l ??= []).push(this.Ft[i]);
337
+ for (e = h; e <= f; e++) {
338
+ a = this.yt[e];
339
+ u = this.Kn ? this.Kn(a) : a;
340
+ i = l.get(u);
341
+ if (i !== undefined && i !== -1) {
342
+ A[i] = this.Mt[e];
343
+ M[i] = this.St[e];
344
+ r && (r[i] = this.jt[e]);
345
+ n && (n[i] = this.kt[e]);
346
+ i = p[i];
347
+ l.set(u, i);
348
+ } else {
349
+ (d ??= []).push(this.St[e]);
350
+ if (false && attrHooks !== null) ;
351
+ }
170
352
  }
171
353
  // 2) create new rows into the temp arrays; an abort disposes only these
172
354
  try {
173
- for (e = o; e <= a; e++) {
174
- if (_[e] !== undefined) continue;
175
- (d ??= []).push(_[e] = createOwner());
176
- m[e] = runWithOwner(_[e], h);
355
+ for (i = h; i <= c; i++) {
356
+ if (M[i] !== undefined) continue;
357
+ (m ??= []).push(M[i] = createOwner());
358
+ if (false && attrHooks !== null) ;
359
+ A[i] = runWithOwner(M[i], o);
177
360
  }
178
361
  } catch (t) {
179
- if (d) for (i = 0; i < d.length; i++) d[i].dispose();
362
+ if (m) for (e = 0; e < m.length; e++) m[e].dispose();
180
363
  throw t;
181
364
  }
182
365
  // 3) commit: land the retained prefix and suffix plus the staged window
183
366
  // into the fresh arrays, swap them in (new identity for downstream
184
367
  // change propagation), then dispose exited rows
185
- for (i = 0; i < o; i++) {
186
- m[i] = this.Kt[i];
187
- _[i] = this.Ft[i];
188
- r && (r[i] = this.$t[i]);
189
- n && (n[i] = this.qt[i]);
368
+ for (e = 0; e < h; e++) {
369
+ A[e] = this.Mt[e];
370
+ M[e] = this.St[e];
371
+ r && (r[e] = this.jt[e]);
372
+ n && (n[e] = this.kt[e]);
190
373
  }
191
- for (e = o; e <= a; e++) {
192
- if (r) setSignal(r[e], t[e]);
193
- if (n) setSignal(n[e], e);
374
+ for (i = h; i <= c; i++) {
375
+ if (r) _(r[i], t[i]);
376
+ if (n) _(n[i], i);
194
377
  }
195
- for (e = a + 1; e < s; e++) {
196
- m[e] = this.Kt[e - O];
197
- _[e] = this.Ft[e - O];
378
+ for (i = c + 1; i < s; i++) {
379
+ A[i] = this.Mt[i - y];
380
+ M[i] = this.St[i - y];
198
381
  if (r) {
199
- r[e] = this.$t[e - O];
200
- setSignal(r[e], t[e]);
382
+ r[i] = this.jt[i - y];
383
+ _(r[i], t[i]);
201
384
  }
202
385
  if (n) {
203
- n[e] = this.qt[e - O];
204
- if (O !== 0) setSignal(n[e], e);
386
+ n[i] = this.kt[i - y];
387
+ if (y !== 0) _(n[i], i);
205
388
  }
206
389
  }
207
- this.Kt = m;
208
- this.Ft = _;
209
- r && (this.$t = r);
210
- n && (this.qt = n);
211
- this.jt = s;
390
+ this.Mt = A;
391
+ this.St = M;
392
+ r && (this.jt = r);
393
+ n && (this.kt = n);
394
+ this.wt = s;
212
395
  // save a copy of the mapped items for the next update
213
- this.Mt = t.slice(0);
214
- if (l) for (i = 0; i < l.length; i++) l[i].dispose();
396
+ this.yt = t.slice(0);
397
+ if (d) for (e = 0; e < d.length; e++) d[e].dispose();
398
+ if (false && attrHooks !== null && w !== undefined && O !== undefined) ;
215
399
  }
216
400
  });
217
- return this.Kt;
401
+ return this.Mt;
218
402
  }
219
403
 
220
404
  /**
@@ -231,25 +415,25 @@ function updateKeyedMap() {
231
415
  * ```
232
416
  *
233
417
  * @description https://docs.solidjs.com/reference/reactive-utilities/repeat
234
- */ function repeat(t, s, i) {
235
- const e = s;
418
+ */ function repeat(t, s, e) {
419
+ const i = s;
236
420
  const r = {
237
- wt: createOwner(),
238
- jt: 0,
239
- Ht: 0,
240
- Jt: t,
241
- xt: e,
242
- Ft: [],
243
- Kt: [],
244
- Vt: i?.from,
245
- Bt: i?.fallback
421
+ ie: createOwner(),
422
+ wt: 0,
423
+ vt: 0,
424
+ It: t,
425
+ At: i,
426
+ St: [],
427
+ Mt: [],
428
+ Ct: e?.from,
429
+ bt: e?.fallback
246
430
  };
247
431
  const n = computed(updateRepeat.bind(r));
248
432
  // Same as mapArray: untracked reads inside the internal owner resolve via
249
433
  // _parentComputed, so async reads in row callbacks register with the node
250
434
  // (pending tracking + post-settle retry) instead of vanishing.
251
- r.wt.It = n;
252
- n.T &= ~CONFIG_AUTO_DISPOSE;
435
+ r.ie.qn = n;
436
+ n.C &= ~CONFIG_AUTO_DISPOSE;
253
437
  return accessor(n);
254
438
  }
255
439
 
@@ -261,59 +445,59 @@ function updateKeyedMap() {
261
445
  // for the post-settle retry. The overlap math also subsumes the previous
262
446
  // disjoint-window/front-clear/end-clear/shift special cases.
263
447
  function updateRepeat() {
264
- const t = this.Jt();
265
- const s = this.Vt?.() || 0;
266
- runWithOwner(this.wt, () => {
448
+ const t = this.It();
449
+ const s = this.Ct?.() || 0;
450
+ runWithOwner(this.ie, () => {
267
451
  if (t === 0) {
268
- if (this.jt !== 0) {
269
- this.wt.dispose(false);
270
- this.Ft = [];
271
- this.Kt = [];
272
- this.jt = 0;
452
+ if (this.wt !== 0) {
453
+ this.ie.dispose(false);
454
+ this.St = [];
455
+ this.Mt = [];
456
+ this.wt = 0;
273
457
  // Reset offset to match the cleared data (#2767, repro 2).
274
- this.Ht = 0;
458
+ this.vt = 0;
275
459
  }
276
- if (this.Bt && !this.Kt[0]) {
460
+ if (this.bt && !this.Mt[0]) {
277
461
  // an aborted fallback attempt leaves an owner without a mapping;
278
462
  // dispose it before re-creating
279
- this.Ft[0]?.dispose();
280
- this.Kt[0] = runWithOwner(this.Ft[0] = createOwner(), this.Bt);
463
+ this.St[0]?.dispose();
464
+ this.Mt[0] = runWithOwner(this.St[0] = createOwner(), this.bt);
281
465
  }
282
466
  return;
283
467
  }
284
- const i = s + t;
285
- const e = this.Ht + this.jt;
468
+ const e = s + t;
469
+ const i = this.vt + this.wt;
286
470
  // Retained overlap [keepStart, keepEnd) in global indexes; empty when the
287
471
  // windows are disjoint or when coming from empty/fallback.
288
- const r = Math.max(s, this.Ht);
289
- const n = Math.min(i, e);
290
- const h = new Array(t);
472
+ const r = Math.max(s, this.vt);
473
+ const n = Math.min(e, i);
291
474
  const o = new Array(t);
475
+ const h = new Array(t);
292
476
  for (let t = r; t < n; t++) {
293
- o[t - s] = this.Ft[t - this.Ht];
294
- h[t - s] = this.Kt[t - this.Ht];
477
+ h[t - s] = this.St[t - this.vt];
478
+ o[t - s] = this.Mt[t - this.vt];
295
479
  }
296
480
  try {
297
- for (let t = s; t < i; t++) {
481
+ for (let t = s; t < e; t++) {
298
482
  if (t >= r && t < n) continue;
299
- h[t - s] = runWithOwner(o[t - s] = createOwner(), () => this.xt(t));
483
+ o[t - s] = runWithOwner(h[t - s] = createOwner(), () => this.At(t));
300
484
  }
301
485
  } catch (t) {
302
- for (let t = s; t < i; t++) if ((t < r || t >= n) && o[t - s]) o[t - s].dispose();
486
+ for (let t = s; t < e; t++) if ((t < r || t >= n) && h[t - s]) h[t - s].dispose();
303
487
  throw t;
304
488
  }
305
489
  // commit: dispose the previous fallback or the rows leaving the window
306
- if (this.jt === 0) this.Ft[0]?.dispose(); else for (let t = this.Ht; t < e; t++) if (t < s || t >= i) this.Ft[t - this.Ht].dispose();
307
- this.Kt = h;
308
- this.Ft = o;
309
- this.Ht = s;
310
- this.jt = t;
490
+ if (this.wt === 0) this.St[0]?.dispose(); else for (let t = this.vt; t < i; t++) if (t < s || t >= e) this.St[t - this.vt].dispose();
491
+ this.Mt = o;
492
+ this.St = h;
493
+ this.vt = s;
494
+ this.wt = t;
311
495
  });
312
- return this.Kt;
496
+ return this.Mt;
313
497
  }
314
498
 
315
- function compare(t, s, i) {
316
- return t ? t(s) === t(i) : true;
499
+ function compare(t, s, e) {
500
+ return t ? t(s) === t(e) : true;
317
501
  }
318
502
 
319
503
  export { mapArray, repeat };