@solidjs/signals 2.0.0-rc.0 → 2.0.0-rc.1
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 +2622 -2438
- package/dist/node.cjs +3770 -3571
- package/dist/prod/core/async.js +186 -132
- package/dist/prod/core/core.js +118 -107
- package/dist/prod/core/effect.js +13 -13
- package/dist/prod/core/external.js +1 -1
- package/dist/prod/core/graph.js +8 -8
- package/dist/prod/core/heap.js +24 -24
- package/dist/prod/core/lanes.js +3 -3
- package/dist/prod/core/optimistic.js +38 -21
- package/dist/prod/core/owner.js +21 -21
- package/dist/prod/core/scheduler.js +55 -47
- package/dist/prod/core/verdict.js +40 -40
- package/dist/prod/index.js +7 -7
- package/dist/prod/map.js +81 -79
- package/dist/prod/signals.js +20 -1
- package/dist/prod/store/index.js +36 -0
- package/dist/prod/store/next/optimistic.js +377 -0
- package/dist/prod/store/next/projection.js +172 -0
- package/dist/prod/store/next/reconcile.js +327 -0
- package/dist/prod/store/next/store.js +1232 -0
- package/dist/prod/store/next/target.js +20 -0
- package/dist/prod/store/store.js +123 -879
- package/dist/prod/store/utils.js +59 -186
- package/dist/types/core/core.d.ts +8 -0
- package/dist/types/core/dev.d.ts +1 -1
- package/dist/types/core/scheduler.d.ts +4 -2
- 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 +24 -0
- package/dist/types/store/next/reconcile.d.ts +3 -0
- package/dist/types/store/next/store.d.ts +71 -0
- package/dist/types/store/next/target.d.ts +99 -0
- package/dist/types/store/store.d.ts +26 -101
- package/dist/types/store/utils.d.ts +0 -40
- package/dist/types-cjs/core/core.d.cts +8 -0
- package/dist/types-cjs/core/dev.d.cts +1 -1
- package/dist/types-cjs/core/scheduler.d.cts +4 -2
- 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 +24 -0
- package/dist/types-cjs/store/next/reconcile.d.cts +3 -0
- package/dist/types-cjs/store/next/store.d.cts +71 -0
- package/dist/types-cjs/store/next/target.d.cts +99 -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
package/dist/prod/core/core.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { handleAsync, clearStatus, parkLoadingWindow, notifyStatus, settleErroredDependents } from "./async.js";
|
|
2
2
|
|
|
3
|
-
import { EFFECT_TRACKED, REACTIVE_OPTIMISTIC_DIRTY, NOT_PENDING, STATUS_UNINITIALIZED, STATUS_ERROR, REACTIVE_REASK, REACTIVE_RECOMPUTING_DEPS, CONFIG_SYNC, STATUS_PENDING, REACTIVE_NONE, REACTIVE_SNAPSHOT_STALE, unwrapOverride, OVERRIDE_UNDEFINED, REACTIVE_LAZY, REACTIVE_DISPOSED, CONFIG_AUTO_DISPOSE, REACTIVE_CHECK, REACTIVE_DIRTY, REACTIVE_IN_HEAP, REACTIVE_IN_HEAP_HEIGHT, defaultContext, CONFIG_IN_SNAPSHOT_SCOPE, CONFIG_TRANSPARENT, CONFIG_OWNED_WRITE, CONFIG_NO_SNAPSHOT, $REFRESH, REACTIVE_MANUAL_WRITE, NO_SNAPSHOT, STORE_SNAPSHOT_PROPS, EFFECT_USER } from "./constants.js";
|
|
3
|
+
import { EFFECT_TRACKED, REACTIVE_OPTIMISTIC_DIRTY, NOT_PENDING, STATUS_UNINITIALIZED, STATUS_ERROR, REACTIVE_REASK, REACTIVE_RECOMPUTING_DEPS, CONFIG_SYNC, STATUS_PENDING, REACTIVE_NONE, REACTIVE_SNAPSHOT_STALE, unwrapOverride, OVERRIDE_UNDEFINED, REACTIVE_LAZY, REACTIVE_DISPOSED, CONFIG_CHILDREN_FORBIDDEN, CONFIG_AUTO_DISPOSE, REACTIVE_CHECK, REACTIVE_DIRTY, REACTIVE_IN_HEAP, REACTIVE_IN_HEAP_HEIGHT, defaultContext, CONFIG_IN_SNAPSHOT_SCOPE, CONFIG_TRANSPARENT, CONFIG_OWNED_WRITE, CONFIG_NO_SNAPSHOT, $REFRESH, REACTIVE_MANUAL_WRITE, NO_SNAPSHOT, STORE_SNAPSHOT_PROPS, EFFECT_USER } from "./constants.js";
|
|
4
4
|
|
|
5
5
|
import { NotReadyError } from "./error.js";
|
|
6
6
|
|
|
@@ -49,7 +49,7 @@ let snapshotSources = null;
|
|
|
49
49
|
function ownerInSnapshotScope(e) {
|
|
50
50
|
while (e) {
|
|
51
51
|
if (e.ve) return true;
|
|
52
|
-
e = e.
|
|
52
|
+
e = e.Fe;
|
|
53
53
|
}
|
|
54
54
|
return false;
|
|
55
55
|
}
|
|
@@ -70,7 +70,7 @@ function releaseSnapshotScope(e) {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
function releaseSubtree(e) {
|
|
73
|
-
let t = e.
|
|
73
|
+
let t = e.ke;
|
|
74
74
|
while (t) {
|
|
75
75
|
if (t.ve) {
|
|
76
76
|
t = t.He;
|
|
@@ -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.Ve > e.
|
|
85
|
+
if (dirtyQueue.Ve > e.Le) dirtyQueue.Ve = e.Le;
|
|
86
86
|
insertIntoHeap(e, dirtyQueue);
|
|
87
87
|
}
|
|
88
88
|
}
|
|
@@ -94,7 +94,7 @@ function releaseSubtree(e) {
|
|
|
94
94
|
function clearSnapshots() {
|
|
95
95
|
if (snapshotSources) {
|
|
96
96
|
for (const e of snapshotSources) {
|
|
97
|
-
delete e.
|
|
97
|
+
delete e.xe;
|
|
98
98
|
// StoreNode targets share one pre-initialized hidden class (see
|
|
99
99
|
// createStoreProxy) — assign undefined instead of deleting, and only
|
|
100
100
|
// when present so signal-node sources don't grow the field.
|
|
@@ -112,25 +112,25 @@ function recompute(e, t = false) {
|
|
|
112
112
|
deleteFromHeap(e, queueFor(e));
|
|
113
113
|
e.Te = null;
|
|
114
114
|
// Tracked effects run after finalizePureQueue, so dispose immediately instead of deferring
|
|
115
|
-
if (e.Ne || n === EFFECT_TRACKED) disposeChildren(e); else if (e.
|
|
115
|
+
if (e.Ne || n === EFFECT_TRACKED) disposeChildren(e); else if (e.ke !== null || e.he !== null) {
|
|
116
116
|
markDisposal(e);
|
|
117
|
-
e.Qe = e.
|
|
118
|
-
e.We = e.
|
|
119
|
-
e.
|
|
120
|
-
e.
|
|
117
|
+
e.Qe = e.he;
|
|
118
|
+
e.We = e.ke;
|
|
119
|
+
e.he = null;
|
|
120
|
+
e.ke = null;
|
|
121
121
|
e.qe = 0;
|
|
122
122
|
} else ;
|
|
123
123
|
}
|
|
124
124
|
let i = !!(e.se & REACTIVE_OPTIMISTIC_DIRTY);
|
|
125
|
-
const l = e.
|
|
125
|
+
const l = e.De !== undefined && e.De !== NOT_PENDING;
|
|
126
126
|
const u = !!(e.S & STATUS_UNINITIALIZED);
|
|
127
127
|
// Outgoing error, captured before the compute clears status: if this run
|
|
128
128
|
// recovers to an unchanged value, dependents still holding this object must
|
|
129
129
|
// be swept (settleErroredDependents, #2949).
|
|
130
|
-
const
|
|
130
|
+
const s = e.S & STATUS_ERROR ? e._ : undefined;
|
|
131
131
|
// Re-ask classification lives in the verdict module; capture the flag before
|
|
132
132
|
// the recompute wipes _flags below.
|
|
133
|
-
const
|
|
133
|
+
const o = (e.se & REACTIVE_REASK) !== 0;
|
|
134
134
|
// Captured before the compute clears it on a sync landing: if that landing
|
|
135
135
|
// is transition-held below, the window must stay open until the hold
|
|
136
136
|
// commits (commitPendingNode) — a closed window plus a held value reads as
|
|
@@ -142,8 +142,8 @@ function recompute(e, t = false) {
|
|
|
142
142
|
e.Ze++;
|
|
143
143
|
e.se = REACTIVE_RECOMPUTING_DEPS;
|
|
144
144
|
e.de = clock;
|
|
145
|
-
let c = e.
|
|
146
|
-
let _ = e.
|
|
145
|
+
let c = e._e === NOT_PENDING ? e.be : e._e;
|
|
146
|
+
let _ = e.Le;
|
|
147
147
|
let f = tracking;
|
|
148
148
|
let E = currentOptimisticLane;
|
|
149
149
|
tracking = true;
|
|
@@ -153,7 +153,7 @@ function recompute(e, t = false) {
|
|
|
153
153
|
// computed) inside latest(fn) came out permanently dependency-less (#2926).
|
|
154
154
|
// latestRead() already suspends the flag for its pull-recomputes; this
|
|
155
155
|
// covers creation-time computes and flushes that run inside the window.
|
|
156
|
-
const
|
|
156
|
+
const N = latestReadActive;
|
|
157
157
|
latestReadActive = false;
|
|
158
158
|
// Lane posture lives with the engine: OPTIMISTIC_DIRTY is only ever set by
|
|
159
159
|
// engine-driven paths, and _optimisticNodes is only pushed by
|
|
@@ -161,6 +161,10 @@ function recompute(e, t = false) {
|
|
|
161
161
|
if (i) {
|
|
162
162
|
const t = GlobalQueue.je(e, true);
|
|
163
163
|
if (t) currentOptimisticLane = t;
|
|
164
|
+
// `false` = wake-only lane demotion: recompute plain so a mid-tick
|
|
165
|
+
// latest()/isPending() pull stages instead of direct-committing (#3009).
|
|
166
|
+
// The predicate lives with the engine (recomputeLane).
|
|
167
|
+
else if (t === false) i = false;
|
|
164
168
|
} else if (activeTransition && !t && activeTransition.Me.length) {
|
|
165
169
|
// Lane adoption: parent-deeper-than-owned-child can run before its OPT-dirty
|
|
166
170
|
// child propagates. Walk deps once and inherit the OPT lane so this node
|
|
@@ -171,9 +175,9 @@ function recompute(e, t = false) {
|
|
|
171
175
|
currentOptimisticLane = t;
|
|
172
176
|
}
|
|
173
177
|
}
|
|
174
|
-
const
|
|
175
|
-
const
|
|
176
|
-
if (
|
|
178
|
+
const T = n && n !== EFFECT_USER;
|
|
179
|
+
const I = stale;
|
|
180
|
+
if (T) stale = true;
|
|
177
181
|
try {
|
|
178
182
|
if (!false && e.T & CONFIG_SYNC) {
|
|
179
183
|
c = e.ce(c);
|
|
@@ -202,9 +206,9 @@ function recompute(e, t = false) {
|
|
|
202
206
|
// On a status-free node clearStatus is a guaranteed no-op: every branch
|
|
203
207
|
// in its body is gated on one of these fields, and with _statusFlags === 0
|
|
204
208
|
// the flags write (create or not) stores the 0 already there.
|
|
205
|
-
if (e.S !== 0 || e.i !== undefined || e._ || e.
|
|
209
|
+
if (e.S !== 0 || e.i !== undefined || e._ || e.pe || e.le || e.oe !== undefined || e.Oe !== undefined || e.ge !== undefined || e.u !== null) clearStatus(e, t);
|
|
206
210
|
// _optimisticLane is only ever assigned by engine paths.
|
|
207
|
-
if (e.Ke) GlobalQueue.
|
|
211
|
+
if (e.Ke) GlobalQueue.Be(e);
|
|
208
212
|
} catch (t) {
|
|
209
213
|
const n = t instanceof NotReadyError;
|
|
210
214
|
if (n && e.Ee) {
|
|
@@ -219,28 +223,28 @@ function recompute(e, t = false) {
|
|
|
219
223
|
} else {
|
|
220
224
|
// Track pending async in the lane (not the lane's source — it creates the lane
|
|
221
225
|
// but doesn't belong to it). Set lane BEFORE notifyStatus for downstream propagation.
|
|
222
|
-
if (n && currentOptimisticLane) GlobalQueue
|
|
226
|
+
if (n && currentOptimisticLane) GlobalQueue.ze(e);
|
|
223
227
|
let i = false;
|
|
224
228
|
if (n) {
|
|
225
|
-
e.
|
|
226
|
-
if (GlobalQueue
|
|
229
|
+
e.le = true;
|
|
230
|
+
if (GlobalQueue.$e !== null) i = GlobalQueue.$e(e, o);
|
|
227
231
|
}
|
|
228
232
|
notifyStatus(e, n ? STATUS_PENDING : STATUS_ERROR, t, undefined, n ? e.Ke : undefined);
|
|
229
233
|
if (i) GlobalQueue.k(e);
|
|
230
234
|
}
|
|
231
235
|
} finally {
|
|
232
236
|
tracking = f;
|
|
233
|
-
latestReadActive =
|
|
234
|
-
if (
|
|
237
|
+
latestReadActive = N;
|
|
238
|
+
if (T) stale = I;
|
|
235
239
|
e.se = REACTIVE_NONE | (t ? e.se & REACTIVE_SNAPSHOT_STALE : 0);
|
|
236
240
|
context = r;
|
|
237
241
|
}
|
|
238
242
|
if (!e._) {
|
|
239
243
|
trimStaleDeps(e);
|
|
240
|
-
const
|
|
244
|
+
const o = l ? unwrapOverride(e.De) : e._e === NOT_PENDING ? e.be : e._e;
|
|
241
245
|
let r = false;
|
|
242
246
|
try {
|
|
243
|
-
r = !n && u || !e.
|
|
247
|
+
r = !n && u || !e.Ue || !e.Ue(o, c);
|
|
244
248
|
} catch (t) {
|
|
245
249
|
// A throwing user comparator is an error of this node's computation.
|
|
246
250
|
// Route it through the same status path as a compute-phase throw so
|
|
@@ -260,24 +264,24 @@ function recompute(e, t = false) {
|
|
|
260
264
|
if (!t) e.C.enqueue(n, e.Xe ??= GlobalQueue.et.bind(null, e));
|
|
261
265
|
}
|
|
262
266
|
if (e._) ; else if (r) {
|
|
263
|
-
const u = l ? e.
|
|
267
|
+
const u = l ? e.De : undefined;
|
|
264
268
|
if (t ||
|
|
265
269
|
// Plain sync flush (no transition on either side) commits effect
|
|
266
270
|
// values directly — the pending round-trip (queuePendingNode +
|
|
267
271
|
// commitPendingNodes) exists to sequence transition reveals, and
|
|
268
272
|
// paying it per effect on the plain path is pure overhead.
|
|
269
273
|
n && (activeTransition !== e.Ne || activeTransition === null) || i) {
|
|
270
|
-
e.
|
|
274
|
+
e.be = c;
|
|
271
275
|
// Lane-propagated correction: upstream data is fresh, correct the
|
|
272
276
|
// override unconditionally. The direct _value commit is the lane's
|
|
273
277
|
// own reveal schedule; drop any superseded older hold so its queued
|
|
274
278
|
// commit can't clobber the fresh value.
|
|
275
279
|
if (l && i) {
|
|
276
|
-
e.
|
|
277
|
-
e.
|
|
280
|
+
e.De = c === undefined ? OVERRIDE_UNDEFINED : c;
|
|
281
|
+
e._e = NOT_PENDING;
|
|
278
282
|
}
|
|
279
283
|
} else {
|
|
280
|
-
e.
|
|
284
|
+
e._e = c;
|
|
281
285
|
// A window landing that gets held re-opens the window until the hold
|
|
282
286
|
// commits — the verdict's held-value branch is window-gated (#2990).
|
|
283
287
|
if (a) e.Ee = true;
|
|
@@ -290,17 +294,17 @@ function recompute(e, t = false) {
|
|
|
290
294
|
}
|
|
291
295
|
// insertSubs only walks _subs (no scheduling of its own), so a
|
|
292
296
|
// subscriber-less node has nothing to notify.
|
|
293
|
-
if (e.o !== null && (!l || i || e.
|
|
297
|
+
if (e.o !== null && (!l || i || e.De !== u)) insertSubs(e, i || l);
|
|
294
298
|
} else if (l) {
|
|
295
299
|
// Unchanged value (equals the override) recomputed while the override
|
|
296
300
|
// is active: _value may still be stale, so hold the authoritative value
|
|
297
301
|
// for commit on its own transition's schedule — invisibly (A17/A18).
|
|
298
|
-
if (e.
|
|
299
|
-
e.
|
|
302
|
+
if (e._e === NOT_PENDING) queuePendingNode(e);
|
|
303
|
+
e._e = c;
|
|
300
304
|
if (a) e.Ee = true;
|
|
301
305
|
// see the held branch above (#2990)
|
|
302
|
-
} else if (e.
|
|
303
|
-
for (let t = e.o; t !== null; t = t.
|
|
306
|
+
} else if (e.Le != _) {
|
|
307
|
+
for (let t = e.o; t !== null; t = t.ue) {
|
|
304
308
|
insertIntoHeapHeight(t.fe, queueFor(t.fe));
|
|
305
309
|
}
|
|
306
310
|
}
|
|
@@ -309,16 +313,16 @@ function recompute(e, t = false) {
|
|
|
309
313
|
// in an errored run and may sit on stale commits (#2949). Changed-value
|
|
310
314
|
// recoveries ride insertSubs above; a comparator throw re-errored the node
|
|
311
315
|
// (el._error re-set), so this only runs on a genuinely clean recovery.
|
|
312
|
-
if (
|
|
316
|
+
if (s !== undefined && !r && !e._) settleErroredDependents(e, s);
|
|
313
317
|
}
|
|
314
318
|
currentOptimisticLane = E;
|
|
315
|
-
const
|
|
319
|
+
const d = e._e !== NOT_PENDING || e.We !== null || e.Qe !== null || (e.S & (STATUS_PENDING | STATUS_UNINITIALIZED)) !== 0;
|
|
316
320
|
// Override-covered holds (hasOverride) always queue: their commit belongs
|
|
317
321
|
// to their own transition's schedule (A18 re-rule) and is unobservable
|
|
318
322
|
// under the override (A17). Revert no longer commits anything, so an
|
|
319
323
|
// unqueued covered hold would leak (INV-7) once the revert clears
|
|
320
324
|
// _transition.
|
|
321
|
-
|
|
325
|
+
d && (!t || e.S & STATUS_PENDING) && (!e.Ne || l) && queuePendingNode(e);
|
|
322
326
|
e.Ne && n && activeTransition !== e.Ne && runInTransition(e.Ne, () => recompute(e));
|
|
323
327
|
}
|
|
324
328
|
|
|
@@ -350,37 +354,37 @@ function computed(e, t) {
|
|
|
350
354
|
const l = {
|
|
351
355
|
id: inheritId(t, n, context),
|
|
352
356
|
T: (n ? CONFIG_TRANSPARENT : 0) | (t?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (!context || t?.lazy ? CONFIG_AUTO_DISPOSE : 0) | (t?.sync ? CONFIG_SYNC : 0) | (t?.V ? CONFIG_NO_SNAPSHOT : 0) | (snapshotCaptureActive && ownerInSnapshotScope(context) ? CONFIG_IN_SNAPSHOT_SCOPE : 0),
|
|
353
|
-
|
|
357
|
+
Ue: t?.equals != null ? t.equals : isEqual,
|
|
354
358
|
ut: t?.unobserved,
|
|
355
|
-
|
|
359
|
+
he: null,
|
|
356
360
|
C: context?.C ?? globalQueue,
|
|
357
361
|
we: context?.we ?? defaultContext,
|
|
358
362
|
qe: 0,
|
|
359
363
|
ce: e,
|
|
360
|
-
|
|
361
|
-
|
|
364
|
+
be: i ? t.loadingValue : undefined,
|
|
365
|
+
Le: 0,
|
|
362
366
|
u: null,
|
|
363
|
-
|
|
364
|
-
|
|
367
|
+
st: undefined,
|
|
368
|
+
ot: null,
|
|
365
369
|
tt: null,
|
|
366
370
|
Ye: null,
|
|
367
371
|
Ze: 0,
|
|
368
372
|
o: null,
|
|
369
373
|
rt: null,
|
|
370
|
-
|
|
374
|
+
Fe: context,
|
|
371
375
|
He: null,
|
|
372
376
|
ct: null,
|
|
373
|
-
|
|
377
|
+
ke: null,
|
|
374
378
|
se: t?.lazy ? REACTIVE_LAZY : REACTIVE_NONE,
|
|
375
379
|
// A loadingValue node is born committed: commit #0 is already in _value.
|
|
376
380
|
S: i ? 0 : STATUS_UNINITIALIZED,
|
|
377
381
|
de: clock,
|
|
378
|
-
|
|
382
|
+
_e: NOT_PENDING,
|
|
379
383
|
Qe: null,
|
|
380
384
|
We: null,
|
|
381
385
|
Te: null,
|
|
382
386
|
Ne: null,
|
|
383
|
-
|
|
387
|
+
pe: false,
|
|
384
388
|
Ee: i
|
|
385
389
|
};
|
|
386
390
|
setupComputedNode(l, t);
|
|
@@ -393,51 +397,51 @@ function computed(e, t) {
|
|
|
393
397
|
* mode (recompute is called explicitly by `effect()`), so we hardcode the lazy bits and skip
|
|
394
398
|
* the auto-dispose CONFIG bit (effect() previously cleared it post-construction).
|
|
395
399
|
*/ function createEffectNode(e, t, n, i, l, u) {
|
|
396
|
-
const
|
|
397
|
-
const
|
|
398
|
-
id: inheritId(u,
|
|
399
|
-
T: (
|
|
400
|
-
|
|
400
|
+
const s = u?.transparent ?? false;
|
|
401
|
+
const o = {
|
|
402
|
+
id: inheritId(u, s, context),
|
|
403
|
+
T: (s ? CONFIG_TRANSPARENT : 0) | (u?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (u?.sync ? CONFIG_SYNC : 0) | (snapshotCaptureActive && ownerInSnapshotScope(context) ? CONFIG_IN_SNAPSHOT_SCOPE : 0),
|
|
404
|
+
Ue: false,
|
|
401
405
|
ut: u?.unobserved,
|
|
402
|
-
|
|
406
|
+
he: null,
|
|
403
407
|
C: context?.C ?? globalQueue,
|
|
404
408
|
we: context?.we ?? defaultContext,
|
|
405
409
|
qe: 0,
|
|
406
410
|
ce: e,
|
|
407
|
-
|
|
408
|
-
|
|
411
|
+
be: undefined,
|
|
412
|
+
Le: 0,
|
|
409
413
|
u: null,
|
|
410
|
-
|
|
411
|
-
|
|
414
|
+
st: undefined,
|
|
415
|
+
ot: null,
|
|
412
416
|
tt: null,
|
|
413
417
|
Ye: null,
|
|
414
418
|
Ze: 0,
|
|
415
419
|
o: null,
|
|
416
420
|
rt: null,
|
|
417
|
-
|
|
421
|
+
Fe: context,
|
|
418
422
|
He: null,
|
|
419
423
|
ct: null,
|
|
420
|
-
|
|
424
|
+
ke: null,
|
|
421
425
|
se: REACTIVE_LAZY,
|
|
422
426
|
S: STATUS_UNINITIALIZED,
|
|
423
427
|
de: clock,
|
|
424
|
-
|
|
428
|
+
_e: NOT_PENDING,
|
|
425
429
|
Qe: null,
|
|
426
430
|
We: null,
|
|
427
431
|
Te: null,
|
|
428
432
|
Ne: null,
|
|
429
|
-
|
|
433
|
+
pe: false,
|
|
430
434
|
Ee: false,
|
|
431
435
|
Je: false,
|
|
432
436
|
_t: undefined,
|
|
433
437
|
ft: t,
|
|
434
438
|
Et: n,
|
|
435
|
-
|
|
439
|
+
Nt: undefined,
|
|
436
440
|
Re: i,
|
|
437
441
|
i: l
|
|
438
442
|
};
|
|
439
|
-
setupComputedNode(
|
|
440
|
-
return
|
|
443
|
+
setupComputedNode(o, lazyOptions);
|
|
444
|
+
return o;
|
|
441
445
|
}
|
|
442
446
|
|
|
443
447
|
const lazyOptions = {
|
|
@@ -445,24 +449,24 @@ const lazyOptions = {
|
|
|
445
449
|
};
|
|
446
450
|
|
|
447
451
|
function setupComputedNode(e, t) {
|
|
448
|
-
e.
|
|
449
|
-
const n = context?.
|
|
452
|
+
e.ot = e;
|
|
453
|
+
const n = context?.Tt ? context.It : context;
|
|
450
454
|
if (context) {
|
|
451
|
-
const t = context.
|
|
455
|
+
const t = context.ke;
|
|
452
456
|
if (t === null) {
|
|
453
|
-
context.
|
|
457
|
+
context.ke = e;
|
|
454
458
|
} else {
|
|
455
459
|
e.He = t;
|
|
456
460
|
t.ct = e;
|
|
457
|
-
context.
|
|
461
|
+
context.ke = e;
|
|
458
462
|
}
|
|
459
463
|
}
|
|
460
|
-
if (n) e.
|
|
461
|
-
if (GlobalQueue.
|
|
464
|
+
if (n) e.Le = n.Le + 1;
|
|
465
|
+
if (GlobalQueue.dt !== null) GlobalQueue.dt(e);
|
|
462
466
|
!t?.lazy && recompute(e, true);
|
|
463
467
|
if (snapshotCaptureActive && !t?.lazy) {
|
|
464
468
|
if (!(e.S & STATUS_PENDING) && !(e.T & CONFIG_NO_SNAPSHOT)) {
|
|
465
|
-
e.
|
|
469
|
+
e.xe = e.be === undefined ? NO_SNAPSHOT : e.be;
|
|
466
470
|
snapshotSources.add(e);
|
|
467
471
|
}
|
|
468
472
|
}
|
|
@@ -470,20 +474,20 @@ function setupComputedNode(e, t) {
|
|
|
470
474
|
|
|
471
475
|
function signal(e, t, n = null) {
|
|
472
476
|
const i = {
|
|
473
|
-
|
|
477
|
+
Ue: t?.equals != null ? t.equals : isEqual,
|
|
474
478
|
T: (t?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (t?.V ? CONFIG_NO_SNAPSHOT : 0),
|
|
475
479
|
ut: t?.unobserved,
|
|
476
|
-
|
|
480
|
+
be: e,
|
|
477
481
|
o: null,
|
|
478
482
|
rt: null,
|
|
479
483
|
de: clock,
|
|
480
484
|
lt: n,
|
|
481
485
|
ae: n?.u || null,
|
|
482
|
-
|
|
486
|
+
_e: NOT_PENDING
|
|
483
487
|
};
|
|
484
488
|
n && (n.u = i);
|
|
485
489
|
if (snapshotCaptureActive && !(i.T & CONFIG_NO_SNAPSHOT) && !((n?.S ?? 0) & STATUS_PENDING)) {
|
|
486
|
-
i.
|
|
490
|
+
i.xe = e === undefined ? NO_SNAPSHOT : e;
|
|
487
491
|
snapshotSources.add(i);
|
|
488
492
|
}
|
|
489
493
|
return i;
|
|
@@ -491,13 +495,13 @@ function signal(e, t, n = null) {
|
|
|
491
495
|
|
|
492
496
|
function optimisticSignal(e, t) {
|
|
493
497
|
const n = signal(e, t);
|
|
494
|
-
n.
|
|
498
|
+
n.De = NOT_PENDING;
|
|
495
499
|
return n;
|
|
496
500
|
}
|
|
497
501
|
|
|
498
502
|
function optimisticComputed(e, t) {
|
|
499
503
|
const n = computed(e, t);
|
|
500
|
-
n.
|
|
504
|
+
n.De = NOT_PENDING;
|
|
501
505
|
return n;
|
|
502
506
|
}
|
|
503
507
|
|
|
@@ -567,11 +571,15 @@ function isEqual(e, t) {
|
|
|
567
571
|
* snapshot / transition / lane / dev-strictRead state all take the full
|
|
568
572
|
* resolution. Anything slow returns READ_SLOW; the caller then calls read().
|
|
569
573
|
*/ function readNodeFast(e) {
|
|
570
|
-
if (latestReadActive || pendingCheckActive || e.ce || e.lt || e.
|
|
574
|
+
if (latestReadActive || pendingCheckActive || e.ce || e.lt || e.De !== undefined || e.xe !== undefined || activeTransition !== null || currentOptimisticLane !== null || snapshotCaptureActive || false) return READ_SLOW;
|
|
571
575
|
let t = context;
|
|
572
|
-
if (t?.
|
|
576
|
+
if (t?.Tt) t = t.It;
|
|
573
577
|
if (t && tracking) link(e, t);
|
|
574
|
-
|
|
578
|
+
// Children-forbidden readers (createTrackedEffect / onSettled callbacks) get
|
|
579
|
+
// committed visibility: like the effect half of createEffect and event
|
|
580
|
+
// handlers, effect-phase code never observes its own unsettled write — the
|
|
581
|
+
// write lands in the same flush's continuation (#3006).
|
|
582
|
+
return !t || e._e === NOT_PENDING || t.T & CONFIG_CHILDREN_FORBIDDEN ? e.be : e._e;
|
|
575
583
|
}
|
|
576
584
|
|
|
577
585
|
function read(e) {
|
|
@@ -581,7 +589,7 @@ function read(e) {
|
|
|
581
589
|
// than the original node (which stays "pending" while held in a transition).
|
|
582
590
|
if (latestReadActive) return GlobalQueue.At(e);
|
|
583
591
|
let t = context;
|
|
584
|
-
if (t?.
|
|
592
|
+
if (t?.Tt) t = t.It;
|
|
585
593
|
const n = e;
|
|
586
594
|
const i = e.lt;
|
|
587
595
|
const l = i || e;
|
|
@@ -593,23 +601,24 @@ function read(e) {
|
|
|
593
601
|
} else if (typeof n.ce === "function") {
|
|
594
602
|
prepareComputed(e, false);
|
|
595
603
|
}
|
|
596
|
-
if (!n.ce && l === e && e.
|
|
604
|
+
if (!n.ce && l === e && e.De === undefined && e.xe === undefined && activeTransition === null && currentOptimisticLane === null && !snapshotCaptureActive && true) {
|
|
597
605
|
if (t && tracking) link(e, t);
|
|
598
|
-
|
|
606
|
+
// Committed visibility for children-forbidden readers — see readNodeFast.
|
|
607
|
+
return !t || e._e === NOT_PENDING || t.T & CONFIG_CHILDREN_FORBIDDEN ? e.be : e._e;
|
|
599
608
|
}
|
|
600
609
|
if (t && tracking) {
|
|
601
610
|
link(e, t, pendingCheckActive);
|
|
602
611
|
if (l.ce) {
|
|
603
612
|
const n = queueFor(e);
|
|
604
|
-
if (l.
|
|
613
|
+
if (l.Le >= n.Ve) {
|
|
605
614
|
markNode(t);
|
|
606
615
|
markHeap(n);
|
|
607
616
|
updateIfNecessary(l);
|
|
608
617
|
}
|
|
609
|
-
const i = l.
|
|
618
|
+
const i = l.Le;
|
|
610
619
|
// parent check is shallow, might need to be recursive
|
|
611
|
-
if (i >= t.
|
|
612
|
-
t.
|
|
620
|
+
if (i >= t.Le && e.Fe !== t) {
|
|
621
|
+
t.Le = i + 1;
|
|
613
622
|
}
|
|
614
623
|
}
|
|
615
624
|
}
|
|
@@ -644,17 +653,17 @@ function read(e) {
|
|
|
644
653
|
} else throw l._;
|
|
645
654
|
}
|
|
646
655
|
if (snapshotCaptureActive && t && t.T & CONFIG_IN_SNAPSHOT_SCOPE) {
|
|
647
|
-
const n = e.
|
|
656
|
+
const n = e.xe;
|
|
648
657
|
if (n !== undefined) {
|
|
649
658
|
const i = n === NO_SNAPSHOT ? undefined : n;
|
|
650
|
-
const l = e.
|
|
659
|
+
const l = e._e !== NOT_PENDING ? e._e : e.be;
|
|
651
660
|
if (l !== i) t.se |= REACTIVE_SNAPSHOT_STALE;
|
|
652
661
|
return i;
|
|
653
662
|
}
|
|
654
663
|
}
|
|
655
|
-
if (e.
|
|
664
|
+
if (e.De !== undefined && e.De !== NOT_PENDING) {
|
|
656
665
|
// A17: the override IS the value for every reader.
|
|
657
|
-
return unwrapOverride(e.
|
|
666
|
+
return unwrapOverride(e.De);
|
|
658
667
|
}
|
|
659
668
|
// Entanglement gate: a reader recomputing under an optimistic lane that reads
|
|
660
669
|
// a pending mid-transition write sees the committed value. Projection-store
|
|
@@ -664,16 +673,18 @@ function read(e) {
|
|
|
664
673
|
// so it re-runs with the new committed view. (Gate details live with the
|
|
665
674
|
// engine — a non-null lane implies it is installed.)
|
|
666
675
|
if (currentOptimisticLane !== null && activeTransition !== null && t !== null && GlobalQueue.Rt(e, l, t)) {
|
|
667
|
-
return e.
|
|
676
|
+
return e.be;
|
|
668
677
|
}
|
|
669
678
|
// In optimistic lane context, return _value for optimistic/lane-assigned signals
|
|
670
679
|
// and for regular signals in stale mode (render effects). Non-stale readers (user
|
|
671
680
|
// effects) see _pendingValue so that latest() and direct reads stay consistent.
|
|
672
|
-
// (The lane-context clause lives with the engine.)
|
|
673
|
-
|
|
681
|
+
// (The lane-context clause lives with the engine.) Children-forbidden readers
|
|
682
|
+
// (createTrackedEffect / onSettled callbacks) get committed visibility — see
|
|
683
|
+
// readNodeFast (#3006).
|
|
684
|
+
const u = !t || currentOptimisticLane !== null && GlobalQueue.Dt(e, l, t) || e._e === NOT_PENDING || t.T & CONFIG_CHILDREN_FORBIDDEN || stale && e.Ne && activeTransition !== e.Ne ? e.be : e._e;
|
|
674
685
|
// Record that this isPending() probe observed the fresh pending value, so
|
|
675
686
|
// the probe doesn't pair "pending" with the new value (#2831).
|
|
676
|
-
if (pendingCheckActive) GlobalQueue.
|
|
687
|
+
if (pendingCheckActive) GlobalQueue.Pt(e, u);
|
|
677
688
|
if (!t && l === e && typeof n.ce === "function" && e.T & CONFIG_AUTO_DISPOSE && !(l.S & STATUS_PENDING) && !e.o) {
|
|
678
689
|
unobserved(e);
|
|
679
690
|
}
|
|
@@ -686,19 +697,19 @@ function setSignal(e, t) {
|
|
|
686
697
|
// optimisticComputed callers and optimistic store nodes carry an
|
|
687
698
|
// _overrideValue slot, and every module that creates one installs the
|
|
688
699
|
// engine first.
|
|
689
|
-
if (e.
|
|
690
|
-
const n = e.
|
|
700
|
+
if (e.De !== undefined && !projectionWriteActive) return GlobalQueue.Gt(e, t);
|
|
701
|
+
const n = e._e === NOT_PENDING ? e.be : e._e;
|
|
691
702
|
if (typeof t === "function") t = t(n);
|
|
692
703
|
// Uninitialized check first: the first commit has no previous value, so the
|
|
693
704
|
// user comparator must not run against `undefined` (matches recompute).
|
|
694
|
-
const i = !!(e.S & STATUS_UNINITIALIZED) || !e.
|
|
705
|
+
const i = !!(e.S & STATUS_UNINITIALIZED) || !e.Ue || !e.Ue(n, t);
|
|
695
706
|
if (!i) return t;
|
|
696
|
-
if (e.
|
|
697
|
-
e.
|
|
707
|
+
if (e._e === NOT_PENDING) queuePendingNode(e);
|
|
708
|
+
e._e = t;
|
|
698
709
|
// syncCompanions only pokes _pendingSignal/_latestValueComputed — with
|
|
699
710
|
// neither companion present the call is a guaranteed no-op (companions are
|
|
700
711
|
// only ever created, never removed, and creating one installs the hook).
|
|
701
|
-
(e.
|
|
712
|
+
(e.Oe !== undefined || e.ge !== undefined) && GlobalQueue.Pe !== null && GlobalQueue.Pe(e, t);
|
|
702
713
|
e.de = clock;
|
|
703
714
|
insertSubs(e);
|
|
704
715
|
schedule();
|
|
@@ -713,7 +724,7 @@ function setSignal(e, t) {
|
|
|
713
724
|
* cleanup point.
|
|
714
725
|
*/ function suppressComputedRecompute(e) {
|
|
715
726
|
deleteFromHeap(e, queueFor(e));
|
|
716
|
-
if (!(e.se & REACTIVE_MANUAL_WRITE) && e.
|
|
727
|
+
if (!(e.se & REACTIVE_MANUAL_WRITE) && e._e === NOT_PENDING) {
|
|
717
728
|
queuePendingNode(e);
|
|
718
729
|
schedule();
|
|
719
730
|
}
|
package/dist/prod/core/effect.js
CHANGED
|
@@ -62,12 +62,12 @@ function runEffect(t) {
|
|
|
62
62
|
// same flush must not be hijacked by a later-arriving error status.
|
|
63
63
|
if (t.S & STATUS_ERROR && t.Re === EFFECT_USER) {
|
|
64
64
|
const E = unwrapStatusError(t._);
|
|
65
|
-
t._t = t.
|
|
65
|
+
t._t = t.be;
|
|
66
66
|
t.Je = false;
|
|
67
67
|
try {
|
|
68
68
|
t.Et ? t.Et(E, () => {
|
|
69
|
-
const E = t.
|
|
70
|
-
t.
|
|
69
|
+
const E = t.Nt;
|
|
70
|
+
t.Nt = 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.Nt;
|
|
82
|
+
t.Nt = undefined;
|
|
83
83
|
try {
|
|
84
84
|
E?.();
|
|
85
|
-
const e = t.ft(t.
|
|
85
|
+
const e = t.ft(t.be, t._t);
|
|
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.Nt = e;
|
|
89
89
|
} catch (E) {
|
|
90
90
|
t._ = new StatusError(t, E);
|
|
91
91
|
t.S |= STATUS_ERROR;
|
|
@@ -94,7 +94,7 @@ function runEffect(t) {
|
|
|
94
94
|
throw E;
|
|
95
95
|
}
|
|
96
96
|
} finally {
|
|
97
|
-
t._t = t.
|
|
97
|
+
t._t = t.be;
|
|
98
98
|
t.Je = false;
|
|
99
99
|
}
|
|
100
100
|
}
|
|
@@ -114,16 +114,16 @@ GlobalQueue.et = runEffect;
|
|
|
114
114
|
} finally {}
|
|
115
115
|
};
|
|
116
116
|
const e = computed(() => {
|
|
117
|
-
const E = e.
|
|
118
|
-
e.
|
|
117
|
+
const E = e.Nt;
|
|
118
|
+
e.Nt = undefined;
|
|
119
119
|
E?.();
|
|
120
120
|
const R = staleValues(t);
|
|
121
|
-
e.
|
|
121
|
+
e.Nt = R;
|
|
122
122
|
}, {
|
|
123
123
|
...E,
|
|
124
124
|
lazy: true
|
|
125
125
|
});
|
|
126
|
-
e.
|
|
126
|
+
e.Nt = undefined;
|
|
127
127
|
e.T = e.T & ~CONFIG_AUTO_DISPOSE | CONFIG_CHILDREN_FORBIDDEN;
|
|
128
128
|
e.Je = true;
|
|
129
129
|
e.Re = EFFECT_TRACKED;
|
|
@@ -138,7 +138,7 @@ GlobalQueue.et = runEffect;
|
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
140
|
};
|
|
141
|
-
e.
|
|
141
|
+
e.ht = run;
|
|
142
142
|
e.C.enqueue(EFFECT_USER, run);
|
|
143
143
|
}
|
|
144
144
|
|
|
@@ -64,7 +64,7 @@ function externalUntrack(e) {
|
|
|
64
64
|
// removed on reset) so core's null checks stay equivalent to the old
|
|
65
65
|
// `externalSourceConfig` truthiness checks.
|
|
66
66
|
function syncExternalHooks() {
|
|
67
|
-
GlobalQueue.
|
|
67
|
+
GlobalQueue.dt = externalSourceConfig ? wireExternalSource : null;
|
|
68
68
|
GlobalQueue.St = externalSourceConfig ? externalUntrack : null;
|
|
69
69
|
}
|
|
70
70
|
|