@solidjs/signals 2.0.0-beta.24 → 2.0.0-beta.25
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 +465 -81
- package/dist/node.cjs +990 -652
- package/dist/prod/core/core.js +110 -76
- package/dist/prod/core/effect.js +9 -9
- package/dist/prod/core/graph.js +3 -3
- package/dist/prod/core/heap.js +23 -23
- package/dist/prod/core/optimistic.js +6 -4
- package/dist/prod/core/owner.js +10 -10
- package/dist/prod/core/scheduler.js +12 -12
- package/dist/prod/core/verdict.js +3 -3
- package/dist/prod/store/optimistic.js +12 -5
- package/dist/prod/store/projection.js +25 -18
- package/dist/prod/store/reconcile.js +405 -211
- package/dist/prod/store/store.js +196 -102
- package/dist/prod/store/utils.js +22 -22
- package/dist/types/core/core.d.ts +15 -0
- package/dist/types/store/optimistic.d.ts +1 -1
- package/dist/types/store/store.d.ts +20 -2
- package/dist/types-cjs/core/core.d.cts +15 -0
- package/dist/types-cjs/store/optimistic.d.cts +1 -1
- package/dist/types-cjs/store/store.d.cts +20 -2
- package/package.json +1 -1
package/dist/prod/core/core.js
CHANGED
|
@@ -82,7 +82,7 @@ function releaseSubtree(e) {
|
|
|
82
82
|
if (e.se & REACTIVE_SNAPSHOT_STALE) {
|
|
83
83
|
e.se &= ~REACTIVE_SNAPSHOT_STALE;
|
|
84
84
|
e.se |= REACTIVE_DIRTY;
|
|
85
|
-
if (dirtyQueue.
|
|
85
|
+
if (dirtyQueue.Fe > e.He) dirtyQueue.Fe = e.He;
|
|
86
86
|
insertIntoHeap(e, dirtyQueue);
|
|
87
87
|
}
|
|
88
88
|
}
|
|
@@ -114,27 +114,27 @@ function recompute(e, t = false) {
|
|
|
114
114
|
// Tracked effects run after finalizePureQueue, so dispose immediately instead of deferring
|
|
115
115
|
if (e.Ue || n === EFFECT_TRACKED) disposeChildren(e); else if (e.me !== null || e.xe !== null) {
|
|
116
116
|
markDisposal(e);
|
|
117
|
-
e.
|
|
118
|
-
e.
|
|
117
|
+
e.Le = e.xe;
|
|
118
|
+
e.ye = e.me;
|
|
119
119
|
e.xe = null;
|
|
120
120
|
e.me = null;
|
|
121
121
|
e.Qe = 0;
|
|
122
122
|
} else ;
|
|
123
123
|
}
|
|
124
124
|
let i = !!(e.se & REACTIVE_OPTIMISTIC_DIRTY);
|
|
125
|
-
const
|
|
126
|
-
const
|
|
125
|
+
const u = e.Ee !== undefined && e.Ee !== NOT_PENDING;
|
|
126
|
+
const l = !!(e.S & STATUS_UNINITIALIZED);
|
|
127
127
|
// Re-ask classification lives in the verdict module; capture the flag before
|
|
128
128
|
// the recompute wipes _flags below.
|
|
129
129
|
const o = (e.se & REACTIVE_REASK) !== 0;
|
|
130
130
|
const s = context;
|
|
131
131
|
context = e;
|
|
132
132
|
e.qe = null;
|
|
133
|
-
e.
|
|
133
|
+
e.We++;
|
|
134
134
|
e.se = REACTIVE_RECOMPUTING_DEPS;
|
|
135
135
|
e.ce = clock;
|
|
136
136
|
let a = e.Ne === NOT_PENDING ? e.Pe : e.Ne;
|
|
137
|
-
let r = e.
|
|
137
|
+
let r = e.He;
|
|
138
138
|
let c = tracking;
|
|
139
139
|
let _ = currentOptimisticLane;
|
|
140
140
|
tracking = true;
|
|
@@ -144,27 +144,27 @@ function recompute(e, t = false) {
|
|
|
144
144
|
// computed) inside latest(fn) came out permanently dependency-less (#2926).
|
|
145
145
|
// latestRead() already suspends the flag for its pull-recomputes; this
|
|
146
146
|
// covers creation-time computes and flushes that run inside the window.
|
|
147
|
-
const
|
|
147
|
+
const f = latestReadActive;
|
|
148
148
|
latestReadActive = false;
|
|
149
149
|
// Lane posture lives with the engine: OPTIMISTIC_DIRTY is only ever set by
|
|
150
150
|
// engine-driven paths, and _optimisticNodes is only pushed by
|
|
151
151
|
// _optimisticWrite, so the hook is installed whenever either gate holds.
|
|
152
152
|
if (i) {
|
|
153
|
-
const t = GlobalQueue.
|
|
153
|
+
const t = GlobalQueue.Ye(e, true);
|
|
154
154
|
if (t) currentOptimisticLane = t;
|
|
155
155
|
} else if (activeTransition && !t && activeTransition.Ze.length) {
|
|
156
156
|
// Lane adoption: parent-deeper-than-owned-child can run before its OPT-dirty
|
|
157
157
|
// child propagates. Walk deps once and inherit the OPT lane so this node
|
|
158
158
|
// recomputes under the right posture and propagates correctly.
|
|
159
|
-
const t = GlobalQueue.
|
|
159
|
+
const t = GlobalQueue.Ye(e, false);
|
|
160
160
|
if (t) {
|
|
161
161
|
i = true;
|
|
162
162
|
currentOptimisticLane = t;
|
|
163
163
|
}
|
|
164
164
|
}
|
|
165
|
-
const
|
|
165
|
+
const E = n && n !== EFFECT_USER;
|
|
166
166
|
const N = stale;
|
|
167
|
-
if (
|
|
167
|
+
if (E) stale = true;
|
|
168
168
|
try {
|
|
169
169
|
if (!false && e.T & CONFIG_SYNC) {
|
|
170
170
|
a = e.ke(a);
|
|
@@ -178,11 +178,14 @@ function recompute(e, t = false) {
|
|
|
178
178
|
const t = e.Te;
|
|
179
179
|
const n = e.ke(a);
|
|
180
180
|
const i = typeof n === "object" && n !== null;
|
|
181
|
-
const
|
|
182
|
-
a =
|
|
183
|
-
if (!
|
|
181
|
+
const u = e.Te !== t;
|
|
182
|
+
a = u || !i ? n : handleAsync(e, n);
|
|
183
|
+
if (!u && !i) e.Te = null;
|
|
184
184
|
}
|
|
185
|
-
clearStatus
|
|
185
|
+
// On a status-free node clearStatus is a guaranteed no-op: every branch
|
|
186
|
+
// in its body is gated on one of these fields, and with _statusFlags === 0
|
|
187
|
+
// the flags write (create or not) stores the 0 already there.
|
|
188
|
+
if (e.S !== 0 || e.i !== undefined || e._ || e._e || e.Se || e.oe !== undefined || e.be !== undefined || e.ge !== undefined || e.u !== null) clearStatus(e, t);
|
|
186
189
|
// _optimisticLane is only ever assigned by engine paths.
|
|
187
190
|
if (e.je) GlobalQueue.Me(e);
|
|
188
191
|
} catch (t) {
|
|
@@ -198,17 +201,17 @@ function recompute(e, t = false) {
|
|
|
198
201
|
if (n) GlobalQueue.k(e);
|
|
199
202
|
} finally {
|
|
200
203
|
tracking = c;
|
|
201
|
-
latestReadActive =
|
|
202
|
-
if (
|
|
204
|
+
latestReadActive = f;
|
|
205
|
+
if (E) stale = N;
|
|
203
206
|
e.se = REACTIVE_NONE | (t ? e.se & REACTIVE_SNAPSHOT_STALE : 0);
|
|
204
207
|
context = s;
|
|
205
208
|
}
|
|
206
209
|
if (!e._) {
|
|
207
210
|
trimStaleDeps(e);
|
|
208
|
-
const o =
|
|
211
|
+
const o = u ? unwrapOverride(e.Ee) : e.Ne === NOT_PENDING ? e.Pe : e.Ne;
|
|
209
212
|
let s = false;
|
|
210
213
|
try {
|
|
211
|
-
s = !n &&
|
|
214
|
+
s = !n && l || !e.Re || !e.Re(o, a);
|
|
212
215
|
} catch (t) {
|
|
213
216
|
// A throwing user comparator is an error of this node's computation.
|
|
214
217
|
// Route it through the same status path as a compute-phase throw so
|
|
@@ -228,14 +231,19 @@ function recompute(e, t = false) {
|
|
|
228
231
|
if (!t) e.C.enqueue(n, e.Be ??= GlobalQueue.Je.bind(null, e));
|
|
229
232
|
}
|
|
230
233
|
if (e._) ; else if (s) {
|
|
231
|
-
const
|
|
232
|
-
if (t ||
|
|
234
|
+
const l = u ? e.Ee : undefined;
|
|
235
|
+
if (t ||
|
|
236
|
+
// Plain sync flush (no transition on either side) commits effect
|
|
237
|
+
// values directly — the pending round-trip (queuePendingNode +
|
|
238
|
+
// commitPendingNodes) exists to sequence transition reveals, and
|
|
239
|
+
// paying it per effect on the plain path is pure overhead.
|
|
240
|
+
n && (activeTransition !== e.Ue || activeTransition === null) || i) {
|
|
233
241
|
e.Pe = a;
|
|
234
242
|
// Lane-propagated correction: upstream data is fresh, correct the
|
|
235
243
|
// override unconditionally. The direct _value commit is the lane's
|
|
236
244
|
// own reveal schedule; drop any superseded older hold so its queued
|
|
237
245
|
// commit can't clobber the fresh value.
|
|
238
|
-
if (
|
|
246
|
+
if (u && i) {
|
|
239
247
|
e.Ee = a === undefined ? OVERRIDE_UNDEFINED : a;
|
|
240
248
|
e.Ne = NOT_PENDING;
|
|
241
249
|
}
|
|
@@ -248,27 +256,29 @@ function recompute(e, t = false) {
|
|
|
248
256
|
// pending value commits before effects run.
|
|
249
257
|
if ((activeTransition || e.Ue) && GlobalQueue.Ie !== null) GlobalQueue.Ie(e, a);
|
|
250
258
|
}
|
|
251
|
-
|
|
252
|
-
|
|
259
|
+
// insertSubs only walks _subs (no scheduling of its own), so a
|
|
260
|
+
// subscriber-less node has nothing to notify.
|
|
261
|
+
if (e.o !== null && (!u || i || e.Ee !== l)) insertSubs(e, i || u);
|
|
262
|
+
} else if (u) {
|
|
253
263
|
// Unchanged value (equals the override) recomputed while the override
|
|
254
264
|
// is active: _value may still be stale, so hold the authoritative value
|
|
255
265
|
// for commit on its own transition's schedule — invisibly (A17/A18).
|
|
256
266
|
if (e.Ne === NOT_PENDING) queuePendingNode(e);
|
|
257
267
|
e.Ne = a;
|
|
258
|
-
} else if (e.
|
|
268
|
+
} else if (e.He != r) {
|
|
259
269
|
for (let t = e.o; t !== null; t = t.ue) {
|
|
260
270
|
insertIntoHeapHeight(t.le, queueFor(t.le));
|
|
261
271
|
}
|
|
262
272
|
}
|
|
263
273
|
}
|
|
264
274
|
currentOptimisticLane = _;
|
|
265
|
-
const T = e.Ne !== NOT_PENDING || e.
|
|
275
|
+
const T = e.Ne !== NOT_PENDING || e.ye !== null || e.Le !== null || (e.S & (STATUS_PENDING | STATUS_UNINITIALIZED)) !== 0;
|
|
266
276
|
// Override-covered holds (hasOverride) always queue: their commit belongs
|
|
267
277
|
// to their own transition's schedule (A18 re-rule) and is unobservable
|
|
268
278
|
// under the override (A17). Revert no longer commits anything, so an
|
|
269
279
|
// unqueued covered hold would leak (INV-7) once the revert clears
|
|
270
280
|
// _transition.
|
|
271
|
-
T && (!t || e.S & STATUS_PENDING) && (!e.Ue ||
|
|
281
|
+
T && (!t || e.S & STATUS_PENDING) && (!e.Ue || u) && queuePendingNode(e);
|
|
272
282
|
e.Ue && n && activeTransition !== e.Ue && runInTransition(e.Ue, () => recompute(e));
|
|
273
283
|
}
|
|
274
284
|
|
|
@@ -304,13 +314,13 @@ function computed(e, t) {
|
|
|
304
314
|
Qe: 0,
|
|
305
315
|
ke: e,
|
|
306
316
|
Pe: undefined,
|
|
307
|
-
|
|
317
|
+
He: 0,
|
|
308
318
|
u: null,
|
|
309
|
-
|
|
310
|
-
|
|
319
|
+
ut: undefined,
|
|
320
|
+
lt: null,
|
|
311
321
|
Xe: null,
|
|
312
322
|
qe: null,
|
|
313
|
-
|
|
323
|
+
We: 0,
|
|
314
324
|
o: null,
|
|
315
325
|
ot: null,
|
|
316
326
|
Ge: context,
|
|
@@ -321,8 +331,8 @@ function computed(e, t) {
|
|
|
321
331
|
S: STATUS_UNINITIALIZED,
|
|
322
332
|
ce: clock,
|
|
323
333
|
Ne: NOT_PENDING,
|
|
324
|
-
ye: null,
|
|
325
334
|
Le: null,
|
|
335
|
+
ye: null,
|
|
326
336
|
Te: null,
|
|
327
337
|
Ue: null,
|
|
328
338
|
_e: false
|
|
@@ -336,26 +346,26 @@ function computed(e, t) {
|
|
|
336
346
|
* so V8 sees the full hidden class shape at construction time. Effects always run in lazy
|
|
337
347
|
* mode (recompute is called explicitly by `effect()`), so we hardcode the lazy bits and skip
|
|
338
348
|
* the auto-dispose CONFIG bit (effect() previously cleared it post-construction).
|
|
339
|
-
*/ function createEffectNode(e, t, n, i,
|
|
340
|
-
const o =
|
|
349
|
+
*/ function createEffectNode(e, t, n, i, u, l) {
|
|
350
|
+
const o = l?.transparent ?? false;
|
|
341
351
|
const s = {
|
|
342
|
-
id: inheritId(
|
|
343
|
-
T: (o ? CONFIG_TRANSPARENT : 0) | (
|
|
352
|
+
id: inheritId(l, o, context),
|
|
353
|
+
T: (o ? CONFIG_TRANSPARENT : 0) | (l?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (l?.sync ? CONFIG_SYNC : 0) | (snapshotCaptureActive && ownerInSnapshotScope(context) ? CONFIG_IN_SNAPSHOT_SCOPE : 0),
|
|
344
354
|
Re: false,
|
|
345
|
-
it:
|
|
355
|
+
it: l?.unobserved,
|
|
346
356
|
xe: null,
|
|
347
357
|
C: context?.C ?? globalQueue,
|
|
348
358
|
we: context?.we ?? defaultContext,
|
|
349
359
|
Qe: 0,
|
|
350
360
|
ke: e,
|
|
351
361
|
Pe: undefined,
|
|
352
|
-
|
|
362
|
+
He: 0,
|
|
353
363
|
u: null,
|
|
354
|
-
|
|
355
|
-
|
|
364
|
+
ut: undefined,
|
|
365
|
+
lt: null,
|
|
356
366
|
Xe: null,
|
|
357
367
|
qe: null,
|
|
358
|
-
|
|
368
|
+
We: 0,
|
|
359
369
|
o: null,
|
|
360
370
|
ot: null,
|
|
361
371
|
Ge: context,
|
|
@@ -366,8 +376,8 @@ function computed(e, t) {
|
|
|
366
376
|
S: STATUS_UNINITIALIZED,
|
|
367
377
|
ce: clock,
|
|
368
378
|
Ne: NOT_PENDING,
|
|
369
|
-
ye: null,
|
|
370
379
|
Le: null,
|
|
380
|
+
ye: null,
|
|
371
381
|
Te: null,
|
|
372
382
|
Ue: null,
|
|
373
383
|
_e: false,
|
|
@@ -375,9 +385,9 @@ function computed(e, t) {
|
|
|
375
385
|
rt: undefined,
|
|
376
386
|
ct: t,
|
|
377
387
|
_t: n,
|
|
378
|
-
|
|
388
|
+
ft: undefined,
|
|
379
389
|
Ae: i,
|
|
380
|
-
i:
|
|
390
|
+
i: u
|
|
381
391
|
};
|
|
382
392
|
setupComputedNode(s, lazyOptions);
|
|
383
393
|
return s;
|
|
@@ -388,8 +398,8 @@ const lazyOptions = {
|
|
|
388
398
|
};
|
|
389
399
|
|
|
390
400
|
function setupComputedNode(e, t) {
|
|
391
|
-
e.
|
|
392
|
-
const n = context?.
|
|
401
|
+
e.lt = e;
|
|
402
|
+
const n = context?.Et ? context.Nt : context;
|
|
393
403
|
if (context) {
|
|
394
404
|
const t = context.me;
|
|
395
405
|
if (t === null) {
|
|
@@ -400,7 +410,7 @@ function setupComputedNode(e, t) {
|
|
|
400
410
|
context.me = e;
|
|
401
411
|
}
|
|
402
412
|
}
|
|
403
|
-
if (n) e.
|
|
413
|
+
if (n) e.He = n.He + 1;
|
|
404
414
|
if (GlobalQueue.Tt !== null) GlobalQueue.Tt(e);
|
|
405
415
|
!t?.lazy && recompute(e, true);
|
|
406
416
|
if (snapshotCaptureActive && !t?.lazy) {
|
|
@@ -496,59 +506,80 @@ function isEqual(e, t) {
|
|
|
496
506
|
}
|
|
497
507
|
}
|
|
498
508
|
|
|
509
|
+
/**
|
|
510
|
+
* Sentinel returned by readNodeFast when the plain-signal fast path does not
|
|
511
|
+
* apply and the caller must fall back to the full read().
|
|
512
|
+
*/ const READ_SLOW = Symbol("read-slow");
|
|
513
|
+
|
|
514
|
+
/**
|
|
515
|
+
* read()'s plain-signal fast path as a standalone entry for hot callers
|
|
516
|
+
* (store traps). Safe to substitute for read() only because the bail
|
|
517
|
+
* conditions mirror read()'s prelude and fast-path guard exactly: the
|
|
518
|
+
* latestRead and pendingCheck windows run side-effectful hooks before the
|
|
519
|
+
* fast path, `_fn` nodes need prepareComputed, and firewall / override /
|
|
520
|
+
* snapshot / transition / lane / dev-strictRead state all take the full
|
|
521
|
+
* resolution. Anything slow returns READ_SLOW; the caller then calls read().
|
|
522
|
+
*/ function readNodeFast(e) {
|
|
523
|
+
if (latestReadActive || pendingCheckActive || e.ke || e.nt || e.Ee !== undefined || e.Ve !== undefined || activeTransition !== null || currentOptimisticLane !== null || snapshotCaptureActive || false) return READ_SLOW;
|
|
524
|
+
let t = context;
|
|
525
|
+
if (t?.Et) t = t.Nt;
|
|
526
|
+
if (t && tracking) link(e, t);
|
|
527
|
+
return !t || e.Ne === NOT_PENDING ? e.Pe : e.Ne;
|
|
528
|
+
}
|
|
529
|
+
|
|
499
530
|
function read(e) {
|
|
500
531
|
// Handle latest() mode: read from _latestValueComputed
|
|
501
532
|
// Checked before isPending so that isPending(() => latest(x)) checks
|
|
502
533
|
// the _pendingSignal of _latestValueComputed (async in flight) rather
|
|
503
534
|
// than the original node (which stays "pending" while held in a transition).
|
|
504
|
-
if (latestReadActive) return GlobalQueue.
|
|
535
|
+
if (latestReadActive) return GlobalQueue.dt(e);
|
|
505
536
|
let t = context;
|
|
506
|
-
if (t?.
|
|
537
|
+
if (t?.Et) t = t.Nt;
|
|
507
538
|
const n = e;
|
|
508
539
|
const i = e.nt;
|
|
509
|
-
const
|
|
540
|
+
const u = i || e;
|
|
510
541
|
// Handle isPending() mode: collect pending state while preserving normal read semantics.
|
|
511
542
|
// Probe mode is suspended while preparing the node so nested reads during a
|
|
512
543
|
// recompute don't collect into the probe.
|
|
513
544
|
if (pendingCheckActive) {
|
|
514
|
-
GlobalQueue.
|
|
545
|
+
GlobalQueue.St(e, t, u, i);
|
|
515
546
|
} else if (typeof n.ke === "function") {
|
|
516
547
|
prepareComputed(e, false);
|
|
517
548
|
}
|
|
518
|
-
if (!n.ke &&
|
|
549
|
+
if (!n.ke && u === e && e.Ee === undefined && e.Ve === undefined && activeTransition === null && currentOptimisticLane === null && !snapshotCaptureActive && true) {
|
|
519
550
|
if (t && tracking) link(e, t);
|
|
520
551
|
return !t || e.Ne === NOT_PENDING ? e.Pe : e.Ne;
|
|
521
552
|
}
|
|
522
553
|
if (t && tracking) {
|
|
523
554
|
link(e, t, pendingCheckActive);
|
|
524
|
-
if (
|
|
555
|
+
if (u.ke) {
|
|
525
556
|
const n = queueFor(e);
|
|
526
|
-
if (
|
|
557
|
+
if (u.He >= n.Fe) {
|
|
527
558
|
markNode(t);
|
|
528
559
|
markHeap(n);
|
|
529
|
-
updateIfNecessary(
|
|
560
|
+
updateIfNecessary(u);
|
|
530
561
|
}
|
|
531
|
-
const i =
|
|
562
|
+
const i = u.He;
|
|
532
563
|
// parent check is shallow, might need to be recursive
|
|
533
|
-
if (i >= t.
|
|
534
|
-
t.
|
|
564
|
+
if (i >= t.He && e.Ge !== t) {
|
|
565
|
+
t.He = i + 1;
|
|
535
566
|
}
|
|
536
567
|
}
|
|
537
568
|
}
|
|
538
|
-
if (
|
|
539
|
-
if (t && !(stale &&
|
|
569
|
+
if (u.S & STATUS_PENDING) {
|
|
570
|
+
if (t && !(stale && u.Ue && activeTransition !== u.Ue)) {
|
|
540
571
|
// Per-lane suspension lives with the engine (a non-null lane implies it
|
|
541
572
|
// is installed): under a lane, only same-lane pending async without an
|
|
542
573
|
// active override throws.
|
|
543
|
-
if (currentOptimisticLane === null || GlobalQueue.At(
|
|
574
|
+
if (currentOptimisticLane === null || GlobalQueue.At(u)) {
|
|
544
575
|
if (!tracking && e !== t) link(e, t);
|
|
545
|
-
throw
|
|
576
|
+
throw u._;
|
|
546
577
|
}
|
|
547
|
-
} else if (t &&
|
|
578
|
+
} else if (t && u !== e && u.S & STATUS_UNINITIALIZED) {
|
|
548
579
|
if (!tracking && e !== t) link(e, t);
|
|
549
|
-
throw
|
|
550
|
-
} else if (!t &&
|
|
551
|
-
throw
|
|
580
|
+
throw u._;
|
|
581
|
+
} else if (!t && u.S & STATUS_UNINITIALIZED) {
|
|
582
|
+
throw u._;
|
|
552
583
|
}
|
|
553
584
|
}
|
|
554
585
|
if (e.ke && e.S & STATUS_ERROR) {
|
|
@@ -565,8 +596,8 @@ function read(e) {
|
|
|
565
596
|
const n = e.Ve;
|
|
566
597
|
if (n !== undefined) {
|
|
567
598
|
const i = n === NO_SNAPSHOT ? undefined : n;
|
|
568
|
-
const
|
|
569
|
-
if (
|
|
599
|
+
const u = e.Ne !== NOT_PENDING ? e.Ne : e.Pe;
|
|
600
|
+
if (u !== i) t.se |= REACTIVE_SNAPSHOT_STALE;
|
|
570
601
|
return i;
|
|
571
602
|
}
|
|
572
603
|
}
|
|
@@ -581,21 +612,21 @@ function read(e) {
|
|
|
581
612
|
// _pendingValue for correct fetching. The sub is recorded for replay at commit
|
|
582
613
|
// so it re-runs with the new committed view. (Gate details live with the
|
|
583
614
|
// engine — a non-null lane implies it is installed.)
|
|
584
|
-
if (currentOptimisticLane !== null && activeTransition !== null && t !== null && GlobalQueue.Ct(e,
|
|
615
|
+
if (currentOptimisticLane !== null && activeTransition !== null && t !== null && GlobalQueue.Ct(e, u, t)) {
|
|
585
616
|
return e.Pe;
|
|
586
617
|
}
|
|
587
618
|
// In optimistic lane context, return _value for optimistic/lane-assigned signals
|
|
588
619
|
// and for regular signals in stale mode (render effects). Non-stale readers (user
|
|
589
620
|
// effects) see _pendingValue so that latest() and direct reads stay consistent.
|
|
590
621
|
// (The lane-context clause lives with the engine.)
|
|
591
|
-
const
|
|
622
|
+
const l = !t || currentOptimisticLane !== null && GlobalQueue.Ot(e, u, t) || e.Ne === NOT_PENDING || stale && e.Ue && activeTransition !== e.Ue ? e.Pe : e.Ne;
|
|
592
623
|
// Record that this isPending() probe observed the fresh pending value, so
|
|
593
624
|
// the probe doesn't pair "pending" with the new value (#2831).
|
|
594
|
-
if (pendingCheckActive) GlobalQueue.Rt(e,
|
|
595
|
-
if (!t &&
|
|
625
|
+
if (pendingCheckActive) GlobalQueue.Rt(e, l);
|
|
626
|
+
if (!t && u === e && typeof n.ke === "function" && e.T & CONFIG_AUTO_DISPOSE && !(u.S & STATUS_PENDING) && !e.o) {
|
|
596
627
|
unobserved(e);
|
|
597
628
|
}
|
|
598
|
-
return
|
|
629
|
+
return l;
|
|
599
630
|
}
|
|
600
631
|
|
|
601
632
|
function setSignal(e, t) {
|
|
@@ -613,7 +644,10 @@ function setSignal(e, t) {
|
|
|
613
644
|
if (!i) return t;
|
|
614
645
|
if (e.Ne === NOT_PENDING) queuePendingNode(e);
|
|
615
646
|
e.Ne = t;
|
|
616
|
-
|
|
647
|
+
// syncCompanions only pokes _pendingSignal/_latestValueComputed — with
|
|
648
|
+
// neither companion present the call is a guaranteed no-op (companions are
|
|
649
|
+
// only ever created, never removed, and creating one installs the hook).
|
|
650
|
+
(e.be !== undefined || e.ge !== undefined) && GlobalQueue.Ie !== null && GlobalQueue.Ie(e, t);
|
|
617
651
|
e.ce = clock;
|
|
618
652
|
insertSubs(e);
|
|
619
653
|
schedule();
|
|
@@ -729,4 +763,4 @@ function staleValues(e, t = true) {
|
|
|
729
763
|
}
|
|
730
764
|
}
|
|
731
765
|
|
|
732
|
-
export { clearSnapshots, computed, context, createEffectNode, currentOptimisticLane, isEqual, latestReadActive, markSnapshotScope, optimisticComputed, optimisticSignal, pendingCheckActive, prepareComputed, read, recompute, refresh, releaseSnapshotScope, runWithOwner, setContextInternal, setLatestReadActive, setMemo, setPendingCheckActive, setSignal, setSnapshotCapture, signal, snapshotCaptureActive, snapshotSources, stale, staleValues, suppressComputedRecompute, tracking, untrack };
|
|
766
|
+
export { READ_SLOW, clearSnapshots, computed, context, createEffectNode, currentOptimisticLane, isEqual, latestReadActive, markSnapshotScope, optimisticComputed, optimisticSignal, pendingCheckActive, prepareComputed, read, readNodeFast, recompute, refresh, releaseSnapshotScope, runWithOwner, setContextInternal, setLatestReadActive, setMemo, setPendingCheckActive, setSignal, setSnapshotCapture, signal, snapshotCaptureActive, snapshotSources, stale, staleValues, suppressComputedRecompute, tracking, untrack };
|
package/dist/prod/core/effect.js
CHANGED
|
@@ -66,8 +66,8 @@ function runEffect(t) {
|
|
|
66
66
|
t.$e = false;
|
|
67
67
|
try {
|
|
68
68
|
t._t ? t._t(E, () => {
|
|
69
|
-
const E = t.
|
|
70
|
-
t.
|
|
69
|
+
const E = t.ft;
|
|
70
|
+
t.ft = undefined;
|
|
71
71
|
E?.();
|
|
72
72
|
}) : console.error(E);
|
|
73
73
|
} catch (E) {
|
|
@@ -78,14 +78,14 @@ function runEffect(t) {
|
|
|
78
78
|
}
|
|
79
79
|
return;
|
|
80
80
|
}
|
|
81
|
-
const E = t.
|
|
82
|
-
t.
|
|
81
|
+
const E = t.ft;
|
|
82
|
+
t.ft = undefined;
|
|
83
83
|
try {
|
|
84
84
|
E?.();
|
|
85
85
|
const e = t.ct(t.Pe, t.rt);
|
|
86
86
|
if (false && e !== undefined && typeof e !== "function") ;
|
|
87
87
|
// The final cleanup is invoked by disposeChildren at true disposal.
|
|
88
|
-
t.
|
|
88
|
+
t.ft = e;
|
|
89
89
|
} catch (E) {
|
|
90
90
|
t._ = new StatusError(t, E);
|
|
91
91
|
t.S |= STATUS_ERROR;
|
|
@@ -114,16 +114,16 @@ GlobalQueue.Je = runEffect;
|
|
|
114
114
|
} finally {}
|
|
115
115
|
};
|
|
116
116
|
const e = computed(() => {
|
|
117
|
-
const E = e.
|
|
118
|
-
e.
|
|
117
|
+
const E = e.ft;
|
|
118
|
+
e.ft = undefined;
|
|
119
119
|
E?.();
|
|
120
120
|
const R = staleValues(t);
|
|
121
|
-
e.
|
|
121
|
+
e.ft = R;
|
|
122
122
|
}, {
|
|
123
123
|
...E,
|
|
124
124
|
lazy: true
|
|
125
125
|
});
|
|
126
|
-
e.
|
|
126
|
+
e.ft = undefined;
|
|
127
127
|
e.T = e.T & ~CONFIG_AUTO_DISPOSE | CONFIG_CHILDREN_FORBIDDEN;
|
|
128
128
|
e.$e = true;
|
|
129
129
|
e.Ae = EFFECT_TRACKED;
|
package/dist/prod/core/graph.js
CHANGED
|
@@ -69,7 +69,7 @@ function link(l, n, e = false) {
|
|
|
69
69
|
if (t) {
|
|
70
70
|
s = u !== null ? u.et : n.Xe;
|
|
71
71
|
if (s !== null && s.tt === l) {
|
|
72
|
-
s.nl = n.
|
|
72
|
+
s.nl = n.We;
|
|
73
73
|
n.qe = s;
|
|
74
74
|
// First touch of this pass: the previous pass's label is stale.
|
|
75
75
|
s.De = e;
|
|
@@ -82,7 +82,7 @@ function link(l, n, e = false) {
|
|
|
82
82
|
// (the old alien-signals `isValidLink` walk, O(n²) when a computation
|
|
83
83
|
// re-reads earlier deps non-consecutively, e.g. store leaf reads).
|
|
84
84
|
const i = l.ot;
|
|
85
|
-
if (i !== null && i.le === n && (!t || i.nl === n.
|
|
85
|
+
if (i !== null && i.le === n && (!t || i.nl === n.We)) {
|
|
86
86
|
// Gen-matched during a recompute = repeat touch this pass (AND); outside
|
|
87
87
|
// a recompute there is no pass boundary, so the latest read labels it.
|
|
88
88
|
if (t) i.De &&= e; else i.De = e;
|
|
@@ -94,7 +94,7 @@ function link(l, n, e = false) {
|
|
|
94
94
|
et: s,
|
|
95
95
|
ll: i,
|
|
96
96
|
ue: null,
|
|
97
|
-
nl: n.
|
|
97
|
+
nl: n.We,
|
|
98
98
|
De: e
|
|
99
99
|
};
|
|
100
100
|
if (u !== null) u.et = o; else n.Xe = o;
|
package/dist/prod/core/heap.js
CHANGED
|
@@ -20,20 +20,20 @@ import { zombieQueue, dirtyQueue } from "./scheduler.js";
|
|
|
20
20
|
return;
|
|
21
21
|
}
|
|
22
22
|
const E = queueFor(e);
|
|
23
|
-
if (E.
|
|
23
|
+
if (E.Fe > e.He) E.Fe = e.He;
|
|
24
24
|
insertIntoHeap(e, E);
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
function actualInsertIntoHeap(e, E) {
|
|
28
|
-
const t = (e.Ge?.
|
|
29
|
-
if (t >= e.
|
|
30
|
-
const n = e.
|
|
28
|
+
const t = (e.Ge?.Et ? e.Ge.Nt?.He : e.Ge?.He) ?? -1;
|
|
29
|
+
if (t >= e.He) e.He = t + 1;
|
|
30
|
+
const n = e.He;
|
|
31
31
|
const I = E.eE[n];
|
|
32
32
|
if (I === undefined) E.eE[n] = e; else {
|
|
33
|
-
const E = I.
|
|
34
|
-
E.
|
|
35
|
-
e.
|
|
36
|
-
I.
|
|
33
|
+
const E = I.lt;
|
|
34
|
+
E.ut = e;
|
|
35
|
+
e.lt = E;
|
|
36
|
+
I.lt = e;
|
|
37
37
|
}
|
|
38
38
|
if (n > E.EE) E.EE = n;
|
|
39
39
|
}
|
|
@@ -66,23 +66,23 @@ function deleteFromHeap(e, E) {
|
|
|
66
66
|
const t = e.se;
|
|
67
67
|
if (!(t & (REACTIVE_IN_HEAP | REACTIVE_IN_HEAP_HEIGHT))) return;
|
|
68
68
|
e.se = t & -25;
|
|
69
|
-
const n = e.
|
|
70
|
-
if (e.
|
|
71
|
-
const t = e.
|
|
69
|
+
const n = e.He;
|
|
70
|
+
if (e.lt === e) E.eE[n] = undefined; else {
|
|
71
|
+
const t = e.ut;
|
|
72
72
|
const I = E.eE[n];
|
|
73
73
|
const o = t ?? I;
|
|
74
|
-
if (e === I) E.eE[n] = t; else e.ut
|
|
75
|
-
o.
|
|
74
|
+
if (e === I) E.eE[n] = t; else e.lt.ut = t;
|
|
75
|
+
o.lt = e.lt;
|
|
76
76
|
}
|
|
77
|
-
e.
|
|
78
|
-
e.
|
|
77
|
+
e.lt = e;
|
|
78
|
+
e.ut = undefined;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
function markHeap(e) {
|
|
82
82
|
if (e.tE) return;
|
|
83
83
|
e.tE = true;
|
|
84
84
|
for (let E = 0; E <= e.EE; E++) {
|
|
85
|
-
for (let t = e.eE[E]; t !== undefined; t = t.
|
|
85
|
+
for (let t = e.eE[E]; t !== undefined; t = t.ut) {
|
|
86
86
|
if (t.se & REACTIVE_IN_HEAP) markNode(t);
|
|
87
87
|
}
|
|
88
88
|
}
|
|
@@ -106,11 +106,11 @@ function markNode(e, E = REACTIVE_DIRTY) {
|
|
|
106
106
|
|
|
107
107
|
function runHeap(e, E) {
|
|
108
108
|
e.tE = false;
|
|
109
|
-
for (e.
|
|
110
|
-
let t = e.eE[e.
|
|
109
|
+
for (e.Fe = 0; e.Fe <= e.EE; e.Fe++) {
|
|
110
|
+
let t = e.eE[e.Fe];
|
|
111
111
|
while (t !== undefined) {
|
|
112
112
|
if (t.se & REACTIVE_IN_HEAP) E(t); else adjustHeight(t, e);
|
|
113
|
-
t = e.eE[e.
|
|
113
|
+
t = e.eE[e.Fe];
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
116
|
e.EE = 0;
|
|
@@ -118,14 +118,14 @@ function runHeap(e, E) {
|
|
|
118
118
|
|
|
119
119
|
function adjustHeight(e, E) {
|
|
120
120
|
deleteFromHeap(e, E);
|
|
121
|
-
let t = e.
|
|
121
|
+
let t = e.He;
|
|
122
122
|
for (let E = e.Xe; E; E = E.et) {
|
|
123
123
|
const e = E.tt;
|
|
124
124
|
const n = e.nt || e;
|
|
125
|
-
if (n.ke && n.
|
|
125
|
+
if (n.ke && n.He >= t) t = n.He + 1;
|
|
126
126
|
}
|
|
127
|
-
if (e.
|
|
128
|
-
e.
|
|
127
|
+
if (e.He !== t) {
|
|
128
|
+
e.He = t;
|
|
129
129
|
for (let E = e.o; E !== null; E = E.ue) {
|
|
130
130
|
// Route each subscriber by its own zombie flag, mirroring the
|
|
131
131
|
// post-recompute height-adjust path. Inserting into the running `heap`
|
|
@@ -52,7 +52,9 @@ import { GlobalQueue, activeTransition, globalQueue, clock, insertSubs, schedule
|
|
|
52
52
|
// brand, and erasing it makes the write invisible and routes follow-up
|
|
53
53
|
// writes off the optimistic path into permanent commits (#2898).
|
|
54
54
|
e.Ee = n === undefined ? OVERRIDE_UNDEFINED : n;
|
|
55
|
-
|
|
55
|
+
// syncCompanions only pokes _pendingSignal/_latestValueComputed — with
|
|
56
|
+
// neither companion present the call is a guaranteed no-op.
|
|
57
|
+
(e.be !== undefined || e.ge !== undefined) && GlobalQueue.Ie !== null && GlobalQueue.Ie(e, n);
|
|
56
58
|
e.ce = clock;
|
|
57
59
|
insertSubs(e, true);
|
|
58
60
|
schedule();
|
|
@@ -216,13 +218,13 @@ function trackOptimisticStore(e) {
|
|
|
216
218
|
if (GlobalQueue.Pt !== null) return;
|
|
217
219
|
GlobalQueue.Pt = optimisticWrite;
|
|
218
220
|
GlobalQueue.En = resolveOptimisticNodes;
|
|
219
|
-
GlobalQueue.
|
|
220
|
-
GlobalQueue.
|
|
221
|
+
GlobalQueue.dn = transitionBlocked;
|
|
222
|
+
GlobalQueue.Tn = cleanupCompletedLanes;
|
|
221
223
|
GlobalQueue.In = runLaneEffects;
|
|
222
224
|
GlobalQueue.Ct = gatedRead;
|
|
223
225
|
GlobalQueue.At = laneSuspends;
|
|
224
226
|
GlobalQueue.Ot = laneReadsCommitted;
|
|
225
|
-
GlobalQueue.
|
|
227
|
+
GlobalQueue.Ye = recomputeLane;
|
|
226
228
|
GlobalQueue.Ke = laneAsyncPending;
|
|
227
229
|
GlobalQueue.Me = laneAsyncSettled;
|
|
228
230
|
GlobalQueue.Nn = trackOptimisticStore;
|