@solidjs/signals 2.0.0-rc.19 → 2.0.0-rc.20
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-shared.js +553 -264
- package/dist/dev.attribution.js +18 -18
- package/dist/dev.js +1030 -439
- package/dist/observe/affects.js +12 -2
- package/dist/observe/boundaries.js +168 -115
- package/dist/observe/core/async.js +57 -37
- package/dist/observe/core/attribution.js +6 -6
- package/dist/observe/core/constants.js +9 -1
- package/dist/observe/core/copies.js +10 -0
- package/dist/observe/core/core.js +261 -181
- package/dist/observe/core/effect.js +32 -27
- package/dist/observe/core/graph.js +7 -7
- package/dist/observe/core/heap.js +29 -29
- package/dist/observe/core/lanes.js +301 -101
- package/dist/observe/core/owner.js +13 -13
- package/dist/observe/core/scheduler.js +124 -69
- package/dist/observe/core/truth.js +9 -7
- package/dist/observe/core/verdict.js +160 -98
- package/dist/observe/deferred.js +1 -1
- package/dist/observe/index.js +2 -0
- package/dist/observe/map.js +120 -116
- package/dist/observe/reveal.js +48 -48
- package/dist/observe/signals.js +5 -5
- package/dist/observe/store/affects.js +2 -2
- package/dist/observe/store/optimistic.js +272 -176
- package/dist/observe/store/projection.js +21 -10
- package/dist/observe/store/reconcile.js +8 -2
- package/dist/observe/store/store.js +91 -55
- package/dist/observe/store/types.js +11 -1
- package/dist/observe/store/utils.js +1 -1
- package/dist/prod/affects.js +12 -2
- package/dist/prod/boundaries.js +164 -109
- package/dist/prod/core/async.js +201 -181
- package/dist/prod/core/constants.js +9 -1
- package/dist/prod/core/copies.js +10 -0
- package/dist/prod/core/core.js +244 -164
- package/dist/prod/core/dev.js +108 -3
- package/dist/prod/core/effect.js +28 -23
- package/dist/prod/core/graph.js +9 -9
- package/dist/prod/core/heap.js +16 -16
- package/dist/prod/core/identities.js +1 -1
- package/dist/prod/core/lanes.js +307 -95
- package/dist/prod/core/owner.js +22 -22
- package/dist/prod/core/scheduler.js +266 -211
- package/dist/prod/core/truth.js +9 -7
- package/dist/prod/core/verdict.js +161 -99
- package/dist/prod/deferred.js +1 -1
- package/dist/prod/index.js +2 -0
- package/dist/prod/map.js +78 -74
- package/dist/prod/reveal.js +34 -34
- package/dist/prod/signals.js +3 -3
- package/dist/prod/store/affects.js +15 -15
- package/dist/prod/store/optimistic.js +185 -89
- package/dist/prod/store/projection.js +49 -38
- package/dist/prod/store/reconcile.js +8 -2
- package/dist/prod/store/store.js +99 -63
- package/dist/prod/store/types.js +11 -1
- package/dist/types/affects.d.ts +3 -2
- package/dist/types/boundaries.d.ts +14 -2
- package/dist/types/core/async.d.ts +2 -1
- package/dist/types/core/constants.d.ts +8 -0
- package/dist/types/core/copies.d.ts +54 -0
- package/dist/types/core/core.d.ts +15 -0
- package/dist/types/core/dev.d.ts +1 -1
- package/dist/types/core/lanes.d.ts +8 -1
- package/dist/types/core/scheduler.d.ts +36 -4
- package/dist/types/core/truth.d.ts +3 -1
- package/dist/types/core/types.d.ts +6 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/store/hooks.d.ts +15 -1
- package/dist/types/store/store.d.ts +2 -1
- package/dist/types/store/target.d.ts +5 -0
- package/dist/types/store/types.d.ts +7 -0
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { STATUS_ERROR, STATUS_PENDING, STATUS_NO_VALUE, STATUS_UNINITIALIZED, CONFIG_GUESS, REACTIVE_RECOMPUTING_DEPS, CONFIG_HELD, REACTIVE_STAGED_READ, CONFIG_STAGED, CONFIG_STAGED_ERROR, CONFIG_AUTO_DISPOSE, REACTIVE_ZOMBIE, NewSet, REACTIVE_DIRTY, CONFIG_INPUTS_PUBLISHED, NOT_PENDING, REACTIVE_DISPOSED, CONFIG_REDERIVE, CONFIG_VERDICT, CONFIG_OVERRIDE } from "./constants.js";
|
|
1
|
+
import { STATUS_ERROR, STATUS_PENDING, STATUS_NO_VALUE, STATUS_UNINITIALIZED, CONFIG_GUESS, REACTIVE_REASK, REACTIVE_RECOMPUTING_DEPS, CONFIG_ASYNC, REACTIVE_WINDOW, CONFIG_HELD, REACTIVE_STAGED_READ, CONFIG_STAGED, CONFIG_STAGED_ERROR, CONFIG_AUTO_DISPOSE, REACTIVE_ZOMBIE, NewSet, REACTIVE_DIRTY, CONFIG_INPUTS_PUBLISHED, NOT_PENDING, REACTIVE_DISPOSED, CONFIG_REDERIVE, CONFIG_VERDICT, CONFIG_OVERRIDE } from "./constants.js";
|
|
2
2
|
|
|
3
3
|
import { attrHooks } from "./attribution-hooks.js";
|
|
4
4
|
|
|
@@ -14,7 +14,7 @@ import { enqueueSub } from "./heap.js";
|
|
|
14
14
|
|
|
15
15
|
import { disposeChildren, cleanup } from "./owner.js";
|
|
16
16
|
|
|
17
|
-
import { passLane, joinFuture, question, MAINLINE_QUESTION, globalQueue, schedule, clock, flush, freshHook,
|
|
17
|
+
import { guessing, passLane, joinFuture, txOf, holdWorkHook, question, MAINLINE_QUESTION, globalQueue, schedule, clock, flush, freshHook, laneStageHook, queuePendingNode } from "./scheduler.js";
|
|
18
18
|
|
|
19
19
|
// The lazily-created Set is the ONE container for pending sources. Its
|
|
20
20
|
// predecessor — a singular slot promoted to a Set on the second source —
|
|
@@ -71,16 +71,16 @@ function retryReaches(e, t) {
|
|
|
71
71
|
|
|
72
72
|
function setPendingError(e, t, n) {
|
|
73
73
|
if (!t) {
|
|
74
|
-
if (e.T !== null) e.T.
|
|
74
|
+
if (e.T !== null) e.T.U = null;
|
|
75
75
|
return;
|
|
76
76
|
}
|
|
77
77
|
if (n instanceof NotReadyError && n.source === t) {
|
|
78
|
-
ext(e).
|
|
78
|
+
ext(e).U = n;
|
|
79
79
|
return;
|
|
80
80
|
}
|
|
81
|
-
const r = e.T?.
|
|
81
|
+
const r = e.T?.U;
|
|
82
82
|
if (!(r instanceof NotReadyError) || r.source !== t) {
|
|
83
|
-
ext(e).
|
|
83
|
+
ext(e).U = new NotReadyError(t);
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
|
|
@@ -150,13 +150,13 @@ function releaseSettledDependents(e) {
|
|
|
150
150
|
// (#4109). A flush that parks nothing publishes it at its commit (S-38).
|
|
151
151
|
// Not a projection's derive: its readers learn its error through the
|
|
152
152
|
// family, which the commit's publish never reaches (#4189).
|
|
153
|
-
if (!(e.l & CONFIG_HELD || n && e.R & REACTIVE_STAGED_READ && globalQueue.
|
|
153
|
+
if (!(e.l & CONFIG_HELD || n && e.R & REACTIVE_STAGED_READ && globalQueue.Y && !e.fam) || passLane) return false;
|
|
154
154
|
// The node answered (an error ends the wait — no longer pending, nor
|
|
155
155
|
// blocked); a shown error stays its display until the commit.
|
|
156
156
|
clearPendingSources(e);
|
|
157
157
|
if (e.T) e.T.fe = false;
|
|
158
158
|
if (!((e.m &= STATUS_ERROR | STATUS_UNINITIALIZED) & STATUS_ERROR)) setPendingError(e);
|
|
159
|
-
e.
|
|
159
|
+
e.ue = t instanceof StatusError ? t : new StatusError(e, t);
|
|
160
160
|
e.l |= CONFIG_STAGED | CONFIG_STAGED_ERROR;
|
|
161
161
|
// Readers parked on the flight re-run and derive from the staging; the
|
|
162
162
|
// verdict readers the walk wakes need a flush (#4106).
|
|
@@ -171,7 +171,7 @@ function settleErroredDependents(e, t) {
|
|
|
171
171
|
const visit = e => {
|
|
172
172
|
if (r.has(e)) return;
|
|
173
173
|
r.add(e);
|
|
174
|
-
if (e.T?.
|
|
174
|
+
if (e.T?.U === t) {
|
|
175
175
|
enqueueSub(e);
|
|
176
176
|
n = true;
|
|
177
177
|
}
|
|
@@ -205,10 +205,11 @@ function settlePendingSource(e, t = e) {
|
|
|
205
205
|
// A19: a verdict reader holds no pending of its own (it was re-derived
|
|
206
206
|
// when the source went pending, `propagateStatus`), and a landing
|
|
207
207
|
// equal to the committed value notifies nobody — the source settling
|
|
208
|
-
// is its verdict changing: it runs again.
|
|
209
|
-
|
|
208
|
+
// is its verdict changing: it runs again. (Verdict readers exist only
|
|
209
|
+
// with the verdict engine installed.)
|
|
210
|
+
return holdWorkHook && s.l & CONFIG_VERDICT && enqueueSub(s);
|
|
210
211
|
o.add(s);
|
|
211
|
-
s.
|
|
212
|
+
s.ie = clock;
|
|
212
213
|
const f = s.T?.se?.values().next().value;
|
|
213
214
|
// STATUS_ERROR + pending sources only coexist via an errored loading
|
|
214
215
|
// window's park (notifyStatus(STATUS_ERROR) clears pending sources
|
|
@@ -301,7 +302,10 @@ r) {
|
|
|
301
302
|
});
|
|
302
303
|
}
|
|
303
304
|
if (!s && !o) {
|
|
304
|
-
if (e.T !== null)
|
|
305
|
+
if (e.T !== null) {
|
|
306
|
+
e.T.Ee = null;
|
|
307
|
+
if (holdWorkHook) e.l &= ~CONFIG_ASYNC;
|
|
308
|
+
}
|
|
305
309
|
// A sync landing is the first real answer for a loadingValue node.
|
|
306
310
|
e.ce = false;
|
|
307
311
|
return t;
|
|
@@ -312,9 +316,14 @@ r) {
|
|
|
312
316
|
// fired _flightTeardown. A future non-recompute registration path must
|
|
313
317
|
// release it here before overwriting _inFlight.
|
|
314
318
|
ext(e).Ee = t;
|
|
319
|
+
// D-25 (verdict.ts `holdWork`): an async memo whose answering pass opened
|
|
320
|
+
// no verdict window of its own (`markVerdictReader` clears the bit).
|
|
321
|
+
// Kept by the verdict engine alone (`holdWorkHook`): a build without it
|
|
322
|
+
// folds the bit's upkeep away.
|
|
323
|
+
if (holdWorkHook && !(e.R & REACTIVE_WINDOW)) e.l |= CONFIG_ASYNC;
|
|
315
324
|
// The question this flight answers (A18 provenance, lanes.ts): the action
|
|
316
325
|
// whose slice asked it; mainline is always the current question.
|
|
317
|
-
e.T.
|
|
326
|
+
e.T.Ie = question || MAINLINE_QUESTION;
|
|
318
327
|
// The run that asked this flight read every input without throwing: an
|
|
319
328
|
// input still in flight was masked for it (an active override, A17), so
|
|
320
329
|
// pending state those inputs propagated onto the node earlier does not
|
|
@@ -340,7 +349,7 @@ r) {
|
|
|
340
349
|
// error-retry pull (updateIfNecessary) can also re-ask.
|
|
341
350
|
if (e.T !== null) e.T.Ee = null;
|
|
342
351
|
parkLoadingWindow(e, o);
|
|
343
|
-
e.
|
|
352
|
+
e.ie = clock;
|
|
344
353
|
return;
|
|
345
354
|
}
|
|
346
355
|
// D-41: a held node's error is staged (`stageError`). A derived store's
|
|
@@ -358,7 +367,7 @@ r) {
|
|
|
358
367
|
// rejected flight will never settle its self entry, so transfer ownership
|
|
359
368
|
// after notifyStatus has propagated the replacement source.
|
|
360
369
|
if (s) settlePendingSource(e);
|
|
361
|
-
e.
|
|
370
|
+
e.ie = clock;
|
|
362
371
|
// A real error settles derivatively-pending dependents (notifyStatus
|
|
363
372
|
// cleared their pending sources), so stranded lazy ones release here —
|
|
364
373
|
// the error twin of settlePendingSource's release (#2934).
|
|
@@ -390,7 +399,7 @@ r) {
|
|
|
390
399
|
// a verdict reader of the next flight would suspend instead of being
|
|
391
400
|
// served the screen; held, both at the derive's commit.
|
|
392
401
|
if (!(e.l & CONFIG_HELD)) {
|
|
393
|
-
e.T.Te =
|
|
402
|
+
e.T.Te = null;
|
|
394
403
|
e.l &= ~CONFIG_INPUTS_PUBLISHED;
|
|
395
404
|
}
|
|
396
405
|
if (s) landStatus(e, true);
|
|
@@ -422,7 +431,7 @@ r) {
|
|
|
422
431
|
// (`_pendingValue` set inside setSignal) is not — commitPendingNode closes
|
|
423
432
|
// the window when the flush commits it, so no one-frame pulse can leak to
|
|
424
433
|
// observers between the landing and its commit (#2990).
|
|
425
|
-
if (e.
|
|
434
|
+
if (e.ue === NOT_PENDING) {
|
|
426
435
|
e.ce = false;
|
|
427
436
|
// The landing published: the dependency tail the flight's pass left
|
|
428
437
|
// linked goes now (A30, #3410). A staged landing has not replaced the
|
|
@@ -494,7 +503,7 @@ r) {
|
|
|
494
503
|
}
|
|
495
504
|
};
|
|
496
505
|
const iterate = () => {
|
|
497
|
-
let n, r, l = false,
|
|
506
|
+
let n, r, l = false, S = false, a = true;
|
|
498
507
|
// Protocol tolerance, matching `for await`: `await` unwraps whatever
|
|
499
508
|
// next() returns — a thenable OR a bare IteratorResult. Real producers
|
|
500
509
|
// use the bare form as a promise-free fast path when a value is already
|
|
@@ -512,7 +521,7 @@ r) {
|
|
|
512
521
|
// stash: it must write through the async path or the value is
|
|
513
522
|
// silently dropped. (The deferred posture never has a caller, so
|
|
514
523
|
// initialRead starts false there and everything writes through.)
|
|
515
|
-
if (
|
|
524
|
+
if (a && i) {
|
|
516
525
|
n = r;
|
|
517
526
|
l = true;
|
|
518
527
|
if (r.done) u = true;
|
|
@@ -533,17 +542,17 @@ r) {
|
|
|
533
542
|
settleAutodispose();
|
|
534
543
|
}
|
|
535
544
|
}, n => {
|
|
536
|
-
if (
|
|
545
|
+
if (a && i) {
|
|
537
546
|
r = n;
|
|
538
|
-
|
|
547
|
+
S = true;
|
|
539
548
|
} else if (e.T?.Ee === t) {
|
|
540
549
|
u = true;
|
|
541
550
|
handleError(n);
|
|
542
551
|
settleAutodispose();
|
|
543
552
|
}
|
|
544
553
|
});
|
|
545
|
-
|
|
546
|
-
if (
|
|
554
|
+
a = false;
|
|
555
|
+
if (S) {
|
|
547
556
|
// Match the promise branch, but only rethrow during the initial read.
|
|
548
557
|
u = true;
|
|
549
558
|
handleError(r);
|
|
@@ -657,7 +666,7 @@ function clearStatus(e, t = false) {
|
|
|
657
666
|
if (e.T?.se) clearPendingSources(e);
|
|
658
667
|
if (e.T?.fe) e.T.fe = false;
|
|
659
668
|
e.m = t ? 0 : e.m & STATUS_UNINITIALIZED;
|
|
660
|
-
if (e.T?.
|
|
669
|
+
if (e.T?.U) setPendingError(e);
|
|
661
670
|
const n = statusNotifierOf(e);
|
|
662
671
|
if (n) n.call(e);
|
|
663
672
|
}
|
|
@@ -699,11 +708,11 @@ function clearStatus(e, t = false) {
|
|
|
699
708
|
function notifyStatus(e, t, n) {
|
|
700
709
|
// Wrap regular errors to track source node
|
|
701
710
|
if (t === STATUS_ERROR && !(n instanceof StatusError) && !(n instanceof NotReadyError)) n = new StatusError(e, n);
|
|
702
|
-
const r = t === STATUS_PENDING && n instanceof NotReadyError
|
|
711
|
+
const r = t === STATUS_PENDING && n instanceof NotReadyError && n.source;
|
|
703
712
|
// (CARVE 2: the lane assignment went with the engine.)
|
|
704
713
|
if (t === STATUS_PENDING && r) {
|
|
705
714
|
// D-41: a re-ask of a shown error keeps it the display (`_shownError`).
|
|
706
|
-
if (e.m & STATUS_ERROR) e.T.Te = e.T.
|
|
715
|
+
if (e.m & STATUS_ERROR) e.T.Te = e.T.U;
|
|
707
716
|
addPendingSource(e, r);
|
|
708
717
|
// A re-ask of an error that answered the first read: still no value.
|
|
709
718
|
e.m = STATUS_PENDING | (e.m & STATUS_NO_VALUE ? STATUS_UNINITIALIZED : e.m & STATUS_UNINITIALIZED);
|
|
@@ -715,16 +724,21 @@ function notifyStatus(e, t, n) {
|
|
|
715
724
|
// An error answering a node with no value marks it so; a re-ask of it
|
|
716
725
|
// (pending) is uninitialized again; a write (STATUS_NONE) gives it one.
|
|
717
726
|
e.m = t | (t === STATUS_ERROR ? e.m & (STATUS_UNINITIALIZED | STATUS_NO_VALUE) ? STATUS_NO_VALUE : 0 : t === STATUS_PENDING && e.m & STATUS_NO_VALUE ? STATUS_UNINITIALIZED : e.m & STATUS_UNINITIALIZED);
|
|
718
|
-
ext(e).
|
|
727
|
+
ext(e).U = n;
|
|
719
728
|
}
|
|
720
729
|
// Lanes: a written guess is an optimistic boundary (A17 — "the optimistic
|
|
721
730
|
// future value until we know otherwise"). Its own source in flight is its
|
|
722
731
|
// status, not its readers': they read the guess. The flight is the parent
|
|
723
732
|
// transition's to wait on — the frame it was asked in holds (A17: "a
|
|
724
733
|
// transition whose optimistic node is still pending on its own fetch is
|
|
725
|
-
// not complete"), through the node itself (`blocked`).
|
|
726
|
-
|
|
727
|
-
|
|
734
|
+
// not complete"), through the node itself (`blocked`). An input changed
|
|
735
|
+
// from outside the guess's hold asks a new question: the frame that
|
|
736
|
+
// changed it is held with that hold (D-34, #4336) — it shows beside the
|
|
737
|
+
// guess's truth, which reveals at that hold's commit (F-1). A `refresh()`
|
|
738
|
+
// re-asks the same question: its frame is its own.
|
|
739
|
+
// (No guess written, no arm.)
|
|
740
|
+
if (guessing && t === STATUS_PENDING && e.l & CONFIG_GUESS) {
|
|
741
|
+
if (passLane === null) joinFuture(e.R & REACTIVE_REASK ? null : txOf(e)._parent);
|
|
728
742
|
return;
|
|
729
743
|
}
|
|
730
744
|
const o = statusNotifierOf(e);
|
|
@@ -740,9 +754,9 @@ function notifyStatus(e, t, n) {
|
|
|
740
754
|
* family's leaves, which are not the derive's dependents — the family
|
|
741
755
|
* propagates the derive's status from each leaf to the leaf's readers
|
|
742
756
|
* (store/projection.ts `wakeFamily`), exactly as a memo's would reach its. */ function propagateStatus(e, t, n) {
|
|
743
|
-
const r = t === STATUS_PENDING && n instanceof NotReadyError
|
|
757
|
+
const r = t === STATUS_PENDING && n instanceof NotReadyError && n.source;
|
|
744
758
|
forEachDependent(e, (o, s) => {
|
|
745
|
-
o.
|
|
759
|
+
o.ie = clock;
|
|
746
760
|
// A pending mark on a kept-tail link re-derives the subscriber instead of
|
|
747
761
|
// marking it (A30, #3494 review; fuzzer latest-1 #2141; #3519 review).
|
|
748
762
|
// Past `_depsTail` lie the committed frame's deps, kept by A30 because
|
|
@@ -762,7 +776,13 @@ function notifyStatus(e, t, n) {
|
|
|
762
776
|
// Inheriting the error would make a probe's reader errored. A boundary's
|
|
763
777
|
// output (CONFIG_REDERIVE, boundaries.ts) the same: content or fallback
|
|
764
778
|
// is its pass's call.
|
|
765
|
-
|
|
779
|
+
// Not one D-25 makes the hold's work (verdict.ts `holdWork`): an async
|
|
780
|
+
// memo with no verdict window of its own reads a verdict memo's value,
|
|
781
|
+
// and that source going pending changes none of its reads — re-derived,
|
|
782
|
+
// it is served the committed value it already derived from (A10) and
|
|
783
|
+
// asks that question again. It waits on the source like any derivation
|
|
784
|
+
// (F-9), and asks its next question once, at the landing (#4397).
|
|
785
|
+
if (o.l & CONFIG_REDERIVE || holdWorkHook && o.l & CONFIG_VERDICT && !(r && holdWorkHook(o, e)) || t === STATUS_PENDING && s.de !== o.Ne) {
|
|
766
786
|
enqueueSub(o);
|
|
767
787
|
schedule();
|
|
768
788
|
return;
|
|
@@ -775,10 +795,10 @@ function notifyStatus(e, t, n) {
|
|
|
775
795
|
// shape: the unmount it stages makes the observer a zombie whose say is
|
|
776
796
|
// moot for this transaction, A15 #3463).
|
|
777
797
|
if (t === STATUS_PENDING && r && o.T?.se?.has(r)) {
|
|
778
|
-
if (passLane === null && (o.l & (CONFIG_HELD | CONFIG_OVERRIDE)) === CONFIG_HELD && globalQueue.
|
|
798
|
+
if (passLane === null && (o.l & (CONFIG_HELD | CONFIG_OVERRIDE)) === CONFIG_HELD && globalQueue.Y && !freshHook?.(o, r.ie === clock)) joinFuture(txOf(o));
|
|
779
799
|
return;
|
|
780
800
|
}
|
|
781
|
-
if (t === STATUS_PENDING && r || t !== STATUS_PENDING && (o.T?.
|
|
801
|
+
if (t === STATUS_PENDING && r || t !== STATUS_PENDING && (o.T?.U !== n || o.T?.se)) {
|
|
782
802
|
// The marked subscriber is queued for the commit sweep so its status
|
|
783
803
|
// bookkeeping (loading window, uninitialized clear) runs with the flush
|
|
784
804
|
// — with the lane, when the pass propagating is the lane's work and
|
|
@@ -801,4 +821,4 @@ function notifyStatus(e, t, n) {
|
|
|
801
821
|
});
|
|
802
822
|
}
|
|
803
823
|
|
|
804
|
-
export { addPendingSource, clearStatus, forEachDependent, handleAsync, isThenable, notifyStatus, onSupersede, parkLoadingWindow, propagateStatus, releaseFlightTeardown, releaseIfSettledUnobserved, releaseSettledDependents, setPendingError, settleErroredDependents, settlePendingSource, stageError };
|
|
824
|
+
export { addPendingSource, clearStatus, forEachDependent, handleAsync, isThenable, notifyStatus, onSupersede, parkLoadingWindow, propagateStatus, releaseFlightTeardown, releaseIfSettledUnobserved, releaseSettledDependents, removePendingSource, setPendingError, settleErroredDependents, settlePendingSource, stageError };
|
|
@@ -2705,7 +2705,7 @@ const engineHooks = {
|
|
|
2705
2705
|
prevDeps: n || !wantsRerun() ? null : captureDeps(e),
|
|
2706
2706
|
// Mirror recompute's own prev-value resolution: an earlier run in the
|
|
2707
2707
|
// same flush may still be holding in _pendingValue.
|
|
2708
|
-
prevValue: e.
|
|
2708
|
+
prevValue: e.ue !== NOT_PENDING ? e.ue : e.le,
|
|
2709
2709
|
// A create run inherits the interaction of whatever is building it: the
|
|
2710
2710
|
// enclosing recompute (a parent's fn creating children) or, at the top
|
|
2711
2711
|
// of the recompute stack, the effect callback / handler frame.
|
|
@@ -2732,7 +2732,7 @@ const engineHooks = {
|
|
|
2732
2732
|
// exempt — a side-effect-only compute's work IS its effect phase, and
|
|
2733
2733
|
// identity of `undefined` proves nothing.
|
|
2734
2734
|
if (t && r.causes !== null && e.i) {
|
|
2735
|
-
const n = e.
|
|
2735
|
+
const n = e.ue !== NOT_PENDING ? e.ue : e.le;
|
|
2736
2736
|
if (n !== undefined && n === r.prevValue) t = false;
|
|
2737
2737
|
}
|
|
2738
2738
|
// Unstable-output check: memos only, non-create, plain runs with a
|
|
@@ -2740,12 +2740,12 @@ const engineHooks = {
|
|
|
2740
2740
|
// plain-flush memo commits and in `_value` for direct ones. Overlay runs
|
|
2741
2741
|
// are excluded — an optimistic re-derive legitimately produces fresh
|
|
2742
2742
|
// equivalents while the lane settles.
|
|
2743
|
-
if (r.causes !== null && t && !o && !i && !e.i) checkUnstableOutput(e, r.prevValue, e.
|
|
2743
|
+
if (r.causes !== null && t && !o && !i && !e.i) checkUnstableOutput(e, r.prevValue, e.ue !== NOT_PENDING ? e.ue : e.le);
|
|
2744
2744
|
// The same exemption for memos: a run that committed `undefined` did its
|
|
2745
2745
|
// work as a side effect (a projection's draft writes or reconcile, a
|
|
2746
2746
|
// write from inside a memo), so core's `undefined === undefined` gate
|
|
2747
2747
|
// proves nothing. Reported as changed, so no consumer counts it as waste.
|
|
2748
|
-
if (!t && (e.
|
|
2748
|
+
if (!t && (e.ue !== NOT_PENDING ? e.ue : e.le) === undefined) t = true;
|
|
2749
2749
|
if (r.causes !== null) recordRerun(e, r, {
|
|
2750
2750
|
selfMs: c,
|
|
2751
2751
|
totalMs: a
|
|
@@ -2788,7 +2788,7 @@ const engineHooks = {
|
|
|
2788
2788
|
},
|
|
2789
2789
|
asyncStart(e) {
|
|
2790
2790
|
asyncStartSeq = e.ge?.seq ?? 0;
|
|
2791
|
-
asyncStartTime = e.
|
|
2791
|
+
asyncStartTime = e.ie;
|
|
2792
2792
|
asyncStartValue = e.le;
|
|
2793
2793
|
},
|
|
2794
2794
|
asyncEnd(e, n, t, o) {
|
|
@@ -2799,7 +2799,7 @@ const engineHooks = {
|
|
|
2799
2799
|
// (or `_time`, for a same-reference commit under `equals: false`), and
|
|
2800
2800
|
// a transition hold parks the value in `_pendingValue`. A landing the
|
|
2801
2801
|
// equality gate swallowed moves none of them and must leave no stamp.
|
|
2802
|
-
const o = e.le !== asyncStartValue || e.
|
|
2802
|
+
const o = e.le !== asyncStartValue || e.ie !== asyncStartTime || e.ue === t;
|
|
2803
2803
|
if (o) stampWrite(e, "async", n === undefined ? NO_VALUES : n, t);
|
|
2804
2804
|
// Flight over either way — an equality-swallowed landing still spent
|
|
2805
2805
|
// the wall time (finalizeFlight only chains through a fresh stamp).
|
|
@@ -78,6 +78,11 @@ const REACTIVE_MANUAL_WRITE = 1 << 10;
|
|
|
78
78
|
* later read of the same pass routed it into a verdict lane — that was not
|
|
79
79
|
* the probe's answer (lanes.ts). Per pass. */ const REACTIVE_PROBE_UNANSWERED = 1 << 19;
|
|
80
80
|
|
|
81
|
+
/** The pass opened a verdict window of its own (`isPending`/`latest`) — not
|
|
82
|
+
* only read a verdict memo (F-6, core.ts `read`). An async memo whose pass
|
|
83
|
+
* did not is D-25's hold work while its flight is up (verdict.ts
|
|
84
|
+
* `holdWork`). Per pass (1 << 20 is lanes.ts's LEFT_SHOWN). */ const REACTIVE_WINDOW = 1 << 21;
|
|
85
|
+
|
|
81
86
|
// Static configuration bits packed into Owner/Computed/Signal _config.
|
|
82
87
|
const CONFIG_OWNED_WRITE = 1 << 0;
|
|
83
88
|
|
|
@@ -219,6 +224,9 @@ const CONFIG_HAS_SNAPSHOT = 1 << 9;
|
|
|
219
224
|
* joins nothing, so two mounts under one boundary made in separate flushes
|
|
220
225
|
* keep their holds apart (D-4, S-5 rows 1′–3′, #4283). */ const CONFIG_FRAME = 1 << 23;
|
|
221
226
|
|
|
227
|
+
/** The node's last answering pass registered a flight: an async memo. Kept
|
|
228
|
+
* by the verdict engine alone (verdict.ts `holdWork`), which reads it. */ const CONFIG_ASYNC = 1 << 29;
|
|
229
|
+
|
|
222
230
|
const STATUS_NONE = 0;
|
|
223
231
|
|
|
224
232
|
const STATUS_PENDING = 1 << 0;
|
|
@@ -258,4 +266,4 @@ const defaultContext = {};
|
|
|
258
266
|
|
|
259
267
|
const NewSet = Set;
|
|
260
268
|
|
|
261
|
-
export { $REFRESH, CAUGHT_REARMED, CONFIG_AUTHORITATIVE, CONFIG_AUTO_DISPOSE, CONFIG_CHILDREN_FORBIDDEN, CONFIG_FRAME, CONFIG_FRESH_READ, CONFIG_GUESS, CONFIG_HAS_SNAPSHOT, CONFIG_HELD, CONFIG_HELD_FRAME, CONFIG_INPUTS_PUBLISHED, CONFIG_IN_SNAPSHOT_SCOPE, CONFIG_KEY_BAG, CONFIG_LAGS, CONFIG_MANUAL_WRITE, CONFIG_NO_SNAPSHOT, CONFIG_OVERRIDE, CONFIG_OWNED_WRITE, CONFIG_PLUMBING, CONFIG_PROMOTED, CONFIG_REDERIVE, CONFIG_SLOT_NODE, CONFIG_STAGED, CONFIG_STAGED_ERROR, CONFIG_SYNC, CONFIG_TRANSPARENT, CONFIG_VERDICT, EFFECT_RENDER, EFFECT_TRACKED, EFFECT_USER, NOT_PENDING, NO_SNAPSHOT, NewSet, REACTIVE_CHECK, REACTIVE_DIRTY, REACTIVE_DISPOSED, REACTIVE_FRAME_READ, REACTIVE_IN_HEAP, REACTIVE_IN_HEAP_HEIGHT, REACTIVE_JOINED, REACTIVE_LANE_DIRTY, REACTIVE_LANE_READ, REACTIVE_LAZY, REACTIVE_MANUAL_WRITE, REACTIVE_MISSED_WAKE, REACTIVE_NONE, REACTIVE_PROBED, REACTIVE_PROBE_UNANSWERED, REACTIVE_REASK, REACTIVE_RECOMPUTING_DEPS, REACTIVE_SCREEN_READ, REACTIVE_SNAPSHOT_STALE, REACTIVE_STAGED_READ, REACTIVE_ZOMBIE, STATUS_ERROR, STATUS_NONE, STATUS_NO_VALUE, STATUS_PENDING, STATUS_UNINITIALIZED, SUPPORTS_PROXY, defaultContext };
|
|
269
|
+
export { $REFRESH, CAUGHT_REARMED, CONFIG_ASYNC, CONFIG_AUTHORITATIVE, CONFIG_AUTO_DISPOSE, CONFIG_CHILDREN_FORBIDDEN, CONFIG_FRAME, CONFIG_FRESH_READ, CONFIG_GUESS, CONFIG_HAS_SNAPSHOT, CONFIG_HELD, CONFIG_HELD_FRAME, CONFIG_INPUTS_PUBLISHED, CONFIG_IN_SNAPSHOT_SCOPE, CONFIG_KEY_BAG, CONFIG_LAGS, CONFIG_MANUAL_WRITE, CONFIG_NO_SNAPSHOT, CONFIG_OVERRIDE, CONFIG_OWNED_WRITE, CONFIG_PLUMBING, CONFIG_PROMOTED, CONFIG_REDERIVE, CONFIG_SLOT_NODE, CONFIG_STAGED, CONFIG_STAGED_ERROR, CONFIG_SYNC, CONFIG_TRANSPARENT, CONFIG_VERDICT, EFFECT_RENDER, EFFECT_TRACKED, EFFECT_USER, NOT_PENDING, NO_SNAPSHOT, NewSet, REACTIVE_CHECK, REACTIVE_DIRTY, REACTIVE_DISPOSED, REACTIVE_FRAME_READ, REACTIVE_IN_HEAP, REACTIVE_IN_HEAP_HEIGHT, REACTIVE_JOINED, REACTIVE_LANE_DIRTY, REACTIVE_LANE_READ, REACTIVE_LAZY, REACTIVE_MANUAL_WRITE, REACTIVE_MISSED_WAKE, REACTIVE_NONE, REACTIVE_PROBED, REACTIVE_PROBE_UNANSWERED, REACTIVE_REASK, REACTIVE_RECOMPUTING_DEPS, REACTIVE_SCREEN_READ, REACTIVE_SNAPSHOT_STALE, REACTIVE_STAGED_READ, REACTIVE_WINDOW, REACTIVE_ZOMBIE, STATUS_ERROR, STATUS_NONE, STATUS_NO_VALUE, STATUS_PENDING, STATUS_UNINITIALIZED, SUPPORTS_PROXY, defaultContext };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** @internal Runs `fn` with this copy marked as the one running. */
|
|
2
|
+
function runAsSolidCopy(n) {
|
|
3
|
+
return n();
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
/** @internal An ownerless component or context read: warns if another copy is running. */ function checkForeignOwnerless() {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export { checkForeignOwnerless, runAsSolidCopy };
|