@solidjs/signals 2.0.0-rc.6 → 2.0.0-rc.7
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 +2033 -1291
- package/dist/node.cjs +1821 -2401
- package/dist/node.dev.cjs +13724 -0
- package/dist/prod/boundaries.js +3 -1
- package/dist/prod/core/async.js +6 -1
- package/dist/prod/core/attribution-hooks.js +3 -0
- package/dist/prod/core/constants.js +9 -1
- package/dist/prod/core/context.js +10 -16
- package/dist/prod/core/core.js +215 -139
- package/dist/prod/core/dev.js +2 -0
- package/dist/prod/core/effect.js +37 -28
- package/dist/prod/core/external.js +2 -2
- package/dist/prod/core/graph.js +35 -31
- package/dist/prod/core/heap.js +34 -40
- package/dist/prod/core/lanes.js +41 -27
- package/dist/prod/core/optimistic.js +42 -32
- package/dist/prod/core/owner.js +32 -32
- package/dist/prod/core/scheduler.js +140 -154
- package/dist/prod/core/verdict.js +31 -34
- package/dist/prod/index.js +0 -2
- package/dist/prod/map.js +104 -94
- package/dist/prod/signals.js +51 -34
- package/dist/prod/store/next/optimistic.js +153 -172
- package/dist/prod/store/next/reconcile.js +140 -288
- package/dist/prod/store/next/store.js +307 -237
- package/dist/prod/store/store.js +2 -2
- package/dist/types/core/attribution-hooks.d.ts +64 -0
- package/dist/types/core/attribution.d.ts +265 -9
- package/dist/types/core/constants.d.ts +8 -0
- package/dist/types/core/core.d.ts +12 -3
- package/dist/types/core/dev.d.ts +49 -8
- package/dist/types/core/heap.d.ts +5 -3
- package/dist/types/core/invariants.d.ts +1 -1
- package/dist/types/core/lanes.d.ts +10 -0
- package/dist/types/core/scheduler.d.ts +9 -4
- package/dist/types/signals.d.ts +10 -0
- package/dist/types/store/index.d.ts +3 -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 +3 -9
- package/dist/types/store/next/target.d.ts +20 -46
- package/dist/types/store/store.d.ts +14 -9
- package/dist/types-cjs/core/attribution-hooks.d.cts +64 -0
- package/dist/types-cjs/core/attribution.d.cts +265 -9
- package/dist/types-cjs/core/constants.d.cts +8 -0
- package/dist/types-cjs/core/core.d.cts +12 -3
- package/dist/types-cjs/core/dev.d.cts +49 -8
- package/dist/types-cjs/core/heap.d.cts +5 -3
- package/dist/types-cjs/core/invariants.d.cts +1 -1
- package/dist/types-cjs/core/lanes.d.cts +10 -0
- package/dist/types-cjs/core/scheduler.d.cts +9 -4
- package/dist/types-cjs/signals.d.cts +10 -0
- package/dist/types-cjs/store/index.d.cts +3 -6
- package/dist/types-cjs/store/next/optimistic.d.cts +4 -2
- package/dist/types-cjs/store/next/reconcile.d.cts +5 -12
- package/dist/types-cjs/store/next/store.d.cts +3 -9
- package/dist/types-cjs/store/next/target.d.cts +20 -46
- package/dist/types-cjs/store/store.d.cts +14 -9
- package/package.json +3 -2
- 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/store/next/patch-hooks.d.cts +0 -41
- package/dist/types-cjs/store/next/patch.d.cts +0 -91
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { EFFECT_RENDER, EFFECT_USER, STATUS_PENDING, REACTIVE_IN_HEAP_HEIGHT, REACTIVE_DISPOSED, CONFIG_HELD_TRUTH, REACTIVE_ZOMBIE, CONFIG_HAS_LANE, CONFIG_HAS_SNAPSHOT, REACTIVE_RECOMPUTING_DEPS, REACTIVE_MISSED_WAKE, CONFIG_IN_SNAPSHOT_SCOPE, REACTIVE_SNAPSHOT_STALE, REACTIVE_OPTIMISTIC_DIRTY, NOT_PENDING, CONFIG_HAS_COMPANIONS, EFFECT_TRACKED, REACTIVE_REASK, REACTIVE_MANUAL_WRITE, STATUS_UNINITIALIZED, CONFIG_AUTHORITATIVE_READ } from "./constants.js";
|
|
1
|
+
import { EFFECT_RENDER, EFFECT_USER, STATUS_PENDING, REACTIVE_IN_HEAP_HEIGHT, REACTIVE_DISPOSED, CONFIG_HELD_TRUTH, REACTIVE_ZOMBIE, CONFIG_HAS_LANE, CONFIG_HAS_SNAPSHOT, REACTIVE_RECOMPUTING_DEPS, REACTIVE_MISSED_WAKE, CONFIG_IN_SNAPSHOT_SCOPE, REACTIVE_SNAPSHOT_STALE, REACTIVE_OPTIMISTIC_DIRTY, NOT_PENDING, CONFIG_SLOT_NODE, CONFIG_HAS_COMPANIONS, EFFECT_TRACKED, REACTIVE_REASK, REACTIVE_MANUAL_WRITE, STATUS_UNINITIALIZED, CONFIG_AUTHORITATIVE_READ } from "./constants.js";
|
|
2
2
|
|
|
3
|
-
import { currentOptimisticLane } from "./core.js";
|
|
3
|
+
import { currentOptimisticLane, slotUnobservedHook } from "./core.js";
|
|
4
4
|
|
|
5
5
|
import { DEV } from "./dev.js";
|
|
6
6
|
|
|
@@ -21,14 +21,14 @@ const transitions = new Set;
|
|
|
21
21
|
const dirtyQueue = {
|
|
22
22
|
eE: new Array(2e3).fill(undefined),
|
|
23
23
|
tE: false,
|
|
24
|
-
|
|
24
|
+
Me: 0,
|
|
25
25
|
EE: 0
|
|
26
26
|
};
|
|
27
27
|
|
|
28
28
|
const zombieQueue = {
|
|
29
29
|
eE: new Array(2e3).fill(undefined),
|
|
30
30
|
tE: false,
|
|
31
|
-
|
|
31
|
+
Me: 0,
|
|
32
32
|
EE: 0
|
|
33
33
|
};
|
|
34
34
|
|
|
@@ -63,7 +63,7 @@ const transientStoreNodes = new Set;
|
|
|
63
63
|
|
|
64
64
|
function canUseSimpleSyncFlush(e) {
|
|
65
65
|
const t = e.m;
|
|
66
|
-
return transitions.size === 0 && activeLanes.size === 0 && e.
|
|
66
|
+
return transitions.size === 0 && activeLanes.size === 0 && e.Bt.length === 0 && t.Xe.length === 0 && t.A.length === 0 && t.En.size === 0 && transientStoreNodes.size === 0;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
function sweepTransientStoreNodes() {
|
|
@@ -80,7 +80,7 @@ function sweepTransientStoreNodes() {
|
|
|
80
80
|
// unmarked node for the same property).
|
|
81
81
|
if (e.o?.t) continue;
|
|
82
82
|
transientStoreNodes.delete(e);
|
|
83
|
-
e.o?.
|
|
83
|
+
if (e.T & CONFIG_SLOT_NODE) slotUnobservedHook(e); else e.o?.Nt?.();
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
|
|
@@ -108,15 +108,15 @@ function setProjectionWriteActive(e) {
|
|
|
108
108
|
*/ function createBatch() {
|
|
109
109
|
return {
|
|
110
110
|
Te: clock,
|
|
111
|
-
|
|
111
|
+
Mt: [],
|
|
112
112
|
_e: new Map,
|
|
113
|
-
|
|
113
|
+
Xe: [],
|
|
114
114
|
A: [],
|
|
115
115
|
En: new Set,
|
|
116
116
|
ue: [],
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
117
|
+
wt: {
|
|
118
|
+
jt: [ [], [] ],
|
|
119
|
+
Bt: []
|
|
120
120
|
},
|
|
121
121
|
sn: false,
|
|
122
122
|
cn: new Set
|
|
@@ -127,12 +127,12 @@ function mergeTransitionState(e, t) {
|
|
|
127
127
|
t.sn = e;
|
|
128
128
|
e.ue.push(...t.ue);
|
|
129
129
|
for (const i of activeLanes) if (i.Ae === t) i.Ae = e;
|
|
130
|
-
if (t.
|
|
130
|
+
if (t.Xe.length) {
|
|
131
131
|
// Move (don't copy): the global queue's batch may still be the outgoing
|
|
132
132
|
// transition, and the adoption pass in initTransition would re-push its
|
|
133
133
|
// contents into the target — duplicating every entry.
|
|
134
|
-
e.
|
|
135
|
-
t.
|
|
134
|
+
e.Xe.push(...t.Xe);
|
|
135
|
+
t.Xe.length = 0;
|
|
136
136
|
}
|
|
137
137
|
if (t.A.length) {
|
|
138
138
|
// Move (don't copy): the global queue's batch may still be the outgoing
|
|
@@ -142,26 +142,6 @@ function mergeTransitionState(e, t) {
|
|
|
142
142
|
t.A.length = 0;
|
|
143
143
|
}
|
|
144
144
|
for (const i of t.En) e.En.add(i);
|
|
145
|
-
// Patch-channel stash (store/next/patch.ts): entries held for the outgoing
|
|
146
|
-
// transition must ride the merge like every other per-transition
|
|
147
|
-
// collection — releaseBatch only reads the COMMITTING transition's stash,
|
|
148
|
-
// so a stranded sidecar would silently drop its patches. Move (don't
|
|
149
|
-
// copy), same aliasing rule as the collections above. The field is an
|
|
150
|
-
// expando so this module stays free of patch imports (pay-for-use).
|
|
151
|
-
const i = t.wt;
|
|
152
|
-
if (i !== undefined) {
|
|
153
|
-
t.wt = undefined;
|
|
154
|
-
let n = e.wt;
|
|
155
|
-
if (n !== undefined) n.push(...i); else n = e.wt = i;
|
|
156
|
-
// Retarget the entries' coalescing stamps to the surviving stash
|
|
157
|
-
// (opaque backref contract with store/next/patch.ts): without this a
|
|
158
|
-
// post-merge emission misses the stamp and pushes a SECOND entry —
|
|
159
|
-
// the record's patch applies twice at commit (re-audit 5, P1-2).
|
|
160
|
-
for (let e = 0; e < i.length; e++) {
|
|
161
|
-
const t = i[e].pc;
|
|
162
|
-
if (t !== undefined && t.qe === i[e]) t.qa = n;
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
145
|
for (const [i, n] of t._e) {
|
|
166
146
|
let t = e._e.get(i);
|
|
167
147
|
if (!t) e._e.set(i, t = new Set);
|
|
@@ -201,8 +181,8 @@ function mergeTransitionState(e, t) {
|
|
|
201
181
|
// the awaiting transaction to landings that haven't happened; a merged
|
|
202
182
|
// reporter deadlocked exactly that way).
|
|
203
183
|
let i = false;
|
|
204
|
-
for (let n = e.
|
|
205
|
-
const r = n.
|
|
184
|
+
for (let n = e.lt; n !== null; n = n.ot) {
|
|
185
|
+
const r = n.st;
|
|
206
186
|
if (r.Re !== NOT_PENDING) {
|
|
207
187
|
const e = r.Ae;
|
|
208
188
|
const n = e != null ? currentTransition(e) : null;
|
|
@@ -212,10 +192,10 @@ function mergeTransitionState(e, t) {
|
|
|
212
192
|
// (t === null) must leave the batch NOW — it commits at this flush's
|
|
213
193
|
// end, which would reveal the confirmation under the live optimism
|
|
214
194
|
// it just confirmed.
|
|
215
|
-
const s = n === null ? currentBatch.
|
|
195
|
+
const s = n === null ? currentBatch.Mt : n !== t && n.sn !== true ? n.Mt : null;
|
|
216
196
|
if (s !== null) i = stealEntangledCargo(s, t) || i;
|
|
217
197
|
}
|
|
218
|
-
if (n === e.
|
|
198
|
+
if (n === e.Be) break;
|
|
219
199
|
}
|
|
220
200
|
// The steal never activates the awaiting transaction: the predicate can
|
|
221
201
|
// flip inside another transaction's finalize heap, and adopting the queue
|
|
@@ -244,11 +224,11 @@ function mergeTransitionState(e, t) {
|
|
|
244
224
|
* committed value — while re-running them would re-derive the OLD world
|
|
245
225
|
* and re-stage it over the held truth. The reveal re-notifies
|
|
246
226
|
* (commitPendingNodes), which is when they re-derive for real. */ function stealEntangledCargo(e, t) {
|
|
247
|
-
if (e === t.
|
|
227
|
+
if (e === t.Mt || e.length === 0) return false;
|
|
248
228
|
for (let i = 0; i < e.length; i++) {
|
|
249
229
|
const n = e[i];
|
|
250
230
|
n.Ae = t;
|
|
251
|
-
t.
|
|
231
|
+
t.Mt.push(n);
|
|
252
232
|
// Override-covered nodes stay silent AND unmasked: the override is the
|
|
253
233
|
// display (A17 — its staging never notified, its revert will), so their
|
|
254
234
|
// subs saw nothing and re-running one would break the silence with a
|
|
@@ -307,30 +287,30 @@ function notifyHalted() {
|
|
|
307
287
|
let queueRunToken = 0;
|
|
308
288
|
|
|
309
289
|
class Queue {
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
290
|
+
Le=null;
|
|
291
|
+
jt=[ [], [] ];
|
|
292
|
+
Bt=[];
|
|
293
|
+
qt=0;
|
|
314
294
|
created=clock;
|
|
315
295
|
addChild(e) {
|
|
316
|
-
this.
|
|
317
|
-
e.
|
|
296
|
+
this.Bt.push(e);
|
|
297
|
+
e.Le = this;
|
|
318
298
|
}
|
|
319
299
|
removeChild(e) {
|
|
320
|
-
const t = this.
|
|
300
|
+
const t = this.Bt.indexOf(e);
|
|
321
301
|
if (t >= 0) {
|
|
322
|
-
this.
|
|
323
|
-
e.
|
|
302
|
+
this.Bt.splice(t, 1);
|
|
303
|
+
e.Le = null;
|
|
324
304
|
}
|
|
325
305
|
}
|
|
326
306
|
notify(e, t, i, n) {
|
|
327
|
-
if (this.
|
|
307
|
+
if (this.Le) return this.Le.notify(e, t, i, n);
|
|
328
308
|
return false;
|
|
329
309
|
}
|
|
330
310
|
run(e) {
|
|
331
|
-
if (this.
|
|
332
|
-
const t = this.
|
|
333
|
-
this.
|
|
311
|
+
if (this.jt[e - 1].length) {
|
|
312
|
+
const t = this.jt[e - 1];
|
|
313
|
+
this.jt[e - 1] = [];
|
|
334
314
|
runQueue(t, e);
|
|
335
315
|
}
|
|
336
316
|
// Effects run here can dispose owners, and disposal removes queues from
|
|
@@ -340,12 +320,12 @@ class Queue {
|
|
|
340
320
|
// can be recovered by rescanning from the front and every child still runs
|
|
341
321
|
// exactly once. Children appended mid-pass carry a stale stamp and run,
|
|
342
322
|
// matching the previous live-array behaviour.
|
|
343
|
-
const t = this.
|
|
323
|
+
const t = this.Bt;
|
|
344
324
|
const i = ++queueRunToken;
|
|
345
325
|
for (let n = 0; n < t.length; ) {
|
|
346
326
|
const r = t[n];
|
|
347
|
-
if (r.
|
|
348
|
-
r.
|
|
327
|
+
if (r.qt !== i) {
|
|
328
|
+
r.qt = i;
|
|
349
329
|
r.run?.(e);
|
|
350
330
|
if (t[n] !== r) {
|
|
351
331
|
n = 0;
|
|
@@ -362,34 +342,34 @@ class Queue {
|
|
|
362
342
|
const i = findLane(currentOptimisticLane);
|
|
363
343
|
i.tn[e - 1].push(t);
|
|
364
344
|
} else {
|
|
365
|
-
this.
|
|
345
|
+
this.jt[e - 1].push(t);
|
|
366
346
|
}
|
|
367
347
|
}
|
|
368
348
|
schedule();
|
|
369
349
|
}
|
|
370
350
|
stashQueues(e) {
|
|
371
|
-
e.
|
|
372
|
-
e.
|
|
373
|
-
this.
|
|
374
|
-
for (let t = 0; t < this.
|
|
375
|
-
let i = this.
|
|
376
|
-
let n = e.
|
|
351
|
+
e.jt[0].push(...this.jt[0]);
|
|
352
|
+
e.jt[1].push(...this.jt[1]);
|
|
353
|
+
this.jt = [ [], [] ];
|
|
354
|
+
for (let t = 0; t < this.Bt.length; t++) {
|
|
355
|
+
let i = this.Bt[t];
|
|
356
|
+
let n = e.Bt[t];
|
|
377
357
|
if (!n) {
|
|
378
358
|
n = {
|
|
379
|
-
|
|
380
|
-
|
|
359
|
+
jt: [ [], [] ],
|
|
360
|
+
Bt: []
|
|
381
361
|
};
|
|
382
|
-
e.
|
|
362
|
+
e.Bt[t] = n;
|
|
383
363
|
}
|
|
384
364
|
i.stashQueues(n);
|
|
385
365
|
}
|
|
386
366
|
}
|
|
387
367
|
restoreQueues(e) {
|
|
388
|
-
this.
|
|
389
|
-
this.
|
|
390
|
-
for (let t = 0; t < e.
|
|
391
|
-
const i = e.
|
|
392
|
-
let n = this.
|
|
368
|
+
this.jt[0].push(...e.jt[0]);
|
|
369
|
+
this.jt[1].push(...e.jt[1]);
|
|
370
|
+
for (let t = 0; t < e.Bt.length; t++) {
|
|
371
|
+
const i = e.Bt[t];
|
|
372
|
+
let n = this.Bt[t];
|
|
393
373
|
if (n) n.restoreQueues(i);
|
|
394
374
|
}
|
|
395
375
|
}
|
|
@@ -401,9 +381,9 @@ class GlobalQueue extends Queue {
|
|
|
401
381
|
// transition is active, the active transition itself after initTransition.
|
|
402
382
|
m=createBatch();
|
|
403
383
|
static Fe;
|
|
404
|
-
static
|
|
405
|
-
static
|
|
406
|
-
static
|
|
384
|
+
static ke;
|
|
385
|
+
static ut;
|
|
386
|
+
static Wt=null;
|
|
407
387
|
// Store-side hook: drops a keyless affects() mark's identity scope when the
|
|
408
388
|
// carrier node's last registration releases (wired by store.ts, mirroring
|
|
409
389
|
// _clearOptimisticStore).
|
|
@@ -417,8 +397,8 @@ class GlobalQueue extends Queue {
|
|
|
417
397
|
static N=null;
|
|
418
398
|
// External-source bridge (wired by enableExternalSource(); null while no
|
|
419
399
|
// config is active — including after _resetExternalSourceConfig()).
|
|
420
|
-
static
|
|
421
|
-
static
|
|
400
|
+
static Ft=null;
|
|
401
|
+
static gt=null;
|
|
422
402
|
// Verdict-layer hooks (wired by verdict.ts when isPending()/latest() are
|
|
423
403
|
// imported; null in apps that never use them). Call sites either guard for
|
|
424
404
|
// null or sit behind state only the verdict layer can create (`!` is safe
|
|
@@ -429,15 +409,15 @@ class GlobalQueue extends Queue {
|
|
|
429
409
|
static de=null;
|
|
430
410
|
static me=null;
|
|
431
411
|
static un=null;
|
|
432
|
-
static
|
|
433
|
-
static
|
|
434
|
-
static
|
|
435
|
-
static
|
|
412
|
+
static Vt=null;
|
|
413
|
+
static bt=null;
|
|
414
|
+
static Lt=null;
|
|
415
|
+
static nt=null;
|
|
436
416
|
static k=null;
|
|
437
|
-
static
|
|
417
|
+
static zt=null;
|
|
438
418
|
// Re-asks probes whose verdict was provisionally suppressed by a fresh read
|
|
439
419
|
// of a held value, once the transaction gains an async blocker (#3028).
|
|
440
|
-
static
|
|
420
|
+
static Kt=null;
|
|
441
421
|
// Optimistic-engine hooks (wired by core/optimistic.ts via
|
|
442
422
|
// installOptimisticEngine(), called from verdict.ts / createOptimistic /
|
|
443
423
|
// createOptimisticStore — every module that can create optimistic state).
|
|
@@ -445,7 +425,7 @@ class GlobalQueue extends Queue {
|
|
|
445
425
|
// `_overrideValue` slot, a lane in `activeLanes`, an `_optimisticNodes`
|
|
446
426
|
// entry, or a non-null `currentOptimisticLane`, so `!` invocations are safe
|
|
447
427
|
// once the gate holds.
|
|
448
|
-
static
|
|
428
|
+
static yt=null;
|
|
449
429
|
static Tn=null;
|
|
450
430
|
static dn=null;
|
|
451
431
|
static In=null;
|
|
@@ -454,16 +434,17 @@ class GlobalQueue extends Queue {
|
|
|
454
434
|
* apply at lane-effect timing — visible in flight, unlike the regular
|
|
455
435
|
* effect queues an action stashes. Injected; null when unused. */
|
|
456
436
|
static ln=null;
|
|
457
|
-
static
|
|
458
|
-
static
|
|
459
|
-
static
|
|
460
|
-
static
|
|
461
|
-
static
|
|
462
|
-
/** Authoritative-view reader wakeup
|
|
463
|
-
* Call sites are gated by CONFIG_AUTHORITATIVE_OBSERVED, which
|
|
464
|
-
* carve-out read can set, so `!` invocations are safe once
|
|
437
|
+
static Ut=null;
|
|
438
|
+
static kt=null;
|
|
439
|
+
static xt=null;
|
|
440
|
+
static Je=null;
|
|
441
|
+
static tt=null;
|
|
442
|
+
/** Authoritative-view reader wakeup: installed by until() and refresh() before
|
|
443
|
+
* their first read. Call sites are gated by CONFIG_AUTHORITATIVE_OBSERVED, which
|
|
444
|
+
* only such a reader's carve-out read can set, so `!` invocations are safe once
|
|
445
|
+
* the gate holds (#3303). */
|
|
465
446
|
static he=null;
|
|
466
|
-
static
|
|
447
|
+
static et=null;
|
|
467
448
|
static _n=null;
|
|
468
449
|
flush() {
|
|
469
450
|
if (this.fn) return;
|
|
@@ -472,7 +453,7 @@ class GlobalQueue extends Queue {
|
|
|
472
453
|
// optimistic state. Commit and go; anything a commit hook schedules
|
|
473
454
|
// (companion snaps, store folds notifying subs) re-arms `scheduled`
|
|
474
455
|
// below and the outer drain loop takes the full spine next round.
|
|
475
|
-
if (activeTransition === null && dirtyQueue.EE < dirtyQueue.
|
|
456
|
+
if (activeTransition === null && dirtyQueue.EE < dirtyQueue.Me && this.jt[0].length === 0 && this.jt[1].length === 0 && this.Bt.length === 0 && canUseSimpleSyncFlush(this)) {
|
|
476
457
|
this.fn = true;
|
|
477
458
|
try {
|
|
478
459
|
// Sweep first: unobserved() pulls swept nodes out of the dirty heap,
|
|
@@ -484,7 +465,7 @@ class GlobalQueue extends Queue {
|
|
|
484
465
|
this.fn = false;
|
|
485
466
|
}
|
|
486
467
|
clock++;
|
|
487
|
-
scheduled = dirtyQueue.EE >= dirtyQueue.
|
|
468
|
+
scheduled = dirtyQueue.EE >= dirtyQueue.Me || this.jt[0].length !== 0 || this.jt[1].length !== 0 || this.m.Mt.length !== 0;
|
|
488
469
|
return;
|
|
489
470
|
}
|
|
490
471
|
this.fn = true;
|
|
@@ -520,32 +501,32 @@ class GlobalQueue extends Queue {
|
|
|
520
501
|
GlobalQueue.Nn(EFFECT_RENDER);
|
|
521
502
|
GlobalQueue.Nn(EFFECT_USER);
|
|
522
503
|
}
|
|
523
|
-
this.stashQueues(e.
|
|
504
|
+
this.stashQueues(e.wt);
|
|
524
505
|
clock++;
|
|
525
506
|
// A kept ambient batch may hold pending nodes (#2916): stay
|
|
526
507
|
// scheduled so the outer drain loop commits them via the plain
|
|
527
508
|
// flush path instead of leaving them until the next natural flush.
|
|
528
|
-
scheduled = dirtyQueue.EE >= dirtyQueue.
|
|
529
|
-
reassignPendingTransition(e.
|
|
509
|
+
scheduled = dirtyQueue.EE >= dirtyQueue.Me || this.m.Mt.length > 0;
|
|
510
|
+
reassignPendingTransition(e.Mt);
|
|
530
511
|
activeTransition = null;
|
|
531
512
|
finalizePureQueue(null, true);
|
|
532
513
|
return;
|
|
533
514
|
}
|
|
534
515
|
const t = activeTransition;
|
|
535
516
|
const i = this.m;
|
|
536
|
-
i !== t && i.
|
|
537
|
-
this.restoreQueues(t.
|
|
517
|
+
i !== t && i.Mt.push(...t.Mt);
|
|
518
|
+
this.restoreQueues(t.wt);
|
|
538
519
|
transitions.delete(t);
|
|
539
520
|
activeTransition = null;
|
|
540
|
-
reassignPendingTransition(i.
|
|
521
|
+
reassignPendingTransition(i.Mt);
|
|
541
522
|
finalizePureQueue(t);
|
|
542
523
|
if (i === t) {
|
|
543
524
|
// Drop the dead Transition wrapper but keep its (drained) containers
|
|
544
525
|
// as the ambient batch — late registrations during finalization live
|
|
545
526
|
// there and must survive to the next flush.
|
|
546
527
|
const e = createBatch();
|
|
547
|
-
e.
|
|
548
|
-
e.
|
|
528
|
+
e.Mt = i.Mt;
|
|
529
|
+
e.Xe = i.Xe;
|
|
549
530
|
e.A = i.A;
|
|
550
531
|
e.En = i.En;
|
|
551
532
|
currentBatch = this.m = e;
|
|
@@ -553,7 +534,7 @@ class GlobalQueue extends Queue {
|
|
|
553
534
|
} else {
|
|
554
535
|
if (canUseSimpleSyncFlush(this)) {
|
|
555
536
|
commitPendingNodes();
|
|
556
|
-
if (dirtyQueue.EE >= dirtyQueue.
|
|
537
|
+
if (dirtyQueue.EE >= dirtyQueue.Me) {
|
|
557
538
|
runHeap(dirtyQueue, GlobalQueue.Fe);
|
|
558
539
|
commitPendingNodes();
|
|
559
540
|
}
|
|
@@ -564,7 +545,7 @@ class GlobalQueue extends Queue {
|
|
|
564
545
|
}
|
|
565
546
|
clock++;
|
|
566
547
|
// Check if finalization added items to the heap (from optimistic reversion)
|
|
567
|
-
scheduled = dirtyQueue.EE >= dirtyQueue.
|
|
548
|
+
scheduled = dirtyQueue.EE >= dirtyQueue.Me;
|
|
568
549
|
// Run lane effects first (for ready lanes), then regular effects
|
|
569
550
|
activeLanes.size && GlobalQueue.Nn(EFFECT_RENDER);
|
|
570
551
|
this.run(EFFECT_RENDER);
|
|
@@ -581,21 +562,31 @@ class GlobalQueue extends Queue {
|
|
|
581
562
|
// Only track async if the boundary is propagating STATUS_PENDING (not caught by boundary)
|
|
582
563
|
if (t & STATUS_PENDING) {
|
|
583
564
|
if (i & STATUS_PENDING) {
|
|
584
|
-
|
|
565
|
+
// Callers pass either nothing or this node's own `_x._error`, so `??`
|
|
566
|
+
// is exact (a null error falls back to the same null).
|
|
567
|
+
const t = n ?? e.o?._;
|
|
585
568
|
// A visibility-only mark notification (the affects() boundary
|
|
586
569
|
// channel) updates display state on its way up but must be invisible
|
|
587
570
|
// to completion accounting BY CONSTRUCTION: it never registers a
|
|
588
571
|
// reporter and never counts toward the loading-boundary diagnostic.
|
|
589
572
|
if (t?.l) return true;
|
|
590
|
-
if (
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
if (
|
|
597
|
-
|
|
598
|
-
|
|
573
|
+
if (t) {
|
|
574
|
+
// A reveal can discover a flight started in an earlier flush. Hold
|
|
575
|
+
// the staged writes with that reader (A15), even if the reader is
|
|
576
|
+
// new. Fresh/reset loading boundaries consume pending before it
|
|
577
|
+
// reaches here. A reader already parked in a transition must not
|
|
578
|
+
// open a second one.
|
|
579
|
+
if (!activeTransition && !e.Ae && currentBatch.Mt.length) this.initTransition();
|
|
580
|
+
if (activeTransition) {
|
|
581
|
+
const i = t.source;
|
|
582
|
+
let n = activeTransition._e.get(i);
|
|
583
|
+
if (!n) activeTransition._e.set(i, n = new Set);
|
|
584
|
+
const r = n.size;
|
|
585
|
+
n.add(e);
|
|
586
|
+
if (n.size !== r) {
|
|
587
|
+
schedule();
|
|
588
|
+
GlobalQueue.Kt?.(activeTransition);
|
|
589
|
+
}
|
|
599
590
|
}
|
|
600
591
|
}
|
|
601
592
|
}
|
|
@@ -621,6 +612,11 @@ class GlobalQueue extends Queue {
|
|
|
621
612
|
} else if (e) {
|
|
622
613
|
const t = activeTransition;
|
|
623
614
|
mergeTransitionState(e, t);
|
|
615
|
+
// Effects the outgoing transaction parked belong to the surviving one
|
|
616
|
+
// now: back onto the live queue, where this flush parks them under
|
|
617
|
+
// `transition` or runs them at its completion. The outgoing stash is
|
|
618
|
+
// never read again — the transaction is dead (#3310).
|
|
619
|
+
this.restoreQueues(t.wt);
|
|
624
620
|
transitions.delete(t);
|
|
625
621
|
activeTransition = e;
|
|
626
622
|
}
|
|
@@ -635,15 +631,15 @@ class GlobalQueue extends Queue {
|
|
|
635
631
|
// must not entangle unrelated writes to it; the same rule holds one hop
|
|
636
632
|
// downstream: propagation never queues pended subscribers as pending
|
|
637
633
|
// nodes, see propagateAffectsMark, #2893.
|
|
638
|
-
for (let e = 0; e < t.
|
|
639
|
-
const i = t.
|
|
634
|
+
for (let e = 0; e < t.Mt.length; e++) {
|
|
635
|
+
const i = t.Mt[e];
|
|
640
636
|
i.Ae = activeTransition;
|
|
641
|
-
activeTransition.
|
|
637
|
+
activeTransition.Mt.push(i);
|
|
642
638
|
}
|
|
643
|
-
for (let e = 0; e < t.
|
|
644
|
-
const i = t.
|
|
639
|
+
for (let e = 0; e < t.Xe.length; e++) {
|
|
640
|
+
const i = t.Xe[e];
|
|
645
641
|
i.Ae = activeTransition;
|
|
646
|
-
activeTransition.
|
|
642
|
+
activeTransition.Xe.push(i);
|
|
647
643
|
}
|
|
648
644
|
if (t.A.length) activeTransition.A.push(...t.A);
|
|
649
645
|
for (const e of t.En) activeTransition.En.add(e);
|
|
@@ -671,7 +667,7 @@ class GlobalQueue extends Queue {
|
|
|
671
667
|
}
|
|
672
668
|
|
|
673
669
|
function queuePendingNode(e) {
|
|
674
|
-
currentBatch.
|
|
670
|
+
currentBatch.Mt.push(e);
|
|
675
671
|
}
|
|
676
672
|
|
|
677
673
|
// Sticky: flips true on the first refresh() ever (the only setter of
|
|
@@ -695,7 +691,7 @@ function armReaskClear() {
|
|
|
695
691
|
function insertSubs(e, t = false) {
|
|
696
692
|
// §12d: stamp before walking — setSignal's staged-rewrite fast path skips
|
|
697
693
|
// the next walk for this node while the epoch holds (marking is idempotent).
|
|
698
|
-
e.
|
|
694
|
+
e.Et = notifyEpoch;
|
|
699
695
|
// Get source lane: prefer node's own lane over current context
|
|
700
696
|
// This is important for isPending signals which need their own lane to flush immediately
|
|
701
697
|
// Presence bits gate the optional-slot probes (see constants.ts): one
|
|
@@ -703,8 +699,8 @@ function insertSubs(e, t = false) {
|
|
|
703
699
|
// lookups in the hottest notify loop. Bits are sticky — the field read
|
|
704
700
|
// stays authoritative when a bit is set.
|
|
705
701
|
const i = e.T;
|
|
706
|
-
const n = (i & CONFIG_HAS_LANE ? e.o
|
|
707
|
-
const r = (i & CONFIG_HAS_SNAPSHOT) !== 0 && e.o?.
|
|
702
|
+
const n = (i & CONFIG_HAS_LANE ? e.o?.$e : undefined) || currentOptimisticLane;
|
|
703
|
+
const r = (i & CONFIG_HAS_SNAPSHOT) !== 0 && e.o?.Ye !== undefined;
|
|
708
704
|
const s = reaskArmed;
|
|
709
705
|
for (let i = e.u; i !== null; i = i.ae) {
|
|
710
706
|
const e = i.ce;
|
|
@@ -719,7 +715,7 @@ function insertSubs(e, t = false) {
|
|
|
719
715
|
// pass either re-reads them fresh or trims them), and neither does the
|
|
720
716
|
// tail link: it is the read IN FLIGHT — read() links before it pulls, so
|
|
721
717
|
// this very commit is what that read returns.
|
|
722
|
-
if (e.ie & REACTIVE_RECOMPUTING_DEPS && i.
|
|
718
|
+
if (e.ie & REACTIVE_RECOMPUTING_DEPS && i.vt === e.ze && i !== e.Be) e.ie |= REACTIVE_MISSED_WAKE;
|
|
723
719
|
if (r && e.T & CONFIG_IN_SNAPSHOT_SCOPE) {
|
|
724
720
|
e.ie |= REACTIVE_SNAPSHOT_STALE;
|
|
725
721
|
continue;
|
|
@@ -730,7 +726,7 @@ function insertSubs(e, t = false) {
|
|
|
730
726
|
} else if (t) {
|
|
731
727
|
e.ie |= REACTIVE_OPTIMISTIC_DIRTY;
|
|
732
728
|
// No source lane means reversion - clear subscriber's lane so effects go to regular queue
|
|
733
|
-
if (e.o) e.o
|
|
729
|
+
if (e.o) e.o.$e = undefined;
|
|
734
730
|
}
|
|
735
731
|
enqueueSub(e);
|
|
736
732
|
}
|
|
@@ -750,7 +746,7 @@ function commitPendingNode(e) {
|
|
|
750
746
|
e.be = e.Re;
|
|
751
747
|
e.Re = NOT_PENDING;
|
|
752
748
|
// Set _modified for effects, but not for tracked effects (they handle their own scheduling)
|
|
753
|
-
if (e.ge && e.ge !== EFFECT_TRACKED) e.
|
|
749
|
+
if (e.ge && e.ge !== EFFECT_TRACKED) e.He = true;
|
|
754
750
|
// A quiet re-ask classification preserved through a held landing dies
|
|
755
751
|
// with the value commit — the commit IS the reveal (#3178). Gated on the
|
|
756
752
|
// staged value: status propagation queues pending nodes whose windows
|
|
@@ -764,7 +760,7 @@ function commitPendingNode(e) {
|
|
|
764
760
|
t.Ne = false;
|
|
765
761
|
t.ie &= ~REACTIVE_MANUAL_WRITE;
|
|
766
762
|
if (!(t.S & STATUS_PENDING)) t.S &= ~STATUS_UNINITIALIZED;
|
|
767
|
-
if (t.o != null && (t.o.
|
|
763
|
+
if (t.o != null && (t.o.Ke !== null || t.o.Ze !== null)) GlobalQueue.ke(t, false, true);
|
|
768
764
|
if (e.T & CONFIG_HAS_COMPANIONS) GlobalQueue.un(e);
|
|
769
765
|
}
|
|
770
766
|
|
|
@@ -779,17 +775,6 @@ function setStoreCommitHook(e) {
|
|
|
779
775
|
storeCommitHook = e;
|
|
780
776
|
}
|
|
781
777
|
|
|
782
|
-
/** Patch-channel release hook (next/patch.ts): transition-stamped patch
|
|
783
|
-
* emissions are released when THEIR batch commits. Transitions never
|
|
784
|
-
* abort: failed actions still commit (only optimistic overrides revert),
|
|
785
|
-
* and merged-away transitions hand their stash to the survivor
|
|
786
|
-
* (mergeTransitionState) — every stash drains exactly once. Injected like
|
|
787
|
-
* storeCommitHook to stay tree-shakeable. */ let patchCommitHook = null;
|
|
788
|
-
|
|
789
|
-
function setPatchCommitHook(e) {
|
|
790
|
-
patchCommitHook = e;
|
|
791
|
-
}
|
|
792
|
-
|
|
793
778
|
/** Held truth committed this finalize, awaiting its post-revert wake (see
|
|
794
779
|
* finalizePureQueue): the commit IS the reveal, but subscribers must not
|
|
795
780
|
* re-derive until the settling transaction's optimistic overrides have
|
|
@@ -798,7 +783,7 @@ function setPatchCommitHook(e) {
|
|
|
798
783
|
* frame no timeline contains. */ const heldRevealed = [];
|
|
799
784
|
|
|
800
785
|
function commitPendingNodes() {
|
|
801
|
-
const e = currentBatch.
|
|
786
|
+
const e = currentBatch.Mt;
|
|
802
787
|
for (let t = 0; t < e.length; t++) {
|
|
803
788
|
const i = e[t];
|
|
804
789
|
commitPendingNode(i);
|
|
@@ -821,7 +806,6 @@ function commitPendingNodes() {
|
|
|
821
806
|
}
|
|
822
807
|
e.length = 0;
|
|
823
808
|
storeCommitHook?.();
|
|
824
|
-
patchCommitHook?.(currentBatch);
|
|
825
809
|
}
|
|
826
810
|
|
|
827
811
|
function finalizePureQueue(e = null, t = false) {
|
|
@@ -829,8 +813,8 @@ function finalizePureQueue(e = null, t = false) {
|
|
|
829
813
|
// For completing transitions or no-transition, resolve pending and revert optimistic
|
|
830
814
|
const i = !t;
|
|
831
815
|
if (i) commitPendingNodes();
|
|
832
|
-
if (!t && globalQueue.
|
|
833
|
-
const n = dirtyQueue.EE >= dirtyQueue.
|
|
816
|
+
if (!t && globalQueue.Bt.length) checkBoundaryChildren(globalQueue);
|
|
817
|
+
const n = dirtyQueue.EE >= dirtyQueue.Me;
|
|
834
818
|
if (n) runHeap(dirtyQueue, GlobalQueue.Fe);
|
|
835
819
|
if (i) {
|
|
836
820
|
if (n) commitPendingNodes();
|
|
@@ -838,7 +822,7 @@ function finalizePureQueue(e = null, t = false) {
|
|
|
838
822
|
const t = e ?? globalQueue.m;
|
|
839
823
|
// Optimistic reversion: a non-empty batch means _optimisticWrite ran,
|
|
840
824
|
// which installed the engine's hooks.
|
|
841
|
-
if (t.
|
|
825
|
+
if (t.Xe.length) GlobalQueue.Tn(t.Xe);
|
|
842
826
|
// Replay entanglement: subs recorded by the read-time gate get rescheduled
|
|
843
827
|
// so they re-run with the now-committed values visible. The ambient batch
|
|
844
828
|
// replays too — laneReadsCommitted records readers whose committed-view
|
|
@@ -862,13 +846,13 @@ function finalizePureQueue(e = null, t = false) {
|
|
|
862
846
|
// (the earlier sweep above ran while the marks were still live).
|
|
863
847
|
if (t.A.length) {
|
|
864
848
|
GlobalQueue.G(t.A);
|
|
865
|
-
if (globalQueue.
|
|
849
|
+
if (globalQueue.Bt.length) checkBoundaryChildren(globalQueue);
|
|
866
850
|
}
|
|
867
851
|
// A non-empty set means trackOptimisticStore ran, which installed the
|
|
868
852
|
// hook; the hook iterates, clears, and schedules (keeping the loop out of
|
|
869
853
|
// core lets esbuild shake it — rollup already folds the null guard). The
|
|
870
854
|
// completing transition scopes the clear to its own layer keys (#2899).
|
|
871
|
-
if (t.En.size) GlobalQueue.
|
|
855
|
+
if (t.En.size) GlobalQueue.Wt(t.En, e);
|
|
872
856
|
// Held-truth reveal wake (#3164), post-revert by construction: this
|
|
873
857
|
// finalize committed confirming truth whose subscribers were masked all
|
|
874
858
|
// hold — some re-derived against the committed view (the staging, or a
|
|
@@ -880,7 +864,7 @@ function finalizePureQueue(e = null, t = false) {
|
|
|
880
864
|
// committed but the settling transaction's overrides still display.
|
|
881
865
|
if (heldRevealed.length !== 0) {
|
|
882
866
|
while (heldRevealed.length) insertSubs(heldRevealed.pop());
|
|
883
|
-
if (dirtyQueue.EE >= dirtyQueue.
|
|
867
|
+
if (dirtyQueue.EE >= dirtyQueue.Me) {
|
|
884
868
|
runHeap(dirtyQueue, GlobalQueue.Fe);
|
|
885
869
|
commitPendingNodes();
|
|
886
870
|
}
|
|
@@ -892,7 +876,7 @@ function finalizePureQueue(e = null, t = false) {
|
|
|
892
876
|
}
|
|
893
877
|
|
|
894
878
|
function checkBoundaryChildren(e) {
|
|
895
|
-
for (const t of e.
|
|
879
|
+
for (const t of e.Bt) {
|
|
896
880
|
t.se?.();
|
|
897
881
|
checkBoundaryChildren(t);
|
|
898
882
|
}
|
|
@@ -962,11 +946,11 @@ function runQueue(e, t) {
|
|
|
962
946
|
function reporterBlocksSource(e, t) {
|
|
963
947
|
if (e.ie & (REACTIVE_ZOMBIE | REACTIVE_DISPOSED)) return false;
|
|
964
948
|
if (e.o?.le?.has(t)) return true;
|
|
965
|
-
for (let i = e.
|
|
966
|
-
let e = i.
|
|
949
|
+
for (let i = e.lt; i; i = i.ot) {
|
|
950
|
+
let e = i.st;
|
|
967
951
|
while (e) {
|
|
968
|
-
if (e === t || e.
|
|
969
|
-
e = e.o?.
|
|
952
|
+
if (e === t || e.rt === t) return true;
|
|
953
|
+
e = e.o?.St;
|
|
970
954
|
}
|
|
971
955
|
}
|
|
972
956
|
return !!(e.S & STATUS_PENDING && e.o?._ instanceof NotReadyError && e.o?._.source === t);
|
|
@@ -974,7 +958,9 @@ function reporterBlocksSource(e, t) {
|
|
|
974
958
|
|
|
975
959
|
function transitionComplete(e) {
|
|
976
960
|
if (e.sn) return true;
|
|
977
|
-
if (e.ue.length)
|
|
961
|
+
if (e.ue.length) {
|
|
962
|
+
return false;
|
|
963
|
+
}
|
|
978
964
|
let t = true;
|
|
979
965
|
for (const [i, n] of e._e) {
|
|
980
966
|
let r = false;
|
|
@@ -1043,4 +1029,4 @@ function runInTransition(e, t) {
|
|
|
1043
1029
|
}
|
|
1044
1030
|
}
|
|
1045
1031
|
|
|
1046
|
-
export { GlobalQueue, Queue, activeAffectsMarks, activeLanes, activeTransition, armReaskClear, assignOrMergeLane, bumpNotifyEpoch, clock, createTransition, currentTransition, dirtyQueue, enforceLoadingBoundary, entangleConfirmingTransitions, finalizePureQueue, findLane, flush, globalQueue, haltReactivity, hasActiveOverride, insertSubs, notifyEpoch,
|
|
1032
|
+
export { GlobalQueue, Queue, activeAffectsMarks, activeLanes, activeTransition, armReaskClear, assignOrMergeLane, bumpNotifyEpoch, clock, createTransition, currentTransition, dirtyQueue, enforceLoadingBoundary, entangleConfirmingTransitions, finalizePureQueue, findLane, flush, globalQueue, haltReactivity, hasActiveOverride, insertSubs, notifyEpoch, projectionWriteActive, queuePendingNode, reaskArmed, resetErrorHalt, runAsTransitionBatch, runInTransition, schedule, setProjectionWriteActive, setStoreCommitHook, shiftAffectsMarks, storeCommitHook, zombieQueue };
|