@solidjs/signals 2.0.0-beta.18 → 2.0.0-beta.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 (68) hide show
  1. package/dist/dev.js +3276 -928
  2. package/dist/node.cjs +6646 -4189
  3. package/dist/prod/affects.js +218 -0
  4. package/dist/prod/boundaries.js +568 -0
  5. package/dist/prod/core/action.js +96 -0
  6. package/dist/prod/core/async.js +380 -0
  7. package/dist/prod/core/constants.js +92 -0
  8. package/dist/prod/core/context.js +67 -0
  9. package/dist/prod/core/core.js +772 -0
  10. package/dist/prod/core/dev.js +3 -0
  11. package/dist/prod/core/effect.js +145 -0
  12. package/dist/prod/core/error.js +59 -0
  13. package/dist/prod/core/external.js +98 -0
  14. package/dist/prod/core/graph.js +91 -0
  15. package/dist/prod/core/heap.js +132 -0
  16. package/dist/prod/core/invariants.js +42 -0
  17. package/dist/prod/core/lanes.js +140 -0
  18. package/dist/prod/core/optimistic.js +273 -0
  19. package/dist/prod/core/owner.js +293 -0
  20. package/dist/prod/core/scheduler.js +689 -0
  21. package/dist/prod/core/verdict.js +292 -0
  22. package/dist/prod/index.js +45 -0
  23. package/dist/prod/map.js +293 -0
  24. package/dist/prod/signals.js +389 -0
  25. package/dist/prod/store/optimistic.js +184 -0
  26. package/dist/prod/store/projection.js +184 -0
  27. package/dist/prod/store/reconcile.js +426 -0
  28. package/dist/prod/store/store.js +870 -0
  29. package/dist/prod/store/storePath.js +103 -0
  30. package/dist/prod/store/utils.js +316 -0
  31. package/dist/types/affects.d.ts +1 -1
  32. package/dist/types/boundaries.d.ts +6 -6
  33. package/dist/types/core/action.d.ts +19 -6
  34. package/dist/types/core/async.d.ts +4 -38
  35. package/dist/types/core/constants.d.ts +12 -0
  36. package/dist/types/core/core.d.ts +12 -78
  37. package/dist/types/core/dev.d.ts +7 -0
  38. package/dist/types/core/external.d.ts +0 -30
  39. package/dist/types/core/heap.d.ts +8 -0
  40. package/dist/types/core/index.d.ts +3 -2
  41. package/dist/types/core/lanes.d.ts +2 -0
  42. package/dist/types/core/optimistic.d.ts +6 -0
  43. package/dist/types/core/owner.d.ts +8 -0
  44. package/dist/types/core/scheduler.d.ts +40 -39
  45. package/dist/types/core/types.d.ts +9 -1
  46. package/dist/types/core/verdict.d.ts +2 -0
  47. package/dist/types/store/projection.d.ts +0 -1
  48. package/dist/types/store/store.d.ts +8 -2
  49. package/dist/types-cjs/affects.d.cts +1 -1
  50. package/dist/types-cjs/boundaries.d.cts +6 -6
  51. package/dist/types-cjs/core/action.d.cts +19 -6
  52. package/dist/types-cjs/core/async.d.cts +4 -38
  53. package/dist/types-cjs/core/constants.d.cts +12 -0
  54. package/dist/types-cjs/core/core.d.cts +12 -78
  55. package/dist/types-cjs/core/dev.d.cts +7 -0
  56. package/dist/types-cjs/core/external.d.cts +0 -30
  57. package/dist/types-cjs/core/heap.d.cts +8 -0
  58. package/dist/types-cjs/core/index.d.cts +3 -2
  59. package/dist/types-cjs/core/lanes.d.cts +2 -0
  60. package/dist/types-cjs/core/optimistic.d.cts +6 -0
  61. package/dist/types-cjs/core/owner.d.cts +8 -0
  62. package/dist/types-cjs/core/scheduler.d.cts +40 -39
  63. package/dist/types-cjs/core/types.d.cts +9 -1
  64. package/dist/types-cjs/core/verdict.d.cts +2 -0
  65. package/dist/types-cjs/store/projection.d.cts +0 -1
  66. package/dist/types-cjs/store/store.d.cts +8 -2
  67. package/package.json +8 -6
  68. package/dist/prod.js +0 -4637
@@ -0,0 +1,292 @@
1
+ import { NOT_PENDING, REACTIVE_DISPOSED, REACTIVE_DIRTY, REACTIVE_CHECK, unwrapOverride, STATUS_UNINITIALIZED, STATUS_PENDING, REACTIVE_MANUAL_WRITE } from "./constants.js";
2
+
3
+ import { setSignal, read, context, stale, currentOptimisticLane, prepareComputed, tracking, setLatestReadActive, setContextInternal, optimisticComputed, setPendingCheckActive, latestReadActive, optimisticSignal, pendingCheckActive } from "./core.js";
4
+
5
+ import { NotReadyError } from "./error.js";
6
+
7
+ import { link } from "./graph.js";
8
+
9
+ import { insertIntoHeap, queueFor } from "./heap.js";
10
+
11
+ import "./invariants.js";
12
+
13
+ import { findLane, hasActiveOverride } from "./lanes.js";
14
+
15
+ import { installOptimisticEngine } from "./optimistic.js";
16
+
17
+ import { GlobalQueue, clock, insertSubs, schedule } from "./scheduler.js";
18
+
19
+ /**
20
+ * The isPending()/latest() verdict layer, moved out of core.ts. Importing this
21
+ * module installs the companion-maintenance hooks on GlobalQueue; apps that
22
+ * never import isPending/latest never pay for any of it.
23
+ */
24
+ // Companions (pending signals / latest shadows) are optimistic nodes: their
25
+ // writes go through the optimistic write path and their reversion rides the
26
+ // same lanes, so the verdict layer brings the engine with it.
27
+ installOptimisticEngine();
28
+
29
+ let pendingProbe = null;
30
+
31
+ /**
32
+ * Get or create the pending signal for a node (lazy).
33
+ * Used by isPending() to track pending state reactively.
34
+ */ function getPendingSignal(e) {
35
+ if (!e.ye) {
36
+ // Start false, write true if pending - ensures reversion returns to false
37
+ e.ye = optimisticSignal(false, {
38
+ ownedWrite: true
39
+ });
40
+ e.ye.en = e;
41
+ if (computePendingState(e)) setSignal(e.ye, true);
42
+ }
43
+ return e.ye;
44
+ }
45
+
46
+ function collectPendingSources(e) {
47
+ if (!pendingProbe) return;
48
+ pendingProbe.sources.add(e);
49
+ const t = e.rt || e;
50
+ if (t !== e) pendingProbe.sources.add(t);
51
+ }
52
+
53
+ /**
54
+ * Adds a node to the active isPending() probe without reading it. The store's
55
+ * untracked-probe fallback (`witnessAffectsMark`) reaches this through
56
+ * `GlobalQueue._witnessAffects` — its callers guard on `pendingCheckActive`,
57
+ * which only flips inside `isPending()`, so the hook is always installed by
58
+ * the time it can fire.
59
+ */ function witnessAffects(e) {
60
+ pendingProbe?.sources.add(e);
61
+ }
62
+
63
+ function quietPending(e) {
64
+ if (e.m) {
65
+ for (const t of e.m) if (!t.A) return false;
66
+ return true;
67
+ }
68
+ return e.A;
69
+ }
70
+
71
+ function newQuestionInFlight(e) {
72
+ return !!(e.i & STATUS_PENDING) && !(e.i & STATUS_UNINITIALIZED) && !quietPending(e);
73
+ }
74
+
75
+ function computePendingState(e) {
76
+ const t = e;
77
+ if (t.u & REACTIVE_DISPOSED) return false;
78
+ if (e.M) return true;
79
+ const n = e.rt;
80
+ if (e.en) {
81
+ const t = e.en;
82
+ if (t.M) return true;
83
+ const n = t.rt || t;
84
+ return newQuestionInFlight(n);
85
+ }
86
+ if (n && e.ge !== NOT_PENDING && !hasActiveOverride(e)) {
87
+ return !!(n.u & REACTIVE_MANUAL_WRITE) || !n.Ae && !(n.i & STATUS_PENDING) || !!(n.i & STATUS_PENDING) && quietPending(n);
88
+ }
89
+ if (e.ge !== NOT_PENDING && !(t.i & STATUS_UNINITIALIZED)) {
90
+ if (hasActiveOverride(e)) return !e.Ge || !e.Ge(e.ge, unwrapOverride(e.be));
91
+ return true;
92
+ }
93
+ return newQuestionInFlight(t);
94
+ }
95
+
96
+ function syncCompanions(e, t) {
97
+ if (e.ye) updatePendingSignal(e);
98
+ if (e.pe) setSignal(e.pe, t);
99
+ }
100
+
101
+ function updatePendingSignal(e) {
102
+ if (e.ye) {
103
+ setSignal(e.ye, computePendingState(e));
104
+ }
105
+ if (e.pe) updatePendingSignal(e.pe);
106
+ }
107
+
108
+ function updateChildCompanions(e) {
109
+ for (let t = e.G; t !== null; t = t.Ne) {
110
+ if (t.ye || t.pe) updatePendingSignal(t);
111
+ }
112
+ }
113
+
114
+ function repollDownstreamVerdicts(e) {
115
+ const t = new Set;
116
+ const visit = e => {
117
+ if (t.has(e)) return;
118
+ t.add(e);
119
+ if (e.ye || e.pe) updatePendingSignal(e);
120
+ for (let t = e.p; t !== null; t = t.de) visit(t.Ee);
121
+ for (let t = e.G ?? null; t !== null; t = t.Ne) {
122
+ visit(t);
123
+ }
124
+ };
125
+ visit(e);
126
+ }
127
+
128
+ function snapCompanionsToState(e) {
129
+ const t = e.ye;
130
+ if (t && (t.be === undefined || t.be === NOT_PENDING)) {
131
+ const n = computePendingState(e);
132
+ if (t.Ue !== n || t.ge !== NOT_PENDING) {
133
+ t.Ue = n;
134
+ t.ge = NOT_PENDING;
135
+ t.Ie = clock;
136
+ insertSubs(t);
137
+ schedule();
138
+ }
139
+ }
140
+ const n = e.pe;
141
+ if (n && !(n.u & REACTIVE_DISPOSED)) {
142
+ if ((n.be === undefined || n.be === NOT_PENDING) && n.ge === NOT_PENDING && !Object.is(n.Ue, e.Ue) && !(n.u & (REACTIVE_DIRTY | REACTIVE_CHECK))) {
143
+ n.u |= REACTIVE_DIRTY;
144
+ insertIntoHeap(n, queueFor(n));
145
+ insertSubs(n);
146
+ schedule();
147
+ }
148
+ snapCompanionsToState(n);
149
+ }
150
+ }
151
+
152
+ function getLatestValueComputed(e) {
153
+ if (!e.pe) {
154
+ const t = latestReadActive;
155
+ setLatestReadActive(false);
156
+ const n = pendingCheckActive;
157
+ setPendingCheckActive(false);
158
+ const i = context;
159
+ setContextInternal(null);
160
+ // Detach from owner so it isn't disposed with effects
161
+ e.pe = optimisticComputed(() => read(e));
162
+ e.pe.en = e;
163
+ // Parent-child lane relationship
164
+ setContextInternal(i);
165
+ setPendingCheckActive(n);
166
+ setLatestReadActive(t);
167
+ }
168
+ return e.pe;
169
+ }
170
+
171
+ /** The latest()-mode read path, installed as GlobalQueue._latestRead. */ function latestRead(e) {
172
+ const t = getLatestValueComputed(e);
173
+ const n = latestReadActive;
174
+ setLatestReadActive(false);
175
+ const i = e.be !== undefined && e.be !== NOT_PENDING ? unwrapOverride(e.be) : e.Ue;
176
+ let r;
177
+ try {
178
+ r = read(t);
179
+ } catch (t) {
180
+ if (t instanceof NotReadyError && (!context || !(e.i & STATUS_UNINITIALIZED))) return i;
181
+ throw t;
182
+ } finally {
183
+ setLatestReadActive(n);
184
+ }
185
+ if (t.i & STATUS_PENDING) return i;
186
+ if (stale && currentOptimisticLane && t.Je) {
187
+ const e = findLane(t.Je);
188
+ const n = findLane(currentOptimisticLane);
189
+ if (e !== n && e.Pe.size > 0) {
190
+ return i;
191
+ }
192
+ }
193
+ return r;
194
+ }
195
+
196
+ /** The isPending()-probe read path, installed as GlobalQueue._pendingCheck. */ function pendingCheckRead(e, t, n, i) {
197
+ setPendingCheckActive(false);
198
+ if (typeof e.xe === "function") prepareComputed(e, true);
199
+ const r = n.i;
200
+ if (t && r & STATUS_PENDING && r & STATUS_UNINITIALIZED) {
201
+ if (tracking && e !== t) link(e, t);
202
+ setPendingCheckActive(true);
203
+ throw n.k;
204
+ }
205
+ collectPendingSources(e);
206
+ if (i) collectPendingSources(i);
207
+ setPendingCheckActive(true);
208
+ }
209
+
210
+ function recordFreshRead(e, t) {
211
+ if (pendingProbe !== null && e.ge !== NOT_PENDING && t === e.ge) pendingProbe.freshReads.add(e);
212
+ }
213
+
214
+ function applyReask(e, t) {
215
+ const n = !!(e.i & STATUS_PENDING);
216
+ const i = t && !(n && !e.A);
217
+ const r = n && e.A !== i;
218
+ e.A = i;
219
+ return r;
220
+ }
221
+
222
+ function latest(e) {
223
+ const t = latestReadActive;
224
+ setLatestReadActive(true);
225
+ try {
226
+ return e();
227
+ } finally {
228
+ setLatestReadActive(t);
229
+ }
230
+ }
231
+
232
+ function isPending(e) {
233
+ const t = pendingCheckActive;
234
+ const n = pendingProbe;
235
+ setPendingCheckActive(true);
236
+ const i = pendingProbe = {
237
+ found: false,
238
+ sources: new Set,
239
+ freshReads: new Set
240
+ };
241
+ const collectPending = () => {
242
+ setPendingCheckActive(false);
243
+ try {
244
+ i.sources.forEach(e => {
245
+ if (read(getPendingSignal(e)) && !i.freshReads.has(e)) i.found = true;
246
+ });
247
+ } finally {
248
+ setPendingCheckActive(true);
249
+ }
250
+ };
251
+ try {
252
+ e();
253
+ collectPending();
254
+ return i.found;
255
+ } catch (e) {
256
+ collectPending();
257
+ if (e instanceof NotReadyError) {
258
+ const t = !!(e.source?.i & STATUS_UNINITIALIZED);
259
+ if (i.found && !t) return true;
260
+ if (context && t) throw e;
261
+ }
262
+ return i.found;
263
+ } finally {
264
+ setPendingCheckActive(t);
265
+ pendingProbe = n;
266
+ }
267
+ }
268
+
269
+ // Hook installation (same late-binding pattern as GlobalQueue._update /
270
+ // _propagateAffects): core call sites fire these behind the same guards the
271
+ // direct calls used, so behavior is identical once this module loads.
272
+ GlobalQueue._e = syncCompanions;
273
+
274
+ GlobalQueue.P = updatePendingSignal;
275
+
276
+ GlobalQueue.me = updateChildCompanions;
277
+
278
+ GlobalQueue.R = snapCompanionsToState;
279
+
280
+ GlobalQueue.Gt = latestRead;
281
+
282
+ GlobalQueue.Pt = pendingCheckRead;
283
+
284
+ GlobalQueue.kt = recordFreshRead;
285
+
286
+ GlobalQueue.tt = applyReask;
287
+
288
+ GlobalQueue.nt = repollDownstreamVerdicts;
289
+
290
+ GlobalQueue.wt = witnessAffects;
291
+
292
+ export { isPending, latest };
@@ -0,0 +1,45 @@
1
+ export { ContextNotFoundError, NoOwnerError, NotReadyError } from "./core/error.js";
2
+
3
+ export { clearSnapshots, isEqual, markSnapshotScope, refresh, releaseSnapshotScope, runWithOwner, setSnapshotCapture, untrack } from "./core/core.js";
4
+
5
+ export { enableExternalSource } from "./core/external.js";
6
+
7
+ export { createOwner, createRoot, getNextChildId, getObserver, getOwner, isDisposed, peekNextChildId } from "./core/owner.js";
8
+
9
+ export { createContext, getContext, setContext } from "./core/context.js";
10
+
11
+ export { $REFRESH, SUPPORTS_PROXY } from "./core/constants.js";
12
+
13
+ import "./core/invariants.js";
14
+
15
+ export { enforceLoadingBoundary, flush, resetErrorHalt } from "./core/scheduler.js";
16
+
17
+ export { isPending, latest } from "./core/verdict.js";
18
+
19
+ import "./core/effect.js";
20
+
21
+ export { action } from "./core/action.js";
22
+
23
+ export { createEffect, createMemo, createOptimistic, createReaction, createRenderEffect, createSignal, createTrackedEffect, onCleanup, onSettled, resolve } from "./signals.js";
24
+
25
+ export { affects } from "./affects.js";
26
+
27
+ export { mapArray, repeat } from "./map.js";
28
+
29
+ export { $PROXY, $TARGET, $TRACK, createStore, isWrappable } from "./store/store.js";
30
+
31
+ export { createProjection } from "./store/projection.js";
32
+
33
+ export { createOptimisticStore } from "./store/optimistic.js";
34
+
35
+ export { reconcile } from "./store/reconcile.js";
36
+
37
+ export { storePath } from "./store/storePath.js";
38
+
39
+ export { deep, merge, omit, snapshot } from "./store/utils.js";
40
+
41
+ export { createErrorBoundary, createLoadingBoundary, createRevealOrder, flatten } from "./boundaries.js";
42
+
43
+ const DEV = undefined;
44
+
45
+ export { DEV };
@@ -0,0 +1,293 @@
1
+ import { computed, runWithOwner, signal, setSignal } from "./core/core.js";
2
+
3
+ import { createOwner } from "./core/owner.js";
4
+
5
+ import "./core/scheduler.js";
6
+
7
+ import { CONFIG_AUTO_DISPOSE } from "./core/constants.js";
8
+
9
+ import "./core/invariants.js";
10
+
11
+ import "./core/verdict.js";
12
+
13
+ import "./core/effect.js";
14
+
15
+ import { accessor } from "./signals.js";
16
+
17
+ import { $TRACK } from "./store/store.js";
18
+
19
+ function mapArray(t, s, i) {
20
+ const e = typeof i?.keyed === "function" ? i.keyed : undefined;
21
+ const r = s.length > 1;
22
+ const n = s;
23
+ const h = {
24
+ jt: createOwner(),
25
+ Wt: 0,
26
+ Kt: t,
27
+ xt: [],
28
+ $t: n,
29
+ qt: [],
30
+ zt: [],
31
+ Ht: e,
32
+ Jt: e || i?.keyed === false ? [] : undefined,
33
+ Xt: r && i?.keyed !== false ? [] : undefined,
34
+ Yt: i?.keyed === false,
35
+ Zt: i?.fallback
36
+ };
37
+ const o = computed(updateKeyedMap.bind(h));
38
+ // Untracked reads inside the internal owner resolve via _parentComputed; routing
39
+ // them through node lets store-proxy lookups see pending writes (not stale _value).
40
+ h.jt.Ct = o;
41
+ o.U &= ~CONFIG_AUTO_DISPOSE;
42
+ return accessor(o);
43
+ }
44
+
45
+ const pureOptions = {
46
+ ownedWrite: true
47
+ };
48
+
49
+ // Exception safety (#2903): a map callback can throw NotReadyError mid-pass
50
+ // (async read), and the computed re-runs the whole pass after settle. Every
51
+ // pass therefore STAGES its work — new rows are created into temp arrays and
52
+ // removals are deferred — and commits to `this` only after every mapper
53
+ // succeeded. An aborted pass disposes just the owners it created and leaves
54
+ // `_items`/`_mappings`/`_nodes`/`_rows`/`_indexes`/`_len` exactly as they
55
+ // were, so the retry diffs against uncorrupted state. Consequence of the
56
+ // strong-abort ordering: removed rows now dispose AFTER the pass's new rows
57
+ // are created (you cannot destroy state before knowing the pass will land).
58
+ function updateKeyedMap() {
59
+ const t = this.Kt() || [], s = t.length;
60
+ t[$TRACK];
61
+ // top level tracking
62
+ runWithOwner(this.jt, () => {
63
+ let i, e, r, n,
64
+ // Mappers write freshly-created row/index signals into the STAGE
65
+ // arrays (`rows`/`indexes`), never into `this._rows`/`this._indexes`.
66
+ h = this.Jt ? this.Yt ? () => {
67
+ r[e] = signal(t[e], pureOptions);
68
+ return this.$t(accessor(r[e]), e);
69
+ } : () => {
70
+ r[e] = signal(t[e], pureOptions);
71
+ n && (n[e] = signal(e, pureOptions));
72
+ return this.$t(accessor(r[e]), n ? accessor(n[e]) : undefined);
73
+ } : this.Xt ? () => {
74
+ const s = t[e];
75
+ n[e] = signal(e, pureOptions);
76
+ return this.$t(s, accessor(n[e]));
77
+ } : () => {
78
+ const s = t[e];
79
+ return this.$t(s);
80
+ };
81
+ // fast path for empty arrays
82
+ if (s === 0) {
83
+ if (this.Wt !== 0) {
84
+ this.jt.dispose(false);
85
+ this.zt = [];
86
+ this.xt = [];
87
+ this.qt = [];
88
+ this.Wt = 0;
89
+ this.Jt && (this.Jt = []);
90
+ this.Xt && (this.Xt = []);
91
+ }
92
+ if (this.Zt && !this.qt[0]) {
93
+ // an aborted fallback attempt leaves an owner without a mapping;
94
+ // dispose it before re-creating
95
+ this.zt[0]?.dispose();
96
+ this.qt[0] = runWithOwner(this.zt[0] = createOwner(), this.Zt);
97
+ }
98
+ }
99
+ // fast path for new create
100
+ else if (this.Wt === 0) {
101
+ const o = new Array(s);
102
+ const c = new Array(s);
103
+ r = this.Jt && new Array(s);
104
+ n = this.Xt && new Array(s);
105
+ try {
106
+ for (e = 0; e < s; e++) o[e] = runWithOwner(c[e] = createOwner(), h);
107
+ } catch (t) {
108
+ for (i = 0; i <= e; i++) c[i]?.dispose();
109
+ throw t;
110
+ }
111
+ // commit
112
+ if (this.zt[0]) this.zt[0].dispose();
113
+ // previous fallback
114
+ this.qt = o;
115
+ this.zt = c;
116
+ r && (this.Jt = r);
117
+ n && (this.Xt = n);
118
+ this.xt = t.slice(0);
119
+ this.Wt = s;
120
+ } else {
121
+ let o, c, a, f, u, p, w, l, d, O = new Array(s), m = new Array(s);
122
+ r = this.Jt ? new Array(s) : undefined;
123
+ n = this.Xt ? new Array(s) : undefined;
124
+ // skip common prefix
125
+ for (o = 0, c = Math.min(this.Wt, s); o < c && (this.xt[o] === t[o] || this.Jt && compare(this.Ht, this.xt[o], t[o])); o++) {
126
+ if (this.Jt) setSignal(this.Jt[o], t[o]);
127
+ }
128
+ // common suffix
129
+ for (c = this.Wt - 1, a = s - 1; c >= o && a >= o && (this.xt[c] === t[a] || this.Jt && compare(this.Ht, this.xt[c], t[a])); c--,
130
+ a--) {
131
+ O[a] = this.qt[c];
132
+ m[a] = this.zt[c];
133
+ r && (r[a] = this.Jt[c]);
134
+ n && (n[a] = this.Xt[c]);
135
+ }
136
+ // 0) prepare a map of all indices in newItems, scanning backwards so we encounter them in natural order
137
+ p = new Map;
138
+ w = new Array(a + 1);
139
+ for (e = a; e >= o; e--) {
140
+ f = t[e];
141
+ u = this.Ht ? this.Ht(f) : f;
142
+ i = p.get(u);
143
+ w[e] = i === undefined ? -1 : i;
144
+ p.set(u, e);
145
+ }
146
+ // 1) step through all old items and see if they can be found in the new set; if so, save them in a temp array and mark them moved; if not, queue them for disposal at commit
147
+ for (i = o; i <= c; i++) {
148
+ f = this.xt[i];
149
+ u = this.Ht ? this.Ht(f) : f;
150
+ e = p.get(u);
151
+ if (e !== undefined && e !== -1) {
152
+ O[e] = this.qt[i];
153
+ m[e] = this.zt[i];
154
+ r && (r[e] = this.Jt[i]);
155
+ n && (n[e] = this.Xt[i]);
156
+ e = w[e];
157
+ p.set(u, e);
158
+ } else (l ??= []).push(this.zt[i]);
159
+ }
160
+ // 2) create new rows into the temp arrays; an abort disposes only these
161
+ try {
162
+ for (e = o; e < s; e++) {
163
+ if (e in O) continue;
164
+ (d ??= []).push(m[e] = createOwner());
165
+ O[e] = runWithOwner(m[e], h);
166
+ }
167
+ } catch (t) {
168
+ if (d) for (i = 0; i < d.length; i++) d[i].dispose();
169
+ throw t;
170
+ }
171
+ // 3) commit: land positions, then dispose exited rows
172
+ for (e = o; e < s; e++) {
173
+ this.qt[e] = O[e];
174
+ this.zt[e] = m[e];
175
+ if (r) {
176
+ this.Jt[e] = r[e];
177
+ setSignal(this.Jt[e], t[e]);
178
+ }
179
+ if (n) {
180
+ this.Xt[e] = n[e];
181
+ setSignal(this.Xt[e], e);
182
+ }
183
+ }
184
+ if (l) for (i = 0; i < l.length; i++) l[i].dispose();
185
+ // 4) in case the new set is shorter than the old, set the length of the mapped array
186
+ this.qt = this.qt.slice(0, this.Wt = s);
187
+ // 5) save a copy of the mapped items for the next update
188
+ this.xt = t.slice(0);
189
+ }
190
+ });
191
+ return this.qt;
192
+ }
193
+
194
+ /**
195
+ * Reactively renders a callback `count` times, reusing previously-rendered
196
+ * entries when only the count changes. Underlying helper for `<Repeat>`.
197
+ *
198
+ * - `options.from` — start index (default `0`); useful for offset/windowed
199
+ * rendering.
200
+ * - `options.fallback` — accessor returning a value to show when count is `0`.
201
+ *
202
+ * @example
203
+ * ```ts
204
+ * const view = repeat(count, i => `Item ${i}`, { fallback: () => "empty" });
205
+ * ```
206
+ *
207
+ * @description https://docs.solidjs.com/reference/reactive-utilities/repeat
208
+ */ function repeat(t, s, i) {
209
+ const e = s;
210
+ const r = {
211
+ jt: createOwner(),
212
+ Wt: 0,
213
+ ts: 0,
214
+ ss: t,
215
+ $t: e,
216
+ zt: [],
217
+ qt: [],
218
+ es: i?.from,
219
+ Zt: i?.fallback
220
+ };
221
+ const n = computed(updateRepeat.bind(r));
222
+ // Same as mapArray: untracked reads inside the internal owner resolve via
223
+ // _parentComputed, so async reads in row callbacks register with the node
224
+ // (pending tracking + post-settle retry) instead of vanishing.
225
+ r.jt.Ct = n;
226
+ n.U &= ~CONFIG_AUTO_DISPOSE;
227
+ return accessor(n);
228
+ }
229
+
230
+ // Same staged-commit discipline as `updateKeyedMap` (#2903): the retained
231
+ // window overlap is copied into fresh arrays, missing indexes are created
232
+ // into them, and `this` is only touched — including disposal of rows leaving
233
+ // the window — after every `_map` call succeeded. A NotReadyError mid-pass
234
+ // disposes only the owners this pass created and leaves prior state intact
235
+ // for the post-settle retry. The overlap math also subsumes the previous
236
+ // disjoint-window/front-clear/end-clear/shift special cases.
237
+ function updateRepeat() {
238
+ const t = this.ss();
239
+ const s = this.es?.() || 0;
240
+ runWithOwner(this.jt, () => {
241
+ if (t === 0) {
242
+ if (this.Wt !== 0) {
243
+ this.jt.dispose(false);
244
+ this.zt = [];
245
+ this.qt = [];
246
+ this.Wt = 0;
247
+ // Reset offset to match the cleared data (#2767, repro 2).
248
+ this.ts = 0;
249
+ }
250
+ if (this.Zt && !this.qt[0]) {
251
+ // an aborted fallback attempt leaves an owner without a mapping;
252
+ // dispose it before re-creating
253
+ this.zt[0]?.dispose();
254
+ this.qt[0] = runWithOwner(this.zt[0] = createOwner(), this.Zt);
255
+ }
256
+ return;
257
+ }
258
+ const i = s + t;
259
+ const e = this.ts + this.Wt;
260
+ // Retained overlap [keepStart, keepEnd) in global indexes; empty when the
261
+ // windows are disjoint or when coming from empty/fallback.
262
+ const r = Math.max(s, this.ts);
263
+ const n = Math.min(i, e);
264
+ const h = new Array(t);
265
+ const o = new Array(t);
266
+ for (let t = r; t < n; t++) {
267
+ o[t - s] = this.zt[t - this.ts];
268
+ h[t - s] = this.qt[t - this.ts];
269
+ }
270
+ try {
271
+ for (let t = s; t < i; t++) {
272
+ if (t >= r && t < n) continue;
273
+ h[t - s] = runWithOwner(o[t - s] = createOwner(), () => this.$t(t));
274
+ }
275
+ } catch (t) {
276
+ for (let t = s; t < i; t++) if ((t < r || t >= n) && o[t - s]) o[t - s].dispose();
277
+ throw t;
278
+ }
279
+ // commit: dispose the previous fallback or the rows leaving the window
280
+ if (this.Wt === 0) this.zt[0]?.dispose(); else for (let t = this.ts; t < e; t++) if (t < s || t >= i) this.zt[t - this.ts].dispose();
281
+ this.qt = h;
282
+ this.zt = o;
283
+ this.ts = s;
284
+ this.Wt = t;
285
+ });
286
+ return this.qt;
287
+ }
288
+
289
+ function compare(t, s, i) {
290
+ return t ? t(s) === t(i) : true;
291
+ }
292
+
293
+ export { mapArray, repeat };