@solidjs/signals 0.9.8 → 0.9.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dev.js +442 -184
- package/dist/node.cjs +1198 -959
- package/dist/prod.js +1000 -767
- package/dist/types/boundaries.d.ts +3 -2
- package/dist/types/core/core.d.ts +4 -2
- package/dist/types/core/error.d.ts +6 -2
- package/dist/types/core/scheduler.d.ts +67 -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,93 @@ 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
|
+
const parentSource = signal._parentSource;
|
|
162
|
+
const parentLane = parentSource?._optimisticLane ? findLane(parentSource._optimisticLane) : null;
|
|
163
|
+
lane = {
|
|
164
|
+
_source: signal,
|
|
165
|
+
_pendingAsync: new Set(),
|
|
166
|
+
_effectQueues: [[], []],
|
|
167
|
+
_mergedInto: null,
|
|
168
|
+
_transition: activeTransition,
|
|
169
|
+
_parentLane: parentLane
|
|
170
|
+
};
|
|
171
|
+
signalLanes.set(signal, lane);
|
|
172
|
+
activeLanes.add(lane);
|
|
173
|
+
signal._laneVersion = signal._overrideVersion || 0;
|
|
174
|
+
return lane;
|
|
175
|
+
}
|
|
176
|
+
function findLane(lane) {
|
|
177
|
+
while (lane._mergedInto) lane = lane._mergedInto;
|
|
178
|
+
return lane;
|
|
179
|
+
}
|
|
180
|
+
function mergeLanes(lane1, lane2) {
|
|
181
|
+
lane1 = findLane(lane1);
|
|
182
|
+
lane2 = findLane(lane2);
|
|
183
|
+
if (lane1 === lane2) return lane1;
|
|
184
|
+
lane2._mergedInto = lane1;
|
|
185
|
+
for (const node of lane2._pendingAsync) lane1._pendingAsync.add(node);
|
|
186
|
+
lane1._effectQueues[0].push(...lane2._effectQueues[0]);
|
|
187
|
+
lane1._effectQueues[1].push(...lane2._effectQueues[1]);
|
|
188
|
+
return lane1;
|
|
189
|
+
}
|
|
190
|
+
function clearLaneEntry(signal) {
|
|
191
|
+
signalLanes.delete(signal);
|
|
192
|
+
}
|
|
193
|
+
function resolveLane(el) {
|
|
194
|
+
const lane = el._optimisticLane;
|
|
195
|
+
if (!lane) return undefined;
|
|
196
|
+
const root = findLane(lane);
|
|
197
|
+
if (activeLanes.has(root)) return root;
|
|
198
|
+
el._optimisticLane = undefined;
|
|
199
|
+
return undefined;
|
|
200
|
+
}
|
|
201
|
+
function hasActiveOverride(el) {
|
|
202
|
+
return !!(el._optimistic && el._pendingValue !== NOT_PENDING);
|
|
203
|
+
}
|
|
204
|
+
function assignOrMergeLane(el, sourceLane) {
|
|
205
|
+
const sourceRoot = findLane(sourceLane);
|
|
206
|
+
const existing = el._optimisticLane;
|
|
207
|
+
if (existing) {
|
|
208
|
+
if (existing._mergedInto) {
|
|
209
|
+
el._optimisticLane = sourceLane;
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
const existingRoot = findLane(existing);
|
|
213
|
+
if (activeLanes.has(existingRoot)) {
|
|
214
|
+
if (existingRoot !== sourceRoot && !hasActiveOverride(el)) {
|
|
215
|
+
if (sourceRoot._parentLane && findLane(sourceRoot._parentLane) === existingRoot) {
|
|
216
|
+
el._optimisticLane = sourceLane;
|
|
217
|
+
} else if (existingRoot._parentLane && findLane(existingRoot._parentLane) === sourceRoot);
|
|
218
|
+
else {
|
|
219
|
+
mergeLanes(sourceRoot, existingRoot);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
el._optimisticLane = sourceLane;
|
|
226
|
+
}
|
|
227
|
+
function runLaneEffects(type) {
|
|
228
|
+
for (const lane of activeLanes) {
|
|
229
|
+
if (lane._mergedInto || lane._pendingAsync.size > 0) continue;
|
|
230
|
+
const effects = lane._effectQueues[type - 1];
|
|
231
|
+
if (effects.length) {
|
|
232
|
+
lane._effectQueues[type - 1] = [];
|
|
233
|
+
runQueue(effects, type);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
147
236
|
}
|
|
148
237
|
function setProjectionWriteActive(value) {
|
|
149
238
|
projectionWriteActive = value;
|
|
@@ -156,7 +245,6 @@ function schedule() {
|
|
|
156
245
|
class Queue {
|
|
157
246
|
_parent = null;
|
|
158
247
|
_queues = [[], []];
|
|
159
|
-
_optimisticQueues = [[], []];
|
|
160
248
|
_children = [];
|
|
161
249
|
created = clock;
|
|
162
250
|
addChild(child) {
|
|
@@ -170,30 +258,26 @@ class Queue {
|
|
|
170
258
|
child._parent = null;
|
|
171
259
|
}
|
|
172
260
|
}
|
|
173
|
-
notify(node, mask, flags) {
|
|
174
|
-
if (this._parent) return this._parent.notify(node, mask, flags);
|
|
261
|
+
notify(node, mask, flags, error) {
|
|
262
|
+
if (this._parent) return this._parent.notify(node, mask, flags, error);
|
|
175
263
|
return false;
|
|
176
264
|
}
|
|
177
|
-
|
|
178
|
-
if (
|
|
179
|
-
const effects =
|
|
180
|
-
|
|
265
|
+
run(type) {
|
|
266
|
+
if (this._queues[type - 1].length) {
|
|
267
|
+
const effects = this._queues[type - 1];
|
|
268
|
+
this._queues[type - 1] = [];
|
|
181
269
|
runQueue(effects, type);
|
|
182
270
|
}
|
|
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");
|
|
271
|
+
for (let i = 0; i < this._children.length; i++) this._children[i].run?.(type);
|
|
192
272
|
}
|
|
193
273
|
enqueue(type, fn) {
|
|
194
274
|
if (type) {
|
|
195
|
-
|
|
196
|
-
|
|
275
|
+
if (currentOptimisticLane) {
|
|
276
|
+
const lane = findLane(currentOptimisticLane);
|
|
277
|
+
lane._effectQueues[type - 1].push(fn);
|
|
278
|
+
} else {
|
|
279
|
+
this._queues[type - 1].push(fn);
|
|
280
|
+
}
|
|
197
281
|
}
|
|
198
282
|
schedule();
|
|
199
283
|
}
|
|
@@ -242,23 +326,23 @@ class GlobalQueue extends Queue {
|
|
|
242
326
|
this._pendingNodes = [];
|
|
243
327
|
this._optimisticNodes = [];
|
|
244
328
|
this._optimisticStores = new Set();
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
this.stashQueues(activeTransition.
|
|
329
|
+
runLaneEffects(EFFECT_RENDER);
|
|
330
|
+
runLaneEffects(EFFECT_USER);
|
|
331
|
+
this.stashQueues(activeTransition._queueStash);
|
|
248
332
|
clock++;
|
|
249
|
-
scheduled =
|
|
250
|
-
|
|
333
|
+
scheduled = dirtyQueue._max >= dirtyQueue._min;
|
|
334
|
+
reassignPendingTransition(activeTransition._pendingNodes);
|
|
251
335
|
activeTransition = null;
|
|
252
336
|
finalizePureQueue(null, true);
|
|
253
337
|
return;
|
|
254
338
|
}
|
|
255
|
-
this._pendingNodes !== activeTransition.
|
|
256
|
-
this._pendingNodes.push(...activeTransition.
|
|
257
|
-
this.restoreQueues(activeTransition.
|
|
339
|
+
this._pendingNodes !== activeTransition._pendingNodes &&
|
|
340
|
+
this._pendingNodes.push(...activeTransition._pendingNodes);
|
|
341
|
+
this.restoreQueues(activeTransition._queueStash);
|
|
258
342
|
transitions.delete(activeTransition);
|
|
259
343
|
const completingTransition = activeTransition;
|
|
260
344
|
activeTransition = null;
|
|
261
|
-
|
|
345
|
+
reassignPendingTransition(this._pendingNodes);
|
|
262
346
|
finalizePureQueue(completingTransition);
|
|
263
347
|
} else {
|
|
264
348
|
if (transitions.size) runHeap(zombieQueue, GlobalQueue._update);
|
|
@@ -266,23 +350,24 @@ class GlobalQueue extends Queue {
|
|
|
266
350
|
}
|
|
267
351
|
clock++;
|
|
268
352
|
scheduled = dirtyQueue._max >= dirtyQueue._min;
|
|
269
|
-
|
|
353
|
+
runLaneEffects(EFFECT_RENDER);
|
|
270
354
|
this.run(EFFECT_RENDER);
|
|
271
|
-
|
|
355
|
+
runLaneEffects(EFFECT_USER);
|
|
272
356
|
this.run(EFFECT_USER);
|
|
273
357
|
} finally {
|
|
274
358
|
this._running = false;
|
|
275
359
|
}
|
|
276
360
|
}
|
|
277
|
-
notify(node, mask, flags) {
|
|
361
|
+
notify(node, mask, flags, error) {
|
|
278
362
|
if (mask & STATUS_PENDING) {
|
|
279
363
|
if (flags & STATUS_PENDING) {
|
|
364
|
+
const actualError = error !== undefined ? error : node._error;
|
|
280
365
|
if (
|
|
281
366
|
activeTransition &&
|
|
282
|
-
|
|
283
|
-
!activeTransition.
|
|
367
|
+
actualError &&
|
|
368
|
+
!activeTransition._asyncNodes.includes(actualError._source)
|
|
284
369
|
) {
|
|
285
|
-
activeTransition.
|
|
370
|
+
activeTransition._asyncNodes.push(actualError._source);
|
|
286
371
|
schedule();
|
|
287
372
|
}
|
|
288
373
|
}
|
|
@@ -293,47 +378,63 @@ class GlobalQueue extends Queue {
|
|
|
293
378
|
initTransition(transition) {
|
|
294
379
|
if (transition) transition = currentTransition(transition);
|
|
295
380
|
if (transition && transition === activeTransition) return;
|
|
296
|
-
if (!transition && activeTransition && activeTransition.
|
|
381
|
+
if (!transition && activeTransition && activeTransition._time === clock) return;
|
|
297
382
|
if (!activeTransition) {
|
|
298
383
|
activeTransition = transition ?? {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
384
|
+
_time: clock,
|
|
385
|
+
_pendingNodes: [],
|
|
386
|
+
_asyncNodes: [],
|
|
387
|
+
_optimisticNodes: [],
|
|
388
|
+
_optimisticStores: new Set(),
|
|
389
|
+
_actions: [],
|
|
390
|
+
_queueStash: { _queues: [[], []], _children: [] },
|
|
391
|
+
_done: false
|
|
307
392
|
};
|
|
308
393
|
} else if (transition) {
|
|
309
|
-
|
|
310
|
-
transition
|
|
311
|
-
|
|
394
|
+
const outgoing = activeTransition;
|
|
395
|
+
outgoing._done = transition;
|
|
396
|
+
transition._actions.push(...outgoing._actions);
|
|
397
|
+
for (const lane of activeLanes) {
|
|
398
|
+
if (lane._transition === outgoing) lane._transition = transition;
|
|
399
|
+
}
|
|
400
|
+
transition._optimisticNodes.push(...outgoing._optimisticNodes);
|
|
401
|
+
for (const store of outgoing._optimisticStores) {
|
|
402
|
+
transition._optimisticStores.add(store);
|
|
403
|
+
}
|
|
404
|
+
transitions.delete(outgoing);
|
|
312
405
|
activeTransition = transition;
|
|
313
406
|
}
|
|
314
407
|
transitions.add(activeTransition);
|
|
315
|
-
activeTransition.
|
|
408
|
+
activeTransition._time = clock;
|
|
316
409
|
for (let i = 0; i < this._pendingNodes.length; i++) {
|
|
317
410
|
const n = this._pendingNodes[i];
|
|
318
411
|
n._transition = activeTransition;
|
|
319
|
-
activeTransition.
|
|
412
|
+
activeTransition._pendingNodes.push(n);
|
|
320
413
|
}
|
|
321
|
-
this._pendingNodes = activeTransition.
|
|
414
|
+
this._pendingNodes = activeTransition._pendingNodes;
|
|
322
415
|
for (let i = 0; i < this._optimisticNodes.length; i++) {
|
|
323
416
|
const node = this._optimisticNodes[i];
|
|
324
417
|
node._transition = activeTransition;
|
|
325
|
-
activeTransition.
|
|
418
|
+
activeTransition._optimisticNodes.push(node);
|
|
326
419
|
}
|
|
327
|
-
this._optimisticNodes = activeTransition.
|
|
328
|
-
for (const
|
|
329
|
-
|
|
420
|
+
this._optimisticNodes = activeTransition._optimisticNodes;
|
|
421
|
+
for (const lane of activeLanes) {
|
|
422
|
+
if (!lane._transition) lane._transition = activeTransition;
|
|
330
423
|
}
|
|
331
|
-
this._optimisticStores
|
|
424
|
+
for (const store of this._optimisticStores) activeTransition._optimisticStores.add(store);
|
|
425
|
+
this._optimisticStores = activeTransition._optimisticStores;
|
|
332
426
|
}
|
|
333
427
|
}
|
|
334
428
|
function insertSubs(node, optimistic = false) {
|
|
429
|
+
const sourceLane = node._optimisticLane || currentOptimisticLane;
|
|
335
430
|
for (let s = node._subs; s !== null; s = s._nextSub) {
|
|
336
|
-
if (optimistic
|
|
431
|
+
if (optimistic && sourceLane) {
|
|
432
|
+
s._sub._flags |= REACTIVE_OPTIMISTIC_DIRTY;
|
|
433
|
+
assignOrMergeLane(s._sub, sourceLane);
|
|
434
|
+
} else if (optimistic) {
|
|
435
|
+
s._sub._flags |= REACTIVE_OPTIMISTIC_DIRTY;
|
|
436
|
+
s._sub._optimisticLane = undefined;
|
|
437
|
+
}
|
|
337
438
|
const sub = s._sub;
|
|
338
439
|
if (sub._type === EFFECT_TRACKED) {
|
|
339
440
|
if (!sub._modified) {
|
|
@@ -349,9 +450,8 @@ function insertSubs(node, optimistic = false) {
|
|
|
349
450
|
}
|
|
350
451
|
function finalizePureQueue(completingTransition = null, incomplete = false) {
|
|
351
452
|
let resolvePending = !incomplete;
|
|
352
|
-
if (
|
|
353
|
-
|
|
354
|
-
}
|
|
453
|
+
if (!incomplete) checkBoundaryChildren(globalQueue);
|
|
454
|
+
if (dirtyQueue._max >= dirtyQueue._min) runHeap(dirtyQueue, GlobalQueue._update);
|
|
355
455
|
if (resolvePending) {
|
|
356
456
|
const pendingNodes = globalQueue._pendingNodes;
|
|
357
457
|
for (let i = 0; i < pendingNodes.length; i++) {
|
|
@@ -361,15 +461,17 @@ function finalizePureQueue(completingTransition = null, incomplete = false) {
|
|
|
361
461
|
n._pendingValue = NOT_PENDING;
|
|
362
462
|
if (n._type && n._type !== EFFECT_TRACKED) n._modified = true;
|
|
363
463
|
}
|
|
464
|
+
n._statusFlags &= ~STATUS_UNINITIALIZED;
|
|
364
465
|
if (n._fn) GlobalQueue._dispose(n, false, true);
|
|
365
466
|
}
|
|
366
467
|
pendingNodes.length = 0;
|
|
367
468
|
const optimisticNodes = completingTransition
|
|
368
|
-
? completingTransition.
|
|
469
|
+
? completingTransition._optimisticNodes
|
|
369
470
|
: globalQueue._optimisticNodes;
|
|
370
471
|
for (let i = 0; i < optimisticNodes.length; i++) {
|
|
371
472
|
const n = optimisticNodes[i];
|
|
372
473
|
const original = n._pendingValue;
|
|
474
|
+
n._optimisticLane = undefined;
|
|
373
475
|
if (original !== NOT_PENDING && n._value !== original) {
|
|
374
476
|
n._value = original;
|
|
375
477
|
insertSubs(n, true);
|
|
@@ -379,7 +481,7 @@ function finalizePureQueue(completingTransition = null, incomplete = false) {
|
|
|
379
481
|
}
|
|
380
482
|
optimisticNodes.length = 0;
|
|
381
483
|
const optimisticStores = completingTransition
|
|
382
|
-
? completingTransition.
|
|
484
|
+
? completingTransition._optimisticStores
|
|
383
485
|
: globalQueue._optimisticStores;
|
|
384
486
|
if (GlobalQueue._clearOptimisticStore && optimisticStores.size) {
|
|
385
487
|
for (const store of optimisticStores) {
|
|
@@ -388,13 +490,35 @@ function finalizePureQueue(completingTransition = null, incomplete = false) {
|
|
|
388
490
|
optimisticStores.clear();
|
|
389
491
|
schedule();
|
|
390
492
|
}
|
|
493
|
+
for (const lane of activeLanes) {
|
|
494
|
+
const owned = completingTransition
|
|
495
|
+
? lane._transition === completingTransition
|
|
496
|
+
: !lane._transition;
|
|
497
|
+
if (!owned) continue;
|
|
498
|
+
if (!lane._mergedInto) {
|
|
499
|
+
if (lane._effectQueues[0].length) runQueue(lane._effectQueues[0], EFFECT_RENDER);
|
|
500
|
+
if (lane._effectQueues[1].length) runQueue(lane._effectQueues[1], EFFECT_USER);
|
|
501
|
+
}
|
|
502
|
+
if (lane._source._optimisticLane === lane) lane._source._optimisticLane = undefined;
|
|
503
|
+
lane._pendingAsync.clear();
|
|
504
|
+
lane._effectQueues[0].length = 0;
|
|
505
|
+
lane._effectQueues[1].length = 0;
|
|
506
|
+
activeLanes.delete(lane);
|
|
507
|
+
signalLanes.delete(lane._source);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
function checkBoundaryChildren(queue) {
|
|
512
|
+
for (const child of queue._children) {
|
|
513
|
+
child.checkSources?.();
|
|
514
|
+
checkBoundaryChildren(child);
|
|
391
515
|
}
|
|
392
516
|
}
|
|
393
517
|
function trackOptimisticStore(store) {
|
|
394
518
|
globalQueue._optimisticStores.add(store);
|
|
395
519
|
schedule();
|
|
396
520
|
}
|
|
397
|
-
function
|
|
521
|
+
function reassignPendingTransition(pendingNodes) {
|
|
398
522
|
for (let i = 0; i < pendingNodes.length; i++) {
|
|
399
523
|
pendingNodes[i]._transition = activeTransition;
|
|
400
524
|
}
|
|
@@ -411,20 +535,21 @@ function runQueue(queue, type) {
|
|
|
411
535
|
for (let i = 0; i < queue.length; i++) queue[i](type);
|
|
412
536
|
}
|
|
413
537
|
function transitionComplete(transition) {
|
|
414
|
-
if (transition.
|
|
415
|
-
if (transition.
|
|
538
|
+
if (transition._done) return true;
|
|
539
|
+
if (transition._actions.length) return false;
|
|
416
540
|
let done = true;
|
|
417
|
-
for (let i = 0; i < transition.
|
|
418
|
-
|
|
541
|
+
for (let i = 0; i < transition._asyncNodes.length; i++) {
|
|
542
|
+
const node = transition._asyncNodes[i];
|
|
543
|
+
if (node._statusFlags & STATUS_PENDING && node._error?._source === node) {
|
|
419
544
|
done = false;
|
|
420
545
|
break;
|
|
421
546
|
}
|
|
422
547
|
}
|
|
423
|
-
done && (transition.
|
|
548
|
+
done && (transition._done = true);
|
|
424
549
|
return done;
|
|
425
550
|
}
|
|
426
551
|
function currentTransition(transition) {
|
|
427
|
-
while (transition.
|
|
552
|
+
while (transition._done && typeof transition._done === "object") transition = transition._done;
|
|
428
553
|
return transition;
|
|
429
554
|
}
|
|
430
555
|
function runInTransition(transition, fn) {
|
|
@@ -448,11 +573,11 @@ function action(genFn) {
|
|
|
448
573
|
const it = genFn(...args);
|
|
449
574
|
globalQueue.initTransition();
|
|
450
575
|
let ctx = activeTransition;
|
|
451
|
-
ctx.
|
|
576
|
+
ctx._actions.push(it);
|
|
452
577
|
const done = (v, e) => {
|
|
453
578
|
ctx = currentTransition(ctx);
|
|
454
|
-
const i = ctx.
|
|
455
|
-
if (i >= 0) ctx.
|
|
579
|
+
const i = ctx._actions.indexOf(it);
|
|
580
|
+
if (i >= 0) ctx._actions.splice(i, 1);
|
|
456
581
|
activeTransition = ctx;
|
|
457
582
|
schedule();
|
|
458
583
|
e ? reject(e) : resolve(v);
|
|
@@ -499,7 +624,7 @@ function recompute(el, create = false) {
|
|
|
499
624
|
if (el._transition && (!isEffect || activeTransition) && activeTransition !== el._transition)
|
|
500
625
|
globalQueue.initTransition(el._transition);
|
|
501
626
|
deleteFromHeap(el, el._flags & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue);
|
|
502
|
-
if (el._transition) disposeChildren(el);
|
|
627
|
+
if (el._transition || isEffect === EFFECT_TRACKED) disposeChildren(el);
|
|
503
628
|
else {
|
|
504
629
|
markDisposal(el);
|
|
505
630
|
el._pendingDisposal = el._disposal;
|
|
@@ -509,7 +634,8 @@ function recompute(el, create = false) {
|
|
|
509
634
|
}
|
|
510
635
|
}
|
|
511
636
|
const isOptimisticDirty = !!(el._flags & REACTIVE_OPTIMISTIC_DIRTY);
|
|
512
|
-
const
|
|
637
|
+
const hasOverride = hasActiveOverride(el);
|
|
638
|
+
const wasPending = !!(el._statusFlags & STATUS_PENDING);
|
|
513
639
|
const oldcontext = context;
|
|
514
640
|
context = el;
|
|
515
641
|
el._depsTail = null;
|
|
@@ -518,17 +644,36 @@ function recompute(el, create = false) {
|
|
|
518
644
|
let value = el._pendingValue === NOT_PENDING ? el._value : el._pendingValue;
|
|
519
645
|
let oldHeight = el._height;
|
|
520
646
|
let prevTracking = tracking;
|
|
521
|
-
let
|
|
647
|
+
let prevLane = currentOptimisticLane;
|
|
522
648
|
tracking = true;
|
|
523
|
-
if (isOptimisticDirty)
|
|
649
|
+
if (isOptimisticDirty) {
|
|
650
|
+
const lane = resolveLane(el);
|
|
651
|
+
if (lane) setCurrentOptimisticLane(lane);
|
|
652
|
+
}
|
|
524
653
|
try {
|
|
525
654
|
value = handleAsync(el, el._fn(value));
|
|
526
655
|
clearStatus(el);
|
|
656
|
+
const resolvedLane = resolveLane(el);
|
|
657
|
+
if (resolvedLane) {
|
|
658
|
+
resolvedLane._pendingAsync.delete(el);
|
|
659
|
+
updatePendingSignal(resolvedLane._source);
|
|
660
|
+
}
|
|
527
661
|
} catch (e) {
|
|
528
|
-
if (e instanceof NotReadyError) {
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
662
|
+
if (e instanceof NotReadyError && currentOptimisticLane) {
|
|
663
|
+
const lane = findLane(currentOptimisticLane);
|
|
664
|
+
if (lane._source !== el) {
|
|
665
|
+
lane._pendingAsync.add(el);
|
|
666
|
+
el._optimisticLane = lane;
|
|
667
|
+
updatePendingSignal(lane._source);
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
notifyStatus(
|
|
671
|
+
el,
|
|
672
|
+
e instanceof NotReadyError ? STATUS_PENDING : STATUS_ERROR,
|
|
673
|
+
e,
|
|
674
|
+
undefined,
|
|
675
|
+
e instanceof NotReadyError ? el._optimisticLane : undefined
|
|
676
|
+
);
|
|
532
677
|
} finally {
|
|
533
678
|
tracking = prevTracking;
|
|
534
679
|
el._flags = REACTIVE_NONE;
|
|
@@ -544,21 +689,34 @@ function recompute(el, create = false) {
|
|
|
544
689
|
if (depsTail !== null) depsTail._nextDep = null;
|
|
545
690
|
else el._deps = null;
|
|
546
691
|
}
|
|
547
|
-
const
|
|
548
|
-
|
|
549
|
-
|
|
692
|
+
const compareValue = hasOverride
|
|
693
|
+
? el._value
|
|
694
|
+
: el._pendingValue === NOT_PENDING
|
|
695
|
+
? el._value
|
|
696
|
+
: el._pendingValue;
|
|
697
|
+
const valueChanged = !el._equals || !el._equals(compareValue, value);
|
|
550
698
|
if (valueChanged) {
|
|
699
|
+
const prevVisible = hasOverride ? el._value : undefined;
|
|
551
700
|
if (create || (isEffect && activeTransition !== el._transition) || isOptimisticDirty)
|
|
552
701
|
el._value = value;
|
|
553
702
|
else el._pendingValue = value;
|
|
554
|
-
|
|
703
|
+
if (hasOverride && !isOptimisticDirty && wasPending) {
|
|
704
|
+
const ov = el._overrideVersion || 0;
|
|
705
|
+
const lv = el._laneVersion || 0;
|
|
706
|
+
if (ov <= lv) el._value = value;
|
|
707
|
+
}
|
|
708
|
+
if (!hasOverride || isOptimisticDirty || el._value !== prevVisible) {
|
|
709
|
+
insertSubs(el, isOptimisticDirty || hasOverride);
|
|
710
|
+
}
|
|
711
|
+
} else if (hasOverride) {
|
|
712
|
+
el._pendingValue = value;
|
|
555
713
|
} else if (el._height != oldHeight) {
|
|
556
714
|
for (let s = el._subs; s !== null; s = s._nextSub) {
|
|
557
715
|
insertIntoHeapHeight(s._sub, s._sub._flags & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue);
|
|
558
716
|
}
|
|
559
717
|
}
|
|
560
718
|
}
|
|
561
|
-
|
|
719
|
+
setCurrentOptimisticLane(prevLane);
|
|
562
720
|
(!create || el._statusFlags & STATUS_PENDING) &&
|
|
563
721
|
!el._transition &&
|
|
564
722
|
!(activeTransition && el._optimistic) &&
|
|
@@ -581,27 +739,40 @@ function handleAsync(el, result, setter) {
|
|
|
581
739
|
const handleError = error => {
|
|
582
740
|
if (el._inFlight !== result) return;
|
|
583
741
|
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);
|
|
742
|
+
notifyStatus(el, error instanceof NotReadyError ? STATUS_PENDING : STATUS_ERROR, error);
|
|
588
743
|
el._time = clock;
|
|
589
744
|
};
|
|
590
745
|
const asyncWrite = (value, then) => {
|
|
591
746
|
if (el._inFlight !== result) return;
|
|
747
|
+
if (el._flags & (REACTIVE_DIRTY | REACTIVE_OPTIMISTIC_DIRTY)) return;
|
|
592
748
|
globalQueue.initTransition(el._transition);
|
|
593
749
|
clearStatus(el);
|
|
750
|
+
const lane = resolveLane(el);
|
|
751
|
+
if (lane) lane._pendingAsync.delete(el);
|
|
594
752
|
if (setter) setter(value);
|
|
595
753
|
else if (el._optimistic) {
|
|
596
|
-
const
|
|
754
|
+
const hadOverride = el._pendingValue !== NOT_PENDING;
|
|
597
755
|
if (el._fn) el._pendingValue = value;
|
|
598
|
-
if (!
|
|
756
|
+
if (!hadOverride) {
|
|
599
757
|
el._value = value;
|
|
600
758
|
insertSubs(el);
|
|
601
759
|
}
|
|
602
760
|
el._time = clock;
|
|
603
|
-
|
|
604
|
-
|
|
761
|
+
} else if (lane) {
|
|
762
|
+
const prevValue = el._value;
|
|
763
|
+
const equals = el._equals;
|
|
764
|
+
if (!equals || !equals(value, prevValue)) {
|
|
765
|
+
el._value = value;
|
|
766
|
+
el._time = clock;
|
|
767
|
+
if (el._pendingValueComputed) {
|
|
768
|
+
setSignal(el._pendingValueComputed, value);
|
|
769
|
+
}
|
|
770
|
+
insertSubs(el, true);
|
|
771
|
+
}
|
|
772
|
+
} else {
|
|
773
|
+
setSignal(el, () => value);
|
|
774
|
+
}
|
|
775
|
+
schedule();
|
|
605
776
|
flush();
|
|
606
777
|
then?.();
|
|
607
778
|
};
|
|
@@ -660,32 +831,51 @@ function handleAsync(el, result, setter) {
|
|
|
660
831
|
return syncValue;
|
|
661
832
|
}
|
|
662
833
|
function clearStatus(el) {
|
|
663
|
-
el._statusFlags =
|
|
834
|
+
el._statusFlags = el._statusFlags & STATUS_UNINITIALIZED;
|
|
664
835
|
el._error = null;
|
|
665
836
|
updatePendingSignal(el);
|
|
837
|
+
el._notifyStatus?.();
|
|
838
|
+
}
|
|
839
|
+
function notifyStatus(el, status, error, blockStatus, lane) {
|
|
840
|
+
if (
|
|
841
|
+
status === STATUS_ERROR &&
|
|
842
|
+
!(error instanceof StatusError) &&
|
|
843
|
+
!(error instanceof NotReadyError)
|
|
844
|
+
)
|
|
845
|
+
error = new StatusError(el, error);
|
|
846
|
+
const isSource = error instanceof NotReadyError && error._source === el;
|
|
847
|
+
const isOptimisticBoundary = status === STATUS_PENDING && el._optimistic && !isSource;
|
|
848
|
+
const startsBlocking = isOptimisticBoundary && hasActiveOverride(el);
|
|
849
|
+
if (!blockStatus) {
|
|
850
|
+
el._statusFlags =
|
|
851
|
+
status | (status !== STATUS_ERROR ? el._statusFlags & STATUS_UNINITIALIZED : 0);
|
|
852
|
+
el._error = error;
|
|
853
|
+
updatePendingSignal(el);
|
|
854
|
+
}
|
|
855
|
+
if (lane && !blockStatus) {
|
|
856
|
+
assignOrMergeLane(el, lane);
|
|
857
|
+
}
|
|
858
|
+
if (startsBlocking && activeTransition && error instanceof NotReadyError) {
|
|
859
|
+
const source = error._source;
|
|
860
|
+
if (!activeTransition._asyncNodes.includes(source)) {
|
|
861
|
+
activeTransition._asyncNodes.push(source);
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
const downstreamBlockStatus = blockStatus || startsBlocking;
|
|
865
|
+
const downstreamLane = blockStatus || isOptimisticBoundary ? undefined : lane;
|
|
666
866
|
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
|
-
}
|
|
867
|
+
if (downstreamBlockStatus) {
|
|
868
|
+
el._notifyStatus(status, error);
|
|
869
|
+
} else {
|
|
870
|
+
el._notifyStatus();
|
|
675
871
|
}
|
|
676
|
-
|
|
872
|
+
return;
|
|
677
873
|
}
|
|
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
874
|
for (let s = el._subs; s !== null; s = s._nextSub) {
|
|
685
875
|
s._sub._time = clock;
|
|
686
876
|
if (s._sub._error !== error) {
|
|
687
877
|
!s._sub._transition && globalQueue._pendingNodes.push(s._sub);
|
|
688
|
-
notifyStatus(s._sub, status, error);
|
|
878
|
+
notifyStatus(s._sub, status, error, downstreamBlockStatus, downstreamLane);
|
|
689
879
|
}
|
|
690
880
|
}
|
|
691
881
|
for (let child = el._child; child !== null; child = child._nextChild) {
|
|
@@ -693,7 +883,7 @@ function notifyStatus(el, status, error) {
|
|
|
693
883
|
s._sub._time = clock;
|
|
694
884
|
if (s._sub._error !== error) {
|
|
695
885
|
!s._sub._transition && globalQueue._pendingNodes.push(s._sub);
|
|
696
|
-
notifyStatus(s._sub, status, error);
|
|
886
|
+
notifyStatus(s._sub, status, error, downstreamBlockStatus, downstreamLane);
|
|
697
887
|
}
|
|
698
888
|
}
|
|
699
889
|
}
|
|
@@ -711,7 +901,7 @@ function updateIfNecessary(el) {
|
|
|
711
901
|
}
|
|
712
902
|
}
|
|
713
903
|
}
|
|
714
|
-
if (el._flags & REACTIVE_DIRTY) {
|
|
904
|
+
if (el._flags & (REACTIVE_DIRTY | REACTIVE_OPTIMISTIC_DIRTY) || (el._error && el._time < clock)) {
|
|
715
905
|
recompute(el);
|
|
716
906
|
}
|
|
717
907
|
el._flags = REACTIVE_NONE;
|
|
@@ -929,29 +1119,60 @@ function optimisticComputed(fn, initialValue, options) {
|
|
|
929
1119
|
function getPendingSignal(el) {
|
|
930
1120
|
if (!el._pendingSignal) {
|
|
931
1121
|
el._pendingSignal = optimisticSignal(false, { pureWrite: true });
|
|
1122
|
+
if (el._parentSource) {
|
|
1123
|
+
el._pendingSignal._parentSource = el;
|
|
1124
|
+
}
|
|
932
1125
|
if (computePendingState(el)) setSignal(el._pendingSignal, true);
|
|
933
1126
|
}
|
|
934
1127
|
return el._pendingSignal;
|
|
935
1128
|
}
|
|
936
1129
|
function computePendingState(el) {
|
|
937
|
-
if (el._pendingValue !== NOT_PENDING) return true;
|
|
938
1130
|
const comp = el;
|
|
1131
|
+
if (el._optimistic && el._pendingValue !== NOT_PENDING) {
|
|
1132
|
+
if (comp._statusFlags & STATUS_PENDING && !(comp._statusFlags & STATUS_UNINITIALIZED))
|
|
1133
|
+
return true;
|
|
1134
|
+
if (el._parentSource) {
|
|
1135
|
+
const lane = el._optimisticLane ? findLane(el._optimisticLane) : null;
|
|
1136
|
+
return !!(lane && lane._pendingAsync.size > 0);
|
|
1137
|
+
}
|
|
1138
|
+
return true;
|
|
1139
|
+
}
|
|
1140
|
+
if (el._pendingValue !== NOT_PENDING && !(comp._statusFlags & STATUS_UNINITIALIZED)) return true;
|
|
939
1141
|
return !!(comp._statusFlags & STATUS_PENDING && !(comp._statusFlags & STATUS_UNINITIALIZED));
|
|
940
1142
|
}
|
|
941
1143
|
function getPendingValueComputed(el) {
|
|
942
1144
|
if (!el._pendingValueComputed) {
|
|
943
1145
|
const prevPending = pendingReadActive;
|
|
944
1146
|
pendingReadActive = false;
|
|
1147
|
+
const prevCheck = pendingCheckActive;
|
|
1148
|
+
pendingCheckActive = false;
|
|
945
1149
|
const prevContext = context;
|
|
946
1150
|
context = null;
|
|
947
1151
|
el._pendingValueComputed = optimisticComputed(() => read(el));
|
|
1152
|
+
el._pendingValueComputed._parentSource = el;
|
|
948
1153
|
context = prevContext;
|
|
1154
|
+
pendingCheckActive = prevCheck;
|
|
949
1155
|
pendingReadActive = prevPending;
|
|
950
1156
|
}
|
|
951
1157
|
return el._pendingValueComputed;
|
|
952
1158
|
}
|
|
953
1159
|
function updatePendingSignal(el) {
|
|
954
|
-
if (el._pendingSignal)
|
|
1160
|
+
if (el._pendingSignal) {
|
|
1161
|
+
const pending = computePendingState(el);
|
|
1162
|
+
const sig = el._pendingSignal;
|
|
1163
|
+
setSignal(sig, pending);
|
|
1164
|
+
if (!pending && sig._optimisticLane) {
|
|
1165
|
+
const sourceLane = resolveLane(el);
|
|
1166
|
+
if (sourceLane && sourceLane._pendingAsync.size > 0) {
|
|
1167
|
+
const sigLane = findLane(sig._optimisticLane);
|
|
1168
|
+
if (sigLane !== sourceLane) {
|
|
1169
|
+
mergeLanes(sourceLane, sigLane);
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
clearLaneEntry(sig);
|
|
1173
|
+
sig._optimisticLane = undefined;
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
955
1176
|
}
|
|
956
1177
|
function isEqual(a, b) {
|
|
957
1178
|
return a === b;
|
|
@@ -966,6 +1187,22 @@ function untrack(fn) {
|
|
|
966
1187
|
}
|
|
967
1188
|
}
|
|
968
1189
|
function read(el) {
|
|
1190
|
+
if (pendingReadActive) {
|
|
1191
|
+
const pendingComputed = getPendingValueComputed(el);
|
|
1192
|
+
const prevPending = pendingReadActive;
|
|
1193
|
+
pendingReadActive = false;
|
|
1194
|
+
const value = read(pendingComputed);
|
|
1195
|
+
pendingReadActive = prevPending;
|
|
1196
|
+
if (pendingComputed._statusFlags & STATUS_PENDING) return el._value;
|
|
1197
|
+
if (stale && currentOptimisticLane && pendingComputed._optimisticLane) {
|
|
1198
|
+
const pcLane = findLane(pendingComputed._optimisticLane);
|
|
1199
|
+
const curLane = findLane(currentOptimisticLane);
|
|
1200
|
+
if (pcLane !== curLane && pcLane._pendingAsync.size > 0) {
|
|
1201
|
+
return el._value;
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
return value;
|
|
1205
|
+
}
|
|
969
1206
|
if (pendingCheckActive) {
|
|
970
1207
|
const target = el._firewall || el;
|
|
971
1208
|
const pendingSig = getPendingSignal(target);
|
|
@@ -977,15 +1214,6 @@ function read(el) {
|
|
|
977
1214
|
pendingCheckActive = prevCheck;
|
|
978
1215
|
return el._value;
|
|
979
1216
|
}
|
|
980
|
-
if (pendingReadActive) {
|
|
981
|
-
const pendingComputed = getPendingValueComputed(el);
|
|
982
|
-
const prevPending = pendingReadActive;
|
|
983
|
-
pendingReadActive = false;
|
|
984
|
-
const value = read(pendingComputed);
|
|
985
|
-
pendingReadActive = prevPending;
|
|
986
|
-
if (pendingComputed._statusFlags & STATUS_PENDING) return el._value;
|
|
987
|
-
return value;
|
|
988
|
-
}
|
|
989
1217
|
let c = context;
|
|
990
1218
|
if (c?._root) c = c._parentComputed;
|
|
991
1219
|
if (refreshing && el._fn) recompute(el);
|
|
@@ -1009,11 +1237,21 @@ function read(el) {
|
|
|
1009
1237
|
const asyncCompute = el._firewall || el;
|
|
1010
1238
|
if (
|
|
1011
1239
|
c &&
|
|
1012
|
-
!optimisticReadActive &&
|
|
1013
1240
|
asyncCompute._statusFlags & STATUS_PENDING &&
|
|
1014
1241
|
!(stale && asyncCompute._transition && activeTransition !== asyncCompute._transition)
|
|
1015
|
-
)
|
|
1016
|
-
|
|
1242
|
+
) {
|
|
1243
|
+
if (currentOptimisticLane) {
|
|
1244
|
+
const pendingLane = asyncCompute._optimisticLane;
|
|
1245
|
+
const lane = findLane(currentOptimisticLane);
|
|
1246
|
+
if (pendingLane && findLane(pendingLane) === lane && !hasActiveOverride(asyncCompute)) {
|
|
1247
|
+
if (!tracking) link(el, c);
|
|
1248
|
+
throw asyncCompute._error;
|
|
1249
|
+
}
|
|
1250
|
+
} else {
|
|
1251
|
+
if (!tracking) link(el, c);
|
|
1252
|
+
throw asyncCompute._error;
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1017
1255
|
if (el._fn && el._statusFlags & STATUS_ERROR) {
|
|
1018
1256
|
if (el._time < clock) {
|
|
1019
1257
|
recompute(el, true);
|
|
@@ -1021,7 +1259,7 @@ function read(el) {
|
|
|
1021
1259
|
} else throw el._error;
|
|
1022
1260
|
}
|
|
1023
1261
|
return !c ||
|
|
1024
|
-
|
|
1262
|
+
currentOptimisticLane !== null ||
|
|
1025
1263
|
el._pendingValue === NOT_PENDING ||
|
|
1026
1264
|
(stale && el._transition && activeTransition !== el._transition)
|
|
1027
1265
|
? el._value
|
|
@@ -1040,7 +1278,13 @@ function setSignal(el, v) {
|
|
|
1040
1278
|
: el._pendingValue;
|
|
1041
1279
|
if (typeof v === "function") v = v(currentValue);
|
|
1042
1280
|
const valueChanged = !el._equals || !el._equals(currentValue, v);
|
|
1043
|
-
if (!valueChanged)
|
|
1281
|
+
if (!valueChanged) {
|
|
1282
|
+
if (isOptimistic && el._pendingValue !== NOT_PENDING && el._fn) {
|
|
1283
|
+
insertSubs(el, true);
|
|
1284
|
+
schedule();
|
|
1285
|
+
}
|
|
1286
|
+
return v;
|
|
1287
|
+
}
|
|
1044
1288
|
if (isOptimistic) {
|
|
1045
1289
|
const alreadyTracked = globalQueue._optimisticNodes.includes(el);
|
|
1046
1290
|
if (el._transition && alreadyTracked) {
|
|
@@ -1052,6 +1296,9 @@ function setSignal(el, v) {
|
|
|
1052
1296
|
if (!alreadyTracked) {
|
|
1053
1297
|
globalQueue._optimisticNodes.push(el);
|
|
1054
1298
|
}
|
|
1299
|
+
el._overrideVersion = (el._overrideVersion || 0) + 1;
|
|
1300
|
+
const lane = getOrCreateLane(el);
|
|
1301
|
+
el._optimisticLane = lane;
|
|
1055
1302
|
el._value = v;
|
|
1056
1303
|
} else {
|
|
1057
1304
|
if (el._pendingValue === NOT_PENDING) globalQueue._pendingNodes.push(el);
|
|
@@ -1156,6 +1403,8 @@ function isPending(fn) {
|
|
|
1156
1403
|
try {
|
|
1157
1404
|
fn();
|
|
1158
1405
|
return foundPending;
|
|
1406
|
+
} catch {
|
|
1407
|
+
return foundPending;
|
|
1159
1408
|
} finally {
|
|
1160
1409
|
pendingCheckActive = prevPendingCheck;
|
|
1161
1410
|
foundPending = prevFoundPending;
|
|
@@ -1228,25 +1477,27 @@ function effect(compute, effect, error, initialValue, options) {
|
|
|
1228
1477
|
node._errorFn = error;
|
|
1229
1478
|
node._cleanup = undefined;
|
|
1230
1479
|
node._type = options?.render ? EFFECT_RENDER : EFFECT_USER;
|
|
1231
|
-
node._notifyStatus = () => {
|
|
1232
|
-
|
|
1233
|
-
|
|
1480
|
+
node._notifyStatus = (status, error) => {
|
|
1481
|
+
const actualStatus = status !== undefined ? status : node._statusFlags;
|
|
1482
|
+
const actualError = error !== undefined ? error : node._error;
|
|
1483
|
+
if (actualStatus & STATUS_ERROR) {
|
|
1484
|
+
let err = actualError;
|
|
1234
1485
|
node._queue.notify(node, STATUS_PENDING, 0);
|
|
1235
1486
|
if (node._type === EFFECT_USER) {
|
|
1236
1487
|
try {
|
|
1237
1488
|
return node._errorFn
|
|
1238
|
-
? node._errorFn(
|
|
1489
|
+
? node._errorFn(err, () => {
|
|
1239
1490
|
node._cleanup?.();
|
|
1240
1491
|
node._cleanup = undefined;
|
|
1241
1492
|
})
|
|
1242
|
-
: console.error(
|
|
1493
|
+
: console.error(err);
|
|
1243
1494
|
} catch (e) {
|
|
1244
|
-
|
|
1495
|
+
err = e;
|
|
1245
1496
|
}
|
|
1246
1497
|
}
|
|
1247
|
-
if (!node._queue.notify(node, STATUS_ERROR, STATUS_ERROR)) throw
|
|
1498
|
+
if (!node._queue.notify(node, STATUS_ERROR, STATUS_ERROR)) throw err;
|
|
1248
1499
|
} else if (node._type === EFFECT_RENDER)
|
|
1249
|
-
node._queue.notify(node, STATUS_PENDING | STATUS_ERROR,
|
|
1500
|
+
node._queue.notify(node, STATUS_PENDING | STATUS_ERROR, actualStatus, actualError);
|
|
1250
1501
|
};
|
|
1251
1502
|
recompute(node, true);
|
|
1252
1503
|
!options?.defer &&
|
|
@@ -1994,18 +2245,27 @@ function clearOptimisticStore(store) {
|
|
|
1994
2245
|
if (!target || !target[STORE_OPTIMISTIC_OVERRIDE]) return;
|
|
1995
2246
|
const override = target[STORE_OPTIMISTIC_OVERRIDE];
|
|
1996
2247
|
const nodes = target[STORE_NODE];
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2248
|
+
setProjectionWriteActive(true);
|
|
2249
|
+
try {
|
|
2250
|
+
if (nodes) {
|
|
2251
|
+
for (const key of Reflect.ownKeys(override)) {
|
|
2252
|
+
if (nodes[key]) {
|
|
2253
|
+
nodes[key]._optimisticLane = undefined;
|
|
2254
|
+
const baseValue =
|
|
2255
|
+
target[STORE_OVERRIDE] && key in target[STORE_OVERRIDE]
|
|
2256
|
+
? target[STORE_OVERRIDE][key]
|
|
2257
|
+
: target[STORE_VALUE][key];
|
|
2258
|
+
const value = baseValue === $DELETED ? undefined : baseValue;
|
|
2259
|
+
setSignal(nodes[key], isWrappable(value) ? wrap(value, target) : value);
|
|
2260
|
+
}
|
|
2261
|
+
}
|
|
2262
|
+
if (nodes[$TRACK]) {
|
|
2263
|
+
nodes[$TRACK]._optimisticLane = undefined;
|
|
2264
|
+
setSignal(nodes[$TRACK], undefined);
|
|
2006
2265
|
}
|
|
2007
2266
|
}
|
|
2008
|
-
|
|
2267
|
+
} finally {
|
|
2268
|
+
setProjectionWriteActive(false);
|
|
2009
2269
|
}
|
|
2010
2270
|
delete target[STORE_OPTIMISTIC_OVERRIDE];
|
|
2011
2271
|
}
|
|
@@ -2453,10 +2713,11 @@ function compare(key, a, b) {
|
|
|
2453
2713
|
}
|
|
2454
2714
|
function boundaryComputed(fn, propagationMask) {
|
|
2455
2715
|
const node = computed(fn, undefined, { lazy: true });
|
|
2456
|
-
node._notifyStatus = () => {
|
|
2457
|
-
const flags = node._statusFlags;
|
|
2716
|
+
node._notifyStatus = (status, error) => {
|
|
2717
|
+
const flags = status !== undefined ? status : node._statusFlags;
|
|
2718
|
+
const actualError = error !== undefined ? error : node._error;
|
|
2458
2719
|
node._statusFlags &= ~node._propagationMask;
|
|
2459
|
-
node._queue.notify(node, node._propagationMask, flags);
|
|
2720
|
+
node._queue.notify(node, node._propagationMask, flags, actualError);
|
|
2460
2721
|
};
|
|
2461
2722
|
node._propagationMask = propagationMask;
|
|
2462
2723
|
node._preventAutoDisposal = true;
|
|
@@ -2484,7 +2745,7 @@ class ConditionalQueue extends Queue {
|
|
|
2484
2745
|
if (!type || read(this._disabled)) return;
|
|
2485
2746
|
return super.run(type);
|
|
2486
2747
|
}
|
|
2487
|
-
notify(node, type, flags) {
|
|
2748
|
+
notify(node, type, flags, error) {
|
|
2488
2749
|
if (read(this._disabled)) {
|
|
2489
2750
|
if (type & STATUS_PENDING) {
|
|
2490
2751
|
if (flags & STATUS_PENDING) {
|
|
@@ -2499,12 +2760,12 @@ class ConditionalQueue extends Queue {
|
|
|
2499
2760
|
} else if (this._errorNodes.delete(node)) type &= ~STATUS_ERROR;
|
|
2500
2761
|
}
|
|
2501
2762
|
}
|
|
2502
|
-
return type ? super.notify(node, type, flags) : true;
|
|
2763
|
+
return type ? super.notify(node, type, flags, error ?? node._error) : true;
|
|
2503
2764
|
}
|
|
2504
2765
|
}
|
|
2505
2766
|
class CollectionQueue extends Queue {
|
|
2506
2767
|
_collectionType;
|
|
2507
|
-
|
|
2768
|
+
_sources = new Set();
|
|
2508
2769
|
_disabled = signal(false, { pureWrite: true });
|
|
2509
2770
|
_initialized = false;
|
|
2510
2771
|
constructor(type) {
|
|
@@ -2515,21 +2776,28 @@ class CollectionQueue extends Queue {
|
|
|
2515
2776
|
if (!type || read(this._disabled)) return;
|
|
2516
2777
|
return super.run(type);
|
|
2517
2778
|
}
|
|
2518
|
-
notify(node, type, flags) {
|
|
2779
|
+
notify(node, type, flags, error) {
|
|
2519
2780
|
if (
|
|
2520
2781
|
!(type & this._collectionType) ||
|
|
2521
2782
|
(this._collectionType & STATUS_PENDING && this._initialized)
|
|
2522
2783
|
)
|
|
2523
|
-
return super.notify(node, type, flags);
|
|
2784
|
+
return super.notify(node, type, flags, error);
|
|
2524
2785
|
if (flags & this._collectionType) {
|
|
2525
|
-
|
|
2526
|
-
if (
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2786
|
+
const source = error?._source || node._error?._source;
|
|
2787
|
+
if (source) {
|
|
2788
|
+
const wasEmpty = this._sources.size === 0;
|
|
2789
|
+
this._sources.add(source);
|
|
2790
|
+
if (wasEmpty) setSignal(this._disabled, true);
|
|
2791
|
+
}
|
|
2530
2792
|
}
|
|
2531
2793
|
type &= ~this._collectionType;
|
|
2532
|
-
return type ? super.notify(node, type, flags) : true;
|
|
2794
|
+
return type ? super.notify(node, type, flags, error) : true;
|
|
2795
|
+
}
|
|
2796
|
+
checkSources() {
|
|
2797
|
+
for (const source of this._sources) {
|
|
2798
|
+
if (!(source._statusFlags & this._collectionType)) this._sources.delete(source);
|
|
2799
|
+
}
|
|
2800
|
+
if (!this._sources.size) setSignal(this._disabled, false);
|
|
2533
2801
|
}
|
|
2534
2802
|
}
|
|
2535
2803
|
var BoundaryMode;
|
|
@@ -2545,8 +2813,12 @@ function createBoundary(fn, condition) {
|
|
|
2545
2813
|
const disabled = read(queue._disabled);
|
|
2546
2814
|
tree._propagationMask = disabled ? STATUS_ERROR | STATUS_PENDING : 0;
|
|
2547
2815
|
if (!disabled) {
|
|
2548
|
-
queue._pendingNodes.forEach(node =>
|
|
2549
|
-
|
|
2816
|
+
queue._pendingNodes.forEach(node =>
|
|
2817
|
+
queue.notify(node, STATUS_PENDING, STATUS_PENDING, node._error)
|
|
2818
|
+
);
|
|
2819
|
+
queue._errorNodes.forEach(node =>
|
|
2820
|
+
queue.notify(node, STATUS_ERROR, STATUS_ERROR, node._error)
|
|
2821
|
+
);
|
|
2550
2822
|
queue._pendingNodes.clear();
|
|
2551
2823
|
queue._errorNodes.clear();
|
|
2552
2824
|
}
|
|
@@ -2572,26 +2844,12 @@ function createCollectionBoundary(type, fn, fallback) {
|
|
|
2572
2844
|
function createLoadBoundary(fn, fallback) {
|
|
2573
2845
|
return createCollectionBoundary(STATUS_PENDING, fn, () => fallback());
|
|
2574
2846
|
}
|
|
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
2847
|
function createErrorBoundary(fn, fallback) {
|
|
2589
2848
|
return createCollectionBoundary(STATUS_ERROR, fn, queue => {
|
|
2590
|
-
let
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
for (const
|
|
2594
|
-
for (const source of sources) recompute(source);
|
|
2849
|
+
let source = queue._sources.values().next().value;
|
|
2850
|
+
const error = source._error?.cause ?? source._error;
|
|
2851
|
+
return fallback(error, () => {
|
|
2852
|
+
for (const source of queue._sources) recompute(source);
|
|
2595
2853
|
schedule();
|
|
2596
2854
|
});
|
|
2597
2855
|
});
|