@solidjs/signals 2.0.0-rc.1 → 2.0.0-rc.10
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 +7138 -0
- package/dist/dev.attribution.js +3307 -0
- package/dist/dev.js +5691 -4491
- package/dist/observe/affects.js +129 -0
- package/dist/observe/attribution.js +7 -0
- package/dist/observe/boundaries.js +793 -0
- package/dist/observe/core/action.js +177 -0
- package/dist/observe/core/async.js +849 -0
- package/dist/observe/core/attribution-costs.js +66 -0
- package/dist/observe/core/attribution-feedback.js +280 -0
- package/dist/observe/core/attribution-hooks.js +83 -0
- package/dist/observe/core/attribution-queries.js +43 -0
- package/dist/observe/core/attribution.js +2904 -0
- package/dist/observe/core/constants.js +283 -0
- package/dist/{types-cjs/core/context.d.cts → observe/core/context.js} +37 -12
- package/dist/observe/core/core.js +1999 -0
- package/dist/observe/core/dev.js +343 -0
- package/dist/observe/core/effect.js +200 -0
- package/dist/observe/core/error-hooks.js +71 -0
- package/dist/observe/core/error.js +80 -0
- package/dist/observe/core/external.js +98 -0
- package/dist/observe/core/graph.js +155 -0
- package/dist/observe/core/heap.js +147 -0
- package/dist/observe/core/invariants.js +45 -0
- package/dist/observe/core/lanes.js +205 -0
- package/dist/observe/core/optimistic.js +627 -0
- package/dist/observe/core/owner.js +353 -0
- package/dist/observe/core/scheduler.js +1547 -0
- package/dist/observe/core/verdict.js +674 -0
- package/dist/observe/index.js +59 -0
- package/dist/observe/map.js +484 -0
- package/dist/observe/signals.js +731 -0
- package/dist/observe/store/index.js +44 -0
- package/dist/observe/store/next/optimistic.js +717 -0
- package/dist/observe/store/next/projection.js +266 -0
- package/dist/observe/store/next/reconcile.js +375 -0
- package/dist/observe/store/next/store.js +2480 -0
- package/dist/observe/store/next/target.js +51 -0
- package/dist/observe/store/store.js +331 -0
- package/dist/observe/store/storePath.js +103 -0
- package/dist/observe/store/utils.js +1070 -0
- package/dist/prod/affects.js +10 -9
- package/dist/prod/attribution.js +45 -0
- package/dist/prod/boundaries.js +388 -178
- package/dist/prod/core/action.js +65 -37
- package/dist/prod/core/async.js +378 -163
- package/dist/prod/core/attribution-hooks.js +3 -0
- package/dist/prod/core/constants.js +186 -1
- package/dist/prod/core/context.js +10 -16
- package/dist/prod/core/core.js +1546 -416
- package/dist/prod/core/dev.js +18 -1
- package/dist/prod/core/effect.js +119 -79
- package/dist/prod/core/error-hooks.js +71 -0
- package/dist/prod/core/error.js +13 -1
- package/dist/prod/core/external.js +4 -4
- package/dist/prod/core/graph.js +105 -54
- package/dist/prod/core/heap.js +72 -65
- package/dist/prod/core/invariants.js +3 -2
- package/dist/prod/core/lanes.js +117 -52
- package/dist/prod/core/optimistic.js +458 -104
- package/dist/prod/core/owner.js +131 -84
- package/dist/prod/core/scheduler.js +998 -241
- package/dist/prod/core/verdict.js +417 -112
- package/dist/prod/index.js +20 -8
- package/dist/prod/map.js +312 -151
- package/dist/prod/signals.js +363 -32
- package/dist/prod/store/index.js +2 -0
- package/dist/prod/store/next/optimistic.js +530 -197
- package/dist/prod/store/next/projection.js +142 -57
- package/dist/prod/store/next/reconcile.js +149 -103
- package/dist/prod/store/next/store.js +1470 -346
- package/dist/prod/store/next/target.js +40 -9
- package/dist/prod/store/store.js +23 -19
- package/dist/prod/store/utils.js +997 -130
- package/dist/types/attribution.d.ts +19 -0
- package/dist/types/attribution.prod.d.ts +22 -0
- package/dist/types/boundaries.d.ts +78 -5
- package/dist/types/core/action.d.ts +12 -5
- package/dist/types/core/async.d.ts +3 -1
- package/dist/types/core/attribution-costs.d.ts +35 -0
- package/dist/types/core/attribution-feedback.d.ts +133 -0
- package/dist/types/core/attribution-hooks.d.ts +304 -0
- package/dist/types/core/attribution-queries.d.ts +24 -0
- package/dist/types/core/attribution.d.ts +892 -0
- package/dist/types/core/constants.d.ts +179 -0
- package/dist/types/core/core.d.ts +299 -25
- package/dist/types/core/dev.d.ts +421 -8
- package/dist/types/core/effect.d.ts +8 -1
- package/dist/types/core/error-hooks.d.ts +71 -0
- package/dist/types/core/error.d.ts +9 -0
- package/dist/types/core/graph.d.ts +23 -0
- package/dist/types/core/heap.d.ts +5 -3
- package/dist/types/core/index.d.ts +6 -3
- package/dist/types/core/invariants.d.ts +5 -1
- package/dist/types/core/lanes.d.ts +51 -19
- package/dist/types/core/owner.d.ts +15 -3
- package/dist/types/core/scheduler.d.ts +248 -1
- package/dist/types/core/types.d.ts +124 -41
- package/dist/types/index.d.ts +18 -5
- package/dist/types/map.d.ts +2 -0
- package/dist/types/signals.d.ts +145 -13
- package/dist/types/store/index.d.ts +7 -6
- package/dist/types/store/next/optimistic.d.ts +18 -13
- package/dist/types/store/next/projection.d.ts +5 -2
- package/dist/types/store/next/reconcile.d.ts +7 -0
- package/dist/types/store/next/store.d.ts +83 -11
- package/dist/types/store/next/target.d.ts +108 -11
- package/dist/types/store/store.d.ts +20 -11
- package/dist/types/store/utils.d.ts +188 -0
- package/package.json +31 -26
- package/dist/node.cjs +0 -8137
- package/dist/types/store/optimistic.d.ts +0 -45
- package/dist/types/store/projection.d.ts +0 -70
- package/dist/types/store/reconcile.d.ts +0 -46
- package/dist/types-cjs/affects.d.cts +0 -47
- package/dist/types-cjs/boundaries.d.cts +0 -175
- package/dist/types-cjs/core/action.d.cts +0 -64
- package/dist/types-cjs/core/async.d.cts +0 -21
- package/dist/types-cjs/core/constants.d.cts +0 -71
- package/dist/types-cjs/core/core.d.cts +0 -156
- package/dist/types-cjs/core/dev.d.cts +0 -64
- package/dist/types-cjs/core/effect.d.cts +0 -30
- package/dist/types-cjs/core/error.d.cts +0 -47
- package/dist/types-cjs/core/external.d.cts +0 -15
- package/dist/types-cjs/core/graph.d.cts +0 -5
- package/dist/types-cjs/core/heap.d.cts +0 -22
- package/dist/types-cjs/core/index.d.cts +0 -13
- package/dist/types-cjs/core/invariants.d.cts +0 -59
- package/dist/types-cjs/core/lanes.d.cts +0 -56
- package/dist/types-cjs/core/optimistic.d.cts +0 -6
- package/dist/types-cjs/core/owner.d.cts +0 -124
- package/dist/types-cjs/core/scheduler.d.cts +0 -172
- package/dist/types-cjs/core/types.d.cts +0 -148
- package/dist/types-cjs/core/verdict.d.cts +0 -2
- package/dist/types-cjs/index.d.cts +0 -10
- package/dist/types-cjs/map.d.cts +0 -69
- package/dist/types-cjs/package.json +0 -3
- package/dist/types-cjs/signals.d.cts +0 -624
- package/dist/types-cjs/store/index.d.cts +0 -19
- package/dist/types-cjs/store/next/optimistic.d.cts +0 -20
- package/dist/types-cjs/store/next/projection.d.cts +0 -24
- package/dist/types-cjs/store/next/reconcile.d.cts +0 -3
- package/dist/types-cjs/store/next/store.d.cts +0 -71
- package/dist/types-cjs/store/next/target.d.cts +0 -99
- package/dist/types-cjs/store/optimistic.d.cts +0 -45
- package/dist/types-cjs/store/projection.d.cts +0 -70
- package/dist/types-cjs/store/reconcile.d.cts +0 -46
- package/dist/types-cjs/store/store.d.cts +0 -138
- package/dist/types-cjs/store/storePath.d.cts +0 -58
- package/dist/types-cjs/store/utils.d.cts +0 -74
package/dist/prod/boundaries.js
CHANGED
|
@@ -1,72 +1,153 @@
|
|
|
1
|
-
import { runWithOwner, signal,
|
|
1
|
+
import { runWithOwner, signal, spectate, computed, read, untrack, setSignal, notifyOnLane, recompute, currentOptimisticLane, ext } from "./core/core.js";
|
|
2
2
|
|
|
3
3
|
import { NotReadyError, unwrapStatusError } from "./core/error.js";
|
|
4
4
|
|
|
5
5
|
import { createOwner, cleanup } from "./core/owner.js";
|
|
6
6
|
|
|
7
|
-
import { Queue,
|
|
7
|
+
import { Queue, transitions, reporterBlocksSource, wakeParked, schedule, queueRearm, haltReactivity } from "./core/scheduler.js";
|
|
8
8
|
|
|
9
9
|
import { getContext, setContext, createContext } from "./core/context.js";
|
|
10
10
|
|
|
11
|
-
import { STATUS_PENDING, STATUS_ERROR, REACTIVE_DISPOSED, CONFIG_AUTO_DISPOSE } from "./core/constants.js";
|
|
11
|
+
import { STATUS_PENDING, STATUS_ERROR, REACTIVE_DISPOSED, REACTIVE_ZOMBIE, STATUS_UNINITIALIZED, NOT_PENDING, CONFIG_AUTO_DISPOSE } from "./core/constants.js";
|
|
12
12
|
|
|
13
13
|
import "./core/invariants.js";
|
|
14
14
|
|
|
15
|
+
import { enqueueSub } from "./core/heap.js";
|
|
16
|
+
|
|
15
17
|
import "./core/verdict.js";
|
|
16
18
|
|
|
17
19
|
import "./core/effect.js";
|
|
18
20
|
|
|
21
|
+
import { reportClientError } from "./core/error-hooks.js";
|
|
22
|
+
|
|
19
23
|
import { accessor } from "./signals.js";
|
|
20
24
|
|
|
21
25
|
function boundaryComputed(e, t) {
|
|
22
26
|
const r = computed(e, {
|
|
23
27
|
lazy: true
|
|
24
28
|
});
|
|
25
|
-
r.
|
|
29
|
+
ext(r).S = (e, t) => {
|
|
26
30
|
// Use passed values if provided, otherwise read from node
|
|
27
|
-
const n = e !== undefined ? e : r.
|
|
28
|
-
const
|
|
31
|
+
const n = e !== undefined ? e : r.h;
|
|
32
|
+
const i = t !== undefined ? t : r.o?._;
|
|
29
33
|
// Notify both status dimensions like a render effect does; the queue chain
|
|
30
34
|
// consumes this boundary's own type and forwards the remainder upward until
|
|
31
35
|
// a boundary that handles it is found.
|
|
32
|
-
r.
|
|
33
|
-
const
|
|
36
|
+
r.h &= ~r.R;
|
|
37
|
+
const s = r.T.notify(r, STATUS_PENDING | STATUS_ERROR, n, i);
|
|
34
38
|
// The queue is the only propagation channel: a foreign status must not stay
|
|
35
39
|
// reader-visible on the tree, or reads re-throw it across the boundary and
|
|
36
40
|
// link unrelated ambient contexts (the #2809 nested-boundary loop). Deps are
|
|
37
41
|
// untouched, so the tree still recomputes when the foreign source settles.
|
|
38
42
|
const o = n & ~r.R & (STATUS_PENDING | STATUS_ERROR);
|
|
39
43
|
if (o) {
|
|
40
|
-
r.
|
|
41
|
-
if (r._ ===
|
|
44
|
+
r.h &= ~o;
|
|
45
|
+
if (r.o?._ === i && !(r.h & (STATUS_PENDING | STATUS_ERROR))) if (r.o !== null) r.o._ = undefined;
|
|
42
46
|
}
|
|
43
47
|
// An ERROR the chain could not deliver to any boundary is uncaught. The
|
|
44
48
|
// scrub above already removed it from reader-visible state, so without
|
|
45
49
|
// escalation here it would vanish entirely (#2884) — halt-and-throw,
|
|
46
50
|
// exactly like an unhandled effect error.
|
|
47
|
-
if (!
|
|
48
|
-
haltReactivity(unwrapStatusError(
|
|
49
|
-
throw
|
|
51
|
+
if (!s && n & STATUS_ERROR) {
|
|
52
|
+
haltReactivity(unwrapStatusError(i));
|
|
53
|
+
throw i;
|
|
50
54
|
}
|
|
51
55
|
};
|
|
52
56
|
r.R = t;
|
|
53
|
-
r.
|
|
57
|
+
r.C &= ~CONFIG_AUTO_DISPOSE;
|
|
54
58
|
recompute(r, true);
|
|
55
59
|
return r;
|
|
56
60
|
}
|
|
57
61
|
|
|
62
|
+
/**
|
|
63
|
+
* A boundary's `on` dependencies (#3540): `onFn` runs tracked, as a
|
|
64
|
+
* computation whose value is discarded — what it READS is the point. Every
|
|
65
|
+
* run after the first is a notification (a source it read was written, went
|
|
66
|
+
* pending, or landed; an optimistic write notifies like any other) and
|
|
67
|
+
* queues the boundary for re-arming once this pass's heap has run
|
|
68
|
+
* (scheduler.ts `pendingRearms`: the re-arm needs what the notifying write
|
|
69
|
+
* put in flight, which this pass — at the height of its reads — runs ahead
|
|
70
|
+
* of). The value is never compared: a thunk that returns a fresh object per
|
|
71
|
+
* run but reads nothing reactive never re-arms, and one that returns the
|
|
72
|
+
* same constant re-arms whenever a read source changes. A zero-argument
|
|
73
|
+
* function is an accessor, tracked like any other.
|
|
74
|
+
*
|
|
75
|
+
* The pass's posture is the notification's. A plain pass derives from the
|
|
76
|
+
* frame the write belongs to, and the re-arm follows that frame. A pass
|
|
77
|
+
* under a lane read display-ahead state — `latest()` (its shadow is an
|
|
78
|
+
* optimistic computed), an optimistic write — and the re-arm shows the
|
|
79
|
+
* fallback through that lane (`_rearmLane`): now, beside whatever frame a
|
|
80
|
+
* transaction still holds.
|
|
81
|
+
*
|
|
82
|
+
* Created under `owner` while the owner's queue is still the parent's, so
|
|
83
|
+
* the node belongs to the parent boundary, not to this one — as the
|
|
84
|
+
* condition of a `<Show>` wrapping the boundary would. Two status rules set
|
|
85
|
+
* it apart from a plain memo:
|
|
86
|
+
* - Pending is not the parent's: a source of `on` that is not ready is a
|
|
87
|
+
* notification for this boundary (it re-arms: the fallback shows here, not
|
|
88
|
+
* in an outer boundary). Propagation marks the node without a pass, so the
|
|
89
|
+
* channel scrubs the mark and re-derives it; the pass reads the source
|
|
90
|
+
* (linking to its landing) and catches. The node never registers as a
|
|
91
|
+
* reporter: `on` reading a pending source holds no frame.
|
|
92
|
+
* - An error IS the parent's, as a wrapping `<Show>` condition's would be:
|
|
93
|
+
* forwarded up the queue chain like a render effect's; uncaught, it halts
|
|
94
|
+
* (#2884).
|
|
95
|
+
*/ function onNode(e, t, r) {
|
|
96
|
+
let n = false;
|
|
97
|
+
const i = runWithOwner(e, () => computed(() => {
|
|
98
|
+
try {
|
|
99
|
+
r();
|
|
100
|
+
} catch (e) {
|
|
101
|
+
if (!(e instanceof NotReadyError)) throw e;
|
|
102
|
+
}
|
|
103
|
+
if (n) {
|
|
104
|
+
if (currentOptimisticLane !== null) t.O = currentOptimisticLane;
|
|
105
|
+
queueRearm(t);
|
|
106
|
+
} else n = true;
|
|
107
|
+
}, {
|
|
108
|
+
lazy: true
|
|
109
|
+
}));
|
|
110
|
+
ext(i).S = (e, t) => {
|
|
111
|
+
const r = e !== undefined ? e : i.h;
|
|
112
|
+
if (r & STATUS_PENDING) {
|
|
113
|
+
i.h &= ~STATUS_PENDING;
|
|
114
|
+
if (i.o?._ instanceof NotReadyError) i.o._ = undefined;
|
|
115
|
+
enqueueSub(i);
|
|
116
|
+
schedule();
|
|
117
|
+
}
|
|
118
|
+
if (r & STATUS_ERROR) {
|
|
119
|
+
const e = t !== undefined ? t : i.o?._;
|
|
120
|
+
i.h &= ~STATUS_ERROR;
|
|
121
|
+
if (i.o?._ === e && i.o !== null) i.o._ = undefined;
|
|
122
|
+
if (!i.T.notify(i, STATUS_ERROR, r, e)) {
|
|
123
|
+
haltReactivity(unwrapStatusError(e));
|
|
124
|
+
throw e;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
i.C &= ~CONFIG_AUTO_DISPOSE;
|
|
129
|
+
recompute(i, true);
|
|
130
|
+
return i;
|
|
131
|
+
}
|
|
132
|
+
|
|
58
133
|
function createBoundChildren(e, t, r, n) {
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
cleanup(() =>
|
|
62
|
-
|
|
63
|
-
|
|
134
|
+
const i = e.T;
|
|
135
|
+
i.addChild(e.T = r);
|
|
136
|
+
cleanup(() => i.removeChild(e.T));
|
|
137
|
+
// Named for the observe tier's owner paths: user content under a boundary
|
|
138
|
+
// is owned by `children`, and the boundary's own two nodes read as
|
|
139
|
+
// structure rather than as anonymous `computed`s between `<Loading>` and
|
|
140
|
+
// the content (`<App> › <Loading> › children › <Feed>`).
|
|
141
|
+
return runWithOwner(e, () => {
|
|
142
|
+
// The call, not the argument, is gated: `computed(fn, void 0)` would keep
|
|
143
|
+
// a trailing argument in the prod artifact.
|
|
144
|
+
const e = false ? computed(t, {
|
|
145
|
+
name: "children"
|
|
146
|
+
}) : computed(t);
|
|
64
147
|
return boundaryComputed(() => flatten(read(e)), n);
|
|
65
148
|
});
|
|
66
149
|
}
|
|
67
150
|
|
|
68
|
-
const ON_INIT = Symbol();
|
|
69
|
-
|
|
70
151
|
const RevealControllerContext = /* @__PURE__ */ createContext(null);
|
|
71
152
|
|
|
72
153
|
let _revealUsed = false;
|
|
@@ -80,53 +161,53 @@ function isRevealController(e) {
|
|
|
80
161
|
}
|
|
81
162
|
|
|
82
163
|
function isSlotReady(e) {
|
|
83
|
-
return isRevealController(e) ? e.
|
|
164
|
+
return isRevealController(e) ? e.I() : e.U.size === 0 && !e.v;
|
|
84
165
|
}
|
|
85
166
|
|
|
86
167
|
function isSlotMinimallyReady(e) {
|
|
87
|
-
return isRevealController(e) ? e.
|
|
168
|
+
return isRevealController(e) ? e.D() : isSlotReady(e);
|
|
88
169
|
}
|
|
89
170
|
|
|
90
171
|
function setSlotState(e, t, r, n) {
|
|
91
|
-
setSignal(e.
|
|
92
|
-
setSignal(e.
|
|
172
|
+
setSignal(e.P, r);
|
|
173
|
+
setSignal(e.L, n);
|
|
93
174
|
if (isRevealController(e)) {
|
|
94
|
-
if (!r && e.
|
|
95
|
-
return e.
|
|
175
|
+
if (!r && e.j === t) e.j = undefined;
|
|
176
|
+
return e.B(r, n);
|
|
96
177
|
}
|
|
97
|
-
if (!r && e.
|
|
178
|
+
if (!r && e.W === t && e.q) e.W = undefined;
|
|
98
179
|
}
|
|
99
180
|
|
|
100
181
|
class RevealController {
|
|
101
|
-
|
|
182
|
+
V;
|
|
102
183
|
F;
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
184
|
+
Z=[];
|
|
185
|
+
j;
|
|
186
|
+
P=signal(false, {
|
|
106
187
|
ownedWrite: true,
|
|
107
|
-
|
|
188
|
+
H: true
|
|
108
189
|
});
|
|
109
|
-
|
|
190
|
+
L=signal(false, {
|
|
110
191
|
ownedWrite: true,
|
|
111
|
-
|
|
192
|
+
H: true
|
|
112
193
|
});
|
|
113
|
-
H=true;
|
|
114
194
|
J=true;
|
|
115
|
-
K=
|
|
195
|
+
K=true;
|
|
196
|
+
X=false;
|
|
116
197
|
constructor(e, t) {
|
|
117
|
-
this.
|
|
198
|
+
this.V = e;
|
|
118
199
|
this.F = t;
|
|
119
200
|
}
|
|
120
|
-
|
|
121
|
-
for (let t = 0; t < this.
|
|
122
|
-
const r = this.
|
|
123
|
-
if ((isRevealController(r) ? r.
|
|
201
|
+
Y(e) {
|
|
202
|
+
for (let t = 0; t < this.Z.length; t++) {
|
|
203
|
+
const r = this.Z[t];
|
|
204
|
+
if ((isRevealController(r) ? r.j : r.W) !== this) continue;
|
|
124
205
|
if (e(r) === false) return false;
|
|
125
206
|
}
|
|
126
207
|
return true;
|
|
127
208
|
}
|
|
128
|
-
|
|
129
|
-
return this.
|
|
209
|
+
I() {
|
|
210
|
+
return this.Y(isSlotReady);
|
|
130
211
|
}
|
|
131
212
|
/**
|
|
132
213
|
* "Minimally ready" = this group has something visible to show under its own policy.
|
|
@@ -134,13 +215,13 @@ class RevealController {
|
|
|
134
215
|
* - `together`: every direct slot is minimally ready.
|
|
135
216
|
* - `sequential`: the first owned slot is minimally ready (frontier can advance).
|
|
136
217
|
* - `natural`: any owned slot is minimally ready.
|
|
137
|
-
*/
|
|
138
|
-
const e = untrack(this.
|
|
139
|
-
if (e === "together") return this.
|
|
218
|
+
*/ D() {
|
|
219
|
+
const e = untrack(this.V);
|
|
220
|
+
if (e === "together") return this.Y(isSlotMinimallyReady);
|
|
140
221
|
if (e === "natural") {
|
|
141
222
|
let e = false;
|
|
142
223
|
let t = false;
|
|
143
|
-
this.
|
|
224
|
+
this.Y(r => {
|
|
144
225
|
e = true;
|
|
145
226
|
if (isSlotMinimallyReady(r)) {
|
|
146
227
|
t = true;
|
|
@@ -151,45 +232,45 @@ class RevealController {
|
|
|
151
232
|
}
|
|
152
233
|
// sequential: only the first owned slot matters.
|
|
153
234
|
let t = true;
|
|
154
|
-
this.
|
|
235
|
+
this.Y(e => {
|
|
155
236
|
t = isSlotMinimallyReady(e);
|
|
156
237
|
return false;
|
|
157
238
|
});
|
|
158
239
|
return t;
|
|
159
240
|
}
|
|
160
|
-
|
|
161
|
-
if (this.
|
|
162
|
-
this.
|
|
163
|
-
const t = untrack(this.
|
|
164
|
-
setSignal(e.
|
|
165
|
-
untrack(() => this.
|
|
241
|
+
$(e) {
|
|
242
|
+
if (this.Z.includes(e)) return;
|
|
243
|
+
this.Z.push(e);
|
|
244
|
+
const t = untrack(this.V);
|
|
245
|
+
setSignal(e.P, true), setSignal(e.L, t === "sequential" ? !!untrack(this.F) : false);
|
|
246
|
+
untrack(() => this.B());
|
|
166
247
|
}
|
|
167
|
-
|
|
168
|
-
const t = this.
|
|
169
|
-
if (t >= 0) this.
|
|
170
|
-
untrack(() => this.
|
|
248
|
+
ee(e) {
|
|
249
|
+
const t = this.Z.indexOf(e);
|
|
250
|
+
if (t >= 0) this.Z.splice(t, 1);
|
|
251
|
+
untrack(() => this.B());
|
|
171
252
|
}
|
|
172
|
-
|
|
173
|
-
if (this.
|
|
174
|
-
this.
|
|
175
|
-
const r = this.
|
|
176
|
-
const n = this.
|
|
253
|
+
B(e, t) {
|
|
254
|
+
if (this.X) return;
|
|
255
|
+
this.X = true;
|
|
256
|
+
const r = this.J;
|
|
257
|
+
const n = this.K;
|
|
177
258
|
try {
|
|
178
|
-
const r = e ?? read(this.
|
|
259
|
+
const r = e ?? read(this.P), n = untrack(this.V), i = n === "sequential" && !!untrack(this.F), s = t ?? i;
|
|
179
260
|
if (r) {
|
|
180
261
|
// Held by an outer group. Propagate the hold (and whatever collapsed policy
|
|
181
262
|
// the outer asked for) down the whole subtree. Inner order is ignored while
|
|
182
263
|
// held; it resumes once the outer releases us.
|
|
183
|
-
this.
|
|
264
|
+
this.Y(e => setSlotState(e, this, true, s));
|
|
184
265
|
} else if (n === "natural") {
|
|
185
266
|
// Each child reveals based on its own readiness. A nested controller slot
|
|
186
267
|
// is released to run its own order locally — we bypass setSlotState for it
|
|
187
268
|
// so the parent backpointer survives for upward readiness notifications.
|
|
188
|
-
this.
|
|
269
|
+
this.Y(e => {
|
|
189
270
|
if (isRevealController(e)) {
|
|
190
|
-
setSignal(e.
|
|
191
|
-
setSignal(e.
|
|
192
|
-
e.
|
|
271
|
+
setSignal(e.L, false);
|
|
272
|
+
setSignal(e.P, false);
|
|
273
|
+
e.B(false, false);
|
|
193
274
|
} else {
|
|
194
275
|
setSlotState(e, this, !isSlotReady(e), false);
|
|
195
276
|
}
|
|
@@ -200,12 +281,12 @@ class RevealController {
|
|
|
200
281
|
// sequential's first slot being ready is minimally ready; natural having any
|
|
201
282
|
// ready child is minimally ready. This lets `together` guarantee a single
|
|
202
283
|
// cohesive reveal without waiting for every grandchild.
|
|
203
|
-
const e = this.
|
|
204
|
-
this.
|
|
284
|
+
const e = this.Y(isSlotMinimallyReady);
|
|
285
|
+
this.Y(t => setSlotState(t, this, !e, false));
|
|
205
286
|
} else {
|
|
206
287
|
let e = false;
|
|
207
|
-
this.
|
|
208
|
-
if (e) return setSlotState(t, this, true,
|
|
288
|
+
this.Y(t => {
|
|
289
|
+
if (e) return setSlotState(t, this, true, i);
|
|
209
290
|
if (isSlotReady(t)) return setSlotState(t, this, false, false);
|
|
210
291
|
e = true;
|
|
211
292
|
// Frontier slot. For a leaf, holding `_disabled=true` is what keeps its
|
|
@@ -215,65 +296,121 @@ class RevealController {
|
|
|
215
296
|
// advancing past this slot, and we bypass setSlotState so the parent
|
|
216
297
|
// backpointer survives for upward readiness notifications.
|
|
217
298
|
if (isRevealController(t)) {
|
|
218
|
-
setSignal(t.
|
|
219
|
-
setSignal(t.
|
|
220
|
-
t.
|
|
299
|
+
setSignal(t.L, false);
|
|
300
|
+
setSignal(t.P, false);
|
|
301
|
+
t.B(false, false);
|
|
221
302
|
} else {
|
|
222
303
|
setSlotState(t, this, true, false);
|
|
223
304
|
}
|
|
224
305
|
});
|
|
225
306
|
}
|
|
226
307
|
} finally {
|
|
227
|
-
this.
|
|
228
|
-
this.
|
|
229
|
-
this.
|
|
308
|
+
this.J = this.I();
|
|
309
|
+
this.K = this.D();
|
|
310
|
+
this.X = false;
|
|
230
311
|
}
|
|
231
|
-
if (this.
|
|
312
|
+
if (this.j && (r !== this.J || n !== this.K)) this.j.B();
|
|
232
313
|
}
|
|
233
314
|
}
|
|
234
315
|
|
|
235
316
|
class CollectionQueue extends Queue {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
317
|
+
te;
|
|
318
|
+
U=new Set;
|
|
319
|
+
re;
|
|
320
|
+
/** The output pass — fallback or content (createCollectionBoundary). */
|
|
321
|
+
ne;
|
|
322
|
+
v=true;
|
|
323
|
+
P=signal(false, {
|
|
241
324
|
ownedWrite: true,
|
|
242
|
-
|
|
325
|
+
H: true
|
|
243
326
|
});
|
|
244
327
|
_;
|
|
245
|
-
|
|
328
|
+
L=signal(false, {
|
|
246
329
|
ownedWrite: true,
|
|
247
|
-
|
|
330
|
+
H: true
|
|
248
331
|
});
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
332
|
+
W;
|
|
333
|
+
q=false;
|
|
334
|
+
/** The boundary's owner — where a `caught` report locates itself, set before the children are built (a creation-time throw arrives before `_tree`). */
|
|
335
|
+
ie;
|
|
336
|
+
/** The lane the `on` pass that queued this re-arm ran under (onNode), if
|
|
337
|
+
* any: the fallback swap is display-ahead — shown through the lane. */
|
|
338
|
+
O=null;
|
|
253
339
|
constructor(e) {
|
|
254
340
|
super();
|
|
255
|
-
this
|
|
341
|
+
this.te = e;
|
|
256
342
|
}
|
|
257
343
|
run(e) {
|
|
258
|
-
if (!e || read(this.
|
|
344
|
+
if (!e || read(this.P) && (!_revealUsed || read(this.L))) return;
|
|
259
345
|
return super.run(e);
|
|
260
346
|
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
347
|
+
/** An `on` dependency notified (onNode → scheduler `pendingRearms`);
|
|
348
|
+
* drained after the heap, before the verdict, under the notifying write's
|
|
349
|
+
* transaction (#3540). A boundary showing content is fresh again: it
|
|
350
|
+
* releases its hold now and, if anything under it is still pending, swaps
|
|
351
|
+
* to its fallback. The swap is staged, so it lands with the write's frame
|
|
352
|
+
* — at once when nothing else holds it, with the rest of the new page
|
|
353
|
+
* when something outside the boundary does; if the pending lands first,
|
|
354
|
+
* `_checkSources` clears it and no fallback is shown. An `on` that read a
|
|
355
|
+
* lane (`latest()`, an optimistic write) asked for the change now:
|
|
356
|
+
* `_rearmLane` shows the swap through the lane, beside the held frame.
|
|
357
|
+
* Children stay alive behind the fallback. */ se() {
|
|
358
|
+
const e = this.O;
|
|
359
|
+
this.O = null;
|
|
360
|
+
if (this.re === undefined || this.re.oe & REACTIVE_DISPOSED) return;
|
|
361
|
+
if (!this.q) return;
|
|
362
|
+
// Readers forwarded while this boundary showed content are what it
|
|
363
|
+
// would wait on now. They never re-notify (status propagation dedupes on
|
|
364
|
+
// the reader's `_pendingSources`), so the re-arm collects it from their
|
|
365
|
+
// registrations — the one place a forwarded reader is recorded (INV-3)
|
|
366
|
+
// — or a sibling reader's flight that lands first reveals them stale
|
|
367
|
+
// (A33, #3459). Before the verdict, a registration may have stopped
|
|
368
|
+
// counting without being pruned yet (its flight landed this pass):
|
|
369
|
+
// `reporterBlocksSource` is the verdict's own test.
|
|
370
|
+
const t = new Set;
|
|
371
|
+
for (const e of transitions) for (const [r, n] of e.le) {
|
|
372
|
+
for (const e of n) if (this.ae(e) && reporterBlocksSource(e, r)) {
|
|
373
|
+
t.add(r);
|
|
374
|
+
e.o?.ue?.forEach(e => t.add(e));
|
|
275
375
|
}
|
|
276
376
|
}
|
|
377
|
+
if (!t.size) return;
|
|
378
|
+
this.q = false;
|
|
379
|
+
this.U = t;
|
|
380
|
+
this.v = true;
|
|
381
|
+
this.fe(e);
|
|
382
|
+
// Those readers are behind the fallback now: they stop blocking
|
|
383
|
+
// (`reporterBlocksSource`), and the transactions they were holding must
|
|
384
|
+
// be re-judged for it (A33, #3375) — the active one by the verdict that
|
|
385
|
+
// follows this drain, parked ones by the wake. A live action keeps its
|
|
386
|
+
// transaction parked regardless (transitionComplete): its batch commits
|
|
387
|
+
// when it settles, intact.
|
|
388
|
+
wakeParked();
|
|
389
|
+
}
|
|
390
|
+
/** Show the fallback: the swap the output pass selects on. Staged, it is
|
|
391
|
+
* the frame's and lands with its commit. Re-armed from a lane pass
|
|
392
|
+
* (`lane`), it is the current frame's — committed outright, as the lane's
|
|
393
|
+
* view already is on screen — and shown through the lane: the output pass
|
|
394
|
+
* publishes a derived override and its readers run from the lane's queue,
|
|
395
|
+
* at the park, ahead of the transaction (a lane pass reads staged plain
|
|
396
|
+
* writes committed, so a staged swap would be invisible to it). */ fe(e) {
|
|
397
|
+
if (e === null) setSignal(this.P, true); else {
|
|
398
|
+
this.P.ce = true;
|
|
399
|
+
notifyOnLane(this.P, e);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
/** Retry the collected failures of an error boundary: recompute each
|
|
403
|
+
* source that threw, so the boundary can recover. */ Se() {
|
|
404
|
+
for (const e of this.U) {
|
|
405
|
+
// Non-computed sources (patch-channel registrations under plain
|
|
406
|
+
// owners) are not recomputable — their reset is the record's next
|
|
407
|
+
// transition re-applying the patch (re-audit 2, P1-4).
|
|
408
|
+
if (e.he !== undefined) recompute(e);
|
|
409
|
+
}
|
|
410
|
+
schedule();
|
|
411
|
+
}
|
|
412
|
+
notify(e, t, r, n) {
|
|
413
|
+
if (!(t & this.te)) return super.notify(e, t, r, n);
|
|
277
414
|
// Routing is dimension-independent: each boundary consumes only its own
|
|
278
415
|
// status dimension from the mask (`type &= ~collectionType` below) and
|
|
279
416
|
// forwards the remainder up the queue chain. An error inside a `Loading`
|
|
@@ -284,93 +421,144 @@ class CollectionQueue extends Queue {
|
|
|
284
421
|
// dimension, while a status already caught by an inner boundary arrives with
|
|
285
422
|
// its dimension consumed from the mask and is correctly not re-routed
|
|
286
423
|
// (the Loading > Errored > content composition escape, #2856).
|
|
287
|
-
if (this
|
|
288
|
-
if (r & this
|
|
289
|
-
this.
|
|
290
|
-
const t = n?.source || e._?.source;
|
|
424
|
+
if (this.te & STATUS_PENDING && this.q) return super.notify(e, t, r, n);
|
|
425
|
+
if (r & this.te) {
|
|
426
|
+
this.v = true;
|
|
427
|
+
const t = n?.source || e.o?._?.source;
|
|
291
428
|
if (t) {
|
|
292
|
-
const
|
|
293
|
-
this.
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
429
|
+
const r = this.U.size === 0;
|
|
430
|
+
this.U.add(t);
|
|
431
|
+
// A collecting boundary waits on everything the effect is pending on,
|
|
432
|
+
// not only the source this notification carries. Status propagation
|
|
433
|
+
// dedupes on the effect's `_pendingSources`: a source it already
|
|
434
|
+
// carries (a flight that started before an `on` reset cleared the
|
|
435
|
+
// set) is never re-reported, and that source's later re-flight
|
|
436
|
+
// stays invisible — the boundary revealed when its one collected
|
|
437
|
+
// source settled while the effect was still pending (#3375).
|
|
438
|
+
if (this.te & STATUS_PENDING) e.o?.ue?.forEach(e => this.U.add(e));
|
|
439
|
+
if (r) {
|
|
440
|
+
setSignal(this.P, true);
|
|
441
|
+
}
|
|
442
|
+
if (this.te & STATUS_ERROR) {
|
|
443
|
+
const e = unwrapStatusError(t.o?._);
|
|
444
|
+
setSignal(this._, e);
|
|
445
|
+
// The client error hook: this boundary renders its fallback for
|
|
446
|
+
// it — the one road a rendered failure took that no global handler
|
|
447
|
+
// ever saw. `source` is the computation that threw (the status
|
|
448
|
+
// wrapper's, made at the first landing and kept downstream), so the
|
|
449
|
+
// hook hears where it broke as well as where it was met. Once per
|
|
450
|
+
// error object; a `reset()` re-collecting the same failure says
|
|
451
|
+
// nothing new.
|
|
452
|
+
reportClientError(e, this.ie, t);
|
|
297
453
|
}
|
|
298
454
|
}
|
|
299
455
|
}
|
|
300
|
-
t &= ~this
|
|
456
|
+
t &= ~this.te;
|
|
301
457
|
return t ? super.notify(e, t, r, n) : true;
|
|
302
458
|
}
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
if (e.se & REACTIVE_DISPOSED || !e.t && !(e.S & this.$) && !(this.$ & STATUS_ERROR && e.S & STATUS_PENDING)) this.v.delete(e);
|
|
459
|
+
/** Is `reporter` live and routed to this boundary — under it, with no
|
|
460
|
+
* collecting pending-type boundary in between (`reporterBlocksSource`'s test)? */ ae(e) {
|
|
461
|
+
if (e.oe & (REACTIVE_ZOMBIE | REACTIVE_DISPOSED)) return false;
|
|
462
|
+
for (let t = e.T; t; t = t._parent) {
|
|
463
|
+
if (t === this) return true;
|
|
464
|
+
if (t.te & STATUS_PENDING && !t.q) return false;
|
|
310
465
|
}
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
466
|
+
return false;
|
|
467
|
+
}
|
|
468
|
+
/** Has a collected source stopped counting for this boundary? A source
|
|
469
|
+
* with a live affects() mark holds display state for the mark's lifetime
|
|
470
|
+
* (the visual channel): the marked node carries no status of its own, so
|
|
471
|
+
* the count is the liveness test. The release sweep (finalizePureQueue
|
|
472
|
+
* after mark release) re-runs this check. A source born held under this
|
|
473
|
+
* boundary (recompute, #3540) carries no status either: it is collected
|
|
474
|
+
* while it has a staged value and no committed one, and released by the
|
|
475
|
+
* commit that initializes it. */ de(e) {
|
|
476
|
+
return !!(e.oe & REACTIVE_DISPOSED || !e.o?.t && !(e.h & this.te) && !(this.te & STATUS_ERROR && e.h & STATUS_PENDING) && !(this.te & STATUS_PENDING && e.h & STATUS_UNINITIALIZED && e._e !== NOT_PENDING));
|
|
477
|
+
}
|
|
478
|
+
/** The pre-verdict sweep (scheduler run(), #3540): a collecting boundary
|
|
479
|
+
* whose OUTPUT is pending — its fallback read something not ready — is
|
|
480
|
+
* judged here, under the transaction. That output is what an initialized
|
|
481
|
+
* parent holds the frame on, and it derives from `_disabled`, not the
|
|
482
|
+
* tree: the tree settling never re-runs it, only a sweep does, and the
|
|
483
|
+
* commit sweep runs after the verdict the output's own read keeps parking
|
|
484
|
+
* — the content waited for the fallback's flight. Judged ready here, the
|
|
485
|
+
* boundary stages `_disabled` false with the frame and the output re-runs
|
|
486
|
+
* in this heap: it reads the tree and drops the fallback's read (recompute
|
|
487
|
+
* settles a pass's outgoing pending sources), so the verdict sees the
|
|
488
|
+
* release. A boundary showing a ready fallback parks nothing and keeps the
|
|
489
|
+
* commit sweep's reveal. */ Re() {
|
|
490
|
+
if (this.q || !(this.ne.h & STATUS_PENDING)) return;
|
|
491
|
+
this.Ee();
|
|
492
|
+
}
|
|
493
|
+
Ee() {
|
|
494
|
+
for (const e of this.U) if (this.de(e)) this.U.delete(e);
|
|
495
|
+
if (!this.U.size) {
|
|
496
|
+
if (this.te & STATUS_PENDING && this.v && !this.q && this.re) {
|
|
497
|
+
this.v = !!(this.re.h & this.te);
|
|
314
498
|
} else {
|
|
315
|
-
this.
|
|
499
|
+
this.v = false;
|
|
316
500
|
}
|
|
317
|
-
if (!this.
|
|
318
|
-
setSignal(this.
|
|
319
|
-
if (this.te) {
|
|
320
|
-
try {
|
|
321
|
-
this.re = untrack(() => this.te());
|
|
322
|
-
} catch {
|
|
323
|
-
/* value not yet committed — _prevOn stays stale, next notify will reset */}
|
|
324
|
-
}
|
|
501
|
+
if (!this.v) {
|
|
502
|
+
setSignal(this.P, false);
|
|
325
503
|
}
|
|
326
504
|
}
|
|
327
|
-
if (_revealUsed) this.B
|
|
505
|
+
if (_revealUsed) this.W?.B();
|
|
328
506
|
}
|
|
329
507
|
}
|
|
330
508
|
|
|
331
509
|
function createCollectionBoundary(e, t, r, n) {
|
|
332
|
-
const
|
|
333
|
-
if (_revealUsed) setContext(RevealControllerContext, null,
|
|
334
|
-
const
|
|
335
|
-
|
|
510
|
+
const i = createOwner();
|
|
511
|
+
if (_revealUsed) setContext(RevealControllerContext, null, i);
|
|
512
|
+
const s = new CollectionQueue(e);
|
|
513
|
+
s.ie = i;
|
|
514
|
+
if (e === STATUS_ERROR) s._ = signal(undefined, {
|
|
336
515
|
ownedWrite: true,
|
|
337
|
-
|
|
516
|
+
H: true
|
|
338
517
|
});
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
//
|
|
342
|
-
|
|
518
|
+
// The `on` dependencies live OUTSIDE the boundary, as the condition of a
|
|
519
|
+
// `<Show>` wrapping it would: created before the owner's queue becomes
|
|
520
|
+
// this boundary's (onNode).
|
|
521
|
+
n && onNode(i, s, n);
|
|
522
|
+
const o = s.re = createBoundChildren(i, t, s, e);
|
|
523
|
+
// Prime source tracking so reveal registration sees pending sources. A
|
|
524
|
+
// bookkeeping read (`spectate`): the mounting pass derives nothing from
|
|
525
|
+
// the tree — it must not be linked to it, nor enter the transaction a
|
|
526
|
+
// tree born held (A29 under a boundary, #3540) was staged into.
|
|
527
|
+
spectate(() => {
|
|
343
528
|
let t = false;
|
|
344
529
|
try {
|
|
345
530
|
read(o);
|
|
346
531
|
} catch (e) {
|
|
347
532
|
if (e instanceof NotReadyError) t = true; else throw e;
|
|
348
533
|
}
|
|
349
|
-
|
|
534
|
+
s.v = t || !!(o.h & e) || o.o?._ instanceof NotReadyError;
|
|
350
535
|
});
|
|
351
536
|
const l = _revealUsed && e === STATUS_PENDING ? getContext(RevealControllerContext) : null;
|
|
352
537
|
if (l) {
|
|
353
|
-
|
|
354
|
-
l
|
|
355
|
-
cleanup(() => l.
|
|
538
|
+
s.W = l;
|
|
539
|
+
l.$(s);
|
|
540
|
+
cleanup(() => l.ee(s));
|
|
356
541
|
}
|
|
357
|
-
return accessor(computed(() => {
|
|
358
|
-
|
|
542
|
+
return accessor(s.ne = computed(() => {
|
|
543
|
+
// `_disabled` selects fallback or content: set by a collecting
|
|
544
|
+
// notification or a re-arm (`_rearm`), cleared by the sweep when the
|
|
545
|
+
// collected sources settle — each re-runs this pass.
|
|
546
|
+
if (!read(s.P)) {
|
|
359
547
|
const e = read(o);
|
|
360
|
-
if (!untrack(() => read(
|
|
548
|
+
if (!untrack(() => read(s.P))) return s.q = true, e;
|
|
361
549
|
}
|
|
362
550
|
// Collapsed reveal slots suppress their own output entirely; the
|
|
363
551
|
// renderer treats the hole as empty, so the cast never leaks to users
|
|
364
552
|
// outside a `createRevealOrder` scope.
|
|
365
|
-
if (_revealUsed && read(
|
|
366
|
-
return r(
|
|
553
|
+
if (_revealUsed && read(s.L)) return undefined;
|
|
554
|
+
return r(s);
|
|
367
555
|
},
|
|
368
556
|
// Boundary structure, not a user source: its value is fallback-or-content and
|
|
369
557
|
// legitimately swaps mid-hydration (reveal/resume), so it must never be frozen
|
|
370
558
|
// by snapshot capture. The tree no longer carries foreign status flags, so
|
|
371
559
|
// capture can't rely on PENDING to skip this node the way it used to.
|
|
372
560
|
{
|
|
373
|
-
|
|
561
|
+
H: true
|
|
374
562
|
}));
|
|
375
563
|
}
|
|
376
564
|
|
|
@@ -383,8 +571,27 @@ function createCollectionBoundary(e, t, r, n) {
|
|
|
383
571
|
*
|
|
384
572
|
* @param fn the tracked subtree
|
|
385
573
|
* @param fallback the fallback shown while async reads in `fn` are unresolved
|
|
386
|
-
* @param options `on` —
|
|
387
|
-
*
|
|
574
|
+
* @param options `on` — a dependency list: a tracked function whose reads
|
|
575
|
+
* re-arm the boundary. Its return value is irrelevant (never compared);
|
|
576
|
+
* what matters is what it reads. Without `on`, a boundary that has shown
|
|
577
|
+
* content keeps it through a refetch (the pending holds with the
|
|
578
|
+
* transaction). With `on`, a write to anything it reads makes the boundary
|
|
579
|
+
* fresh again: it stops waiting on its current content, and if something
|
|
580
|
+
* under it is pending it shows `fallback` until the new content is ready;
|
|
581
|
+
* if nothing is pending, the notification is a no-op. The fallback lands
|
|
582
|
+
* with the same frame as the change that caused it — now, when nothing
|
|
583
|
+
* else holds that frame; together with the rest of the new page during a
|
|
584
|
+
* held navigation, not before it. If the same data is also read outside
|
|
585
|
+
* the boundary, the frame waits on it and the fallback can never be seen
|
|
586
|
+
* (DEV warns `LOADING_ON_OUTSIDE_HOLD`); the fix is structural — move the
|
|
587
|
+
* outside read under the boundary so one hold owns the data. A frame held
|
|
588
|
+
* past the content's landing by something else (the write's action, other
|
|
589
|
+
* pending data) also shows no fallback; that is a race the fallback may
|
|
590
|
+
* lose, a legitimate outcome, and not reported. A display-ahead read in
|
|
591
|
+
* `on` (`latest()`) shows the fallback now, beside the held frame; that
|
|
592
|
+
* is a capability, not the recommended shape. Optimistic writes and a
|
|
593
|
+
* source going pending notify like any other. The children are not
|
|
594
|
+
* re-created — they stay alive behind the fallback.
|
|
388
595
|
*
|
|
389
596
|
* @example
|
|
390
597
|
* ```tsx
|
|
@@ -423,10 +630,7 @@ function createCollectionBoundary(e, t, r, n) {
|
|
|
423
630
|
* }
|
|
424
631
|
* ```
|
|
425
632
|
*/ function createErrorBoundary(e, t) {
|
|
426
|
-
return createCollectionBoundary(STATUS_ERROR, e, e => t(accessor(e._), () =>
|
|
427
|
-
for (const t of e.v) recompute(t);
|
|
428
|
-
schedule();
|
|
429
|
-
}));
|
|
633
|
+
return createCollectionBoundary(STATUS_ERROR, e, e => t(accessor(e._), () => e.Se()));
|
|
430
634
|
}
|
|
431
635
|
|
|
432
636
|
/**
|
|
@@ -473,20 +677,23 @@ function createCollectionBoundary(e, t, r, n) {
|
|
|
473
677
|
_revealUsed = true;
|
|
474
678
|
const r = createOwner();
|
|
475
679
|
const n = getContext(RevealControllerContext);
|
|
476
|
-
const
|
|
477
|
-
const o = new RevealController(
|
|
680
|
+
const i = t?.order || SEQUENTIAL_ACCESSOR, s = t?.collapsed || FALSE_ACCESSOR;
|
|
681
|
+
const o = new RevealController(i, s);
|
|
478
682
|
setContext(RevealControllerContext, o, r);
|
|
479
683
|
return runWithOwner(r, () => {
|
|
480
684
|
const t = e();
|
|
481
|
-
computed(() => {
|
|
482
|
-
s();
|
|
685
|
+
const r = computed(() => {
|
|
483
686
|
i();
|
|
484
|
-
|
|
687
|
+
s();
|
|
688
|
+
o.B();
|
|
485
689
|
});
|
|
690
|
+
// Post-construction rather than an options argument, so the prod call
|
|
691
|
+
// keeps its shape; the observe node literal already carries the slot.
|
|
692
|
+
if (false) ;
|
|
486
693
|
if (n) {
|
|
487
|
-
o.
|
|
488
|
-
n
|
|
489
|
-
cleanup(() => n.
|
|
694
|
+
o.j = n;
|
|
695
|
+
n.$(o);
|
|
696
|
+
cleanup(() => n.ee(o));
|
|
490
697
|
}
|
|
491
698
|
return t;
|
|
492
699
|
});
|
|
@@ -541,14 +748,14 @@ function createCollectionBoundary(e, t, r, n) {
|
|
|
541
748
|
|
|
542
749
|
function flattenArray(e, t = [], r) {
|
|
543
750
|
let n = null;
|
|
544
|
-
let
|
|
545
|
-
for (let
|
|
751
|
+
let i = false;
|
|
752
|
+
for (let s = 0; s < e.length; s++) {
|
|
546
753
|
try {
|
|
547
|
-
let n = e[
|
|
754
|
+
let n = e[s];
|
|
548
755
|
if (typeof n === "function" && !n.length) {
|
|
549
756
|
if (r?.doNotUnwrap) {
|
|
550
757
|
t.push(n);
|
|
551
|
-
|
|
758
|
+
i = true;
|
|
552
759
|
continue;
|
|
553
760
|
}
|
|
554
761
|
do {
|
|
@@ -556,7 +763,10 @@ function flattenArray(e, t = [], r) {
|
|
|
556
763
|
} while (typeof n === "function" && !n.length);
|
|
557
764
|
}
|
|
558
765
|
if (Array.isArray(n)) {
|
|
559
|
-
|
|
766
|
+
// OR, don't overwrite: an accessor already pushed under doNotUnwrap
|
|
767
|
+
// still needs the resolving wrapper even when a later sibling
|
|
768
|
+
// fragment contains no functions (#3133).
|
|
769
|
+
i = flattenArray(n, t, r) || i;
|
|
560
770
|
} else if (r?.skipNonRendered && (n == null || n === true || n === false || n === "")) {
|
|
561
771
|
// skip
|
|
562
772
|
} else t.push(n);
|
|
@@ -566,7 +776,7 @@ function flattenArray(e, t = [], r) {
|
|
|
566
776
|
}
|
|
567
777
|
}
|
|
568
778
|
if (n) throw n;
|
|
569
|
-
return
|
|
779
|
+
return i;
|
|
570
780
|
}
|
|
571
781
|
|
|
572
782
|
export { CollectionQueue, RevealController, createErrorBoundary, createLoadingBoundary, createRevealOrder, flatten };
|