@solidjs/signals 2.0.0-beta.22 → 2.0.0-beta.24
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.js +199 -68
- package/dist/node.cjs +1138 -996
- package/dist/prod/core/async.js +27 -11
- package/dist/prod/core/core.js +33 -30
- package/dist/prod/core/effect.js +3 -3
- package/dist/prod/core/error.js +9 -0
- package/dist/prod/core/graph.js +7 -2
- package/dist/prod/core/heap.js +12 -12
- package/dist/prod/core/lanes.js +2 -2
- package/dist/prod/core/optimistic.js +5 -5
- package/dist/prod/core/owner.js +1 -1
- package/dist/prod/core/scheduler.js +11 -11
- package/dist/prod/core/verdict.js +30 -30
- package/dist/prod/map.js +53 -29
- package/dist/prod/store/optimistic.js +31 -29
- package/dist/prod/store/reconcile.js +92 -61
- package/dist/prod/store/store.js +143 -103
- package/dist/prod/store/utils.js +12 -0
- package/dist/types/core/error.d.ts +1 -1
- package/dist/types/store/reconcile.d.ts +17 -8
- package/dist/types-cjs/core/error.d.cts +1 -1
- package/dist/types-cjs/store/reconcile.d.cts +17 -8
- package/package.json +1 -1
package/dist/prod/core/async.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { STATUS_UNINITIALIZED, STATUS_ERROR, STATUS_PENDING, REACTIVE_DIRTY, REACTIVE_OPTIMISTIC_DIRTY, NOT_PENDING } from "./constants.js";
|
|
1
|
+
import { STATUS_UNINITIALIZED, STATUS_ERROR, STATUS_PENDING, REACTIVE_DIRTY, REACTIVE_OPTIMISTIC_DIRTY, NOT_PENDING, CONFIG_AUTO_DISPOSE } from "./constants.js";
|
|
2
2
|
|
|
3
3
|
import { untrack, context, setSignal } from "./core.js";
|
|
4
4
|
|
|
@@ -6,7 +6,7 @@ import "./invariants.js";
|
|
|
6
6
|
|
|
7
7
|
import { NotReadyError, StatusError } from "./error.js";
|
|
8
8
|
|
|
9
|
-
import { trimStaleDeps } from "./graph.js";
|
|
9
|
+
import { trimStaleDeps, unobserved } from "./graph.js";
|
|
10
10
|
|
|
11
11
|
import { enqueueSub } from "./heap.js";
|
|
12
12
|
|
|
@@ -160,11 +160,11 @@ function handleAsync(e, n, r) {
|
|
|
160
160
|
} else if (l) {
|
|
161
161
|
// Route through lane's effect queue for independent flushing
|
|
162
162
|
const n = e.Ae;
|
|
163
|
-
const r = e.
|
|
164
|
-
const o = e.
|
|
163
|
+
const r = e.Pe;
|
|
164
|
+
const o = e.Re;
|
|
165
165
|
try {
|
|
166
166
|
if (!n && u || !o || !o(t, r)) {
|
|
167
|
-
e.
|
|
167
|
+
e.Pe = t;
|
|
168
168
|
e.ce = clock;
|
|
169
169
|
// The latest() shadow write gives latest() effects independent lanes; the
|
|
170
170
|
// _pendingSignal update is a no-op repeat of the clearStatus() call above
|
|
@@ -193,18 +193,34 @@ function handleAsync(e, n, r) {
|
|
|
193
193
|
flush();
|
|
194
194
|
o?.();
|
|
195
195
|
};
|
|
196
|
+
// A pending node's in-flight promise is an observer: `unlinkSubs` skips
|
|
197
|
+
// autodispose while STATUS_PENDING so subscriber churn can't orphan the
|
|
198
|
+
// work (a lazy async memo would otherwise tear down and re-execute — one
|
|
199
|
+
// fetch per suspended re-read). Settling is that observer's release, so
|
|
200
|
+
// it runs the same last-one-out check the other release sites run.
|
|
201
|
+
const settleAutodispose = () => {
|
|
202
|
+
if (e.T & CONFIG_AUTO_DISPOSE && !e.o && !(e.S & STATUS_PENDING)) {
|
|
203
|
+
unobserved(e);
|
|
204
|
+
}
|
|
205
|
+
};
|
|
196
206
|
if (o) {
|
|
197
207
|
let r = false, t = false, o, l = true;
|
|
198
208
|
n.then(e => {
|
|
199
209
|
if (l) {
|
|
200
210
|
u = e;
|
|
201
211
|
r = true;
|
|
202
|
-
} else
|
|
212
|
+
} else {
|
|
213
|
+
asyncWrite(e);
|
|
214
|
+
settleAutodispose();
|
|
215
|
+
}
|
|
203
216
|
}, e => {
|
|
204
217
|
if (l) {
|
|
205
218
|
o = e;
|
|
206
219
|
t = true;
|
|
207
|
-
} else
|
|
220
|
+
} else {
|
|
221
|
+
handleError(e);
|
|
222
|
+
settleAutodispose();
|
|
223
|
+
}
|
|
208
224
|
});
|
|
209
225
|
l = false;
|
|
210
226
|
if (t) {
|
|
@@ -294,13 +310,13 @@ function clearStatus(e, n = false) {
|
|
|
294
310
|
// The pending window is over; its quiet classification dies with it.
|
|
295
311
|
// (Unconditional: _reask is baked into the node literals, so this is a
|
|
296
312
|
// plain store to an existing slot — no shape change.)
|
|
297
|
-
e.
|
|
313
|
+
e._e = false;
|
|
298
314
|
e.S = n ? 0 : e.S & STATUS_UNINITIALIZED;
|
|
299
315
|
if (e._) setPendingError(e);
|
|
300
316
|
// Update pending signal for isPending() reactivity (companions only exist
|
|
301
317
|
// once the verdict layer created them, which installs the hooks).
|
|
302
|
-
if (e.
|
|
303
|
-
if (e.u && GlobalQueue.
|
|
318
|
+
if (e.be || e.ge) GlobalQueue.ae(e);
|
|
319
|
+
if (e.u && GlobalQueue.he !== null) GlobalQueue.he(e);
|
|
304
320
|
if (e.i) e.i();
|
|
305
321
|
}
|
|
306
322
|
|
|
@@ -324,7 +340,7 @@ function notifyStatus(e, n, r, t, o) {
|
|
|
324
340
|
e._ = r;
|
|
325
341
|
}
|
|
326
342
|
GlobalQueue.ae !== null && GlobalQueue.ae(e);
|
|
327
|
-
if (e.u && GlobalQueue.
|
|
343
|
+
if (e.u && GlobalQueue.he !== null) GlobalQueue.he(e);
|
|
328
344
|
}
|
|
329
345
|
if (o && !t) {
|
|
330
346
|
assignOrMergeLane(e, o);
|
package/dist/prod/core/core.js
CHANGED
|
@@ -82,7 +82,7 @@ function releaseSubtree(e) {
|
|
|
82
82
|
if (e.se & REACTIVE_SNAPSHOT_STALE) {
|
|
83
83
|
e.se &= ~REACTIVE_SNAPSHOT_STALE;
|
|
84
84
|
e.se |= REACTIVE_DIRTY;
|
|
85
|
-
if (dirtyQueue.
|
|
85
|
+
if (dirtyQueue.He > e.Fe) dirtyQueue.He = e.Fe;
|
|
86
86
|
insertIntoHeap(e, dirtyQueue);
|
|
87
87
|
}
|
|
88
88
|
}
|
|
@@ -95,7 +95,10 @@ function clearSnapshots() {
|
|
|
95
95
|
if (snapshotSources) {
|
|
96
96
|
for (const e of snapshotSources) {
|
|
97
97
|
delete e.Ve;
|
|
98
|
-
|
|
98
|
+
// StoreNode targets share one pre-initialized hidden class (see
|
|
99
|
+
// createStoreProxy) — assign undefined instead of deleting, and only
|
|
100
|
+
// when present so signal-node sources don't grow the field.
|
|
101
|
+
if (e[STORE_SNAPSHOT_PROPS] !== undefined) e[STORE_SNAPSHOT_PROPS] = undefined;
|
|
99
102
|
}
|
|
100
103
|
snapshotSources = null;
|
|
101
104
|
}
|
|
@@ -130,8 +133,8 @@ function recompute(e, t = false) {
|
|
|
130
133
|
e.Ye++;
|
|
131
134
|
e.se = REACTIVE_RECOMPUTING_DEPS;
|
|
132
135
|
e.ce = clock;
|
|
133
|
-
let a = e.Ne === NOT_PENDING ? e.
|
|
134
|
-
let r = e.
|
|
136
|
+
let a = e.Ne === NOT_PENDING ? e.Pe : e.Ne;
|
|
137
|
+
let r = e.Fe;
|
|
135
138
|
let c = tracking;
|
|
136
139
|
let _ = currentOptimisticLane;
|
|
137
140
|
tracking = true;
|
|
@@ -202,10 +205,10 @@ function recompute(e, t = false) {
|
|
|
202
205
|
}
|
|
203
206
|
if (!e._) {
|
|
204
207
|
trimStaleDeps(e);
|
|
205
|
-
const o = l ? unwrapOverride(e.Ee) : e.Ne === NOT_PENDING ? e.
|
|
208
|
+
const o = l ? unwrapOverride(e.Ee) : e.Ne === NOT_PENDING ? e.Pe : e.Ne;
|
|
206
209
|
let s = false;
|
|
207
210
|
try {
|
|
208
|
-
s = !n && u || !e.
|
|
211
|
+
s = !n && u || !e.Re || !e.Re(o, a);
|
|
209
212
|
} catch (t) {
|
|
210
213
|
// A throwing user comparator is an error of this node's computation.
|
|
211
214
|
// Route it through the same status path as a compute-phase throw so
|
|
@@ -227,7 +230,7 @@ function recompute(e, t = false) {
|
|
|
227
230
|
if (e._) ; else if (s) {
|
|
228
231
|
const u = l ? e.Ee : undefined;
|
|
229
232
|
if (t || n && activeTransition !== e.Ue || i) {
|
|
230
|
-
e.
|
|
233
|
+
e.Pe = a;
|
|
231
234
|
// Lane-propagated correction: upstream data is fresh, correct the
|
|
232
235
|
// override unconditionally. The direct _value commit is the lane's
|
|
233
236
|
// own reveal schedule; drop any superseded older hold so its queued
|
|
@@ -252,7 +255,7 @@ function recompute(e, t = false) {
|
|
|
252
255
|
// for commit on its own transition's schedule — invisibly (A17/A18).
|
|
253
256
|
if (e.Ne === NOT_PENDING) queuePendingNode(e);
|
|
254
257
|
e.Ne = a;
|
|
255
|
-
} else if (e.
|
|
258
|
+
} else if (e.Fe != r) {
|
|
256
259
|
for (let t = e.o; t !== null; t = t.ue) {
|
|
257
260
|
insertIntoHeapHeight(t.le, queueFor(t.le));
|
|
258
261
|
}
|
|
@@ -293,15 +296,15 @@ function computed(e, t) {
|
|
|
293
296
|
const i = {
|
|
294
297
|
id: inheritId(t, n, context),
|
|
295
298
|
T: (n ? CONFIG_TRANSPARENT : 0) | (t?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (!context || t?.lazy ? CONFIG_AUTO_DISPOSE : 0) | (t?.sync ? CONFIG_SYNC : 0) | (t?.V ? CONFIG_NO_SNAPSHOT : 0) | (snapshotCaptureActive && ownerInSnapshotScope(context) ? CONFIG_IN_SNAPSHOT_SCOPE : 0),
|
|
296
|
-
|
|
299
|
+
Re: t?.equals != null ? t.equals : isEqual,
|
|
297
300
|
it: t?.unobserved,
|
|
298
301
|
xe: null,
|
|
299
302
|
C: context?.C ?? globalQueue,
|
|
300
303
|
we: context?.we ?? defaultContext,
|
|
301
304
|
Qe: 0,
|
|
302
305
|
ke: e,
|
|
303
|
-
|
|
304
|
-
|
|
306
|
+
Pe: undefined,
|
|
307
|
+
Fe: 0,
|
|
305
308
|
u: null,
|
|
306
309
|
lt: undefined,
|
|
307
310
|
ut: null,
|
|
@@ -322,7 +325,7 @@ function computed(e, t) {
|
|
|
322
325
|
Le: null,
|
|
323
326
|
Te: null,
|
|
324
327
|
Ue: null,
|
|
325
|
-
|
|
328
|
+
_e: false
|
|
326
329
|
};
|
|
327
330
|
setupComputedNode(i, t);
|
|
328
331
|
return i;
|
|
@@ -338,15 +341,15 @@ function computed(e, t) {
|
|
|
338
341
|
const s = {
|
|
339
342
|
id: inheritId(u, o, context),
|
|
340
343
|
T: (o ? CONFIG_TRANSPARENT : 0) | (u?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (u?.sync ? CONFIG_SYNC : 0) | (snapshotCaptureActive && ownerInSnapshotScope(context) ? CONFIG_IN_SNAPSHOT_SCOPE : 0),
|
|
341
|
-
|
|
344
|
+
Re: false,
|
|
342
345
|
it: u?.unobserved,
|
|
343
346
|
xe: null,
|
|
344
347
|
C: context?.C ?? globalQueue,
|
|
345
348
|
we: context?.we ?? defaultContext,
|
|
346
349
|
Qe: 0,
|
|
347
350
|
ke: e,
|
|
348
|
-
|
|
349
|
-
|
|
351
|
+
Pe: undefined,
|
|
352
|
+
Fe: 0,
|
|
350
353
|
u: null,
|
|
351
354
|
lt: undefined,
|
|
352
355
|
ut: null,
|
|
@@ -367,7 +370,7 @@ function computed(e, t) {
|
|
|
367
370
|
Le: null,
|
|
368
371
|
Te: null,
|
|
369
372
|
Ue: null,
|
|
370
|
-
|
|
373
|
+
_e: false,
|
|
371
374
|
$e: false,
|
|
372
375
|
rt: undefined,
|
|
373
376
|
ct: t,
|
|
@@ -397,12 +400,12 @@ function setupComputedNode(e, t) {
|
|
|
397
400
|
context.me = e;
|
|
398
401
|
}
|
|
399
402
|
}
|
|
400
|
-
if (n) e.
|
|
403
|
+
if (n) e.Fe = n.Fe + 1;
|
|
401
404
|
if (GlobalQueue.Tt !== null) GlobalQueue.Tt(e);
|
|
402
405
|
!t?.lazy && recompute(e, true);
|
|
403
406
|
if (snapshotCaptureActive && !t?.lazy) {
|
|
404
407
|
if (!(e.S & STATUS_PENDING) && !(e.T & CONFIG_NO_SNAPSHOT)) {
|
|
405
|
-
e.Ve = e.
|
|
408
|
+
e.Ve = e.Pe === undefined ? NO_SNAPSHOT : e.Pe;
|
|
406
409
|
snapshotSources.add(e);
|
|
407
410
|
}
|
|
408
411
|
}
|
|
@@ -410,10 +413,10 @@ function setupComputedNode(e, t) {
|
|
|
410
413
|
|
|
411
414
|
function signal(e, t, n = null) {
|
|
412
415
|
const i = {
|
|
413
|
-
|
|
416
|
+
Re: t?.equals != null ? t.equals : isEqual,
|
|
414
417
|
T: (t?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (t?.V ? CONFIG_NO_SNAPSHOT : 0),
|
|
415
418
|
it: t?.unobserved,
|
|
416
|
-
|
|
419
|
+
Pe: e,
|
|
417
420
|
o: null,
|
|
418
421
|
ot: null,
|
|
419
422
|
ce: clock,
|
|
@@ -514,21 +517,21 @@ function read(e) {
|
|
|
514
517
|
}
|
|
515
518
|
if (!n.ke && l === e && e.Ee === undefined && e.Ve === undefined && activeTransition === null && currentOptimisticLane === null && !snapshotCaptureActive && true) {
|
|
516
519
|
if (t && tracking) link(e, t);
|
|
517
|
-
return !t || e.Ne === NOT_PENDING ? e.
|
|
520
|
+
return !t || e.Ne === NOT_PENDING ? e.Pe : e.Ne;
|
|
518
521
|
}
|
|
519
522
|
if (t && tracking) {
|
|
520
523
|
link(e, t, pendingCheckActive);
|
|
521
524
|
if (l.ke) {
|
|
522
525
|
const n = queueFor(e);
|
|
523
|
-
if (l.
|
|
526
|
+
if (l.Fe >= n.He) {
|
|
524
527
|
markNode(t);
|
|
525
528
|
markHeap(n);
|
|
526
529
|
updateIfNecessary(l);
|
|
527
530
|
}
|
|
528
|
-
const i = l.
|
|
531
|
+
const i = l.Fe;
|
|
529
532
|
// parent check is shallow, might need to be recursive
|
|
530
|
-
if (i >= t.
|
|
531
|
-
t.
|
|
533
|
+
if (i >= t.Fe && e.Ge !== t) {
|
|
534
|
+
t.Fe = i + 1;
|
|
532
535
|
}
|
|
533
536
|
}
|
|
534
537
|
}
|
|
@@ -562,7 +565,7 @@ function read(e) {
|
|
|
562
565
|
const n = e.Ve;
|
|
563
566
|
if (n !== undefined) {
|
|
564
567
|
const i = n === NO_SNAPSHOT ? undefined : n;
|
|
565
|
-
const l = e.Ne !== NOT_PENDING ? e.Ne : e.
|
|
568
|
+
const l = e.Ne !== NOT_PENDING ? e.Ne : e.Pe;
|
|
566
569
|
if (l !== i) t.se |= REACTIVE_SNAPSHOT_STALE;
|
|
567
570
|
return i;
|
|
568
571
|
}
|
|
@@ -579,13 +582,13 @@ function read(e) {
|
|
|
579
582
|
// so it re-runs with the new committed view. (Gate details live with the
|
|
580
583
|
// engine — a non-null lane implies it is installed.)
|
|
581
584
|
if (currentOptimisticLane !== null && activeTransition !== null && t !== null && GlobalQueue.Ct(e, l, t)) {
|
|
582
|
-
return e.
|
|
585
|
+
return e.Pe;
|
|
583
586
|
}
|
|
584
587
|
// In optimistic lane context, return _value for optimistic/lane-assigned signals
|
|
585
588
|
// and for regular signals in stale mode (render effects). Non-stale readers (user
|
|
586
589
|
// effects) see _pendingValue so that latest() and direct reads stay consistent.
|
|
587
590
|
// (The lane-context clause lives with the engine.)
|
|
588
|
-
const u = !t || currentOptimisticLane !== null && GlobalQueue.Ot(e, l, t) || e.Ne === NOT_PENDING || stale && e.Ue && activeTransition !== e.Ue ? e.
|
|
591
|
+
const u = !t || currentOptimisticLane !== null && GlobalQueue.Ot(e, l, t) || e.Ne === NOT_PENDING || stale && e.Ue && activeTransition !== e.Ue ? e.Pe : e.Ne;
|
|
589
592
|
// Record that this isPending() probe observed the fresh pending value, so
|
|
590
593
|
// the probe doesn't pair "pending" with the new value (#2831).
|
|
591
594
|
if (pendingCheckActive) GlobalQueue.Rt(e, u);
|
|
@@ -602,11 +605,11 @@ function setSignal(e, t) {
|
|
|
602
605
|
// _overrideValue slot, and every module that creates one installs the
|
|
603
606
|
// engine first.
|
|
604
607
|
if (e.Ee !== undefined && !projectionWriteActive) return GlobalQueue.Pt(e, t);
|
|
605
|
-
const n = e.Ne === NOT_PENDING ? e.
|
|
608
|
+
const n = e.Ne === NOT_PENDING ? e.Pe : e.Ne;
|
|
606
609
|
if (typeof t === "function") t = t(n);
|
|
607
610
|
// Uninitialized check first: the first commit has no previous value, so the
|
|
608
611
|
// user comparator must not run against `undefined` (matches recompute).
|
|
609
|
-
const i = !!(e.S & STATUS_UNINITIALIZED) || !e.
|
|
612
|
+
const i = !!(e.S & STATUS_UNINITIALIZED) || !e.Re || !e.Re(n, t);
|
|
610
613
|
if (!i) return t;
|
|
611
614
|
if (e.Ne === NOT_PENDING) queuePendingNode(e);
|
|
612
615
|
e.Ne = t;
|
package/dist/prod/core/effect.js
CHANGED
|
@@ -62,7 +62,7 @@ function runEffect(t) {
|
|
|
62
62
|
// same flush must not be hijacked by a later-arriving error status.
|
|
63
63
|
if (t.S & STATUS_ERROR && t.Ae === EFFECT_USER) {
|
|
64
64
|
const E = unwrapStatusError(t._);
|
|
65
|
-
t.rt = t.
|
|
65
|
+
t.rt = t.Pe;
|
|
66
66
|
t.$e = false;
|
|
67
67
|
try {
|
|
68
68
|
t._t ? t._t(E, () => {
|
|
@@ -82,7 +82,7 @@ function runEffect(t) {
|
|
|
82
82
|
t.Et = undefined;
|
|
83
83
|
try {
|
|
84
84
|
E?.();
|
|
85
|
-
const e = t.ct(t.
|
|
85
|
+
const e = t.ct(t.Pe, t.rt);
|
|
86
86
|
if (false && e !== undefined && typeof e !== "function") ;
|
|
87
87
|
// The final cleanup is invoked by disposeChildren at true disposal.
|
|
88
88
|
t.Et = e;
|
|
@@ -94,7 +94,7 @@ function runEffect(t) {
|
|
|
94
94
|
throw E;
|
|
95
95
|
}
|
|
96
96
|
} finally {
|
|
97
|
-
t.rt = t.
|
|
97
|
+
t.rt = t.Pe;
|
|
98
98
|
t.$e = false;
|
|
99
99
|
}
|
|
100
100
|
}
|
package/dist/prod/core/error.js
CHANGED
|
@@ -25,7 +25,16 @@
|
|
|
25
25
|
class NotReadyError extends Error {
|
|
26
26
|
source;
|
|
27
27
|
constructor(r) {
|
|
28
|
+
// Control-flow throw: it happens on every read of a pending source, so in
|
|
29
|
+
// production skip V8's eager stack capture (proportional to stack depth —
|
|
30
|
+
// real cost under SSR) by zeroing the V8-specific stackTraceLimit around
|
|
31
|
+
// super(). Dev keeps the stack for debuggability; non-V8 engines (no
|
|
32
|
+
// stackTraceLimit) take the plain path.
|
|
33
|
+
const o = Error;
|
|
34
|
+
const t = o.stackTraceLimit;
|
|
35
|
+
if (t !== undefined) o.stackTraceLimit = 0;
|
|
28
36
|
super();
|
|
37
|
+
if (t !== undefined) o.stackTraceLimit = t;
|
|
29
38
|
this.source = r;
|
|
30
39
|
}
|
|
31
40
|
}
|
package/dist/prod/core/graph.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CONFIG_AUTO_DISPOSE, REACTIVE_ZOMBIE, REACTIVE_RECOMPUTING_DEPS } from "./constants.js";
|
|
1
|
+
import { CONFIG_AUTO_DISPOSE, REACTIVE_ZOMBIE, STATUS_PENDING, REACTIVE_RECOMPUTING_DEPS } from "./constants.js";
|
|
2
2
|
|
|
3
3
|
import { deleteFromHeap, queueFor } from "./heap.js";
|
|
4
4
|
|
|
@@ -18,8 +18,13 @@ function unlinkSubs(l) {
|
|
|
18
18
|
if (u === null) {
|
|
19
19
|
n.it?.();
|
|
20
20
|
// No more subscribers; only tear down if CONFIG_AUTO_DISPOSE is set.
|
|
21
|
+
// A pending node is exempt: its in-flight async work (or the
|
|
22
|
+
// transition holding it) is an observer — tearing down would orphan
|
|
23
|
+
// the work and re-execute it on the next read. The settle path runs
|
|
24
|
+
// this same last-one-out check when that observer releases (the
|
|
25
|
+
// untracked-read dispose in core.ts guards on pending identically).
|
|
21
26
|
const l = n;
|
|
22
|
-
l.ke && l.T & CONFIG_AUTO_DISPOSE && !(l.se & REACTIVE_ZOMBIE) && unobserved(l);
|
|
27
|
+
l.ke && l.T & CONFIG_AUTO_DISPOSE && !(l.se & REACTIVE_ZOMBIE) && !(l.S & STATUS_PENDING) && unobserved(l);
|
|
23
28
|
}
|
|
24
29
|
}
|
|
25
30
|
return e;
|
package/dist/prod/core/heap.js
CHANGED
|
@@ -20,14 +20,14 @@ import { zombieQueue, dirtyQueue } from "./scheduler.js";
|
|
|
20
20
|
return;
|
|
21
21
|
}
|
|
22
22
|
const E = queueFor(e);
|
|
23
|
-
if (E.
|
|
23
|
+
if (E.He > e.Fe) E.He = e.Fe;
|
|
24
24
|
insertIntoHeap(e, E);
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
function actualInsertIntoHeap(e, E) {
|
|
28
|
-
const t = (e.Ge?.ft ? e.Ge.Nt?.
|
|
29
|
-
if (t >= e.
|
|
30
|
-
const n = e.
|
|
28
|
+
const t = (e.Ge?.ft ? e.Ge.Nt?.Fe : e.Ge?.Fe) ?? -1;
|
|
29
|
+
if (t >= e.Fe) e.Fe = t + 1;
|
|
30
|
+
const n = e.Fe;
|
|
31
31
|
const I = E.eE[n];
|
|
32
32
|
if (I === undefined) E.eE[n] = e; else {
|
|
33
33
|
const E = I.ut;
|
|
@@ -66,7 +66,7 @@ function deleteFromHeap(e, E) {
|
|
|
66
66
|
const t = e.se;
|
|
67
67
|
if (!(t & (REACTIVE_IN_HEAP | REACTIVE_IN_HEAP_HEIGHT))) return;
|
|
68
68
|
e.se = t & -25;
|
|
69
|
-
const n = e.
|
|
69
|
+
const n = e.Fe;
|
|
70
70
|
if (e.ut === e) E.eE[n] = undefined; else {
|
|
71
71
|
const t = e.lt;
|
|
72
72
|
const I = E.eE[n];
|
|
@@ -106,11 +106,11 @@ function markNode(e, E = REACTIVE_DIRTY) {
|
|
|
106
106
|
|
|
107
107
|
function runHeap(e, E) {
|
|
108
108
|
e.tE = false;
|
|
109
|
-
for (e.
|
|
110
|
-
let t = e.eE[e.
|
|
109
|
+
for (e.He = 0; e.He <= e.EE; e.He++) {
|
|
110
|
+
let t = e.eE[e.He];
|
|
111
111
|
while (t !== undefined) {
|
|
112
112
|
if (t.se & REACTIVE_IN_HEAP) E(t); else adjustHeight(t, e);
|
|
113
|
-
t = e.eE[e.
|
|
113
|
+
t = e.eE[e.He];
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
116
|
e.EE = 0;
|
|
@@ -118,14 +118,14 @@ function runHeap(e, E) {
|
|
|
118
118
|
|
|
119
119
|
function adjustHeight(e, E) {
|
|
120
120
|
deleteFromHeap(e, E);
|
|
121
|
-
let t = e.
|
|
121
|
+
let t = e.Fe;
|
|
122
122
|
for (let E = e.Xe; E; E = E.et) {
|
|
123
123
|
const e = E.tt;
|
|
124
124
|
const n = e.nt || e;
|
|
125
|
-
if (n.ke && n.
|
|
125
|
+
if (n.ke && n.Fe >= t) t = n.Fe + 1;
|
|
126
126
|
}
|
|
127
|
-
if (e.
|
|
128
|
-
e.
|
|
127
|
+
if (e.Fe !== t) {
|
|
128
|
+
e.Fe = t;
|
|
129
129
|
for (let E = e.o; E !== null; E = E.ue) {
|
|
130
130
|
// Route each subscriber by its own zombie flag, mirroring the
|
|
131
131
|
// post-recompute height-adjust path. Inserting into the running `heap`
|
package/dist/prod/core/lanes.js
CHANGED
|
@@ -36,8 +36,8 @@ const activeLanes = new Set;
|
|
|
36
36
|
// parent-child is a property of the nodes, not of write order — otherwise
|
|
37
37
|
// the owner's write merges the companion's subscribers into this lane and
|
|
38
38
|
// their effects wait on its async instead of flushing immediately.
|
|
39
|
-
adoptCompanionLane(n.
|
|
40
|
-
adoptCompanionLane(n.
|
|
39
|
+
adoptCompanionLane(n.be, e);
|
|
40
|
+
adoptCompanionLane(n.ge, e);
|
|
41
41
|
return e;
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -25,9 +25,9 @@ import { GlobalQueue, activeTransition, globalQueue, clock, insertSubs, schedule
|
|
|
25
25
|
*/
|
|
26
26
|
/** The optimistic half of setSignal, fired when `_overrideValue !== undefined`. */ function optimisticWrite(e, n) {
|
|
27
27
|
const t = e.Ee !== NOT_PENDING;
|
|
28
|
-
const i = t ? unwrapOverride(e.Ee) : e.
|
|
28
|
+
const i = t ? unwrapOverride(e.Ee) : e.Pe;
|
|
29
29
|
if (typeof n === "function") n = n(i);
|
|
30
|
-
const u = !!(e.S & STATUS_UNINITIALIZED) || !e.
|
|
30
|
+
const u = !!(e.S & STATUS_UNINITIALIZED) || !e.Re || !e.Re(i, n);
|
|
31
31
|
if (!u) {
|
|
32
32
|
// Same-value write with an active override still entangles the current
|
|
33
33
|
// action's transition — the hold must outlast all overlapping actions.
|
|
@@ -87,7 +87,7 @@ function resolveOptimisticNodes(e) {
|
|
|
87
87
|
if (!(n.S & STATUS_PENDING)) n.S &= ~STATUS_UNINITIALIZED;
|
|
88
88
|
const i = n.Ee;
|
|
89
89
|
n.Ee = NOT_PENDING;
|
|
90
|
-
if (i !== NOT_PENDING && n.
|
|
90
|
+
if (i !== NOT_PENDING && n.Pe !== unwrapOverride(i)) insertSubs(n, true);
|
|
91
91
|
n.Ue = null;
|
|
92
92
|
n.sn = null;
|
|
93
93
|
}
|
|
@@ -96,9 +96,9 @@ function resolveOptimisticNodes(e) {
|
|
|
96
96
|
// transition that produced them (A19 — pending is a property of the data).
|
|
97
97
|
for (let t = 0; t < n; t++) {
|
|
98
98
|
const n = e[t];
|
|
99
|
-
if (n.
|
|
99
|
+
if (n.be || n.ge) GlobalQueue.un(n);
|
|
100
100
|
const i = n.nn;
|
|
101
|
-
if (i && (i.
|
|
101
|
+
if (i && (i.be === n || i.ge === n)) GlobalQueue.un(i);
|
|
102
102
|
}
|
|
103
103
|
e.splice(0, n);
|
|
104
104
|
}
|
package/dist/prod/core/owner.js
CHANGED
|
@@ -51,7 +51,7 @@ function disposeChildren(e, n = false, t) {
|
|
|
51
51
|
// edge). Snap runs after the DISPOSED flag is set so the oracle reads
|
|
52
52
|
// false, and notifies subscribers still watching the companion.
|
|
53
53
|
const n = e;
|
|
54
|
-
if (n.
|
|
54
|
+
if (n.be || n.ge) GlobalQueue.un(n);
|
|
55
55
|
}
|
|
56
56
|
if (n && e.ke) e.Te = null;
|
|
57
57
|
let l = t ? e.Le : e.me;
|
|
@@ -19,14 +19,14 @@ const transitions = new Set;
|
|
|
19
19
|
const dirtyQueue = {
|
|
20
20
|
eE: new Array(2e3).fill(undefined),
|
|
21
21
|
tE: false,
|
|
22
|
-
|
|
22
|
+
He: 0,
|
|
23
23
|
EE: 0
|
|
24
24
|
};
|
|
25
25
|
|
|
26
26
|
const zombieQueue = {
|
|
27
27
|
eE: new Array(2e3).fill(undefined),
|
|
28
28
|
tE: false,
|
|
29
|
-
|
|
29
|
+
He: 0,
|
|
30
30
|
EE: 0
|
|
31
31
|
};
|
|
32
32
|
|
|
@@ -279,7 +279,7 @@ class GlobalQueue extends Queue {
|
|
|
279
279
|
// isPending()/latest()).
|
|
280
280
|
static Ie=null;
|
|
281
281
|
static ae=null;
|
|
282
|
-
static
|
|
282
|
+
static he=null;
|
|
283
283
|
static un=null;
|
|
284
284
|
static St=null;
|
|
285
285
|
static dt=null;
|
|
@@ -334,7 +334,7 @@ class GlobalQueue extends Queue {
|
|
|
334
334
|
// A kept ambient batch may hold pending nodes (#2916): stay
|
|
335
335
|
// scheduled so the outer drain loop commits them via the plain
|
|
336
336
|
// flush path instead of leaving them until the next natural flush.
|
|
337
|
-
scheduled = dirtyQueue.EE >= dirtyQueue.
|
|
337
|
+
scheduled = dirtyQueue.EE >= dirtyQueue.He || this.m.Qt.length > 0;
|
|
338
338
|
reassignPendingTransition(e.Qt);
|
|
339
339
|
activeTransition = null;
|
|
340
340
|
finalizePureQueue(null, true);
|
|
@@ -362,7 +362,7 @@ class GlobalQueue extends Queue {
|
|
|
362
362
|
} else {
|
|
363
363
|
if (canUseSimpleSyncFlush(this)) {
|
|
364
364
|
commitPendingNodes();
|
|
365
|
-
if (dirtyQueue.EE >= dirtyQueue.
|
|
365
|
+
if (dirtyQueue.EE >= dirtyQueue.He) {
|
|
366
366
|
runHeap(dirtyQueue, GlobalQueue.pe);
|
|
367
367
|
commitPendingNodes();
|
|
368
368
|
}
|
|
@@ -373,7 +373,7 @@ class GlobalQueue extends Queue {
|
|
|
373
373
|
}
|
|
374
374
|
clock++;
|
|
375
375
|
// Check if finalization added items to the heap (from optimistic reversion)
|
|
376
|
-
scheduled = dirtyQueue.EE >= dirtyQueue.
|
|
376
|
+
scheduled = dirtyQueue.EE >= dirtyQueue.He;
|
|
377
377
|
// Run lane effects first (for ready lanes), then regular effects
|
|
378
378
|
activeLanes.size && GlobalQueue.In(EFFECT_RENDER);
|
|
379
379
|
this.run(EFFECT_RENDER);
|
|
@@ -495,14 +495,14 @@ function commitPendingNode(e) {
|
|
|
495
495
|
const t = e;
|
|
496
496
|
if (!t.ke) {
|
|
497
497
|
if (e.Ne !== NOT_PENDING) {
|
|
498
|
-
e.
|
|
498
|
+
e.Pe = e.Ne;
|
|
499
499
|
e.Ne = NOT_PENDING;
|
|
500
500
|
}
|
|
501
|
-
if (e.
|
|
501
|
+
if (e.be || e.ge) GlobalQueue.un(e);
|
|
502
502
|
return;
|
|
503
503
|
}
|
|
504
504
|
if (e.Ne !== NOT_PENDING) {
|
|
505
|
-
e.
|
|
505
|
+
e.Pe = e.Ne;
|
|
506
506
|
e.Ne = NOT_PENDING;
|
|
507
507
|
// Set _modified for effects, but not for tracked effects (they handle their own scheduling)
|
|
508
508
|
if (e.Ae && e.Ae !== EFFECT_TRACKED) e.$e = true;
|
|
@@ -510,7 +510,7 @@ function commitPendingNode(e) {
|
|
|
510
510
|
t.se &= ~REACTIVE_MANUAL_WRITE;
|
|
511
511
|
if (!(t.S & STATUS_PENDING)) t.S &= ~STATUS_UNINITIALIZED;
|
|
512
512
|
if (t.Le !== null || t.ye !== null) GlobalQueue.Ce(t, false, true);
|
|
513
|
-
if (e.
|
|
513
|
+
if (e.be || e.ge) GlobalQueue.un(e);
|
|
514
514
|
}
|
|
515
515
|
|
|
516
516
|
function commitPendingNodes() {
|
|
@@ -527,7 +527,7 @@ function finalizePureQueue(e = null, t = false) {
|
|
|
527
527
|
const i = !t;
|
|
528
528
|
if (i) commitPendingNodes();
|
|
529
529
|
if (!t && globalQueue.vt.length) checkBoundaryChildren(globalQueue);
|
|
530
|
-
const n = dirtyQueue.EE >= dirtyQueue.
|
|
530
|
+
const n = dirtyQueue.EE >= dirtyQueue.He;
|
|
531
531
|
if (n) runHeap(dirtyQueue, GlobalQueue.pe);
|
|
532
532
|
if (i) {
|
|
533
533
|
if (n) commitPendingNodes();
|