@solidjs/signals 2.0.0-beta.20 → 2.0.0-beta.22
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 +5 -1
- package/dist/dev.js +267 -307
- package/dist/node.cjs +1125 -1168
- package/dist/prod/affects.js +71 -163
- package/dist/prod/boundaries.js +141 -137
- package/dist/prod/core/action.js +50 -12
- package/dist/prod/core/async.js +83 -99
- package/dist/prod/core/core.js +255 -298
- package/dist/prod/core/effect.js +46 -46
- package/dist/prod/core/external.js +4 -4
- package/dist/prod/core/graph.js +54 -46
- package/dist/prod/core/heap.js +58 -50
- package/dist/prod/core/lanes.js +34 -34
- package/dist/prod/core/optimistic.js +64 -106
- package/dist/prod/core/owner.js +52 -52
- package/dist/prod/core/scheduler.js +217 -211
- package/dist/prod/core/verdict.js +144 -78
- package/dist/prod/map.js +101 -101
- package/dist/prod/signals.js +23 -5
- package/dist/prod/store/optimistic.js +11 -11
- package/dist/prod/store/projection.js +2 -2
- package/dist/prod/store/store.js +14 -14
- package/dist/types/affects.d.ts +9 -9
- package/dist/types/core/action.d.ts +16 -0
- package/dist/types/core/async.d.ts +1 -1
- package/dist/types/core/error.d.ts +7 -0
- package/dist/types/core/scheduler.d.ts +1 -6
- package/dist/types/core/types.d.ts +6 -11
- package/dist/types-cjs/affects.d.cts +9 -9
- package/dist/types-cjs/core/action.d.cts +16 -0
- package/dist/types-cjs/core/async.d.cts +1 -1
- package/dist/types-cjs/core/error.d.cts +7 -0
- package/dist/types-cjs/core/scheduler.d.cts +1 -6
- package/dist/types-cjs/core/types.d.cts +6 -11
- package/package.json +1 -1
package/dist/prod/core/core.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { handleAsync, clearStatus, notifyStatus } from "./async.js";
|
|
2
2
|
|
|
3
|
-
import { EFFECT_TRACKED, REACTIVE_OPTIMISTIC_DIRTY, NOT_PENDING, STATUS_UNINITIALIZED, REACTIVE_REASK, REACTIVE_RECOMPUTING_DEPS, CONFIG_SYNC, STATUS_PENDING, STATUS_ERROR, REACTIVE_NONE, REACTIVE_SNAPSHOT_STALE, unwrapOverride, OVERRIDE_UNDEFINED,
|
|
3
|
+
import { EFFECT_TRACKED, REACTIVE_OPTIMISTIC_DIRTY, NOT_PENDING, STATUS_UNINITIALIZED, REACTIVE_REASK, REACTIVE_RECOMPUTING_DEPS, CONFIG_SYNC, STATUS_PENDING, STATUS_ERROR, 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";
|
|
4
4
|
|
|
5
5
|
import { NotReadyError } from "./error.js";
|
|
6
6
|
|
|
@@ -8,15 +8,15 @@ import { trimStaleDeps, link, unobserved } from "./graph.js";
|
|
|
8
8
|
|
|
9
9
|
import { deleteFromHeap, queueFor, insertIntoHeapHeight, markNode, markHeap, insertIntoHeap } from "./heap.js";
|
|
10
10
|
|
|
11
|
-
import { GlobalQueue, activeTransition, globalQueue, clock, insertSubs, queuePendingNode,
|
|
11
|
+
import { GlobalQueue, activeTransition, globalQueue, clock, insertSubs, queuePendingNode, runInTransition, schedule, dirtyQueue, projectionWriteActive, armReaskClear } from "./scheduler.js";
|
|
12
12
|
|
|
13
13
|
import "./invariants.js";
|
|
14
14
|
|
|
15
15
|
import { disposeChildren, markDisposal, inheritId } from "./owner.js";
|
|
16
16
|
|
|
17
|
-
GlobalQueue.
|
|
17
|
+
GlobalQueue.pe = recompute;
|
|
18
18
|
|
|
19
|
-
GlobalQueue.
|
|
19
|
+
GlobalQueue.Ce = disposeChildren;
|
|
20
20
|
|
|
21
21
|
let tracking = false;
|
|
22
22
|
|
|
@@ -42,25 +42,14 @@ let context = null;
|
|
|
42
42
|
|
|
43
43
|
let currentOptimisticLane = null;
|
|
44
44
|
|
|
45
|
-
/**
|
|
46
|
-
* Marked sources read by the recompute currently on the stack (saved/restored
|
|
47
|
-
* per recompute, like `context`). A computed that reads a node with a live
|
|
48
|
-
* `affects()` mark inherits the mark's pendingness — `recompute` applies the
|
|
49
|
-
* collected sources through `applyAffectsReads` after its commit, because the
|
|
50
|
-
* `clearStatus` at the top of the commit path wipes whatever sentinel entries
|
|
51
|
-
* the node held from the registration-time push. This is the pull half of
|
|
52
|
-
* mark propagation (real async re-establishes itself by re-throwing on read;
|
|
53
|
-
* marks are value-transparent, so they re-establish here instead).
|
|
54
|
-
*/ let affectsReads = null;
|
|
55
|
-
|
|
56
45
|
let snapshotCaptureActive = false;
|
|
57
46
|
|
|
58
47
|
let snapshotSources = null;
|
|
59
48
|
|
|
60
49
|
function ownerInSnapshotScope(e) {
|
|
61
50
|
while (e) {
|
|
62
|
-
if (e.
|
|
63
|
-
e = e.
|
|
51
|
+
if (e.Oe) return true;
|
|
52
|
+
e = e.Ge;
|
|
64
53
|
}
|
|
65
54
|
return false;
|
|
66
55
|
}
|
|
@@ -71,41 +60,41 @@ function setSnapshotCapture(e) {
|
|
|
71
60
|
}
|
|
72
61
|
|
|
73
62
|
function markSnapshotScope(e) {
|
|
74
|
-
e.
|
|
63
|
+
e.Oe = true;
|
|
75
64
|
}
|
|
76
65
|
|
|
77
66
|
function releaseSnapshotScope(e) {
|
|
78
|
-
e.
|
|
67
|
+
e.Oe = false;
|
|
79
68
|
releaseSubtree(e);
|
|
80
69
|
schedule();
|
|
81
70
|
}
|
|
82
71
|
|
|
83
72
|
function releaseSubtree(e) {
|
|
84
|
-
let t = e.
|
|
73
|
+
let t = e.me;
|
|
85
74
|
while (t) {
|
|
86
|
-
if (t.
|
|
87
|
-
t = t.
|
|
75
|
+
if (t.Oe) {
|
|
76
|
+
t = t.ve;
|
|
88
77
|
continue;
|
|
89
78
|
}
|
|
90
|
-
if (t.
|
|
79
|
+
if (t.ke) {
|
|
91
80
|
const e = t;
|
|
92
|
-
e.
|
|
93
|
-
if (e.
|
|
94
|
-
e.
|
|
95
|
-
e.
|
|
96
|
-
if (dirtyQueue.
|
|
81
|
+
e.T &= ~CONFIG_IN_SNAPSHOT_SCOPE;
|
|
82
|
+
if (e.se & REACTIVE_SNAPSHOT_STALE) {
|
|
83
|
+
e.se &= ~REACTIVE_SNAPSHOT_STALE;
|
|
84
|
+
e.se |= REACTIVE_DIRTY;
|
|
85
|
+
if (dirtyQueue.Fe > e.He) dirtyQueue.Fe = e.He;
|
|
97
86
|
insertIntoHeap(e, dirtyQueue);
|
|
98
87
|
}
|
|
99
88
|
}
|
|
100
89
|
releaseSubtree(t);
|
|
101
|
-
t = t.
|
|
90
|
+
t = t.ve;
|
|
102
91
|
}
|
|
103
92
|
}
|
|
104
93
|
|
|
105
94
|
function clearSnapshots() {
|
|
106
95
|
if (snapshotSources) {
|
|
107
96
|
for (const e of snapshotSources) {
|
|
108
|
-
delete e.
|
|
97
|
+
delete e.Ve;
|
|
109
98
|
delete e[STORE_SNAPSHOT_PROPS];
|
|
110
99
|
}
|
|
111
100
|
snapshotSources = null;
|
|
@@ -114,105 +103,109 @@ function clearSnapshots() {
|
|
|
114
103
|
}
|
|
115
104
|
|
|
116
105
|
function recompute(e, t = false) {
|
|
117
|
-
const n = e.
|
|
106
|
+
const n = e.Ae;
|
|
118
107
|
if (!t) {
|
|
119
|
-
if (e.
|
|
108
|
+
if (e.Ue && (!n || activeTransition) && activeTransition !== e.Ue) globalQueue.initTransition(e.Ue);
|
|
120
109
|
deleteFromHeap(e, queueFor(e));
|
|
121
|
-
e.
|
|
110
|
+
e.Te = null;
|
|
122
111
|
// Tracked effects run after finalizePureQueue, so dispose immediately instead of deferring
|
|
123
|
-
if (e.
|
|
112
|
+
if (e.Ue || n === EFFECT_TRACKED) disposeChildren(e); else if (e.me !== null || e.xe !== null) {
|
|
124
113
|
markDisposal(e);
|
|
125
|
-
e.
|
|
126
|
-
e.
|
|
127
|
-
e.
|
|
128
|
-
e.
|
|
129
|
-
e.
|
|
114
|
+
e.ye = e.xe;
|
|
115
|
+
e.Le = e.me;
|
|
116
|
+
e.xe = null;
|
|
117
|
+
e.me = null;
|
|
118
|
+
e.Qe = 0;
|
|
130
119
|
} else ;
|
|
131
120
|
}
|
|
132
|
-
let i = !!(e.
|
|
133
|
-
const l = e.
|
|
134
|
-
const u = !!(e.
|
|
121
|
+
let i = !!(e.se & REACTIVE_OPTIMISTIC_DIRTY);
|
|
122
|
+
const l = e.Ee !== undefined && e.Ee !== NOT_PENDING;
|
|
123
|
+
const u = !!(e.S & STATUS_UNINITIALIZED);
|
|
135
124
|
// Re-ask classification lives in the verdict module; capture the flag before
|
|
136
125
|
// the recompute wipes _flags below.
|
|
137
|
-
const
|
|
138
|
-
const
|
|
126
|
+
const o = (e.se & REACTIVE_REASK) !== 0;
|
|
127
|
+
const s = context;
|
|
139
128
|
context = e;
|
|
140
|
-
e.
|
|
141
|
-
e.
|
|
142
|
-
e.
|
|
143
|
-
e.
|
|
144
|
-
let a = e.
|
|
145
|
-
let r = e.
|
|
129
|
+
e.qe = null;
|
|
130
|
+
e.Ye++;
|
|
131
|
+
e.se = REACTIVE_RECOMPUTING_DEPS;
|
|
132
|
+
e.ce = clock;
|
|
133
|
+
let a = e.Ne === NOT_PENDING ? e.Re : e.Ne;
|
|
134
|
+
let r = e.He;
|
|
146
135
|
let c = tracking;
|
|
147
|
-
|
|
148
|
-
affectsReads = null;
|
|
149
|
-
let f = null;
|
|
150
|
-
let E = currentOptimisticLane;
|
|
136
|
+
let _ = currentOptimisticLane;
|
|
151
137
|
tracking = true;
|
|
138
|
+
// A computed's fn establishes its OWN dependencies, so it must never run
|
|
139
|
+
// inside a latest() read window: read() short-circuits through the
|
|
140
|
+
// companion path before dependency linking, so a memo created (eagerly
|
|
141
|
+
// computed) inside latest(fn) came out permanently dependency-less (#2926).
|
|
142
|
+
// latestRead() already suspends the flag for its pull-recomputes; this
|
|
143
|
+
// covers creation-time computes and flushes that run inside the window.
|
|
144
|
+
const E = latestReadActive;
|
|
145
|
+
latestReadActive = false;
|
|
152
146
|
// Lane posture lives with the engine: OPTIMISTIC_DIRTY is only ever set by
|
|
153
147
|
// engine-driven paths, and _optimisticNodes is only pushed by
|
|
154
148
|
// _optimisticWrite, so the hook is installed whenever either gate holds.
|
|
155
149
|
if (i) {
|
|
156
|
-
const t = GlobalQueue
|
|
150
|
+
const t = GlobalQueue.We(e, true);
|
|
157
151
|
if (t) currentOptimisticLane = t;
|
|
158
|
-
} else if (activeTransition && !t && activeTransition.
|
|
152
|
+
} else if (activeTransition && !t && activeTransition.Ze.length) {
|
|
159
153
|
// Lane adoption: parent-deeper-than-owned-child can run before its OPT-dirty
|
|
160
154
|
// child propagates. Walk deps once and inherit the OPT lane so this node
|
|
161
155
|
// recomputes under the right posture and propagates correctly.
|
|
162
|
-
const t = GlobalQueue
|
|
156
|
+
const t = GlobalQueue.We(e, false);
|
|
163
157
|
if (t) {
|
|
164
158
|
i = true;
|
|
165
159
|
currentOptimisticLane = t;
|
|
166
160
|
}
|
|
167
161
|
}
|
|
168
|
-
const
|
|
169
|
-
const
|
|
170
|
-
if (
|
|
162
|
+
const f = n && n !== EFFECT_USER;
|
|
163
|
+
const N = stale;
|
|
164
|
+
if (f) stale = true;
|
|
171
165
|
try {
|
|
172
|
-
if (!false && e.
|
|
173
|
-
a = e.
|
|
174
|
-
e.
|
|
166
|
+
if (!false && e.T & CONFIG_SYNC) {
|
|
167
|
+
a = e.ke(a);
|
|
168
|
+
e.Te = null;
|
|
175
169
|
} else {
|
|
176
170
|
// Snapshot `_inFlight` so we can detect whether `_fn` self-registered an async
|
|
177
171
|
// subscription (e.g. `createProjection` calls `handleAsync` from inside its body
|
|
178
172
|
// with a setter callback). In that case, the outer `handleAsync` call below would
|
|
179
173
|
// clobber the fresh subscription, so we skip it and let the internally-registered
|
|
180
174
|
// iteration drive updates.
|
|
181
|
-
const t = e.
|
|
182
|
-
const n = e.
|
|
175
|
+
const t = e.Te;
|
|
176
|
+
const n = e.ke(a);
|
|
183
177
|
const i = typeof n === "object" && n !== null;
|
|
184
|
-
const l = e.
|
|
178
|
+
const l = e.Te !== t;
|
|
185
179
|
a = l || !i ? n : handleAsync(e, n);
|
|
186
|
-
if (!l && !i) e.
|
|
180
|
+
if (!l && !i) e.Te = null;
|
|
187
181
|
}
|
|
188
182
|
clearStatus(e, t);
|
|
189
183
|
// _optimisticLane is only ever assigned by engine paths.
|
|
190
|
-
if (e.
|
|
184
|
+
if (e.je) GlobalQueue.Me(e);
|
|
191
185
|
} catch (t) {
|
|
192
186
|
// Track pending async in the lane (not the lane's source — it creates the lane
|
|
193
187
|
// but doesn't belong to it). Set lane BEFORE notifyStatus for downstream propagation.
|
|
194
|
-
if (t instanceof NotReadyError && currentOptimisticLane) GlobalQueue.
|
|
188
|
+
if (t instanceof NotReadyError && currentOptimisticLane) GlobalQueue.Ke(e);
|
|
195
189
|
let n = false;
|
|
196
190
|
if (t instanceof NotReadyError) {
|
|
197
|
-
e.
|
|
198
|
-
if (GlobalQueue.
|
|
191
|
+
e.Se = true;
|
|
192
|
+
if (GlobalQueue.ze !== null) n = GlobalQueue.ze(e, o);
|
|
199
193
|
}
|
|
200
|
-
notifyStatus(e, t instanceof NotReadyError ? STATUS_PENDING : STATUS_ERROR, t, undefined, t instanceof NotReadyError ? e.
|
|
201
|
-
if (n) GlobalQueue.
|
|
194
|
+
notifyStatus(e, t instanceof NotReadyError ? STATUS_PENDING : STATUS_ERROR, t, undefined, t instanceof NotReadyError ? e.je : undefined);
|
|
195
|
+
if (n) GlobalQueue.k(e);
|
|
202
196
|
} finally {
|
|
203
197
|
tracking = c;
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
affectsReads = _;
|
|
198
|
+
latestReadActive = E;
|
|
199
|
+
if (f) stale = N;
|
|
200
|
+
e.se = REACTIVE_NONE | (t ? e.se & REACTIVE_SNAPSHOT_STALE : 0);
|
|
201
|
+
context = s;
|
|
209
202
|
}
|
|
210
|
-
if (!e.
|
|
203
|
+
if (!e._) {
|
|
211
204
|
trimStaleDeps(e);
|
|
212
|
-
const
|
|
213
|
-
let
|
|
205
|
+
const o = l ? unwrapOverride(e.Ee) : e.Ne === NOT_PENDING ? e.Re : e.Ne;
|
|
206
|
+
let s = false;
|
|
214
207
|
try {
|
|
215
|
-
|
|
208
|
+
s = !n && u || !e.Pe || !e.Pe(o, a);
|
|
216
209
|
} catch (t) {
|
|
217
210
|
// A throwing user comparator is an error of this node's computation.
|
|
218
211
|
// Route it through the same status path as a compute-phase throw so
|
|
@@ -225,124 +218,111 @@ function recompute(e, t = false) {
|
|
|
225
218
|
// its runner — happen here instead. `!create` matches the previous `initialized`
|
|
226
219
|
// gate: the explicit recompute(node, true) inside effect() does not enqueue, so
|
|
227
220
|
// effect() can call its runner synchronously for the first run.
|
|
228
|
-
if (n &&
|
|
229
|
-
e
|
|
221
|
+
if (n && s) {
|
|
222
|
+
e.$e = !e._;
|
|
230
223
|
// Reuse one bound runner per effect — runEffect no-ops on a stale
|
|
231
224
|
// `_modified`, so re-enqueueing the same function is harmless.
|
|
232
|
-
if (!t) e.
|
|
225
|
+
if (!t) e.C.enqueue(n, e.Be ??= GlobalQueue.Je.bind(null, e));
|
|
233
226
|
}
|
|
234
|
-
if (e.
|
|
235
|
-
const u = l ? e.
|
|
236
|
-
if (t || n && activeTransition !== e.
|
|
237
|
-
e.
|
|
227
|
+
if (e._) ; else if (s) {
|
|
228
|
+
const u = l ? e.Ee : undefined;
|
|
229
|
+
if (t || n && activeTransition !== e.Ue || i) {
|
|
230
|
+
e.Re = a;
|
|
238
231
|
// Lane-propagated correction: upstream data is fresh, correct the
|
|
239
232
|
// override unconditionally. The direct _value commit is the lane's
|
|
240
233
|
// own reveal schedule; drop any superseded older hold so its queued
|
|
241
234
|
// commit can't clobber the fresh value.
|
|
242
235
|
if (l && i) {
|
|
243
|
-
e.
|
|
244
|
-
e.
|
|
236
|
+
e.Ee = a === undefined ? OVERRIDE_UNDEFINED : a;
|
|
237
|
+
e.Ne = NOT_PENDING;
|
|
245
238
|
}
|
|
246
239
|
} else {
|
|
247
|
-
e.
|
|
240
|
+
e.Ne = a;
|
|
248
241
|
// Transition-held sync recompute is a write path like setSignal/asyncWrite,
|
|
249
242
|
// so sync derivations of held sources stay visible to isPending()/latest()
|
|
250
243
|
// (#2831). Both companion writes are transition-scoped (optimistic) and
|
|
251
244
|
// auto-revert/re-derive at commit. Skipped for plain flushes where the
|
|
252
245
|
// pending value commits before effects run.
|
|
253
|
-
if ((activeTransition || e.
|
|
246
|
+
if ((activeTransition || e.Ue) && GlobalQueue.Ie !== null) GlobalQueue.Ie(e, a);
|
|
254
247
|
}
|
|
255
|
-
if (!l || i || e.
|
|
248
|
+
if (!l || i || e.Ee !== u) insertSubs(e, i || l);
|
|
256
249
|
} else if (l) {
|
|
257
250
|
// Unchanged value (equals the override) recomputed while the override
|
|
258
251
|
// is active: _value may still be stale, so hold the authoritative value
|
|
259
252
|
// for commit on its own transition's schedule — invisibly (A17/A18).
|
|
260
|
-
if (e.
|
|
261
|
-
e.
|
|
262
|
-
} else if (e.
|
|
263
|
-
for (let t = e.
|
|
264
|
-
insertIntoHeapHeight(t.
|
|
253
|
+
if (e.Ne === NOT_PENDING) queuePendingNode(e);
|
|
254
|
+
e.Ne = a;
|
|
255
|
+
} else if (e.He != r) {
|
|
256
|
+
for (let t = e.o; t !== null; t = t.ue) {
|
|
257
|
+
insertIntoHeapHeight(t.le, queueFor(t.le));
|
|
265
258
|
}
|
|
266
259
|
}
|
|
267
260
|
}
|
|
268
|
-
currentOptimisticLane =
|
|
269
|
-
|
|
270
|
-
// earlier, the sentinel's NotReadyError in `_error` would have routed the
|
|
271
|
-
// fresh value into the error-skip branch instead of committing it. A real
|
|
272
|
-
// (non-NotReady) error wins over marks (#2893): applying the sentinel here
|
|
273
|
-
// would clobber the user's error with a NotReadyError from a node whose
|
|
274
|
-
// reads value-transparency promises can never throw NotReady.
|
|
275
|
-
// `markedReads` only collects under a live mark, so the hook is installed.
|
|
276
|
-
if (f && !(e.i & STATUS_ERROR)) GlobalQueue.j(e, f);
|
|
277
|
-
// Mark-only pending doesn't queue (#2893): the node holds no value needing
|
|
278
|
-
// a transition-scheduled commit, and queueing would stamp the marking
|
|
279
|
-
// action's transaction onto it — freezing unrelated writes that share it.
|
|
280
|
-
// (Single mask test up front keeps the mark-free hot path at original cost.)
|
|
281
|
-
const I = e.i & (STATUS_PENDING | STATUS_UNINITIALIZED);
|
|
282
|
-
const p = e.ge !== NOT_PENDING || e.Ze !== null || e.We !== null || I !== 0 && (I !== STATUS_PENDING || activeAffectsMarks === 0 || !GlobalQueue.$(e));
|
|
261
|
+
currentOptimisticLane = _;
|
|
262
|
+
const T = e.Ne !== NOT_PENDING || e.Le !== null || e.ye !== null || (e.S & (STATUS_PENDING | STATUS_UNINITIALIZED)) !== 0;
|
|
283
263
|
// Override-covered holds (hasOverride) always queue: their commit belongs
|
|
284
264
|
// to their own transition's schedule (A18 re-rule) and is unobservable
|
|
285
265
|
// under the override (A17). Revert no longer commits anything, so an
|
|
286
266
|
// unqueued covered hold would leak (INV-7) once the revert clears
|
|
287
267
|
// _transition.
|
|
288
|
-
|
|
289
|
-
e.
|
|
268
|
+
T && (!t || e.S & STATUS_PENDING) && (!e.Ue || l) && queuePendingNode(e);
|
|
269
|
+
e.Ue && n && activeTransition !== e.Ue && runInTransition(e.Ue, () => recompute(e));
|
|
290
270
|
}
|
|
291
271
|
|
|
292
272
|
function updateIfNecessary(e) {
|
|
293
|
-
if (e.
|
|
294
|
-
for (let t = e.
|
|
295
|
-
const n = t.
|
|
296
|
-
const i = n.
|
|
297
|
-
if (i.
|
|
273
|
+
if (e.se & REACTIVE_CHECK) {
|
|
274
|
+
for (let t = e.Xe; t; t = t.et) {
|
|
275
|
+
const n = t.tt;
|
|
276
|
+
const i = n.nt || n;
|
|
277
|
+
if (i.ke) {
|
|
298
278
|
updateIfNecessary(i);
|
|
299
279
|
}
|
|
300
|
-
if (e.
|
|
280
|
+
if (e.se & REACTIVE_DIRTY) {
|
|
301
281
|
break;
|
|
302
282
|
}
|
|
303
283
|
}
|
|
304
284
|
}
|
|
305
|
-
if (e.
|
|
285
|
+
if (e.se & (REACTIVE_DIRTY | REACTIVE_OPTIMISTIC_DIRTY) || e._ && e.ce < clock && !e.Te) {
|
|
306
286
|
recompute(e);
|
|
307
287
|
}
|
|
308
|
-
e.
|
|
288
|
+
e.se = e.se & (REACTIVE_SNAPSHOT_STALE | REACTIVE_IN_HEAP | REACTIVE_IN_HEAP_HEIGHT);
|
|
309
289
|
}
|
|
310
290
|
|
|
311
291
|
function computed(e, t) {
|
|
312
292
|
const n = t?.transparent ?? false;
|
|
313
293
|
const i = {
|
|
314
294
|
id: inheritId(t, n, context),
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
295
|
+
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),
|
|
296
|
+
Pe: t?.equals != null ? t.equals : isEqual,
|
|
297
|
+
it: t?.unobserved,
|
|
298
|
+
xe: null,
|
|
299
|
+
C: context?.C ?? globalQueue,
|
|
320
300
|
we: context?.we ?? defaultContext,
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
Ve: null,
|
|
335
|
-
Nt: null,
|
|
336
|
-
He: null,
|
|
337
|
-
u: t?.lazy ? REACTIVE_LAZY : REACTIVE_NONE,
|
|
338
|
-
i: STATUS_UNINITIALIZED,
|
|
339
|
-
Ie: clock,
|
|
340
|
-
ge: NOT_PENDING,
|
|
341
|
-
We: null,
|
|
342
|
-
Ze: null,
|
|
343
|
-
Ae: null,
|
|
301
|
+
Qe: 0,
|
|
302
|
+
ke: e,
|
|
303
|
+
Re: undefined,
|
|
304
|
+
He: 0,
|
|
305
|
+
u: null,
|
|
306
|
+
lt: undefined,
|
|
307
|
+
ut: null,
|
|
308
|
+
Xe: null,
|
|
309
|
+
qe: null,
|
|
310
|
+
Ye: 0,
|
|
311
|
+
o: null,
|
|
312
|
+
ot: null,
|
|
313
|
+
Ge: context,
|
|
344
314
|
ve: null,
|
|
345
|
-
|
|
315
|
+
st: null,
|
|
316
|
+
me: null,
|
|
317
|
+
se: t?.lazy ? REACTIVE_LAZY : REACTIVE_NONE,
|
|
318
|
+
S: STATUS_UNINITIALIZED,
|
|
319
|
+
ce: clock,
|
|
320
|
+
Ne: NOT_PENDING,
|
|
321
|
+
ye: null,
|
|
322
|
+
Le: null,
|
|
323
|
+
Te: null,
|
|
324
|
+
Ue: null,
|
|
325
|
+
be: false
|
|
346
326
|
};
|
|
347
327
|
setupComputedNode(i, t);
|
|
348
328
|
return i;
|
|
@@ -354,50 +334,50 @@ function computed(e, t) {
|
|
|
354
334
|
* mode (recompute is called explicitly by `effect()`), so we hardcode the lazy bits and skip
|
|
355
335
|
* the auto-dispose CONFIG bit (effect() previously cleared it post-construction).
|
|
356
336
|
*/ function createEffectNode(e, t, n, i, l, u) {
|
|
357
|
-
const
|
|
358
|
-
const
|
|
359
|
-
id: inheritId(u,
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
337
|
+
const o = u?.transparent ?? false;
|
|
338
|
+
const s = {
|
|
339
|
+
id: inheritId(u, o, context),
|
|
340
|
+
T: (o ? CONFIG_TRANSPARENT : 0) | (u?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (u?.sync ? CONFIG_SYNC : 0) | (snapshotCaptureActive && ownerInSnapshotScope(context) ? CONFIG_IN_SNAPSHOT_SCOPE : 0),
|
|
341
|
+
Pe: false,
|
|
342
|
+
it: u?.unobserved,
|
|
343
|
+
xe: null,
|
|
344
|
+
C: context?.C ?? globalQueue,
|
|
365
345
|
we: context?.we ?? defaultContext,
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
Ve: null,
|
|
380
|
-
Nt: null,
|
|
381
|
-
He: null,
|
|
382
|
-
u: REACTIVE_LAZY,
|
|
383
|
-
i: STATUS_UNINITIALIZED,
|
|
384
|
-
Ie: clock,
|
|
385
|
-
ge: NOT_PENDING,
|
|
386
|
-
We: null,
|
|
387
|
-
Ze: null,
|
|
388
|
-
Ae: null,
|
|
346
|
+
Qe: 0,
|
|
347
|
+
ke: e,
|
|
348
|
+
Re: undefined,
|
|
349
|
+
He: 0,
|
|
350
|
+
u: null,
|
|
351
|
+
lt: undefined,
|
|
352
|
+
ut: null,
|
|
353
|
+
Xe: null,
|
|
354
|
+
qe: null,
|
|
355
|
+
Ye: 0,
|
|
356
|
+
o: null,
|
|
357
|
+
ot: null,
|
|
358
|
+
Ge: context,
|
|
389
359
|
ve: null,
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
360
|
+
st: null,
|
|
361
|
+
me: null,
|
|
362
|
+
se: REACTIVE_LAZY,
|
|
363
|
+
S: STATUS_UNINITIALIZED,
|
|
364
|
+
ce: clock,
|
|
365
|
+
Ne: NOT_PENDING,
|
|
366
|
+
ye: null,
|
|
367
|
+
Le: null,
|
|
368
|
+
Te: null,
|
|
369
|
+
Ue: null,
|
|
370
|
+
be: false,
|
|
371
|
+
$e: false,
|
|
372
|
+
rt: undefined,
|
|
373
|
+
ct: t,
|
|
374
|
+
_t: n,
|
|
375
|
+
Et: undefined,
|
|
376
|
+
Ae: i,
|
|
377
|
+
i: l
|
|
398
378
|
};
|
|
399
|
-
setupComputedNode(
|
|
400
|
-
return
|
|
379
|
+
setupComputedNode(s, lazyOptions);
|
|
380
|
+
return s;
|
|
401
381
|
}
|
|
402
382
|
|
|
403
383
|
const lazyOptions = {
|
|
@@ -405,24 +385,24 @@ const lazyOptions = {
|
|
|
405
385
|
};
|
|
406
386
|
|
|
407
387
|
function setupComputedNode(e, t) {
|
|
408
|
-
e.
|
|
409
|
-
const n = context?.
|
|
388
|
+
e.ut = e;
|
|
389
|
+
const n = context?.ft ? context.Nt : context;
|
|
410
390
|
if (context) {
|
|
411
|
-
const t = context.
|
|
391
|
+
const t = context.me;
|
|
412
392
|
if (t === null) {
|
|
413
|
-
context.
|
|
393
|
+
context.me = e;
|
|
414
394
|
} else {
|
|
415
|
-
e.
|
|
416
|
-
t.
|
|
417
|
-
context.
|
|
395
|
+
e.ve = t;
|
|
396
|
+
t.st = e;
|
|
397
|
+
context.me = e;
|
|
418
398
|
}
|
|
419
399
|
}
|
|
420
|
-
if (n) e.
|
|
421
|
-
if (GlobalQueue.
|
|
400
|
+
if (n) e.He = n.He + 1;
|
|
401
|
+
if (GlobalQueue.Tt !== null) GlobalQueue.Tt(e);
|
|
422
402
|
!t?.lazy && recompute(e, true);
|
|
423
403
|
if (snapshotCaptureActive && !t?.lazy) {
|
|
424
|
-
if (!(e.
|
|
425
|
-
e.
|
|
404
|
+
if (!(e.S & STATUS_PENDING) && !(e.T & CONFIG_NO_SNAPSHOT)) {
|
|
405
|
+
e.Ve = e.Re === undefined ? NO_SNAPSHOT : e.Re;
|
|
426
406
|
snapshotSources.add(e);
|
|
427
407
|
}
|
|
428
408
|
}
|
|
@@ -430,20 +410,20 @@ function setupComputedNode(e, t) {
|
|
|
430
410
|
|
|
431
411
|
function signal(e, t, n = null) {
|
|
432
412
|
const i = {
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
413
|
+
Pe: t?.equals != null ? t.equals : isEqual,
|
|
414
|
+
T: (t?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (t?.V ? CONFIG_NO_SNAPSHOT : 0),
|
|
415
|
+
it: t?.unobserved,
|
|
416
|
+
Re: e,
|
|
417
|
+
o: null,
|
|
418
|
+
ot: null,
|
|
419
|
+
ce: clock,
|
|
420
|
+
nt: n,
|
|
421
|
+
fe: n?.u || null,
|
|
422
|
+
Ne: NOT_PENDING
|
|
443
423
|
};
|
|
444
|
-
n && (n.
|
|
445
|
-
if (snapshotCaptureActive && !(i.
|
|
446
|
-
i.
|
|
424
|
+
n && (n.u = i);
|
|
425
|
+
if (snapshotCaptureActive && !(i.T & CONFIG_NO_SNAPSHOT) && !((n?.S ?? 0) & STATUS_PENDING)) {
|
|
426
|
+
i.Ve = e === undefined ? NO_SNAPSHOT : e;
|
|
447
427
|
snapshotSources.add(i);
|
|
448
428
|
}
|
|
449
429
|
return i;
|
|
@@ -451,13 +431,13 @@ function signal(e, t, n = null) {
|
|
|
451
431
|
|
|
452
432
|
function optimisticSignal(e, t) {
|
|
453
433
|
const n = signal(e, t);
|
|
454
|
-
n.
|
|
434
|
+
n.Ee = NOT_PENDING;
|
|
455
435
|
return n;
|
|
456
436
|
}
|
|
457
437
|
|
|
458
438
|
function optimisticComputed(e, t) {
|
|
459
439
|
const n = computed(e, t);
|
|
460
|
-
n.
|
|
440
|
+
n.Ee = NOT_PENDING;
|
|
461
441
|
return n;
|
|
462
442
|
}
|
|
463
443
|
|
|
@@ -487,11 +467,11 @@ function isEqual(e, t) {
|
|
|
487
467
|
* );
|
|
488
468
|
* ```
|
|
489
469
|
*/ function untrack(e, t) {
|
|
490
|
-
if (GlobalQueue.
|
|
470
|
+
if (GlobalQueue.It === null && !tracking && true) return e();
|
|
491
471
|
const n = tracking;
|
|
492
472
|
tracking = false;
|
|
493
473
|
try {
|
|
494
|
-
if (GlobalQueue.
|
|
474
|
+
if (GlobalQueue.It !== null) return GlobalQueue.It(e);
|
|
495
475
|
return e();
|
|
496
476
|
} finally {
|
|
497
477
|
tracking = n;
|
|
@@ -503,10 +483,10 @@ function isEqual(e, t) {
|
|
|
503
483
|
* an isPending() probe (`refresh`) additionally pulls the node fully up to
|
|
504
484
|
* date so its status flags reflect the current graph.
|
|
505
485
|
*/ function prepareComputed(e, t) {
|
|
506
|
-
if (e.
|
|
507
|
-
e.
|
|
486
|
+
if (e.se & REACTIVE_LAZY) {
|
|
487
|
+
e.se &= ~REACTIVE_LAZY;
|
|
508
488
|
recompute(e, true);
|
|
509
|
-
} else if (e.
|
|
489
|
+
} else if (e.se & REACTIVE_DISPOSED) {
|
|
510
490
|
recompute(e, true);
|
|
511
491
|
} else if (t) {
|
|
512
492
|
updateIfNecessary(e);
|
|
@@ -518,101 +498,78 @@ function read(e) {
|
|
|
518
498
|
// Checked before isPending so that isPending(() => latest(x)) checks
|
|
519
499
|
// the _pendingSignal of _latestValueComputed (async in flight) rather
|
|
520
500
|
// than the original node (which stays "pending" while held in a transition).
|
|
521
|
-
if (latestReadActive) return GlobalQueue.
|
|
501
|
+
if (latestReadActive) return GlobalQueue.St(e);
|
|
522
502
|
let t = context;
|
|
523
|
-
if (t?.
|
|
503
|
+
if (t?.ft) t = t.Nt;
|
|
524
504
|
const n = e;
|
|
525
|
-
const i = e.
|
|
505
|
+
const i = e.nt;
|
|
526
506
|
const l = i || e;
|
|
527
507
|
// Handle isPending() mode: collect pending state while preserving normal read semantics.
|
|
528
508
|
// Probe mode is suspended while preparing the node so nested reads during a
|
|
529
509
|
// recompute don't collect into the probe.
|
|
530
510
|
if (pendingCheckActive) {
|
|
531
|
-
GlobalQueue.
|
|
532
|
-
} else if (typeof n.
|
|
511
|
+
GlobalQueue.dt(e, t, l, i);
|
|
512
|
+
} else if (typeof n.ke === "function") {
|
|
533
513
|
prepareComputed(e, false);
|
|
534
514
|
}
|
|
535
|
-
if (!n.
|
|
536
|
-
if (t && tracking)
|
|
537
|
-
|
|
538
|
-
// A live mark on a read source flows to the reader (probe reads are
|
|
539
|
-
// excluded: the probe's own collection owns that verdict, and marking
|
|
540
|
-
// the enclosing memo would make an `isPending` wrapper itself pending).
|
|
541
|
-
if (activeAffectsMarks !== 0 && e.M && !pendingCheckActive) (affectsReads ??= []).push(e);
|
|
542
|
-
}
|
|
543
|
-
return !t || e.ge === NOT_PENDING ? e.Ue : e.ge;
|
|
515
|
+
if (!n.ke && l === e && e.Ee === undefined && e.Ve === undefined && activeTransition === null && currentOptimisticLane === null && !snapshotCaptureActive && true) {
|
|
516
|
+
if (t && tracking) link(e, t);
|
|
517
|
+
return !t || e.Ne === NOT_PENDING ? e.Re : e.Ne;
|
|
544
518
|
}
|
|
545
519
|
if (t && tracking) {
|
|
546
520
|
link(e, t, pendingCheckActive);
|
|
547
|
-
|
|
548
|
-
// transitive half (#2893): a mark-pended owner's sentinel sources flow to
|
|
549
|
-
// the reader like a direct mark — value-transparent reads have no throw
|
|
550
|
-
// to re-establish through, so without this a mid-window recompute sheds
|
|
551
|
-
// pendingness permanently past one derivation level.
|
|
552
|
-
if (activeAffectsMarks !== 0 && !pendingCheckActive) {
|
|
553
|
-
if (e.M) (affectsReads ??= []).push(e);
|
|
554
|
-
if (l.i & STATUS_PENDING) GlobalQueue.I(l, affectsReads ??= []);
|
|
555
|
-
}
|
|
556
|
-
if (l.xe) {
|
|
521
|
+
if (l.ke) {
|
|
557
522
|
const n = queueFor(e);
|
|
558
|
-
if (l.
|
|
523
|
+
if (l.He >= n.Fe) {
|
|
559
524
|
markNode(t);
|
|
560
525
|
markHeap(n);
|
|
561
526
|
updateIfNecessary(l);
|
|
562
527
|
}
|
|
563
|
-
const i = l.
|
|
528
|
+
const i = l.He;
|
|
564
529
|
// parent check is shallow, might need to be recursive
|
|
565
|
-
if (i >= t.
|
|
566
|
-
t.
|
|
530
|
+
if (i >= t.He && e.Ge !== t) {
|
|
531
|
+
t.He = i + 1;
|
|
567
532
|
}
|
|
568
533
|
}
|
|
569
534
|
}
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
// pending sources are mark sentinels keeps its real value readable —
|
|
573
|
-
// pendingness reaches readers through verdicts (isPending), not throws.
|
|
574
|
-
// (`activeAffectsMarks` gates the source scan off the mark-free hot path;
|
|
575
|
-
// sentinels can't survive in pending sources past their last release.)
|
|
576
|
-
if (l.i & STATUS_PENDING && !(activeAffectsMarks !== 0 && GlobalQueue.$(l))) {
|
|
577
|
-
if (t && !(stale && l.ve && activeTransition !== l.ve)) {
|
|
535
|
+
if (l.S & STATUS_PENDING) {
|
|
536
|
+
if (t && !(stale && l.Ue && activeTransition !== l.Ue)) {
|
|
578
537
|
// Per-lane suspension lives with the engine (a non-null lane implies it
|
|
579
538
|
// is installed): under a lane, only same-lane pending async without an
|
|
580
539
|
// active override throws.
|
|
581
|
-
if (currentOptimisticLane === null || GlobalQueue.
|
|
540
|
+
if (currentOptimisticLane === null || GlobalQueue.At(l)) {
|
|
582
541
|
if (!tracking && e !== t) link(e, t);
|
|
583
|
-
throw l.
|
|
542
|
+
throw l._;
|
|
584
543
|
}
|
|
585
|
-
} else if (t && l !== e && l.
|
|
544
|
+
} else if (t && l !== e && l.S & STATUS_UNINITIALIZED) {
|
|
586
545
|
if (!tracking && e !== t) link(e, t);
|
|
587
|
-
throw l.
|
|
588
|
-
} else if (!t && l.
|
|
589
|
-
throw l.
|
|
546
|
+
throw l._;
|
|
547
|
+
} else if (!t && l.S & STATUS_UNINITIALIZED) {
|
|
548
|
+
throw l._;
|
|
590
549
|
}
|
|
591
550
|
}
|
|
592
|
-
if (e.
|
|
551
|
+
if (e.ke && e.S & STATUS_ERROR) {
|
|
593
552
|
// Only a genuine reactive re-read may retry an errored async source:
|
|
594
553
|
// - tracking: owned/tracked scope only (never events / `untrack` / effect side-effect phase)
|
|
595
554
|
// - !pendingCheckActive: an `isPending` probe observes the error, never refetches
|
|
596
555
|
// - el._time < clock: only on a later cycle than the one the error was found
|
|
597
|
-
if (tracking && !pendingCheckActive && e.
|
|
556
|
+
if (tracking && !pendingCheckActive && e.ce < clock) {
|
|
598
557
|
recompute(e);
|
|
599
558
|
return read(e);
|
|
600
|
-
} else throw e.
|
|
559
|
+
} else throw e._;
|
|
601
560
|
}
|
|
602
|
-
if (snapshotCaptureActive && t && t.
|
|
603
|
-
const n = e.
|
|
561
|
+
if (snapshotCaptureActive && t && t.T & CONFIG_IN_SNAPSHOT_SCOPE) {
|
|
562
|
+
const n = e.Ve;
|
|
604
563
|
if (n !== undefined) {
|
|
605
564
|
const i = n === NO_SNAPSHOT ? undefined : n;
|
|
606
|
-
const l = e.
|
|
607
|
-
if (l !== i) t.
|
|
565
|
+
const l = e.Ne !== NOT_PENDING ? e.Ne : e.Re;
|
|
566
|
+
if (l !== i) t.se |= REACTIVE_SNAPSHOT_STALE;
|
|
608
567
|
return i;
|
|
609
568
|
}
|
|
610
569
|
}
|
|
611
|
-
if (e.
|
|
612
|
-
//
|
|
613
|
-
|
|
614
|
-
if (t && stale && GlobalQueue.Dt(e)) return e.Ue;
|
|
615
|
-
return unwrapOverride(e.be);
|
|
570
|
+
if (e.Ee !== undefined && e.Ee !== NOT_PENDING) {
|
|
571
|
+
// A17: the override IS the value for every reader.
|
|
572
|
+
return unwrapOverride(e.Ee);
|
|
616
573
|
}
|
|
617
574
|
// Entanglement gate: a reader recomputing under an optimistic lane that reads
|
|
618
575
|
// a pending mid-transition write sees the committed value. Projection-store
|
|
@@ -621,40 +578,40 @@ function read(e) {
|
|
|
621
578
|
// _pendingValue for correct fetching. The sub is recorded for replay at commit
|
|
622
579
|
// so it re-runs with the new committed view. (Gate details live with the
|
|
623
580
|
// engine — a non-null lane implies it is installed.)
|
|
624
|
-
if (currentOptimisticLane !== null && activeTransition !== null && t !== null && GlobalQueue.
|
|
625
|
-
return e.
|
|
581
|
+
if (currentOptimisticLane !== null && activeTransition !== null && t !== null && GlobalQueue.Ct(e, l, t)) {
|
|
582
|
+
return e.Re;
|
|
626
583
|
}
|
|
627
584
|
// In optimistic lane context, return _value for optimistic/lane-assigned signals
|
|
628
585
|
// and for regular signals in stale mode (render effects). Non-stale readers (user
|
|
629
586
|
// effects) see _pendingValue so that latest() and direct reads stay consistent.
|
|
630
587
|
// (The lane-context clause lives with the engine.)
|
|
631
|
-
const u = !t || currentOptimisticLane !== null && GlobalQueue.
|
|
588
|
+
const u = !t || currentOptimisticLane !== null && GlobalQueue.Ot(e, l, t) || e.Ne === NOT_PENDING || stale && e.Ue && activeTransition !== e.Ue ? e.Re : e.Ne;
|
|
632
589
|
// Record that this isPending() probe observed the fresh pending value, so
|
|
633
590
|
// the probe doesn't pair "pending" with the new value (#2831).
|
|
634
|
-
if (pendingCheckActive) GlobalQueue.
|
|
635
|
-
if (!t && l === e && typeof n.
|
|
591
|
+
if (pendingCheckActive) GlobalQueue.Rt(e, u);
|
|
592
|
+
if (!t && l === e && typeof n.ke === "function" && e.T & CONFIG_AUTO_DISPOSE && !(l.S & STATUS_PENDING) && !e.o) {
|
|
636
593
|
unobserved(e);
|
|
637
594
|
}
|
|
638
595
|
return u;
|
|
639
596
|
}
|
|
640
597
|
|
|
641
598
|
function setSignal(e, t) {
|
|
642
|
-
if (e.
|
|
599
|
+
if (e.Ue && activeTransition !== e.Ue) globalQueue.initTransition(e.Ue);
|
|
643
600
|
// The optimistic write path lives with the engine: only optimisticSignal /
|
|
644
601
|
// optimisticComputed callers and optimistic store nodes carry an
|
|
645
602
|
// _overrideValue slot, and every module that creates one installs the
|
|
646
603
|
// engine first.
|
|
647
|
-
if (e.
|
|
648
|
-
const n = e.
|
|
604
|
+
if (e.Ee !== undefined && !projectionWriteActive) return GlobalQueue.Pt(e, t);
|
|
605
|
+
const n = e.Ne === NOT_PENDING ? e.Re : e.Ne;
|
|
649
606
|
if (typeof t === "function") t = t(n);
|
|
650
607
|
// Uninitialized check first: the first commit has no previous value, so the
|
|
651
608
|
// user comparator must not run against `undefined` (matches recompute).
|
|
652
|
-
const i = !!(e.
|
|
609
|
+
const i = !!(e.S & STATUS_UNINITIALIZED) || !e.Pe || !e.Pe(n, t);
|
|
653
610
|
if (!i) return t;
|
|
654
|
-
if (e.
|
|
655
|
-
e.
|
|
656
|
-
GlobalQueue.
|
|
657
|
-
e.
|
|
611
|
+
if (e.Ne === NOT_PENDING) queuePendingNode(e);
|
|
612
|
+
e.Ne = t;
|
|
613
|
+
GlobalQueue.Ie !== null && GlobalQueue.Ie(e, t);
|
|
614
|
+
e.ce = clock;
|
|
658
615
|
insertSubs(e);
|
|
659
616
|
schedule();
|
|
660
617
|
return t;
|
|
@@ -668,11 +625,11 @@ function setSignal(e, t) {
|
|
|
668
625
|
* cleanup point.
|
|
669
626
|
*/ function suppressComputedRecompute(e) {
|
|
670
627
|
deleteFromHeap(e, queueFor(e));
|
|
671
|
-
if (!(e.
|
|
628
|
+
if (!(e.se & REACTIVE_MANUAL_WRITE) && e.Ne === NOT_PENDING) {
|
|
672
629
|
queuePendingNode(e);
|
|
673
630
|
schedule();
|
|
674
631
|
}
|
|
675
|
-
e.
|
|
632
|
+
e.se = e.se & -4 | REACTIVE_MANUAL_WRITE;
|
|
676
633
|
}
|
|
677
634
|
|
|
678
635
|
/**
|
|
@@ -751,7 +708,7 @@ function staleValues(e, t = true) {
|
|
|
751
708
|
if (!t) {
|
|
752
709
|
return;
|
|
753
710
|
}
|
|
754
|
-
if (typeof t.
|
|
711
|
+
if (typeof t.ke === "function" && !(t.se & (REACTIVE_DISPOSED | REACTIVE_MANUAL_WRITE))) {
|
|
755
712
|
// A refresh with no value-change dirt already queued is a re-ask of the
|
|
756
713
|
// same question: mark it so the recompute classifies any resulting
|
|
757
714
|
// pending window as quiet (not pending). If the node is already dirty
|
|
@@ -759,11 +716,11 @@ function staleValues(e, t = true) {
|
|
|
759
716
|
// REACTIVE_IN_HEAP counts as dirt: insertSubs schedules subscribers by
|
|
760
717
|
// heap insertion alone (no DIRTY/CHECK flag), so a same-batch value
|
|
761
718
|
// change followed by refresh() must not be laundered into a quiet re-ask.
|
|
762
|
-
if (!(t.
|
|
763
|
-
t.
|
|
719
|
+
if (!(t.se & (REACTIVE_DIRTY | REACTIVE_CHECK | REACTIVE_IN_HEAP))) {
|
|
720
|
+
t.se |= REACTIVE_REASK;
|
|
764
721
|
armReaskClear();
|
|
765
722
|
}
|
|
766
|
-
t.
|
|
723
|
+
t.se = t.se & ~REACTIVE_CHECK | REACTIVE_DIRTY;
|
|
767
724
|
insertIntoHeap(t, queueFor(t));
|
|
768
725
|
schedule();
|
|
769
726
|
}
|