@solidjs/signals 2.0.0-rc.5 → 2.0.0-rc.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dev.js +2467 -1322
- package/dist/node.cjs +2037 -2428
- package/dist/node.dev.cjs +13724 -0
- package/dist/prod/boundaries.js +3 -1
- package/dist/prod/core/async.js +47 -20
- package/dist/prod/core/attribution-hooks.js +3 -0
- package/dist/prod/core/constants.js +9 -1
- package/dist/prod/core/context.js +10 -16
- package/dist/prod/core/core.js +260 -188
- package/dist/prod/core/dev.js +2 -0
- package/dist/prod/core/effect.js +41 -32
- package/dist/prod/core/external.js +2 -2
- package/dist/prod/core/graph.js +35 -31
- package/dist/prod/core/heap.js +34 -40
- package/dist/prod/core/lanes.js +44 -30
- package/dist/prod/core/optimistic.js +55 -45
- package/dist/prod/core/owner.js +35 -35
- package/dist/prod/core/scheduler.js +176 -177
- package/dist/prod/core/verdict.js +53 -52
- package/dist/prod/index.js +0 -2
- package/dist/prod/map.js +104 -94
- package/dist/prod/signals.js +119 -35
- package/dist/prod/store/next/optimistic.js +217 -163
- package/dist/prod/store/next/projection.js +2 -2
- package/dist/prod/store/next/reconcile.js +140 -288
- package/dist/prod/store/next/store.js +338 -252
- package/dist/prod/store/store.js +2 -2
- package/dist/types/core/attribution-hooks.d.ts +75 -0
- package/dist/types/core/attribution.d.ts +313 -9
- package/dist/types/core/constants.d.ts +8 -0
- package/dist/types/core/core.d.ts +12 -3
- package/dist/types/core/dev.d.ts +56 -9
- package/dist/types/core/heap.d.ts +5 -3
- package/dist/types/core/invariants.d.ts +1 -1
- package/dist/types/core/lanes.d.ts +10 -0
- package/dist/types/core/scheduler.d.ts +14 -4
- package/dist/types/signals.d.ts +10 -11
- package/dist/types/store/index.d.ts +3 -6
- package/dist/types/store/next/optimistic.d.ts +4 -2
- package/dist/types/store/next/reconcile.d.ts +5 -12
- package/dist/types/store/next/store.d.ts +3 -9
- package/dist/types/store/next/target.d.ts +30 -46
- package/dist/types/store/store.d.ts +14 -9
- package/dist/types-cjs/core/attribution-hooks.d.cts +75 -0
- package/dist/types-cjs/core/attribution.d.cts +313 -9
- package/dist/types-cjs/core/constants.d.cts +8 -0
- package/dist/types-cjs/core/core.d.cts +12 -3
- package/dist/types-cjs/core/dev.d.cts +56 -9
- package/dist/types-cjs/core/heap.d.cts +5 -3
- package/dist/types-cjs/core/invariants.d.cts +1 -1
- package/dist/types-cjs/core/lanes.d.cts +10 -0
- package/dist/types-cjs/core/scheduler.d.cts +14 -4
- package/dist/types-cjs/signals.d.cts +10 -11
- package/dist/types-cjs/store/index.d.cts +3 -6
- package/dist/types-cjs/store/next/optimistic.d.cts +4 -2
- package/dist/types-cjs/store/next/reconcile.d.cts +5 -12
- package/dist/types-cjs/store/next/store.d.cts +3 -9
- package/dist/types-cjs/store/next/target.d.cts +30 -46
- package/dist/types-cjs/store/store.d.cts +14 -9
- package/package.json +3 -2
- package/dist/prod/store/next/patch-hooks.js +0 -13
- package/dist/prod/store/next/patch.js +0 -614
- package/dist/types/store/next/patch-hooks.d.ts +0 -41
- package/dist/types/store/next/patch.d.ts +0 -91
- package/dist/types-cjs/store/next/patch-hooks.d.cts +0 -41
- package/dist/types-cjs/store/next/patch.d.cts +0 -91
package/dist/prod/core/core.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { releaseFlightTeardown, handleAsync, clearStatus, parkLoadingWindow, notifyStatus,
|
|
1
|
+
import { releaseFlightTeardown, handleAsync, clearStatus, parkLoadingWindow, notifyStatus, settlePendingSource, settleErroredDependents } from "./async.js";
|
|
2
2
|
|
|
3
|
-
import { EFFECT_TRACKED, REACTIVE_OPTIMISTIC_DIRTY, CONFIG_OPTIMISTIC, NOT_PENDING, STATUS_UNINITIALIZED, STATUS_ERROR,
|
|
3
|
+
import { EFFECT_TRACKED, EFFECT_USER, REACTIVE_OPTIMISTIC_DIRTY, CONFIG_OPTIMISTIC, NOT_PENDING, STATUS_UNINITIALIZED, STATUS_ERROR, REACTIVE_REASK, REACTIVE_RECOMPUTING_DEPS, CONFIG_SYNC, CONFIG_HAS_LANE, STATUS_PENDING, REACTIVE_MISSED_WAKE, REACTIVE_NONE, REACTIVE_SNAPSHOT_STALE, unwrapOverride, CONFIG_DIRECT_COMMIT, OVERRIDE_UNDEFINED, CONFIG_AUTHORITATIVE_OBSERVED, CONFIG_HAS_COMPANIONS, REACTIVE_LAZY, REACTIVE_DISPOSED, CONFIG_AUTO_DISPOSE, CONFIG_CHILDREN_FORBIDDEN, CONFIG_FRESH_READ, CONFIG_AUTHORITATIVE_READ, CONFIG_HELD_TRUTH, REACTIVE_CHECK, REACTIVE_DIRTY, REACTIVE_IN_HEAP, REACTIVE_IN_HEAP_HEIGHT, defaultContext, CONFIG_IN_SNAPSHOT_SCOPE, CONFIG_TRANSPARENT, CONFIG_OWNED_WRITE, CONFIG_NO_SNAPSHOT, CONFIG_FW_CHILDREN, NO_SNAPSHOT, CONFIG_HAS_SNAPSHOT, REACTIVE_MANUAL_WRITE, CONFIG_SLOT_NODE, STORE_SNAPSHOT_PROPS } from "./constants.js";
|
|
4
4
|
|
|
5
5
|
import { NotReadyError } from "./error.js";
|
|
6
6
|
|
|
@@ -14,9 +14,23 @@ import "./invariants.js";
|
|
|
14
14
|
|
|
15
15
|
import { disposeChildren, markDisposal, inheritId } from "./owner.js";
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
// The heap's per-node step. A tracked effect's heap visit is its compute
|
|
18
|
+
// phase — empty, like a user effect whose compute reads nothing — and hands
|
|
19
|
+
// the callback to the user queue. Routing the wake through the heap, rather
|
|
20
|
+
// than straight into the queue at notify time, is what orders the run after
|
|
21
|
+
// the commit regardless of which phase the write came from: a write in a
|
|
22
|
+
// render-effect callback stages its value for the next pass, but a wake pushed
|
|
23
|
+
// directly into the user queue ran in the SAME pass, read the old value, and
|
|
24
|
+
// nothing re-notified it when the value landed (#3291).
|
|
25
|
+
GlobalQueue.Fe = e => {
|
|
26
|
+
if (e.ge === EFFECT_TRACKED) {
|
|
27
|
+
deleteFromHeap(e, queueFor(e));
|
|
28
|
+
e.He = true;
|
|
29
|
+
e.C.enqueue(EFFECT_USER, e.Ve);
|
|
30
|
+
} else recompute(e);
|
|
31
|
+
};
|
|
18
32
|
|
|
19
|
-
GlobalQueue.
|
|
33
|
+
GlobalQueue.ke = disposeChildren;
|
|
20
34
|
|
|
21
35
|
let tracking = false;
|
|
22
36
|
|
|
@@ -48,8 +62,8 @@ let snapshotSources = null;
|
|
|
48
62
|
|
|
49
63
|
function ownerInSnapshotScope(e) {
|
|
50
64
|
while (e) {
|
|
51
|
-
if (e.
|
|
52
|
-
e = e.
|
|
65
|
+
if (e.xe) return true;
|
|
66
|
+
e = e.Le;
|
|
53
67
|
}
|
|
54
68
|
return false;
|
|
55
69
|
}
|
|
@@ -60,20 +74,20 @@ function setSnapshotCapture(e) {
|
|
|
60
74
|
}
|
|
61
75
|
|
|
62
76
|
function markSnapshotScope(e) {
|
|
63
|
-
e.
|
|
77
|
+
e.xe = true;
|
|
64
78
|
}
|
|
65
79
|
|
|
66
80
|
function releaseSnapshotScope(e) {
|
|
67
|
-
e.
|
|
81
|
+
e.xe = false;
|
|
68
82
|
releaseSubtree(e);
|
|
69
83
|
schedule();
|
|
70
84
|
}
|
|
71
85
|
|
|
72
86
|
function releaseSubtree(e) {
|
|
73
|
-
let t = e.
|
|
87
|
+
let t = e.Qe;
|
|
74
88
|
while (t) {
|
|
75
|
-
if (t.
|
|
76
|
-
t = t.
|
|
89
|
+
if (t.xe) {
|
|
90
|
+
t = t.We;
|
|
77
91
|
continue;
|
|
78
92
|
}
|
|
79
93
|
if (t.oe) {
|
|
@@ -82,19 +96,19 @@ function releaseSubtree(e) {
|
|
|
82
96
|
if (e.ie & REACTIVE_SNAPSHOT_STALE) {
|
|
83
97
|
e.ie &= ~REACTIVE_SNAPSHOT_STALE;
|
|
84
98
|
e.ie |= REACTIVE_DIRTY;
|
|
85
|
-
if (dirtyQueue.
|
|
99
|
+
if (dirtyQueue.Me > e.qe) dirtyQueue.Me = e.qe;
|
|
86
100
|
insertIntoHeap(e, dirtyQueue);
|
|
87
101
|
}
|
|
88
102
|
}
|
|
89
103
|
releaseSubtree(t);
|
|
90
|
-
t = t.
|
|
104
|
+
t = t.We;
|
|
91
105
|
}
|
|
92
106
|
}
|
|
93
107
|
|
|
94
108
|
function clearSnapshots() {
|
|
95
109
|
if (snapshotSources) {
|
|
96
110
|
for (const e of snapshotSources) {
|
|
97
|
-
delete e.o?.
|
|
111
|
+
delete e.o?.Ye;
|
|
98
112
|
// StoreNode targets share one pre-initialized hidden class (see
|
|
99
113
|
// createStoreProxy) — assign undefined instead of deleting, and only
|
|
100
114
|
// when present so signal-node sources don't grow the field.
|
|
@@ -108,7 +122,7 @@ function clearSnapshots() {
|
|
|
108
122
|
function recompute(e, t = false) {
|
|
109
123
|
// §12d: any recompute can clean a marked subscriber — invalidate skips.
|
|
110
124
|
bumpNotifyEpoch();
|
|
111
|
-
const n = e.
|
|
125
|
+
const n = e.ge;
|
|
112
126
|
if (!t) {
|
|
113
127
|
if (e.Ae && (!n || activeTransition) && activeTransition !== e.Ae) globalQueue.initTransition(e.Ae);
|
|
114
128
|
deleteFromHeap(e, queueFor(e));
|
|
@@ -122,18 +136,18 @@ function recompute(e, t = false) {
|
|
|
122
136
|
releaseFlightTeardown(e);
|
|
123
137
|
}
|
|
124
138
|
// Tracked effects run after finalizePureQueue, so dispose immediately instead of deferring
|
|
125
|
-
if (e.Ae || n === EFFECT_TRACKED) disposeChildren(e); else if (e.
|
|
139
|
+
if (e.Ae || n === EFFECT_TRACKED) disposeChildren(e); else if (e.Qe !== null || e.Ge !== null) {
|
|
126
140
|
markDisposal(e);
|
|
127
141
|
const t = ext(e);
|
|
128
|
-
t.
|
|
129
|
-
t.
|
|
130
|
-
e.
|
|
131
|
-
e.
|
|
132
|
-
e.
|
|
142
|
+
t.Ze = e.Ge;
|
|
143
|
+
t.Ke = e.Qe;
|
|
144
|
+
e.Ge = null;
|
|
145
|
+
e.Qe = null;
|
|
146
|
+
e.je = 0;
|
|
133
147
|
} else ;
|
|
134
148
|
}
|
|
135
149
|
let i = !!(e.ie & REACTIVE_OPTIMISTIC_DIRTY);
|
|
136
|
-
const u = (e.T & CONFIG_OPTIMISTIC) !== 0 && e.o?.
|
|
150
|
+
const u = (e.T & CONFIG_OPTIMISTIC) !== 0 && e.o?.Pe !== NOT_PENDING && e.o?.Pe !== undefined;
|
|
137
151
|
const l = !!(e.S & STATUS_UNINITIALIZED);
|
|
138
152
|
// Outgoing error, captured before the compute clears status: if this run
|
|
139
153
|
// recovers to an unchanged value, dependents still holding this object must
|
|
@@ -145,7 +159,7 @@ function recompute(e, t = false) {
|
|
|
145
159
|
// settles synchronously, those dependents settle HERE — asyncWrite's
|
|
146
160
|
// settlePendingSource walk never runs for a landing that was preempted
|
|
147
161
|
// (#3181).
|
|
148
|
-
const s =
|
|
162
|
+
const s = e.o?.le?.has(e);
|
|
149
163
|
// Re-ask classification lives in the verdict module; capture the flag before
|
|
150
164
|
// the recompute wipes _flags below.
|
|
151
165
|
const a = (e.ie & REACTIVE_REASK) !== 0;
|
|
@@ -154,14 +168,14 @@ function recompute(e, t = false) {
|
|
|
154
168
|
// commits (commitPendingNode) — a closed window plus a held value reads as
|
|
155
169
|
// a pending frame to live observers of the verdict (#2990).
|
|
156
170
|
const r = e.Ne;
|
|
157
|
-
const
|
|
171
|
+
const _ = context;
|
|
158
172
|
context = e;
|
|
159
|
-
e.
|
|
160
|
-
e.
|
|
173
|
+
e.Be = null;
|
|
174
|
+
e.ze++;
|
|
161
175
|
e.ie = REACTIVE_RECOMPUTING_DEPS;
|
|
162
176
|
e.Te = clock;
|
|
163
|
-
let
|
|
164
|
-
let f = e.
|
|
177
|
+
let c = e.Re === NOT_PENDING ? e.be : e.Re;
|
|
178
|
+
let f = e.qe;
|
|
165
179
|
let I = false;
|
|
166
180
|
let E = tracking;
|
|
167
181
|
let N = currentOptimisticLane;
|
|
@@ -178,17 +192,17 @@ function recompute(e, t = false) {
|
|
|
178
192
|
// engine-driven paths, and _optimisticNodes is only pushed by
|
|
179
193
|
// _optimisticWrite, so the hook is installed whenever either gate holds.
|
|
180
194
|
if (i) {
|
|
181
|
-
const t = GlobalQueue.
|
|
195
|
+
const t = GlobalQueue.Je(e, true);
|
|
182
196
|
if (t) currentOptimisticLane = t;
|
|
183
197
|
// `false` = wake-only lane demotion: recompute plain so a mid-tick
|
|
184
198
|
// latest()/isPending() pull stages instead of direct-committing (#3009).
|
|
185
199
|
// The predicate lives with the engine (recomputeLane).
|
|
186
200
|
else if (t === false) i = false;
|
|
187
|
-
} else if (activeTransition && !t && activeTransition.
|
|
201
|
+
} else if (activeTransition && !t && activeTransition.Xe.length) {
|
|
188
202
|
// Lane adoption: parent-deeper-than-owned-child can run before its OPT-dirty
|
|
189
203
|
// child propagates. Walk deps once and inherit the OPT lane so this node
|
|
190
204
|
// recomputes under the right posture and propagates correctly.
|
|
191
|
-
const t = GlobalQueue.
|
|
205
|
+
const t = GlobalQueue.Je(e, false);
|
|
192
206
|
if (t) {
|
|
193
207
|
i = true;
|
|
194
208
|
currentOptimisticLane = t;
|
|
@@ -199,7 +213,7 @@ function recompute(e, t = false) {
|
|
|
199
213
|
if (S) stale = true;
|
|
200
214
|
try {
|
|
201
215
|
if (!false && e.T & CONFIG_SYNC) {
|
|
202
|
-
|
|
216
|
+
c = e.oe(c);
|
|
203
217
|
if (e.o !== null) e.o.Ie = null;
|
|
204
218
|
e.Ne = false;
|
|
205
219
|
} else {
|
|
@@ -209,10 +223,10 @@ function recompute(e, t = false) {
|
|
|
209
223
|
// clobber the fresh subscription, so we skip it and let the internally-registered
|
|
210
224
|
// iteration drive updates.
|
|
211
225
|
const t = e.o?.Ie;
|
|
212
|
-
const n = e.oe(
|
|
226
|
+
const n = e.oe(c);
|
|
213
227
|
const i = typeof n === "object" && n !== null;
|
|
214
228
|
const u = e.o?.Ie !== t;
|
|
215
|
-
|
|
229
|
+
c = u || !i ? n : handleAsync(e, n);
|
|
216
230
|
if (!u && !i) {
|
|
217
231
|
if (e.o !== null) e.o.Ie = null;
|
|
218
232
|
// A sync (non-object) return is the first real answer; async-shaped
|
|
@@ -229,7 +243,7 @@ function recompute(e, t = false) {
|
|
|
229
243
|
if (e.S !== 0 || e.o !== null) clearStatus(e, t);
|
|
230
244
|
// _optimisticLane is only ever assigned by engine paths (CONFIG_HAS_LANE
|
|
231
245
|
// is their sticky presence mark).
|
|
232
|
-
if (e.T & CONFIG_HAS_LANE && e.o
|
|
246
|
+
if (e.T & CONFIG_HAS_LANE && e.o?.$e) GlobalQueue.et(e);
|
|
233
247
|
} catch (t) {
|
|
234
248
|
const n = t instanceof NotReadyError;
|
|
235
249
|
if (n && e.Ne) {
|
|
@@ -244,13 +258,16 @@ function recompute(e, t = false) {
|
|
|
244
258
|
} else {
|
|
245
259
|
// Track pending async in the lane (not the lane's source — it creates the lane
|
|
246
260
|
// but doesn't belong to it). Set lane BEFORE notifyStatus for downstream propagation.
|
|
247
|
-
if (n && currentOptimisticLane) GlobalQueue
|
|
261
|
+
if (n && currentOptimisticLane) GlobalQueue.tt(e);
|
|
248
262
|
let i = false;
|
|
249
263
|
if (n) {
|
|
250
264
|
ext(e).fe = true;
|
|
251
|
-
if (GlobalQueue.
|
|
265
|
+
if (GlobalQueue.nt !== null) i = GlobalQueue.nt(e, a);
|
|
252
266
|
}
|
|
253
|
-
notifyStatus(e, n ? STATUS_PENDING : STATUS_ERROR, t, undefined, n ? e.o
|
|
267
|
+
notifyStatus(e, n ? STATUS_PENDING : STATUS_ERROR, t, undefined, n ? e.o?.$e : undefined);
|
|
268
|
+
// The replacement source is fully propagated now. If no new flight
|
|
269
|
+
// re-owned self, retire the superseded flight and its dependent copies.
|
|
270
|
+
if (n && s && !e.o?.Ie) settlePendingSource(e);
|
|
254
271
|
if (i) GlobalQueue.k(e);
|
|
255
272
|
}
|
|
256
273
|
} finally {
|
|
@@ -264,14 +281,14 @@ function recompute(e, t = false) {
|
|
|
264
281
|
// bookkeeping, and those marks are correctly discarded here.
|
|
265
282
|
I = (e.ie & REACTIVE_MISSED_WAKE) !== 0;
|
|
266
283
|
e.ie = REACTIVE_NONE | (t ? e.ie & REACTIVE_SNAPSHOT_STALE : 0);
|
|
267
|
-
context =
|
|
284
|
+
context = _;
|
|
268
285
|
}
|
|
269
286
|
if (!e.o?._) {
|
|
270
287
|
trimStaleDeps(e);
|
|
271
|
-
const a = u ? unwrapOverride(e.o?.
|
|
272
|
-
let
|
|
288
|
+
const a = u ? unwrapOverride(e.o?.Pe) : e.Re === NOT_PENDING ? e.be : e.Re;
|
|
289
|
+
let _ = false;
|
|
273
290
|
try {
|
|
274
|
-
|
|
291
|
+
_ = !n && l || !e.pe || !e.pe(a, c);
|
|
275
292
|
} catch (t) {
|
|
276
293
|
// A throwing user comparator is an error of this node's computation.
|
|
277
294
|
// Route it through the same status path as a compute-phase throw so
|
|
@@ -284,14 +301,14 @@ function recompute(e, t = false) {
|
|
|
284
301
|
// its runner — happen here instead. `!create` matches the previous `initialized`
|
|
285
302
|
// gate: the explicit recompute(node, true) inside effect() does not enqueue, so
|
|
286
303
|
// effect() can call its runner synchronously for the first run.
|
|
287
|
-
if (n &&
|
|
288
|
-
e.
|
|
304
|
+
if (n && _) {
|
|
305
|
+
e.He = !e.o?._;
|
|
289
306
|
// Reuse one bound runner per effect — runEffect no-ops on a stale
|
|
290
307
|
// `_modified`, so re-enqueueing the same function is harmless.
|
|
291
|
-
if (!t) e.C.enqueue(n, e.
|
|
308
|
+
if (!t) e.C.enqueue(n, e.it ??= GlobalQueue.ut.bind(null, e));
|
|
292
309
|
}
|
|
293
|
-
if (e.o?._) ; else if (
|
|
294
|
-
const l = u ? e.o?.
|
|
310
|
+
if (e.o?._) ; else if (_) {
|
|
311
|
+
const l = u ? e.o?.Pe : undefined;
|
|
295
312
|
if (t ||
|
|
296
313
|
// Plain sync flush (no transition on either side) commits effect
|
|
297
314
|
// values directly — the pending round-trip (queuePendingNode +
|
|
@@ -302,17 +319,17 @@ function recompute(e, t = false) {
|
|
|
302
319
|
// not the stashed queues, so a staged value would hand the immediate
|
|
303
320
|
// apply stale state — see CONFIG_DIRECT_COMMIT.
|
|
304
321
|
n && (activeTransition !== e.Ae || activeTransition === null || e.T & CONFIG_DIRECT_COMMIT) || i) {
|
|
305
|
-
e.be =
|
|
322
|
+
e.be = c;
|
|
306
323
|
// Lane-propagated correction: upstream data is fresh, correct the
|
|
307
324
|
// override unconditionally. The direct _value commit is the lane's
|
|
308
325
|
// own reveal schedule; drop any superseded older hold so its queued
|
|
309
326
|
// commit can't clobber the fresh value.
|
|
310
327
|
if (u && i) {
|
|
311
|
-
ext(e).
|
|
312
|
-
e.
|
|
328
|
+
ext(e).Pe = c === undefined ? OVERRIDE_UNDEFINED : c;
|
|
329
|
+
e.Re = NOT_PENDING;
|
|
313
330
|
}
|
|
314
331
|
} else {
|
|
315
|
-
e.
|
|
332
|
+
e.Re = c;
|
|
316
333
|
// A window landing that gets held re-opens the window until the hold
|
|
317
334
|
// commits — the verdict's held-value branch is window-gated (#2990).
|
|
318
335
|
if (r) e.Ne = true;
|
|
@@ -321,26 +338,26 @@ function recompute(e, t = false) {
|
|
|
321
338
|
// (#2831). Both companion writes are transition-scoped (optimistic) and
|
|
322
339
|
// auto-revert/re-derive at commit. Skipped for plain flushes where the
|
|
323
340
|
// pending value commits before effects run.
|
|
324
|
-
if ((activeTransition || e.Ae) && GlobalQueue.
|
|
341
|
+
if ((activeTransition || e.Ae) && GlobalQueue.Ue !== null) GlobalQueue.Ue(e, c);
|
|
325
342
|
}
|
|
326
343
|
// insertSubs only walks _subs (no scheduling of its own), so a
|
|
327
344
|
// subscriber-less node has nothing to notify.
|
|
328
|
-
if (e.u !== null && (!u || i || e.o?.
|
|
345
|
+
if (e.u !== null && (!u || i || e.o?.Pe !== l)) insertSubs(e, i || u);
|
|
329
346
|
} else if (u) {
|
|
330
347
|
// Unchanged value (equals the override) recomputed while the override
|
|
331
348
|
// is active: _value may still be stale, so hold the authoritative value
|
|
332
349
|
// for commit on its own transition's schedule — invisibly (A17/A18).
|
|
333
|
-
if (e.
|
|
334
|
-
e.
|
|
350
|
+
if (e.Re === NOT_PENDING) queuePendingNode(e);
|
|
351
|
+
e.Re = c;
|
|
335
352
|
if (r) e.Ne = true;
|
|
336
353
|
// see the held branch above (#2990)
|
|
337
|
-
//
|
|
338
|
-
// override — and "authoritative arrival
|
|
339
|
-
// exactly the acknowledgment it waits for.
|
|
340
|
-
// A17 silence holds for every ordinary
|
|
341
|
-
//
|
|
342
|
-
if (e.T & CONFIG_AUTHORITATIVE_OBSERVED) GlobalQueue.
|
|
343
|
-
} else if (e.
|
|
354
|
+
// An authoritative-view reader (until()'s predicate, refresh()'s waiter)
|
|
355
|
+
// observed this node past its override — and "authoritative arrival
|
|
356
|
+
// equal to the override" is exactly the acknowledgment it waits for.
|
|
357
|
+
// Wake those readers only; A17 silence holds for every ordinary
|
|
358
|
+
// subscriber. (Hook installed by both setters of the gating bit, #3303.)
|
|
359
|
+
if (e.T & CONFIG_AUTHORITATIVE_OBSERVED) GlobalQueue.he(e);
|
|
360
|
+
} else if (e.qe != f) {
|
|
344
361
|
for (let t = e.u; t !== null; t = t.ae) {
|
|
345
362
|
insertIntoHeapHeight(t.ce, queueFor(t.ce));
|
|
346
363
|
}
|
|
@@ -350,21 +367,14 @@ function recompute(e, t = false) {
|
|
|
350
367
|
// in an errored run and may sit on stale commits (#2949). Changed-value
|
|
351
368
|
// recoveries ride insertSubs above; a comparator throw re-errored the node
|
|
352
369
|
// (el._x?._error re-set), so this only runs on a genuinely clean recovery.
|
|
353
|
-
if (o !== undefined && !
|
|
354
|
-
//
|
|
355
|
-
//
|
|
356
|
-
//
|
|
357
|
-
|
|
358
|
-
// is the dangerous shape (a projection reconciling in place: a memo over
|
|
359
|
-
// it re-throws its cached NotReadyError forever, and every reader that
|
|
360
|
-
// suspended through that memo re-parks on the dead source), but the walk
|
|
361
|
-
// runs on the changed shape too, exactly as the landing path does —
|
|
362
|
-
// insertSubs notifies value SUBSCRIBERS, not pending REGISTRANTS, and
|
|
363
|
-
// the two sets only partially overlap.
|
|
364
|
-
if (s && !(e.S & STATUS_PENDING)) settlePendingSource(e);
|
|
370
|
+
if (o !== undefined && !_ && !e.o?._) settleErroredDependents(e, o);
|
|
371
|
+
// #3181: a synchronous settle supersedes the old landing callback, so
|
|
372
|
+
// recompute owns its pending-source sweep. An uninitialized node without
|
|
373
|
+
// a replacement source still has no truth to reveal and must stay parked.
|
|
374
|
+
if (s && !(e.S & (STATUS_PENDING | STATUS_UNINITIALIZED))) settlePendingSource(e);
|
|
365
375
|
}
|
|
366
376
|
currentOptimisticLane = N;
|
|
367
|
-
const A = e.
|
|
377
|
+
const A = e.Re !== NOT_PENDING || e.o !== null && (e.o.Ke !== null || e.o.Ze !== null) || (e.S & (STATUS_PENDING | STATUS_UNINITIALIZED)) !== 0;
|
|
368
378
|
// Override-covered holds (hasOverride) always queue: their commit belongs
|
|
369
379
|
// to their own transition's schedule (A18 re-rule) and is unobservable
|
|
370
380
|
// under the override (A17). Revert no longer commits anything, so an
|
|
@@ -392,9 +402,9 @@ function updateIfNecessary(e) {
|
|
|
392
402
|
// would resurrect it (#2983) — readers serve its last value.
|
|
393
403
|
if (e.ie & (REACTIVE_RECOMPUTING_DEPS | REACTIVE_DISPOSED)) return;
|
|
394
404
|
if (e.ie & REACTIVE_CHECK) {
|
|
395
|
-
for (let t = e.
|
|
396
|
-
const n = t.
|
|
397
|
-
const i = n.
|
|
405
|
+
for (let t = e.lt; t; t = t.ot) {
|
|
406
|
+
const n = t.st;
|
|
407
|
+
const i = n.rt || n;
|
|
398
408
|
if (i.oe) {
|
|
399
409
|
updateIfNecessary(i);
|
|
400
410
|
}
|
|
@@ -418,32 +428,32 @@ function computed(e, t) {
|
|
|
418
428
|
const u = {
|
|
419
429
|
id: inheritId(t, n, context),
|
|
420
430
|
T: (n ? CONFIG_TRANSPARENT : 0) | (t?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (!context || t?.lazy ? CONFIG_AUTO_DISPOSE : 0) | (t?.sync ? CONFIG_SYNC : 0) | (t?.H ? CONFIG_NO_SNAPSHOT : 0) | (snapshotCaptureActive && ownerInSnapshotScope(context) ? CONFIG_IN_SNAPSHOT_SCOPE : 0),
|
|
421
|
-
|
|
422
|
-
|
|
431
|
+
pe: t?.equals ?? isEqual,
|
|
432
|
+
Ge: null,
|
|
423
433
|
C: context?.C ?? globalQueue,
|
|
424
434
|
we: context?.we ?? defaultContext,
|
|
425
|
-
|
|
435
|
+
je: 0,
|
|
426
436
|
oe: e,
|
|
427
437
|
be: i ? t.loadingValue : undefined,
|
|
428
|
-
|
|
429
|
-
|
|
438
|
+
qe: 0,
|
|
439
|
+
_t: undefined,
|
|
430
440
|
ct: null,
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
441
|
+
lt: null,
|
|
442
|
+
Be: null,
|
|
443
|
+
ze: 0,
|
|
434
444
|
u: null,
|
|
435
|
-
_t: null,
|
|
436
|
-
ke: context,
|
|
437
|
-
Le: null,
|
|
438
445
|
ft: null,
|
|
439
|
-
|
|
446
|
+
Le: context,
|
|
447
|
+
We: null,
|
|
448
|
+
It: null,
|
|
449
|
+
Qe: null,
|
|
440
450
|
ie: t?.lazy ? REACTIVE_LAZY : REACTIVE_NONE,
|
|
441
451
|
// A loadingValue node is born committed: commit #0 is already in _value.
|
|
442
452
|
S: i ? 0 : STATUS_UNINITIALIZED,
|
|
443
453
|
Te: clock,
|
|
444
|
-
|
|
454
|
+
Re: NOT_PENDING,
|
|
445
455
|
Ae: null,
|
|
446
|
-
|
|
456
|
+
Et: -1,
|
|
447
457
|
Ne: i,
|
|
448
458
|
// Cold machinery (async/transition/optimistic/verdict slots) lives one
|
|
449
459
|
// hop away in the lazily-allocated extension — the core literal MUST
|
|
@@ -451,7 +461,7 @@ function computed(e, t) {
|
|
|
451
461
|
// allocation spills to a backing store and creation cost ~4x's).
|
|
452
462
|
o: null
|
|
453
463
|
};
|
|
454
|
-
if (t?.unobserved) ext(u).
|
|
464
|
+
if (t?.unobserved) ext(u).Nt = t.unobserved;
|
|
455
465
|
setupComputedNode(u, t);
|
|
456
466
|
return u;
|
|
457
467
|
}
|
|
@@ -461,12 +471,12 @@ function computed(e, t) {
|
|
|
461
471
|
* this; hot paths read `el._x?._field` gated by the _config presence bits.
|
|
462
472
|
* Never call ext() just to store a field's default. */ function ext(e) {
|
|
463
473
|
return e.o ??= {
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
474
|
+
Pe: undefined,
|
|
475
|
+
Tt: undefined,
|
|
476
|
+
$e: undefined,
|
|
467
477
|
ye: undefined,
|
|
468
478
|
Ce: undefined,
|
|
469
|
-
|
|
479
|
+
St: undefined,
|
|
470
480
|
t: 0,
|
|
471
481
|
Ie: null,
|
|
472
482
|
Ee: null,
|
|
@@ -474,13 +484,13 @@ function computed(e, t) {
|
|
|
474
484
|
fe: undefined,
|
|
475
485
|
le: undefined,
|
|
476
486
|
h: undefined,
|
|
477
|
-
|
|
487
|
+
De: false,
|
|
478
488
|
i: null,
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
489
|
+
Nt: undefined,
|
|
490
|
+
Ye: undefined,
|
|
491
|
+
Ze: null,
|
|
492
|
+
Ke: null,
|
|
493
|
+
dt: undefined
|
|
484
494
|
};
|
|
485
495
|
}
|
|
486
496
|
|
|
@@ -493,39 +503,39 @@ function computed(e, t) {
|
|
|
493
503
|
const l = u?.transparent ?? false;
|
|
494
504
|
const o = {
|
|
495
505
|
id: inheritId(u, l, context),
|
|
496
|
-
T: (l ? CONFIG_TRANSPARENT : 0) | (u?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (u?.sync ? CONFIG_SYNC : 0) | (u?.
|
|
497
|
-
|
|
498
|
-
|
|
506
|
+
T: (l ? CONFIG_TRANSPARENT : 0) | (u?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (u?.sync ? CONFIG_SYNC : 0) | (u?.At ?? 0) | (snapshotCaptureActive && ownerInSnapshotScope(context) ? CONFIG_IN_SNAPSHOT_SCOPE : 0),
|
|
507
|
+
pe: false,
|
|
508
|
+
Ge: null,
|
|
499
509
|
C: context?.C ?? globalQueue,
|
|
500
510
|
we: context?.we ?? defaultContext,
|
|
501
|
-
|
|
511
|
+
je: 0,
|
|
502
512
|
oe: e,
|
|
503
513
|
be: undefined,
|
|
504
|
-
|
|
505
|
-
|
|
514
|
+
qe: 0,
|
|
515
|
+
_t: undefined,
|
|
506
516
|
ct: null,
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
517
|
+
lt: null,
|
|
518
|
+
Be: null,
|
|
519
|
+
ze: 0,
|
|
510
520
|
u: null,
|
|
511
|
-
_t: null,
|
|
512
|
-
ke: context,
|
|
513
|
-
Le: null,
|
|
514
521
|
ft: null,
|
|
515
|
-
|
|
522
|
+
Le: context,
|
|
523
|
+
We: null,
|
|
524
|
+
It: null,
|
|
525
|
+
Qe: null,
|
|
516
526
|
ie: REACTIVE_LAZY,
|
|
517
527
|
S: STATUS_UNINITIALIZED,
|
|
518
528
|
Te: clock,
|
|
519
|
-
|
|
529
|
+
Re: NOT_PENDING,
|
|
520
530
|
Ae: null,
|
|
521
|
-
|
|
531
|
+
Et: -1,
|
|
522
532
|
Ne: false,
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
533
|
+
He: false,
|
|
534
|
+
Ot: undefined,
|
|
535
|
+
Ct: t,
|
|
536
|
+
Rt: n,
|
|
537
|
+
Gt: undefined,
|
|
538
|
+
ge: i,
|
|
529
539
|
o: null
|
|
530
540
|
};
|
|
531
541
|
// Effects dispatch status through the SHARED notifier (statusNotifierOf,
|
|
@@ -533,7 +543,7 @@ function computed(e, t) {
|
|
|
533
543
|
// allocation on EVERY effect at creation (an alloc + 19 field stores,
|
|
534
544
|
// +23% effect creation, caught by the creation benches). Only genuinely
|
|
535
545
|
// per-node channels (boundaries) live on _x.
|
|
536
|
-
if (u?.unobserved) ext(o).
|
|
546
|
+
if (u?.unobserved) ext(o).Nt = u.unobserved;
|
|
537
547
|
setupComputedNode(o, lazyOptions);
|
|
538
548
|
return o;
|
|
539
549
|
}
|
|
@@ -556,7 +566,7 @@ function setEffectStatusNotify(e) {
|
|
|
556
566
|
* per-node field did when every effect carried one. */ function statusNotifierOf(e) {
|
|
557
567
|
const t = e.o?.h;
|
|
558
568
|
if (t !== undefined) return t;
|
|
559
|
-
return e.
|
|
569
|
+
return e.ge ? effectStatusNotify ?? undefined : undefined;
|
|
560
570
|
}
|
|
561
571
|
|
|
562
572
|
const lazyOptions = {
|
|
@@ -565,23 +575,23 @@ const lazyOptions = {
|
|
|
565
575
|
|
|
566
576
|
function setupComputedNode(e, t) {
|
|
567
577
|
e.ct = e;
|
|
568
|
-
const n = context?.
|
|
578
|
+
const n = context?.Dt ? context.Pt : context;
|
|
569
579
|
if (context) {
|
|
570
|
-
const t = context.
|
|
580
|
+
const t = context.Qe;
|
|
571
581
|
if (t === null) {
|
|
572
|
-
context.
|
|
582
|
+
context.Qe = e;
|
|
573
583
|
} else {
|
|
574
|
-
e.
|
|
575
|
-
t.
|
|
576
|
-
context.
|
|
584
|
+
e.We = t;
|
|
585
|
+
t.It = e;
|
|
586
|
+
context.Qe = e;
|
|
577
587
|
}
|
|
578
588
|
}
|
|
579
|
-
if (n) e.
|
|
580
|
-
if (GlobalQueue.
|
|
589
|
+
if (n) e.qe = n.qe + 1;
|
|
590
|
+
if (GlobalQueue.Ft !== null) GlobalQueue.Ft(e);
|
|
581
591
|
!t?.lazy && recompute(e, true);
|
|
582
592
|
if (snapshotCaptureActive && !t?.lazy) {
|
|
583
593
|
if (!(e.S & STATUS_PENDING) && !(e.T & CONFIG_NO_SNAPSHOT)) {
|
|
584
|
-
ext(e).
|
|
594
|
+
ext(e).Ye = e.be === undefined ? NO_SNAPSHOT : e.be;
|
|
585
595
|
e.T |= CONFIG_HAS_SNAPSHOT;
|
|
586
596
|
snapshotSources.add(e);
|
|
587
597
|
}
|
|
@@ -590,47 +600,99 @@ function setupComputedNode(e, t) {
|
|
|
590
600
|
|
|
591
601
|
function signal(e, t, n = null) {
|
|
592
602
|
const i = {
|
|
593
|
-
|
|
603
|
+
pe: t?.equals ?? isEqual,
|
|
594
604
|
T: (t?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (t?.H ? CONFIG_NO_SNAPSHOT : 0),
|
|
595
605
|
be: e,
|
|
596
606
|
u: null,
|
|
597
|
-
|
|
607
|
+
ft: null,
|
|
598
608
|
Te: clock,
|
|
599
|
-
|
|
609
|
+
rt: n,
|
|
600
610
|
Se: n?.o?.i || null,
|
|
601
|
-
|
|
611
|
+
Re: NOT_PENDING,
|
|
602
612
|
// Signal-literal diet (§12e): NO _time/_fn/_statusFlags slots. Stores
|
|
603
613
|
// materialize one signal per touched leaf, so signal bytes are store
|
|
604
614
|
// bytes. _time is write-only on signals (every read site is computed-
|
|
605
615
|
// typed error-retry gating); _fn/_statusFlags read falsy-identically as
|
|
606
616
|
// missing properties on the shared paths (undefined masks to 0).
|
|
607
617
|
Ae: null,
|
|
608
|
-
|
|
618
|
+
Et: -1,
|
|
609
619
|
o: null
|
|
610
620
|
};
|
|
611
|
-
if (t?.unobserved) ext(i).
|
|
621
|
+
if (t?.unobserved) ext(i).Nt = t.unobserved;
|
|
612
622
|
if (n) {
|
|
613
623
|
ext(n).i = i;
|
|
614
624
|
n.T |= CONFIG_FW_CHILDREN;
|
|
615
625
|
}
|
|
616
626
|
if (snapshotCaptureActive && !(i.T & CONFIG_NO_SNAPSHOT) && !((n?.S ?? 0) & STATUS_PENDING)) {
|
|
617
|
-
ext(i).
|
|
627
|
+
ext(i).Ye = e === undefined ? NO_SNAPSHOT : e;
|
|
618
628
|
i.T |= CONFIG_HAS_SNAPSHOT;
|
|
619
629
|
snapshotSources.add(i);
|
|
620
630
|
}
|
|
621
631
|
return i;
|
|
622
632
|
}
|
|
623
633
|
|
|
634
|
+
// ---------------------------------------------------------------------------
|
|
635
|
+
// SLOT SIGNALS (store leaves) — the create-floor diet. Store mounts
|
|
636
|
+
// materialize one signal per touched leaf (~13 × rows on dbmon), so per-node
|
|
637
|
+
// allocations are mount bytes: the generic path costs an options object, an
|
|
638
|
+
// equals closure, an unobserved closure, a NodeExtension to hold it, and
|
|
639
|
+
// three post-construction expandos (acc/px/pxv → hidden-class transitions).
|
|
640
|
+
// slotSignal bakes everything into ONE literal: `_host`/`_key` backrefs
|
|
641
|
+
// replace the closures (equals is a method call — `this` is the node; the
|
|
642
|
+
// unobserved sweep dispatches CONFIG_SLOT_NODE to one shared hook), and the
|
|
643
|
+
// store's wrap-cache fields are pre-shaped.
|
|
644
|
+
/** The shared slot-node unobserved handler — a live binding read directly by
|
|
645
|
+
* the sweep sites (no wrapper frame, no null check: a CONFIG_SLOT_NODE node
|
|
646
|
+
* existing implies the store module loaded and registered the hook). */ let slotUnobservedHook;
|
|
647
|
+
|
|
648
|
+
/** Install the shared slot-node unobserved handler (store module, once). */ function setSlotUnobserved(e) {
|
|
649
|
+
slotUnobservedHook = e;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
function slotSignal(e, t, n, i, u, l = null) {
|
|
653
|
+
const o = {
|
|
654
|
+
pe: t,
|
|
655
|
+
T: CONFIG_OWNED_WRITE | CONFIG_SLOT_NODE,
|
|
656
|
+
be: e,
|
|
657
|
+
u: null,
|
|
658
|
+
ft: null,
|
|
659
|
+
Te: clock,
|
|
660
|
+
rt: l,
|
|
661
|
+
Se: l?.o?.i || null,
|
|
662
|
+
Re: NOT_PENDING,
|
|
663
|
+
Ae: null,
|
|
664
|
+
Et: -1,
|
|
665
|
+
o: null,
|
|
666
|
+
// Slot backrefs: what the equals/unobserved closures used to capture.
|
|
667
|
+
ht: n,
|
|
668
|
+
Ht: i,
|
|
669
|
+
// Store read-path caches, pre-shaped (were post-construction expandos).
|
|
670
|
+
acc: u,
|
|
671
|
+
px: undefined,
|
|
672
|
+
pxv: undefined
|
|
673
|
+
};
|
|
674
|
+
if (l) {
|
|
675
|
+
ext(l).i = o;
|
|
676
|
+
l.T |= CONFIG_FW_CHILDREN;
|
|
677
|
+
}
|
|
678
|
+
if (snapshotCaptureActive && !((l?.S ?? 0) & STATUS_PENDING)) {
|
|
679
|
+
ext(o).Ye = e === undefined ? NO_SNAPSHOT : e;
|
|
680
|
+
o.T |= CONFIG_HAS_SNAPSHOT;
|
|
681
|
+
snapshotSources.add(o);
|
|
682
|
+
}
|
|
683
|
+
return o;
|
|
684
|
+
}
|
|
685
|
+
|
|
624
686
|
function optimisticSignal(e, t) {
|
|
625
687
|
const n = signal(e, t);
|
|
626
|
-
ext(n).
|
|
688
|
+
ext(n).Pe = NOT_PENDING;
|
|
627
689
|
n.T |= CONFIG_OPTIMISTIC;
|
|
628
690
|
return n;
|
|
629
691
|
}
|
|
630
692
|
|
|
631
693
|
function optimisticComputed(e, t) {
|
|
632
694
|
const n = computed(e, t);
|
|
633
|
-
ext(n).
|
|
695
|
+
ext(n).Pe = NOT_PENDING;
|
|
634
696
|
n.T |= CONFIG_OPTIMISTIC;
|
|
635
697
|
return n;
|
|
636
698
|
}
|
|
@@ -661,11 +723,11 @@ function isEqual(e, t) {
|
|
|
661
723
|
* );
|
|
662
724
|
* ```
|
|
663
725
|
*/ function untrack(e, t) {
|
|
664
|
-
if (GlobalQueue.
|
|
726
|
+
if (GlobalQueue.gt === null && !tracking && true) return e();
|
|
665
727
|
const n = tracking;
|
|
666
728
|
tracking = false;
|
|
667
729
|
try {
|
|
668
|
-
if (GlobalQueue.
|
|
730
|
+
if (GlobalQueue.gt !== null) return GlobalQueue.gt(e);
|
|
669
731
|
return e();
|
|
670
732
|
} finally {
|
|
671
733
|
tracking = n;
|
|
@@ -722,28 +784,30 @@ function isEqual(e, t) {
|
|
|
722
784
|
// itself have pulled this recompute (updateIfNecessary from its own
|
|
723
785
|
// read), and the heap refuses RECOMPUTING nodes — latch so recompute's
|
|
724
786
|
// tail reschedules it with the staged value visible.
|
|
725
|
-
if (e.ie & REACTIVE_RECOMPUTING_DEPS && t.
|
|
787
|
+
if (e.ie & REACTIVE_RECOMPUTING_DEPS && t.vt === e.ze && t !== e.Be) e.ie |= REACTIVE_MISSED_WAKE;
|
|
726
788
|
enqueueSub(e);
|
|
727
789
|
}
|
|
728
790
|
schedule();
|
|
729
791
|
}
|
|
730
792
|
|
|
731
|
-
/** Installs the
|
|
732
|
-
*
|
|
733
|
-
*
|
|
734
|
-
|
|
793
|
+
/** Installs the authoritative-reader wakeup hook. Idempotent; called by every
|
|
794
|
+
* creator of a CONFIG_AUTHORITATIVE_READ computation — until() and refresh() —
|
|
795
|
+
* before its first read (same late-binding contract as the optimistic engine;
|
|
796
|
+
* the gating bit is only ever set by such a read, so the `!` call sites are
|
|
797
|
+
* safe once every setter installs, #3303). */ function installAuthoritativeRead() {
|
|
798
|
+
if (GlobalQueue.he === null) GlobalQueue.he = notifyAuthoritativeObservers;
|
|
735
799
|
}
|
|
736
800
|
|
|
737
801
|
function readNodeFast(e) {
|
|
738
|
-
if (latestReadActive || pendingCheckActive || e.oe || e.
|
|
802
|
+
if (latestReadActive || pendingCheckActive || e.oe || e.rt || e.o?.Pe !== undefined || e.o?.Ye !== undefined || activeTransition !== null || currentOptimisticLane !== null || snapshotCaptureActive || false) return READ_SLOW;
|
|
739
803
|
let t = context;
|
|
740
|
-
if (t?.
|
|
804
|
+
if (t?.Dt) t = t.Pt;
|
|
741
805
|
if (t && tracking) link(e, t);
|
|
742
806
|
// Children-forbidden readers (createTrackedEffect / onSettled callbacks) get
|
|
743
807
|
// committed visibility: like the effect half of createEffect and event
|
|
744
808
|
// handlers, effect-phase code never observes its own unsettled write — the
|
|
745
809
|
// write lands in the same flush's continuation (#3006).
|
|
746
|
-
return !t || e.
|
|
810
|
+
return !t || e.Re === NOT_PENDING || t.T & CONFIG_CHILDREN_FORBIDDEN ? e.be : e.Re;
|
|
747
811
|
}
|
|
748
812
|
|
|
749
813
|
function read(e) {
|
|
@@ -751,30 +815,30 @@ function read(e) {
|
|
|
751
815
|
// Checked before isPending so that isPending(() => latest(x)) checks
|
|
752
816
|
// the _pendingSignal of _latestValueComputed (async in flight) rather
|
|
753
817
|
// than the original node (which stays "pending" while held in a transition).
|
|
754
|
-
if (latestReadActive) return GlobalQueue.
|
|
818
|
+
if (latestReadActive) return GlobalQueue.Vt(e);
|
|
755
819
|
let t = context;
|
|
756
|
-
if (t?.
|
|
820
|
+
if (t?.Dt) t = t.Pt;
|
|
757
821
|
const n = e;
|
|
758
|
-
const i = e.
|
|
822
|
+
const i = e.rt;
|
|
759
823
|
const u = i || e;
|
|
760
824
|
// Handle isPending() mode: collect pending state while preserving normal read semantics.
|
|
761
825
|
// Probe mode is suspended while preparing the node so nested reads during a
|
|
762
826
|
// recompute don't collect into the probe.
|
|
763
827
|
if (pendingCheckActive) {
|
|
764
|
-
GlobalQueue.
|
|
828
|
+
GlobalQueue.bt(e, t, u, i);
|
|
765
829
|
} else if (typeof n.oe === "function") {
|
|
766
830
|
prepareComputed(e, false);
|
|
767
831
|
}
|
|
768
|
-
if (!n.oe && u === e && e.o?.
|
|
832
|
+
if (!n.oe && u === e && e.o?.Pe === undefined && e.o?.Ye === undefined && activeTransition === null && currentOptimisticLane === null && !snapshotCaptureActive && true) {
|
|
769
833
|
if (t && tracking) link(e, t);
|
|
770
834
|
// Committed visibility for children-forbidden readers — see readNodeFast.
|
|
771
|
-
return !t || e.
|
|
835
|
+
return !t || e.Re === NOT_PENDING || t.T & CONFIG_CHILDREN_FORBIDDEN ? e.be : e.Re;
|
|
772
836
|
}
|
|
773
837
|
if (t && tracking) {
|
|
774
838
|
link(e, t, pendingCheckActive);
|
|
775
839
|
if (u.oe) {
|
|
776
840
|
const n = queueFor(e);
|
|
777
|
-
if (u.
|
|
841
|
+
if (u.qe >= n.Me) {
|
|
778
842
|
markNode(t);
|
|
779
843
|
markHeap(n);
|
|
780
844
|
updateIfNecessary(u);
|
|
@@ -786,10 +850,10 @@ function read(e) {
|
|
|
786
850
|
// node no-ops and updateIfNecessary refuses disposed nodes (#2983) —
|
|
787
851
|
// a dead target serves its last value, which is already quiescent.
|
|
788
852
|
else if (t.T & CONFIG_FRESH_READ) updateIfNecessary(u);
|
|
789
|
-
const i = u.
|
|
853
|
+
const i = u.qe;
|
|
790
854
|
// parent check is shallow, might need to be recursive
|
|
791
|
-
if (i >= t.
|
|
792
|
-
t.
|
|
855
|
+
if (i >= t.qe && e.Le !== t) {
|
|
856
|
+
t.qe = i + 1;
|
|
793
857
|
}
|
|
794
858
|
}
|
|
795
859
|
}
|
|
@@ -797,8 +861,10 @@ function read(e) {
|
|
|
797
861
|
if (t && !(stale && u.Ae && activeTransition !== u.Ae)) {
|
|
798
862
|
// Per-lane suspension lives with the engine (a non-null lane implies it
|
|
799
863
|
// is installed): under a lane, only same-lane pending async without an
|
|
800
|
-
// active override throws
|
|
801
|
-
|
|
864
|
+
// active override throws — plus uninitialized sources regardless of
|
|
865
|
+
// lane (#3276); that check rides laneSuspends so floor bundles don't
|
|
866
|
+
// pay for it.
|
|
867
|
+
if (currentOptimisticLane === null || GlobalQueue.kt(u)) {
|
|
802
868
|
if (!tracking && e !== t) link(e, t);
|
|
803
869
|
throw u.o?._;
|
|
804
870
|
}
|
|
@@ -834,15 +900,15 @@ function read(e) {
|
|
|
834
900
|
} else throw u.o?._;
|
|
835
901
|
}
|
|
836
902
|
if (snapshotCaptureActive && t && t.T & CONFIG_IN_SNAPSHOT_SCOPE) {
|
|
837
|
-
const n = e.o?.
|
|
903
|
+
const n = e.o?.Ye;
|
|
838
904
|
if (n !== undefined) {
|
|
839
905
|
const i = n === NO_SNAPSHOT ? undefined : n;
|
|
840
|
-
const u = e.
|
|
906
|
+
const u = e.Re !== NOT_PENDING ? e.Re : e.be;
|
|
841
907
|
if (u !== i) t.ie |= REACTIVE_SNAPSHOT_STALE;
|
|
842
908
|
return i;
|
|
843
909
|
}
|
|
844
910
|
}
|
|
845
|
-
if (e.o?.
|
|
911
|
+
if (e.o?.Pe !== undefined && e.o?.Pe !== NOT_PENDING) {
|
|
846
912
|
// A17: the override IS the value for every reader — except an authoritative
|
|
847
913
|
// reader (until()'s predicate carries CONFIG_AUTHORITATIVE_READ): it must
|
|
848
914
|
// observe independently-arriving truth, and serving it the caller's own
|
|
@@ -853,7 +919,7 @@ function read(e) {
|
|
|
853
919
|
// authoritative — optimism never lives there); the sticky mark makes the
|
|
854
920
|
// A17-silent "landing equals override" paths notify this node's subs so
|
|
855
921
|
// the reader re-runs when truth arrives.
|
|
856
|
-
if (!(t && t.T & CONFIG_AUTHORITATIVE_READ)) return unwrapOverride(e.o?.
|
|
922
|
+
if (!(t && t.T & CONFIG_AUTHORITATIVE_READ)) return unwrapOverride(e.o?.Pe);
|
|
857
923
|
e.T |= CONFIG_AUTHORITATIVE_OBSERVED;
|
|
858
924
|
}
|
|
859
925
|
// Entanglement gate: a reader recomputing under an optimistic lane that reads
|
|
@@ -863,7 +929,7 @@ function read(e) {
|
|
|
863
929
|
// _pendingValue for correct fetching. The sub is recorded for replay at commit
|
|
864
930
|
// so it re-runs with the new committed view. (Gate details live with the
|
|
865
931
|
// engine — a non-null lane implies it is installed.)
|
|
866
|
-
if (currentOptimisticLane !== null && activeTransition !== null && t !== null && GlobalQueue.
|
|
932
|
+
if (currentOptimisticLane !== null && activeTransition !== null && t !== null && GlobalQueue.Ut(e, u, t)) {
|
|
867
933
|
return e.be;
|
|
868
934
|
}
|
|
869
935
|
// In optimistic lane context, return _value for optimistic/lane-assigned signals
|
|
@@ -872,7 +938,7 @@ function read(e) {
|
|
|
872
938
|
// (The lane-context clause lives with the engine.) Children-forbidden readers
|
|
873
939
|
// (createTrackedEffect / onSettled callbacks) get committed visibility — see
|
|
874
940
|
// readNodeFast (#3006).
|
|
875
|
-
const l = !t || currentOptimisticLane !== null && GlobalQueue.
|
|
941
|
+
const l = !t || currentOptimisticLane !== null && GlobalQueue.xt(e, u, t) || e.Re === NOT_PENDING || t.T & CONFIG_CHILDREN_FORBIDDEN || stale && e.Ae && activeTransition !== e.Ae ||
|
|
876
942
|
// A17 for HELD truth (#3164, see CONFIG_HELD_TRUTH): staged confirming
|
|
877
943
|
// truth — fold-staged onto an armed family, or entangle-stolen by an
|
|
878
944
|
// awaited until() — is masked from ordinary readers until its
|
|
@@ -881,10 +947,10 @@ function read(e) {
|
|
|
881
947
|
// compose override + staged truth into a state no timeline contains).
|
|
882
948
|
// Authoritative readers (until()'s predicate) and latest() see the
|
|
883
949
|
// staged truth — the tunnel that keeps the hold deadlock-free.
|
|
884
|
-
e.T & CONFIG_HELD_TRUTH && !latestReadActive && !(t.T & CONFIG_AUTHORITATIVE_READ) ? e.be : e.
|
|
950
|
+
e.T & CONFIG_HELD_TRUTH && !latestReadActive && !(t.T & CONFIG_AUTHORITATIVE_READ) ? e.be : e.Re;
|
|
885
951
|
// Record that this isPending() probe observed the fresh pending value, so
|
|
886
952
|
// the probe doesn't pair "pending" with the new value (#2831).
|
|
887
|
-
if (pendingCheckActive) GlobalQueue.
|
|
953
|
+
if (pendingCheckActive) GlobalQueue.Lt(e, l);
|
|
888
954
|
if (!t && u === e && typeof n.oe === "function" && e.T & CONFIG_AUTO_DISPOSE && !(u.S & STATUS_PENDING) && !e.u) {
|
|
889
955
|
// Deferred, not inline (#3078): an inline unobserved() here made untracked
|
|
890
956
|
// reads destructive — dispose on this read, full revival recompute on the
|
|
@@ -905,22 +971,22 @@ function setSignal(e, t) {
|
|
|
905
971
|
// _overrideValue slot (flagged by CONFIG_OPTIMISTIC — a masked read of the
|
|
906
972
|
// always-present config instead of a missing-property probe), and every
|
|
907
973
|
// module that installs one installs the engine first.
|
|
908
|
-
if (e.T & CONFIG_OPTIMISTIC && !projectionWriteActive) return GlobalQueue.
|
|
909
|
-
const n = e.
|
|
974
|
+
if (e.T & CONFIG_OPTIMISTIC && !projectionWriteActive) return GlobalQueue.yt(e, t);
|
|
975
|
+
const n = e.Re === NOT_PENDING ? e.be : e.Re;
|
|
910
976
|
if (typeof t === "function") t = t(n);
|
|
911
977
|
// Uninitialized check first: the first commit has no previous value, so the
|
|
912
978
|
// user comparator must not run against `undefined` (matches recompute).
|
|
913
|
-
const i = !!(e.S & STATUS_UNINITIALIZED) || !e.
|
|
979
|
+
const i = !!(e.S & STATUS_UNINITIALIZED) || !e.pe || !e.pe(n, t);
|
|
914
980
|
if (!i) return t;
|
|
915
|
-
const u = e.
|
|
981
|
+
const u = e.Re !== NOT_PENDING;
|
|
916
982
|
if (!u) queuePendingNode(e);
|
|
917
|
-
e.
|
|
983
|
+
e.Re = t;
|
|
918
984
|
// syncCompanions only pokes _pendingSignal/_latestValueComputed — with
|
|
919
985
|
// neither companion present the call is a guaranteed no-op (companions are
|
|
920
986
|
// only ever created, never removed, and creating one installs the hook and
|
|
921
987
|
// sets CONFIG_HAS_COMPANIONS — one masked read replaces two optional-field
|
|
922
988
|
// probes on every write).
|
|
923
|
-
e.T & CONFIG_HAS_COMPANIONS && GlobalQueue.
|
|
989
|
+
e.T & CONFIG_HAS_COMPANIONS && GlobalQueue.Ue !== null && GlobalQueue.Ue(e, t);
|
|
924
990
|
// _time is a computed-only slot (§12e): writing it on a signal would fork
|
|
925
991
|
// the lean shape. Every read site is computed-typed.
|
|
926
992
|
if (e.oe !== undefined) e.Te = clock;
|
|
@@ -929,7 +995,7 @@ function setSignal(e, t) {
|
|
|
929
995
|
// (epoch) — re-stages the value and stops. The walk is idempotent (subs
|
|
930
996
|
// marked, heap entries flag-guarded, effects queued once); lane and reask
|
|
931
997
|
// contexts change what a walk MEANS, so they always walk.
|
|
932
|
-
if (u && e.
|
|
998
|
+
if (u && e.Et === notifyEpoch && currentOptimisticLane === null && !reaskArmed) return t;
|
|
933
999
|
insertSubs(e);
|
|
934
1000
|
schedule();
|
|
935
1001
|
return t;
|
|
@@ -943,12 +1009,12 @@ function setSignal(e, t) {
|
|
|
943
1009
|
* cleanup point.
|
|
944
1010
|
*/ function suppressComputedRecompute(e) {
|
|
945
1011
|
deleteFromHeap(e, queueFor(e));
|
|
946
|
-
if (!(e.ie & REACTIVE_MANUAL_WRITE) && e.
|
|
1012
|
+
if (!(e.ie & REACTIVE_MANUAL_WRITE) && e.Re === NOT_PENDING) {
|
|
947
1013
|
queuePendingNode(e);
|
|
948
1014
|
schedule();
|
|
949
1015
|
}
|
|
950
1016
|
e.ie = e.ie & -4 | REACTIVE_MANUAL_WRITE;
|
|
951
|
-
e.
|
|
1017
|
+
e.Qt = clock;
|
|
952
1018
|
}
|
|
953
1019
|
|
|
954
1020
|
/**
|
|
@@ -1018,10 +1084,16 @@ function staleValues(e, t = true) {
|
|
|
1018
1084
|
// refresh is a later, explicit re-ask and lifts the mask — otherwise
|
|
1019
1085
|
// any setStore early in an action silently swallows every refresh()
|
|
1020
1086
|
// for the rest of the transaction (#3026).
|
|
1021
|
-
if (e.
|
|
1087
|
+
if (e.Qt === clock) return;
|
|
1022
1088
|
e.ie &= ~REACTIVE_MANUAL_WRITE;
|
|
1023
|
-
//
|
|
1024
|
-
//
|
|
1089
|
+
// The lift falls through to the re-ask classification below. The held
|
|
1090
|
+
// write's value change already rides the transaction; the refetch it
|
|
1091
|
+
// asks for is the same question with unchanged inputs. Skipping the
|
|
1092
|
+
// mark here classified that refetch as a NEW question, which pends
|
|
1093
|
+
// every leaf (3.1) — an action doing setStore + yield + refresh(store)
|
|
1094
|
+
// lit up every sibling row, and affects() could not narrow it (a mark
|
|
1095
|
+
// only turns pending on). Same-question motion stays silent (3.4);
|
|
1096
|
+
// the written slot and any declared mark carry the pending instead.
|
|
1025
1097
|
}
|
|
1026
1098
|
// A refresh with no value-change dirt already queued is a re-ask of the
|
|
1027
1099
|
// same question: mark it so the recompute classifies any resulting
|
|
@@ -1030,7 +1102,7 @@ function staleValues(e, t = true) {
|
|
|
1030
1102
|
// REACTIVE_IN_HEAP counts as dirt: insertSubs schedules subscribers by
|
|
1031
1103
|
// heap insertion alone (no DIRTY/CHECK flag), so a same-batch value
|
|
1032
1104
|
// change followed by refresh() must not be laundered into a quiet re-ask.
|
|
1033
|
-
|
|
1105
|
+
if (!(e.ie & (REACTIVE_DIRTY | REACTIVE_CHECK | REACTIVE_IN_HEAP))) {
|
|
1034
1106
|
e.ie |= REACTIVE_REASK;
|
|
1035
1107
|
armReaskClear();
|
|
1036
1108
|
}
|
|
@@ -1040,4 +1112,4 @@ function staleValues(e, t = true) {
|
|
|
1040
1112
|
}
|
|
1041
1113
|
}
|
|
1042
1114
|
|
|
1043
|
-
export { READ_SLOW, clearSnapshots, computed, context, createEffectNode, currentOptimisticLane, effectStatusNotify, ext, installAuthoritativeRead, isEqual, latestReadActive, markRefresh, markSnapshotScope, notifyAuthoritativeObservers, optimisticComputed, optimisticSignal, pendingCheckActive, prepareComputed, read, readNodeFast, recompute, releaseSnapshotScope, runWithOwner, setContextInternal, setEffectStatusNotify, setLatestReadActive, setMemo, setPendingCheckActive, setSignal, setSnapshotCapture, signal, snapshotCaptureActive, snapshotSources, stale, staleValues, statusNotifierOf, suppressComputedRecompute, tracking, untrack };
|
|
1115
|
+
export { READ_SLOW, clearSnapshots, computed, context, createEffectNode, currentOptimisticLane, effectStatusNotify, ext, installAuthoritativeRead, isEqual, latestReadActive, markRefresh, markSnapshotScope, notifyAuthoritativeObservers, optimisticComputed, optimisticSignal, pendingCheckActive, prepareComputed, read, readNodeFast, recompute, releaseSnapshotScope, runWithOwner, setContextInternal, setEffectStatusNotify, setLatestReadActive, setMemo, setPendingCheckActive, setSignal, setSlotUnobserved, setSnapshotCapture, signal, slotSignal, slotUnobservedHook, snapshotCaptureActive, snapshotSources, stale, staleValues, statusNotifierOf, suppressComputedRecompute, tracking, untrack };
|