@solidjs/signals 2.0.0-rc.14 → 2.0.0-rc.15
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 +248 -189
- package/dist/dev.attribution.js +124 -41
- package/dist/dev.js +553 -322
- package/dist/observe/affects.js +34 -31
- package/dist/observe/boundaries.js +166 -132
- package/dist/observe/core/async.js +90 -83
- package/dist/observe/core/attribution-queries.js +1 -1
- package/dist/observe/core/attribution.js +281 -197
- package/dist/observe/core/constants.js +7 -2
- package/dist/observe/core/context.js +3 -3
- package/dist/observe/core/core.js +277 -245
- package/dist/observe/core/dev.js +3 -3
- package/dist/observe/core/effect.js +21 -21
- package/dist/observe/core/external.js +2 -2
- package/dist/observe/core/graph.js +25 -25
- package/dist/observe/core/heap.js +9 -9
- package/dist/observe/core/lanes.js +206 -160
- package/dist/observe/core/owner.js +27 -27
- package/dist/observe/core/scheduler.js +92 -86
- package/dist/observe/core/verdict.js +66 -54
- package/dist/observe/map.js +35 -35
- package/dist/observe/reveal.js +24 -24
- package/dist/observe/signals.js +38 -28
- package/dist/observe/store/affects.js +75 -68
- package/dist/observe/store/hooks.js +13 -0
- package/dist/observe/store/index.js +0 -2
- package/dist/observe/store/optimistic.js +67 -34
- package/dist/observe/store/projection.js +37 -31
- package/dist/observe/store/reconcile.js +32 -30
- package/dist/observe/store/store.js +128 -85
- package/dist/prod/affects.js +34 -31
- package/dist/prod/boundaries.js +143 -109
- package/dist/prod/core/async.js +64 -67
- package/dist/prod/core/constants.js +7 -2
- package/dist/prod/core/context.js +3 -3
- package/dist/prod/core/core.js +302 -270
- package/dist/prod/core/effect.js +38 -38
- package/dist/prod/core/external.js +4 -4
- package/dist/prod/core/graph.js +27 -27
- package/dist/prod/core/heap.js +30 -30
- package/dist/prod/core/lanes.js +257 -211
- package/dist/prod/core/owner.js +39 -39
- package/dist/prod/core/scheduler.js +125 -119
- package/dist/prod/core/verdict.js +70 -58
- package/dist/prod/map.js +73 -73
- package/dist/prod/reveal.js +38 -38
- package/dist/prod/signals.js +30 -20
- package/dist/prod/store/affects.js +75 -68
- package/dist/prod/store/hooks.js +13 -0
- package/dist/prod/store/index.js +0 -2
- package/dist/prod/store/optimistic.js +114 -81
- package/dist/prod/store/projection.js +30 -24
- package/dist/prod/store/reconcile.js +32 -30
- package/dist/prod/store/store.js +136 -93
- package/dist/types/boundaries.d.ts +4 -0
- package/dist/types/core/attribution.d.ts +6 -2
- package/dist/types/core/constants.d.ts +5 -0
- package/dist/types/core/core.d.ts +33 -3
- package/dist/types/core/lanes.d.ts +10 -0
- package/dist/types/core/scheduler.d.ts +12 -6
- package/dist/types/core/types.d.ts +0 -6
- package/dist/types/store/affects.d.ts +11 -0
- package/dist/types/store/hooks.d.ts +48 -0
- package/dist/types/store/index.d.ts +0 -1
- package/dist/types/store/store.d.ts +3 -38
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { STATUS_PENDING, STATUS_ERROR, CONFIG_REDERIVE, REACTIVE_DISPOSED, STATUS_UNINITIALIZED, CONFIG_HELD, REACTIVE_ZOMBIE, CONFIG_VERDICT, REACTIVE_LANE_READ, CONFIG_OVERRIDE, EFFECT_USER, EFFECT_TRACKED } from "./core/constants.js";
|
|
1
|
+
import { STATUS_PENDING, STATUS_ERROR, CONFIG_REDERIVE, REACTIVE_DISPOSED, STATUS_UNINITIALIZED, CONFIG_HELD, EFFECT_RENDER, REACTIVE_ZOMBIE, CONFIG_VERDICT, REACTIVE_LANE_READ, CONFIG_OVERRIDE, EFFECT_USER, EFFECT_TRACKED } from "./core/constants.js";
|
|
2
2
|
|
|
3
3
|
import { signal, runWithOwner, computed, read, setSignal, recompute } from "./core/core.js";
|
|
4
4
|
|
|
@@ -12,7 +12,7 @@ import { link } from "./core/graph.js";
|
|
|
12
12
|
|
|
13
13
|
import { enqueueSub } from "./core/heap.js";
|
|
14
14
|
|
|
15
|
-
import { createOwner, getOwner, cleanup } from "./core/owner.js";
|
|
15
|
+
import { createOwner, getOwner, cleanup, dispose } from "./core/owner.js";
|
|
16
16
|
|
|
17
17
|
import { globalQueue, haltReactivity, passLane, joinFuture, GlobalQueue, flushTransaction, schedule, setPassLane, passTx, resolveTx, txOf } from "./core/scheduler.js";
|
|
18
18
|
|
|
@@ -77,34 +77,34 @@ function setRevealHooks(e) {
|
|
|
77
77
|
|
|
78
78
|
/** Boundaries with readers to sweep (or an arm to resolve) at the seam. */ const collecting = new Set;
|
|
79
79
|
|
|
80
|
-
const boundaryOf = e => e.
|
|
80
|
+
const boundaryOf = e => e.D[BOUNDARY];
|
|
81
81
|
|
|
82
82
|
/** Catches what reaches it: an error boundary always; a loading one until it
|
|
83
|
-
* has shown content, or while re-armed. */ const isCollecting = e => e.
|
|
83
|
+
* has shown content, or while re-armed. */ const isCollecting = e => e.u === STATUS_ERROR || !e.h || e.U;
|
|
84
84
|
|
|
85
85
|
/** The reader goes to the fallback: recorded, and the output re-derives
|
|
86
86
|
* (a no-op while the output's own pass is running — its post-check
|
|
87
87
|
* decides). */ function caught(e, n, r) {
|
|
88
|
-
if (e.
|
|
88
|
+
if (e.u === STATUS_ERROR) {
|
|
89
89
|
// An error boundary waits on what THREW (`StatusError.source`), not on
|
|
90
90
|
// the reader that saw it: the reader recovers the moment a refetch
|
|
91
91
|
// starts (its boundary catches the pending), while the error is settled
|
|
92
92
|
// only when its source is neither errored nor in flight. `reset` re-runs
|
|
93
93
|
// the same node.
|
|
94
|
-
r ??= n.m?.
|
|
94
|
+
r ??= n.m?.F;
|
|
95
95
|
n = r?.source ?? n;
|
|
96
96
|
const t = unwrapStatusError(r);
|
|
97
|
-
setSignal(e.
|
|
98
|
-
reportClientError(t, e.
|
|
97
|
+
setSignal(e.F, t);
|
|
98
|
+
reportClientError(t, e.L, n);
|
|
99
99
|
}
|
|
100
|
-
e.
|
|
100
|
+
e.v.add(n);
|
|
101
101
|
collecting.add(e);
|
|
102
|
-
if (e.
|
|
102
|
+
if (e.U) flip(e);
|
|
103
103
|
// Already showing the fallback: one more reader to wait on changes
|
|
104
104
|
// nothing on screen. The fallback is instantiated once per show — a later
|
|
105
105
|
// error reaches it through the `error` accessor, which is why it is one.
|
|
106
|
-
if (!e.
|
|
107
|
-
if (e.
|
|
106
|
+
if (!e.H) redraw(e);
|
|
107
|
+
if (e.V !== null) revealHooks.P(e.V);
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
/** A re-armed boundary found something pending: fresh again, and the swap
|
|
@@ -112,14 +112,14 @@ const boundaryOf = e => e.U[BOUNDARY];
|
|
|
112
112
|
* the lane's work from its next pass's head — not a re-pass of the
|
|
113
113
|
* transaction holding its pending content, which would entangle that
|
|
114
114
|
* transaction with the arming frame's (#3540 `on: () => latest(dep)`). */ function flip(e) {
|
|
115
|
-
e.
|
|
116
|
-
e.
|
|
117
|
-
if (e.
|
|
115
|
+
e.h = false;
|
|
116
|
+
e.B = e.j;
|
|
117
|
+
if (e.B !== null && e.Z !== null) GlobalQueue.W(e.Z, e.B, true, false);
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
function redraw(e) {
|
|
121
|
-
if (e.
|
|
122
|
-
enqueueSub(e.
|
|
121
|
+
if (e.Z !== null && !(e.Z.R & (REACTIVE_DISPOSED | REACTIVE_ZOMBIE))) {
|
|
122
|
+
enqueueSub(e.Z);
|
|
123
123
|
schedule();
|
|
124
124
|
}
|
|
125
125
|
}
|
|
@@ -135,26 +135,26 @@ function redraw(e) {
|
|
|
135
135
|
// held reader's landing has joined its transaction, so the content
|
|
136
136
|
// lands with its run, not a round after). Others still waiting: nothing
|
|
137
137
|
// on screen changes, the fallback stays as it is.
|
|
138
|
-
if (collecting.size !== 0) for (let n = boundaryOf(e); n !== undefined; n = n._parent ?? undefined) if (!(e.
|
|
139
|
-
if (n.
|
|
140
|
-
if (n.
|
|
138
|
+
if (collecting.size !== 0) for (let n = boundaryOf(e); n !== undefined; n = n._parent ?? undefined) if (!(e.S & unsettled(n)) && n.v.delete(e) && n.v.size === 0) {
|
|
139
|
+
if (n.H) redraw(n);
|
|
140
|
+
if (n.V !== null) revealHooks.P(n.V);
|
|
141
141
|
}
|
|
142
142
|
return false;
|
|
143
143
|
}
|
|
144
144
|
for (let t = boundaryOf(e); t !== undefined; t = t._parent ?? undefined) {
|
|
145
|
-
if (!(t.
|
|
145
|
+
if (!(t.u & n)) continue;
|
|
146
146
|
if (isCollecting(t)) {
|
|
147
147
|
caught(t, e, r);
|
|
148
148
|
return true;
|
|
149
149
|
}
|
|
150
|
-
t.
|
|
150
|
+
t.v.add(e);
|
|
151
151
|
collecting.add(t);
|
|
152
152
|
}
|
|
153
153
|
return false;
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
/** The nearest boundary on `r`'s chain showing its fallback, if any. */ function hiddenBy(e) {
|
|
157
|
-
for (let n = boundaryOf(e); n !== undefined; n = n._parent ?? undefined) if (n.
|
|
157
|
+
for (let n = boundaryOf(e); n !== undefined; n = n._parent ?? undefined) if (n.H) return n;
|
|
158
158
|
return undefined;
|
|
159
159
|
}
|
|
160
160
|
|
|
@@ -175,19 +175,19 @@ function redraw(e) {
|
|
|
175
175
|
* still showing its fallback holds it again then. */ function heldRun(e) {
|
|
176
176
|
const n = hiddenBy(e);
|
|
177
177
|
if (n === undefined) return false;
|
|
178
|
-
(n.
|
|
178
|
+
(n.K ??= new Set).add(e);
|
|
179
179
|
return true;
|
|
180
180
|
}
|
|
181
181
|
|
|
182
182
|
/** The reveal: the runs held behind the fallback are this flush's, each in
|
|
183
183
|
* its own phase — render updates with the frame that attaches the content,
|
|
184
184
|
* user effects after it. */ function release(e) {
|
|
185
|
-
if (e.
|
|
186
|
-
for (const n of e.
|
|
187
|
-
const e = n.
|
|
188
|
-
globalQueue.enqueue(e === EFFECT_TRACKED ? EFFECT_USER : e, e === EFFECT_TRACKED ? n.
|
|
185
|
+
if (e.K === null) return;
|
|
186
|
+
for (const n of e.K) {
|
|
187
|
+
const e = n.u;
|
|
188
|
+
globalQueue.enqueue(e === EFFECT_TRACKED ? EFFECT_USER : e, e === EFFECT_TRACKED ? n.M : n.Y ??= GlobalQueue.q.bind(null, n));
|
|
189
189
|
}
|
|
190
|
-
e.
|
|
190
|
+
e.K = null;
|
|
191
191
|
}
|
|
192
192
|
|
|
193
193
|
/** Drop the readers that settled or died. Settled: a loading reader no
|
|
@@ -195,37 +195,40 @@ function redraw(e) {
|
|
|
195
195
|
* that landed but is held (its value staged in a transaction) is not: the
|
|
196
196
|
* content reveals at the commit, with its run. The tree is: the output reads
|
|
197
197
|
* it and enters the transaction itself (its committed value shows until the
|
|
198
|
-
* landing). */ const unsettled = e => e.
|
|
198
|
+
* landing). */ const unsettled = e => e.u === STATUS_ERROR ? STATUS_ERROR | STATUS_PENDING : STATUS_PENDING;
|
|
199
199
|
|
|
200
200
|
function prune(e, n) {
|
|
201
201
|
const r = unsettled(e);
|
|
202
|
-
for (const t of e.
|
|
203
|
-
if (t.R & REACTIVE_DISPOSED) e.
|
|
204
|
-
if (t !== e
|
|
202
|
+
for (const t of e.v) {
|
|
203
|
+
if (t.R & REACTIVE_DISPOSED) e.v.delete(t); else if (!(t.S & r)) {
|
|
204
|
+
if (t !== e.J && (t.i & (CONFIG_HELD | CONFIG_OVERRIDE)) === CONFIG_HELD) {
|
|
205
205
|
// Landed, held: the content is that transaction's — the output's
|
|
206
206
|
// pass enters it and the reveal lands with the reader's run. The
|
|
207
207
|
// seam, past its park decision, waits for the commit instead. (A
|
|
208
|
-
// lane's reader reveals with the lane, this round.)
|
|
209
|
-
|
|
208
|
+
// lane's reader reveals with the lane, this round.) A boundary that
|
|
209
|
+
// has not shown content catches it instead: the fallback stays until
|
|
210
|
+
// the reader is committed (#3540: what a fresh boundary catches holds
|
|
211
|
+
// nothing outside it).
|
|
212
|
+
if (!n || !e.h) continue;
|
|
210
213
|
joinFuture(txOf(t));
|
|
211
214
|
}
|
|
212
|
-
e.
|
|
215
|
+
e.v.delete(t);
|
|
213
216
|
}
|
|
214
217
|
}
|
|
215
|
-
return e.
|
|
218
|
+
return e.v.size;
|
|
216
219
|
}
|
|
217
220
|
|
|
218
221
|
/** Reveal order: a slot is ready when its content can show — it has shown
|
|
219
222
|
* content, or nothing under it is unready (the tree neither pending nor
|
|
220
223
|
* born held, no reader waited on). */ function ready(e) {
|
|
221
|
-
return e.
|
|
224
|
+
return e.h || !(e.J.S & STATUS_PENDING) && !(e.J.i & CONFIG_HELD && (e.Z === null || e.Z.S & STATUS_UNINITIALIZED)) && prune(e, false) === 0;
|
|
222
225
|
}
|
|
223
226
|
|
|
224
227
|
/** GlobalQueue._boundarySeam, end of the seam: readers that settled, died,
|
|
225
228
|
* or landed and committed are dropped; a fallback with none left reveals
|
|
226
229
|
* next round. An arm resolves: nothing collected, nothing happened. */ function boundarySeam() {
|
|
227
230
|
for (const e of collecting) {
|
|
228
|
-
const n = e.
|
|
231
|
+
const n = e.Z.R;
|
|
229
232
|
if (n & REACTIVE_DISPOSED) {
|
|
230
233
|
collecting.delete(e);
|
|
231
234
|
continue;
|
|
@@ -233,11 +236,11 @@ function prune(e, n) {
|
|
|
233
236
|
// A parked frame's boundary (zombie) keeps its state for its revival.
|
|
234
237
|
if (n & REACTIVE_ZOMBIE) continue;
|
|
235
238
|
prune(e, false);
|
|
236
|
-
e.
|
|
237
|
-
if (e.
|
|
239
|
+
e.U = false;
|
|
240
|
+
if (e.v.size === 0) {
|
|
238
241
|
collecting.delete(e);
|
|
239
|
-
if (e.
|
|
240
|
-
if (e.
|
|
242
|
+
if (e.H) redraw(e);
|
|
243
|
+
if (e.V !== null) revealHooks.P(e.V);
|
|
241
244
|
}
|
|
242
245
|
}
|
|
243
246
|
}
|
|
@@ -245,22 +248,22 @@ function prune(e, n) {
|
|
|
245
248
|
/** The `on` pass is a verdict's: it probed itself (CONFIG_VERDICT), or it
|
|
246
249
|
* read a memo that did (#3528's `createMemo(() => isPending(m2))`) — its
|
|
247
250
|
* swap is display-ahead either way. */ function verdictDerived(e) {
|
|
248
|
-
if (e.
|
|
249
|
-
for (let n = e.
|
|
251
|
+
if (e.i & CONFIG_VERDICT) return true;
|
|
252
|
+
for (let n = e.G; n !== null; n = n._) if (n.I.i & CONFIG_VERDICT) return true;
|
|
250
253
|
return false;
|
|
251
254
|
}
|
|
252
255
|
|
|
253
256
|
/** `on` changed after the mount: fresh again if anything under it is
|
|
254
257
|
* pending now; collecting for the rest of the flush either way. */ function arm(e) {
|
|
255
|
-
if (!e.
|
|
258
|
+
if (!e.h) {
|
|
256
259
|
// Already re-armed and on its fallback, as the frame's work — and the
|
|
257
260
|
// `on` pass arms again as lane work: its verdict was provisional (a
|
|
258
261
|
// memo of `isPending(m2)` is a watcher until the flush parks, then the
|
|
259
262
|
// holder's verdict lane's — verdict.ts), and the swap it asked for is
|
|
260
263
|
// display-ahead after all (#3528). Re-home the swap: the output re-runs
|
|
261
264
|
// as the lane's, shown now beside the held frame.
|
|
262
|
-
if (e.
|
|
263
|
-
e.
|
|
265
|
+
if (e.H && e.B === null && e.j === null && passLane !== null) {
|
|
266
|
+
e.j = passLane;
|
|
264
267
|
// The swap the frame's pass staged (held with the frame) is void: the
|
|
265
268
|
// lane's pass stages it anew (`flip` lists the output in the lane,
|
|
266
269
|
// which voids its staging), as a watcher's provisional value is
|
|
@@ -270,20 +273,20 @@ function prune(e, n) {
|
|
|
270
273
|
}
|
|
271
274
|
return;
|
|
272
275
|
}
|
|
273
|
-
e.
|
|
276
|
+
e.U = true;
|
|
274
277
|
// A verdict read in `on` (`isPending`) whose frame has no transaction
|
|
275
278
|
// yet: the swap is still display-ahead — the frame gets one now (it lands
|
|
276
279
|
// at this very seam if nothing holds it), and the swap is its verdict
|
|
277
280
|
// lane's work, shown ahead of the frame's own runs (#3528).
|
|
278
281
|
let n = passLane;
|
|
279
|
-
if (n === null && globalQueue.
|
|
282
|
+
if (n === null && globalQueue.X && verdictDerived(getOwner())) {
|
|
280
283
|
joinFuture(null);
|
|
281
|
-
n = GlobalQueue
|
|
284
|
+
n = GlobalQueue.$(flushTransaction);
|
|
282
285
|
}
|
|
283
|
-
e.
|
|
286
|
+
e.j = n;
|
|
284
287
|
collecting.add(e);
|
|
285
|
-
for (const n of e.
|
|
286
|
-
if (n.
|
|
288
|
+
for (const n of e.v) {
|
|
289
|
+
if (n.S & STATUS_PENDING && !(n.R & REACTIVE_DISPOSED)) {
|
|
287
290
|
flip(e);
|
|
288
291
|
redraw(e);
|
|
289
292
|
return;
|
|
@@ -294,35 +297,36 @@ function prune(e, n) {
|
|
|
294
297
|
/** The error boundary's `reset`: re-run what threw (a comparator throw
|
|
295
298
|
* names a signal — nothing to re-run). */ function reset(e) {
|
|
296
299
|
// A snapshot: a source failing again is caught — and re-added — mid-walk.
|
|
297
|
-
for (const n of [ ...e.
|
|
300
|
+
for (const n of [ ...e.v ]) if (n.ee !== undefined && !(n.R & REACTIVE_DISPOSED)) recompute(n);
|
|
298
301
|
schedule();
|
|
299
302
|
}
|
|
300
303
|
|
|
301
304
|
function createBoundary(e, n, r, t) {
|
|
302
|
-
const
|
|
303
|
-
const
|
|
304
|
-
|
|
305
|
-
_parent: boundaryOf(
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
K: null,
|
|
309
|
-
V: new Set,
|
|
310
|
-
k: false,
|
|
311
|
-
L: false,
|
|
312
|
-
W: null,
|
|
305
|
+
const l = createOwner();
|
|
306
|
+
const o = {
|
|
307
|
+
u: e,
|
|
308
|
+
_parent: boundaryOf(l) ?? null,
|
|
309
|
+
L: l,
|
|
310
|
+
J: null,
|
|
313
311
|
Z: null,
|
|
314
|
-
|
|
315
|
-
|
|
312
|
+
v: new Set,
|
|
313
|
+
h: false,
|
|
314
|
+
U: false,
|
|
315
|
+
j: null,
|
|
316
316
|
B: null,
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
317
|
+
H: false,
|
|
318
|
+
K: null,
|
|
319
|
+
V: null,
|
|
320
|
+
ne: false,
|
|
321
|
+
re: false,
|
|
322
|
+
F: e === STATUS_ERROR ? signal(undefined, ERROR_SIGNAL) : null,
|
|
323
|
+
te: r,
|
|
324
|
+
le: null
|
|
321
325
|
};
|
|
322
|
-
const u = e === STATUS_PENDING ?
|
|
326
|
+
const u = e === STATUS_PENDING ? l.D[REVEAL] : null;
|
|
323
327
|
if (getOwner()) cleanup(() => {
|
|
324
|
-
collecting.delete(
|
|
325
|
-
if (u) revealHooks.
|
|
328
|
+
collecting.delete(o);
|
|
329
|
+
if (u) revealHooks.oe(u, o);
|
|
326
330
|
});
|
|
327
331
|
// The `on` dependencies live OUTSIDE the boundary, as the condition of a
|
|
328
332
|
// `<Show>` wrapping it would: created before the owner's context names it.
|
|
@@ -331,7 +335,7 @@ function createBoundary(e, n, r, t) {
|
|
|
331
335
|
// does not suspend the parent — and re-arms.
|
|
332
336
|
if (t) {
|
|
333
337
|
let e = false;
|
|
334
|
-
runWithOwner(
|
|
338
|
+
runWithOwner(l, () => computed(() => {
|
|
335
339
|
try {
|
|
336
340
|
t();
|
|
337
341
|
} catch (e) {
|
|
@@ -343,16 +347,16 @@ function createBoundary(e, n, r, t) {
|
|
|
343
347
|
return;
|
|
344
348
|
}
|
|
345
349
|
}
|
|
346
|
-
if (e) arm(
|
|
347
|
-
})).
|
|
350
|
+
if (e) arm(o); else e = true;
|
|
351
|
+
})).i |= CONFIG_REDERIVE;
|
|
348
352
|
}
|
|
349
353
|
const a = {
|
|
350
|
-
...
|
|
351
|
-
[BOUNDARY]:
|
|
354
|
+
...l.D,
|
|
355
|
+
[BOUNDARY]: o
|
|
352
356
|
};
|
|
353
357
|
if (revealHooks !== null) a[REVEAL] = null;
|
|
354
|
-
|
|
355
|
-
const i = runWithOwner(
|
|
358
|
+
l.D = a;
|
|
359
|
+
const i = runWithOwner(l, () => {
|
|
356
360
|
const e = true ? computed(n, {
|
|
357
361
|
name: "children"
|
|
358
362
|
}) : computed(n);
|
|
@@ -360,29 +364,29 @@ function createBoundary(e, n, r, t) {
|
|
|
360
364
|
name: "boundary"
|
|
361
365
|
}) : computed(() => flatten(read(e)));
|
|
362
366
|
});
|
|
363
|
-
|
|
367
|
+
o.J = i;
|
|
364
368
|
// A slot of the reveal order in its context (reveal.ts): gated until the
|
|
365
369
|
// controller releases it — before the output's first pass.
|
|
366
|
-
if (u) revealHooks.
|
|
370
|
+
if (u) revealHooks.ue(u, o);
|
|
367
371
|
const f = computed(() => {
|
|
368
372
|
// Reveal order (reveal.ts): a gated slot shows its fallback — or, in a
|
|
369
373
|
// collapsed tail, nothing — whatever its content's state; the
|
|
370
374
|
// controller is told the pass ran (its readiness may have changed) and
|
|
371
375
|
// releases it in turn.
|
|
372
|
-
if (
|
|
376
|
+
if (o.ne) {
|
|
373
377
|
// Linked without being read: the tree settling (or changing)
|
|
374
378
|
// re-derives this pass, which is how the controller hears of it.
|
|
375
379
|
// It may release this very slot (the frontier whose content just
|
|
376
380
|
// settled): the pass goes on to show it — the redraw it asks for is
|
|
377
381
|
// refused mid-pass and not needed.
|
|
378
382
|
link(i, getOwner());
|
|
379
|
-
if (
|
|
380
|
-
if (
|
|
381
|
-
if (
|
|
382
|
-
|
|
383
|
+
if (o.V !== null) revealHooks.P(o.V);
|
|
384
|
+
if (o.ne) {
|
|
385
|
+
if (o.re) {
|
|
386
|
+
o.H = true;
|
|
383
387
|
return undefined;
|
|
384
388
|
}
|
|
385
|
-
return fallback(
|
|
389
|
+
return fallback(o);
|
|
386
390
|
}
|
|
387
391
|
}
|
|
388
392
|
// A tree carrying a status is not read: an errored memo's reactive
|
|
@@ -392,24 +396,24 @@ function createBoundary(e, n, r, t) {
|
|
|
392
396
|
// display-ahead `on` causes is the lane's, and must still be the
|
|
393
397
|
// fallback. Linked, so its recovery re-derives this pass; read again
|
|
394
398
|
// once clean.
|
|
395
|
-
const n = i.
|
|
399
|
+
const n = i.S & (STATUS_PENDING | STATUS_ERROR);
|
|
396
400
|
if (n !== 0) {
|
|
397
401
|
link(i, getOwner());
|
|
398
402
|
if (n & e) {
|
|
399
|
-
if (isCollecting(
|
|
400
|
-
caught(
|
|
401
|
-
return fallback(
|
|
403
|
+
if (isCollecting(o)) {
|
|
404
|
+
caught(o, i, undefined);
|
|
405
|
+
return fallback(o);
|
|
402
406
|
}
|
|
403
407
|
// Forwarded: a loading boundary showing content keeps it and
|
|
404
408
|
// holds the frame like any reader (recorded for its `on`).
|
|
405
|
-
|
|
406
|
-
collecting.add(
|
|
409
|
+
o.v.add(i);
|
|
410
|
+
collecting.add(o);
|
|
407
411
|
}
|
|
408
412
|
// A pending passes an error boundary by (A6); an error, a loading
|
|
409
413
|
// one; a loading boundary showing content forwards its pending.
|
|
410
|
-
throw i.m.
|
|
414
|
+
throw i.m.F;
|
|
411
415
|
}
|
|
412
|
-
if (isCollecting(
|
|
416
|
+
if (isCollecting(o)) {
|
|
413
417
|
// A29's boundary exemption (#3540): a boundary MOUNTED over a held
|
|
414
418
|
// value (its first pass; a first pass under it that read a hold was
|
|
415
419
|
// collected, `joinPass` — the tree's own, or a render effect's that
|
|
@@ -422,43 +426,56 @@ function createBoundary(e, n, r, t) {
|
|
|
422
426
|
// which reveals the content — a fallback staged earlier is replaced
|
|
423
427
|
// ahead of the commit and never shown.
|
|
424
428
|
const e = getOwner();
|
|
425
|
-
if (
|
|
429
|
+
if (o.v.size !== 0 && e.S & STATUS_UNINITIALIZED && !(e.i & CONFIG_HELD)) return fallback(o);
|
|
426
430
|
// Readers under it still unready: the fallback, the tree untouched.
|
|
427
431
|
// The seam re-derives this pass when they settle.
|
|
428
|
-
if (prune(
|
|
432
|
+
if (prune(o, true) !== 0) return fallback(o);
|
|
429
433
|
}
|
|
430
434
|
let r;
|
|
431
435
|
try {
|
|
432
436
|
r = read(i);
|
|
433
437
|
} catch (n) {
|
|
434
438
|
if (n instanceof NotReadyError ? e === STATUS_PENDING : e === STATUS_ERROR) {
|
|
435
|
-
if (isCollecting(
|
|
436
|
-
caught(
|
|
437
|
-
return fallback(
|
|
439
|
+
if (isCollecting(o)) {
|
|
440
|
+
caught(o, i, n);
|
|
441
|
+
return fallback(o);
|
|
438
442
|
}
|
|
439
443
|
// Forwarded: a loading boundary showing content keeps it and
|
|
440
444
|
// holds the frame like any reader (recorded for its `on`).
|
|
441
|
-
|
|
442
|
-
collecting.add(
|
|
445
|
+
o.v.add(i);
|
|
446
|
+
collecting.add(o);
|
|
443
447
|
}
|
|
444
448
|
// A pending passes an error boundary by (A6).
|
|
445
449
|
throw n;
|
|
446
450
|
}
|
|
447
451
|
// Readers under it still unready (caught before, or while the read
|
|
448
452
|
// ran the content at a mount): the fallback.
|
|
449
|
-
if (isCollecting(
|
|
450
|
-
|
|
453
|
+
if (isCollecting(o) && o.v.size !== 0) return fallback(o);
|
|
454
|
+
o.h = true;
|
|
451
455
|
// Observe: the fallback stops showing (a hide before its commit means
|
|
452
456
|
// it never displayed — the engine knows the swap it was staged with).
|
|
453
|
-
if (
|
|
454
|
-
|
|
455
|
-
|
|
457
|
+
if (o.H && o.u & STATUS_PENDING && attrHooks !== null) attrHooks.boundaryFallback(o, o.J, false);
|
|
458
|
+
o.H = false;
|
|
459
|
+
// The fallback dies when the content that replaces it is on screen —
|
|
460
|
+
// with this flush's commits when the pass is the frame's, at the
|
|
461
|
+
// landing when the frame parks (the run is held with it, as the old
|
|
462
|
+
// children of a held pass are) — not now: a held swap keeps the
|
|
463
|
+
// fallback on screen, live, until it commits. A pass back to the
|
|
464
|
+
// fallback before then finds it still built and keeps it.
|
|
465
|
+
const t = o.le;
|
|
466
|
+
if (t !== null) globalQueue.enqueue(EFFECT_RENDER, () => {
|
|
467
|
+
if (!o.H && o.le === t) {
|
|
468
|
+
dispose(t);
|
|
469
|
+
o.le = null;
|
|
470
|
+
}
|
|
471
|
+
});
|
|
472
|
+
release(o);
|
|
456
473
|
// Shown: the slot leaves its reveal order (a later re-arm gates nobody
|
|
457
474
|
// else; the frontier moves on).
|
|
458
|
-
if (
|
|
459
|
-
const e =
|
|
460
|
-
|
|
461
|
-
revealHooks.
|
|
475
|
+
if (o.V !== null) {
|
|
476
|
+
const e = o.V;
|
|
477
|
+
o.V = null;
|
|
478
|
+
revealHooks.P(e);
|
|
462
479
|
}
|
|
463
480
|
return r;
|
|
464
481
|
},
|
|
@@ -467,10 +484,10 @@ function createBoundary(e, n, r, t) {
|
|
|
467
484
|
// frozen by snapshot capture.
|
|
468
485
|
{
|
|
469
486
|
name: "value",
|
|
470
|
-
|
|
487
|
+
ae: true
|
|
471
488
|
});
|
|
472
|
-
f.
|
|
473
|
-
|
|
489
|
+
f.i |= CONFIG_REDERIVE;
|
|
490
|
+
o.Z = f;
|
|
474
491
|
return accessor(f);
|
|
475
492
|
}
|
|
476
493
|
|
|
@@ -478,26 +495,43 @@ function fallback(e) {
|
|
|
478
495
|
// The swap a display-ahead re-arm asked for: this pass is the lane's — a
|
|
479
496
|
// lane read by construction (REACTIVE_LANE_READ: `recompute`'s tail keeps
|
|
480
497
|
// the pass in the lane).
|
|
481
|
-
if (e.
|
|
482
|
-
setPassLane(e.
|
|
483
|
-
e.
|
|
484
|
-
e.
|
|
498
|
+
if (e.B !== null) {
|
|
499
|
+
setPassLane(e.B);
|
|
500
|
+
e.Z.R |= REACTIVE_LANE_READ;
|
|
501
|
+
e.B = null;
|
|
485
502
|
}
|
|
486
503
|
// Observe: a loading boundary starts showing its fallback — the swap lands
|
|
487
504
|
// with the frame's transaction, or this drain commits it (lane work, or no
|
|
488
505
|
// transaction). A mount's synchronous first show has no drain of its own:
|
|
489
506
|
// one is scheduled so the engine's display instant (`flushEnd`) comes.
|
|
490
|
-
if (!e.
|
|
491
|
-
attrHooks.boundaryFallback(e, e
|
|
492
|
-
if (!globalQueue.
|
|
507
|
+
if (!e.H && e.u & STATUS_PENDING && attrHooks !== null) {
|
|
508
|
+
attrHooks.boundaryFallback(e, e.J, true, passLane !== null ? null : flushTransaction !== null ? resolveTx(flushTransaction) : passTx);
|
|
509
|
+
if (!globalQueue.X) schedule();
|
|
510
|
+
}
|
|
511
|
+
e.H = true;
|
|
512
|
+
// Built in its own scope, like `Show`'s function child, once per show
|
|
513
|
+
// (D-39: the fallback is the display until a new answer replaces the
|
|
514
|
+
// error): a re-derive of the output while it shows — a second reader
|
|
515
|
+
// caught, the same error propagated again through a sibling's re-run, a
|
|
516
|
+
// retry pending after `reset()`, a later error — keeps the built
|
|
517
|
+
// fallback, its DOM and focus with it (#3991). A later error reaches it
|
|
518
|
+
// through the error accessor; only a fallback reading the accessor at its
|
|
519
|
+
// top level is rebuilt by it. Created beside the output — in its owner,
|
|
520
|
+
// outside the boundary, as the output is: its errors and runs are the
|
|
521
|
+
// enclosing boundary's — with the output's id, so what it builds gets the
|
|
522
|
+
// ids a build under the output would; disposed once content is on screen.
|
|
523
|
+
if (e.le === null) {
|
|
524
|
+
const n = getOwner();
|
|
525
|
+
e.le = runWithOwner(n._parent, () => computed(() => e.te(e), {
|
|
526
|
+
id: n.id
|
|
527
|
+
}));
|
|
493
528
|
}
|
|
494
|
-
e.
|
|
495
|
-
return e.le(e);
|
|
529
|
+
return read(e.le);
|
|
496
530
|
}
|
|
497
531
|
|
|
498
532
|
const ERROR_SIGNAL = {
|
|
499
533
|
ownedWrite: true,
|
|
500
|
-
|
|
534
|
+
ae: true
|
|
501
535
|
};
|
|
502
536
|
|
|
503
537
|
/**
|
|
@@ -568,19 +602,19 @@ const ERROR_SIGNAL = {
|
|
|
568
602
|
* }
|
|
569
603
|
* ```
|
|
570
604
|
*/ function createErrorBoundary(e, n) {
|
|
571
|
-
return createBoundary(STATUS_ERROR, e, e => n(accessor(e.
|
|
605
|
+
return createBoundary(STATUS_ERROR, e, e => n(accessor(e.F), () => reset(e)));
|
|
572
606
|
}
|
|
573
607
|
|
|
574
608
|
// Installed at module evaluation — present exactly when something imports a
|
|
575
609
|
// boundary. An app without one pays the three null checks and nothing else.
|
|
576
|
-
GlobalQueue.
|
|
610
|
+
GlobalQueue.ie = catchStatus;
|
|
577
611
|
|
|
578
|
-
GlobalQueue.
|
|
612
|
+
GlobalQueue.fe = e => e.S & STATUS_UNINITIALIZED && catchStatus(e, STATUS_PENDING);
|
|
579
613
|
|
|
580
614
|
GlobalQueue.se = hidden;
|
|
581
615
|
|
|
582
|
-
GlobalQueue.
|
|
616
|
+
GlobalQueue.ce = boundarySeam;
|
|
583
617
|
|
|
584
|
-
GlobalQueue.
|
|
618
|
+
GlobalQueue.Ee = heldRun;
|
|
585
619
|
|
|
586
620
|
export { REVEAL, createErrorBoundary, createLoadingBoundary, prune, ready, redraw, revealHooks, setRevealHooks };
|