@solidjs/signals 2.0.0-rc.6 → 2.0.0-rc.8
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.
- package/dist/dev-shared.js +5243 -0
- package/dist/dev.attribution.js +2333 -0
- package/dist/dev.js +1758 -6621
- package/dist/observe/affects.js +127 -0
- package/dist/observe/attribution.js +1 -0
- package/dist/observe/boundaries.js +586 -0
- package/dist/observe/core/action.js +167 -0
- package/dist/observe/core/async.js +736 -0
- package/dist/observe/core/attribution-hooks.js +60 -0
- package/dist/observe/core/attribution.js +2318 -0
- package/dist/{types-cjs/core/constants.d.cts → observe/core/constants.js} +135 -71
- package/dist/{types-cjs/core/context.d.cts → observe/core/context.js} +37 -12
- package/dist/observe/core/core.js +1289 -0
- package/dist/observe/core/dev.js +232 -0
- package/dist/observe/core/effect.js +179 -0
- package/dist/observe/core/error.js +80 -0
- package/dist/observe/core/external.js +98 -0
- package/dist/observe/core/graph.js +155 -0
- package/dist/observe/core/heap.js +147 -0
- package/dist/observe/core/invariants.js +43 -0
- package/dist/observe/core/lanes.js +168 -0
- package/dist/observe/core/optimistic.js +438 -0
- package/dist/observe/core/owner.js +308 -0
- package/dist/observe/core/scheduler.js +1190 -0
- package/dist/observe/core/verdict.js +551 -0
- package/dist/observe/index.js +55 -0
- package/dist/observe/map.js +482 -0
- package/dist/{types-cjs/signals.d.cts → observe/signals.js} +305 -317
- package/dist/observe/store/index.js +38 -0
- package/dist/observe/store/next/optimistic.js +651 -0
- package/dist/observe/store/next/projection.js +242 -0
- package/dist/observe/store/next/reconcile.js +373 -0
- package/dist/observe/store/next/store.js +2213 -0
- package/dist/observe/store/next/target.js +51 -0
- package/dist/observe/store/store.js +323 -0
- package/dist/observe/store/storePath.js +103 -0
- package/dist/observe/store/utils.js +210 -0
- package/dist/prod/attribution.js +32 -0
- package/dist/prod/boundaries.js +3 -1
- package/dist/prod/core/action.js +52 -32
- package/dist/prod/core/async.js +177 -128
- package/dist/prod/core/attribution-hooks.js +3 -0
- package/dist/prod/core/constants.js +32 -1
- package/dist/prod/core/context.js +10 -16
- package/dist/prod/core/core.js +505 -286
- package/dist/prod/core/dev.js +2 -0
- package/dist/prod/core/effect.js +72 -43
- package/dist/prod/core/external.js +2 -2
- package/dist/prod/core/graph.js +40 -36
- package/dist/prod/core/heap.js +50 -51
- package/dist/prod/core/lanes.js +43 -22
- package/dist/prod/core/optimistic.js +224 -80
- package/dist/prod/core/owner.js +43 -39
- package/dist/prod/core/scheduler.js +347 -232
- package/dist/prod/core/verdict.js +71 -74
- package/dist/prod/index.js +9 -5
- package/dist/prod/map.js +311 -150
- package/dist/prod/signals.js +52 -38
- package/dist/prod/store/next/optimistic.js +127 -131
- package/dist/prod/store/next/projection.js +3 -3
- package/dist/prod/store/next/reconcile.js +149 -294
- package/dist/prod/store/next/store.js +694 -380
- package/dist/prod/store/next/target.js +32 -10
- package/dist/prod/store/store.js +12 -14
- package/dist/prod/store/utils.js +36 -27
- package/dist/types/attribution.d.ts +15 -0
- package/dist/types/attribution.prod.d.ts +13 -0
- package/dist/types/core/async.d.ts +1 -1
- package/dist/types/core/attribution-hooks.d.ts +183 -6
- package/dist/types/core/attribution.d.ts +435 -24
- package/dist/types/core/constants.d.ts +31 -0
- package/dist/types/core/core.d.ts +19 -3
- package/dist/types/core/dev.d.ts +165 -26
- package/dist/types/core/effect.d.ts +8 -1
- package/dist/types/core/heap.d.ts +5 -3
- package/dist/types/core/index.d.ts +2 -1
- package/dist/types/core/invariants.d.ts +1 -1
- package/dist/types/core/lanes.d.ts +17 -0
- package/dist/types/core/scheduler.d.ts +69 -4
- package/dist/types/core/types.d.ts +29 -9
- package/dist/types/index.d.ts +9 -2
- package/dist/types/map.d.ts +2 -0
- package/dist/types/signals.d.ts +10 -0
- package/dist/types/store/index.d.ts +4 -6
- package/dist/types/store/next/optimistic.d.ts +4 -2
- package/dist/types/store/next/reconcile.d.ts +5 -12
- package/dist/types/store/next/store.d.ts +8 -9
- package/dist/types/store/next/target.d.ts +56 -55
- package/dist/types/store/store.d.ts +14 -9
- package/dist/types/store/utils.d.ts +7 -0
- package/package.json +21 -16
- package/dist/node.cjs +0 -11121
- package/dist/prod/store/next/patch-hooks.js +0 -13
- package/dist/prod/store/next/patch.js +0 -614
- package/dist/types/store/next/patch-hooks.d.ts +0 -41
- package/dist/types/store/next/patch.d.ts +0 -91
- package/dist/types-cjs/affects.d.cts +0 -47
- package/dist/types-cjs/boundaries.d.cts +0 -175
- package/dist/types-cjs/core/action.d.cts +0 -64
- package/dist/types-cjs/core/async.d.cts +0 -23
- package/dist/types-cjs/core/attribution-hooks.d.cts +0 -63
- package/dist/types-cjs/core/attribution.d.cts +0 -239
- package/dist/types-cjs/core/core.d.cts +0 -176
- package/dist/types-cjs/core/dev.d.cts +0 -95
- package/dist/types-cjs/core/effect.d.cts +0 -30
- package/dist/types-cjs/core/error.d.cts +0 -56
- package/dist/types-cjs/core/external.d.cts +0 -15
- package/dist/types-cjs/core/graph.d.cts +0 -28
- package/dist/types-cjs/core/heap.d.cts +0 -22
- package/dist/types-cjs/core/index.d.cts +0 -13
- package/dist/types-cjs/core/invariants.d.cts +0 -59
- package/dist/types-cjs/core/lanes.d.cts +0 -44
- package/dist/types-cjs/core/optimistic.d.cts +0 -6
- package/dist/types-cjs/core/owner.d.cts +0 -124
- package/dist/types-cjs/core/scheduler.d.cts +0 -231
- package/dist/types-cjs/core/types.d.cts +0 -204
- package/dist/types-cjs/core/verdict.d.cts +0 -2
- package/dist/types-cjs/index.d.cts +0 -10
- package/dist/types-cjs/map.d.cts +0 -69
- package/dist/types-cjs/package.json +0 -3
- package/dist/types-cjs/store/index.d.cts +0 -21
- package/dist/types-cjs/store/next/optimistic.d.cts +0 -23
- package/dist/types-cjs/store/next/patch-hooks.d.cts +0 -41
- package/dist/types-cjs/store/next/patch.d.cts +0 -91
- package/dist/types-cjs/store/next/projection.d.cts +0 -8
- package/dist/types-cjs/store/next/reconcile.d.cts +0 -17
- package/dist/types-cjs/store/next/store.d.cts +0 -127
- package/dist/types-cjs/store/next/target.d.cts +0 -192
- package/dist/types-cjs/store/store.d.cts +0 -138
- package/dist/types-cjs/store/storePath.d.cts +0 -58
- package/dist/types-cjs/store/utils.d.cts +0 -74
|
@@ -0,0 +1,482 @@
|
|
|
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 { attrHooks } from "./core/attribution-hooks.js";
|
|
10
|
+
|
|
11
|
+
import "./core/invariants.js";
|
|
12
|
+
|
|
13
|
+
import "./core/verdict.js";
|
|
14
|
+
|
|
15
|
+
import "./core/effect.js";
|
|
16
|
+
|
|
17
|
+
import { accessor } from "./signals.js";
|
|
18
|
+
|
|
19
|
+
import { $TRACK } from "./store/store.js";
|
|
20
|
+
|
|
21
|
+
import "./store/next/store.js";
|
|
22
|
+
|
|
23
|
+
function mapArray(t, s, i) {
|
|
24
|
+
const e = typeof i?.keyed === "function" ? i.keyed : undefined;
|
|
25
|
+
const r = s.length > 1;
|
|
26
|
+
const n = s;
|
|
27
|
+
const o = {
|
|
28
|
+
an: createOwner(),
|
|
29
|
+
ts: 0,
|
|
30
|
+
ss: t,
|
|
31
|
+
es: [],
|
|
32
|
+
rs: n,
|
|
33
|
+
ns: [],
|
|
34
|
+
hs: [],
|
|
35
|
+
_n: e,
|
|
36
|
+
fs: e || i?.keyed === false ? [] : undefined,
|
|
37
|
+
cs: r && i?.keyed !== false ? [] : undefined,
|
|
38
|
+
us: i?.keyed === false,
|
|
39
|
+
ls: i?.fallback
|
|
40
|
+
};
|
|
41
|
+
const h = computed(updateKeyedMap.bind(o), i?.name ? {
|
|
42
|
+
name: i.name
|
|
43
|
+
} : undefined);
|
|
44
|
+
// Untracked reads inside the internal owner resolve via _parentComputed; routing
|
|
45
|
+
// them through node lets store-proxy lookups see pending writes (not stale _value).
|
|
46
|
+
o.an.ln = h;
|
|
47
|
+
h.T &= ~CONFIG_AUTO_DISPOSE;
|
|
48
|
+
return accessor(h);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const pureOptions = {
|
|
52
|
+
ownedWrite: true
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
function trySmallMove(t, s, i, e) {
|
|
56
|
+
const r = t.es;
|
|
57
|
+
const n = t.ts - 1;
|
|
58
|
+
const o = [];
|
|
59
|
+
const h = [];
|
|
60
|
+
const f = [];
|
|
61
|
+
// flat triples: oldStart, newStart, length
|
|
62
|
+
let c = 256;
|
|
63
|
+
let a = e;
|
|
64
|
+
let u = e;
|
|
65
|
+
let l = false;
|
|
66
|
+
while (a <= n && u <= i - 1) {
|
|
67
|
+
const t = r[a];
|
|
68
|
+
const e = s[u];
|
|
69
|
+
if (t === e) {
|
|
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 d = -1;
|
|
82
|
+
let p = Math.min(32 - o.length, n - a, c);
|
|
83
|
+
for (let t = 1; t <= p; t++) {
|
|
84
|
+
if (r[a + t] === e) {
|
|
85
|
+
d = t;
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
c -= d === -1 ? p : d;
|
|
90
|
+
let w = -1;
|
|
91
|
+
p = Math.min(32 - h.length, i - 1 - u, c);
|
|
92
|
+
for (let i = 1; i <= p; i++) {
|
|
93
|
+
if (s[u + i] === t) {
|
|
94
|
+
w = i;
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
c -= w === -1 ? p : w;
|
|
99
|
+
if (d !== -1 && (w === -1 || d <= w)) {
|
|
100
|
+
while (d-- > 0) o.push(a++);
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if (w !== -1) {
|
|
104
|
+
while (w-- > 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 <= i - 1; u++) {
|
|
116
|
+
if (h.length === 32) return false;
|
|
117
|
+
h.push(u);
|
|
118
|
+
}
|
|
119
|
+
return commitSmallMove(t, s, i, 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, i, e, r, n) {
|
|
129
|
+
const o = t.es;
|
|
130
|
+
let h;
|
|
131
|
+
let f;
|
|
132
|
+
let c;
|
|
133
|
+
if (r.length !== 0) {
|
|
134
|
+
c = new Array(e.length);
|
|
135
|
+
for (f = 0; f < r.length; f++) {
|
|
136
|
+
let t = -1;
|
|
137
|
+
for (h = 0; h < e.length; h++) {
|
|
138
|
+
if (!c[h] && o[e[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 (e.length !== 0 || r.length !== 0) {
|
|
156
|
+
const t = new Set;
|
|
157
|
+
for (h = 0; h < e.length; h++) t.add(o[e[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 i = n[s];
|
|
161
|
+
for (let e = 0, r = n[s + 2]; e < r; e++) if (t.has(o[i + e])) return false;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
const a = t.ns;
|
|
165
|
+
const u = t.hs;
|
|
166
|
+
const l = a.slice(0, i);
|
|
167
|
+
const d = u.slice(0, i);
|
|
168
|
+
for (let t = 0; t < n.length; t += 3) {
|
|
169
|
+
const s = n[t];
|
|
170
|
+
const i = n[t + 1];
|
|
171
|
+
if (s !== i) {
|
|
172
|
+
for (let e = 0; e < n[t + 2]; e++) {
|
|
173
|
+
l[i + e] = a[s + e];
|
|
174
|
+
d[i + e] = u[s + e];
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
for (f = 0; f < r.length; f++) {
|
|
179
|
+
const t = r[f] >> 6;
|
|
180
|
+
const s = e[r[f] & 63];
|
|
181
|
+
l[t] = a[s];
|
|
182
|
+
d[t] = u[s];
|
|
183
|
+
}
|
|
184
|
+
t.ns = l;
|
|
185
|
+
t.hs = d;
|
|
186
|
+
t.ts = i;
|
|
187
|
+
t.es = s.slice(0);
|
|
188
|
+
// Dispose unmatched sources LAST (general-path ordering).
|
|
189
|
+
for (h = 0; h < e.length; h++) {
|
|
190
|
+
if (c === undefined || !c[h]) u[e[h]].dispose();
|
|
191
|
+
}
|
|
192
|
+
return true;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function updateKeyedMap() {
|
|
196
|
+
const t = this.ss() || [], s = t.length;
|
|
197
|
+
t[$TRACK];
|
|
198
|
+
// top level tracking
|
|
199
|
+
runWithOwner(this.an, () => {
|
|
200
|
+
let i, e, r, n,
|
|
201
|
+
// Mappers write freshly-created row/index signals into the STAGE
|
|
202
|
+
// arrays (`rows`/`indexes`), never into `this._rows`/`this._indexes`.
|
|
203
|
+
o = this.fs ? this.us ? () => {
|
|
204
|
+
r[e] = signal(t[e], pureOptions);
|
|
205
|
+
return this.rs(accessor(r[e]), e);
|
|
206
|
+
} : () => {
|
|
207
|
+
r[e] = signal(t[e], pureOptions);
|
|
208
|
+
n && (n[e] = signal(e, pureOptions));
|
|
209
|
+
return this.rs(accessor(r[e]), n ? accessor(n[e]) : undefined);
|
|
210
|
+
} : this.cs ? () => {
|
|
211
|
+
const s = t[e];
|
|
212
|
+
n[e] = signal(e, pureOptions);
|
|
213
|
+
return this.rs(s, accessor(n[e]));
|
|
214
|
+
} : () => {
|
|
215
|
+
const s = t[e];
|
|
216
|
+
return this.rs(s);
|
|
217
|
+
};
|
|
218
|
+
// fast path for empty arrays
|
|
219
|
+
if (s === 0) {
|
|
220
|
+
if (this.ts !== 0) {
|
|
221
|
+
this.an.dispose(false);
|
|
222
|
+
this.hs = [];
|
|
223
|
+
this.es = [];
|
|
224
|
+
this.ns = [];
|
|
225
|
+
this.ts = 0;
|
|
226
|
+
this.fs && (this.fs = []);
|
|
227
|
+
this.cs && (this.cs = []);
|
|
228
|
+
}
|
|
229
|
+
if (this.ls && !this.ns[0]) {
|
|
230
|
+
// an aborted fallback attempt leaves an owner without a mapping;
|
|
231
|
+
// dispose it before re-creating
|
|
232
|
+
this.hs[0]?.dispose();
|
|
233
|
+
this.ns[0] = runWithOwner(this.hs[0] = createOwner(), this.ls);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
// fast path for new create
|
|
237
|
+
else if (this.ts === 0) {
|
|
238
|
+
const h = new Array(s);
|
|
239
|
+
const f = new Array(s);
|
|
240
|
+
r = this.fs && new Array(s);
|
|
241
|
+
n = this.cs && new Array(s);
|
|
242
|
+
try {
|
|
243
|
+
for (e = 0; e < s; e++) h[e] = runWithOwner(f[e] = createOwner(), o);
|
|
244
|
+
} catch (t) {
|
|
245
|
+
for (i = 0; i <= e; i++) f[i]?.dispose();
|
|
246
|
+
throw t;
|
|
247
|
+
}
|
|
248
|
+
// commit
|
|
249
|
+
if (this.hs[0]) this.hs[0].dispose();
|
|
250
|
+
// previous fallback
|
|
251
|
+
this.ns = h;
|
|
252
|
+
this.hs = f;
|
|
253
|
+
r && (this.fs = r);
|
|
254
|
+
n && (this.cs = n);
|
|
255
|
+
this.es = t.slice(0);
|
|
256
|
+
this.ts = s;
|
|
257
|
+
} else {
|
|
258
|
+
let h, f, c, a, u, l, d, p, w,
|
|
259
|
+
// Dev (attribution engine installed): the items behind the exited and
|
|
260
|
+
// entered rows, for the list-identity census.
|
|
261
|
+
m, O;
|
|
262
|
+
// skip common prefix
|
|
263
|
+
for (h = 0, f = Math.min(this.ts, s); h < f && (this.es[h] === t[h] || this.fs && compare(this._n, this.es[h], t[h])); h++) {
|
|
264
|
+
if (this.fs) setSignal(this.fs[h], t[h]);
|
|
265
|
+
}
|
|
266
|
+
// skip common suffix — counted only; retained entries land in one pass
|
|
267
|
+
// at commit instead of being staged and copied twice
|
|
268
|
+
for (f = this.ts - 1, c = s - 1; f >= h && c >= h && (this.es[f] === t[c] || this.fs && compare(this._n, this.es[f], t[c])); f--,
|
|
269
|
+
c--) ;
|
|
270
|
+
// no structural change (every position matched in place at equal
|
|
271
|
+
// length — the common post-reconcile shape): keep the same mapped
|
|
272
|
+
// array identity so downstream consumers don't re-run at all
|
|
273
|
+
if (h === s && this.ts === s) {
|
|
274
|
+
this.es = t.slice(0);
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
// SMALL-MOVE FAST PATH: extracted to its own function — inlining it
|
|
278
|
+
// here bloats updateKeyedMap past the JIT's optimization budget and
|
|
279
|
+
// deoptimizes the GENERAL path (measured 2x on reverse). Gated to
|
|
280
|
+
// LARGE trimmed windows: when the trims already shrank the window
|
|
281
|
+
// (plain removals, tail edits), the general path is window-
|
|
282
|
+
// proportional and cheap — the fast path would only re-walk what the
|
|
283
|
+
// trims proved.
|
|
284
|
+
if (s <= this.ts && f - h > 64 && this.fs === undefined && this.cs === undefined) {
|
|
285
|
+
// PROBE before the scan: a small move keeps a mid-window item within
|
|
286
|
+
// ±32 of its old position; a REPLACE (all fresh items — the shape
|
|
287
|
+
// every page's first structural pass usually is) has it nowhere.
|
|
288
|
+
// ~65 compares, no allocation, and the scan function is never
|
|
289
|
+
// compiled for a replace (its cold first-call compile was the cost).
|
|
290
|
+
const i = h + (c - h >> 1);
|
|
291
|
+
const e = t[i];
|
|
292
|
+
const r = Math.min(f, i + 32);
|
|
293
|
+
let n = Math.max(h, i - 32);
|
|
294
|
+
while (n <= r && this.es[n] !== e) n++;
|
|
295
|
+
if (n <= r && trySmallMove(this, t, s, h)) return;
|
|
296
|
+
}
|
|
297
|
+
const _ = s - this.ts;
|
|
298
|
+
const y = new Array(s);
|
|
299
|
+
const A = new Array(s);
|
|
300
|
+
r = this.fs ? new Array(s) : undefined;
|
|
301
|
+
n = this.cs ? new Array(s) : undefined;
|
|
302
|
+
// 0) prepare a map of all indices in the changed window of newItems,
|
|
303
|
+
// scanning backwards so we encounter them in natural order
|
|
304
|
+
l = new Map;
|
|
305
|
+
d = new Array(c + 1);
|
|
306
|
+
for (e = c; e >= h; e--) {
|
|
307
|
+
a = t[e];
|
|
308
|
+
u = this._n ? this._n(a) : a;
|
|
309
|
+
i = l.get(u);
|
|
310
|
+
d[e] = i === undefined ? -1 : i;
|
|
311
|
+
l.set(u, e);
|
|
312
|
+
}
|
|
313
|
+
// 1) step through the old changed window and see if items can be found
|
|
314
|
+
// in the new set; if so, stage them at their new positions; if not,
|
|
315
|
+
// queue them for disposal at commit
|
|
316
|
+
for (i = h; i <= f; i++) {
|
|
317
|
+
a = this.es[i];
|
|
318
|
+
u = this._n ? this._n(a) : a;
|
|
319
|
+
e = l.get(u);
|
|
320
|
+
if (e !== undefined && e !== -1) {
|
|
321
|
+
y[e] = this.ns[i];
|
|
322
|
+
A[e] = this.hs[i];
|
|
323
|
+
r && (r[e] = this.fs[i]);
|
|
324
|
+
n && (n[e] = this.cs[i]);
|
|
325
|
+
e = d[e];
|
|
326
|
+
l.set(u, e);
|
|
327
|
+
} else {
|
|
328
|
+
(p ??= []).push(this.hs[i]);
|
|
329
|
+
if (true && attrHooks !== null) (m ??= []).push(a);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
// 2) create new rows into the temp arrays; an abort disposes only these
|
|
333
|
+
try {
|
|
334
|
+
for (e = h; e <= c; e++) {
|
|
335
|
+
if (A[e] !== undefined) continue;
|
|
336
|
+
(w ??= []).push(A[e] = createOwner());
|
|
337
|
+
if (true && attrHooks !== null) (O ??= []).push(t[e]);
|
|
338
|
+
y[e] = runWithOwner(A[e], o);
|
|
339
|
+
}
|
|
340
|
+
} catch (t) {
|
|
341
|
+
if (w) for (i = 0; i < w.length; i++) w[i].dispose();
|
|
342
|
+
throw t;
|
|
343
|
+
}
|
|
344
|
+
// 3) commit: land the retained prefix and suffix plus the staged window
|
|
345
|
+
// into the fresh arrays, swap them in (new identity for downstream
|
|
346
|
+
// change propagation), then dispose exited rows
|
|
347
|
+
for (i = 0; i < h; i++) {
|
|
348
|
+
y[i] = this.ns[i];
|
|
349
|
+
A[i] = this.hs[i];
|
|
350
|
+
r && (r[i] = this.fs[i]);
|
|
351
|
+
n && (n[i] = this.cs[i]);
|
|
352
|
+
}
|
|
353
|
+
for (e = h; e <= c; e++) {
|
|
354
|
+
if (r) setSignal(r[e], t[e]);
|
|
355
|
+
if (n) setSignal(n[e], e);
|
|
356
|
+
}
|
|
357
|
+
for (e = c + 1; e < s; e++) {
|
|
358
|
+
y[e] = this.ns[e - _];
|
|
359
|
+
A[e] = this.hs[e - _];
|
|
360
|
+
if (r) {
|
|
361
|
+
r[e] = this.fs[e - _];
|
|
362
|
+
setSignal(r[e], t[e]);
|
|
363
|
+
}
|
|
364
|
+
if (n) {
|
|
365
|
+
n[e] = this.cs[e - _];
|
|
366
|
+
if (_ !== 0) setSignal(n[e], e);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
this.ns = y;
|
|
370
|
+
this.hs = A;
|
|
371
|
+
r && (this.fs = r);
|
|
372
|
+
n && (this.cs = n);
|
|
373
|
+
this.ts = s;
|
|
374
|
+
// save a copy of the mapped items for the next update
|
|
375
|
+
this.es = t.slice(0);
|
|
376
|
+
if (p) for (i = 0; i < p.length; i++) p[i].dispose();
|
|
377
|
+
if (true && attrHooks !== null && m !== undefined && O !== undefined) attrHooks.listChurn(this.an.ln, m, O, s, this._n !== undefined);
|
|
378
|
+
}
|
|
379
|
+
});
|
|
380
|
+
return this.ns;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Reactively renders a callback `count` times, reusing previously-rendered
|
|
385
|
+
* entries when only the count changes. Underlying helper for `<Repeat>`.
|
|
386
|
+
*
|
|
387
|
+
* - `options.from` — start index (default `0`); useful for offset/windowed
|
|
388
|
+
* rendering.
|
|
389
|
+
* - `options.fallback` — accessor returning a value to show when count is `0`.
|
|
390
|
+
*
|
|
391
|
+
* @example
|
|
392
|
+
* ```ts
|
|
393
|
+
* const view = repeat(count, i => `Item ${i}`, { fallback: () => "empty" });
|
|
394
|
+
* ```
|
|
395
|
+
*
|
|
396
|
+
* @description https://docs.solidjs.com/reference/reactive-utilities/repeat
|
|
397
|
+
*/ function repeat(t, s, i) {
|
|
398
|
+
const e = s;
|
|
399
|
+
const r = {
|
|
400
|
+
an: createOwner(),
|
|
401
|
+
ts: 0,
|
|
402
|
+
ds: 0,
|
|
403
|
+
ps: t,
|
|
404
|
+
rs: e,
|
|
405
|
+
hs: [],
|
|
406
|
+
ns: [],
|
|
407
|
+
ws: i?.from,
|
|
408
|
+
ls: i?.fallback
|
|
409
|
+
};
|
|
410
|
+
const n = computed(updateRepeat.bind(r));
|
|
411
|
+
// Same as mapArray: untracked reads inside the internal owner resolve via
|
|
412
|
+
// _parentComputed, so async reads in row callbacks register with the node
|
|
413
|
+
// (pending tracking + post-settle retry) instead of vanishing.
|
|
414
|
+
r.an.ln = n;
|
|
415
|
+
n.T &= ~CONFIG_AUTO_DISPOSE;
|
|
416
|
+
return accessor(n);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// Same staged-commit discipline as `updateKeyedMap` (#2903): the retained
|
|
420
|
+
// window overlap is copied into fresh arrays, missing indexes are created
|
|
421
|
+
// into them, and `this` is only touched — including disposal of rows leaving
|
|
422
|
+
// the window — after every `_map` call succeeded. A NotReadyError mid-pass
|
|
423
|
+
// disposes only the owners this pass created and leaves prior state intact
|
|
424
|
+
// for the post-settle retry. The overlap math also subsumes the previous
|
|
425
|
+
// disjoint-window/front-clear/end-clear/shift special cases.
|
|
426
|
+
function updateRepeat() {
|
|
427
|
+
const t = this.ps();
|
|
428
|
+
const s = this.ws?.() || 0;
|
|
429
|
+
runWithOwner(this.an, () => {
|
|
430
|
+
if (t === 0) {
|
|
431
|
+
if (this.ts !== 0) {
|
|
432
|
+
this.an.dispose(false);
|
|
433
|
+
this.hs = [];
|
|
434
|
+
this.ns = [];
|
|
435
|
+
this.ts = 0;
|
|
436
|
+
// Reset offset to match the cleared data (#2767, repro 2).
|
|
437
|
+
this.ds = 0;
|
|
438
|
+
}
|
|
439
|
+
if (this.ls && !this.ns[0]) {
|
|
440
|
+
// an aborted fallback attempt leaves an owner without a mapping;
|
|
441
|
+
// dispose it before re-creating
|
|
442
|
+
this.hs[0]?.dispose();
|
|
443
|
+
this.ns[0] = runWithOwner(this.hs[0] = createOwner(), this.ls);
|
|
444
|
+
}
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
const i = s + t;
|
|
448
|
+
const e = this.ds + this.ts;
|
|
449
|
+
// Retained overlap [keepStart, keepEnd) in global indexes; empty when the
|
|
450
|
+
// windows are disjoint or when coming from empty/fallback.
|
|
451
|
+
const r = Math.max(s, this.ds);
|
|
452
|
+
const n = Math.min(i, e);
|
|
453
|
+
const o = new Array(t);
|
|
454
|
+
const h = new Array(t);
|
|
455
|
+
for (let t = r; t < n; t++) {
|
|
456
|
+
h[t - s] = this.hs[t - this.ds];
|
|
457
|
+
o[t - s] = this.ns[t - this.ds];
|
|
458
|
+
}
|
|
459
|
+
try {
|
|
460
|
+
for (let t = s; t < i; t++) {
|
|
461
|
+
if (t >= r && t < n) continue;
|
|
462
|
+
o[t - s] = runWithOwner(h[t - s] = createOwner(), () => this.rs(t));
|
|
463
|
+
}
|
|
464
|
+
} catch (t) {
|
|
465
|
+
for (let t = s; t < i; t++) if ((t < r || t >= n) && h[t - s]) h[t - s].dispose();
|
|
466
|
+
throw t;
|
|
467
|
+
}
|
|
468
|
+
// commit: dispose the previous fallback or the rows leaving the window
|
|
469
|
+
if (this.ts === 0) this.hs[0]?.dispose(); else for (let t = this.ds; t < e; t++) if (t < s || t >= i) this.hs[t - this.ds].dispose();
|
|
470
|
+
this.ns = o;
|
|
471
|
+
this.hs = h;
|
|
472
|
+
this.ds = s;
|
|
473
|
+
this.ts = t;
|
|
474
|
+
});
|
|
475
|
+
return this.ns;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
function compare(t, s, i) {
|
|
479
|
+
return t ? t(s) === t(i) : true;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
export { mapArray, repeat };
|