@solidjs/signals 2.0.0-rc.8 → 2.0.0-rc.9
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 +1399 -285
- package/dist/dev.attribution.js +459 -307
- package/dist/dev.js +1864 -435
- package/dist/observe/affects.js +3 -1
- package/dist/observe/attribution.js +7 -1
- package/dist/observe/boundaries.js +209 -154
- package/dist/observe/core/action.js +18 -8
- package/dist/observe/core/async.js +220 -110
- package/dist/observe/core/attribution-costs.js +66 -0
- package/dist/observe/core/attribution-feedback.js +282 -0
- package/dist/observe/core/attribution-hooks.js +23 -1
- package/dist/observe/core/attribution-queries.js +28 -0
- package/dist/observe/core/attribution.js +262 -485
- package/dist/observe/core/constants.js +34 -1
- package/dist/observe/core/context.js +3 -3
- package/dist/observe/core/core.js +867 -367
- package/dist/observe/core/dev.js +78 -17
- package/dist/observe/core/effect.js +67 -51
- package/dist/observe/core/error-hooks.js +71 -0
- package/dist/observe/core/external.js +4 -4
- package/dist/observe/core/graph.js +37 -37
- package/dist/observe/core/heap.js +45 -45
- package/dist/observe/core/invariants.js +2 -0
- package/dist/observe/core/lanes.js +86 -49
- package/dist/observe/core/optimistic.js +242 -95
- package/dist/observe/core/owner.js +98 -84
- package/dist/observe/core/scheduler.js +543 -305
- package/dist/observe/core/verdict.js +247 -129
- package/dist/observe/index.js +7 -3
- package/dist/observe/map.js +126 -124
- package/dist/observe/signals.js +33 -17
- package/dist/observe/store/index.js +2 -0
- package/dist/observe/store/next/optimistic.js +141 -132
- package/dist/observe/store/next/projection.js +34 -21
- package/dist/observe/store/next/reconcile.js +58 -56
- package/dist/observe/store/next/store.js +260 -146
- package/dist/observe/store/store.js +5 -3
- package/dist/observe/store/utils.js +948 -135
- package/dist/prod/attribution.js +26 -17
- package/dist/prod/boundaries.js +128 -76
- package/dist/prod/core/action.js +16 -8
- package/dist/prod/core/async.js +251 -143
- package/dist/prod/core/constants.js +34 -1
- package/dist/prod/core/context.js +3 -3
- package/dist/prod/core/core.js +843 -347
- package/dist/prod/core/dev.js +17 -1
- package/dist/prod/core/effect.js +48 -34
- package/dist/prod/core/error-hooks.js +71 -0
- package/dist/prod/core/external.js +4 -4
- package/dist/prod/core/graph.js +37 -37
- package/dist/prod/core/heap.js +45 -45
- package/dist/prod/core/lanes.js +90 -53
- package/dist/prod/core/optimistic.js +247 -100
- package/dist/prod/core/owner.js +57 -45
- package/dist/prod/core/scheduler.js +543 -305
- package/dist/prod/core/verdict.js +245 -127
- package/dist/prod/index.js +7 -3
- package/dist/prod/map.js +112 -112
- package/dist/prod/signals.js +28 -12
- package/dist/prod/store/next/optimistic.js +135 -128
- package/dist/prod/store/next/projection.js +31 -20
- package/dist/prod/store/next/store.js +325 -252
- package/dist/prod/store/store.js +2 -2
- package/dist/prod/store/utils.js +946 -135
- package/dist/types/attribution.d.ts +7 -2
- package/dist/types/attribution.prod.d.ts +10 -1
- package/dist/types/boundaries.d.ts +10 -1
- package/dist/types/core/action.d.ts +12 -5
- package/dist/types/core/attribution-costs.d.ts +35 -0
- package/dist/types/core/attribution-feedback.d.ts +133 -0
- package/dist/types/core/attribution-hooks.d.ts +28 -3
- package/dist/types/core/attribution-queries.d.ts +10 -0
- package/dist/types/core/attribution.d.ts +51 -172
- package/dist/types/core/constants.d.ts +33 -0
- package/dist/types/core/core.d.ts +186 -5
- package/dist/types/core/dev.d.ts +129 -9
- package/dist/types/core/error-hooks.d.ts +71 -0
- package/dist/types/core/index.d.ts +3 -1
- package/dist/types/core/invariants.d.ts +4 -0
- package/dist/types/core/lanes.d.ts +31 -4
- package/dist/types/core/scheduler.d.ts +95 -2
- package/dist/types/core/types.d.ts +3 -0
- package/dist/types/index.d.ts +2 -2
- package/dist/types/signals.d.ts +8 -0
- package/dist/types/store/index.d.ts +2 -1
- package/dist/types/store/next/optimistic.d.ts +1 -1
- package/dist/types/store/next/store.d.ts +6 -5
- package/dist/types/store/next/target.d.ts +1 -1
- package/dist/types/store/utils.d.ts +177 -6
- package/package.json +1 -1
package/dist/prod/map.js
CHANGED
|
@@ -25,23 +25,23 @@ function mapArray(t, s, i) {
|
|
|
25
25
|
const r = s.length > 1;
|
|
26
26
|
const n = s;
|
|
27
27
|
const o = {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
28
|
+
se: createOwner(),
|
|
29
|
+
ts: 0,
|
|
30
|
+
ss: t,
|
|
31
|
+
es: [],
|
|
32
|
+
rs: n,
|
|
33
|
+
ns: [],
|
|
33
34
|
hs: [],
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
cs:
|
|
37
|
-
ls:
|
|
38
|
-
us: i?.
|
|
39
|
-
ps: i?.fallback
|
|
35
|
+
qt: e,
|
|
36
|
+
fs: e || i?.keyed === false ? [] : undefined,
|
|
37
|
+
cs: r && i?.keyed !== false ? [] : undefined,
|
|
38
|
+
ls: i?.keyed === false,
|
|
39
|
+
us: i?.fallback
|
|
40
40
|
};
|
|
41
41
|
const h = computed(updateKeyedMap.bind(o), undefined);
|
|
42
42
|
// Untracked reads inside the internal owner resolve via _parentComputed; routing
|
|
43
43
|
// them through node lets store-proxy lookups see pending writes (not stale _value).
|
|
44
|
-
o.
|
|
44
|
+
o.se.Qt = h;
|
|
45
45
|
h.T &= ~CONFIG_AUTO_DISPOSE;
|
|
46
46
|
return accessor(h);
|
|
47
47
|
}
|
|
@@ -51,8 +51,8 @@ const pureOptions = {
|
|
|
51
51
|
};
|
|
52
52
|
|
|
53
53
|
function trySmallMove(t, s, i, e) {
|
|
54
|
-
const r = t.
|
|
55
|
-
const n = t.
|
|
54
|
+
const r = t.es;
|
|
55
|
+
const n = t.ts - 1;
|
|
56
56
|
const o = [];
|
|
57
57
|
const h = [];
|
|
58
58
|
const f = [];
|
|
@@ -124,7 +124,7 @@ function trySmallMove(t, s, i, e) {
|
|
|
124
124
|
* body. Pairs displaced sources with destinations (an unmatched destination
|
|
125
125
|
* is a replacement/insertion → general path), then commits: slice() the live
|
|
126
126
|
* arrays, copy shifted runs, patch displaced pairs, dispose leftovers. */ function commitSmallMove(t, s, i, e, r, n) {
|
|
127
|
-
const o = t.
|
|
127
|
+
const o = t.es;
|
|
128
128
|
let h;
|
|
129
129
|
let f;
|
|
130
130
|
let c;
|
|
@@ -159,8 +159,8 @@ function trySmallMove(t, s, i, e) {
|
|
|
159
159
|
for (let e = 0, r = n[s + 2]; e < r; e++) if (t.has(o[i + e])) return false;
|
|
160
160
|
}
|
|
161
161
|
}
|
|
162
|
-
const a = t.
|
|
163
|
-
const l = t.
|
|
162
|
+
const a = t.ns;
|
|
163
|
+
const l = t.hs;
|
|
164
164
|
const u = a.slice(0, i);
|
|
165
165
|
const p = l.slice(0, i);
|
|
166
166
|
for (let t = 0; t < n.length; t += 3) {
|
|
@@ -179,10 +179,10 @@ function trySmallMove(t, s, i, e) {
|
|
|
179
179
|
u[t] = a[s];
|
|
180
180
|
p[t] = l[s];
|
|
181
181
|
}
|
|
182
|
-
t.
|
|
183
|
-
t.
|
|
184
|
-
t.
|
|
185
|
-
t.
|
|
182
|
+
t.ns = u;
|
|
183
|
+
t.hs = p;
|
|
184
|
+
t.ts = i;
|
|
185
|
+
t.es = s.slice(0);
|
|
186
186
|
// Dispose unmatched sources LAST (general-path ordering).
|
|
187
187
|
for (h = 0; h < e.length; h++) {
|
|
188
188
|
if (c === undefined || !c[h]) l[e[h]].dispose();
|
|
@@ -191,52 +191,52 @@ function trySmallMove(t, s, i, e) {
|
|
|
191
191
|
}
|
|
192
192
|
|
|
193
193
|
function updateKeyedMap() {
|
|
194
|
-
const t = this.
|
|
194
|
+
const t = this.ss() || [], s = t.length;
|
|
195
195
|
t[$TRACK];
|
|
196
196
|
// top level tracking
|
|
197
|
-
runWithOwner(this.
|
|
197
|
+
runWithOwner(this.se, () => {
|
|
198
198
|
let i, e, r, n,
|
|
199
199
|
// Mappers write freshly-created row/index signals into the STAGE
|
|
200
200
|
// arrays (`rows`/`indexes`), never into `this._rows`/`this._indexes`.
|
|
201
|
-
o = this.
|
|
201
|
+
o = this.fs ? this.ls ? () => {
|
|
202
202
|
r[e] = signal(t[e], pureOptions);
|
|
203
|
-
return this.
|
|
203
|
+
return this.rs(accessor(r[e]), e);
|
|
204
204
|
} : () => {
|
|
205
205
|
r[e] = signal(t[e], pureOptions);
|
|
206
206
|
n && (n[e] = signal(e, pureOptions));
|
|
207
|
-
return this.
|
|
208
|
-
} : this.
|
|
207
|
+
return this.rs(accessor(r[e]), n ? accessor(n[e]) : undefined);
|
|
208
|
+
} : this.cs ? () => {
|
|
209
209
|
const s = t[e];
|
|
210
210
|
n[e] = signal(e, pureOptions);
|
|
211
|
-
return this.
|
|
211
|
+
return this.rs(s, accessor(n[e]));
|
|
212
212
|
} : () => {
|
|
213
213
|
const s = t[e];
|
|
214
|
-
return this.
|
|
214
|
+
return this.rs(s);
|
|
215
215
|
};
|
|
216
216
|
// fast path for empty arrays
|
|
217
217
|
if (s === 0) {
|
|
218
|
-
if (this.
|
|
219
|
-
this.
|
|
220
|
-
this.fs = [];
|
|
221
|
-
this.rs = [];
|
|
218
|
+
if (this.ts !== 0) {
|
|
219
|
+
this.se.dispose(false);
|
|
222
220
|
this.hs = [];
|
|
223
|
-
this.
|
|
221
|
+
this.es = [];
|
|
222
|
+
this.ns = [];
|
|
223
|
+
this.ts = 0;
|
|
224
|
+
this.fs && (this.fs = []);
|
|
224
225
|
this.cs && (this.cs = []);
|
|
225
|
-
this.ls && (this.ls = []);
|
|
226
226
|
}
|
|
227
|
-
if (this.
|
|
227
|
+
if (this.us && !this.ns[0]) {
|
|
228
228
|
// an aborted fallback attempt leaves an owner without a mapping;
|
|
229
229
|
// dispose it before re-creating
|
|
230
|
-
this.
|
|
231
|
-
this.
|
|
230
|
+
this.hs[0]?.dispose();
|
|
231
|
+
this.ns[0] = runWithOwner(this.hs[0] = createOwner(), this.us);
|
|
232
232
|
}
|
|
233
233
|
}
|
|
234
234
|
// fast path for new create
|
|
235
|
-
else if (this.
|
|
235
|
+
else if (this.ts === 0) {
|
|
236
236
|
const h = new Array(s);
|
|
237
237
|
const f = new Array(s);
|
|
238
|
-
r = this.
|
|
239
|
-
n = this.
|
|
238
|
+
r = this.fs && new Array(s);
|
|
239
|
+
n = this.cs && new Array(s);
|
|
240
240
|
try {
|
|
241
241
|
for (e = 0; e < s; e++) h[e] = runWithOwner(f[e] = createOwner(), o);
|
|
242
242
|
} catch (t) {
|
|
@@ -244,32 +244,32 @@ function updateKeyedMap() {
|
|
|
244
244
|
throw t;
|
|
245
245
|
}
|
|
246
246
|
// commit
|
|
247
|
-
if (this.
|
|
247
|
+
if (this.hs[0]) this.hs[0].dispose();
|
|
248
248
|
// previous fallback
|
|
249
|
-
this.
|
|
250
|
-
this.
|
|
251
|
-
r && (this.
|
|
252
|
-
n && (this.
|
|
253
|
-
this.
|
|
254
|
-
this.
|
|
249
|
+
this.ns = h;
|
|
250
|
+
this.hs = f;
|
|
251
|
+
r && (this.fs = r);
|
|
252
|
+
n && (this.cs = n);
|
|
253
|
+
this.es = t.slice(0);
|
|
254
|
+
this.ts = s;
|
|
255
255
|
} else {
|
|
256
256
|
let h, f, c, a, l, u, p, d, w,
|
|
257
257
|
// Dev (attribution engine installed): the items behind the exited and
|
|
258
258
|
// entered rows, for the list-identity census.
|
|
259
259
|
m, O;
|
|
260
260
|
// skip common prefix
|
|
261
|
-
for (h = 0, f = Math.min(this.
|
|
262
|
-
if (this.
|
|
261
|
+
for (h = 0, f = Math.min(this.ts, s); h < f && (this.es[h] === t[h] || this.fs && compare(this.qt, this.es[h], t[h])); h++) {
|
|
262
|
+
if (this.fs) setSignal(this.fs[h], t[h]);
|
|
263
263
|
}
|
|
264
264
|
// skip common suffix — counted only; retained entries land in one pass
|
|
265
265
|
// at commit instead of being staged and copied twice
|
|
266
|
-
for (f = this.
|
|
266
|
+
for (f = this.ts - 1, c = s - 1; f >= h && c >= h && (this.es[f] === t[c] || this.fs && compare(this.qt, this.es[f], t[c])); f--,
|
|
267
267
|
c--) ;
|
|
268
268
|
// no structural change (every position matched in place at equal
|
|
269
269
|
// length — the common post-reconcile shape): keep the same mapped
|
|
270
270
|
// array identity so downstream consumers don't re-run at all
|
|
271
|
-
if (h === s && this.
|
|
272
|
-
this.
|
|
271
|
+
if (h === s && this.ts === s) {
|
|
272
|
+
this.es = t.slice(0);
|
|
273
273
|
return;
|
|
274
274
|
}
|
|
275
275
|
// SMALL-MOVE FAST PATH: extracted to its own function — inlining it
|
|
@@ -279,7 +279,7 @@ function updateKeyedMap() {
|
|
|
279
279
|
// (plain removals, tail edits), the general path is window-
|
|
280
280
|
// proportional and cheap — the fast path would only re-walk what the
|
|
281
281
|
// trims proved.
|
|
282
|
-
if (s <= this.
|
|
282
|
+
if (s <= this.ts && f - h > 64 && this.fs === undefined && this.cs === undefined) {
|
|
283
283
|
// PROBE before the scan: a small move keeps a mid-window item within
|
|
284
284
|
// ±32 of its old position; a REPLACE (all fresh items — the shape
|
|
285
285
|
// every page's first structural pass usually is) has it nowhere.
|
|
@@ -289,21 +289,21 @@ function updateKeyedMap() {
|
|
|
289
289
|
const e = t[i];
|
|
290
290
|
const r = Math.min(f, i + 32);
|
|
291
291
|
let n = Math.max(h, i - 32);
|
|
292
|
-
while (n <= r && this.
|
|
292
|
+
while (n <= r && this.es[n] !== e) n++;
|
|
293
293
|
if (n <= r && trySmallMove(this, t, s, h)) return;
|
|
294
294
|
}
|
|
295
|
-
const _ = s - this.
|
|
295
|
+
const _ = s - this.ts;
|
|
296
296
|
const y = new Array(s);
|
|
297
297
|
const A = new Array(s);
|
|
298
|
-
r = this.
|
|
299
|
-
n = this.
|
|
298
|
+
r = this.fs ? new Array(s) : undefined;
|
|
299
|
+
n = this.cs ? new Array(s) : undefined;
|
|
300
300
|
// 0) prepare a map of all indices in the changed window of newItems,
|
|
301
301
|
// scanning backwards so we encounter them in natural order
|
|
302
302
|
u = new Map;
|
|
303
303
|
p = new Array(c + 1);
|
|
304
304
|
for (e = c; e >= h; e--) {
|
|
305
305
|
a = t[e];
|
|
306
|
-
l = this.
|
|
306
|
+
l = this.qt ? this.qt(a) : a;
|
|
307
307
|
i = u.get(l);
|
|
308
308
|
p[e] = i === undefined ? -1 : i;
|
|
309
309
|
u.set(l, e);
|
|
@@ -312,18 +312,18 @@ function updateKeyedMap() {
|
|
|
312
312
|
// in the new set; if so, stage them at their new positions; if not,
|
|
313
313
|
// queue them for disposal at commit
|
|
314
314
|
for (i = h; i <= f; i++) {
|
|
315
|
-
a = this.
|
|
316
|
-
l = this.
|
|
315
|
+
a = this.es[i];
|
|
316
|
+
l = this.qt ? this.qt(a) : a;
|
|
317
317
|
e = u.get(l);
|
|
318
318
|
if (e !== undefined && e !== -1) {
|
|
319
|
-
y[e] = this.
|
|
320
|
-
A[e] = this.
|
|
321
|
-
r && (r[e] = this.
|
|
322
|
-
n && (n[e] = this.
|
|
319
|
+
y[e] = this.ns[i];
|
|
320
|
+
A[e] = this.hs[i];
|
|
321
|
+
r && (r[e] = this.fs[i]);
|
|
322
|
+
n && (n[e] = this.cs[i]);
|
|
323
323
|
e = p[e];
|
|
324
324
|
u.set(l, e);
|
|
325
325
|
} else {
|
|
326
|
-
(d ??= []).push(this.
|
|
326
|
+
(d ??= []).push(this.hs[i]);
|
|
327
327
|
if (false && attrHooks !== null) ;
|
|
328
328
|
}
|
|
329
329
|
}
|
|
@@ -343,39 +343,39 @@ function updateKeyedMap() {
|
|
|
343
343
|
// into the fresh arrays, swap them in (new identity for downstream
|
|
344
344
|
// change propagation), then dispose exited rows
|
|
345
345
|
for (i = 0; i < h; i++) {
|
|
346
|
-
y[i] = this.
|
|
347
|
-
A[i] = this.
|
|
348
|
-
r && (r[i] = this.
|
|
349
|
-
n && (n[i] = this.
|
|
346
|
+
y[i] = this.ns[i];
|
|
347
|
+
A[i] = this.hs[i];
|
|
348
|
+
r && (r[i] = this.fs[i]);
|
|
349
|
+
n && (n[i] = this.cs[i]);
|
|
350
350
|
}
|
|
351
351
|
for (e = h; e <= c; e++) {
|
|
352
352
|
if (r) setSignal(r[e], t[e]);
|
|
353
353
|
if (n) setSignal(n[e], e);
|
|
354
354
|
}
|
|
355
355
|
for (e = c + 1; e < s; e++) {
|
|
356
|
-
y[e] = this.
|
|
357
|
-
A[e] = this.
|
|
356
|
+
y[e] = this.ns[e - _];
|
|
357
|
+
A[e] = this.hs[e - _];
|
|
358
358
|
if (r) {
|
|
359
|
-
r[e] = this.
|
|
359
|
+
r[e] = this.fs[e - _];
|
|
360
360
|
setSignal(r[e], t[e]);
|
|
361
361
|
}
|
|
362
362
|
if (n) {
|
|
363
|
-
n[e] = this.
|
|
363
|
+
n[e] = this.cs[e - _];
|
|
364
364
|
if (_ !== 0) setSignal(n[e], e);
|
|
365
365
|
}
|
|
366
366
|
}
|
|
367
|
-
this.
|
|
368
|
-
this.
|
|
369
|
-
r && (this.
|
|
370
|
-
n && (this.
|
|
371
|
-
this.
|
|
367
|
+
this.ns = y;
|
|
368
|
+
this.hs = A;
|
|
369
|
+
r && (this.fs = r);
|
|
370
|
+
n && (this.cs = n);
|
|
371
|
+
this.ts = s;
|
|
372
372
|
// save a copy of the mapped items for the next update
|
|
373
|
-
this.
|
|
373
|
+
this.es = t.slice(0);
|
|
374
374
|
if (d) for (i = 0; i < d.length; i++) d[i].dispose();
|
|
375
375
|
if (false && attrHooks !== null && m !== undefined && O !== undefined) ;
|
|
376
376
|
}
|
|
377
377
|
});
|
|
378
|
-
return this.
|
|
378
|
+
return this.ns;
|
|
379
379
|
}
|
|
380
380
|
|
|
381
381
|
/**
|
|
@@ -395,21 +395,21 @@ function updateKeyedMap() {
|
|
|
395
395
|
*/ function repeat(t, s, i) {
|
|
396
396
|
const e = s;
|
|
397
397
|
const r = {
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
fs: [],
|
|
398
|
+
se: createOwner(),
|
|
399
|
+
ts: 0,
|
|
400
|
+
ps: 0,
|
|
401
|
+
ds: t,
|
|
402
|
+
rs: e,
|
|
404
403
|
hs: [],
|
|
405
|
-
|
|
406
|
-
|
|
404
|
+
ns: [],
|
|
405
|
+
ws: i?.from,
|
|
406
|
+
us: i?.fallback
|
|
407
407
|
};
|
|
408
408
|
const n = computed(updateRepeat.bind(r));
|
|
409
409
|
// Same as mapArray: untracked reads inside the internal owner resolve via
|
|
410
410
|
// _parentComputed, so async reads in row callbacks register with the node
|
|
411
411
|
// (pending tracking + post-settle retry) instead of vanishing.
|
|
412
|
-
r.
|
|
412
|
+
r.se.Qt = n;
|
|
413
413
|
n.T &= ~CONFIG_AUTO_DISPOSE;
|
|
414
414
|
return accessor(n);
|
|
415
415
|
}
|
|
@@ -422,55 +422,55 @@ function updateKeyedMap() {
|
|
|
422
422
|
// for the post-settle retry. The overlap math also subsumes the previous
|
|
423
423
|
// disjoint-window/front-clear/end-clear/shift special cases.
|
|
424
424
|
function updateRepeat() {
|
|
425
|
-
const t = this.
|
|
426
|
-
const s = this.
|
|
427
|
-
runWithOwner(this.
|
|
425
|
+
const t = this.ds();
|
|
426
|
+
const s = this.ws?.() || 0;
|
|
427
|
+
runWithOwner(this.se, () => {
|
|
428
428
|
if (t === 0) {
|
|
429
|
-
if (this.
|
|
430
|
-
this.
|
|
431
|
-
this.fs = [];
|
|
429
|
+
if (this.ts !== 0) {
|
|
430
|
+
this.se.dispose(false);
|
|
432
431
|
this.hs = [];
|
|
433
|
-
this.
|
|
432
|
+
this.ns = [];
|
|
433
|
+
this.ts = 0;
|
|
434
434
|
// Reset offset to match the cleared data (#2767, repro 2).
|
|
435
|
-
this.
|
|
435
|
+
this.ps = 0;
|
|
436
436
|
}
|
|
437
|
-
if (this.
|
|
437
|
+
if (this.us && !this.ns[0]) {
|
|
438
438
|
// an aborted fallback attempt leaves an owner without a mapping;
|
|
439
439
|
// dispose it before re-creating
|
|
440
|
-
this.
|
|
441
|
-
this.
|
|
440
|
+
this.hs[0]?.dispose();
|
|
441
|
+
this.ns[0] = runWithOwner(this.hs[0] = createOwner(), this.us);
|
|
442
442
|
}
|
|
443
443
|
return;
|
|
444
444
|
}
|
|
445
445
|
const i = s + t;
|
|
446
|
-
const e = this.
|
|
446
|
+
const e = this.ps + this.ts;
|
|
447
447
|
// Retained overlap [keepStart, keepEnd) in global indexes; empty when the
|
|
448
448
|
// windows are disjoint or when coming from empty/fallback.
|
|
449
|
-
const r = Math.max(s, this.
|
|
449
|
+
const r = Math.max(s, this.ps);
|
|
450
450
|
const n = Math.min(i, e);
|
|
451
451
|
const o = new Array(t);
|
|
452
452
|
const h = new Array(t);
|
|
453
453
|
for (let t = r; t < n; t++) {
|
|
454
|
-
h[t - s] = this.
|
|
455
|
-
o[t - s] = this.
|
|
454
|
+
h[t - s] = this.hs[t - this.ps];
|
|
455
|
+
o[t - s] = this.ns[t - this.ps];
|
|
456
456
|
}
|
|
457
457
|
try {
|
|
458
458
|
for (let t = s; t < i; t++) {
|
|
459
459
|
if (t >= r && t < n) continue;
|
|
460
|
-
o[t - s] = runWithOwner(h[t - s] = createOwner(), () => this.
|
|
460
|
+
o[t - s] = runWithOwner(h[t - s] = createOwner(), () => this.rs(t));
|
|
461
461
|
}
|
|
462
462
|
} catch (t) {
|
|
463
463
|
for (let t = s; t < i; t++) if ((t < r || t >= n) && h[t - s]) h[t - s].dispose();
|
|
464
464
|
throw t;
|
|
465
465
|
}
|
|
466
466
|
// commit: dispose the previous fallback or the rows leaving the window
|
|
467
|
-
if (this.
|
|
468
|
-
this.
|
|
469
|
-
this.
|
|
470
|
-
this.
|
|
471
|
-
this.
|
|
467
|
+
if (this.ts === 0) this.hs[0]?.dispose(); else for (let t = this.ps; t < e; t++) if (t < s || t >= i) this.hs[t - this.ps].dispose();
|
|
468
|
+
this.ns = o;
|
|
469
|
+
this.hs = h;
|
|
470
|
+
this.ps = s;
|
|
471
|
+
this.ts = t;
|
|
472
472
|
});
|
|
473
|
-
return this.
|
|
473
|
+
return this.ns;
|
|
474
474
|
}
|
|
475
475
|
|
|
476
476
|
function compare(t, s, i) {
|
package/dist/prod/signals.js
CHANGED
|
@@ -4,7 +4,7 @@ import { computed, optimisticComputed, setSignal, optimisticSignal, runWithOwner
|
|
|
4
4
|
|
|
5
5
|
import { cleanup, createRoot, getOwner, dispose, getObserver } from "./core/owner.js";
|
|
6
6
|
|
|
7
|
-
import { globalQueue, Queue, entangleConfirmingTransitions, activeTransition } from "./core/scheduler.js";
|
|
7
|
+
import { globalQueue, dirtyQueue, Queue, entangleConfirmingTransitions, activeTransition } from "./core/scheduler.js";
|
|
8
8
|
|
|
9
9
|
import { CONFIG_AUTO_DISPOSE, CONFIG_CHILDREN_FORBIDDEN, EFFECT_USER, $REFRESH, CONFIG_DIRECT_COMMIT, CONFIG_AUTHORITATIVE_READ, CONFIG_FRESH_READ } from "./core/constants.js";
|
|
10
10
|
|
|
@@ -327,7 +327,7 @@ function createMemo(e, t) {
|
|
|
327
327
|
// route through the inherited queue.
|
|
328
328
|
const i = getOwner();
|
|
329
329
|
const o = new MicrotaskQueue;
|
|
330
|
-
o.
|
|
330
|
+
o._parent = i.C;
|
|
331
331
|
// notify() forwards up the normal chain
|
|
332
332
|
i.C = o;
|
|
333
333
|
// A user effect rather than a bare computed: computeds are pull-based and
|
|
@@ -349,7 +349,7 @@ function createMemo(e, t) {
|
|
|
349
349
|
// stale mainline value and resolves with old data.
|
|
350
350
|
{
|
|
351
351
|
user: true,
|
|
352
|
-
|
|
352
|
+
kt: CONFIG_DIRECT_COMMIT
|
|
353
353
|
});
|
|
354
354
|
});
|
|
355
355
|
});
|
|
@@ -442,7 +442,7 @@ function createMemo(e, t) {
|
|
|
442
442
|
if (i === null) {
|
|
443
443
|
i = getOwner();
|
|
444
444
|
const e = new MicrotaskQueue;
|
|
445
|
-
e.
|
|
445
|
+
e._parent = i.C;
|
|
446
446
|
i.C = e;
|
|
447
447
|
}
|
|
448
448
|
return read(t);
|
|
@@ -454,7 +454,7 @@ function createMemo(e, t) {
|
|
|
454
454
|
dispose(i);
|
|
455
455
|
}, {
|
|
456
456
|
user: true,
|
|
457
|
-
|
|
457
|
+
kt: CONFIG_DIRECT_COMMIT | CONFIG_AUTHORITATIVE_READ | CONFIG_FRESH_READ
|
|
458
458
|
});
|
|
459
459
|
make();
|
|
460
460
|
});
|
|
@@ -505,12 +505,20 @@ function createMemo(e, t) {
|
|
|
505
505
|
*
|
|
506
506
|
* Must be called *outside* a tracking scope.
|
|
507
507
|
*
|
|
508
|
+
* Inside an action, call it from a step: after an `await`, put a bare `yield`
|
|
509
|
+
* before `yield until(...)`. The runtime cannot hook an async generator's
|
|
510
|
+
* `await` continuation, so the `until(...)` expression — which CREATES the
|
|
511
|
+
* predicate's reader — would otherwise run outside the transaction; created
|
|
512
|
+
* there it is born held (A29) and replays only at the commit its own promise
|
|
513
|
+
* holds open (#3482). See {@link action}.
|
|
514
|
+
*
|
|
508
515
|
* @example
|
|
509
516
|
* ```ts
|
|
510
517
|
* const send = action(async function* (text: string) {
|
|
511
518
|
* const clientId = crypto.randomUUID();
|
|
512
519
|
* setMessages(m => { m.push({ clientId, text, pending: true }); }); // optimistic
|
|
513
520
|
* await socket.send({ clientId, text }); // fire-and-forget transport
|
|
521
|
+
* yield; // re-enter the transaction after the await
|
|
514
522
|
* // Hold until the live source echoes the write (authoritative view —
|
|
515
523
|
* // the optimistic row above cannot satisfy this):
|
|
516
524
|
* yield until(() => messages.some(m => m.clientId === clientId), { timeout: 10_000 });
|
|
@@ -537,10 +545,10 @@ function createMemo(e, t) {
|
|
|
537
545
|
// microtask so the promise can settle while the transaction the caller
|
|
538
546
|
// yielded it into is still open — that transaction being open is the
|
|
539
547
|
// entire point of the hold.
|
|
540
|
-
const
|
|
541
|
-
const
|
|
542
|
-
|
|
543
|
-
|
|
548
|
+
const u = getOwner();
|
|
549
|
+
const s = new MicrotaskQueue;
|
|
550
|
+
s._parent = u.C;
|
|
551
|
+
u.C = s;
|
|
544
552
|
let f;
|
|
545
553
|
let a;
|
|
546
554
|
const settle = e => {
|
|
@@ -569,7 +577,7 @@ function createMemo(e, t) {
|
|
|
569
577
|
// the hold itself is keeping uncommitted.
|
|
570
578
|
{
|
|
571
579
|
user: true,
|
|
572
|
-
|
|
580
|
+
kt: CONFIG_AUTHORITATIVE_READ | CONFIG_DIRECT_COMMIT
|
|
573
581
|
});
|
|
574
582
|
if (t?.timeout !== undefined) f = setTimeout(() => settle(() => i(new TimeoutError)), t.timeout);
|
|
575
583
|
if (o !== undefined) {
|
|
@@ -691,12 +699,20 @@ function createOptimistic(e, t) {
|
|
|
691
699
|
* on owner disposal
|
|
692
700
|
*/ function onSettled(e) {
|
|
693
701
|
const t = getOwner();
|
|
694
|
-
t && !(t.T & CONFIG_CHILDREN_FORBIDDEN) ? trackedEffect(() => untrack(e), undefined) : globalQueue.enqueue(EFFECT_USER, ()
|
|
702
|
+
t && !(t.T & CONFIG_CHILDREN_FORBIDDEN) ? trackedEffect(() => untrack(e), undefined) : globalQueue.enqueue(EFFECT_USER, function fire() {
|
|
703
|
+
// Settled means derived. A settle that reverts optimism (or replays
|
|
704
|
+
// gated reads) only enqueues the affected subscribers; the pass after
|
|
705
|
+
// the commit re-derives them. Fired in the commit pass, the callback
|
|
706
|
+
// read the optimistic source already reverted beside a sync memo of it
|
|
707
|
+
// still holding the optimistic value — reads do not pull (#3411). Fall
|
|
708
|
+
// to the next pass while the heap has work; `run` swapped the queue,
|
|
709
|
+
// so this lands there, and `enqueue` keeps the drain alive.
|
|
710
|
+
if (dirtyQueue.EE >= dirtyQueue.et) return globalQueue.enqueue(EFFECT_USER, fire);
|
|
695
711
|
// Unowned, out-of-band fire (no owner, or a children-forbidden one this
|
|
696
712
|
// one-shot must not bind to): a returned cleanup has no lifecycle to
|
|
697
713
|
// attach to. Reject it in dev; in production the return is simply
|
|
698
714
|
// dropped — never bound to an unrelated owner or run eagerly.
|
|
699
|
-
|
|
715
|
+
e();
|
|
700
716
|
});
|
|
701
717
|
}
|
|
702
718
|
|