@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
package/dist/prod/boundaries.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { STATUS_PENDING, STATUS_ERROR, CONFIG_REDERIVE, CONFIG_HELD, CONFIG_FRAME, STATUS_UNINITIALIZED, EFFECT_RENDER, CONFIG_VERDICT, REACTIVE_DISPOSED, REACTIVE_LANE_READ, CONFIG_OVERRIDE, EFFECT_USER, EFFECT_TRACKED, REACTIVE_ZOMBIE, CAUGHT_REARMED } from "./core/constants.js";
|
|
1
|
+
import { STATUS_PENDING, STATUS_ERROR, CONFIG_REDERIVE, CONFIG_HELD, CONFIG_FRAME, STATUS_UNINITIALIZED, EFFECT_RENDER, CONFIG_VERDICT, REACTIVE_DISPOSED, REACTIVE_LANE_READ, REACTIVE_PROBED, CONFIG_STAGED_ERROR, CONFIG_OVERRIDE, EFFECT_USER, EFFECT_TRACKED, REACTIVE_ZOMBIE, CAUGHT_REARMED } from "./core/constants.js";
|
|
2
2
|
|
|
3
3
|
import { signal, runWithOwner, computed, read, setSignal, recompute } from "./core/core.js";
|
|
4
4
|
|
|
5
|
+
import { reportDiagnostic, emitDiagnostic } from "./core/dev.js";
|
|
6
|
+
|
|
5
7
|
import { NotReadyError, unwrapStatusError } from "./core/error.js";
|
|
6
8
|
|
|
7
9
|
import { reportClientError } from "./core/error-hooks.js";
|
|
@@ -81,27 +83,37 @@ const boundaryOf = e => e.A[BOUNDARY];
|
|
|
81
83
|
/** Catches what reaches it: an error boundary always; a loading one until it
|
|
82
84
|
* has shown content, or while re-armed. */ const isCollecting = e => e.i === STATUS_ERROR || !e.D || e.h;
|
|
83
85
|
|
|
84
|
-
/** A reader `b` waits on: recorded for its `on`, and `b` visited at the seam. */ function record(e, r) {
|
|
85
|
-
e.F.
|
|
86
|
+
/** A reader `b` waits on: recorded for its `on`, and `b` visited at the seam. */ function record(e, n, r = n) {
|
|
87
|
+
e.F.set(n, r);
|
|
86
88
|
collecting.add(e);
|
|
87
89
|
}
|
|
88
90
|
|
|
89
91
|
/** The reader goes to the fallback: recorded, and the output re-derives
|
|
90
92
|
* (a no-op while the output's own pass is running — its post-check
|
|
91
|
-
* decides). */ function caught(e, r, n) {
|
|
93
|
+
* decides). */ function caught(e, n, r, o = n) {
|
|
92
94
|
if (e.i === STATUS_ERROR) {
|
|
93
95
|
// An error boundary waits on what THREW (`StatusError.source`), not on
|
|
94
|
-
// the reader that saw it
|
|
95
|
-
//
|
|
96
|
-
//
|
|
97
|
-
//
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
96
|
+
// the reader that saw it, while the error is settled only when its
|
|
97
|
+
// source is neither errored nor in flight and the reader is not pending
|
|
98
|
+
// on the answer that replaces it (`prune`) — or when the
|
|
99
|
+
// reader is disposed: a source no live reader holds holds nothing
|
|
100
|
+
// (#4373). A source that died (a memo its reader owned, kept past the
|
|
101
|
+
// pass that disposed it) settles nothing: the reader is waited on.
|
|
102
|
+
// `reset` re-runs the source.
|
|
103
|
+
r ??= n.T?.U;
|
|
104
|
+
o = r?.source ?? n;
|
|
105
|
+
if (o.R & REACTIVE_DISPOSED) o = n;
|
|
106
|
+
const t = unwrapStatusError(r);
|
|
107
|
+
setSignal(e.U, t);
|
|
108
|
+
reportClientError(t, e.H, o);
|
|
103
109
|
}
|
|
104
|
-
record(e,
|
|
110
|
+
record(e, n, o);
|
|
111
|
+
// A loading fallback behind an error fallback is hidden: the error stays
|
|
112
|
+
// the display until what the fallback waits on answers (D-39) — the
|
|
113
|
+
// error boundary waits on it too.
|
|
114
|
+
// (`_type`: STATUS_PENDING 1 < STATUS_ERROR 2 — an error boundary above a
|
|
115
|
+
// loading one.)
|
|
116
|
+
for (let r = e; r = r._parent; ) if (r.L && r.i > e.i) record(r, n);
|
|
105
117
|
if (e.h) flip(e);
|
|
106
118
|
// Already showing the fallback: one more reader to wait on changes
|
|
107
119
|
// nothing on screen. The fallback is instantiated once per show — a later
|
|
@@ -117,8 +129,8 @@ const boundaryOf = e => e.A[BOUNDARY];
|
|
|
117
129
|
* transaction with the arming frame's (#3540 `on: () => latest(dep)`). */ function flip(e) {
|
|
118
130
|
e.D = false;
|
|
119
131
|
e.P = e.B;
|
|
120
|
-
const
|
|
121
|
-
if (!e.P &&
|
|
132
|
+
const n = e.j;
|
|
133
|
+
if (!e.P && n.l & CONFIG_HELD && txOf(n) !== flushTransaction) unhold(n);
|
|
122
134
|
if (laneStageHook && e.P !== null && e.j !== null) laneStageHook(e.j, e.P, true, false);
|
|
123
135
|
}
|
|
124
136
|
|
|
@@ -131,25 +143,29 @@ function redraw(e) {
|
|
|
131
143
|
|
|
132
144
|
/** `catchHook` (scheduler.ts): status from a frame reader, nearest boundary first.
|
|
133
145
|
* A loading boundary on the way records a pending reader whether or not it
|
|
134
|
-
* catches it (its `on` may collect it later). */ function catchStatus(e,
|
|
135
|
-
if (
|
|
146
|
+
* catches it (its `on` may collect it later). */ function catchStatus(e, n, r) {
|
|
147
|
+
if (n === 0) {
|
|
136
148
|
// A status cleared. Judged by the node's status now, against each
|
|
137
|
-
// boundary's own rule (`
|
|
149
|
+
// boundary's own rule (`prune`'s mask) — the error path clears pending
|
|
138
150
|
// first and the node is still errored then. The last reader a fallback
|
|
139
151
|
// waited on settling re-derives the output now, in the same heap (a
|
|
140
152
|
// held reader's landing has joined its transaction, so the content
|
|
141
153
|
// lands with its run, not a round after). Others still waiting: nothing
|
|
142
|
-
// on screen changes, the fallback stays as it is.
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
154
|
+
// on screen changes, the fallback stays as it is. `node` here is an
|
|
155
|
+
// effect reporting its own status. An error boundary records an effect
|
|
156
|
+
// only while it is errored, and a staged error keeps STATUS_ERROR on a
|
|
157
|
+
// node that had it (`stageError`), so `prune`'s CONFIG_STAGED_ERROR case
|
|
158
|
+
// cannot reach this path (#4364).
|
|
159
|
+
if (collecting.size !== 0) for (let n = boundaryOf(e); n; n = n._parent) if (!(n.F.get(e)?.m & (n.i | STATUS_PENDING)) && n.F.delete(e) && n.F.size === 0) {
|
|
160
|
+
if (n.L) redraw(n);
|
|
161
|
+
if (revealHooks && n.v !== null) revealHooks.V(n.v);
|
|
146
162
|
}
|
|
147
163
|
return false;
|
|
148
164
|
}
|
|
149
165
|
for (let o = boundaryOf(e); o; o = o._parent) {
|
|
150
|
-
if (!(o.i &
|
|
166
|
+
if (!(o.i & n)) continue;
|
|
151
167
|
if (isCollecting(o)) {
|
|
152
|
-
caught(o, e,
|
|
168
|
+
caught(o, e, r);
|
|
153
169
|
return o.h ? CAUGHT_REARMED : true;
|
|
154
170
|
}
|
|
155
171
|
record(o, e);
|
|
@@ -159,12 +175,12 @@ function redraw(e) {
|
|
|
159
175
|
|
|
160
176
|
/** The nearest loading boundary that would catch `node` was re-armed this
|
|
161
177
|
* flush. */ function armedOver(e) {
|
|
162
|
-
for (let
|
|
178
|
+
for (let n = boundaryOf(e); n; n = n._parent) if (n.i & STATUS_PENDING && isCollecting(n)) return n.h;
|
|
163
179
|
}
|
|
164
180
|
|
|
165
181
|
/** The nearest boundary on `r`'s chain showing its fallback, if any
|
|
166
182
|
* (`hiddenHook`: `r` is behind a fallback). */ function hiddenBy(e) {
|
|
167
|
-
for (let
|
|
183
|
+
for (let n = boundaryOf(e); n; n = n._parent) if (n.L) return n;
|
|
168
184
|
return undefined;
|
|
169
185
|
}
|
|
170
186
|
|
|
@@ -179,9 +195,9 @@ function redraw(e) {
|
|
|
179
195
|
* synchronous on creation and never comes here. The run's `_modified` stays
|
|
180
196
|
* set; the reveal re-queues it by type (`release`), and a boundary above
|
|
181
197
|
* still showing its fallback holds it again then. */ function heldRun(e) {
|
|
182
|
-
const
|
|
183
|
-
if (
|
|
184
|
-
(
|
|
198
|
+
const n = hiddenBy(e);
|
|
199
|
+
if (n === undefined) return false;
|
|
200
|
+
(n.M ??= new Set).add(e);
|
|
185
201
|
return true;
|
|
186
202
|
}
|
|
187
203
|
|
|
@@ -189,9 +205,9 @@ function redraw(e) {
|
|
|
189
205
|
* its own phase — render updates with the frame that attaches the content,
|
|
190
206
|
* user effects after it. */ function release(e) {
|
|
191
207
|
if (e.M === null) return;
|
|
192
|
-
for (const
|
|
193
|
-
const e =
|
|
194
|
-
globalQueue.enqueue(e === EFFECT_TRACKED ? EFFECT_USER : e, e === EFFECT_TRACKED ?
|
|
208
|
+
for (const n of e.M) {
|
|
209
|
+
const e = n.i;
|
|
210
|
+
globalQueue.enqueue(e === EFFECT_TRACKED ? EFFECT_USER : e, e === EFFECT_TRACKED ? n.Z : n.W ??= GlobalQueue.q.bind(null, n));
|
|
195
211
|
}
|
|
196
212
|
e.M = null;
|
|
197
213
|
}
|
|
@@ -201,13 +217,21 @@ function redraw(e) {
|
|
|
201
217
|
* that landed but is held (its value staged in a transaction) is not: the
|
|
202
218
|
* content reveals at the commit, with its run. The tree is: the output reads
|
|
203
219
|
* it and enters the transaction itself (its committed value shows until the
|
|
204
|
-
* landing).
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
220
|
+
* landing). The statuses that keep a reader: pending — and its error, for an
|
|
221
|
+
* error boundary (`_type` is the status it catches) — on the reader or its
|
|
222
|
+
* source. A reader pending again after the source that threw answered (it
|
|
223
|
+
* re-asks through a memo that carried the error) has no new answer yet: the
|
|
224
|
+
* error stays the display (D-39: a pending is not a value; async-gen 91501
|
|
225
|
+
* #1831). */ function prune(e, n) {
|
|
226
|
+
const r = e.i | STATUS_PENDING;
|
|
227
|
+
for (const [o, t] of e.F) {
|
|
228
|
+
if (!((o.R | t.R) & REACTIVE_DISPOSED)) {
|
|
229
|
+
// An error staged on its source (D-41, `stageError`) is not settled:
|
|
230
|
+
// it publishes with the commit. A reader that threw it now (a lane
|
|
231
|
+
// pass, a reader of a node born staged) reached the boundary first
|
|
232
|
+
// (#4364).
|
|
233
|
+
if ((o.m | t.m) & r || r & STATUS_ERROR && t.l & CONFIG_STAGED_ERROR) continue;
|
|
234
|
+
if ((t !== e.K || e.h) && (t.l & (CONFIG_HELD | CONFIG_OVERRIDE)) === CONFIG_HELD) {
|
|
211
235
|
// Landed, held: the content is that transaction's — the output's
|
|
212
236
|
// pass enters it and the reveal lands with the reader's run. The
|
|
213
237
|
// seam, past its park decision, waits for the commit instead. (A
|
|
@@ -215,11 +239,11 @@ function prune(e, r) {
|
|
|
215
239
|
// has not shown content catches it instead: the fallback stays until
|
|
216
240
|
// the reader is committed (#3540: what a fresh boundary catches holds
|
|
217
241
|
// nothing outside it).
|
|
218
|
-
if (!
|
|
219
|
-
joinFuture(txOf(
|
|
242
|
+
if (!n || !e.D) continue;
|
|
243
|
+
joinFuture(txOf(t));
|
|
220
244
|
}
|
|
221
|
-
e.F.delete(o);
|
|
222
245
|
}
|
|
246
|
+
e.F.delete(o);
|
|
223
247
|
}
|
|
224
248
|
return e.F.size;
|
|
225
249
|
}
|
|
@@ -227,23 +251,28 @@ function prune(e, r) {
|
|
|
227
251
|
/** Reveal order: a slot is ready when its content can show — it has shown
|
|
228
252
|
* content, or nothing under it is unready (the tree neither pending nor
|
|
229
253
|
* born held, no reader waited on). */ function ready(e) {
|
|
230
|
-
return e.D || !(e.
|
|
254
|
+
return e.D || !(e.K.m & STATUS_PENDING) && !(e.K.l & CONFIG_HELD && (e.j === null || e.j.m & STATUS_UNINITIALIZED)) && prune(e, false) === 0;
|
|
231
255
|
}
|
|
232
256
|
|
|
233
257
|
/** `boundarySeamHook` (scheduler.ts), end of the seam: readers that settled, died,
|
|
234
258
|
* or landed and committed are dropped; a fallback with none left reveals
|
|
235
259
|
* next round. An arm resolves: nothing collected, nothing happened. */ function boundarySeam() {
|
|
236
260
|
for (const e of collecting) {
|
|
237
|
-
const
|
|
238
|
-
if (
|
|
261
|
+
const n = e.j.R;
|
|
262
|
+
if (n & REACTIVE_DISPOSED) {
|
|
239
263
|
collecting.delete(e);
|
|
240
264
|
continue;
|
|
241
265
|
}
|
|
242
266
|
// A parked frame's boundary (zombie) keeps its state for its revival.
|
|
243
|
-
if (
|
|
267
|
+
if (n & REACTIVE_ZOMBIE) continue;
|
|
244
268
|
prune(e, false);
|
|
245
|
-
const
|
|
246
|
-
|
|
269
|
+
const r = e.j;
|
|
270
|
+
// A fallback staged into the very hold its readers landed in folds back
|
|
271
|
+
// (D-16, U-9): the content is ready when that hold commits (D-15). Not
|
|
272
|
+
// only at the re-arm's own seam: readers pending then land, held, a
|
|
273
|
+
// flush later (#4379 — the staged fallback otherwise commits with the
|
|
274
|
+
// hold, and a quiet refresh then caught keeps it up, F-9).
|
|
275
|
+
if (!e.D && r.l & CONFIG_HELD && [ ...e.F ].every(([, e]) => !(e.m & STATUS_PENDING) && e.l & CONFIG_HELD && txOf(e) === txOf(r))) {
|
|
247
276
|
e.F.clear();
|
|
248
277
|
e.D = true;
|
|
249
278
|
}
|
|
@@ -284,22 +313,25 @@ function prune(e, r) {
|
|
|
284
313
|
// whose frame has no transaction yet: the swap is still display-ahead — the frame gets one now (it lands
|
|
285
314
|
// at this very seam if nothing holds it), and the swap is its verdict
|
|
286
315
|
// lane's work, shown ahead of the frame's own runs (#3528).
|
|
287
|
-
let
|
|
288
|
-
if (
|
|
316
|
+
let n = passLane;
|
|
317
|
+
if (n === null && globalQueue.Y && getOwner().l & CONFIG_VERDICT) {
|
|
289
318
|
joinFuture(null);
|
|
290
|
-
|
|
319
|
+
n = GlobalQueue.J(flushTransaction);
|
|
291
320
|
}
|
|
292
|
-
e.B =
|
|
321
|
+
e.B = n;
|
|
293
322
|
collecting.add(e);
|
|
294
|
-
const
|
|
295
|
-
heldUnder(e.H, flushTransaction,
|
|
296
|
-
for (const
|
|
297
|
-
if (e.F.size !==
|
|
323
|
+
const r = e.F.size;
|
|
324
|
+
heldUnder(e.H, flushTransaction, n => record(e, n));
|
|
325
|
+
for (const [n] of e.F) {
|
|
326
|
+
if (e.F.size !== r || n.m & STATUS_PENDING && !(n.R & REACTIVE_DISPOSED)) {
|
|
298
327
|
// What it collects was forwarded through it to the boundaries above
|
|
299
328
|
// too (`catchStatus` records a reader in every boundary on the way).
|
|
300
329
|
// It is this boundary's alone now (B5, the nearest catcher): an outer
|
|
301
330
|
// re-armed by the same tick does not wait for it (D-14, U-4).
|
|
302
|
-
for (let
|
|
331
|
+
for (let n = e._parent; n !== null; n = n._parent)
|
|
332
|
+
// An outer error boundary keys its readers too, but waits on their
|
|
333
|
+
// sources: a re-armed Loading taking the pending does not settle it.
|
|
334
|
+
if (n.i & STATUS_PENDING) for (const [r] of e.F) n.F.delete(r);
|
|
303
335
|
flip(e);
|
|
304
336
|
redraw(e);
|
|
305
337
|
return;
|
|
@@ -310,19 +342,33 @@ function prune(e, r) {
|
|
|
310
342
|
/** The error boundary's `reset`: re-run what threw (a comparator throw
|
|
311
343
|
* names a signal — nothing to re-run). */ function reset(e) {
|
|
312
344
|
// A snapshot: a source failing again is caught — and re-added — mid-walk.
|
|
313
|
-
for (const
|
|
345
|
+
for (const n of new Set(e.F.values())) if (n.X !== undefined && !(n.R & REACTIVE_DISPOSED)) recompute(n);
|
|
314
346
|
schedule();
|
|
315
347
|
}
|
|
316
348
|
|
|
317
|
-
|
|
349
|
+
/**
|
|
350
|
+
* Dev CHECK: the `on` dependencies evaluated to a function — `<Loading
|
|
351
|
+
* on={route}>` or `on={() => route()}` passes the accessor itself, a stable
|
|
352
|
+
* value that is never called, so nothing is read and the boundary never
|
|
353
|
+
* re-arms. Checked on the first run only: the shape is static.
|
|
354
|
+
*/ function reportOnAccessor(e) {
|
|
355
|
+
reportDiagnostic(emitDiagnostic({
|
|
356
|
+
code: "LOADING_ON_ACCESSOR",
|
|
357
|
+
kind: "async",
|
|
358
|
+
severity: "warn",
|
|
359
|
+
message: "[LOADING_ON_ACCESSOR] A Loading boundary's `on` received a function. `on` takes the " + "dependency's value — `on={route()}`, or `on={[query(), page()]}` for several — and an " + "accessor passed instead is never called, so nothing is read and the boundary never re-arms."
|
|
360
|
+
}, e.H));
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
function createBoundary(e, n, r, o) {
|
|
318
364
|
const t = createOwner();
|
|
319
365
|
const l = {
|
|
320
366
|
i: e,
|
|
321
367
|
_parent: boundaryOf(t) ?? null,
|
|
322
368
|
H: t,
|
|
323
|
-
|
|
369
|
+
K: null,
|
|
324
370
|
j: null,
|
|
325
|
-
F: new
|
|
371
|
+
F: new Map,
|
|
326
372
|
D: false,
|
|
327
373
|
h: false,
|
|
328
374
|
B: null,
|
|
@@ -333,13 +379,13 @@ function createBoundary(e, r, n, o) {
|
|
|
333
379
|
$: false,
|
|
334
380
|
ee: false,
|
|
335
381
|
U: e === STATUS_ERROR ? signal(undefined, ERROR_SIGNAL) : null,
|
|
336
|
-
|
|
337
|
-
|
|
382
|
+
ne: r,
|
|
383
|
+
re: null
|
|
338
384
|
};
|
|
339
|
-
const
|
|
385
|
+
const a = e === STATUS_PENDING ? t.A[REVEAL] : null;
|
|
340
386
|
if (getOwner()) cleanup(() => {
|
|
341
387
|
collecting.delete(l);
|
|
342
|
-
if (revealHooks &&
|
|
388
|
+
if (revealHooks && a) revealHooks.oe(a, l);
|
|
343
389
|
});
|
|
344
390
|
// The `on` dependencies live OUTSIDE the boundary, as the condition of a
|
|
345
391
|
// `<Show>` wrapping it would: created before the owner's context names it.
|
|
@@ -350,7 +396,8 @@ function createBoundary(e, r, n, o) {
|
|
|
350
396
|
let e = false;
|
|
351
397
|
runWithOwner(t, () => computed(() => {
|
|
352
398
|
try {
|
|
353
|
-
o();
|
|
399
|
+
const n = o();
|
|
400
|
+
if (false && !e && typeof n === "function") ;
|
|
354
401
|
} catch (e) {
|
|
355
402
|
if (!(e instanceof NotReadyError)) {
|
|
356
403
|
if (!globalQueue.notify(getOwner(), STATUS_ERROR, STATUS_ERROR, e)) {
|
|
@@ -363,32 +410,32 @@ function createBoundary(e, r, n, o) {
|
|
|
363
410
|
if (e) arm(l); else e = true;
|
|
364
411
|
})).l |= CONFIG_REDERIVE;
|
|
365
412
|
}
|
|
366
|
-
const
|
|
413
|
+
const u = {
|
|
367
414
|
...t.A,
|
|
368
415
|
[BOUNDARY]: l
|
|
369
416
|
};
|
|
370
|
-
if (revealHooks !== null)
|
|
371
|
-
t.A =
|
|
417
|
+
if (revealHooks !== null) u[REVEAL] = null;
|
|
418
|
+
t.A = u;
|
|
372
419
|
const i = runWithOwner(t, () => {
|
|
373
|
-
const e = false ? computed(
|
|
420
|
+
const e = false ? computed(n, {
|
|
374
421
|
name: "children"
|
|
375
|
-
}) : computed(
|
|
422
|
+
}) : computed(n);
|
|
376
423
|
return false ? computed(() => flatten(read(e)), {
|
|
377
424
|
name: "boundary"
|
|
378
425
|
}) : computed(() => flatten(read(e)));
|
|
379
426
|
});
|
|
380
|
-
l.
|
|
427
|
+
l.K = i;
|
|
381
428
|
// A slot of the reveal order in its context (reveal.ts): gated until the
|
|
382
429
|
// controller releases it — before the output's first pass.
|
|
383
|
-
if (revealHooks &&
|
|
384
|
-
const
|
|
430
|
+
if (revealHooks && a) revealHooks.te(a, l);
|
|
431
|
+
const s = computed(() => {
|
|
385
432
|
// Structure, not a derivation of its content (CONFIG_FRAME, #4283): it
|
|
386
433
|
// reads a hold it is not part of as the screen, as the render effect
|
|
387
434
|
// flattening the same children without a boundary would. Not while a
|
|
388
435
|
// re-arm's swap is the change's work (`arm`), until that swap commits
|
|
389
436
|
// (D-13, #3540).
|
|
390
|
-
const
|
|
391
|
-
if (!l.h && !(
|
|
437
|
+
const n = getOwner();
|
|
438
|
+
if (!l.h && !(n.l & CONFIG_HELD)) n.l |= CONFIG_FRAME;
|
|
392
439
|
// Reveal order (reveal.ts): a gated slot shows its fallback — or, in a
|
|
393
440
|
// collapsed tail, nothing — whatever its content's state; the
|
|
394
441
|
// controller is told the pass ran (its readiness may have changed) and
|
|
@@ -399,7 +446,7 @@ function createBoundary(e, r, n, o) {
|
|
|
399
446
|
// It may release this very slot (the frontier whose content just
|
|
400
447
|
// settled): the pass goes on to show it — the redraw it asks for is
|
|
401
448
|
// refused mid-pass and not needed.
|
|
402
|
-
link(i,
|
|
449
|
+
link(i, n);
|
|
403
450
|
if (revealHooks && l.v !== null) revealHooks.V(l.v);
|
|
404
451
|
if (l.$) {
|
|
405
452
|
if (l.ee) {
|
|
@@ -416,10 +463,10 @@ function createBoundary(e, r, n, o) {
|
|
|
416
463
|
// display-ahead `on` causes is the lane's, and must still be the
|
|
417
464
|
// fallback. Linked, so its recovery re-derives this pass; read again
|
|
418
465
|
// once clean.
|
|
419
|
-
const
|
|
420
|
-
if (
|
|
421
|
-
link(i,
|
|
422
|
-
if (
|
|
466
|
+
const r = i.m & (STATUS_PENDING | STATUS_ERROR);
|
|
467
|
+
if (r !== 0) {
|
|
468
|
+
link(i, n);
|
|
469
|
+
if (r & e) {
|
|
423
470
|
if (isCollecting(l)) {
|
|
424
471
|
caught(l, i, undefined);
|
|
425
472
|
return fallback(l);
|
|
@@ -444,7 +491,7 @@ function createBoundary(e, r, n, o) {
|
|
|
444
491
|
// enters: the outside sees its committed value until the landing,
|
|
445
492
|
// which reveals the content — a fallback staged earlier is replaced
|
|
446
493
|
// ahead of the commit and never shown.
|
|
447
|
-
if (l.F.size !== 0 &&
|
|
494
|
+
if (l.F.size !== 0 && n.m & STATUS_UNINITIALIZED && !(n.l & CONFIG_HELD)) return fallback(l);
|
|
448
495
|
// Readers under it still unready: the fallback, the tree untouched.
|
|
449
496
|
// The seam re-derives this pass when they settle.
|
|
450
497
|
if (prune(l, true) !== 0) return fallback(l);
|
|
@@ -452,10 +499,10 @@ function createBoundary(e, r, n, o) {
|
|
|
452
499
|
let o;
|
|
453
500
|
try {
|
|
454
501
|
o = read(i);
|
|
455
|
-
} catch (
|
|
456
|
-
if (
|
|
502
|
+
} catch (n) {
|
|
503
|
+
if (n instanceof NotReadyError ? e === STATUS_PENDING : e === STATUS_ERROR) {
|
|
457
504
|
if (isCollecting(l)) {
|
|
458
|
-
caught(l, i,
|
|
505
|
+
caught(l, i, n);
|
|
459
506
|
return fallback(l);
|
|
460
507
|
}
|
|
461
508
|
// Forwarded: a loading boundary showing content keeps it and
|
|
@@ -463,7 +510,7 @@ function createBoundary(e, r, n, o) {
|
|
|
463
510
|
record(l, i);
|
|
464
511
|
}
|
|
465
512
|
// A pending passes an error boundary by (A6).
|
|
466
|
-
throw
|
|
513
|
+
throw n;
|
|
467
514
|
}
|
|
468
515
|
// Readers under it still unready (caught before, or while the read
|
|
469
516
|
// ran the content at a mount): the fallback.
|
|
@@ -479,15 +526,15 @@ function createBoundary(e, r, n, o) {
|
|
|
479
526
|
// the screen does not show (a swap staged with a held frame, replaced
|
|
480
527
|
// before it commits) dies now: what it reads holds nothing (S-22 row
|
|
481
528
|
// 3′, #4268).
|
|
482
|
-
const t = l.
|
|
529
|
+
const t = l.re;
|
|
483
530
|
const drop = () => {
|
|
484
|
-
if (!l.L && l.
|
|
531
|
+
if (!l.L && l.re === t) {
|
|
485
532
|
// A fallback that threw (a rethrow the boundary does not
|
|
486
533
|
// handle) is what an enclosing boundary waits on: it died, and
|
|
487
534
|
// the seam of another round drops it there (#4270).
|
|
488
535
|
if (t.m & STATUS_ERROR) schedule();
|
|
489
536
|
dispose(t);
|
|
490
|
-
l.
|
|
537
|
+
l.re = null;
|
|
491
538
|
}
|
|
492
539
|
};
|
|
493
540
|
if (t !== null) l.j.le !== t.le ? drop() : globalQueue.enqueue(EFFECT_RENDER, drop);
|
|
@@ -505,22 +552,24 @@ function createBoundary(e, r, n, o) {
|
|
|
505
552
|
// and legitimately swaps mid-hydration (resume), so it must never be
|
|
506
553
|
// frozen by snapshot capture.
|
|
507
554
|
{
|
|
508
|
-
|
|
555
|
+
ae: true
|
|
509
556
|
});
|
|
510
|
-
|
|
557
|
+
s.l |= CONFIG_REDERIVE;
|
|
511
558
|
// The tree is structure too (the output's pass marks the output).
|
|
512
559
|
i.l |= CONFIG_FRAME;
|
|
513
|
-
l.j =
|
|
514
|
-
return accessor(
|
|
560
|
+
l.j = s;
|
|
561
|
+
return accessor(s);
|
|
515
562
|
}
|
|
516
563
|
|
|
517
564
|
function fallback(e) {
|
|
565
|
+
// (The output's pass.)
|
|
566
|
+
const n = getOwner();
|
|
518
567
|
// The swap a display-ahead re-arm asked for: this pass is the lane's — a
|
|
519
568
|
// lane read by construction (REACTIVE_LANE_READ: `recompute`'s tail keeps
|
|
520
569
|
// the pass in the lane).
|
|
521
|
-
|
|
570
|
+
if (e.P !== null) {
|
|
522
571
|
setPassLane(e.P);
|
|
523
|
-
|
|
572
|
+
n.R |= REACTIVE_LANE_READ;
|
|
524
573
|
e.P = null;
|
|
525
574
|
}
|
|
526
575
|
e.L = true;
|
|
@@ -535,18 +584,24 @@ function fallback(e) {
|
|
|
535
584
|
// outside the boundary, as the output is: its errors and runs are the
|
|
536
585
|
// enclosing boundary's — with the output's id, so what it builds gets the
|
|
537
586
|
// ids a build under the output would; disposed once content is on screen.
|
|
538
|
-
if (e.
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
587
|
+
if (e.re === null) e.re = runWithOwner(n._parent, () => computed(() => e.ne(e), {
|
|
588
|
+
id: n.id
|
|
589
|
+
}));
|
|
590
|
+
// The swap is structure (#3540): what the fallback reads ahead — a
|
|
591
|
+
// verdict (`latest()`), a lane — is the fallback's display-ahead, not the
|
|
592
|
+
// swap's: the output's pass stays where it was (F-6 stays inside the
|
|
593
|
+
// fallback, #4337).
|
|
594
|
+
const r = passLane;
|
|
595
|
+
const o = n.R;
|
|
596
|
+
const t = read(e.re);
|
|
597
|
+
setPassLane(r);
|
|
598
|
+
n.R ^= (n.R ^ o) & (REACTIVE_PROBED | REACTIVE_LANE_READ);
|
|
599
|
+
return t;
|
|
545
600
|
}
|
|
546
601
|
|
|
547
602
|
const ERROR_SIGNAL = {
|
|
548
603
|
ownedWrite: true,
|
|
549
|
-
|
|
604
|
+
ae: true
|
|
550
605
|
};
|
|
551
606
|
|
|
552
607
|
/**
|
|
@@ -590,8 +645,8 @@ const ERROR_SIGNAL = {
|
|
|
590
645
|
* ) as unknown as JSX.Element;
|
|
591
646
|
* }
|
|
592
647
|
* ```
|
|
593
|
-
*/ function createLoadingBoundary(e,
|
|
594
|
-
return createBoundary(STATUS_PENDING, e, () =>
|
|
648
|
+
*/ function createLoadingBoundary(e, n, r) {
|
|
649
|
+
return createBoundary(STATUS_PENDING, e, () => n(), r?.on);
|
|
595
650
|
}
|
|
596
651
|
|
|
597
652
|
/**
|
|
@@ -616,12 +671,12 @@ const ERROR_SIGNAL = {
|
|
|
616
671
|
* ) as unknown as JSX.Element;
|
|
617
672
|
* }
|
|
618
673
|
* ```
|
|
619
|
-
*/ function createErrorBoundary(e,
|
|
620
|
-
return createBoundary(STATUS_ERROR, e, e =>
|
|
674
|
+
*/ function createErrorBoundary(e, n) {
|
|
675
|
+
return createBoundary(STATUS_ERROR, e, e => n(accessor(e.U), () => reset(e)));
|
|
621
676
|
}
|
|
622
677
|
|
|
623
678
|
// Installed at module evaluation — present exactly when something imports a
|
|
624
679
|
// boundary. An app without one pays the three null checks and nothing else.
|
|
625
|
-
installBoundaryHooks(catchStatus, (e,
|
|
680
|
+
installBoundaryHooks(catchStatus, (e, n) => !n && (e.m & STATUS_UNINITIALIZED ? catchStatus(e, STATUS_PENDING) : armedOver(e)), hiddenBy, boundarySeam, heldRun);
|
|
626
681
|
|
|
627
682
|
export { REVEAL, createErrorBoundary, createLoadingBoundary, prune, ready, redraw, revealHooks, setRevealHooks };
|