@solidjs/signals 2.0.0-rc.4 → 2.0.0-rc.5
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 +1169 -186
- package/dist/node.cjs +2041 -1167
- package/dist/prod/boundaries.js +4 -1
- package/dist/prod/core/async.js +124 -95
- package/dist/prod/core/constants.js +55 -1
- package/dist/prod/core/core.js +297 -222
- package/dist/prod/core/effect.js +28 -28
- package/dist/prod/core/error.js +13 -1
- package/dist/prod/core/external.js +2 -2
- package/dist/prod/core/graph.js +27 -27
- package/dist/prod/core/heap.js +30 -30
- package/dist/prod/core/lanes.js +32 -32
- package/dist/prod/core/optimistic.js +54 -54
- package/dist/prod/core/owner.js +34 -34
- package/dist/prod/core/scheduler.js +318 -137
- package/dist/prod/core/verdict.js +112 -59
- package/dist/prod/index.js +3 -3
- package/dist/prod/map.js +106 -106
- package/dist/prod/signals.js +253 -25
- package/dist/prod/store/next/optimistic.js +262 -123
- package/dist/prod/store/next/patch.js +6 -6
- package/dist/prod/store/next/projection.js +23 -19
- package/dist/prod/store/next/store.js +129 -35
- package/dist/prod/store/store.js +2 -2
- package/dist/types/core/async.d.ts +2 -0
- package/dist/types/core/attribution.d.ts +9 -4
- package/dist/types/core/constants.d.ts +54 -0
- package/dist/types/core/core.d.ts +19 -20
- package/dist/types/core/error.d.ts +9 -0
- package/dist/types/core/index.d.ts +2 -2
- package/dist/types/core/scheduler.d.ts +34 -0
- package/dist/types/core/types.d.ts +12 -0
- package/dist/types/index.d.ts +3 -3
- package/dist/types/signals.d.ts +108 -0
- package/dist/types/store/next/optimistic.d.ts +13 -10
- package/dist/types/store/next/projection.d.ts +1 -1
- package/dist/types/store/next/store.d.ts +22 -0
- package/dist/types/store/next/target.d.ts +15 -0
- package/dist/types-cjs/core/async.d.cts +2 -0
- package/dist/types-cjs/core/attribution.d.cts +9 -4
- package/dist/types-cjs/core/constants.d.cts +54 -0
- package/dist/types-cjs/core/core.d.cts +19 -20
- package/dist/types-cjs/core/error.d.cts +9 -0
- package/dist/types-cjs/core/index.d.cts +2 -2
- package/dist/types-cjs/core/scheduler.d.cts +34 -0
- package/dist/types-cjs/core/types.d.cts +12 -0
- package/dist/types-cjs/index.d.cts +3 -3
- package/dist/types-cjs/signals.d.cts +108 -0
- package/dist/types-cjs/store/next/optimistic.d.cts +13 -10
- package/dist/types-cjs/store/next/projection.d.cts +1 -1
- package/dist/types-cjs/store/next/store.d.cts +22 -0
- package/dist/types-cjs/store/next/target.d.cts +15 -0
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NOT_PENDING, REACTIVE_DISPOSED, REACTIVE_DIRTY, REACTIVE_CHECK, unwrapOverride, REACTIVE_ZOMBIE, STATUS_UNINITIALIZED, STATUS_PENDING, REACTIVE_OPTIMISTIC_DIRTY, REACTIVE_MANUAL_WRITE, CONFIG_HAS_COMPANIONS, CONFIG_CHILD_COMPANIONS, STATUS_ERROR, REACTIVE_RECOMPUTING_DEPS } from "./constants.js";
|
|
2
2
|
|
|
3
|
-
import { setSignal, prepareComputed, read, context, stale, currentOptimisticLane, tracking, ext, setLatestReadActive, setContextInternal, optimisticComputed,
|
|
3
|
+
import { setSignal, pendingCheckActive, setPendingCheckActive, prepareComputed, read, context, stale, currentOptimisticLane, tracking, ext, setLatestReadActive, setContextInternal, optimisticComputed, latestReadActive, optimisticSignal } from "./core.js";
|
|
4
4
|
|
|
5
5
|
import { NotReadyError } from "./error.js";
|
|
6
6
|
|
|
@@ -47,23 +47,23 @@ let pendingProbe = null;
|
|
|
47
47
|
* O(all-leaves-ever-read)-per-update pathology). Entries are permanent like
|
|
48
48
|
* the companions themselves; a store with no leaf-level isPending()/latest()
|
|
49
49
|
* reads never allocates the set or pays the walk. */ function markFirewallChildCompanions(e) {
|
|
50
|
-
const t = e.
|
|
50
|
+
const t = e.st;
|
|
51
51
|
if (!t) return;
|
|
52
52
|
t.T |= CONFIG_CHILD_COMPANIONS;
|
|
53
|
-
(ext(t).
|
|
53
|
+
(ext(t).St ??= new Set).add(e);
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
function getPendingSignal(e) {
|
|
57
|
-
let t = e.o?.
|
|
57
|
+
let t = e.o?.ye;
|
|
58
58
|
if (!t) {
|
|
59
59
|
// Start false, write true if pending - ensures reversion returns to false
|
|
60
60
|
t = optimisticSignal(false, {
|
|
61
61
|
ownedWrite: true
|
|
62
62
|
});
|
|
63
|
-
ext(e).
|
|
63
|
+
ext(e).ye = t;
|
|
64
64
|
e.T |= CONFIG_HAS_COMPANIONS;
|
|
65
65
|
markFirewallChildCompanions(e);
|
|
66
|
-
ext(t).
|
|
66
|
+
ext(t).Tt = e;
|
|
67
67
|
if (computePendingState(e)) setSignal(t, true);
|
|
68
68
|
}
|
|
69
69
|
return t;
|
|
@@ -72,7 +72,7 @@ function getPendingSignal(e) {
|
|
|
72
72
|
function collectPendingSources(e) {
|
|
73
73
|
if (!pendingProbe) return;
|
|
74
74
|
pendingProbe.sources.add(e);
|
|
75
|
-
const t = e.
|
|
75
|
+
const t = e.st || e;
|
|
76
76
|
if (t !== e) pendingProbe.sources.add(t);
|
|
77
77
|
}
|
|
78
78
|
|
|
@@ -105,17 +105,17 @@ function collectPendingSources(e) {
|
|
|
105
105
|
if (e.S & STATUS_ERROR) return false;
|
|
106
106
|
if (t.has(e)) return false;
|
|
107
107
|
t.add(e);
|
|
108
|
-
const n = e.
|
|
108
|
+
const n = e.st;
|
|
109
109
|
if (n && markWalk(n, t)) return true;
|
|
110
110
|
// Mid-recompute (the clearStatus companion poke runs before
|
|
111
111
|
// trimStaleDeps), only the validated prefix [_deps.._depsTail] is this
|
|
112
112
|
// pass's dependency set — walking past it would read dropped deps and
|
|
113
113
|
// latch a stale verdict on the companion.
|
|
114
114
|
const i = e;
|
|
115
|
-
const r = i.ie & REACTIVE_RECOMPUTING_DEPS ? i.
|
|
115
|
+
const r = i.ie & REACTIVE_RECOMPUTING_DEPS ? i.je : undefined;
|
|
116
116
|
if (r !== null) {
|
|
117
|
-
for (let e = i.
|
|
118
|
-
if (!e.
|
|
117
|
+
for (let e = i.ut ?? null; e !== null; e = e.lt) {
|
|
118
|
+
if (!e.ve && markWalk(e.ot, t)) return true;
|
|
119
119
|
if (e === r) break;
|
|
120
120
|
}
|
|
121
121
|
}
|
|
@@ -128,10 +128,10 @@ function collectPendingSources(e) {
|
|
|
128
128
|
|
|
129
129
|
function quietPending(e) {
|
|
130
130
|
if (e.o?.le) {
|
|
131
|
-
for (const t of e.o.le) if (!t.o?.
|
|
131
|
+
for (const t of e.o.le) if (!t.o?.Ge) return false;
|
|
132
132
|
return true;
|
|
133
133
|
}
|
|
134
|
-
return e.o?.
|
|
134
|
+
return e.o?.Ge ?? false;
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
// NOTE: a loadingValue node's open loading window (_loading) is verdict-quiet
|
|
@@ -152,40 +152,40 @@ function computePendingState(e) {
|
|
|
152
152
|
// reaches its owner (and a store leaf its firewall) through its own deps,
|
|
153
153
|
// so the one walk covers direct marks, derivation, and companion chains.
|
|
154
154
|
if (markCovered(e)) return true;
|
|
155
|
-
const n = e.
|
|
156
|
-
if (e.o?.
|
|
157
|
-
const t = e.o?.
|
|
158
|
-
const n = t.
|
|
155
|
+
const n = e.st;
|
|
156
|
+
if (e.o?.Tt) {
|
|
157
|
+
const t = e.o?.Tt;
|
|
158
|
+
const n = t.st || t;
|
|
159
159
|
return newQuestionInFlight(n);
|
|
160
160
|
}
|
|
161
161
|
if (n && e.Pe !== NOT_PENDING && !hasActiveOverride(e)) {
|
|
162
|
-
return !!(n.ie & REACTIVE_MANUAL_WRITE) || !n.o?.
|
|
162
|
+
return !!(n.ie & REACTIVE_MANUAL_WRITE) || !n.o?.Ie && !(n.S & STATUS_PENDING) || !!(n.S & STATUS_PENDING) && quietPending(n);
|
|
163
163
|
}
|
|
164
164
|
// `!comp._loading`: a hold created while the loading window is still open is
|
|
165
165
|
// the window's own landing in flight to its commit — verdict-quiet like the
|
|
166
166
|
// rest of the window (the UNINITIALIZED check suppresses exactly this frame
|
|
167
167
|
// for windowless first loads; born-committed nodes need their own gate, #2990).
|
|
168
|
-
if (e.Pe !== NOT_PENDING && !(t.S & STATUS_UNINITIALIZED) && !t.
|
|
169
|
-
if (hasActiveOverride(e)) return !e.
|
|
168
|
+
if (e.Pe !== NOT_PENDING && !(t.S & STATUS_UNINITIALIZED) && !t.Ne) {
|
|
169
|
+
if (hasActiveOverride(e)) return !e.ge || !e.ge(e.Pe, unwrapOverride(e.o?.Oe));
|
|
170
170
|
return true;
|
|
171
171
|
}
|
|
172
172
|
return newQuestionInFlight(t);
|
|
173
173
|
}
|
|
174
174
|
|
|
175
175
|
function syncCompanions(e, t) {
|
|
176
|
-
if (e.o?.
|
|
177
|
-
if (e.o?.
|
|
176
|
+
if (e.o?.ye) updatePendingSignal(e);
|
|
177
|
+
if (e.o?.Ce) setSignal(e.o?.Ce, t);
|
|
178
178
|
}
|
|
179
179
|
|
|
180
180
|
function updatePendingSignal(e) {
|
|
181
|
-
if (e.o?.
|
|
182
|
-
setSignal(e.o?.
|
|
181
|
+
if (e.o?.ye) {
|
|
182
|
+
setSignal(e.o?.ye, computePendingState(e));
|
|
183
183
|
}
|
|
184
|
-
if (e.o?.
|
|
184
|
+
if (e.o?.Ce) updatePendingSignal(e.o?.Ce);
|
|
185
185
|
}
|
|
186
186
|
|
|
187
187
|
function updateChildCompanions(e) {
|
|
188
|
-
const t = e.o?.
|
|
188
|
+
const t = e.o?.St;
|
|
189
189
|
if (t === undefined) return;
|
|
190
190
|
for (const e of t) updatePendingSignal(e);
|
|
191
191
|
}
|
|
@@ -204,7 +204,7 @@ function updateChildCompanions(e) {
|
|
|
204
204
|
const visit = e => {
|
|
205
205
|
if (i.has(e)) return;
|
|
206
206
|
i.add(e);
|
|
207
|
-
if (e.o?.
|
|
207
|
+
if (e.o?.ye || e.o?.Ce) n(e);
|
|
208
208
|
for (let t = e.u; t !== null; t = t.ae) visit(t.ce);
|
|
209
209
|
for (let t = e.o?.i ?? null; t !== null; t = t.Se) {
|
|
210
210
|
visit(t);
|
|
@@ -227,7 +227,7 @@ function updateChildCompanions(e) {
|
|
|
227
227
|
if (suppressedProbes.size === 0) return;
|
|
228
228
|
let t = false;
|
|
229
229
|
for (const [n, i] of suppressedProbes) {
|
|
230
|
-
const r = n.
|
|
230
|
+
const r = n.Ae;
|
|
231
231
|
const s = r ? currentTransition(r) : null;
|
|
232
232
|
if (!s) {
|
|
233
233
|
suppressedProbes.delete(n);
|
|
@@ -235,11 +235,11 @@ function updateChildCompanions(e) {
|
|
|
235
235
|
}
|
|
236
236
|
if (s !== e) continue;
|
|
237
237
|
suppressedProbes.delete(n);
|
|
238
|
-
const o = n.o?.
|
|
238
|
+
const o = n.o?.ye?.o?.Je;
|
|
239
239
|
for (const e of i) {
|
|
240
240
|
if (e.ie & REACTIVE_DISPOSED) continue;
|
|
241
241
|
e.ie |= REACTIVE_OPTIMISTIC_DIRTY;
|
|
242
|
-
if (o) assignOrMergeLane(e, o); else if (e.o !== null) e.o.
|
|
242
|
+
if (o) assignOrMergeLane(e, o); else if (e.o !== null) e.o.Je = undefined;
|
|
243
243
|
enqueueSub(e);
|
|
244
244
|
t = true;
|
|
245
245
|
}
|
|
@@ -249,8 +249,8 @@ function updateChildCompanions(e) {
|
|
|
249
249
|
|
|
250
250
|
function snapCompanionsToState(e) {
|
|
251
251
|
suppressedProbes.size !== 0 && suppressedProbes.delete(e);
|
|
252
|
-
const t = e.o?.
|
|
253
|
-
if (t && (t.o?.
|
|
252
|
+
const t = e.o?.ye;
|
|
253
|
+
if (t && (t.o?.Oe === undefined || t.o?.Oe === NOT_PENDING)) {
|
|
254
254
|
const n = computePendingState(e);
|
|
255
255
|
if (t.be !== n || t.Pe !== NOT_PENDING) {
|
|
256
256
|
t.be = n;
|
|
@@ -259,9 +259,9 @@ function snapCompanionsToState(e) {
|
|
|
259
259
|
schedule();
|
|
260
260
|
}
|
|
261
261
|
}
|
|
262
|
-
const n = e.o?.
|
|
262
|
+
const n = e.o?.Ce;
|
|
263
263
|
if (n && !(n.ie & REACTIVE_DISPOSED)) {
|
|
264
|
-
if ((n.o?.
|
|
264
|
+
if ((n.o?.Oe === undefined || n.o?.Oe === NOT_PENDING) && n.Pe === NOT_PENDING && !Object.is(n.be, e.be) && !(n.ie & (REACTIVE_DIRTY | REACTIVE_CHECK))) {
|
|
265
265
|
n.ie |= REACTIVE_DIRTY;
|
|
266
266
|
insertIntoHeap(n, queueFor(n));
|
|
267
267
|
insertSubs(n);
|
|
@@ -272,7 +272,7 @@ function snapCompanionsToState(e) {
|
|
|
272
272
|
}
|
|
273
273
|
|
|
274
274
|
function getLatestValueComputed(e) {
|
|
275
|
-
let t = e.o?.
|
|
275
|
+
let t = e.o?.Ce;
|
|
276
276
|
// A shadow disposed while unobserved (its gated reader unmounted at a
|
|
277
277
|
// landing) is a corpse: sync writes into it equality-swallow against its
|
|
278
278
|
// frozen _value, and a later read revives it via recompute — clearing
|
|
@@ -289,10 +289,10 @@ function getLatestValueComputed(e) {
|
|
|
289
289
|
setContextInternal(null);
|
|
290
290
|
// Detach from owner so it isn't disposed with effects
|
|
291
291
|
t = optimisticComputed(() => read(e));
|
|
292
|
-
ext(e).
|
|
292
|
+
ext(e).Ce = t;
|
|
293
293
|
e.T |= CONFIG_HAS_COMPANIONS;
|
|
294
294
|
markFirewallChildCompanions(e);
|
|
295
|
-
ext(t).
|
|
295
|
+
ext(t).Tt = e;
|
|
296
296
|
// Parent-child lane relationship
|
|
297
297
|
// Backfill an in-flight write (mirrors getPendingSignal): the companion is
|
|
298
298
|
// created lazily, possibly after the write was processed — syncCompanions
|
|
@@ -310,7 +310,7 @@ function getLatestValueComputed(e) {
|
|
|
310
310
|
const t = getLatestValueComputed(e);
|
|
311
311
|
const n = latestReadActive;
|
|
312
312
|
setLatestReadActive(false);
|
|
313
|
-
const i = e.o?.
|
|
313
|
+
const i = e.o?.Oe !== undefined && e.o?.Oe !== NOT_PENDING ? unwrapOverride(e.o?.Oe) : e.be;
|
|
314
314
|
let r;
|
|
315
315
|
try {
|
|
316
316
|
// An untracked latest() read has no reading context, so read() never
|
|
@@ -319,9 +319,24 @@ function getLatestValueComputed(e) {
|
|
|
319
319
|
// until the flush (#2922). Mirror the tracked-read pull here: mark the
|
|
320
320
|
// queued staleness through the graph, then bring the shadow up to date.
|
|
321
321
|
const e = queueFor(t);
|
|
322
|
-
if (t.
|
|
322
|
+
if (t.Me >= e.Qe && !(t.ie & (REACTIVE_DISPOSED | REACTIVE_ZOMBIE))) {
|
|
323
323
|
markHeap(e);
|
|
324
|
-
|
|
324
|
+
// Suspend probe collection during the pull (mirrors pendingCheckRead's
|
|
325
|
+
// prepare): a probe through latest() answers for the SHADOW — the
|
|
326
|
+
// read() dispatch collects it deliberately, so the verdict reflects
|
|
327
|
+
// async still in flight for the latest view, not the parent's held
|
|
328
|
+
// write. A stale shadow recomputing HERE ran its `read(parent)` with
|
|
329
|
+
// the probe still live and collected the parent too, so the verdict
|
|
330
|
+
// depended on whether anything had pulled the shadow current earlier
|
|
331
|
+
// in the tick (#3104: reading latest(m) flipped a later
|
|
332
|
+
// latest(() => isPending(x)) from true to false).
|
|
333
|
+
const n = pendingCheckActive;
|
|
334
|
+
setPendingCheckActive(false);
|
|
335
|
+
try {
|
|
336
|
+
prepareComputed(t, true);
|
|
337
|
+
} finally {
|
|
338
|
+
setPendingCheckActive(n);
|
|
339
|
+
}
|
|
325
340
|
}
|
|
326
341
|
r = read(t);
|
|
327
342
|
} catch (t) {
|
|
@@ -331,10 +346,10 @@ function getLatestValueComputed(e) {
|
|
|
331
346
|
setLatestReadActive(n);
|
|
332
347
|
}
|
|
333
348
|
if (t.S & STATUS_PENDING) return i;
|
|
334
|
-
if (stale && currentOptimisticLane && t.o?.
|
|
335
|
-
const e = findLane(t.o?.
|
|
349
|
+
if (stale && currentOptimisticLane && t.o?.Je) {
|
|
350
|
+
const e = findLane(t.o?.Je);
|
|
336
351
|
const n = findLane(currentOptimisticLane);
|
|
337
|
-
if (e !== n && e.
|
|
352
|
+
if (e !== n && e.De.size > 0) {
|
|
338
353
|
return i;
|
|
339
354
|
}
|
|
340
355
|
}
|
|
@@ -342,15 +357,41 @@ function getLatestValueComputed(e) {
|
|
|
342
357
|
// speculative value in _pendingValue; a contextless read() only surfaces
|
|
343
358
|
// _value. Overrides stay authoritative (A17), and stale readers keep the
|
|
344
359
|
// other transition's committed view, matching read()'s own selection.
|
|
345
|
-
if (t.Pe !== NOT_PENDING && !hasActiveOverride(t) && !(stale && t.
|
|
360
|
+
if (t.Pe !== NOT_PENDING && !hasActiveOverride(t) && !(stale && t.Ae && activeTransition !== t.Ae)) return t.Pe;
|
|
346
361
|
return r;
|
|
347
362
|
}
|
|
348
363
|
|
|
364
|
+
/**
|
|
365
|
+
* A latest() shadow that is uninitialized only because it was CREATED during
|
|
366
|
+
* an active flight — its parent source already has a committed value, so
|
|
367
|
+
* latest() serves that as the visible value and a tracked reader has
|
|
368
|
+
* something to pair a verdict with (#3166). Same parent resolution as
|
|
369
|
+
* computePendingState. The pending signal companion also carries
|
|
370
|
+
* `_parentSource` but is a plain signal (no `_fn`) that never goes pending,
|
|
371
|
+
* so the `_fn` check is belt-and-braces for this call site.
|
|
372
|
+
*/ function latestShadowWithInitializedParent(e) {
|
|
373
|
+
if (typeof e.oe !== "function") return false;
|
|
374
|
+
const t = e.o?.Tt;
|
|
375
|
+
if (t === undefined) return false;
|
|
376
|
+
const n = t.st || t;
|
|
377
|
+
return !(n.S & STATUS_UNINITIALIZED);
|
|
378
|
+
}
|
|
379
|
+
|
|
349
380
|
/** The isPending()-probe read path, installed as GlobalQueue._pendingCheck. */ function pendingCheckRead(e, t, n, i) {
|
|
350
381
|
setPendingCheckActive(false);
|
|
351
382
|
if (typeof e.oe === "function") prepareComputed(e, true);
|
|
352
383
|
const r = n.S;
|
|
353
|
-
if (t && r & STATUS_PENDING && r & STATUS_UNINITIALIZED
|
|
384
|
+
if (t && r & STATUS_PENDING && r & STATUS_UNINITIALIZED &&
|
|
385
|
+
// The suspend-throw is for a genuinely-first-load source: the tracked
|
|
386
|
+
// reader has nothing to pair a verdict with, so it parks on the source.
|
|
387
|
+
// A latest() SHADOW created lazily mid-flight is born uninitialized even
|
|
388
|
+
// though its parent has a committed value latest() will serve — throwing
|
|
389
|
+
// here (swallowed by latestRead's fallback) dropped the shadow from the
|
|
390
|
+
// probe, so a tracked latest(isPending()) probe created during a
|
|
391
|
+
// new-question flight cached `false` for that whole flight (#3166).
|
|
392
|
+
// Defer to the PARENT's initialization state and fall through to normal
|
|
393
|
+
// collection; the plain pending throw downstream still links the reader.
|
|
394
|
+
!latestShadowWithInitializedParent(n)) {
|
|
354
395
|
if (tracking && e !== t) link(e, t);
|
|
355
396
|
setPendingCheckActive(true);
|
|
356
397
|
throw n.o?._;
|
|
@@ -368,9 +409,9 @@ function getLatestValueComputed(e) {
|
|
|
368
409
|
* reader saw is an input, and pending remains the truth for every reader
|
|
369
410
|
* (#3028).
|
|
370
411
|
*/ function heldAwaitingAsync(e) {
|
|
371
|
-
const t = e.
|
|
412
|
+
const t = e.Ae;
|
|
372
413
|
const n = t ? currentTransition(t) : activeTransition;
|
|
373
|
-
if (!n || n.
|
|
414
|
+
if (!n || n.sn) return false;
|
|
374
415
|
// A plain staged write (a signal/store leaf — no _fn) held while an action
|
|
375
416
|
// is still running is an INPUT to a computation still in flight (#3078):
|
|
376
417
|
// the pairing rule must not suppress the verdict, or a memo recomputing
|
|
@@ -385,7 +426,7 @@ function getLatestValueComputed(e) {
|
|
|
385
426
|
// action check above; the reporter scan below is for transition-held
|
|
386
427
|
// writes whose source async is still computing.
|
|
387
428
|
if (!t) return false;
|
|
388
|
-
for (const [e, t] of n.
|
|
429
|
+
for (const [e, t] of n._e) {
|
|
389
430
|
if (t.size && e.S & STATUS_PENDING && e.o?._?.source === e) return true;
|
|
390
431
|
}
|
|
391
432
|
return false;
|
|
@@ -400,10 +441,10 @@ function recordFreshRead(e, t) {
|
|
|
400
441
|
|
|
401
442
|
function applyReask(e, t) {
|
|
402
443
|
const n = !!(e.S & STATUS_PENDING);
|
|
403
|
-
const i = t && !(n && !e.o?.
|
|
404
|
-
const r = n && (e.o?.
|
|
444
|
+
const i = t && !(n && !e.o?.Ge);
|
|
445
|
+
const r = n && (e.o?.Ge ?? false) !== i;
|
|
405
446
|
// Allocation-free for the quiet case: false is the extension default.
|
|
406
|
-
if (i) ext(e).
|
|
447
|
+
if (i) ext(e).Ge = true; else if (e.o !== null) e.o.Ge = false;
|
|
407
448
|
return r;
|
|
408
449
|
}
|
|
409
450
|
|
|
@@ -429,6 +470,17 @@ function isPending(e) {
|
|
|
429
470
|
};
|
|
430
471
|
const collectPending = () => {
|
|
431
472
|
setPendingCheckActive(false);
|
|
473
|
+
// Companion reads are mode-neutral plumbing: under an outer latest()
|
|
474
|
+
// (isPending inside a latest window — #3104's memo shape) leaving latest
|
|
475
|
+
// mode active dispatched these reads through latestRead, which built a
|
|
476
|
+
// SHADOW OF THE PENDING SIGNAL itself. The next updatePendingSignal then
|
|
477
|
+
// wrote that companion-on-companion from inside a recompute
|
|
478
|
+
// (syncCompanions → setSignal on a shadow created without ownedWrite)
|
|
479
|
+
// and halted dev with the owned-scope write guard. The creation paths
|
|
480
|
+
// (getLatestValueComputed / getPendingSignal) already suspend both
|
|
481
|
+
// modes; this read site must too.
|
|
482
|
+
const e = latestReadActive;
|
|
483
|
+
setLatestReadActive(false);
|
|
432
484
|
try {
|
|
433
485
|
i.sources.forEach(e => {
|
|
434
486
|
if (read(getPendingSignal(e))) {
|
|
@@ -436,6 +488,7 @@ function isPending(e) {
|
|
|
436
488
|
}
|
|
437
489
|
});
|
|
438
490
|
} finally {
|
|
491
|
+
setLatestReadActive(e);
|
|
439
492
|
setPendingCheckActive(true);
|
|
440
493
|
}
|
|
441
494
|
// A "not pending" verdict that exists only because this reader saw the
|
|
@@ -472,26 +525,26 @@ function isPending(e) {
|
|
|
472
525
|
// Hook installation (same late-binding pattern as GlobalQueue._update /
|
|
473
526
|
// _propagateAffects): core call sites fire these behind the same guards the
|
|
474
527
|
// direct calls used, so behavior is identical once this module loads.
|
|
475
|
-
GlobalQueue.
|
|
528
|
+
GlobalQueue.Re = syncCompanions;
|
|
476
529
|
|
|
477
530
|
GlobalQueue.de = updatePendingSignal;
|
|
478
531
|
|
|
479
|
-
GlobalQueue.
|
|
532
|
+
GlobalQueue.me = updateChildCompanions;
|
|
480
533
|
|
|
481
534
|
GlobalQueue.un = snapCompanionsToState;
|
|
482
535
|
|
|
483
|
-
GlobalQueue.
|
|
536
|
+
GlobalQueue.gt = latestRead;
|
|
484
537
|
|
|
485
|
-
GlobalQueue.
|
|
538
|
+
GlobalQueue.Ht = pendingCheckRead;
|
|
486
539
|
|
|
487
|
-
GlobalQueue.
|
|
540
|
+
GlobalQueue.kt = recordFreshRead;
|
|
488
541
|
|
|
489
|
-
GlobalQueue.
|
|
542
|
+
GlobalQueue.et = applyReask;
|
|
490
543
|
|
|
491
544
|
GlobalQueue.k = repollDownstreamVerdicts;
|
|
492
545
|
|
|
493
|
-
GlobalQueue.
|
|
546
|
+
GlobalQueue.Wt = witnessAffects;
|
|
494
547
|
|
|
495
|
-
GlobalQueue.
|
|
548
|
+
GlobalQueue.zt = wakeSuppressedProbes;
|
|
496
549
|
|
|
497
550
|
export { isPending, latest };
|
package/dist/prod/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { ContextNotFoundError, NoOwnerError, NotReadyError } from "./core/error.js";
|
|
1
|
+
export { ContextNotFoundError, NoOwnerError, NotReadyError, TimeoutError } from "./core/error.js";
|
|
2
2
|
|
|
3
|
-
export { clearSnapshots, isEqual, markSnapshotScope,
|
|
3
|
+
export { clearSnapshots, isEqual, markSnapshotScope, releaseSnapshotScope, runWithOwner, setSnapshotCapture, untrack } from "./core/core.js";
|
|
4
4
|
|
|
5
5
|
export { enableExternalSource } from "./core/external.js";
|
|
6
6
|
|
|
@@ -20,7 +20,7 @@ import "./core/effect.js";
|
|
|
20
20
|
|
|
21
21
|
export { action } from "./core/action.js";
|
|
22
22
|
|
|
23
|
-
export { createEffect, createMemo, createOptimistic, createReaction, createRenderEffect, createSignal, createTrackedEffect, onCleanup, onSettled, resolve } from "./signals.js";
|
|
23
|
+
export { createEffect, createMemo, createOptimistic, createReaction, createRenderEffect, createSignal, createTrackedEffect, onCleanup, onSettled, refresh, resolve, until } from "./signals.js";
|
|
24
24
|
|
|
25
25
|
export { affects } from "./affects.js";
|
|
26
26
|
|