@solidjs/signals 2.0.0-rc.0 → 2.0.0-rc.2
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/README.md +1 -1
- package/dist/dev.js +4287 -2803
- package/dist/node.cjs +4563 -3756
- package/dist/prod/affects.js +16 -16
- package/dist/prod/boundaries.js +90 -90
- package/dist/prod/core/action.js +3 -3
- package/dist/prod/core/async.js +234 -178
- package/dist/prod/core/constants.js +39 -1
- package/dist/prod/core/core.js +362 -243
- package/dist/prod/core/effect.js +56 -56
- package/dist/prod/core/external.js +4 -4
- package/dist/prod/core/graph.js +65 -54
- package/dist/prod/core/heap.js +47 -39
- package/dist/prod/core/invariants.js +3 -2
- package/dist/prod/core/lanes.js +41 -34
- package/dist/prod/core/optimistic.js +78 -58
- package/dist/prod/core/owner.js +101 -100
- package/dist/prod/core/scheduler.js +249 -192
- package/dist/prod/core/verdict.js +185 -78
- package/dist/prod/index.js +7 -7
- package/dist/prod/map.js +108 -106
- package/dist/prod/signals.js +20 -1
- package/dist/prod/store/index.js +36 -0
- package/dist/prod/store/next/optimistic.js +385 -0
- package/dist/prod/store/next/projection.js +172 -0
- package/dist/prod/store/next/reconcile.js +331 -0
- package/dist/prod/store/next/store.js +1499 -0
- package/dist/prod/store/next/target.js +20 -0
- package/dist/prod/store/store.js +126 -882
- package/dist/prod/store/utils.js +59 -186
- package/dist/types/core/attribution-hooks.d.ts +52 -0
- package/dist/types/core/attribution.d.ts +186 -0
- package/dist/types/core/constants.d.ts +26 -0
- package/dist/types/core/core.d.ts +16 -1
- package/dist/types/core/dev.d.ts +20 -3
- package/dist/types/core/graph.d.ts +1 -0
- package/dist/types/core/lanes.d.ts +4 -16
- package/dist/types/core/scheduler.d.ts +12 -2
- package/dist/types/core/types.d.ts +85 -41
- package/dist/types/signals.d.ts +19 -0
- package/dist/types/store/index.d.ts +15 -5
- package/dist/types/store/next/optimistic.d.ts +20 -0
- package/dist/types/store/next/projection.d.ts +8 -0
- package/dist/types/store/next/reconcile.d.ts +3 -0
- package/dist/types/store/next/store.d.ts +77 -0
- package/dist/types/store/next/target.d.ts +117 -0
- package/dist/types/store/store.d.ts +26 -101
- package/dist/types/store/utils.d.ts +0 -40
- package/dist/types-cjs/core/attribution-hooks.d.cts +52 -0
- package/dist/types-cjs/core/attribution.d.cts +186 -0
- package/dist/types-cjs/core/constants.d.cts +26 -0
- package/dist/types-cjs/core/core.d.cts +16 -1
- package/dist/types-cjs/core/dev.d.cts +20 -3
- package/dist/types-cjs/core/graph.d.cts +1 -0
- package/dist/types-cjs/core/lanes.d.cts +4 -16
- package/dist/types-cjs/core/scheduler.d.cts +12 -2
- package/dist/types-cjs/core/types.d.cts +85 -41
- package/dist/types-cjs/signals.d.cts +19 -0
- package/dist/types-cjs/store/index.d.cts +15 -5
- package/dist/types-cjs/store/next/optimistic.d.cts +20 -0
- package/dist/types-cjs/store/next/projection.d.cts +8 -0
- package/dist/types-cjs/store/next/reconcile.d.cts +3 -0
- package/dist/types-cjs/store/next/store.d.cts +77 -0
- package/dist/types-cjs/store/next/target.d.cts +117 -0
- package/dist/types-cjs/store/store.d.cts +26 -101
- package/dist/types-cjs/store/utils.d.cts +0 -40
- package/package.json +2 -1
- package/dist/prod/store/optimistic.js +0 -217
- package/dist/prod/store/projection.js +0 -231
- package/dist/prod/store/reconcile.js +0 -707
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EFFECT_RENDER, EFFECT_USER, STATUS_PENDING, REACTIVE_IN_HEAP_HEIGHT, REACTIVE_DISPOSED, REACTIVE_ZOMBIE, NOT_PENDING, EFFECT_TRACKED, CONFIG_IN_SNAPSHOT_SCOPE, REACTIVE_SNAPSHOT_STALE, REACTIVE_OPTIMISTIC_DIRTY, REACTIVE_REASK, REACTIVE_MANUAL_WRITE, STATUS_UNINITIALIZED } from "./constants.js";
|
|
1
|
+
import { EFFECT_RENDER, EFFECT_USER, STATUS_PENDING, REACTIVE_IN_HEAP_HEIGHT, REACTIVE_DISPOSED, REACTIVE_ZOMBIE, NOT_PENDING, CONFIG_HAS_COMPANIONS, EFFECT_TRACKED, CONFIG_HAS_LANE, CONFIG_HAS_SNAPSHOT, REACTIVE_RECOMPUTING_DEPS, REACTIVE_MISSED_WAKE, CONFIG_IN_SNAPSHOT_SCOPE, REACTIVE_SNAPSHOT_STALE, REACTIVE_OPTIMISTIC_DIRTY, REACTIVE_REASK, REACTIVE_MANUAL_WRITE, STATUS_UNINITIALIZED } from "./constants.js";
|
|
2
2
|
|
|
3
3
|
import { currentOptimisticLane } from "./core.js";
|
|
4
4
|
|
|
@@ -19,23 +19,23 @@ const transitions = new Set;
|
|
|
19
19
|
const dirtyQueue = {
|
|
20
20
|
eE: new Array(2e3).fill(undefined),
|
|
21
21
|
tE: false,
|
|
22
|
-
|
|
22
|
+
xe: 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
|
+
xe: 0,
|
|
30
30
|
EE: 0
|
|
31
31
|
};
|
|
32
32
|
|
|
33
33
|
/** runHeap callback that discards a queued zombie recompute instead of running
|
|
34
34
|
* it: unlink pure recompute entries; strip just the recompute bit from dirtied
|
|
35
35
|
* height-adjust entries so their height work still happens. */ function cancelZombieRecompute(e) {
|
|
36
|
-
if (e.
|
|
36
|
+
if (e.ie & REACTIVE_IN_HEAP_HEIGHT) e.ie &= -12; else {
|
|
37
37
|
deleteFromHeap(e, zombieQueue);
|
|
38
|
-
e.
|
|
38
|
+
e.ie &= -4;
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
|
|
@@ -59,30 +59,26 @@ let projectionWriteActive = false;
|
|
|
59
59
|
// releasing the slot in the parent store's node map.
|
|
60
60
|
const transientStoreNodes = new Set;
|
|
61
61
|
|
|
62
|
-
function registerTransientStoreNode(e) {
|
|
63
|
-
transientStoreNodes.add(e);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
62
|
function canUseSimpleSyncFlush(e) {
|
|
67
|
-
const t = e.
|
|
68
|
-
return transitions.size === 0 && activeLanes.size === 0 && e.
|
|
63
|
+
const t = e.k;
|
|
64
|
+
return transitions.size === 0 && activeLanes.size === 0 && e.Qt.length === 0 && t.Ke.length === 0 && t.m.length === 0 && t.cn.size === 0 && transientStoreNodes.size === 0;
|
|
69
65
|
}
|
|
70
66
|
|
|
71
67
|
function sweepTransientStoreNodes() {
|
|
72
68
|
if (transientStoreNodes.size === 0) return;
|
|
73
69
|
for (const e of transientStoreNodes) {
|
|
74
|
-
if (e.
|
|
70
|
+
if (e.u !== null) {
|
|
75
71
|
transientStoreNodes.delete(e);
|
|
76
72
|
continue;
|
|
77
73
|
}
|
|
78
|
-
if (e.
|
|
79
|
-
if (e.
|
|
74
|
+
if (e.Pe !== NOT_PENDING) continue;
|
|
75
|
+
if (e.o?.De !== undefined && e.o?.De !== NOT_PENDING) continue;
|
|
80
76
|
// A live affects() mark keeps the node addressable: sweeping it would
|
|
81
77
|
// detach the refcount from the slot (a fresh probe would upsert a new,
|
|
82
78
|
// unmarked node for the same property).
|
|
83
|
-
if (e.t) continue;
|
|
79
|
+
if (e.o?.t) continue;
|
|
84
80
|
transientStoreNodes.delete(e);
|
|
85
|
-
e.
|
|
81
|
+
e.o?.ft?.();
|
|
86
82
|
}
|
|
87
83
|
}
|
|
88
84
|
|
|
@@ -109,44 +105,44 @@ function setProjectionWriteActive(e) {
|
|
|
109
105
|
* land there directly — no per-field aliasing.
|
|
110
106
|
*/ function createBatch() {
|
|
111
107
|
return {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
108
|
+
Te: clock,
|
|
109
|
+
yt: [],
|
|
110
|
+
Ne: new Map,
|
|
111
|
+
Ke: [],
|
|
112
|
+
m: [],
|
|
117
113
|
cn: new Set,
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
114
|
+
oe: [],
|
|
115
|
+
bt: {
|
|
116
|
+
Lt: [ [], [] ],
|
|
117
|
+
Qt: []
|
|
122
118
|
},
|
|
123
|
-
|
|
119
|
+
an: false,
|
|
124
120
|
ln: new Set
|
|
125
121
|
};
|
|
126
122
|
}
|
|
127
123
|
|
|
128
124
|
function mergeTransitionState(e, t) {
|
|
129
|
-
t.
|
|
130
|
-
e.
|
|
131
|
-
for (const i of activeLanes) if (i.
|
|
132
|
-
if (t.
|
|
125
|
+
t.an = e;
|
|
126
|
+
e.oe.push(...t.oe);
|
|
127
|
+
for (const i of activeLanes) if (i._e === t) i._e = e;
|
|
128
|
+
if (t.Ke.length) {
|
|
133
129
|
// Move (don't copy): the global queue's batch may still be the outgoing
|
|
134
130
|
// transition, and the adoption pass in initTransition would re-push its
|
|
135
131
|
// contents into the target — duplicating every entry.
|
|
136
|
-
e.
|
|
137
|
-
t.
|
|
132
|
+
e.Ke.push(...t.Ke);
|
|
133
|
+
t.Ke.length = 0;
|
|
138
134
|
}
|
|
139
|
-
if (t.
|
|
135
|
+
if (t.m.length) {
|
|
140
136
|
// Move (don't copy): the global queue's batch may still be the outgoing
|
|
141
137
|
// transition, and the adoption pass in initTransition would re-push its
|
|
142
138
|
// contents into the target — double-releasing every mark.
|
|
143
|
-
e.
|
|
144
|
-
t.
|
|
139
|
+
e.m.push(...t.m);
|
|
140
|
+
t.m.length = 0;
|
|
145
141
|
}
|
|
146
142
|
for (const i of t.cn) e.cn.add(i);
|
|
147
|
-
for (const [i, n] of t.
|
|
148
|
-
let t = e.
|
|
149
|
-
if (!t) e.
|
|
143
|
+
for (const [i, n] of t.Ne) {
|
|
144
|
+
let t = e.Ne.get(i);
|
|
145
|
+
if (!t) e.Ne.set(i, t = new Set);
|
|
150
146
|
for (const e of n) t.add(e);
|
|
151
147
|
}
|
|
152
148
|
for (const i of t.ln) e.ln.add(i);
|
|
@@ -159,7 +155,7 @@ function schedule() {
|
|
|
159
155
|
}
|
|
160
156
|
if (scheduled) return;
|
|
161
157
|
scheduled = true;
|
|
162
|
-
if (!syncDepth && !globalQueue.
|
|
158
|
+
if (!syncDepth && !globalQueue.sn && !projectionWriteActive) queueMicrotask(flush);
|
|
163
159
|
}
|
|
164
160
|
|
|
165
161
|
/**
|
|
@@ -193,30 +189,30 @@ function notifyHalted() {
|
|
|
193
189
|
let queueRunToken = 0;
|
|
194
190
|
|
|
195
191
|
class Queue {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
192
|
+
ve=null;
|
|
193
|
+
Lt=[ [], [] ];
|
|
194
|
+
Qt=[];
|
|
195
|
+
Mt=0;
|
|
200
196
|
created=clock;
|
|
201
197
|
addChild(e) {
|
|
202
|
-
this.
|
|
203
|
-
e.
|
|
198
|
+
this.Qt.push(e);
|
|
199
|
+
e.ve = this;
|
|
204
200
|
}
|
|
205
201
|
removeChild(e) {
|
|
206
|
-
const t = this.
|
|
202
|
+
const t = this.Qt.indexOf(e);
|
|
207
203
|
if (t >= 0) {
|
|
208
|
-
this.
|
|
209
|
-
e.
|
|
204
|
+
this.Qt.splice(t, 1);
|
|
205
|
+
e.ve = null;
|
|
210
206
|
}
|
|
211
207
|
}
|
|
212
208
|
notify(e, t, i, n) {
|
|
213
|
-
if (this.
|
|
209
|
+
if (this.ve) return this.ve.notify(e, t, i, n);
|
|
214
210
|
return false;
|
|
215
211
|
}
|
|
216
212
|
run(e) {
|
|
217
|
-
if (this.
|
|
218
|
-
const t = this.
|
|
219
|
-
this.
|
|
213
|
+
if (this.Lt[e - 1].length) {
|
|
214
|
+
const t = this.Lt[e - 1];
|
|
215
|
+
this.Lt[e - 1] = [];
|
|
220
216
|
runQueue(t, e);
|
|
221
217
|
}
|
|
222
218
|
// Effects run here can dispose owners, and disposal removes queues from
|
|
@@ -226,12 +222,12 @@ class Queue {
|
|
|
226
222
|
// can be recovered by rescanning from the front and every child still runs
|
|
227
223
|
// exactly once. Children appended mid-pass carry a stale stamp and run,
|
|
228
224
|
// matching the previous live-array behaviour.
|
|
229
|
-
const t = this.
|
|
225
|
+
const t = this.Qt;
|
|
230
226
|
const i = ++queueRunToken;
|
|
231
227
|
for (let n = 0; n < t.length; ) {
|
|
232
228
|
const s = t[n];
|
|
233
|
-
if (s.
|
|
234
|
-
s.
|
|
229
|
+
if (s.Mt !== i) {
|
|
230
|
+
s.Mt = i;
|
|
235
231
|
s.run?.(e);
|
|
236
232
|
if (t[n] !== s) {
|
|
237
233
|
n = 0;
|
|
@@ -246,81 +242,84 @@ class Queue {
|
|
|
246
242
|
// Route to lane's effect queue if we're in an optimistic recomputation
|
|
247
243
|
if (currentOptimisticLane) {
|
|
248
244
|
const i = findLane(currentOptimisticLane);
|
|
249
|
-
i.
|
|
245
|
+
i.en[e - 1].push(t);
|
|
250
246
|
} else {
|
|
251
|
-
this.
|
|
247
|
+
this.Lt[e - 1].push(t);
|
|
252
248
|
}
|
|
253
249
|
}
|
|
254
250
|
schedule();
|
|
255
251
|
}
|
|
256
252
|
stashQueues(e) {
|
|
257
|
-
e.
|
|
258
|
-
e.
|
|
259
|
-
this.
|
|
260
|
-
for (let t = 0; t < this.
|
|
261
|
-
let i = this.
|
|
262
|
-
let n = e.
|
|
253
|
+
e.Lt[0].push(...this.Lt[0]);
|
|
254
|
+
e.Lt[1].push(...this.Lt[1]);
|
|
255
|
+
this.Lt = [ [], [] ];
|
|
256
|
+
for (let t = 0; t < this.Qt.length; t++) {
|
|
257
|
+
let i = this.Qt[t];
|
|
258
|
+
let n = e.Qt[t];
|
|
263
259
|
if (!n) {
|
|
264
260
|
n = {
|
|
265
|
-
|
|
266
|
-
|
|
261
|
+
Lt: [ [], [] ],
|
|
262
|
+
Qt: []
|
|
267
263
|
};
|
|
268
|
-
e.
|
|
264
|
+
e.Qt[t] = n;
|
|
269
265
|
}
|
|
270
266
|
i.stashQueues(n);
|
|
271
267
|
}
|
|
272
268
|
}
|
|
273
269
|
restoreQueues(e) {
|
|
274
|
-
this.
|
|
275
|
-
this.
|
|
276
|
-
for (let t = 0; t < e.
|
|
277
|
-
const i = e.
|
|
278
|
-
let n = this.
|
|
270
|
+
this.Lt[0].push(...e.Lt[0]);
|
|
271
|
+
this.Lt[1].push(...e.Lt[1]);
|
|
272
|
+
for (let t = 0; t < e.Qt.length; t++) {
|
|
273
|
+
const i = e.Qt[t];
|
|
274
|
+
let n = this.Qt[t];
|
|
279
275
|
if (n) n.restoreQueues(i);
|
|
280
276
|
}
|
|
281
277
|
}
|
|
282
278
|
}
|
|
283
279
|
|
|
284
280
|
class GlobalQueue extends Queue {
|
|
285
|
-
|
|
281
|
+
sn=false;
|
|
286
282
|
// The current transaction-shaped batch: a plain ambient batch while no
|
|
287
283
|
// transition is active, the active transition itself after initTransition.
|
|
288
|
-
|
|
284
|
+
k=createBatch();
|
|
289
285
|
static Ce;
|
|
290
|
-
static
|
|
291
|
-
static
|
|
292
|
-
static
|
|
286
|
+
static Fe;
|
|
287
|
+
static tt;
|
|
288
|
+
static Vt=null;
|
|
293
289
|
// Store-side hook: drops a keyless affects() mark's identity scope when the
|
|
294
290
|
// carrier node's last registration releases (wired by store.ts, mirroring
|
|
295
291
|
// _clearOptimisticStore).
|
|
296
|
-
static
|
|
292
|
+
static G=null;
|
|
297
293
|
// affects()-side hooks (wired by affects.ts, mirroring _update): the mark
|
|
298
294
|
// engine — count/register/release — lives with the feature. Every call site
|
|
299
295
|
// is gated by state only that module creates, so `!` invocations are safe
|
|
300
296
|
// once the gate holds.
|
|
301
|
-
static G=null;
|
|
302
297
|
static M=null;
|
|
303
298
|
static h=null;
|
|
299
|
+
static j=null;
|
|
304
300
|
// External-source bridge (wired by enableExternalSource(); null while no
|
|
305
301
|
// config is active — including after _resetExternalSourceConfig()).
|
|
306
|
-
static
|
|
307
|
-
static
|
|
302
|
+
static Rt=null;
|
|
303
|
+
static Gt=null;
|
|
308
304
|
// Verdict-layer hooks (wired by verdict.ts when isPending()/latest() are
|
|
309
305
|
// imported; null in apps that never use them). Call sites either guard for
|
|
310
306
|
// null or sit behind state only the verdict layer can create (`!` is safe
|
|
311
307
|
// there: `_pendingSignal`/`_latestValueComputed` are only ever assigned by
|
|
312
308
|
// verdict.ts, and `pendingCheckActive`/`latestReadActive` only flip inside
|
|
313
309
|
// isPending()/latest()).
|
|
314
|
-
static Pe=null;
|
|
315
|
-
static Se=null;
|
|
316
310
|
static Oe=null;
|
|
311
|
+
static de=null;
|
|
312
|
+
static ye=null;
|
|
317
313
|
static un=null;
|
|
318
|
-
static
|
|
319
|
-
static
|
|
320
|
-
static
|
|
321
|
-
static
|
|
322
|
-
static
|
|
323
|
-
static
|
|
314
|
+
static Pt=null;
|
|
315
|
+
static Dt=null;
|
|
316
|
+
static Ht=null;
|
|
317
|
+
static Je=null;
|
|
318
|
+
static p=null;
|
|
319
|
+
static Bt=null;
|
|
320
|
+
// Re-asks probes whose verdict was provisionally suppressed by a fresh read
|
|
321
|
+
// of a held value, once the transaction gains an async blocker (#3028).
|
|
322
|
+
static wt=null;
|
|
324
323
|
// Optimistic-engine hooks (wired by core/optimistic.ts via
|
|
325
324
|
// installOptimisticEngine(), called from verdict.ts / createOptimistic /
|
|
326
325
|
// createOptimisticStore — every module that can create optimistic state).
|
|
@@ -328,21 +327,37 @@ class GlobalQueue extends Queue {
|
|
|
328
327
|
// `_overrideValue` slot, a lane in `activeLanes`, an `_optimisticNodes`
|
|
329
328
|
// entry, or a non-null `currentOptimisticLane`, so `!` invocations are safe
|
|
330
329
|
// once the gate holds.
|
|
331
|
-
static
|
|
330
|
+
static vt=null;
|
|
331
|
+
static fn=null;
|
|
332
|
+
static dn=null;
|
|
332
333
|
static En=null;
|
|
333
334
|
static Tn=null;
|
|
334
|
-
static
|
|
335
|
-
static
|
|
336
|
-
static
|
|
337
|
-
static Ot=null;
|
|
338
|
-
static Pt=null;
|
|
335
|
+
static Ft=null;
|
|
336
|
+
static ht=null;
|
|
337
|
+
static gt=null;
|
|
339
338
|
static je=null;
|
|
340
339
|
static $e=null;
|
|
341
340
|
static ze=null;
|
|
342
341
|
static Nn=null;
|
|
343
342
|
flush() {
|
|
344
|
-
if (this.
|
|
345
|
-
|
|
343
|
+
if (this.sn) return;
|
|
344
|
+
// Fast drain: nothing in flight but plain pending commits — no dirty
|
|
345
|
+
// computeds, no queued effects, no child queues, no transitions/lanes/
|
|
346
|
+
// optimistic state. Commit and go; anything a commit hook schedules
|
|
347
|
+
// (companion snaps, store folds notifying subs) re-arms `scheduled`
|
|
348
|
+
// below and the outer drain loop takes the full spine next round.
|
|
349
|
+
if (activeTransition === null && dirtyQueue.EE < dirtyQueue.xe && this.Lt[0].length === 0 && this.Lt[1].length === 0 && this.Qt.length === 0 && canUseSimpleSyncFlush(this)) {
|
|
350
|
+
this.sn = true;
|
|
351
|
+
try {
|
|
352
|
+
commitPendingNodes();
|
|
353
|
+
} finally {
|
|
354
|
+
this.sn = false;
|
|
355
|
+
}
|
|
356
|
+
clock++;
|
|
357
|
+
scheduled = dirtyQueue.EE >= dirtyQueue.xe || this.Lt[0].length !== 0 || this.Lt[1].length !== 0 || this.k.yt.length !== 0;
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
this.sn = true;
|
|
346
361
|
try {
|
|
347
362
|
if (false) ;
|
|
348
363
|
runHeap(dirtyQueue, GlobalQueue.Ce);
|
|
@@ -358,53 +373,53 @@ class GlobalQueue extends Queue {
|
|
|
358
373
|
// zombies here. Height-adjust entries still process normally: a
|
|
359
374
|
// dirtied one keeps its height flag and falls through to runHeap's
|
|
360
375
|
// adjustHeight path on the next pass of the bucket.
|
|
361
|
-
runHeap(zombieQueue, this.
|
|
376
|
+
runHeap(zombieQueue, this.k === e ? cancelZombieRecompute : GlobalQueue.Ce);
|
|
362
377
|
// Detach: the stashed transition keeps its batch; ambient work that
|
|
363
378
|
// follows lands in a fresh one. If the batch is already a separate
|
|
364
379
|
// ambient one — action done() restored activeTransition without
|
|
365
380
|
// adopting the batch, and an ordinary write landed there before
|
|
366
381
|
// the scheduled flush (#2916) — keep it: replacing it would strand
|
|
367
382
|
// its queued pending nodes with held _pendingValues forever.
|
|
368
|
-
if (this.
|
|
383
|
+
if (this.k === e) currentBatch = this.k = createBatch();
|
|
369
384
|
// Run lane effects immediately (before stashing) - lanes with no pending async
|
|
370
385
|
if (activeLanes.size) {
|
|
371
|
-
GlobalQueue.
|
|
372
|
-
GlobalQueue.
|
|
386
|
+
GlobalQueue.Tn(EFFECT_RENDER);
|
|
387
|
+
GlobalQueue.Tn(EFFECT_USER);
|
|
373
388
|
}
|
|
374
|
-
this.stashQueues(e.
|
|
389
|
+
this.stashQueues(e.bt);
|
|
375
390
|
clock++;
|
|
376
391
|
// A kept ambient batch may hold pending nodes (#2916): stay
|
|
377
392
|
// scheduled so the outer drain loop commits them via the plain
|
|
378
393
|
// flush path instead of leaving them until the next natural flush.
|
|
379
|
-
scheduled = dirtyQueue.EE >= dirtyQueue.
|
|
380
|
-
reassignPendingTransition(e.
|
|
394
|
+
scheduled = dirtyQueue.EE >= dirtyQueue.xe || this.k.yt.length > 0;
|
|
395
|
+
reassignPendingTransition(e.yt);
|
|
381
396
|
activeTransition = null;
|
|
382
397
|
finalizePureQueue(null, true);
|
|
383
398
|
return;
|
|
384
399
|
}
|
|
385
400
|
const t = activeTransition;
|
|
386
|
-
const i = this.
|
|
387
|
-
i !== t && i.
|
|
388
|
-
this.restoreQueues(t.
|
|
401
|
+
const i = this.k;
|
|
402
|
+
i !== t && i.yt.push(...t.yt);
|
|
403
|
+
this.restoreQueues(t.bt);
|
|
389
404
|
transitions.delete(t);
|
|
390
405
|
activeTransition = null;
|
|
391
|
-
reassignPendingTransition(i.
|
|
406
|
+
reassignPendingTransition(i.yt);
|
|
392
407
|
finalizePureQueue(t);
|
|
393
408
|
if (i === t) {
|
|
394
409
|
// Drop the dead Transition wrapper but keep its (drained) containers
|
|
395
410
|
// as the ambient batch — late registrations during finalization live
|
|
396
411
|
// there and must survive to the next flush.
|
|
397
412
|
const e = createBatch();
|
|
398
|
-
e.
|
|
399
|
-
e.
|
|
400
|
-
e.
|
|
413
|
+
e.yt = i.yt;
|
|
414
|
+
e.Ke = i.Ke;
|
|
415
|
+
e.m = i.m;
|
|
401
416
|
e.cn = i.cn;
|
|
402
|
-
currentBatch = this.
|
|
417
|
+
currentBatch = this.k = e;
|
|
403
418
|
}
|
|
404
419
|
} else {
|
|
405
420
|
if (canUseSimpleSyncFlush(this)) {
|
|
406
421
|
commitPendingNodes();
|
|
407
|
-
if (dirtyQueue.EE >= dirtyQueue.
|
|
422
|
+
if (dirtyQueue.EE >= dirtyQueue.xe) {
|
|
408
423
|
runHeap(dirtyQueue, GlobalQueue.Ce);
|
|
409
424
|
commitPendingNodes();
|
|
410
425
|
}
|
|
@@ -415,36 +430,39 @@ class GlobalQueue extends Queue {
|
|
|
415
430
|
}
|
|
416
431
|
clock++;
|
|
417
432
|
// Check if finalization added items to the heap (from optimistic reversion)
|
|
418
|
-
scheduled = dirtyQueue.EE >= dirtyQueue.
|
|
433
|
+
scheduled = dirtyQueue.EE >= dirtyQueue.xe;
|
|
419
434
|
// Run lane effects first (for ready lanes), then regular effects
|
|
420
|
-
activeLanes.size && GlobalQueue.
|
|
435
|
+
activeLanes.size && GlobalQueue.Tn(EFFECT_RENDER);
|
|
421
436
|
this.run(EFFECT_RENDER);
|
|
422
|
-
activeLanes.size && GlobalQueue.
|
|
437
|
+
activeLanes.size && GlobalQueue.Tn(EFFECT_USER);
|
|
423
438
|
this.run(EFFECT_USER);
|
|
424
439
|
if (false) ;
|
|
425
440
|
if (false && !scheduled && !activeTransition && transitions.size === 0 && activeLanes.size === 0) ;
|
|
426
441
|
if (false) ;
|
|
427
442
|
} finally {
|
|
428
|
-
this.
|
|
443
|
+
this.sn = false;
|
|
429
444
|
}
|
|
430
445
|
}
|
|
431
446
|
notify(e, t, i, n) {
|
|
432
447
|
// Only track async if the boundary is propagating STATUS_PENDING (not caught by boundary)
|
|
433
448
|
if (t & STATUS_PENDING) {
|
|
434
449
|
if (i & STATUS_PENDING) {
|
|
435
|
-
const t = n !== undefined ? n : e._;
|
|
450
|
+
const t = n !== undefined ? n : e.o?._;
|
|
436
451
|
// A visibility-only mark notification (the affects() boundary
|
|
437
452
|
// channel) updates display state on its way up but must be invisible
|
|
438
453
|
// to completion accounting BY CONSTRUCTION: it never registers a
|
|
439
454
|
// reporter and never counts toward the loading-boundary diagnostic.
|
|
440
|
-
if (t?.
|
|
455
|
+
if (t?.i) return true;
|
|
441
456
|
if (activeTransition && t) {
|
|
442
457
|
const i = t.source;
|
|
443
|
-
let n = activeTransition.
|
|
444
|
-
if (!n) activeTransition.
|
|
458
|
+
let n = activeTransition.Ne.get(i);
|
|
459
|
+
if (!n) activeTransition.Ne.set(i, n = new Set);
|
|
445
460
|
const s = n.size;
|
|
446
461
|
n.add(e);
|
|
447
|
-
if (n.size !== s)
|
|
462
|
+
if (n.size !== s) {
|
|
463
|
+
schedule();
|
|
464
|
+
GlobalQueue.wt?.(activeTransition);
|
|
465
|
+
}
|
|
448
466
|
}
|
|
449
467
|
}
|
|
450
468
|
return true;
|
|
@@ -454,7 +472,7 @@ class GlobalQueue extends Queue {
|
|
|
454
472
|
initTransition(e) {
|
|
455
473
|
if (e) e = currentTransition(e);
|
|
456
474
|
if (e && e === activeTransition) return;
|
|
457
|
-
if (!e && activeTransition && activeTransition.
|
|
475
|
+
if (!e && activeTransition && activeTransition.Te === clock) return;
|
|
458
476
|
if (!activeTransition) {
|
|
459
477
|
activeTransition = e ?? createBatch();
|
|
460
478
|
} else if (e) {
|
|
@@ -464,8 +482,8 @@ class GlobalQueue extends Queue {
|
|
|
464
482
|
activeTransition = e;
|
|
465
483
|
}
|
|
466
484
|
transitions.add(activeTransition);
|
|
467
|
-
activeTransition.
|
|
468
|
-
const t = this.
|
|
485
|
+
activeTransition.Te = clock;
|
|
486
|
+
const t = this.k;
|
|
469
487
|
if (t !== activeTransition) {
|
|
470
488
|
// Adopt the ambient batch into the transaction, then make the
|
|
471
489
|
// transaction the batch so later registrations land there directly.
|
|
@@ -474,17 +492,17 @@ class GlobalQueue extends Queue {
|
|
|
474
492
|
// must not entangle unrelated writes to it; the same rule holds one hop
|
|
475
493
|
// downstream: propagation never queues pended subscribers as pending
|
|
476
494
|
// nodes, see propagateAffectsMark, #2893.
|
|
477
|
-
for (let e = 0; e < t.
|
|
478
|
-
const i = t.
|
|
479
|
-
i.
|
|
480
|
-
activeTransition.
|
|
495
|
+
for (let e = 0; e < t.yt.length; e++) {
|
|
496
|
+
const i = t.yt[e];
|
|
497
|
+
i._e = activeTransition;
|
|
498
|
+
activeTransition.yt.push(i);
|
|
481
499
|
}
|
|
482
|
-
for (let e = 0; e < t.
|
|
483
|
-
const i = t.
|
|
484
|
-
i.
|
|
485
|
-
activeTransition.
|
|
500
|
+
for (let e = 0; e < t.Ke.length; e++) {
|
|
501
|
+
const i = t.Ke[e];
|
|
502
|
+
i._e = activeTransition;
|
|
503
|
+
activeTransition.Ke.push(i);
|
|
486
504
|
}
|
|
487
|
-
if (t.
|
|
505
|
+
if (t.m.length) activeTransition.m.push(...t.m);
|
|
488
506
|
for (const e of t.cn) activeTransition.cn.add(e);
|
|
489
507
|
// Gated readers recorded against the ambient batch move with it: their
|
|
490
508
|
// replay-at-commit now happens at the transaction's completion.
|
|
@@ -492,16 +510,16 @@ class GlobalQueue extends Queue {
|
|
|
492
510
|
for (const e of t.ln) activeTransition.ln.add(e);
|
|
493
511
|
t.ln.clear();
|
|
494
512
|
}
|
|
495
|
-
currentBatch = this.
|
|
513
|
+
currentBatch = this.k = activeTransition;
|
|
496
514
|
}
|
|
497
515
|
for (const e of activeLanes) {
|
|
498
|
-
if (!e.
|
|
516
|
+
if (!e._e) e._e = activeTransition;
|
|
499
517
|
}
|
|
500
518
|
}
|
|
501
519
|
}
|
|
502
520
|
|
|
503
521
|
function queuePendingNode(e) {
|
|
504
|
-
currentBatch.
|
|
522
|
+
currentBatch.yt.push(e);
|
|
505
523
|
}
|
|
506
524
|
|
|
507
525
|
// Sticky: flips true on the first refresh() ever (the only setter of
|
|
@@ -509,68 +527,107 @@ function queuePendingNode(e) {
|
|
|
509
527
|
// clear entirely in apps that never refresh.
|
|
510
528
|
let reaskArmed = false;
|
|
511
529
|
|
|
530
|
+
/** §12d: bumped by every recompute and every new subscriber edge. A node's
|
|
531
|
+
* staged-rewrite skip is sound only while NOTHING recomputed or linked since
|
|
532
|
+
* its last notify — a mid-batch pull can clean a marked subscriber, and a
|
|
533
|
+
* skipped re-write would leave it stale. */ let notifyEpoch = 0;
|
|
534
|
+
|
|
535
|
+
function bumpNotifyEpoch() {
|
|
536
|
+
notifyEpoch++;
|
|
537
|
+
}
|
|
538
|
+
|
|
512
539
|
function armReaskClear() {
|
|
513
540
|
reaskArmed = true;
|
|
514
541
|
}
|
|
515
542
|
|
|
516
543
|
function insertSubs(e, t = false) {
|
|
544
|
+
// §12d: stamp before walking — setSignal's staged-rewrite fast path skips
|
|
545
|
+
// the next walk for this node while the epoch holds (marking is idempotent).
|
|
546
|
+
e._t = notifyEpoch;
|
|
517
547
|
// Get source lane: prefer node's own lane over current context
|
|
518
548
|
// This is important for isPending signals which need their own lane to flush immediately
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
549
|
+
// Presence bits gate the optional-slot probes (see constants.ts): one
|
|
550
|
+
// masked read of the always-present _config instead of missing-property
|
|
551
|
+
// lookups in the hottest notify loop. Bits are sticky — the field read
|
|
552
|
+
// stays authoritative when a bit is set.
|
|
553
|
+
const i = e.T;
|
|
554
|
+
const n = (i & CONFIG_HAS_LANE ? e.o?.Be : undefined) || currentOptimisticLane;
|
|
555
|
+
const s = (i & CONFIG_HAS_SNAPSHOT) !== 0 && e.o?.Qe !== undefined;
|
|
556
|
+
const o = reaskArmed;
|
|
557
|
+
for (let i = e.u; i !== null; i = i.fe) {
|
|
558
|
+
const e = i.ae;
|
|
523
559
|
// A value-change notification is a new question for the subscriber: any
|
|
524
560
|
// pending re-ask mark (refresh) it carried is superseded.
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
561
|
+
if (o) e.ie &= ~REACTIVE_REASK;
|
|
562
|
+
// Missed-wake latch (#3037): this write is landing while the subscriber
|
|
563
|
+
// is mid-recompute (a nested pull committing beneath its reads), and the
|
|
564
|
+
// heap refuses RECOMPUTING nodes. A gen-current link means the pass
|
|
565
|
+
// already validated this dep — the value it read is now stale — so latch
|
|
566
|
+
// for recompute's tail to reschedule. Untouched links need no latch (the
|
|
567
|
+
// pass either re-reads them fresh or trims them), and neither does the
|
|
568
|
+
// tail link: it is the read IN FLIGHT — read() links before it pulls, so
|
|
569
|
+
// this very commit is what that read returns.
|
|
570
|
+
if (e.ie & REACTIVE_RECOMPUTING_DEPS && i.ll === e.Ze && i !== e.Ye) e.ie |= REACTIVE_MISSED_WAKE;
|
|
571
|
+
if (s && e.T & CONFIG_IN_SNAPSHOT_SCOPE) {
|
|
572
|
+
e.ie |= REACTIVE_SNAPSHOT_STALE;
|
|
528
573
|
continue;
|
|
529
574
|
}
|
|
530
|
-
if (t &&
|
|
531
|
-
|
|
532
|
-
assignOrMergeLane(
|
|
575
|
+
if (t && n) {
|
|
576
|
+
e.ie |= REACTIVE_OPTIMISTIC_DIRTY;
|
|
577
|
+
assignOrMergeLane(e, n);
|
|
533
578
|
} else if (t) {
|
|
534
|
-
|
|
579
|
+
e.ie |= REACTIVE_OPTIMISTIC_DIRTY;
|
|
535
580
|
// No source lane means reversion - clear subscriber's lane so effects go to regular queue
|
|
536
|
-
|
|
581
|
+
if (e.o) e.o.Be = undefined;
|
|
537
582
|
}
|
|
538
|
-
enqueueSub(
|
|
583
|
+
enqueueSub(e);
|
|
539
584
|
}
|
|
540
585
|
}
|
|
541
586
|
|
|
542
587
|
function commitPendingNode(e) {
|
|
543
588
|
const t = e;
|
|
544
|
-
if (!t.
|
|
545
|
-
if (e.
|
|
546
|
-
e.
|
|
547
|
-
e.
|
|
589
|
+
if (!t.Se) {
|
|
590
|
+
if (e.Pe !== NOT_PENDING) {
|
|
591
|
+
e.be = e.Pe;
|
|
592
|
+
e.Pe = NOT_PENDING;
|
|
548
593
|
}
|
|
549
|
-
if (e.
|
|
594
|
+
if (e.T & CONFIG_HAS_COMPANIONS) GlobalQueue.un(e);
|
|
550
595
|
return;
|
|
551
596
|
}
|
|
552
|
-
if (e.
|
|
553
|
-
e.
|
|
554
|
-
e.
|
|
597
|
+
if (e.Pe !== NOT_PENDING) {
|
|
598
|
+
e.be = e.Pe;
|
|
599
|
+
e.Pe = NOT_PENDING;
|
|
555
600
|
// Set _modified for effects, but not for tracked effects (they handle their own scheduling)
|
|
556
|
-
if (e.Re && e.Re !== EFFECT_TRACKED) e.
|
|
601
|
+
if (e.Re && e.Re !== EFFECT_TRACKED) e.Xe = true;
|
|
557
602
|
}
|
|
558
603
|
// The committed hold is the first observable answer for a loading-window
|
|
559
604
|
// node — the window closes here, not at compute time (#2990). Unconditional
|
|
560
605
|
// store to an always-present computed slot.
|
|
561
|
-
t.
|
|
562
|
-
t.
|
|
606
|
+
t.Ie = false;
|
|
607
|
+
t.ie &= ~REACTIVE_MANUAL_WRITE;
|
|
563
608
|
if (!(t.S & STATUS_PENDING)) t.S &= ~STATUS_UNINITIALIZED;
|
|
564
|
-
if (t.
|
|
565
|
-
if (e.
|
|
609
|
+
if (t.o != null && (t.o.qe !== null || t.o.We !== null)) GlobalQueue.Fe(t, false, true);
|
|
610
|
+
if (e.T & CONFIG_HAS_COMPANIONS) GlobalQueue.un(e);
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
// Store commit hook (INTERNALS-STORE-STATE.md §3): installed by the store
|
|
614
|
+
// module at init (same treeshakeable pattern as _resolveOptimistic /
|
|
615
|
+
// _clearOptimisticStores). Folds committed store-node values into their
|
|
616
|
+
// backing objects at the same moment pending values commit — the single
|
|
617
|
+
// mutation point of the owned-raw model.
|
|
618
|
+
let storeCommitHook = null;
|
|
619
|
+
|
|
620
|
+
function setStoreCommitHook(e) {
|
|
621
|
+
storeCommitHook = e;
|
|
566
622
|
}
|
|
567
623
|
|
|
568
624
|
function commitPendingNodes() {
|
|
569
|
-
const e = currentBatch.
|
|
625
|
+
const e = currentBatch.yt;
|
|
570
626
|
for (let t = 0; t < e.length; t++) {
|
|
571
627
|
commitPendingNode(e[t]);
|
|
572
628
|
}
|
|
573
629
|
e.length = 0;
|
|
630
|
+
storeCommitHook?.();
|
|
574
631
|
}
|
|
575
632
|
|
|
576
633
|
function finalizePureQueue(e = null, t = false) {
|
|
@@ -578,23 +635,23 @@ function finalizePureQueue(e = null, t = false) {
|
|
|
578
635
|
// For completing transitions or no-transition, resolve pending and revert optimistic
|
|
579
636
|
const i = !t;
|
|
580
637
|
if (i) commitPendingNodes();
|
|
581
|
-
if (!t && globalQueue.
|
|
582
|
-
const n = dirtyQueue.EE >= dirtyQueue.
|
|
638
|
+
if (!t && globalQueue.Qt.length) checkBoundaryChildren(globalQueue);
|
|
639
|
+
const n = dirtyQueue.EE >= dirtyQueue.xe;
|
|
583
640
|
if (n) runHeap(dirtyQueue, GlobalQueue.Ce);
|
|
584
641
|
if (i) {
|
|
585
642
|
if (n) commitPendingNodes();
|
|
586
643
|
// The settling batch: the completing transaction's, or the ambient one.
|
|
587
|
-
const t = e ?? globalQueue.
|
|
644
|
+
const t = e ?? globalQueue.k;
|
|
588
645
|
// Optimistic reversion: a non-empty batch means _optimisticWrite ran,
|
|
589
646
|
// which installed the engine's hooks.
|
|
590
|
-
if (t.
|
|
647
|
+
if (t.Ke.length) GlobalQueue.fn(t.Ke);
|
|
591
648
|
// Replay entanglement: subs recorded by the read-time gate get rescheduled
|
|
592
649
|
// so they re-run with the now-committed values visible. The ambient batch
|
|
593
650
|
// replays too — laneReadsCommitted records readers whose committed-view
|
|
594
651
|
// read hid a same-tick plain write that just committed above (#2963).
|
|
595
652
|
if (t.ln.size) {
|
|
596
653
|
for (const e of t.ln) {
|
|
597
|
-
if (e.
|
|
654
|
+
if (e.ie & REACTIVE_DISPOSED) continue;
|
|
598
655
|
enqueueSub(e);
|
|
599
656
|
}
|
|
600
657
|
t.ln.clear();
|
|
@@ -609,24 +666,24 @@ function finalizePureQueue(e = null, t = false) {
|
|
|
609
666
|
// held boundary display state through the visual channel, and their
|
|
610
667
|
// release is the display-state update point — re-run the boundary sweep
|
|
611
668
|
// (the earlier sweep above ran while the marks were still live).
|
|
612
|
-
if (t.
|
|
613
|
-
GlobalQueue.
|
|
614
|
-
if (globalQueue.
|
|
669
|
+
if (t.m.length) {
|
|
670
|
+
GlobalQueue.M(t.m);
|
|
671
|
+
if (globalQueue.Qt.length) checkBoundaryChildren(globalQueue);
|
|
615
672
|
}
|
|
616
673
|
// A non-empty set means trackOptimisticStore ran, which installed the
|
|
617
674
|
// hook; the hook iterates, clears, and schedules (keeping the loop out of
|
|
618
675
|
// core lets esbuild shake it — rollup already folds the null guard). The
|
|
619
676
|
// completing transition scopes the clear to its own layer keys (#2899).
|
|
620
|
-
if (t.cn.size) GlobalQueue.
|
|
677
|
+
if (t.cn.size) GlobalQueue.Vt(t.cn, e);
|
|
621
678
|
sweepTransientStoreNodes();
|
|
622
679
|
// Lanes only enter activeLanes through the engine's getOrCreateLane.
|
|
623
|
-
if (activeLanes.size) GlobalQueue.
|
|
680
|
+
if (activeLanes.size) GlobalQueue.En(e);
|
|
624
681
|
}
|
|
625
682
|
}
|
|
626
683
|
|
|
627
684
|
function checkBoundaryChildren(e) {
|
|
628
|
-
for (const t of e.
|
|
629
|
-
t.
|
|
685
|
+
for (const t of e.Qt) {
|
|
686
|
+
t.se?.();
|
|
630
687
|
checkBoundaryChildren(t);
|
|
631
688
|
}
|
|
632
689
|
}
|
|
@@ -649,7 +706,7 @@ function checkBoundaryChildren(e) {
|
|
|
649
706
|
|
|
650
707
|
function reassignPendingTransition(e) {
|
|
651
708
|
for (let t = 0; t < e.length; t++) {
|
|
652
|
-
e[t].
|
|
709
|
+
e[t]._e = activeTransition;
|
|
653
710
|
}
|
|
654
711
|
}
|
|
655
712
|
|
|
@@ -660,7 +717,7 @@ const globalQueue = new GlobalQueue;
|
|
|
660
717
|
// property hop through `_batch` was a measured instruction-count regression
|
|
661
718
|
// (CodSpeed update1to1, PR #2905). The field stays authoritative for
|
|
662
719
|
// cross-module readers; every `_batch` assignment updates both.
|
|
663
|
-
let currentBatch = globalQueue.
|
|
720
|
+
let currentBatch = globalQueue.k;
|
|
664
721
|
|
|
665
722
|
function flush(e) {
|
|
666
723
|
if (e) {
|
|
@@ -677,7 +734,7 @@ function flush(e) {
|
|
|
677
734
|
}
|
|
678
735
|
}
|
|
679
736
|
}
|
|
680
|
-
if (globalQueue.
|
|
737
|
+
if (globalQueue.sn) {
|
|
681
738
|
return;
|
|
682
739
|
}
|
|
683
740
|
if (halted) return;
|
|
@@ -693,23 +750,23 @@ function runQueue(e, t) {
|
|
|
693
750
|
}
|
|
694
751
|
|
|
695
752
|
function reporterBlocksSource(e, t) {
|
|
696
|
-
if (e.
|
|
697
|
-
if (e.
|
|
698
|
-
for (let i = e.
|
|
699
|
-
let e = i.
|
|
753
|
+
if (e.ie & (REACTIVE_ZOMBIE | REACTIVE_DISPOSED)) return false;
|
|
754
|
+
if (e.o?.le?.has(t)) return true;
|
|
755
|
+
for (let i = e.nt; i; i = i.it) {
|
|
756
|
+
let e = i.ut;
|
|
700
757
|
while (e) {
|
|
701
758
|
if (e === t || e.lt === t) return true;
|
|
702
|
-
e = e.
|
|
759
|
+
e = e.o?.It;
|
|
703
760
|
}
|
|
704
761
|
}
|
|
705
|
-
return !!(e.S & STATUS_PENDING && e._ instanceof NotReadyError && e._.source === t);
|
|
762
|
+
return !!(e.S & STATUS_PENDING && e.o?._ instanceof NotReadyError && e.o?._.source === t);
|
|
706
763
|
}
|
|
707
764
|
|
|
708
765
|
function transitionComplete(e) {
|
|
709
|
-
if (e.
|
|
710
|
-
if (e.
|
|
766
|
+
if (e.an) return true;
|
|
767
|
+
if (e.oe.length) return false;
|
|
711
768
|
let t = true;
|
|
712
|
-
for (const [i, n] of e.
|
|
769
|
+
for (const [i, n] of e.Ne) {
|
|
713
770
|
let s = false;
|
|
714
771
|
for (const e of n) {
|
|
715
772
|
if (reporterBlocksSource(e, i)) {
|
|
@@ -718,7 +775,7 @@ function transitionComplete(e) {
|
|
|
718
775
|
}
|
|
719
776
|
n.delete(e);
|
|
720
777
|
}
|
|
721
|
-
if (!s) e.
|
|
778
|
+
if (!s) e.Ne.delete(i); else if (i.S & STATUS_PENDING && i.o?._?.source === i) {
|
|
722
779
|
t = false;
|
|
723
780
|
break;
|
|
724
781
|
}
|
|
@@ -726,13 +783,13 @@ function transitionComplete(e) {
|
|
|
726
783
|
// Override blockage lives with the engine (absent hook = "no optimistic
|
|
727
784
|
// blockage"); the hook's loops over _optimisticNodes/_optimisticStores are
|
|
728
785
|
// no-ops when the transition holds neither, so no pre-check is needed.
|
|
729
|
-
if (t && GlobalQueue.
|
|
730
|
-
t && (e.
|
|
786
|
+
if (t && GlobalQueue.dn?.(e)) t = false;
|
|
787
|
+
t && (e.an = true);
|
|
731
788
|
return t;
|
|
732
789
|
}
|
|
733
790
|
|
|
734
791
|
function currentTransition(e) {
|
|
735
|
-
while (e.
|
|
792
|
+
while (e.an && typeof e.an === "object") e = e.an;
|
|
736
793
|
return e;
|
|
737
794
|
}
|
|
738
795
|
|
|
@@ -746,4 +803,4 @@ function runInTransition(e, t) {
|
|
|
746
803
|
}
|
|
747
804
|
}
|
|
748
805
|
|
|
749
|
-
export { GlobalQueue, Queue, activeAffectsMarks, activeLanes, activeTransition, armReaskClear, assignOrMergeLane, clock, currentTransition, dirtyQueue, enforceLoadingBoundary, finalizePureQueue, findLane, flush, globalQueue, haltReactivity, insertSubs, projectionWriteActive, queuePendingNode,
|
|
806
|
+
export { GlobalQueue, Queue, activeAffectsMarks, activeLanes, activeTransition, armReaskClear, assignOrMergeLane, bumpNotifyEpoch, clock, currentTransition, dirtyQueue, enforceLoadingBoundary, finalizePureQueue, findLane, flush, globalQueue, haltReactivity, insertSubs, notifyEpoch, projectionWriteActive, queuePendingNode, reaskArmed, resetErrorHalt, runInTransition, schedule, setProjectionWriteActive, setStoreCommitHook, shiftAffectsMarks, storeCommitHook, zombieQueue };
|