@solidjs/signals 2.0.0-rc.18 → 2.0.0-rc.19
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 +168 -88
- package/dist/dev.attribution.js +16 -13
- package/dist/dev.js +272 -129
- package/dist/observe/boundaries.js +88 -67
- package/dist/observe/core/action.js +8 -0
- package/dist/observe/core/async.js +46 -34
- package/dist/observe/core/attribution.js +30 -28
- package/dist/observe/core/constants.js +21 -1
- package/dist/observe/core/core.js +164 -136
- package/dist/observe/core/effect.js +6 -6
- package/dist/observe/core/graph.js +3 -3
- package/dist/observe/core/heap.js +5 -5
- package/dist/observe/core/lanes.js +104 -84
- package/dist/observe/core/owner.js +10 -9
- package/dist/observe/core/scheduler.js +38 -35
- package/dist/observe/core/truth.js +6 -6
- package/dist/observe/core/verdict.js +13 -13
- package/dist/observe/deferred.js +39 -40
- package/dist/observe/index.js +2 -2
- package/dist/observe/map.js +22 -22
- package/dist/observe/reveal.js +5 -5
- package/dist/observe/signals.js +57 -15
- package/dist/observe/store/affects.js +1 -1
- package/dist/observe/store/hooks.js +3 -0
- package/dist/observe/store/optimistic.js +11 -11
- package/dist/observe/store/projection.js +34 -21
- package/dist/observe/store/reconcile.js +2 -2
- package/dist/observe/store/store.js +63 -53
- package/dist/observe/store/utils.js +7 -2
- package/dist/prod/boundaries.js +153 -132
- package/dist/prod/core/action.js +8 -0
- package/dist/prod/core/async.js +55 -43
- package/dist/prod/core/constants.js +14 -1
- package/dist/prod/core/core.js +162 -134
- package/dist/prod/core/effect.js +9 -9
- package/dist/prod/core/graph.js +3 -3
- package/dist/prod/core/heap.js +12 -12
- package/dist/prod/core/lanes.js +98 -78
- package/dist/prod/core/owner.js +15 -14
- package/dist/prod/core/scheduler.js +43 -40
- package/dist/prod/core/truth.js +6 -6
- package/dist/prod/core/verdict.js +17 -17
- package/dist/prod/deferred.js +39 -40
- package/dist/prod/index.js +2 -2
- package/dist/prod/map.js +14 -14
- package/dist/prod/reveal.js +8 -8
- package/dist/prod/signals.js +46 -4
- package/dist/prod/store/affects.js +1 -1
- package/dist/prod/store/hooks.js +3 -0
- package/dist/prod/store/optimistic.js +16 -16
- package/dist/prod/store/projection.js +22 -9
- package/dist/prod/store/reconcile.js +2 -2
- package/dist/prod/store/store.js +262 -262
- package/dist/prod/store/utils.js +2 -0
- package/dist/types/core/action.d.ts +8 -0
- package/dist/types/core/constants.d.ts +20 -0
- package/dist/types/core/core.d.ts +14 -1
- package/dist/types/core/dev.d.ts +1 -1
- package/dist/types/core/index.d.ts +1 -1
- package/dist/types/core/lanes.d.ts +5 -1
- package/dist/types/core/scheduler.d.ts +2 -0
- package/dist/types/index.d.ts +3 -1
- package/dist/types/signals.d.ts +37 -0
- package/dist/types/store/target.d.ts +2 -0
- package/package.json +1 -1
package/dist/dev.js
CHANGED
|
@@ -33,8 +33,8 @@ import {
|
|
|
33
33
|
A as tracking,
|
|
34
34
|
B as CONFIG_CHILDREN_FORBIDDEN,
|
|
35
35
|
D as passLane,
|
|
36
|
-
E as
|
|
37
|
-
F as
|
|
36
|
+
E as EFFECT_RENDER,
|
|
37
|
+
F as setPassLane,
|
|
38
38
|
H as sameLane,
|
|
39
39
|
I as flushTransaction,
|
|
40
40
|
J as REACTIVE_SCREEN_READ,
|
|
@@ -44,15 +44,15 @@ import {
|
|
|
44
44
|
O as REACTIVE_IN_HEAP,
|
|
45
45
|
P as REACTIVE_DIRTY,
|
|
46
46
|
Q as REACTIVE_CHECK,
|
|
47
|
-
T as
|
|
48
|
-
U as
|
|
49
|
-
V as
|
|
50
|
-
W as
|
|
51
|
-
X as
|
|
52
|
-
Y as
|
|
53
|
-
Z as
|
|
54
|
-
_ as
|
|
55
|
-
$ as
|
|
47
|
+
T as STATUS_PENDING,
|
|
48
|
+
U as CONFIG_INPUTS_PUBLISHED,
|
|
49
|
+
V as releaseQueues,
|
|
50
|
+
W as CONFIG_SLOT_NODE,
|
|
51
|
+
X as holdNode,
|
|
52
|
+
Y as joinFuture,
|
|
53
|
+
Z as reruns,
|
|
54
|
+
_ as CONFIG_STAGED,
|
|
55
|
+
$ as merge$1,
|
|
56
56
|
a0 as REACTIVE_JOINED,
|
|
57
57
|
a1 as REACTIVE_STAGED_READ,
|
|
58
58
|
a2 as stagedRead,
|
|
@@ -161,31 +161,33 @@ import {
|
|
|
161
161
|
bF as joinPassAt,
|
|
162
162
|
bG as notifyEpoch,
|
|
163
163
|
bH as SUPPORTS_PROXY,
|
|
164
|
-
bI as
|
|
165
|
-
bJ as
|
|
166
|
-
bK as
|
|
167
|
-
bL as
|
|
168
|
-
bM as
|
|
169
|
-
bN as
|
|
170
|
-
bO as
|
|
171
|
-
bP as
|
|
172
|
-
bQ as
|
|
173
|
-
bR as
|
|
174
|
-
bS as
|
|
175
|
-
bT as
|
|
176
|
-
bU as
|
|
164
|
+
bI as CONFIG_KEY_BAG,
|
|
165
|
+
bJ as releaseMarksHook,
|
|
166
|
+
bK as installMarkHooks,
|
|
167
|
+
bL as CONFIG_LAGS,
|
|
168
|
+
bM as REACTIVE_REASK,
|
|
169
|
+
bN as onSupersede,
|
|
170
|
+
bO as haltReactivity,
|
|
171
|
+
bP as CONFIG_FRAME,
|
|
172
|
+
bQ as heldUnder,
|
|
173
|
+
bR as unhold,
|
|
174
|
+
bS as laneStageHook,
|
|
175
|
+
bT as REACTIVE_ZOMBIE,
|
|
176
|
+
bU as installBoundaryHooks,
|
|
177
|
+
bV as CAUGHT_REARMED,
|
|
178
|
+
bW as OBSERVE$1
|
|
177
179
|
} from "./dev-shared.js";
|
|
178
180
|
export {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
181
|
+
bX as clearSnapshots,
|
|
182
|
+
bY as enforceLoadingBoundary,
|
|
183
|
+
bZ as getNextChildId,
|
|
184
|
+
b_ as markSnapshotScope,
|
|
185
|
+
b$ as peekNextChildId,
|
|
186
|
+
c0 as releaseSnapshotScope,
|
|
187
|
+
c1 as resetErrorHalt,
|
|
188
|
+
c2 as setConsoleFooter,
|
|
189
|
+
c3 as setSnapshotCapture,
|
|
190
|
+
c4 as setWriteHook
|
|
189
191
|
} from "./dev-shared.js";
|
|
190
192
|
|
|
191
193
|
// Truth reads (`until`, `refresh`; CONFIG_AUTHORITATIVE) over lane nodes.
|
|
@@ -700,7 +702,11 @@ function dissolveLane(l, into, except) {
|
|
|
700
702
|
* has shown, or one the seam has not judged yet (its run waits on the
|
|
701
703
|
* verdict: released if the lane shows, held if it blocks) — and sees the
|
|
702
704
|
* lane's latest. NOT_PENDING falls through: lane work's read of a pending
|
|
703
|
-
* member throws like any.
|
|
705
|
+
* member throws like any. A verdict reader entering a lane the seam has
|
|
706
|
+
* not judged reads ahead of it like a staging read: if the seam holds the
|
|
707
|
+
* lane, the pass re-derives on the screen (`entered`, #4284) — `latest()`
|
|
708
|
+
* beside the lane's nodes tears ahead of the hold however the reads are
|
|
709
|
+
* grouped into effects. */
|
|
704
710
|
function laneRead(c, el) {
|
|
705
711
|
const guess = el._config & CONFIG_GUESS;
|
|
706
712
|
const l = txOf(el);
|
|
@@ -718,6 +724,7 @@ function laneRead(c, el) {
|
|
|
718
724
|
// An errored member's lane value predates its error; the error is the answer (#4106).
|
|
719
725
|
if (!guess && status & STATUS_ERROR) return NOT_PENDING;
|
|
720
726
|
if (c === null) return laneValueOf(el);
|
|
727
|
+
const pending = !guess && status & STATUS_PENDING;
|
|
721
728
|
if (!tracking || c._config & CONFIG_CHILDREN_FORBIDDEN) {
|
|
722
729
|
// An untracked read inside lane work derives from the lane like a
|
|
723
730
|
// tracked one, minus the subscription — `untrack` is about
|
|
@@ -726,40 +733,47 @@ function laneRead(c, el) {
|
|
|
726
733
|
// lanes read by one pass link, as for tracked reads). Outside lane
|
|
727
734
|
// work, the screen.
|
|
728
735
|
if (passLane === null || c._config & CONFIG_CHILDREN_FORBIDDEN) return display(el);
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
736
|
+
} else if (c._type === EFFECT_RENDER) {
|
|
737
|
+
// A flight whose value has never shown: nothing to show — the leaf
|
|
738
|
+
// waits on it, and its own frame holds (A15, #3334), not the lane's
|
|
739
|
+
// parent. The landing lands the frame: its own pass (the flush joined
|
|
740
|
+
// its transaction) reads the answer it waited on — the lane's staging,
|
|
741
|
+
// revealed at this seam.
|
|
742
|
+
const never = pending && el._x._lane === NOT_PENDING;
|
|
743
|
+
// D-28: a leaf a verdict read moved into the lane still throws on such
|
|
744
|
+
// a flight — the pass leaves the lane, and its frame holds as if the
|
|
745
|
+
// read had come first (S-39, #4275). Nor does a verdict lane's seat carry
|
|
746
|
+
// the leaf into another lane (no link): it reads that lane as from the
|
|
747
|
+
// frame's seat (#4284).
|
|
748
|
+
if ((never || passLane !== l) && passLane?._parent._verdict === passLane) setPassLane(null);
|
|
749
|
+
if (passLane === null || !sameLane(passLane, l)) {
|
|
750
|
+
// (A lane that has never shown: the screen is the committed value.)
|
|
751
|
+
if (never && l._shown) return NOT_PENDING;
|
|
741
752
|
if (
|
|
753
|
+
!guess &&
|
|
742
754
|
el._pendingValue !== NOT_PENDING &&
|
|
743
755
|
c._config & CONFIG_HELD &&
|
|
744
756
|
flushTransaction !== null &&
|
|
745
757
|
resolveTx(flushTransaction) === txOf(c)
|
|
746
758
|
)
|
|
747
759
|
return el._pendingValue;
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
760
|
+
if (l._held || pending) {
|
|
761
|
+
if (!guess && !l._shown && status & STATUS_UNINITIALIZED) throw new NotReadyError(null);
|
|
762
|
+
// Re-derived at the reveal; once per pass (the pass may also be a stale
|
|
763
|
+
// reader of a transaction, REACTIVE_FRAME_READ — both reruns apply).
|
|
764
|
+
if (!(c._flags & REACTIVE_SCREEN_READ)) {
|
|
765
|
+
c._flags |= REACTIVE_FRAME_READ | REACTIVE_SCREEN_READ;
|
|
766
|
+
l._reruns.push(c);
|
|
767
|
+
}
|
|
768
|
+
return display(el);
|
|
756
769
|
}
|
|
757
|
-
|
|
770
|
+
// A verdict reader reads ahead of the seam's verdict: re-derived on the
|
|
771
|
+
// screen if the lane holds (#4284).
|
|
772
|
+
if (c._config & CONFIG_VERDICT && l._parent._verdict !== l) entered.push(c);
|
|
758
773
|
}
|
|
759
774
|
}
|
|
760
775
|
enterLane(l, c);
|
|
761
|
-
|
|
762
|
-
return laneValueOf(el);
|
|
776
|
+
return pending ? NOT_PENDING : laneValueOf(el);
|
|
763
777
|
}
|
|
764
778
|
/** The value a guess covered: the node's committed value — a store slot's
|
|
765
779
|
* asked of the store (a chained link follows the inner store's commits). */
|
|
@@ -992,7 +1006,17 @@ const laneSeams = leaks => {
|
|
|
992
1006
|
}
|
|
993
1007
|
for (let k = Math.min(judged, lanes.length) - 1; k >= 0; k--)
|
|
994
1008
|
laneSeam(lanes[k], leaked.indexOf(lanes[k]) !== -1);
|
|
1009
|
+
// A verdict reader that entered a lane this seam held: its run waits with
|
|
1010
|
+
// the lane, and the verdict beside it would freeze — it re-derives next
|
|
1011
|
+
// round from the frame's seat, a stale reader of the lane (#4284).
|
|
1012
|
+
for (let r; (r = entered.pop()); )
|
|
1013
|
+
if (r._x._transaction?._held) {
|
|
1014
|
+
r._flags &= ~REACTIVE_LANE_DIRTY;
|
|
1015
|
+
enqueueSub(r);
|
|
1016
|
+
}
|
|
995
1017
|
};
|
|
1018
|
+
/** Render effects that read a verdict and entered a lane before its seam (#4284). */
|
|
1019
|
+
const entered = [];
|
|
996
1020
|
installLaneHooks(
|
|
997
1021
|
laneRead,
|
|
998
1022
|
laneStage,
|
|
@@ -1510,6 +1534,14 @@ function inTransaction(t, q, fn) {
|
|
|
1510
1534
|
* yield until(() => todos.some(t => t.id === saved.id));
|
|
1511
1535
|
* ```
|
|
1512
1536
|
*
|
|
1537
|
+
* The same holds inside an async helper the action yields
|
|
1538
|
+
* (`yield (async () => { ... })()`): everything after its first `await` runs
|
|
1539
|
+
* outside the transaction. An `await refresh(x)` or `await until(...)` there
|
|
1540
|
+
* waits for this action's commit, which waits on the helper, so it hangs
|
|
1541
|
+
* whenever `x` re-ran during the action (#4263) and works otherwise. Call
|
|
1542
|
+
* `refresh(x)` in the generator once the helper returns; `yield` it only when
|
|
1543
|
+
* the action needs the fresh value.
|
|
1544
|
+
*
|
|
1513
1545
|
* (For the same reason, don't call `flush()` inside an action body — it
|
|
1514
1546
|
* cannot reveal the held writes and is refused.)
|
|
1515
1547
|
*
|
|
@@ -3093,6 +3125,65 @@ function onSettled(callback) {
|
|
|
3093
3125
|
}
|
|
3094
3126
|
});
|
|
3095
3127
|
}
|
|
3128
|
+
/**
|
|
3129
|
+
* Schedules `callback` to run **once**, right after the pending flush
|
|
3130
|
+
* finishes, in the same microtask checkpoint (before the browser paints).
|
|
3131
|
+
* Unlike `onSettled`, it never waits on async work: if that flush is held by
|
|
3132
|
+
* a pending transition, the callback still runs.
|
|
3133
|
+
*
|
|
3134
|
+
* Its main use is keeping a write out of another update's hold. Writes made
|
|
3135
|
+
* in the same synchronous frame are applied together, so when one of them
|
|
3136
|
+
* starts async work (a route change, a fetch), the others are held with it
|
|
3137
|
+
* until it resolves. A write made in `onFlush` happens after that flush, so
|
|
3138
|
+
* it is its own update: it commits on its own unless something it changes
|
|
3139
|
+
* also derives from the held work (a memo or `createEffect` reading both),
|
|
3140
|
+
* in which case it joins that hold as any later write would.
|
|
3141
|
+
*
|
|
3142
|
+
* Call it from event handlers and effect callbacks (including
|
|
3143
|
+
* `createTrackedEffect` and `onSettled` bodies). In an owned scope such as a
|
|
3144
|
+
* component body or a computation it warns in dev: use `onSettled` there.
|
|
3145
|
+
*
|
|
3146
|
+
* - A write in the callback lands after any write made inline in the same
|
|
3147
|
+
* frame. Don't write the same signal both inside and outside it; use a
|
|
3148
|
+
* functional setter if the order matters.
|
|
3149
|
+
* - Several `onFlush` callbacks run in call order and batch into one flush.
|
|
3150
|
+
* - `queueMicrotask` is not a substitute: called before the frame's first
|
|
3151
|
+
* write, it runs before that flush and its write joins it.
|
|
3152
|
+
*
|
|
3153
|
+
* @example
|
|
3154
|
+
* ```tsx
|
|
3155
|
+
* // A menu closes now even when the consumer's onSelect starts async work.
|
|
3156
|
+
* const select = (id: string) => {
|
|
3157
|
+
* onFlush(() => setOpen(false));
|
|
3158
|
+
* props.onSelect?.(id);
|
|
3159
|
+
* };
|
|
3160
|
+
* ```
|
|
3161
|
+
*
|
|
3162
|
+
* @param callback Function to run once after the pending flush
|
|
3163
|
+
*/
|
|
3164
|
+
function onFlush(callback) {
|
|
3165
|
+
{
|
|
3166
|
+
const owner = getOwner();
|
|
3167
|
+
if (owner && !(owner._config & CONFIG_CHILDREN_FORBIDDEN)) {
|
|
3168
|
+
const message =
|
|
3169
|
+
"[ON_FLUSH_IN_OWNED_SCOPE] onFlush called in an owned scope (a component body or a computation). It is meant for event handlers and effect callbacks; to run work after this scope's first stable render, use onSettled.";
|
|
3170
|
+
reportDiagnostic(
|
|
3171
|
+
emitDiagnostic({
|
|
3172
|
+
code: "ON_FLUSH_IN_OWNED_SCOPE",
|
|
3173
|
+
kind: "lifecycle",
|
|
3174
|
+
severity: "warn",
|
|
3175
|
+
message,
|
|
3176
|
+
ownerId: owner.id,
|
|
3177
|
+
ownerName: owner._name
|
|
3178
|
+
})
|
|
3179
|
+
);
|
|
3180
|
+
}
|
|
3181
|
+
}
|
|
3182
|
+
// The frame's flush is queued (or already draining) ahead of this
|
|
3183
|
+
// microtask, so the callback's writes start a flush of their own.
|
|
3184
|
+
schedule();
|
|
3185
|
+
queueMicrotask(callback);
|
|
3186
|
+
}
|
|
3096
3187
|
|
|
3097
3188
|
function mapArray(list, map, options) {
|
|
3098
3189
|
const keyFn = typeof options?.keyed === "function" ? options.keyed : undefined;
|
|
@@ -3721,6 +3812,9 @@ function compare(key, a, b) {
|
|
|
3721
3812
|
return key ? key(a) === key(b) : true;
|
|
3722
3813
|
}
|
|
3723
3814
|
|
|
3815
|
+
// Set before any family is optimistic (`fam.opt`): a call site checks the
|
|
3816
|
+
// hooks first, so a build that does not import optimistic.ts folds the arm
|
|
3817
|
+
// away.
|
|
3724
3818
|
let optHooks = null;
|
|
3725
3819
|
function installOptHooks(hooks) {
|
|
3726
3820
|
optHooks = hooks;
|
|
@@ -4272,7 +4366,7 @@ function ensurePB(target) {
|
|
|
4272
4366
|
// An optimistic edit composes on the view the user saw and becomes
|
|
4273
4367
|
// guesses at the setter's exit: nothing is staged, nothing folds
|
|
4274
4368
|
// (optimistic.ts).
|
|
4275
|
-
if (userWrite && target.fam?.opt === true && !pendingNotify.has(target))
|
|
4369
|
+
if (optHooks && userWrite && target.fam?.opt === true && !pendingNotify.has(target))
|
|
4276
4370
|
return (target.pb = optHooks.draft(target));
|
|
4277
4371
|
if (pb !== null && !isOwned(pb)) {
|
|
4278
4372
|
// An adopted object awaiting its fold is the user's: the draft writes a
|
|
@@ -4552,9 +4646,9 @@ function foldTarget(t, old) {
|
|
|
4552
4646
|
else delete v[key];
|
|
4553
4647
|
}
|
|
4554
4648
|
} else {
|
|
4555
|
-
for (const key of Reflect.ownKeys(pb)) copyOwn(v, pb, key);
|
|
4649
|
+
for (const key of Reflect.ownKeys(pb)) if (key !== $OWNER) copyOwn(v, pb, key);
|
|
4556
4650
|
for (const key of Reflect.ownKeys(old)) {
|
|
4557
|
-
if (!hasOwn$1.call(pb, key)) delete v[key];
|
|
4651
|
+
if (key !== $OWNER && !hasOwn$1.call(pb, key)) delete v[key];
|
|
4558
4652
|
}
|
|
4559
4653
|
}
|
|
4560
4654
|
} else {
|
|
@@ -4604,6 +4698,9 @@ function reportReplacedContainers(t, old, pb, writtenKeys) {
|
|
|
4604
4698
|
const keys = writtenKeys ?? Reflect.ownKeys(pb);
|
|
4605
4699
|
const isArray = Array.isArray(pb);
|
|
4606
4700
|
const owner = storeRootOwner(t);
|
|
4701
|
+
// Items the array held before the write: an index that now holds one of
|
|
4702
|
+
// them was moved into place (an in-place splice / shift), not replaced.
|
|
4703
|
+
let oldArrayItems = null;
|
|
4607
4704
|
for (const key of keys) {
|
|
4608
4705
|
if ((isArray && key === "length") || key === $OWNER) continue;
|
|
4609
4706
|
if (t.del?.has(key)) continue;
|
|
@@ -4618,6 +4715,13 @@ function reportReplacedContainers(t, old, pb, writtenKeys) {
|
|
|
4618
4715
|
targetsEqual(ov, nv)
|
|
4619
4716
|
)
|
|
4620
4717
|
continue;
|
|
4718
|
+
if (isArray) {
|
|
4719
|
+
if (oldArrayItems === null) {
|
|
4720
|
+
oldArrayItems = new Set();
|
|
4721
|
+
for (const item of old) oldArrayItems.add(unwrapValue(item));
|
|
4722
|
+
}
|
|
4723
|
+
if (oldArrayItems.has(nv)) continue;
|
|
4724
|
+
}
|
|
4621
4725
|
const isArr = Array.isArray(nv);
|
|
4622
4726
|
if (isArr !== Array.isArray(ov)) continue;
|
|
4623
4727
|
let total;
|
|
@@ -4679,7 +4783,7 @@ function notifyWrites(t) {
|
|
|
4679
4783
|
// Optimistic channel: a user's writes on an optimistic family become
|
|
4680
4784
|
// guesses on the nodes (lanes); the draft is discarded, the committed
|
|
4681
4785
|
// backing never touched.
|
|
4682
|
-
if (userWrite && t.fam?.opt === true) {
|
|
4786
|
+
if (optHooks && userWrite && t.fam?.opt === true) {
|
|
4683
4787
|
// The draft is discarded first: the diff reads the target (its nodes
|
|
4684
4788
|
// are born from the committed frame, not the draft).
|
|
4685
4789
|
t.pb = null;
|
|
@@ -5353,10 +5457,10 @@ function enumerationSource(target) {
|
|
|
5353
5457
|
// A container's arrangement guess is not a backing: the view composes
|
|
5354
5458
|
// over the base it is shown over.
|
|
5355
5459
|
const base = asBacking(read(getContainerNode(target)));
|
|
5356
|
-
return target.fam?.opt === true ? optHooks.view(target, base) : base;
|
|
5460
|
+
return optHooks && target.fam?.opt === true ? optHooks.view(target, base) : base;
|
|
5357
5461
|
}
|
|
5358
5462
|
const src = readSource(target);
|
|
5359
|
-
return optRead(target) ? optHooks.view(target, src) : src;
|
|
5463
|
+
return optHooks && optRead(target) ? optHooks.view(target, src) : src;
|
|
5360
5464
|
}
|
|
5361
5465
|
/** A read on an optimistic family that composes the lanes' values: not the
|
|
5362
5466
|
* draft's (it composed already), not a derive's write-override read (the
|
|
@@ -5616,7 +5720,7 @@ const traps = {
|
|
|
5616
5720
|
node._value = present; // the link follows the inner store (S4)
|
|
5617
5721
|
if (node._config & CONFIG_OVERRIDE) return !!nv;
|
|
5618
5722
|
return present;
|
|
5619
|
-
} else if (optRead(target)) {
|
|
5723
|
+
} else if (optHooks && optRead(target)) {
|
|
5620
5724
|
const guessed = optHooks.has(target, key);
|
|
5621
5725
|
if (guessed !== undefined) return guessed;
|
|
5622
5726
|
}
|
|
@@ -5656,7 +5760,7 @@ const traps = {
|
|
|
5656
5760
|
return undefined;
|
|
5657
5761
|
} else src = readSource(target, key, true);
|
|
5658
5762
|
let desc;
|
|
5659
|
-
if (!enumerating && optRead(target)) {
|
|
5763
|
+
if (optHooks && !enumerating && optRead(target)) {
|
|
5660
5764
|
const guessed = optHooks.descriptor(target, key);
|
|
5661
5765
|
if (guessed === null) return undefined;
|
|
5662
5766
|
desc = guessed;
|
|
@@ -5850,7 +5954,7 @@ function storeSetter(proxy, fn, guard = true) {
|
|
|
5850
5954
|
// A returned replacement: on an optimistic family a user's is itself an
|
|
5851
5955
|
// optimistic edit — diffed against the view as guesses (`next` parity);
|
|
5852
5956
|
// otherwise it is adopted as the incoming truth.
|
|
5853
|
-
if (guard && target.fam?.opt === true && !writeOverride)
|
|
5957
|
+
if (optHooks && guard && target.fam?.opt === true && !writeOverride)
|
|
5854
5958
|
optHooks.writes(target, unwrapValue(result));
|
|
5855
5959
|
else adoptPB(target, unwrapValue(result));
|
|
5856
5960
|
}
|
|
@@ -6030,7 +6134,7 @@ function snapshotWalk(value, seen, fam) {
|
|
|
6030
6134
|
if (t.ovl) materializePB(t);
|
|
6031
6135
|
backing = t.pb;
|
|
6032
6136
|
}
|
|
6033
|
-
if (optRead(t)) backing = optHooks.view(t, backing);
|
|
6137
|
+
if (optHooks && optRead(t)) backing = optHooks.view(t, backing);
|
|
6034
6138
|
if (backing === src) break;
|
|
6035
6139
|
src = backing;
|
|
6036
6140
|
}
|
|
@@ -6206,7 +6310,7 @@ function reconcileState(value, state, key, replace = false) {
|
|
|
6206
6310
|
// truth but an optimistic edit — the keyed diff is written into the draft
|
|
6207
6311
|
// (a matched row keeps its proxy, its changed leaves become its guesses),
|
|
6208
6312
|
// and the setter's exit turns the draft into guesses like any.
|
|
6209
|
-
if (userWriting() && t.fam?.opt === true) {
|
|
6313
|
+
if (optHooks && userWriting() && t.fam?.opt === true) {
|
|
6210
6314
|
optHooks.reconcile(state, unwrapValue(value), keyFn);
|
|
6211
6315
|
return;
|
|
6212
6316
|
}
|
|
@@ -6247,7 +6351,7 @@ function applyAdopt(t, incoming, keyFn, proj = false) {
|
|
|
6247
6351
|
// Q-D: a landing on an optimistic family is reconciled against the VIEW
|
|
6248
6352
|
// — key matching from the arrangement the guesses made (R28), so a row
|
|
6249
6353
|
// the guess added keeps its proxy when the server returns it.
|
|
6250
|
-
const prevView = t.fam?.opt === true ? optHooks.view(t, old) : old;
|
|
6354
|
+
const prevView = optHooks && t.fam?.opt === true ? optHooks.view(t, old) : old;
|
|
6251
6355
|
const nextArr = Array.isArray(incoming);
|
|
6252
6356
|
const shallow = t.s === true;
|
|
6253
6357
|
adoptPB(t, incoming, false);
|
|
@@ -6563,8 +6667,14 @@ function cloneState(v, shallow) {
|
|
|
6563
6667
|
* pending derivatively on the derive (its readers hold; it re-runs at the
|
|
6564
6668
|
* landing). The leaves do not subscribe to the derive, so the family does
|
|
6565
6669
|
* the walk. */
|
|
6566
|
-
function wakeFamily(fam
|
|
6670
|
+
function wakeFamily(fam) {
|
|
6567
6671
|
const fw = fam.node;
|
|
6672
|
+
// Pending on the derive itself, whatever source took it there (an upstream
|
|
6673
|
+
// memo's flight reaches it as a NotReady of that memo, #4271): the leaves
|
|
6674
|
+
// are not that source's dependents, so only the family's settle — which
|
|
6675
|
+
// retires the derive (`settleFamily`) — reaches the readers parked here. A
|
|
6676
|
+
// reader the landing leaves unchanged does not re-run to clear it (#4305).
|
|
6677
|
+
const error = new NotReadyError(fw);
|
|
6568
6678
|
fam.woke = true;
|
|
6569
6679
|
forEachFamilyNode(fam, n => {
|
|
6570
6680
|
if (n._subs === null) return;
|
|
@@ -6602,6 +6712,13 @@ function settleFamily(fam) {
|
|
|
6602
6712
|
if (n._subs !== null) settlePendingSource(n, fw);
|
|
6603
6713
|
});
|
|
6604
6714
|
}
|
|
6715
|
+
/** A source's status reached the derive by propagation (core
|
|
6716
|
+
* `propagateStatus`), its pass not re-run: the family learns it as from the
|
|
6717
|
+
* pass's own throw. */
|
|
6718
|
+
function familyStatus(status) {
|
|
6719
|
+
if (status & STATUS_PENDING) wakeFamily(this);
|
|
6720
|
+
else if (status & STATUS_ERROR) errorFamily(this);
|
|
6721
|
+
}
|
|
6605
6722
|
function forEachFamilyNode(fam, fn) {
|
|
6606
6723
|
for (const t of fam.live) {
|
|
6607
6724
|
const nodes = t.n;
|
|
@@ -6688,7 +6805,7 @@ function runProjectionComputed(wrappedStore, fn, key, wrapCommit, aroundDraftWri
|
|
|
6688
6805
|
// #2897) — and the flush that runs them advances the clock, so a
|
|
6689
6806
|
// later tracked re-read may retry (core `read`).
|
|
6690
6807
|
if (first && owner._statusFlags & STATUS_UNINITIALIZED) return;
|
|
6691
|
-
if (pending) wakeFamily(fam
|
|
6808
|
+
if (pending) wakeFamily(fam);
|
|
6692
6809
|
else errorFamily(fam);
|
|
6693
6810
|
});
|
|
6694
6811
|
if (!owner._loading) commit(sync);
|
|
@@ -6703,7 +6820,7 @@ function runProjectionComputed(wrappedStore, fn, key, wrapCommit, aroundDraftWri
|
|
|
6703
6820
|
// they do not subscribe to the derive.
|
|
6704
6821
|
// A synchronous error the same way (#3956: a rerun that finds the
|
|
6705
6822
|
// entry failed throws): every live reader re-derives and meets it.
|
|
6706
|
-
if (!first) e instanceof NotReadyError ? wakeFamily(fam
|
|
6823
|
+
if (!first) e instanceof NotReadyError ? wakeFamily(fam) : errorFamily(fam);
|
|
6707
6824
|
throw e;
|
|
6708
6825
|
}
|
|
6709
6826
|
// A pass that returned with a flight up (an iterator's sync first yield):
|
|
@@ -6716,7 +6833,7 @@ function runProjectionComputed(wrappedStore, fn, key, wrapCommit, aroundDraftWri
|
|
|
6716
6833
|
!owner._loading &&
|
|
6717
6834
|
!first
|
|
6718
6835
|
)
|
|
6719
|
-
wakeFamily(fam
|
|
6836
|
+
wakeFamily(fam);
|
|
6720
6837
|
return owner;
|
|
6721
6838
|
}
|
|
6722
6839
|
function createProjectionInternal(fn, seed, options) {
|
|
@@ -6728,6 +6845,7 @@ function createProjectionInternal(fn, seed, options) {
|
|
|
6728
6845
|
map: new WeakMap(),
|
|
6729
6846
|
node: null,
|
|
6730
6847
|
live: new Set(),
|
|
6848
|
+
st: familyStatus,
|
|
6731
6849
|
shallow: !!options?.shallow,
|
|
6732
6850
|
// The row key, for a child paired after the adoption (store.ts
|
|
6733
6851
|
// `adoptChild`, #3712) as the adoption pairs them.
|
|
@@ -8267,7 +8385,9 @@ function merge(...sources) {
|
|
|
8267
8385
|
count++;
|
|
8268
8386
|
only = s;
|
|
8269
8387
|
if (typeof s === "function") {
|
|
8270
|
-
|
|
8388
|
+
// Observe tiers name it and exempt it from UNSTABLE_MEMO_OUTPUT (see
|
|
8389
|
+
// CONFIG_KEY_BAG); prod passes no options.
|
|
8390
|
+
flattened[n] = createMemo(s, { name: "merge", _extraConfig: CONFIG_KEY_BAG });
|
|
8271
8391
|
kinds[n++] = SOURCE_MEMO;
|
|
8272
8392
|
continue;
|
|
8273
8393
|
}
|
|
@@ -8574,7 +8694,7 @@ function walk(value, entry, found, fam, visited) {
|
|
|
8574
8694
|
if (t !== undefined) {
|
|
8575
8695
|
if (t.pb !== null) entry._scope.add(t.v);
|
|
8576
8696
|
// The writer's view: the tick's own unflushed guesses are in motion too.
|
|
8577
|
-
if (t.fam?.opt === true) raw = optHooks.view(t, raw, true);
|
|
8697
|
+
if (optHooks && t.fam?.opt === true) raw = optHooks.view(t, raw, true);
|
|
8578
8698
|
const nodes = t.n;
|
|
8579
8699
|
if (nodes !== null)
|
|
8580
8700
|
for (const k of Reflect.ownKeys(nodes))
|
|
@@ -8882,9 +9002,41 @@ function createDeferred(fn, options) {
|
|
|
8882
9002
|
// Sticky, and read before this wrapper ever opens the window itself.
|
|
8883
9003
|
const open = (answered ||= !(node._statusFlags & STATUS_UNINITIALIZED) && !node._loading);
|
|
8884
9004
|
if (open) ((node._loading = true), (node._config |= CONFIG_LAGS));
|
|
8885
|
-
let r;
|
|
8886
9005
|
try {
|
|
8887
|
-
r = fn(prev);
|
|
9006
|
+
const r = fn(prev);
|
|
9007
|
+
if (open && typeof r === "object" && r !== null) {
|
|
9008
|
+
if (isThenable(r)) {
|
|
9009
|
+
ask(r);
|
|
9010
|
+
const done = () => land(r, true);
|
|
9011
|
+
r.then(done, done);
|
|
9012
|
+
return serve(r);
|
|
9013
|
+
}
|
|
9014
|
+
const iterate = r[Symbol.asyncIterator];
|
|
9015
|
+
if (iterate) {
|
|
9016
|
+
// A stream's flight ends at its first yield (or its end).
|
|
9017
|
+
const it = iterate.call(r);
|
|
9018
|
+
let first = true;
|
|
9019
|
+
const done = () => land(s, true);
|
|
9020
|
+
const s = {
|
|
9021
|
+
// Registered ahead of the engine's own reaction to the same
|
|
9022
|
+
// promise, as for a plain flight: verdict and value in one flush.
|
|
9023
|
+
next: v => {
|
|
9024
|
+
const p = it.next(v);
|
|
9025
|
+
if (first) {
|
|
9026
|
+
first = false;
|
|
9027
|
+
if (isThenable(p)) p.then(done, done);
|
|
9028
|
+
else done();
|
|
9029
|
+
}
|
|
9030
|
+
return p;
|
|
9031
|
+
},
|
|
9032
|
+
return: v => it.return?.(v) ?? Promise.resolve({ done: true, value: v })
|
|
9033
|
+
};
|
|
9034
|
+
ask(s);
|
|
9035
|
+
return serve({ [Symbol.asyncIterator]: () => s });
|
|
9036
|
+
}
|
|
9037
|
+
}
|
|
9038
|
+
land(flight);
|
|
9039
|
+
return r;
|
|
8888
9040
|
} catch (e) {
|
|
8889
9041
|
// The wrapping form: an unready source parks the node in the window,
|
|
8890
9042
|
// and the wait is its flight until the source's settle re-runs it.
|
|
@@ -8892,39 +9044,6 @@ function createDeferred(fn, options) {
|
|
|
8892
9044
|
else land(flight);
|
|
8893
9045
|
throw e;
|
|
8894
9046
|
}
|
|
8895
|
-
if (open && typeof r === "object" && r !== null) {
|
|
8896
|
-
if (isThenable(r)) {
|
|
8897
|
-
ask(r);
|
|
8898
|
-
const done = () => land(r, true);
|
|
8899
|
-
r.then(done, done);
|
|
8900
|
-
return serve(r);
|
|
8901
|
-
}
|
|
8902
|
-
const iterate = r[Symbol.asyncIterator];
|
|
8903
|
-
if (iterate) {
|
|
8904
|
-
// A stream's flight ends at its first yield (or its end).
|
|
8905
|
-
const it = iterate.call(r);
|
|
8906
|
-
let first = true;
|
|
8907
|
-
const done = () => land(s, true);
|
|
8908
|
-
const s = {
|
|
8909
|
-
// Registered ahead of the engine's own reaction to the same
|
|
8910
|
-
// promise, as for a plain flight: verdict and value in one flush.
|
|
8911
|
-
next: v => {
|
|
8912
|
-
const p = it.next(v);
|
|
8913
|
-
if (first) {
|
|
8914
|
-
first = false;
|
|
8915
|
-
if (isThenable(p)) p.then(done, done);
|
|
8916
|
-
else done();
|
|
8917
|
-
}
|
|
8918
|
-
return p;
|
|
8919
|
-
},
|
|
8920
|
-
return: v => it.return?.(v) ?? Promise.resolve({ done: true, value: v })
|
|
8921
|
-
};
|
|
8922
|
-
ask(s);
|
|
8923
|
-
return serve({ [Symbol.asyncIterator]: () => s });
|
|
8924
|
-
}
|
|
8925
|
-
}
|
|
8926
|
-
land(flight);
|
|
8927
|
-
return r;
|
|
8928
9047
|
}, options)
|
|
8929
9048
|
);
|
|
8930
9049
|
}
|
|
@@ -9277,6 +9396,9 @@ const BOUNDARY = Symbol("boundary");
|
|
|
9277
9396
|
* slot of (reveal.ts); a boundary clears it for its content — only direct
|
|
9278
9397
|
* children are slots. */
|
|
9279
9398
|
const REVEAL = Symbol("reveal");
|
|
9399
|
+
// Every call site checks the hooks themselves first (not only the slot or
|
|
9400
|
+
// controller, which are never set without them): a build that does not
|
|
9401
|
+
// import `createRevealOrder` folds the reveal-order arms away.
|
|
9280
9402
|
let revealHooks = null;
|
|
9281
9403
|
function setRevealHooks(h) {
|
|
9282
9404
|
revealHooks = h;
|
|
@@ -9314,7 +9436,7 @@ function caught(b, node, error) {
|
|
|
9314
9436
|
// nothing on screen. The fallback is instantiated once per show — a later
|
|
9315
9437
|
// error reaches it through the `error` accessor, which is why it is one.
|
|
9316
9438
|
if (!b._fallback) redraw(b);
|
|
9317
|
-
if (b._reveal !== null) revealHooks._changed(b._reveal);
|
|
9439
|
+
if (revealHooks && b._reveal !== null) revealHooks._changed(b._reveal);
|
|
9318
9440
|
}
|
|
9319
9441
|
/** A re-armed boundary found something pending: fresh again, and the swap
|
|
9320
9442
|
* the arming pass asked for is that pass's lane's (if any): the output is
|
|
@@ -9326,7 +9448,8 @@ function flip(b) {
|
|
|
9326
9448
|
b._lane = b._armLane;
|
|
9327
9449
|
const o = b._output;
|
|
9328
9450
|
if (!b._lane && o._config & CONFIG_HELD && txOf(o) !== flushTransaction) unhold(o);
|
|
9329
|
-
if (b._lane !== null && b._output !== null)
|
|
9451
|
+
if (laneStageHook && b._lane !== null && b._output !== null)
|
|
9452
|
+
laneStageHook(b._output, b._lane, true, false);
|
|
9330
9453
|
}
|
|
9331
9454
|
function redraw(b) {
|
|
9332
9455
|
if (b._output !== null && !(b._output._flags & (REACTIVE_DISPOSED | REACTIVE_ZOMBIE))) {
|
|
@@ -9354,7 +9477,7 @@ function catchStatus(node, flags, error) {
|
|
|
9354
9477
|
b._readers.size === 0
|
|
9355
9478
|
) {
|
|
9356
9479
|
if (b._fallback) redraw(b);
|
|
9357
|
-
if (b._reveal !== null) revealHooks._changed(b._reveal);
|
|
9480
|
+
if (revealHooks && b._reveal !== null) revealHooks._changed(b._reveal);
|
|
9358
9481
|
}
|
|
9359
9482
|
return false;
|
|
9360
9483
|
}
|
|
@@ -9488,7 +9611,7 @@ function boundarySeam() {
|
|
|
9488
9611
|
if (b._readers.size === 0) {
|
|
9489
9612
|
collecting.delete(b);
|
|
9490
9613
|
if (b._fallback) redraw(b);
|
|
9491
|
-
if (b._reveal !== null) revealHooks._changed(b._reveal);
|
|
9614
|
+
if (revealHooks && b._reveal !== null) revealHooks._changed(b._reveal);
|
|
9492
9615
|
}
|
|
9493
9616
|
}
|
|
9494
9617
|
}
|
|
@@ -9567,6 +9690,8 @@ function arm(b) {
|
|
|
9567
9690
|
return;
|
|
9568
9691
|
}
|
|
9569
9692
|
b._armed = true;
|
|
9693
|
+
// The swap is the change's work: the output joins it (D-13, #3540).
|
|
9694
|
+
b._output._config &= ~CONFIG_FRAME;
|
|
9570
9695
|
// A verdict read in `on` (`isPending`, or a memo of one — #3528's
|
|
9571
9696
|
// `createMemo(() => isPending(m2))`: the mark carries, core.ts `read`)
|
|
9572
9697
|
// whose frame has no transaction yet: the swap is still display-ahead — the frame gets one now (it lands
|
|
@@ -9646,7 +9771,7 @@ function createBoundary(type, fn, show, onFn) {
|
|
|
9646
9771
|
if (getOwner())
|
|
9647
9772
|
cleanup(() => {
|
|
9648
9773
|
collecting.delete(b);
|
|
9649
|
-
if (controller) revealHooks._unregister(controller, b);
|
|
9774
|
+
if (revealHooks && controller) revealHooks._unregister(controller, b);
|
|
9650
9775
|
});
|
|
9651
9776
|
// The `on` dependencies live OUTSIDE the boundary, as the condition of a
|
|
9652
9777
|
// `<Show>` wrapping it would: created before the owner's context names it.
|
|
@@ -9685,9 +9810,16 @@ function createBoundary(type, fn, show, onFn) {
|
|
|
9685
9810
|
b._tree = tree;
|
|
9686
9811
|
// A slot of the reveal order in its context (reveal.ts): gated until the
|
|
9687
9812
|
// controller releases it — before the output's first pass.
|
|
9688
|
-
if (controller) revealHooks._register(controller, b);
|
|
9813
|
+
if (revealHooks && controller) revealHooks._register(controller, b);
|
|
9689
9814
|
const output = computed(
|
|
9690
9815
|
() => {
|
|
9816
|
+
// Structure, not a derivation of its content (CONFIG_FRAME, #4283): it
|
|
9817
|
+
// reads a hold it is not part of as the screen, as the render effect
|
|
9818
|
+
// flattening the same children without a boundary would. Not while a
|
|
9819
|
+
// re-arm's swap is the change's work (`arm`), until that swap commits
|
|
9820
|
+
// (D-13, #3540).
|
|
9821
|
+
const self = getOwner();
|
|
9822
|
+
if (!b._armed && !(self._config & CONFIG_HELD)) self._config |= CONFIG_FRAME;
|
|
9691
9823
|
// Reveal order (reveal.ts): a gated slot shows its fallback — or, in a
|
|
9692
9824
|
// collapsed tail, nothing — whatever its content's state; the
|
|
9693
9825
|
// controller is told the pass ran (its readiness may have changed) and
|
|
@@ -9698,8 +9830,8 @@ function createBoundary(type, fn, show, onFn) {
|
|
|
9698
9830
|
// It may release this very slot (the frontier whose content just
|
|
9699
9831
|
// settled): the pass goes on to show it — the redraw it asks for is
|
|
9700
9832
|
// refused mid-pass and not needed.
|
|
9701
|
-
link(tree,
|
|
9702
|
-
if (b._reveal !== null) revealHooks._changed(b._reveal);
|
|
9833
|
+
link(tree, self);
|
|
9834
|
+
if (revealHooks && b._reveal !== null) revealHooks._changed(b._reveal);
|
|
9703
9835
|
if (b._gated) {
|
|
9704
9836
|
if (b._collapsed) {
|
|
9705
9837
|
b._fallback = true;
|
|
@@ -9717,7 +9849,7 @@ function createBoundary(type, fn, show, onFn) {
|
|
|
9717
9849
|
// once clean.
|
|
9718
9850
|
const status = tree._statusFlags & (STATUS_PENDING | STATUS_ERROR);
|
|
9719
9851
|
if (status !== 0) {
|
|
9720
|
-
link(tree,
|
|
9852
|
+
link(tree, self);
|
|
9721
9853
|
if (status & type) {
|
|
9722
9854
|
if (isCollecting(b)) {
|
|
9723
9855
|
caught(b, tree, undefined);
|
|
@@ -9743,7 +9875,6 @@ function createBoundary(type, fn, show, onFn) {
|
|
|
9743
9875
|
// enters: the outside sees its committed value until the landing,
|
|
9744
9876
|
// which reveals the content — a fallback staged earlier is replaced
|
|
9745
9877
|
// ahead of the commit and never shown.
|
|
9746
|
-
const self = getOwner();
|
|
9747
9878
|
if (
|
|
9748
9879
|
b._readers.size !== 0 &&
|
|
9749
9880
|
self._statusFlags & STATUS_UNINITIALIZED &&
|
|
@@ -9784,19 +9915,27 @@ function createBoundary(type, fn, show, onFn) {
|
|
|
9784
9915
|
// landing when the frame parks (the run is held with it, as the old
|
|
9785
9916
|
// children of a held pass are) — not now: a held swap keeps the
|
|
9786
9917
|
// fallback on screen, live, until it commits. A pass back to the
|
|
9787
|
-
// fallback before then finds it still built and keeps it.
|
|
9918
|
+
// fallback before then finds it still built and keeps it. A fallback
|
|
9919
|
+
// the screen does not show (a swap staged with a held frame, replaced
|
|
9920
|
+
// before it commits) dies now: what it reads holds nothing (S-22 row
|
|
9921
|
+
// 3′, #4268).
|
|
9788
9922
|
const fb = b._fb;
|
|
9923
|
+
const drop = () => {
|
|
9924
|
+
if (!b._fallback && b._fb === fb) {
|
|
9925
|
+
// A fallback that threw (a rethrow the boundary does not
|
|
9926
|
+
// handle) is what an enclosing boundary waits on: it died, and
|
|
9927
|
+
// the seam of another round drops it there (#4270).
|
|
9928
|
+
if (fb._statusFlags & STATUS_ERROR) schedule();
|
|
9929
|
+
dispose(fb);
|
|
9930
|
+
b._fb = null;
|
|
9931
|
+
}
|
|
9932
|
+
};
|
|
9789
9933
|
if (fb !== null)
|
|
9790
|
-
globalQueue.enqueue(EFFECT_RENDER,
|
|
9791
|
-
if (!b._fallback && b._fb === fb) {
|
|
9792
|
-
dispose(fb);
|
|
9793
|
-
b._fb = null;
|
|
9794
|
-
}
|
|
9795
|
-
});
|
|
9934
|
+
b._output._value !== fb._value ? drop() : globalQueue.enqueue(EFFECT_RENDER, drop);
|
|
9796
9935
|
release(b);
|
|
9797
9936
|
// Shown: the slot leaves its reveal order (a later re-arm gates nobody
|
|
9798
9937
|
// else; the frontier moves on).
|
|
9799
|
-
if (b._reveal !== null) {
|
|
9938
|
+
if (revealHooks && b._reveal !== null) {
|
|
9800
9939
|
const controller = b._reveal;
|
|
9801
9940
|
b._reveal = null;
|
|
9802
9941
|
revealHooks._changed(controller);
|
|
@@ -9809,6 +9948,8 @@ function createBoundary(type, fn, show, onFn) {
|
|
|
9809
9948
|
{ name: "value", _noSnapshot: true }
|
|
9810
9949
|
);
|
|
9811
9950
|
output._config |= CONFIG_REDERIVE;
|
|
9951
|
+
// The tree is structure too (the output's pass marks the output).
|
|
9952
|
+
tree._config |= CONFIG_FRAME;
|
|
9812
9953
|
b._output = output;
|
|
9813
9954
|
return accessor(output);
|
|
9814
9955
|
}
|
|
@@ -10177,6 +10318,7 @@ export {
|
|
|
10177
10318
|
TimeoutError,
|
|
10178
10319
|
action,
|
|
10179
10320
|
affects,
|
|
10321
|
+
clock,
|
|
10180
10322
|
configureClientErrors,
|
|
10181
10323
|
createContext,
|
|
10182
10324
|
createDeferred,
|
|
@@ -10218,6 +10360,7 @@ export {
|
|
|
10218
10360
|
omit,
|
|
10219
10361
|
omitView,
|
|
10220
10362
|
onCleanup,
|
|
10363
|
+
onFlush,
|
|
10221
10364
|
onSettled,
|
|
10222
10365
|
reconcile,
|
|
10223
10366
|
refresh,
|