@solidjs/signals 0.9.8 → 0.9.9
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.js +397 -175
- package/dist/node.cjs +1158 -953
- package/dist/prod.js +955 -756
- package/dist/types/boundaries.d.ts +3 -2
- package/dist/types/core/core.d.ts +3 -2
- package/dist/types/core/error.d.ts +6 -2
- package/dist/types/core/scheduler.d.ts +66 -16
- package/package.json +1 -1
package/dist/dev.js
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
class NotReadyError extends Error {
|
|
2
|
-
|
|
3
|
-
constructor(
|
|
2
|
+
_source;
|
|
3
|
+
constructor(_source) {
|
|
4
4
|
super();
|
|
5
|
-
this.
|
|
5
|
+
this._source = _source;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
class StatusError extends Error {
|
|
9
|
+
_source;
|
|
10
|
+
constructor(_source, original) {
|
|
11
|
+
super(original instanceof Error ? original.message : String(original), { cause: original });
|
|
12
|
+
this._source = _source;
|
|
6
13
|
}
|
|
7
14
|
}
|
|
8
15
|
class NoOwnerError extends Error {
|
|
@@ -26,7 +33,6 @@ const REACTIVE_IN_HEAP_HEIGHT = 1 << 4;
|
|
|
26
33
|
const REACTIVE_ZOMBIE = 1 << 5;
|
|
27
34
|
const REACTIVE_DISPOSED = 1 << 6;
|
|
28
35
|
const REACTIVE_OPTIMISTIC_DIRTY = 1 << 7;
|
|
29
|
-
const STATUS_NONE = 0;
|
|
30
36
|
const STATUS_PENDING = 1 << 0;
|
|
31
37
|
const STATUS_ERROR = 1 << 1;
|
|
32
38
|
const STATUS_UNINITIALIZED = 1 << 2;
|
|
@@ -140,10 +146,85 @@ const zombieQueue = { _heap: new Array(2e3).fill(undefined), _marked: false, _mi
|
|
|
140
146
|
let clock = 0;
|
|
141
147
|
let activeTransition = null;
|
|
142
148
|
let scheduled = false;
|
|
143
|
-
let optimisticReadActive = false;
|
|
144
149
|
let projectionWriteActive = false;
|
|
145
|
-
|
|
146
|
-
|
|
150
|
+
const signalLanes = new WeakMap();
|
|
151
|
+
const activeLanes = new Set();
|
|
152
|
+
let currentOptimisticLane = null;
|
|
153
|
+
function setCurrentOptimisticLane(lane) {
|
|
154
|
+
currentOptimisticLane = lane;
|
|
155
|
+
}
|
|
156
|
+
function getOrCreateLane(signal) {
|
|
157
|
+
let lane = signalLanes.get(signal);
|
|
158
|
+
if (lane) {
|
|
159
|
+
return findLane(lane);
|
|
160
|
+
}
|
|
161
|
+
lane = {
|
|
162
|
+
_source: signal,
|
|
163
|
+
_pendingAsync: new Set(),
|
|
164
|
+
_effectQueues: [[], []],
|
|
165
|
+
_mergedInto: null,
|
|
166
|
+
_transition: activeTransition
|
|
167
|
+
};
|
|
168
|
+
signalLanes.set(signal, lane);
|
|
169
|
+
activeLanes.add(lane);
|
|
170
|
+
signal._laneVersion = signal._overrideVersion || 0;
|
|
171
|
+
return lane;
|
|
172
|
+
}
|
|
173
|
+
function findLane(lane) {
|
|
174
|
+
while (lane._mergedInto) lane = lane._mergedInto;
|
|
175
|
+
return lane;
|
|
176
|
+
}
|
|
177
|
+
function mergeLanes(lane1, lane2) {
|
|
178
|
+
lane1 = findLane(lane1);
|
|
179
|
+
lane2 = findLane(lane2);
|
|
180
|
+
if (lane1 === lane2) return lane1;
|
|
181
|
+
lane2._mergedInto = lane1;
|
|
182
|
+
for (const node of lane2._pendingAsync) lane1._pendingAsync.add(node);
|
|
183
|
+
lane1._effectQueues[0].push(...lane2._effectQueues[0]);
|
|
184
|
+
lane1._effectQueues[1].push(...lane2._effectQueues[1]);
|
|
185
|
+
return lane1;
|
|
186
|
+
}
|
|
187
|
+
function clearLaneEntry(signal) {
|
|
188
|
+
signalLanes.delete(signal);
|
|
189
|
+
}
|
|
190
|
+
function resolveLane(el) {
|
|
191
|
+
const lane = el._optimisticLane;
|
|
192
|
+
if (!lane) return undefined;
|
|
193
|
+
const root = findLane(lane);
|
|
194
|
+
if (activeLanes.has(root)) return root;
|
|
195
|
+
el._optimisticLane = undefined;
|
|
196
|
+
return undefined;
|
|
197
|
+
}
|
|
198
|
+
function hasActiveOverride(el) {
|
|
199
|
+
return !!(el._optimistic && el._pendingValue !== NOT_PENDING);
|
|
200
|
+
}
|
|
201
|
+
function assignOrMergeLane(el, sourceLane) {
|
|
202
|
+
const sourceRoot = findLane(sourceLane);
|
|
203
|
+
const existing = el._optimisticLane;
|
|
204
|
+
if (existing) {
|
|
205
|
+
if (existing._mergedInto) {
|
|
206
|
+
el._optimisticLane = sourceLane;
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
const existingRoot = findLane(existing);
|
|
210
|
+
if (activeLanes.has(existingRoot)) {
|
|
211
|
+
if (existingRoot !== sourceRoot && !hasActiveOverride(el)) {
|
|
212
|
+
mergeLanes(sourceRoot, existingRoot);
|
|
213
|
+
}
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
el._optimisticLane = sourceLane;
|
|
218
|
+
}
|
|
219
|
+
function runLaneEffects(type) {
|
|
220
|
+
for (const lane of activeLanes) {
|
|
221
|
+
if (lane._mergedInto || lane._pendingAsync.size > 0) continue;
|
|
222
|
+
const effects = lane._effectQueues[type - 1];
|
|
223
|
+
if (effects.length) {
|
|
224
|
+
lane._effectQueues[type - 1] = [];
|
|
225
|
+
runQueue(effects, type);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
147
228
|
}
|
|
148
229
|
function setProjectionWriteActive(value) {
|
|
149
230
|
projectionWriteActive = value;
|
|
@@ -156,7 +237,6 @@ function schedule() {
|
|
|
156
237
|
class Queue {
|
|
157
238
|
_parent = null;
|
|
158
239
|
_queues = [[], []];
|
|
159
|
-
_optimisticQueues = [[], []];
|
|
160
240
|
_children = [];
|
|
161
241
|
created = clock;
|
|
162
242
|
addChild(child) {
|
|
@@ -170,30 +250,26 @@ class Queue {
|
|
|
170
250
|
child._parent = null;
|
|
171
251
|
}
|
|
172
252
|
}
|
|
173
|
-
notify(node, mask, flags) {
|
|
174
|
-
if (this._parent) return this._parent.notify(node, mask, flags);
|
|
253
|
+
notify(node, mask, flags, error) {
|
|
254
|
+
if (this._parent) return this._parent.notify(node, mask, flags, error);
|
|
175
255
|
return false;
|
|
176
256
|
}
|
|
177
|
-
|
|
178
|
-
if (
|
|
179
|
-
const effects =
|
|
180
|
-
|
|
257
|
+
run(type) {
|
|
258
|
+
if (this._queues[type - 1].length) {
|
|
259
|
+
const effects = this._queues[type - 1];
|
|
260
|
+
this._queues[type - 1] = [];
|
|
181
261
|
runQueue(effects, type);
|
|
182
262
|
}
|
|
183
|
-
for (let i = 0; i < this._children.length; i++)
|
|
184
|
-
this._children[i][method]?.(type);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
run(type) {
|
|
188
|
-
this._runQueue(type, this._queues, "run");
|
|
189
|
-
}
|
|
190
|
-
runOptimistic(type) {
|
|
191
|
-
this._runQueue(type, this._optimisticQueues, "runOptimistic");
|
|
263
|
+
for (let i = 0; i < this._children.length; i++) this._children[i].run?.(type);
|
|
192
264
|
}
|
|
193
265
|
enqueue(type, fn) {
|
|
194
266
|
if (type) {
|
|
195
|
-
|
|
196
|
-
|
|
267
|
+
if (currentOptimisticLane) {
|
|
268
|
+
const lane = findLane(currentOptimisticLane);
|
|
269
|
+
lane._effectQueues[type - 1].push(fn);
|
|
270
|
+
} else {
|
|
271
|
+
this._queues[type - 1].push(fn);
|
|
272
|
+
}
|
|
197
273
|
}
|
|
198
274
|
schedule();
|
|
199
275
|
}
|
|
@@ -242,23 +318,23 @@ class GlobalQueue extends Queue {
|
|
|
242
318
|
this._pendingNodes = [];
|
|
243
319
|
this._optimisticNodes = [];
|
|
244
320
|
this._optimisticStores = new Set();
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
this.stashQueues(activeTransition.
|
|
321
|
+
runLaneEffects(EFFECT_RENDER);
|
|
322
|
+
runLaneEffects(EFFECT_USER);
|
|
323
|
+
this.stashQueues(activeTransition._queueStash);
|
|
248
324
|
clock++;
|
|
249
|
-
scheduled =
|
|
250
|
-
|
|
325
|
+
scheduled = dirtyQueue._max >= dirtyQueue._min;
|
|
326
|
+
reassignPendingTransition(activeTransition._pendingNodes);
|
|
251
327
|
activeTransition = null;
|
|
252
328
|
finalizePureQueue(null, true);
|
|
253
329
|
return;
|
|
254
330
|
}
|
|
255
|
-
this._pendingNodes !== activeTransition.
|
|
256
|
-
this._pendingNodes.push(...activeTransition.
|
|
257
|
-
this.restoreQueues(activeTransition.
|
|
331
|
+
this._pendingNodes !== activeTransition._pendingNodes &&
|
|
332
|
+
this._pendingNodes.push(...activeTransition._pendingNodes);
|
|
333
|
+
this.restoreQueues(activeTransition._queueStash);
|
|
258
334
|
transitions.delete(activeTransition);
|
|
259
335
|
const completingTransition = activeTransition;
|
|
260
336
|
activeTransition = null;
|
|
261
|
-
|
|
337
|
+
reassignPendingTransition(this._pendingNodes);
|
|
262
338
|
finalizePureQueue(completingTransition);
|
|
263
339
|
} else {
|
|
264
340
|
if (transitions.size) runHeap(zombieQueue, GlobalQueue._update);
|
|
@@ -266,23 +342,24 @@ class GlobalQueue extends Queue {
|
|
|
266
342
|
}
|
|
267
343
|
clock++;
|
|
268
344
|
scheduled = dirtyQueue._max >= dirtyQueue._min;
|
|
269
|
-
|
|
345
|
+
runLaneEffects(EFFECT_RENDER);
|
|
270
346
|
this.run(EFFECT_RENDER);
|
|
271
|
-
|
|
347
|
+
runLaneEffects(EFFECT_USER);
|
|
272
348
|
this.run(EFFECT_USER);
|
|
273
349
|
} finally {
|
|
274
350
|
this._running = false;
|
|
275
351
|
}
|
|
276
352
|
}
|
|
277
|
-
notify(node, mask, flags) {
|
|
353
|
+
notify(node, mask, flags, error) {
|
|
278
354
|
if (mask & STATUS_PENDING) {
|
|
279
355
|
if (flags & STATUS_PENDING) {
|
|
356
|
+
const actualError = error !== undefined ? error : node._error;
|
|
280
357
|
if (
|
|
281
358
|
activeTransition &&
|
|
282
|
-
|
|
283
|
-
!activeTransition.
|
|
359
|
+
actualError &&
|
|
360
|
+
!activeTransition._asyncNodes.includes(actualError._source)
|
|
284
361
|
) {
|
|
285
|
-
activeTransition.
|
|
362
|
+
activeTransition._asyncNodes.push(actualError._source);
|
|
286
363
|
schedule();
|
|
287
364
|
}
|
|
288
365
|
}
|
|
@@ -293,47 +370,63 @@ class GlobalQueue extends Queue {
|
|
|
293
370
|
initTransition(transition) {
|
|
294
371
|
if (transition) transition = currentTransition(transition);
|
|
295
372
|
if (transition && transition === activeTransition) return;
|
|
296
|
-
if (!transition && activeTransition && activeTransition.
|
|
373
|
+
if (!transition && activeTransition && activeTransition._time === clock) return;
|
|
297
374
|
if (!activeTransition) {
|
|
298
375
|
activeTransition = transition ?? {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
376
|
+
_time: clock,
|
|
377
|
+
_pendingNodes: [],
|
|
378
|
+
_asyncNodes: [],
|
|
379
|
+
_optimisticNodes: [],
|
|
380
|
+
_optimisticStores: new Set(),
|
|
381
|
+
_actions: [],
|
|
382
|
+
_queueStash: { _queues: [[], []], _children: [] },
|
|
383
|
+
_done: false
|
|
307
384
|
};
|
|
308
385
|
} else if (transition) {
|
|
309
|
-
|
|
310
|
-
transition
|
|
311
|
-
|
|
386
|
+
const outgoing = activeTransition;
|
|
387
|
+
outgoing._done = transition;
|
|
388
|
+
transition._actions.push(...outgoing._actions);
|
|
389
|
+
for (const lane of activeLanes) {
|
|
390
|
+
if (lane._transition === outgoing) lane._transition = transition;
|
|
391
|
+
}
|
|
392
|
+
transition._optimisticNodes.push(...outgoing._optimisticNodes);
|
|
393
|
+
for (const store of outgoing._optimisticStores) {
|
|
394
|
+
transition._optimisticStores.add(store);
|
|
395
|
+
}
|
|
396
|
+
transitions.delete(outgoing);
|
|
312
397
|
activeTransition = transition;
|
|
313
398
|
}
|
|
314
399
|
transitions.add(activeTransition);
|
|
315
|
-
activeTransition.
|
|
400
|
+
activeTransition._time = clock;
|
|
316
401
|
for (let i = 0; i < this._pendingNodes.length; i++) {
|
|
317
402
|
const n = this._pendingNodes[i];
|
|
318
403
|
n._transition = activeTransition;
|
|
319
|
-
activeTransition.
|
|
404
|
+
activeTransition._pendingNodes.push(n);
|
|
320
405
|
}
|
|
321
|
-
this._pendingNodes = activeTransition.
|
|
406
|
+
this._pendingNodes = activeTransition._pendingNodes;
|
|
322
407
|
for (let i = 0; i < this._optimisticNodes.length; i++) {
|
|
323
408
|
const node = this._optimisticNodes[i];
|
|
324
409
|
node._transition = activeTransition;
|
|
325
|
-
activeTransition.
|
|
410
|
+
activeTransition._optimisticNodes.push(node);
|
|
326
411
|
}
|
|
327
|
-
this._optimisticNodes = activeTransition.
|
|
328
|
-
for (const
|
|
329
|
-
|
|
412
|
+
this._optimisticNodes = activeTransition._optimisticNodes;
|
|
413
|
+
for (const lane of activeLanes) {
|
|
414
|
+
if (!lane._transition) lane._transition = activeTransition;
|
|
330
415
|
}
|
|
331
|
-
this._optimisticStores
|
|
416
|
+
for (const store of this._optimisticStores) activeTransition._optimisticStores.add(store);
|
|
417
|
+
this._optimisticStores = activeTransition._optimisticStores;
|
|
332
418
|
}
|
|
333
419
|
}
|
|
334
420
|
function insertSubs(node, optimistic = false) {
|
|
421
|
+
const sourceLane = node._optimisticLane || currentOptimisticLane;
|
|
335
422
|
for (let s = node._subs; s !== null; s = s._nextSub) {
|
|
336
|
-
if (optimistic
|
|
423
|
+
if (optimistic && sourceLane) {
|
|
424
|
+
s._sub._flags |= REACTIVE_OPTIMISTIC_DIRTY;
|
|
425
|
+
assignOrMergeLane(s._sub, sourceLane);
|
|
426
|
+
} else if (optimistic) {
|
|
427
|
+
s._sub._flags |= REACTIVE_OPTIMISTIC_DIRTY;
|
|
428
|
+
s._sub._optimisticLane = undefined;
|
|
429
|
+
}
|
|
337
430
|
const sub = s._sub;
|
|
338
431
|
if (sub._type === EFFECT_TRACKED) {
|
|
339
432
|
if (!sub._modified) {
|
|
@@ -349,9 +442,8 @@ function insertSubs(node, optimistic = false) {
|
|
|
349
442
|
}
|
|
350
443
|
function finalizePureQueue(completingTransition = null, incomplete = false) {
|
|
351
444
|
let resolvePending = !incomplete;
|
|
352
|
-
if (
|
|
353
|
-
|
|
354
|
-
}
|
|
445
|
+
if (!incomplete) checkBoundaryChildren(globalQueue);
|
|
446
|
+
if (dirtyQueue._max >= dirtyQueue._min) runHeap(dirtyQueue, GlobalQueue._update);
|
|
355
447
|
if (resolvePending) {
|
|
356
448
|
const pendingNodes = globalQueue._pendingNodes;
|
|
357
449
|
for (let i = 0; i < pendingNodes.length; i++) {
|
|
@@ -361,15 +453,17 @@ function finalizePureQueue(completingTransition = null, incomplete = false) {
|
|
|
361
453
|
n._pendingValue = NOT_PENDING;
|
|
362
454
|
if (n._type && n._type !== EFFECT_TRACKED) n._modified = true;
|
|
363
455
|
}
|
|
456
|
+
n._statusFlags &= ~STATUS_UNINITIALIZED;
|
|
364
457
|
if (n._fn) GlobalQueue._dispose(n, false, true);
|
|
365
458
|
}
|
|
366
459
|
pendingNodes.length = 0;
|
|
367
460
|
const optimisticNodes = completingTransition
|
|
368
|
-
? completingTransition.
|
|
461
|
+
? completingTransition._optimisticNodes
|
|
369
462
|
: globalQueue._optimisticNodes;
|
|
370
463
|
for (let i = 0; i < optimisticNodes.length; i++) {
|
|
371
464
|
const n = optimisticNodes[i];
|
|
372
465
|
const original = n._pendingValue;
|
|
466
|
+
n._optimisticLane = undefined;
|
|
373
467
|
if (original !== NOT_PENDING && n._value !== original) {
|
|
374
468
|
n._value = original;
|
|
375
469
|
insertSubs(n, true);
|
|
@@ -379,7 +473,7 @@ function finalizePureQueue(completingTransition = null, incomplete = false) {
|
|
|
379
473
|
}
|
|
380
474
|
optimisticNodes.length = 0;
|
|
381
475
|
const optimisticStores = completingTransition
|
|
382
|
-
? completingTransition.
|
|
476
|
+
? completingTransition._optimisticStores
|
|
383
477
|
: globalQueue._optimisticStores;
|
|
384
478
|
if (GlobalQueue._clearOptimisticStore && optimisticStores.size) {
|
|
385
479
|
for (const store of optimisticStores) {
|
|
@@ -388,13 +482,35 @@ function finalizePureQueue(completingTransition = null, incomplete = false) {
|
|
|
388
482
|
optimisticStores.clear();
|
|
389
483
|
schedule();
|
|
390
484
|
}
|
|
485
|
+
for (const lane of activeLanes) {
|
|
486
|
+
const owned = completingTransition
|
|
487
|
+
? lane._transition === completingTransition
|
|
488
|
+
: !lane._transition;
|
|
489
|
+
if (!owned) continue;
|
|
490
|
+
if (!lane._mergedInto) {
|
|
491
|
+
if (lane._effectQueues[0].length) runQueue(lane._effectQueues[0], EFFECT_RENDER);
|
|
492
|
+
if (lane._effectQueues[1].length) runQueue(lane._effectQueues[1], EFFECT_USER);
|
|
493
|
+
}
|
|
494
|
+
if (lane._source._optimisticLane === lane) lane._source._optimisticLane = undefined;
|
|
495
|
+
lane._pendingAsync.clear();
|
|
496
|
+
lane._effectQueues[0].length = 0;
|
|
497
|
+
lane._effectQueues[1].length = 0;
|
|
498
|
+
activeLanes.delete(lane);
|
|
499
|
+
signalLanes.delete(lane._source);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
function checkBoundaryChildren(queue) {
|
|
504
|
+
for (const child of queue._children) {
|
|
505
|
+
child.checkSources?.();
|
|
506
|
+
checkBoundaryChildren(child);
|
|
391
507
|
}
|
|
392
508
|
}
|
|
393
509
|
function trackOptimisticStore(store) {
|
|
394
510
|
globalQueue._optimisticStores.add(store);
|
|
395
511
|
schedule();
|
|
396
512
|
}
|
|
397
|
-
function
|
|
513
|
+
function reassignPendingTransition(pendingNodes) {
|
|
398
514
|
for (let i = 0; i < pendingNodes.length; i++) {
|
|
399
515
|
pendingNodes[i]._transition = activeTransition;
|
|
400
516
|
}
|
|
@@ -411,20 +527,20 @@ function runQueue(queue, type) {
|
|
|
411
527
|
for (let i = 0; i < queue.length; i++) queue[i](type);
|
|
412
528
|
}
|
|
413
529
|
function transitionComplete(transition) {
|
|
414
|
-
if (transition.
|
|
415
|
-
if (transition.
|
|
530
|
+
if (transition._done) return true;
|
|
531
|
+
if (transition._actions.length) return false;
|
|
416
532
|
let done = true;
|
|
417
|
-
for (let i = 0; i < transition.
|
|
418
|
-
if (transition.
|
|
533
|
+
for (let i = 0; i < transition._asyncNodes.length; i++) {
|
|
534
|
+
if (transition._asyncNodes[i]._statusFlags & STATUS_PENDING) {
|
|
419
535
|
done = false;
|
|
420
536
|
break;
|
|
421
537
|
}
|
|
422
538
|
}
|
|
423
|
-
done && (transition.
|
|
539
|
+
done && (transition._done = true);
|
|
424
540
|
return done;
|
|
425
541
|
}
|
|
426
542
|
function currentTransition(transition) {
|
|
427
|
-
while (transition.
|
|
543
|
+
while (transition._done && typeof transition._done === "object") transition = transition._done;
|
|
428
544
|
return transition;
|
|
429
545
|
}
|
|
430
546
|
function runInTransition(transition, fn) {
|
|
@@ -448,11 +564,11 @@ function action(genFn) {
|
|
|
448
564
|
const it = genFn(...args);
|
|
449
565
|
globalQueue.initTransition();
|
|
450
566
|
let ctx = activeTransition;
|
|
451
|
-
ctx.
|
|
567
|
+
ctx._actions.push(it);
|
|
452
568
|
const done = (v, e) => {
|
|
453
569
|
ctx = currentTransition(ctx);
|
|
454
|
-
const i = ctx.
|
|
455
|
-
if (i >= 0) ctx.
|
|
570
|
+
const i = ctx._actions.indexOf(it);
|
|
571
|
+
if (i >= 0) ctx._actions.splice(i, 1);
|
|
456
572
|
activeTransition = ctx;
|
|
457
573
|
schedule();
|
|
458
574
|
e ? reject(e) : resolve(v);
|
|
@@ -499,7 +615,7 @@ function recompute(el, create = false) {
|
|
|
499
615
|
if (el._transition && (!isEffect || activeTransition) && activeTransition !== el._transition)
|
|
500
616
|
globalQueue.initTransition(el._transition);
|
|
501
617
|
deleteFromHeap(el, el._flags & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue);
|
|
502
|
-
if (el._transition) disposeChildren(el);
|
|
618
|
+
if (el._transition || isEffect === EFFECT_TRACKED) disposeChildren(el);
|
|
503
619
|
else {
|
|
504
620
|
markDisposal(el);
|
|
505
621
|
el._pendingDisposal = el._disposal;
|
|
@@ -509,7 +625,8 @@ function recompute(el, create = false) {
|
|
|
509
625
|
}
|
|
510
626
|
}
|
|
511
627
|
const isOptimisticDirty = !!(el._flags & REACTIVE_OPTIMISTIC_DIRTY);
|
|
512
|
-
const
|
|
628
|
+
const hasOverride = hasActiveOverride(el);
|
|
629
|
+
const wasPending = !!(el._statusFlags & STATUS_PENDING);
|
|
513
630
|
const oldcontext = context;
|
|
514
631
|
context = el;
|
|
515
632
|
el._depsTail = null;
|
|
@@ -518,17 +635,32 @@ function recompute(el, create = false) {
|
|
|
518
635
|
let value = el._pendingValue === NOT_PENDING ? el._value : el._pendingValue;
|
|
519
636
|
let oldHeight = el._height;
|
|
520
637
|
let prevTracking = tracking;
|
|
521
|
-
let
|
|
638
|
+
let prevLane = currentOptimisticLane;
|
|
522
639
|
tracking = true;
|
|
523
|
-
if (isOptimisticDirty)
|
|
640
|
+
if (isOptimisticDirty) {
|
|
641
|
+
const lane = resolveLane(el);
|
|
642
|
+
if (lane) setCurrentOptimisticLane(lane);
|
|
643
|
+
}
|
|
524
644
|
try {
|
|
525
645
|
value = handleAsync(el, el._fn(value));
|
|
526
646
|
clearStatus(el);
|
|
647
|
+
const resolvedLane = resolveLane(el);
|
|
648
|
+
if (resolvedLane) resolvedLane._pendingAsync.delete(el);
|
|
527
649
|
} catch (e) {
|
|
528
|
-
if (e instanceof NotReadyError) {
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
650
|
+
if (e instanceof NotReadyError && currentOptimisticLane) {
|
|
651
|
+
const lane = findLane(currentOptimisticLane);
|
|
652
|
+
if (lane._source !== el) {
|
|
653
|
+
lane._pendingAsync.add(el);
|
|
654
|
+
el._optimisticLane = lane;
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
notifyStatus(
|
|
658
|
+
el,
|
|
659
|
+
e instanceof NotReadyError ? STATUS_PENDING : STATUS_ERROR,
|
|
660
|
+
e,
|
|
661
|
+
undefined,
|
|
662
|
+
e instanceof NotReadyError ? el._optimisticLane : undefined
|
|
663
|
+
);
|
|
532
664
|
} finally {
|
|
533
665
|
tracking = prevTracking;
|
|
534
666
|
el._flags = REACTIVE_NONE;
|
|
@@ -544,21 +676,34 @@ function recompute(el, create = false) {
|
|
|
544
676
|
if (depsTail !== null) depsTail._nextDep = null;
|
|
545
677
|
else el._deps = null;
|
|
546
678
|
}
|
|
547
|
-
const
|
|
548
|
-
|
|
549
|
-
|
|
679
|
+
const compareValue = hasOverride
|
|
680
|
+
? el._value
|
|
681
|
+
: el._pendingValue === NOT_PENDING
|
|
682
|
+
? el._value
|
|
683
|
+
: el._pendingValue;
|
|
684
|
+
const valueChanged = !el._equals || !el._equals(compareValue, value);
|
|
550
685
|
if (valueChanged) {
|
|
686
|
+
const prevVisible = hasOverride ? el._value : undefined;
|
|
551
687
|
if (create || (isEffect && activeTransition !== el._transition) || isOptimisticDirty)
|
|
552
688
|
el._value = value;
|
|
553
689
|
else el._pendingValue = value;
|
|
554
|
-
|
|
690
|
+
if (hasOverride && !isOptimisticDirty && wasPending) {
|
|
691
|
+
const ov = el._overrideVersion || 0;
|
|
692
|
+
const lv = el._laneVersion || 0;
|
|
693
|
+
if (ov <= lv) el._value = value;
|
|
694
|
+
}
|
|
695
|
+
if (!hasOverride || isOptimisticDirty || el._value !== prevVisible) {
|
|
696
|
+
insertSubs(el, isOptimisticDirty || hasOverride);
|
|
697
|
+
}
|
|
698
|
+
} else if (hasOverride) {
|
|
699
|
+
el._pendingValue = value;
|
|
555
700
|
} else if (el._height != oldHeight) {
|
|
556
701
|
for (let s = el._subs; s !== null; s = s._nextSub) {
|
|
557
702
|
insertIntoHeapHeight(s._sub, s._sub._flags & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue);
|
|
558
703
|
}
|
|
559
704
|
}
|
|
560
705
|
}
|
|
561
|
-
|
|
706
|
+
setCurrentOptimisticLane(prevLane);
|
|
562
707
|
(!create || el._statusFlags & STATUS_PENDING) &&
|
|
563
708
|
!el._transition &&
|
|
564
709
|
!(activeTransition && el._optimistic) &&
|
|
@@ -581,27 +726,40 @@ function handleAsync(el, result, setter) {
|
|
|
581
726
|
const handleError = error => {
|
|
582
727
|
if (el._inFlight !== result) return;
|
|
583
728
|
globalQueue.initTransition(el._transition);
|
|
584
|
-
|
|
585
|
-
if (error.cause !== el) link(error.cause, el);
|
|
586
|
-
notifyStatus(el, STATUS_PENDING, error);
|
|
587
|
-
} else notifyStatus(el, STATUS_ERROR, error);
|
|
729
|
+
notifyStatus(el, error instanceof NotReadyError ? STATUS_PENDING : STATUS_ERROR, error);
|
|
588
730
|
el._time = clock;
|
|
589
731
|
};
|
|
590
732
|
const asyncWrite = (value, then) => {
|
|
591
733
|
if (el._inFlight !== result) return;
|
|
734
|
+
if (el._flags & (REACTIVE_DIRTY | REACTIVE_OPTIMISTIC_DIRTY)) return;
|
|
592
735
|
globalQueue.initTransition(el._transition);
|
|
593
736
|
clearStatus(el);
|
|
737
|
+
const lane = resolveLane(el);
|
|
738
|
+
if (lane) lane._pendingAsync.delete(el);
|
|
594
739
|
if (setter) setter(value);
|
|
595
740
|
else if (el._optimistic) {
|
|
596
|
-
const
|
|
741
|
+
const hadOverride = el._pendingValue !== NOT_PENDING;
|
|
597
742
|
if (el._fn) el._pendingValue = value;
|
|
598
|
-
if (!
|
|
743
|
+
if (!hadOverride) {
|
|
599
744
|
el._value = value;
|
|
600
745
|
insertSubs(el);
|
|
601
746
|
}
|
|
602
747
|
el._time = clock;
|
|
603
|
-
|
|
604
|
-
|
|
748
|
+
} else if (lane) {
|
|
749
|
+
const prevValue = el._value;
|
|
750
|
+
const equals = el._equals;
|
|
751
|
+
if (!equals || !equals(value, prevValue)) {
|
|
752
|
+
el._value = value;
|
|
753
|
+
el._time = clock;
|
|
754
|
+
if (el._pendingValueComputed) {
|
|
755
|
+
setSignal(el._pendingValueComputed, value);
|
|
756
|
+
}
|
|
757
|
+
insertSubs(el, true);
|
|
758
|
+
}
|
|
759
|
+
} else {
|
|
760
|
+
setSignal(el, () => value);
|
|
761
|
+
}
|
|
762
|
+
schedule();
|
|
605
763
|
flush();
|
|
606
764
|
then?.();
|
|
607
765
|
};
|
|
@@ -660,32 +818,51 @@ function handleAsync(el, result, setter) {
|
|
|
660
818
|
return syncValue;
|
|
661
819
|
}
|
|
662
820
|
function clearStatus(el) {
|
|
663
|
-
el._statusFlags =
|
|
821
|
+
el._statusFlags = el._statusFlags & STATUS_UNINITIALIZED;
|
|
664
822
|
el._error = null;
|
|
665
823
|
updatePendingSignal(el);
|
|
824
|
+
el._notifyStatus?.();
|
|
825
|
+
}
|
|
826
|
+
function notifyStatus(el, status, error, blockStatus, lane) {
|
|
827
|
+
if (
|
|
828
|
+
status === STATUS_ERROR &&
|
|
829
|
+
!(error instanceof StatusError) &&
|
|
830
|
+
!(error instanceof NotReadyError)
|
|
831
|
+
)
|
|
832
|
+
error = new StatusError(el, error);
|
|
833
|
+
const isSource = error instanceof NotReadyError && error._source === el;
|
|
834
|
+
const isOptimisticBoundary = status === STATUS_PENDING && el._optimistic && !isSource;
|
|
835
|
+
const startsBlocking = isOptimisticBoundary && hasActiveOverride(el);
|
|
836
|
+
if (!blockStatus) {
|
|
837
|
+
el._statusFlags =
|
|
838
|
+
status | (status !== STATUS_ERROR ? el._statusFlags & STATUS_UNINITIALIZED : 0);
|
|
839
|
+
el._error = error;
|
|
840
|
+
updatePendingSignal(el);
|
|
841
|
+
}
|
|
842
|
+
if (lane && !blockStatus) {
|
|
843
|
+
assignOrMergeLane(el, lane);
|
|
844
|
+
}
|
|
845
|
+
if (startsBlocking && activeTransition && error instanceof NotReadyError) {
|
|
846
|
+
const source = error._source;
|
|
847
|
+
if (!activeTransition._asyncNodes.includes(source)) {
|
|
848
|
+
activeTransition._asyncNodes.push(source);
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
const downstreamBlockStatus = blockStatus || startsBlocking;
|
|
852
|
+
const downstreamLane = blockStatus || isOptimisticBoundary ? undefined : lane;
|
|
666
853
|
if (el._notifyStatus) {
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
if (s._sub._statusFlags & STATUS_PENDING) {
|
|
672
|
-
insertIntoHeap(s._sub, s._sub._flags & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue);
|
|
673
|
-
}
|
|
674
|
-
}
|
|
854
|
+
if (downstreamBlockStatus) {
|
|
855
|
+
el._notifyStatus(status, error);
|
|
856
|
+
} else {
|
|
857
|
+
el._notifyStatus();
|
|
675
858
|
}
|
|
676
|
-
|
|
859
|
+
return;
|
|
677
860
|
}
|
|
678
|
-
}
|
|
679
|
-
function notifyStatus(el, status, error) {
|
|
680
|
-
el._statusFlags = status | (status !== STATUS_ERROR ? el._statusFlags & STATUS_UNINITIALIZED : 0);
|
|
681
|
-
el._error = error;
|
|
682
|
-
updatePendingSignal(el);
|
|
683
|
-
if (el._notifyStatus) return el._notifyStatus();
|
|
684
861
|
for (let s = el._subs; s !== null; s = s._nextSub) {
|
|
685
862
|
s._sub._time = clock;
|
|
686
863
|
if (s._sub._error !== error) {
|
|
687
864
|
!s._sub._transition && globalQueue._pendingNodes.push(s._sub);
|
|
688
|
-
notifyStatus(s._sub, status, error);
|
|
865
|
+
notifyStatus(s._sub, status, error, downstreamBlockStatus, downstreamLane);
|
|
689
866
|
}
|
|
690
867
|
}
|
|
691
868
|
for (let child = el._child; child !== null; child = child._nextChild) {
|
|
@@ -693,7 +870,7 @@ function notifyStatus(el, status, error) {
|
|
|
693
870
|
s._sub._time = clock;
|
|
694
871
|
if (s._sub._error !== error) {
|
|
695
872
|
!s._sub._transition && globalQueue._pendingNodes.push(s._sub);
|
|
696
|
-
notifyStatus(s._sub, status, error);
|
|
873
|
+
notifyStatus(s._sub, status, error, downstreamBlockStatus, downstreamLane);
|
|
697
874
|
}
|
|
698
875
|
}
|
|
699
876
|
}
|
|
@@ -711,7 +888,7 @@ function updateIfNecessary(el) {
|
|
|
711
888
|
}
|
|
712
889
|
}
|
|
713
890
|
}
|
|
714
|
-
if (el._flags & REACTIVE_DIRTY) {
|
|
891
|
+
if (el._flags & (REACTIVE_DIRTY | REACTIVE_OPTIMISTIC_DIRTY) || (el._error && el._time < clock)) {
|
|
715
892
|
recompute(el);
|
|
716
893
|
}
|
|
717
894
|
el._flags = REACTIVE_NONE;
|
|
@@ -934,8 +1111,8 @@ function getPendingSignal(el) {
|
|
|
934
1111
|
return el._pendingSignal;
|
|
935
1112
|
}
|
|
936
1113
|
function computePendingState(el) {
|
|
937
|
-
if (el._pendingValue !== NOT_PENDING) return true;
|
|
938
1114
|
const comp = el;
|
|
1115
|
+
if (el._pendingValue !== NOT_PENDING && !(comp._statusFlags & STATUS_UNINITIALIZED)) return true;
|
|
939
1116
|
return !!(comp._statusFlags & STATUS_PENDING && !(comp._statusFlags & STATUS_UNINITIALIZED));
|
|
940
1117
|
}
|
|
941
1118
|
function getPendingValueComputed(el) {
|
|
@@ -951,7 +1128,22 @@ function getPendingValueComputed(el) {
|
|
|
951
1128
|
return el._pendingValueComputed;
|
|
952
1129
|
}
|
|
953
1130
|
function updatePendingSignal(el) {
|
|
954
|
-
if (el._pendingSignal)
|
|
1131
|
+
if (el._pendingSignal) {
|
|
1132
|
+
const pending = computePendingState(el);
|
|
1133
|
+
const sig = el._pendingSignal;
|
|
1134
|
+
setSignal(sig, pending);
|
|
1135
|
+
if (!pending && sig._optimisticLane) {
|
|
1136
|
+
const sourceLane = resolveLane(el);
|
|
1137
|
+
if (sourceLane && sourceLane._pendingAsync.size > 0) {
|
|
1138
|
+
const sigLane = findLane(sig._optimisticLane);
|
|
1139
|
+
if (sigLane !== sourceLane) {
|
|
1140
|
+
mergeLanes(sourceLane, sigLane);
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
clearLaneEntry(sig);
|
|
1144
|
+
sig._optimisticLane = undefined;
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
955
1147
|
}
|
|
956
1148
|
function isEqual(a, b) {
|
|
957
1149
|
return a === b;
|
|
@@ -1009,11 +1201,21 @@ function read(el) {
|
|
|
1009
1201
|
const asyncCompute = el._firewall || el;
|
|
1010
1202
|
if (
|
|
1011
1203
|
c &&
|
|
1012
|
-
!optimisticReadActive &&
|
|
1013
1204
|
asyncCompute._statusFlags & STATUS_PENDING &&
|
|
1014
1205
|
!(stale && asyncCompute._transition && activeTransition !== asyncCompute._transition)
|
|
1015
|
-
)
|
|
1016
|
-
|
|
1206
|
+
) {
|
|
1207
|
+
if (currentOptimisticLane) {
|
|
1208
|
+
const pendingLane = asyncCompute._optimisticLane;
|
|
1209
|
+
const lane = findLane(currentOptimisticLane);
|
|
1210
|
+
if (pendingLane && findLane(pendingLane) === lane && !hasActiveOverride(asyncCompute)) {
|
|
1211
|
+
if (!tracking) link(el, c);
|
|
1212
|
+
throw asyncCompute._error;
|
|
1213
|
+
}
|
|
1214
|
+
} else {
|
|
1215
|
+
if (!tracking) link(el, c);
|
|
1216
|
+
throw asyncCompute._error;
|
|
1217
|
+
}
|
|
1218
|
+
}
|
|
1017
1219
|
if (el._fn && el._statusFlags & STATUS_ERROR) {
|
|
1018
1220
|
if (el._time < clock) {
|
|
1019
1221
|
recompute(el, true);
|
|
@@ -1021,7 +1223,7 @@ function read(el) {
|
|
|
1021
1223
|
} else throw el._error;
|
|
1022
1224
|
}
|
|
1023
1225
|
return !c ||
|
|
1024
|
-
|
|
1226
|
+
currentOptimisticLane !== null ||
|
|
1025
1227
|
el._pendingValue === NOT_PENDING ||
|
|
1026
1228
|
(stale && el._transition && activeTransition !== el._transition)
|
|
1027
1229
|
? el._value
|
|
@@ -1040,7 +1242,13 @@ function setSignal(el, v) {
|
|
|
1040
1242
|
: el._pendingValue;
|
|
1041
1243
|
if (typeof v === "function") v = v(currentValue);
|
|
1042
1244
|
const valueChanged = !el._equals || !el._equals(currentValue, v);
|
|
1043
|
-
if (!valueChanged)
|
|
1245
|
+
if (!valueChanged) {
|
|
1246
|
+
if (isOptimistic && el._pendingValue !== NOT_PENDING && el._fn) {
|
|
1247
|
+
insertSubs(el, true);
|
|
1248
|
+
schedule();
|
|
1249
|
+
}
|
|
1250
|
+
return v;
|
|
1251
|
+
}
|
|
1044
1252
|
if (isOptimistic) {
|
|
1045
1253
|
const alreadyTracked = globalQueue._optimisticNodes.includes(el);
|
|
1046
1254
|
if (el._transition && alreadyTracked) {
|
|
@@ -1052,6 +1260,9 @@ function setSignal(el, v) {
|
|
|
1052
1260
|
if (!alreadyTracked) {
|
|
1053
1261
|
globalQueue._optimisticNodes.push(el);
|
|
1054
1262
|
}
|
|
1263
|
+
el._overrideVersion = (el._overrideVersion || 0) + 1;
|
|
1264
|
+
const lane = getOrCreateLane(el);
|
|
1265
|
+
el._optimisticLane = lane;
|
|
1055
1266
|
el._value = v;
|
|
1056
1267
|
} else {
|
|
1057
1268
|
if (el._pendingValue === NOT_PENDING) globalQueue._pendingNodes.push(el);
|
|
@@ -1156,6 +1367,8 @@ function isPending(fn) {
|
|
|
1156
1367
|
try {
|
|
1157
1368
|
fn();
|
|
1158
1369
|
return foundPending;
|
|
1370
|
+
} catch {
|
|
1371
|
+
return foundPending;
|
|
1159
1372
|
} finally {
|
|
1160
1373
|
pendingCheckActive = prevPendingCheck;
|
|
1161
1374
|
foundPending = prevFoundPending;
|
|
@@ -1228,25 +1441,27 @@ function effect(compute, effect, error, initialValue, options) {
|
|
|
1228
1441
|
node._errorFn = error;
|
|
1229
1442
|
node._cleanup = undefined;
|
|
1230
1443
|
node._type = options?.render ? EFFECT_RENDER : EFFECT_USER;
|
|
1231
|
-
node._notifyStatus = () => {
|
|
1232
|
-
|
|
1233
|
-
|
|
1444
|
+
node._notifyStatus = (status, error) => {
|
|
1445
|
+
const actualStatus = status !== undefined ? status : node._statusFlags;
|
|
1446
|
+
const actualError = error !== undefined ? error : node._error;
|
|
1447
|
+
if (actualStatus & STATUS_ERROR) {
|
|
1448
|
+
let err = actualError;
|
|
1234
1449
|
node._queue.notify(node, STATUS_PENDING, 0);
|
|
1235
1450
|
if (node._type === EFFECT_USER) {
|
|
1236
1451
|
try {
|
|
1237
1452
|
return node._errorFn
|
|
1238
|
-
? node._errorFn(
|
|
1453
|
+
? node._errorFn(err, () => {
|
|
1239
1454
|
node._cleanup?.();
|
|
1240
1455
|
node._cleanup = undefined;
|
|
1241
1456
|
})
|
|
1242
|
-
: console.error(
|
|
1457
|
+
: console.error(err);
|
|
1243
1458
|
} catch (e) {
|
|
1244
|
-
|
|
1459
|
+
err = e;
|
|
1245
1460
|
}
|
|
1246
1461
|
}
|
|
1247
|
-
if (!node._queue.notify(node, STATUS_ERROR, STATUS_ERROR)) throw
|
|
1462
|
+
if (!node._queue.notify(node, STATUS_ERROR, STATUS_ERROR)) throw err;
|
|
1248
1463
|
} else if (node._type === EFFECT_RENDER)
|
|
1249
|
-
node._queue.notify(node, STATUS_PENDING | STATUS_ERROR,
|
|
1464
|
+
node._queue.notify(node, STATUS_PENDING | STATUS_ERROR, actualStatus, actualError);
|
|
1250
1465
|
};
|
|
1251
1466
|
recompute(node, true);
|
|
1252
1467
|
!options?.defer &&
|
|
@@ -1994,18 +2209,27 @@ function clearOptimisticStore(store) {
|
|
|
1994
2209
|
if (!target || !target[STORE_OPTIMISTIC_OVERRIDE]) return;
|
|
1995
2210
|
const override = target[STORE_OPTIMISTIC_OVERRIDE];
|
|
1996
2211
|
const nodes = target[STORE_NODE];
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2212
|
+
setProjectionWriteActive(true);
|
|
2213
|
+
try {
|
|
2214
|
+
if (nodes) {
|
|
2215
|
+
for (const key of Reflect.ownKeys(override)) {
|
|
2216
|
+
if (nodes[key]) {
|
|
2217
|
+
nodes[key]._optimisticLane = undefined;
|
|
2218
|
+
const baseValue =
|
|
2219
|
+
target[STORE_OVERRIDE] && key in target[STORE_OVERRIDE]
|
|
2220
|
+
? target[STORE_OVERRIDE][key]
|
|
2221
|
+
: target[STORE_VALUE][key];
|
|
2222
|
+
const value = baseValue === $DELETED ? undefined : baseValue;
|
|
2223
|
+
setSignal(nodes[key], isWrappable(value) ? wrap(value, target) : value);
|
|
2224
|
+
}
|
|
2225
|
+
}
|
|
2226
|
+
if (nodes[$TRACK]) {
|
|
2227
|
+
nodes[$TRACK]._optimisticLane = undefined;
|
|
2228
|
+
setSignal(nodes[$TRACK], undefined);
|
|
2006
2229
|
}
|
|
2007
2230
|
}
|
|
2008
|
-
|
|
2231
|
+
} finally {
|
|
2232
|
+
setProjectionWriteActive(false);
|
|
2009
2233
|
}
|
|
2010
2234
|
delete target[STORE_OPTIMISTIC_OVERRIDE];
|
|
2011
2235
|
}
|
|
@@ -2453,10 +2677,11 @@ function compare(key, a, b) {
|
|
|
2453
2677
|
}
|
|
2454
2678
|
function boundaryComputed(fn, propagationMask) {
|
|
2455
2679
|
const node = computed(fn, undefined, { lazy: true });
|
|
2456
|
-
node._notifyStatus = () => {
|
|
2457
|
-
const flags = node._statusFlags;
|
|
2680
|
+
node._notifyStatus = (status, error) => {
|
|
2681
|
+
const flags = status !== undefined ? status : node._statusFlags;
|
|
2682
|
+
const actualError = error !== undefined ? error : node._error;
|
|
2458
2683
|
node._statusFlags &= ~node._propagationMask;
|
|
2459
|
-
node._queue.notify(node, node._propagationMask, flags);
|
|
2684
|
+
node._queue.notify(node, node._propagationMask, flags, actualError);
|
|
2460
2685
|
};
|
|
2461
2686
|
node._propagationMask = propagationMask;
|
|
2462
2687
|
node._preventAutoDisposal = true;
|
|
@@ -2484,7 +2709,7 @@ class ConditionalQueue extends Queue {
|
|
|
2484
2709
|
if (!type || read(this._disabled)) return;
|
|
2485
2710
|
return super.run(type);
|
|
2486
2711
|
}
|
|
2487
|
-
notify(node, type, flags) {
|
|
2712
|
+
notify(node, type, flags, error) {
|
|
2488
2713
|
if (read(this._disabled)) {
|
|
2489
2714
|
if (type & STATUS_PENDING) {
|
|
2490
2715
|
if (flags & STATUS_PENDING) {
|
|
@@ -2499,12 +2724,12 @@ class ConditionalQueue extends Queue {
|
|
|
2499
2724
|
} else if (this._errorNodes.delete(node)) type &= ~STATUS_ERROR;
|
|
2500
2725
|
}
|
|
2501
2726
|
}
|
|
2502
|
-
return type ? super.notify(node, type, flags) : true;
|
|
2727
|
+
return type ? super.notify(node, type, flags, error ?? node._error) : true;
|
|
2503
2728
|
}
|
|
2504
2729
|
}
|
|
2505
2730
|
class CollectionQueue extends Queue {
|
|
2506
2731
|
_collectionType;
|
|
2507
|
-
|
|
2732
|
+
_sources = new Set();
|
|
2508
2733
|
_disabled = signal(false, { pureWrite: true });
|
|
2509
2734
|
_initialized = false;
|
|
2510
2735
|
constructor(type) {
|
|
@@ -2515,21 +2740,28 @@ class CollectionQueue extends Queue {
|
|
|
2515
2740
|
if (!type || read(this._disabled)) return;
|
|
2516
2741
|
return super.run(type);
|
|
2517
2742
|
}
|
|
2518
|
-
notify(node, type, flags) {
|
|
2743
|
+
notify(node, type, flags, error) {
|
|
2519
2744
|
if (
|
|
2520
2745
|
!(type & this._collectionType) ||
|
|
2521
2746
|
(this._collectionType & STATUS_PENDING && this._initialized)
|
|
2522
2747
|
)
|
|
2523
|
-
return super.notify(node, type, flags);
|
|
2748
|
+
return super.notify(node, type, flags, error);
|
|
2524
2749
|
if (flags & this._collectionType) {
|
|
2525
|
-
|
|
2526
|
-
if (
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2750
|
+
const source = error?._source || node._error?._source;
|
|
2751
|
+
if (source) {
|
|
2752
|
+
const wasEmpty = this._sources.size === 0;
|
|
2753
|
+
this._sources.add(source);
|
|
2754
|
+
if (wasEmpty) setSignal(this._disabled, true);
|
|
2755
|
+
}
|
|
2530
2756
|
}
|
|
2531
2757
|
type &= ~this._collectionType;
|
|
2532
|
-
return type ? super.notify(node, type, flags) : true;
|
|
2758
|
+
return type ? super.notify(node, type, flags, error) : true;
|
|
2759
|
+
}
|
|
2760
|
+
checkSources() {
|
|
2761
|
+
for (const source of this._sources) {
|
|
2762
|
+
if (!(source._statusFlags & this._collectionType)) this._sources.delete(source);
|
|
2763
|
+
}
|
|
2764
|
+
if (!this._sources.size) setSignal(this._disabled, false);
|
|
2533
2765
|
}
|
|
2534
2766
|
}
|
|
2535
2767
|
var BoundaryMode;
|
|
@@ -2545,8 +2777,12 @@ function createBoundary(fn, condition) {
|
|
|
2545
2777
|
const disabled = read(queue._disabled);
|
|
2546
2778
|
tree._propagationMask = disabled ? STATUS_ERROR | STATUS_PENDING : 0;
|
|
2547
2779
|
if (!disabled) {
|
|
2548
|
-
queue._pendingNodes.forEach(node =>
|
|
2549
|
-
|
|
2780
|
+
queue._pendingNodes.forEach(node =>
|
|
2781
|
+
queue.notify(node, STATUS_PENDING, STATUS_PENDING, node._error)
|
|
2782
|
+
);
|
|
2783
|
+
queue._errorNodes.forEach(node =>
|
|
2784
|
+
queue.notify(node, STATUS_ERROR, STATUS_ERROR, node._error)
|
|
2785
|
+
);
|
|
2550
2786
|
queue._pendingNodes.clear();
|
|
2551
2787
|
queue._errorNodes.clear();
|
|
2552
2788
|
}
|
|
@@ -2572,26 +2808,12 @@ function createCollectionBoundary(type, fn, fallback) {
|
|
|
2572
2808
|
function createLoadBoundary(fn, fallback) {
|
|
2573
2809
|
return createCollectionBoundary(STATUS_PENDING, fn, () => fallback());
|
|
2574
2810
|
}
|
|
2575
|
-
function collectErrorSources(node, sources) {
|
|
2576
|
-
let root = true;
|
|
2577
|
-
let dep = node._deps;
|
|
2578
|
-
while (dep !== null) {
|
|
2579
|
-
const source = dep._dep;
|
|
2580
|
-
if (source._deps && source._statusFlags & STATUS_ERROR) {
|
|
2581
|
-
root = false;
|
|
2582
|
-
collectErrorSources(source, sources);
|
|
2583
|
-
}
|
|
2584
|
-
dep = dep._nextDep;
|
|
2585
|
-
}
|
|
2586
|
-
root && sources.push(node);
|
|
2587
|
-
}
|
|
2588
2811
|
function createErrorBoundary(fn, fallback) {
|
|
2589
2812
|
return createCollectionBoundary(STATUS_ERROR, fn, queue => {
|
|
2590
|
-
let
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
for (const
|
|
2594
|
-
for (const source of sources) recompute(source);
|
|
2813
|
+
let source = queue._sources.values().next().value;
|
|
2814
|
+
const error = source._error?.cause ?? source._error;
|
|
2815
|
+
return fallback(error, () => {
|
|
2816
|
+
for (const source of queue._sources) recompute(source);
|
|
2595
2817
|
schedule();
|
|
2596
2818
|
});
|
|
2597
2819
|
});
|