@solidjs/signals 2.0.0-beta.26 → 2.0.0-beta.27
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 +258 -67
- package/dist/node.cjs +1117 -915
- package/dist/prod/core/action.js +11 -6
- package/dist/prod/core/async.js +42 -11
- package/dist/prod/core/core.js +83 -69
- package/dist/prod/core/external.js +2 -2
- package/dist/prod/core/graph.js +4 -4
- package/dist/prod/core/lanes.js +1 -1
- package/dist/prod/core/optimistic.js +5 -5
- package/dist/prod/core/owner.js +1 -1
- package/dist/prod/core/scheduler.js +53 -32
- package/dist/prod/core/verdict.js +26 -26
- package/dist/prod/map.js +2 -2
- package/dist/prod/store/optimistic.js +52 -33
- package/dist/prod/store/projection.js +38 -33
- package/dist/prod/store/reconcile.js +299 -243
- package/dist/prod/store/store.js +98 -47
- package/dist/types/core/async.d.ts +1 -0
- package/dist/types/core/scheduler.d.ts +1 -0
- package/dist/types/store/optimistic.d.ts +2 -2
- package/dist/types/store/projection.d.ts +7 -2
- package/dist/types/store/reconcile.d.ts +14 -0
- package/dist/types/store/store.d.ts +2 -2
- package/dist/types-cjs/core/async.d.cts +1 -0
- package/dist/types-cjs/core/scheduler.d.cts +1 -0
- package/dist/types-cjs/store/optimistic.d.cts +2 -2
- package/dist/types-cjs/store/projection.d.cts +7 -2
- package/dist/types-cjs/store/reconcile.d.cts +14 -0
- package/dist/types-cjs/store/store.d.cts +2 -2
- package/package.json +1 -1
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.he || n.
|
|
54
|
+
if (n.he || n.pe) GlobalQueue.un(n);
|
|
55
55
|
}
|
|
56
56
|
if (n && e.ae) e.Te = null;
|
|
57
57
|
let l = t ? e.Qe : e.ke;
|
|
@@ -66,7 +66,7 @@ function sweepTransientStoreNodes() {
|
|
|
66
66
|
transientStoreNodes.delete(e);
|
|
67
67
|
continue;
|
|
68
68
|
}
|
|
69
|
-
if (e.
|
|
69
|
+
if (e.De !== NOT_PENDING) continue;
|
|
70
70
|
if (e.Ae !== undefined && e.Ae !== NOT_PENDING) continue;
|
|
71
71
|
// A live affects() mark keeps the node addressable: sweeping it would
|
|
72
72
|
// detach the refcount from the slot (a fresh probe would upsert a new,
|
|
@@ -179,10 +179,15 @@ function notifyHalted() {
|
|
|
179
179
|
haltNotified = false;
|
|
180
180
|
}
|
|
181
181
|
|
|
182
|
+
// Identifies one child-traversal pass in `Queue.run` so a rescan after the
|
|
183
|
+
// child list shifts can tell "already run this pass" from "still pending".
|
|
184
|
+
let queueRunToken = 0;
|
|
185
|
+
|
|
182
186
|
class Queue {
|
|
183
187
|
ve=null;
|
|
184
188
|
gt=[ [], [] ];
|
|
185
189
|
vt=[];
|
|
190
|
+
kt=0;
|
|
186
191
|
created=clock;
|
|
187
192
|
addChild(e) {
|
|
188
193
|
this.vt.push(e);
|
|
@@ -205,7 +210,27 @@ class Queue {
|
|
|
205
210
|
this.gt[e - 1] = [];
|
|
206
211
|
runQueue(t, e);
|
|
207
212
|
}
|
|
208
|
-
|
|
213
|
+
// Effects run here can dispose owners, and disposal removes queues from
|
|
214
|
+
// this list — the running child itself, an earlier sibling, or several at
|
|
215
|
+
// once. A plain index walk then skips whatever shifted into the cursor.
|
|
216
|
+
// Stamping each child before it runs makes the pass idempotent, so a shift
|
|
217
|
+
// can be recovered by rescanning from the front and every child still runs
|
|
218
|
+
// exactly once. Children appended mid-pass carry a stale stamp and run,
|
|
219
|
+
// matching the previous live-array behaviour.
|
|
220
|
+
const t = this.vt;
|
|
221
|
+
const i = ++queueRunToken;
|
|
222
|
+
for (let n = 0; n < t.length; ) {
|
|
223
|
+
const s = t[n];
|
|
224
|
+
if (s.kt !== i) {
|
|
225
|
+
s.kt = i;
|
|
226
|
+
s.run?.(e);
|
|
227
|
+
if (t[n] !== s) {
|
|
228
|
+
n = 0;
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
n++;
|
|
233
|
+
}
|
|
209
234
|
}
|
|
210
235
|
enqueue(e, t) {
|
|
211
236
|
if (e) {
|
|
@@ -252,10 +277,10 @@ class GlobalQueue extends Queue {
|
|
|
252
277
|
// The current transaction-shaped batch: a plain ambient batch while no
|
|
253
278
|
// transition is active, the active transition itself after initTransition.
|
|
254
279
|
m=createBatch();
|
|
255
|
-
static pe;
|
|
256
280
|
static Ce;
|
|
281
|
+
static me;
|
|
257
282
|
static Xe;
|
|
258
|
-
static
|
|
283
|
+
static Dt=null;
|
|
259
284
|
// Store-side hook: drops a keyless affects() mark's identity scope when the
|
|
260
285
|
// carrier node's last registration releases (wired by store.ts, mirroring
|
|
261
286
|
// _clearOptimisticStore).
|
|
@@ -269,24 +294,24 @@ class GlobalQueue extends Queue {
|
|
|
269
294
|
static h=null;
|
|
270
295
|
// External-source bridge (wired by enableExternalSource(); null while no
|
|
271
296
|
// config is active — including after _resetExternalSourceConfig()).
|
|
272
|
-
static It=null;
|
|
273
297
|
static dt=null;
|
|
298
|
+
static It=null;
|
|
274
299
|
// Verdict-layer hooks (wired by verdict.ts when isPending()/latest() are
|
|
275
300
|
// imported; null in apps that never use them). Call sites either guard for
|
|
276
301
|
// null or sit behind state only the verdict layer can create (`!` is safe
|
|
277
302
|
// there: `_pendingSignal`/`_latestValueComputed` are only ever assigned by
|
|
278
303
|
// verdict.ts, and `pendingCheckActive`/`latestReadActive` only flip inside
|
|
279
304
|
// isPending()/latest()).
|
|
280
|
-
static
|
|
305
|
+
static _e=null;
|
|
281
306
|
static ce=null;
|
|
282
|
-
static
|
|
307
|
+
static Ge=null;
|
|
283
308
|
static un=null;
|
|
284
309
|
static St=null;
|
|
285
310
|
static At=null;
|
|
286
311
|
static Pt=null;
|
|
287
312
|
static $e=null;
|
|
288
313
|
static k=null;
|
|
289
|
-
static
|
|
314
|
+
static Lt=null;
|
|
290
315
|
// Optimistic-engine hooks (wired by core/optimistic.ts via
|
|
291
316
|
// installOptimisticEngine(), called from verdict.ts / createOptimistic /
|
|
292
317
|
// createOptimisticStore — every module that can create optimistic state).
|
|
@@ -311,12 +336,12 @@ class GlobalQueue extends Queue {
|
|
|
311
336
|
this.bt = true;
|
|
312
337
|
try {
|
|
313
338
|
if (false) ;
|
|
314
|
-
runHeap(dirtyQueue, GlobalQueue.
|
|
339
|
+
runHeap(dirtyQueue, GlobalQueue.Ce);
|
|
315
340
|
if (activeTransition) {
|
|
316
341
|
const e = transitionComplete(activeTransition);
|
|
317
342
|
if (!e) {
|
|
318
343
|
const e = activeTransition;
|
|
319
|
-
runHeap(zombieQueue, GlobalQueue.
|
|
344
|
+
runHeap(zombieQueue, GlobalQueue.Ce);
|
|
320
345
|
// Detach: the stashed transition keeps its batch; ambient work that
|
|
321
346
|
// follows lands in a fresh one. If the batch is already a separate
|
|
322
347
|
// ambient one — action done() restored activeTransition without
|
|
@@ -363,11 +388,11 @@ class GlobalQueue extends Queue {
|
|
|
363
388
|
if (canUseSimpleSyncFlush(this)) {
|
|
364
389
|
commitPendingNodes();
|
|
365
390
|
if (dirtyQueue.EE >= dirtyQueue.He) {
|
|
366
|
-
runHeap(dirtyQueue, GlobalQueue.
|
|
391
|
+
runHeap(dirtyQueue, GlobalQueue.Ce);
|
|
367
392
|
commitPendingNodes();
|
|
368
393
|
}
|
|
369
394
|
} else {
|
|
370
|
-
if (transitions.size) runHeap(zombieQueue, GlobalQueue.
|
|
395
|
+
if (transitions.size) runHeap(zombieQueue, GlobalQueue.Ce);
|
|
371
396
|
finalizePureQueue();
|
|
372
397
|
}
|
|
373
398
|
}
|
|
@@ -494,23 +519,23 @@ function insertSubs(e, t = false) {
|
|
|
494
519
|
function commitPendingNode(e) {
|
|
495
520
|
const t = e;
|
|
496
521
|
if (!t.ae) {
|
|
497
|
-
if (e.
|
|
498
|
-
e.Ue = e.
|
|
499
|
-
e.
|
|
522
|
+
if (e.De !== NOT_PENDING) {
|
|
523
|
+
e.Ue = e.De;
|
|
524
|
+
e.De = NOT_PENDING;
|
|
500
525
|
}
|
|
501
|
-
if (e.he || e.
|
|
526
|
+
if (e.he || e.pe) GlobalQueue.un(e);
|
|
502
527
|
return;
|
|
503
528
|
}
|
|
504
|
-
if (e.
|
|
505
|
-
e.Ue = e.
|
|
506
|
-
e.
|
|
529
|
+
if (e.De !== NOT_PENDING) {
|
|
530
|
+
e.Ue = e.De;
|
|
531
|
+
e.De = NOT_PENDING;
|
|
507
532
|
// Set _modified for effects, but not for tracked effects (they handle their own scheduling)
|
|
508
533
|
if (e.Pe && e.Pe !== EFFECT_TRACKED) e.Be = true;
|
|
509
534
|
}
|
|
510
535
|
t.se &= ~REACTIVE_MANUAL_WRITE;
|
|
511
536
|
if (!(t.S & STATUS_PENDING)) t.S &= ~STATUS_UNINITIALIZED;
|
|
512
|
-
if (t.Qe !== null || t.ye !== null) GlobalQueue.
|
|
513
|
-
if (e.he || e.
|
|
537
|
+
if (t.Qe !== null || t.ye !== null) GlobalQueue.me(t, false, true);
|
|
538
|
+
if (e.he || e.pe) GlobalQueue.un(e);
|
|
514
539
|
}
|
|
515
540
|
|
|
516
541
|
function commitPendingNodes() {
|
|
@@ -528,7 +553,7 @@ function finalizePureQueue(e = null, t = false) {
|
|
|
528
553
|
if (i) commitPendingNodes();
|
|
529
554
|
if (!t && globalQueue.vt.length) checkBoundaryChildren(globalQueue);
|
|
530
555
|
const n = dirtyQueue.EE >= dirtyQueue.He;
|
|
531
|
-
if (n) runHeap(dirtyQueue, GlobalQueue.
|
|
556
|
+
if (n) runHeap(dirtyQueue, GlobalQueue.Ce);
|
|
532
557
|
if (i) {
|
|
533
558
|
if (n) commitPendingNodes();
|
|
534
559
|
// The settling batch: the completing transaction's, or the ambient one.
|
|
@@ -559,7 +584,7 @@ function finalizePureQueue(e = null, t = false) {
|
|
|
559
584
|
// hook; the hook iterates, clears, and schedules (keeping the loop out of
|
|
560
585
|
// core lets esbuild shake it — rollup already folds the null guard). The
|
|
561
586
|
// completing transition scopes the clear to its own layer keys (#2899).
|
|
562
|
-
if (t.cn.size) GlobalQueue.
|
|
587
|
+
if (t.cn.size) GlobalQueue.Dt(t.cn, e);
|
|
563
588
|
sweepTransientStoreNodes();
|
|
564
589
|
// Lanes only enter activeLanes through the engine's getOrCreateLane.
|
|
565
590
|
if (activeLanes.size) GlobalQueue.Tn(e);
|
|
@@ -665,10 +690,10 @@ function transitionComplete(e) {
|
|
|
665
690
|
break;
|
|
666
691
|
}
|
|
667
692
|
}
|
|
668
|
-
// Override blockage lives with the engine
|
|
669
|
-
// blockage"
|
|
670
|
-
//
|
|
671
|
-
if (t &&
|
|
693
|
+
// Override blockage lives with the engine (absent hook = "no optimistic
|
|
694
|
+
// blockage"); the hook's loops over _optimisticNodes/_optimisticStores are
|
|
695
|
+
// no-ops when the transition holds neither, so no pre-check is needed.
|
|
696
|
+
if (t && GlobalQueue.dn?.(e)) t = false;
|
|
672
697
|
t && (e.fn = true);
|
|
673
698
|
return t;
|
|
674
699
|
}
|
|
@@ -678,10 +703,6 @@ function currentTransition(e) {
|
|
|
678
703
|
return e;
|
|
679
704
|
}
|
|
680
705
|
|
|
681
|
-
function setActiveTransition(e) {
|
|
682
|
-
activeTransition = e;
|
|
683
|
-
}
|
|
684
|
-
|
|
685
706
|
function runInTransition(e, t) {
|
|
686
707
|
const i = activeTransition;
|
|
687
708
|
try {
|
|
@@ -692,4 +713,4 @@ function runInTransition(e, t) {
|
|
|
692
713
|
}
|
|
693
714
|
}
|
|
694
715
|
|
|
695
|
-
export { GlobalQueue, Queue, activeAffectsMarks, activeLanes, activeTransition, armReaskClear, assignOrMergeLane, clock, currentTransition, dirtyQueue, enforceLoadingBoundary, finalizePureQueue, findLane, flush, globalQueue, haltReactivity, insertSubs, projectionWriteActive, queuePendingNode, registerTransientStoreNode, resetErrorHalt, runInTransition, schedule,
|
|
716
|
+
export { GlobalQueue, Queue, activeAffectsMarks, activeLanes, activeTransition, armReaskClear, assignOrMergeLane, clock, currentTransition, dirtyQueue, enforceLoadingBoundary, finalizePureQueue, findLane, flush, globalQueue, haltReactivity, insertSubs, projectionWriteActive, queuePendingNode, registerTransientStoreNode, resetErrorHalt, runInTransition, schedule, setProjectionWriteActive, shiftAffectsMarks, zombieQueue };
|
|
@@ -89,7 +89,7 @@ function collectPendingSources(e) {
|
|
|
89
89
|
const r = i.se & REACTIVE_RECOMPUTING_DEPS ? i.We : undefined;
|
|
90
90
|
if (r !== null) {
|
|
91
91
|
for (let e = i.et ?? null; e !== null; e = e.tt) {
|
|
92
|
-
if (!e.
|
|
92
|
+
if (!e.Oe && markWalk(e.nt, t)) return true;
|
|
93
93
|
if (e === r) break;
|
|
94
94
|
}
|
|
95
95
|
}
|
|
@@ -102,10 +102,10 @@ function collectPendingSources(e) {
|
|
|
102
102
|
|
|
103
103
|
function quietPending(e) {
|
|
104
104
|
if (e.oe) {
|
|
105
|
-
for (const t of e.oe) if (!t.
|
|
105
|
+
for (const t of e.oe) if (!t.Re) return false;
|
|
106
106
|
return true;
|
|
107
107
|
}
|
|
108
|
-
return e.
|
|
108
|
+
return e.Re;
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
function newQuestionInFlight(e) {
|
|
@@ -125,11 +125,11 @@ function computePendingState(e) {
|
|
|
125
125
|
const n = t.it || t;
|
|
126
126
|
return newQuestionInFlight(n);
|
|
127
127
|
}
|
|
128
|
-
if (n && e.
|
|
128
|
+
if (n && e.De !== NOT_PENDING && !hasActiveOverride(e)) {
|
|
129
129
|
return !!(n.se & REACTIVE_MANUAL_WRITE) || !n.Te && !(n.S & STATUS_PENDING) || !!(n.S & STATUS_PENDING) && quietPending(n);
|
|
130
130
|
}
|
|
131
|
-
if (e.
|
|
132
|
-
if (hasActiveOverride(e)) return !e.
|
|
131
|
+
if (e.De !== NOT_PENDING && !(t.S & STATUS_UNINITIALIZED)) {
|
|
132
|
+
if (hasActiveOverride(e)) return !e.be || !e.be(e.De, unwrapOverride(e.Ae));
|
|
133
133
|
return true;
|
|
134
134
|
}
|
|
135
135
|
return newQuestionInFlight(t);
|
|
@@ -137,19 +137,19 @@ function computePendingState(e) {
|
|
|
137
137
|
|
|
138
138
|
function syncCompanions(e, t) {
|
|
139
139
|
if (e.he) updatePendingSignal(e);
|
|
140
|
-
if (e.
|
|
140
|
+
if (e.pe) setSignal(e.pe, t);
|
|
141
141
|
}
|
|
142
142
|
|
|
143
143
|
function updatePendingSignal(e) {
|
|
144
144
|
if (e.he) {
|
|
145
145
|
setSignal(e.he, computePendingState(e));
|
|
146
146
|
}
|
|
147
|
-
if (e.
|
|
147
|
+
if (e.pe) updatePendingSignal(e.pe);
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
function updateChildCompanions(e) {
|
|
151
151
|
for (let t = e.u; t !== null; t = t.fe) {
|
|
152
|
-
if (t.he || t.
|
|
152
|
+
if (t.he || t.pe) updatePendingSignal(t);
|
|
153
153
|
}
|
|
154
154
|
}
|
|
155
155
|
|
|
@@ -167,7 +167,7 @@ function updateChildCompanions(e) {
|
|
|
167
167
|
const visit = e => {
|
|
168
168
|
if (i.has(e)) return;
|
|
169
169
|
i.add(e);
|
|
170
|
-
if (e.he || e.
|
|
170
|
+
if (e.he || e.pe) n(e);
|
|
171
171
|
for (let t = e.o; t !== null; t = t.ue) visit(t.le);
|
|
172
172
|
for (let t = e.u ?? null; t !== null; t = t.fe) {
|
|
173
173
|
visit(t);
|
|
@@ -180,17 +180,17 @@ function snapCompanionsToState(e) {
|
|
|
180
180
|
const t = e.he;
|
|
181
181
|
if (t && (t.Ae === undefined || t.Ae === NOT_PENDING)) {
|
|
182
182
|
const n = computePendingState(e);
|
|
183
|
-
if (t.Ue !== n || t.
|
|
183
|
+
if (t.Ue !== n || t.De !== NOT_PENDING) {
|
|
184
184
|
t.Ue = n;
|
|
185
|
-
t.
|
|
185
|
+
t.De = NOT_PENDING;
|
|
186
186
|
t.Se = clock;
|
|
187
187
|
insertSubs(t);
|
|
188
188
|
schedule();
|
|
189
189
|
}
|
|
190
190
|
}
|
|
191
|
-
const n = e.
|
|
191
|
+
const n = e.pe;
|
|
192
192
|
if (n && !(n.se & REACTIVE_DISPOSED)) {
|
|
193
|
-
if ((n.Ae === undefined || n.Ae === NOT_PENDING) && n.
|
|
193
|
+
if ((n.Ae === undefined || n.Ae === NOT_PENDING) && n.De === NOT_PENDING && !Object.is(n.Ue, e.Ue) && !(n.se & (REACTIVE_DIRTY | REACTIVE_CHECK))) {
|
|
194
194
|
n.se |= REACTIVE_DIRTY;
|
|
195
195
|
insertIntoHeap(n, queueFor(n));
|
|
196
196
|
insertSubs(n);
|
|
@@ -201,7 +201,7 @@ function snapCompanionsToState(e) {
|
|
|
201
201
|
}
|
|
202
202
|
|
|
203
203
|
function getLatestValueComputed(e) {
|
|
204
|
-
if (!e.
|
|
204
|
+
if (!e.pe) {
|
|
205
205
|
const t = latestReadActive;
|
|
206
206
|
setLatestReadActive(false);
|
|
207
207
|
const n = pendingCheckActive;
|
|
@@ -209,14 +209,14 @@ function getLatestValueComputed(e) {
|
|
|
209
209
|
const i = context;
|
|
210
210
|
setContextInternal(null);
|
|
211
211
|
// Detach from owner so it isn't disposed with effects
|
|
212
|
-
e.
|
|
213
|
-
e.
|
|
212
|
+
e.pe = optimisticComputed(() => read(e));
|
|
213
|
+
e.pe.nn = e;
|
|
214
214
|
// Parent-child lane relationship
|
|
215
215
|
setContextInternal(i);
|
|
216
216
|
setPendingCheckActive(n);
|
|
217
217
|
setLatestReadActive(t);
|
|
218
218
|
}
|
|
219
|
-
return e.
|
|
219
|
+
return e.pe;
|
|
220
220
|
}
|
|
221
221
|
|
|
222
222
|
/** The latest()-mode read path, installed as GlobalQueue._latestRead. */ function latestRead(e) {
|
|
@@ -255,7 +255,7 @@ function getLatestValueComputed(e) {
|
|
|
255
255
|
// speculative value in _pendingValue; a contextless read() only surfaces
|
|
256
256
|
// _value. Overrides stay authoritative (A17), and stale readers keep the
|
|
257
257
|
// other transition's committed view, matching read()'s own selection.
|
|
258
|
-
if (t.
|
|
258
|
+
if (t.De !== NOT_PENDING && !hasActiveOverride(t) && !(stale && t.Ie && activeTransition !== t.Ie)) return t.De;
|
|
259
259
|
return r;
|
|
260
260
|
}
|
|
261
261
|
|
|
@@ -274,14 +274,14 @@ function getLatestValueComputed(e) {
|
|
|
274
274
|
}
|
|
275
275
|
|
|
276
276
|
function recordFreshRead(e, t) {
|
|
277
|
-
if (pendingProbe !== null && e.
|
|
277
|
+
if (pendingProbe !== null && e.De !== NOT_PENDING && t === e.De) pendingProbe.freshReads.add(e);
|
|
278
278
|
}
|
|
279
279
|
|
|
280
280
|
function applyReask(e, t) {
|
|
281
281
|
const n = !!(e.S & STATUS_PENDING);
|
|
282
|
-
const i = t && !(n && !e.
|
|
283
|
-
const r = n && e.
|
|
284
|
-
e.
|
|
282
|
+
const i = t && !(n && !e.Re);
|
|
283
|
+
const r = n && e.Re !== i;
|
|
284
|
+
e.Re = i;
|
|
285
285
|
return r;
|
|
286
286
|
}
|
|
287
287
|
|
|
@@ -335,11 +335,11 @@ function isPending(e) {
|
|
|
335
335
|
// Hook installation (same late-binding pattern as GlobalQueue._update /
|
|
336
336
|
// _propagateAffects): core call sites fire these behind the same guards the
|
|
337
337
|
// direct calls used, so behavior is identical once this module loads.
|
|
338
|
-
GlobalQueue.
|
|
338
|
+
GlobalQueue._e = syncCompanions;
|
|
339
339
|
|
|
340
340
|
GlobalQueue.ce = updatePendingSignal;
|
|
341
341
|
|
|
342
|
-
GlobalQueue.
|
|
342
|
+
GlobalQueue.Ge = updateChildCompanions;
|
|
343
343
|
|
|
344
344
|
GlobalQueue.un = snapCompanionsToState;
|
|
345
345
|
|
|
@@ -353,6 +353,6 @@ GlobalQueue.$e = applyReask;
|
|
|
353
353
|
|
|
354
354
|
GlobalQueue.k = repollDownstreamVerdicts;
|
|
355
355
|
|
|
356
|
-
GlobalQueue.
|
|
356
|
+
GlobalQueue.Lt = witnessAffects;
|
|
357
357
|
|
|
358
358
|
export { isPending, latest };
|
package/dist/prod/map.js
CHANGED
|
@@ -239,7 +239,7 @@ function updateKeyedMap() {
|
|
|
239
239
|
Kt: e,
|
|
240
240
|
Gt: [],
|
|
241
241
|
xt: [],
|
|
242
|
-
|
|
242
|
+
Vt: i?.from,
|
|
243
243
|
Bt: i?.fallback
|
|
244
244
|
};
|
|
245
245
|
const n = computed(updateRepeat.bind(r));
|
|
@@ -260,7 +260,7 @@ function updateKeyedMap() {
|
|
|
260
260
|
// disjoint-window/front-clear/end-clear/shift special cases.
|
|
261
261
|
function updateRepeat() {
|
|
262
262
|
const t = this.Jt();
|
|
263
|
-
const s = this.
|
|
263
|
+
const s = this.Vt?.() || 0;
|
|
264
264
|
runWithOwner(this.wt, () => {
|
|
265
265
|
if (t === 0) {
|
|
266
266
|
if (this.jt !== 0) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { STATUS_PENDING, CONFIG_AUTO_DISPOSE, NOT_PENDING } from "../core/constants.js";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { computed } from "../core/core.js";
|
|
4
4
|
|
|
5
5
|
import { GlobalQueue, schedule, currentTransition, insertSubs, setProjectionWriteActive, projectionWriteActive } from "../core/scheduler.js";
|
|
6
6
|
|
|
@@ -14,21 +14,40 @@ import { installOptimisticEngine } from "../core/optimistic.js";
|
|
|
14
14
|
|
|
15
15
|
import { runProjectionComputed } from "./projection.js";
|
|
16
16
|
|
|
17
|
-
import {
|
|
17
|
+
import { $TARGET, STORE_FIREWALL, storeSetter, STORE_OPTIMISTIC_OVERRIDE, STORE_NODE, STORE_OPTIMISTIC_OWNERS, getOverlayLayer, STORE_VALUE, $DELETED, isWrappable, wrap, visibleNodeValue, $TRACK, notifySelf, STORE_WRAP, createStoreProxy, storeTraps, STORE_LOOKUP, STORE_SHALLOW, markRawIngest, STORE_OPTIMISTIC } from "./store.js";
|
|
18
18
|
|
|
19
|
-
function createOptimisticStore(e, t,
|
|
19
|
+
function createOptimisticStore(e, t, r) {
|
|
20
20
|
// Register clear function with scheduler; store nodes marked
|
|
21
21
|
// STORE_OPTIMISTIC take the engine's write path, so install it before any
|
|
22
22
|
// node can be created.
|
|
23
23
|
installOptimisticEngine();
|
|
24
|
-
GlobalQueue.
|
|
25
|
-
|
|
24
|
+
if (!GlobalQueue.Dt) {
|
|
25
|
+
GlobalQueue.Dt = clearOptimisticStores;
|
|
26
|
+
// Store half of the engine's override blockage (#2951): signal-form
|
|
27
|
+
// createOptimistic carries the pending async and the override on ONE node,
|
|
28
|
+
// so transitionBlocked sees both; a derived optimistic STORE splits them —
|
|
29
|
+
// the layer sits on store targets while the in-flight truth lives on the
|
|
30
|
+
// firewall computed. Without this, the transition adopting a bare store
|
|
31
|
+
// write settled in the same flush that started the refetch and its settle
|
|
32
|
+
// consumed the layer mid-flight (follow-up writes then drafted from base,
|
|
33
|
+
// clobbering instead of composing). Optimistic state clears when truth
|
|
34
|
+
// lands or its transaction ends — never mid-refetch. Wrapped here (engine
|
|
35
|
+
// is already installed above) so store-free apps never carry the check.
|
|
36
|
+
const e = GlobalQueue.dn;
|
|
37
|
+
GlobalQueue.dn = t => {
|
|
38
|
+
for (const e of t.cn) {
|
|
39
|
+
if ((e[$TARGET]?.[STORE_FIREWALL]?.S ?? 0) & STATUS_PENDING) return true;
|
|
40
|
+
}
|
|
41
|
+
return e(t);
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
const i = typeof e === "function";
|
|
26
45
|
// Plain form: the second slot carries options.
|
|
27
|
-
if (!
|
|
28
|
-
const o =
|
|
29
|
-
const n =
|
|
46
|
+
if (!i && r === undefined) r = t;
|
|
47
|
+
const o = i ? t : e;
|
|
48
|
+
const n = i ? e : undefined;
|
|
30
49
|
// Create optimistic projection store
|
|
31
|
-
const {store: c} = createOptimisticProjectionInternal(n, o,
|
|
50
|
+
const {store: c} = createOptimisticProjectionInternal(n, o, r);
|
|
32
51
|
return [ c, e => storeSetter(c, e) ];
|
|
33
52
|
}
|
|
34
53
|
|
|
@@ -37,8 +56,8 @@ function createOptimisticStore(e, t, i) {
|
|
|
37
56
|
// scheduler's flush tail carries only a size-guarded hook call. The
|
|
38
57
|
// completing transition scopes each clear to its own layer keys (#2899).
|
|
39
58
|
function clearOptimisticStores(e, t) {
|
|
40
|
-
for (const
|
|
41
|
-
const e =
|
|
59
|
+
for (const r of e) {
|
|
60
|
+
const e = r[$TARGET];
|
|
42
61
|
if (e?.[STORE_OPTIMISTIC_OVERRIDE]) clearOptimisticOverride(e, t);
|
|
43
62
|
}
|
|
44
63
|
e.clear();
|
|
@@ -56,9 +75,9 @@ function clearOptimisticStores(e, t) {
|
|
|
56
75
|
* fresh authoritative data) consumes everything — the correction supersedes
|
|
57
76
|
* every tentative layer.
|
|
58
77
|
*/ function clearOptimisticOverride(e, t) {
|
|
59
|
-
const
|
|
60
|
-
if (!
|
|
61
|
-
const
|
|
78
|
+
const r = e[STORE_OPTIMISTIC_OVERRIDE];
|
|
79
|
+
if (!r) return;
|
|
80
|
+
const i = e[STORE_NODE];
|
|
62
81
|
const o = e[STORE_OPTIMISTIC_OWNERS];
|
|
63
82
|
const n = t !== undefined;
|
|
64
83
|
let c = false;
|
|
@@ -68,7 +87,7 @@ function clearOptimisticStores(e, t) {
|
|
|
68
87
|
const O = projectionWriteActive;
|
|
69
88
|
setProjectionWriteActive(true);
|
|
70
89
|
try {
|
|
71
|
-
for (const O of Reflect.ownKeys(
|
|
90
|
+
for (const O of Reflect.ownKeys(r)) {
|
|
72
91
|
if (n) {
|
|
73
92
|
let e = o?.[O] ?? null;
|
|
74
93
|
// Resolve merge chains (entangled actions settle as one); path-compress
|
|
@@ -85,25 +104,25 @@ function clearOptimisticStores(e, t) {
|
|
|
85
104
|
}
|
|
86
105
|
}
|
|
87
106
|
}
|
|
88
|
-
delete
|
|
107
|
+
delete r[O];
|
|
89
108
|
if (o) delete o[O];
|
|
90
109
|
c = true;
|
|
91
|
-
const T =
|
|
110
|
+
const T = i?.[O];
|
|
92
111
|
if (T) {
|
|
93
112
|
// Clear lane association so effects go to regular queue
|
|
94
113
|
T.Me = undefined;
|
|
95
114
|
// Re-read from base — this key left the optimistic layer above, so the
|
|
96
115
|
// overlay resolves to STORE_OVERRIDE or STORE_VALUE.
|
|
97
116
|
const t = getOverlayLayer(e, O);
|
|
98
|
-
const
|
|
99
|
-
const
|
|
100
|
-
const o = isWrappable(
|
|
117
|
+
const r = t ? t[O] : e[STORE_VALUE][O];
|
|
118
|
+
const i = r === $DELETED ? undefined : r;
|
|
119
|
+
const o = isWrappable(i) ? wrap(i, e) : i;
|
|
101
120
|
const n = visibleNodeValue(T);
|
|
102
121
|
T.Ae = NOT_PENDING;
|
|
103
122
|
T.sn = null;
|
|
104
|
-
T.
|
|
123
|
+
T.De = NOT_PENDING;
|
|
105
124
|
T.Ue = o;
|
|
106
|
-
if (!T.
|
|
125
|
+
if (!T.be || !T.be(n, o)) {
|
|
107
126
|
insertSubs(T, true);
|
|
108
127
|
schedule();
|
|
109
128
|
}
|
|
@@ -116,8 +135,8 @@ function clearOptimisticStores(e, t) {
|
|
|
116
135
|
e[STORE_OPTIMISTIC_OWNERS] = undefined;
|
|
117
136
|
}
|
|
118
137
|
// Notify $TRACK
|
|
119
|
-
if (c &&
|
|
120
|
-
|
|
138
|
+
if (c && i?.[$TRACK]) {
|
|
139
|
+
i[$TRACK].Me = undefined;
|
|
121
140
|
notifySelf(e);
|
|
122
141
|
}
|
|
123
142
|
} finally {
|
|
@@ -125,10 +144,10 @@ function clearOptimisticStores(e, t) {
|
|
|
125
144
|
}
|
|
126
145
|
}
|
|
127
146
|
|
|
128
|
-
function createOptimisticProjectionInternal(e, t,
|
|
129
|
-
let
|
|
147
|
+
function createOptimisticProjectionInternal(e, t, r) {
|
|
148
|
+
let i;
|
|
130
149
|
const o = new WeakMap;
|
|
131
|
-
const n = !!
|
|
150
|
+
const n = !!r?.shallow;
|
|
132
151
|
const wrapper = e => {
|
|
133
152
|
e[STORE_WRAP] = wrapProjection;
|
|
134
153
|
e[STORE_LOOKUP] = o;
|
|
@@ -140,7 +159,7 @@ function createOptimisticProjectionInternal(e, t, i) {
|
|
|
140
159
|
// Mark as optimistic store
|
|
141
160
|
Object.defineProperty(e, STORE_FIREWALL, {
|
|
142
161
|
get() {
|
|
143
|
-
return
|
|
162
|
+
return i;
|
|
144
163
|
},
|
|
145
164
|
configurable: true
|
|
146
165
|
});
|
|
@@ -174,19 +193,19 @@ function createOptimisticProjectionInternal(e, t, i) {
|
|
|
174
193
|
setProjectionWriteActive(t);
|
|
175
194
|
}
|
|
176
195
|
};
|
|
177
|
-
|
|
196
|
+
i = computed(() => {
|
|
178
197
|
setProjectionWriteActive(true);
|
|
179
198
|
try {
|
|
180
|
-
runProjectionComputed(c, e,
|
|
199
|
+
runProjectionComputed(c, e, r?.key === undefined ? "id" : r.key, wrapCommit, clearProjectionOverride);
|
|
181
200
|
} finally {
|
|
182
201
|
setProjectionWriteActive(false);
|
|
183
202
|
}
|
|
184
203
|
}, undefined);
|
|
185
|
-
|
|
204
|
+
i.T &= ~CONFIG_AUTO_DISPOSE;
|
|
186
205
|
}
|
|
187
206
|
return {
|
|
188
207
|
store: c,
|
|
189
|
-
node:
|
|
208
|
+
node: i
|
|
190
209
|
};
|
|
191
210
|
}
|
|
192
211
|
|