@solidjs/signals 0.12.0 → 0.13.0
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/README.md +2 -2
- package/dist/dev.js +219 -183
- package/dist/node.cjs +934 -913
- package/dist/prod.js +778 -752
- package/dist/types/boundaries.d.ts +6 -2
- package/dist/types/core/external.d.ts +26 -0
- package/dist/types/core/index.d.ts +3 -2
- package/dist/types/core/lanes.d.ts +3 -5
- package/dist/types/core/scheduler.d.ts +3 -1
- package/dist/types/core/types.d.ts +1 -1
- package/dist/types/index.d.ts +5 -4
- package/dist/types/signals.d.ts +1 -0
- package/dist/types/store/index.d.ts +2 -2
- package/dist/types/store/reconcile.d.ts +1 -1
- package/dist/types/store/store.d.ts +2 -4
- package/dist/types/store/utils.d.ts +8 -0
- package/package.json +1 -1
package/dist/dev.js
CHANGED
|
@@ -151,9 +151,13 @@ let clock = 0;
|
|
|
151
151
|
let activeTransition = null;
|
|
152
152
|
let scheduled = false;
|
|
153
153
|
let projectionWriteActive = false;
|
|
154
|
-
let
|
|
155
|
-
|
|
156
|
-
|
|
154
|
+
let _enforceLoadingBoundary = false;
|
|
155
|
+
let _hitUnhandledAsync = false;
|
|
156
|
+
function resetUnhandledAsync() {
|
|
157
|
+
_hitUnhandledAsync = false;
|
|
158
|
+
}
|
|
159
|
+
function enforceLoadingBoundary(enabled) {
|
|
160
|
+
_enforceLoadingBoundary = enabled;
|
|
157
161
|
}
|
|
158
162
|
function runLaneEffects(type) {
|
|
159
163
|
for (const lane of activeLanes) {
|
|
@@ -291,9 +295,6 @@ class GlobalQueue extends Queue {
|
|
|
291
295
|
}
|
|
292
296
|
notify(node, mask, flags, error) {
|
|
293
297
|
if (mask & STATUS_PENDING) {
|
|
294
|
-
if (_onUnhandledAsync && flags & STATUS_PENDING) {
|
|
295
|
-
_onUnhandledAsync();
|
|
296
|
-
}
|
|
297
298
|
if (flags & STATUS_PENDING) {
|
|
298
299
|
const actualError = error !== undefined ? error : node._error;
|
|
299
300
|
if (
|
|
@@ -304,6 +305,7 @@ class GlobalQueue extends Queue {
|
|
|
304
305
|
activeTransition._asyncNodes.push(actualError.source);
|
|
305
306
|
schedule();
|
|
306
307
|
}
|
|
308
|
+
if (_enforceLoadingBoundary) _hitUnhandledAsync = true;
|
|
307
309
|
}
|
|
308
310
|
return true;
|
|
309
311
|
}
|
|
@@ -387,35 +389,40 @@ function insertSubs(node, optimistic = false) {
|
|
|
387
389
|
insertIntoHeap(s._sub, queue);
|
|
388
390
|
}
|
|
389
391
|
}
|
|
392
|
+
function commitPendingNodes() {
|
|
393
|
+
const pendingNodes = globalQueue._pendingNodes;
|
|
394
|
+
for (let i = 0; i < pendingNodes.length; i++) {
|
|
395
|
+
const n = pendingNodes[i];
|
|
396
|
+
if (n._pendingValue !== NOT_PENDING) {
|
|
397
|
+
n._value = n._pendingValue;
|
|
398
|
+
n._pendingValue = NOT_PENDING;
|
|
399
|
+
if (n._type && n._type !== EFFECT_TRACKED) n._modified = true;
|
|
400
|
+
}
|
|
401
|
+
if (!(n._statusFlags & STATUS_PENDING)) n._statusFlags &= ~STATUS_UNINITIALIZED;
|
|
402
|
+
if (n._fn) GlobalQueue._dispose(n, false, true);
|
|
403
|
+
}
|
|
404
|
+
pendingNodes.length = 0;
|
|
405
|
+
}
|
|
390
406
|
function finalizePureQueue(completingTransition = null, incomplete = false) {
|
|
391
407
|
let resolvePending = !incomplete;
|
|
408
|
+
if (resolvePending) commitPendingNodes();
|
|
392
409
|
if (!incomplete) checkBoundaryChildren(globalQueue);
|
|
393
410
|
if (dirtyQueue._max >= dirtyQueue._min) runHeap(dirtyQueue, GlobalQueue._update);
|
|
394
411
|
if (resolvePending) {
|
|
395
|
-
|
|
396
|
-
for (let i = 0; i < pendingNodes.length; i++) {
|
|
397
|
-
const n = pendingNodes[i];
|
|
398
|
-
if (n._pendingValue !== NOT_PENDING) {
|
|
399
|
-
n._value = n._pendingValue;
|
|
400
|
-
n._pendingValue = NOT_PENDING;
|
|
401
|
-
if (n._type && n._type !== EFFECT_TRACKED) n._modified = true;
|
|
402
|
-
}
|
|
403
|
-
if (!(n._statusFlags & STATUS_PENDING)) n._statusFlags &= ~STATUS_UNINITIALIZED;
|
|
404
|
-
if (n._fn) GlobalQueue._dispose(n, false, true);
|
|
405
|
-
}
|
|
406
|
-
pendingNodes.length = 0;
|
|
412
|
+
commitPendingNodes();
|
|
407
413
|
const optimisticNodes = completingTransition
|
|
408
414
|
? completingTransition._optimisticNodes
|
|
409
415
|
: globalQueue._optimisticNodes;
|
|
410
416
|
for (let i = 0; i < optimisticNodes.length; i++) {
|
|
411
417
|
const n = optimisticNodes[i];
|
|
412
|
-
const original = n._pendingValue;
|
|
413
418
|
n._optimisticLane = undefined;
|
|
414
|
-
if (
|
|
415
|
-
n._value =
|
|
416
|
-
|
|
419
|
+
if (n._pendingValue !== NOT_PENDING) {
|
|
420
|
+
n._value = n._pendingValue;
|
|
421
|
+
n._pendingValue = NOT_PENDING;
|
|
417
422
|
}
|
|
418
|
-
|
|
423
|
+
const prevOverride = n._overrideValue;
|
|
424
|
+
n._overrideValue = NOT_PENDING;
|
|
425
|
+
if (prevOverride !== NOT_PENDING && n._value !== prevOverride) insertSubs(n, true);
|
|
419
426
|
n._transition = null;
|
|
420
427
|
}
|
|
421
428
|
optimisticNodes.length = 0;
|
|
@@ -522,7 +529,7 @@ function getOrCreateLane(signal) {
|
|
|
522
529
|
};
|
|
523
530
|
signalLanes.set(signal, lane);
|
|
524
531
|
activeLanes.add(lane);
|
|
525
|
-
signal.
|
|
532
|
+
signal._overrideSinceLane = false;
|
|
526
533
|
return lane;
|
|
527
534
|
}
|
|
528
535
|
function findLane(lane) {
|
|
@@ -548,7 +555,7 @@ function resolveLane(el) {
|
|
|
548
555
|
return undefined;
|
|
549
556
|
}
|
|
550
557
|
function hasActiveOverride(el) {
|
|
551
|
-
return !!(el.
|
|
558
|
+
return !!(el._overrideValue !== undefined && el._overrideValue !== NOT_PENDING);
|
|
552
559
|
}
|
|
553
560
|
function assignOrMergeLane(el, sourceLane) {
|
|
554
561
|
const sourceRoot = findLane(sourceLane);
|
|
@@ -595,10 +602,10 @@ function handleAsync(el, result, setter) {
|
|
|
595
602
|
const lane = resolveLane(el);
|
|
596
603
|
if (lane) lane._pendingAsync.delete(el);
|
|
597
604
|
if (setter) setter(value);
|
|
598
|
-
else if (el.
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
605
|
+
else if (el._overrideValue !== undefined) {
|
|
606
|
+
if (el._overrideValue !== undefined && el._overrideValue !== NOT_PENDING)
|
|
607
|
+
el._pendingValue = value;
|
|
608
|
+
else {
|
|
602
609
|
el._value = value;
|
|
603
610
|
insertSubs(el);
|
|
604
611
|
}
|
|
@@ -693,7 +700,8 @@ function notifyStatus(el, status, error, blockStatus, lane) {
|
|
|
693
700
|
)
|
|
694
701
|
error = new StatusError(el, error);
|
|
695
702
|
const isSource = error instanceof NotReadyError && error.source === el;
|
|
696
|
-
const isOptimisticBoundary =
|
|
703
|
+
const isOptimisticBoundary =
|
|
704
|
+
status === STATUS_PENDING && el._overrideValue !== undefined && !isSource;
|
|
697
705
|
const startsBlocking = isOptimisticBoundary && hasActiveOverride(el);
|
|
698
706
|
if (!blockStatus) {
|
|
699
707
|
el._statusFlags =
|
|
@@ -844,7 +852,6 @@ function disposeChildren(node, self = false, zombie) {
|
|
|
844
852
|
node._pendingFirstChild = null;
|
|
845
853
|
} else {
|
|
846
854
|
node._firstChild = null;
|
|
847
|
-
node._nextSibling = null;
|
|
848
855
|
node._childCount = 0;
|
|
849
856
|
}
|
|
850
857
|
runDisposal(node, zombie);
|
|
@@ -978,8 +985,14 @@ function effect(compute, effect, error, initialValue, options) {
|
|
|
978
985
|
}
|
|
979
986
|
}
|
|
980
987
|
if (!node._queue.notify(node, STATUS_ERROR, STATUS_ERROR)) throw err;
|
|
981
|
-
} else if (node._type === EFFECT_RENDER)
|
|
988
|
+
} else if (node._type === EFFECT_RENDER) {
|
|
982
989
|
node._queue.notify(node, STATUS_PENDING | STATUS_ERROR, actualStatus, actualError);
|
|
990
|
+
if (_hitUnhandledAsync) {
|
|
991
|
+
resetUnhandledAsync();
|
|
992
|
+
const err = new Error("An async value must be rendered inside a Loading boundary.");
|
|
993
|
+
if (!node._queue.notify(node, STATUS_ERROR, STATUS_ERROR)) throw err;
|
|
994
|
+
}
|
|
995
|
+
}
|
|
983
996
|
};
|
|
984
997
|
recompute(node, true);
|
|
985
998
|
!options?.defer &&
|
|
@@ -993,6 +1006,10 @@ function effect(compute, effect, error, initialValue, options) {
|
|
|
993
1006
|
}
|
|
994
1007
|
function runEffect() {
|
|
995
1008
|
if (!this._modified || this._flags & REACTIVE_DISPOSED) return;
|
|
1009
|
+
let prevStrictRead = false;
|
|
1010
|
+
{
|
|
1011
|
+
prevStrictRead = setStrictRead("an effect callback");
|
|
1012
|
+
}
|
|
996
1013
|
this._cleanup?.();
|
|
997
1014
|
this._cleanup = undefined;
|
|
998
1015
|
try {
|
|
@@ -1000,6 +1017,7 @@ function runEffect() {
|
|
|
1000
1017
|
} catch (error) {
|
|
1001
1018
|
if (!this._queue.notify(this, STATUS_ERROR, STATUS_ERROR)) throw error;
|
|
1002
1019
|
} finally {
|
|
1020
|
+
setStrictRead(prevStrictRead);
|
|
1003
1021
|
this._prevValue = this._value;
|
|
1004
1022
|
this._modified = false;
|
|
1005
1023
|
}
|
|
@@ -1033,6 +1051,29 @@ function trackedEffect(fn, options) {
|
|
|
1033
1051
|
if (!node._parent)
|
|
1034
1052
|
console.warn("Effects created outside a reactive context will never be disposed");
|
|
1035
1053
|
}
|
|
1054
|
+
let externalSourceConfig = null;
|
|
1055
|
+
function enableExternalSource(config) {
|
|
1056
|
+
const { factory: factory, untrack: untrackFn = fn => fn() } = config;
|
|
1057
|
+
if (externalSourceConfig) {
|
|
1058
|
+
const { factory: oldFactory, untrack: oldUntrack } = externalSourceConfig;
|
|
1059
|
+
externalSourceConfig = {
|
|
1060
|
+
factory: (fn, trigger) => {
|
|
1061
|
+
const oldSource = oldFactory(fn, trigger);
|
|
1062
|
+
const source = factory(x => oldSource.track(x), trigger);
|
|
1063
|
+
return {
|
|
1064
|
+
track: x => source.track(x),
|
|
1065
|
+
dispose() {
|
|
1066
|
+
source.dispose();
|
|
1067
|
+
oldSource.dispose();
|
|
1068
|
+
}
|
|
1069
|
+
};
|
|
1070
|
+
},
|
|
1071
|
+
untrack: fn => oldUntrack(() => untrackFn(fn))
|
|
1072
|
+
};
|
|
1073
|
+
} else {
|
|
1074
|
+
externalSourceConfig = { factory: factory, untrack: untrackFn };
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1036
1077
|
GlobalQueue._update = recompute;
|
|
1037
1078
|
GlobalQueue._dispose = disposeChildren;
|
|
1038
1079
|
let tracking = false;
|
|
@@ -1112,7 +1153,7 @@ function recompute(el, create = false) {
|
|
|
1112
1153
|
}
|
|
1113
1154
|
}
|
|
1114
1155
|
const isOptimisticDirty = !!(el._flags & REACTIVE_OPTIMISTIC_DIRTY);
|
|
1115
|
-
const hasOverride =
|
|
1156
|
+
const hasOverride = el._overrideValue !== undefined && el._overrideValue !== NOT_PENDING;
|
|
1116
1157
|
const wasPending = !!(el._statusFlags & STATUS_PENDING);
|
|
1117
1158
|
const oldcontext = context;
|
|
1118
1159
|
context = el;
|
|
@@ -1174,24 +1215,24 @@ function recompute(el, create = false) {
|
|
|
1174
1215
|
else el._deps = null;
|
|
1175
1216
|
}
|
|
1176
1217
|
const compareValue = hasOverride
|
|
1177
|
-
? el.
|
|
1218
|
+
? el._overrideValue
|
|
1178
1219
|
: el._pendingValue === NOT_PENDING
|
|
1179
1220
|
? el._value
|
|
1180
1221
|
: el._pendingValue;
|
|
1181
1222
|
const valueChanged = !el._equals || !el._equals(compareValue, value);
|
|
1182
1223
|
if (valueChanged) {
|
|
1183
|
-
const prevVisible = hasOverride ? el.
|
|
1184
|
-
if (create || (isEffect && activeTransition !== el._transition) || isOptimisticDirty)
|
|
1224
|
+
const prevVisible = hasOverride ? el._overrideValue : undefined;
|
|
1225
|
+
if (create || (isEffect && activeTransition !== el._transition) || isOptimisticDirty) {
|
|
1185
1226
|
el._value = value;
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1227
|
+
if (hasOverride && isOptimisticDirty) {
|
|
1228
|
+
el._overrideValue = value;
|
|
1229
|
+
el._pendingValue = value;
|
|
1230
|
+
}
|
|
1231
|
+
} else el._pendingValue = value;
|
|
1232
|
+
if (hasOverride && !isOptimisticDirty && wasPending && !el._overrideSinceLane)
|
|
1233
|
+
el._overrideValue = value;
|
|
1234
|
+
if (!hasOverride || isOptimisticDirty || el._overrideValue !== prevVisible)
|
|
1193
1235
|
insertSubs(el, isOptimisticDirty || hasOverride);
|
|
1194
|
-
}
|
|
1195
1236
|
} else if (hasOverride) {
|
|
1196
1237
|
el._pendingValue = value;
|
|
1197
1238
|
} else if (el._height != oldHeight) {
|
|
@@ -1203,7 +1244,7 @@ function recompute(el, create = false) {
|
|
|
1203
1244
|
currentOptimisticLane = prevLane;
|
|
1204
1245
|
(!create || el._statusFlags & STATUS_PENDING) &&
|
|
1205
1246
|
!el._transition &&
|
|
1206
|
-
!(activeTransition &&
|
|
1247
|
+
!(activeTransition && hasOverride) &&
|
|
1207
1248
|
globalQueue._pendingNodes.push(el);
|
|
1208
1249
|
el._transition &&
|
|
1209
1250
|
isEffect &&
|
|
@@ -1284,6 +1325,17 @@ function computed(fn, initialValue, options) {
|
|
|
1284
1325
|
}
|
|
1285
1326
|
if (parent) self._height = parent._height + 1;
|
|
1286
1327
|
if (snapshotCaptureActive && ownerInSnapshotScope(context)) self._inSnapshotScope = true;
|
|
1328
|
+
if (externalSourceConfig) {
|
|
1329
|
+
const bridgeSignal = signal(undefined, { equals: false, pureWrite: true });
|
|
1330
|
+
const source = externalSourceConfig.factory(self._fn, () => {
|
|
1331
|
+
setSignal(bridgeSignal, undefined);
|
|
1332
|
+
});
|
|
1333
|
+
onCleanup(() => source.dispose());
|
|
1334
|
+
self._fn = prev => {
|
|
1335
|
+
read(bridgeSignal);
|
|
1336
|
+
return source.track(prev);
|
|
1337
|
+
};
|
|
1338
|
+
}
|
|
1287
1339
|
!options?.lazy && recompute(self, true);
|
|
1288
1340
|
if (snapshotCaptureActive && !options?.lazy) {
|
|
1289
1341
|
if (!(self._statusFlags & STATUS_PENDING)) {
|
|
@@ -1308,7 +1360,7 @@ function signal(v, options, firewall = null) {
|
|
|
1308
1360
|
};
|
|
1309
1361
|
s._name = options?.name ?? "signal";
|
|
1310
1362
|
firewall && (firewall._child = s);
|
|
1311
|
-
if (snapshotCaptureActive && !s._pureWrite) {
|
|
1363
|
+
if (snapshotCaptureActive && !s._pureWrite && !((firewall?._statusFlags ?? 0) & STATUS_PENDING)) {
|
|
1312
1364
|
s._snapshotValue = v === undefined ? NO_SNAPSHOT : v;
|
|
1313
1365
|
snapshotSources.add(s);
|
|
1314
1366
|
}
|
|
@@ -1316,12 +1368,12 @@ function signal(v, options, firewall = null) {
|
|
|
1316
1368
|
}
|
|
1317
1369
|
function optimisticSignal(v, options) {
|
|
1318
1370
|
const s = signal(v, options);
|
|
1319
|
-
s.
|
|
1371
|
+
s._overrideValue = NOT_PENDING;
|
|
1320
1372
|
return s;
|
|
1321
1373
|
}
|
|
1322
1374
|
function optimisticComputed(fn, initialValue, options) {
|
|
1323
1375
|
const c = computed(fn, initialValue, options);
|
|
1324
|
-
c.
|
|
1376
|
+
c._overrideValue = NOT_PENDING;
|
|
1325
1377
|
return c;
|
|
1326
1378
|
}
|
|
1327
1379
|
function isEqual(a, b) {
|
|
@@ -1334,12 +1386,13 @@ function setStrictRead(v) {
|
|
|
1334
1386
|
return prev;
|
|
1335
1387
|
}
|
|
1336
1388
|
function untrack(fn, strictReadLabel) {
|
|
1337
|
-
if (!tracking && !strictRead && !strictReadLabel) return fn();
|
|
1389
|
+
if (!externalSourceConfig && !tracking && !strictRead && !strictReadLabel) return fn();
|
|
1338
1390
|
const prevTracking = tracking;
|
|
1339
1391
|
const prevStrictRead = strictRead;
|
|
1340
1392
|
tracking = false;
|
|
1341
1393
|
strictRead = strictReadLabel || false;
|
|
1342
1394
|
try {
|
|
1395
|
+
if (externalSourceConfig) return externalSourceConfig.untrack(fn);
|
|
1343
1396
|
return fn();
|
|
1344
1397
|
} finally {
|
|
1345
1398
|
tracking = prevTracking;
|
|
@@ -1351,21 +1404,25 @@ function read(el) {
|
|
|
1351
1404
|
const pendingComputed = getLatestValueComputed(el);
|
|
1352
1405
|
const prevPending = latestReadActive;
|
|
1353
1406
|
latestReadActive = false;
|
|
1407
|
+
const visibleValue =
|
|
1408
|
+
el._overrideValue !== undefined && el._overrideValue !== NOT_PENDING
|
|
1409
|
+
? el._overrideValue
|
|
1410
|
+
: el._value;
|
|
1354
1411
|
let value;
|
|
1355
1412
|
try {
|
|
1356
1413
|
value = read(pendingComputed);
|
|
1357
1414
|
} catch (e) {
|
|
1358
|
-
if (!context && e instanceof NotReadyError) return
|
|
1415
|
+
if (!context && e instanceof NotReadyError) return visibleValue;
|
|
1359
1416
|
throw e;
|
|
1360
1417
|
} finally {
|
|
1361
1418
|
latestReadActive = prevPending;
|
|
1362
1419
|
}
|
|
1363
|
-
if (pendingComputed._statusFlags & STATUS_PENDING) return
|
|
1420
|
+
if (pendingComputed._statusFlags & STATUS_PENDING) return visibleValue;
|
|
1364
1421
|
if (stale && currentOptimisticLane && pendingComputed._optimisticLane) {
|
|
1365
1422
|
const pcLane = findLane(pendingComputed._optimisticLane);
|
|
1366
1423
|
const curLane = findLane(currentOptimisticLane);
|
|
1367
1424
|
if (pcLane !== curLane && pcLane._pendingAsync.size > 0) {
|
|
1368
|
-
return
|
|
1425
|
+
return visibleValue;
|
|
1369
1426
|
}
|
|
1370
1427
|
}
|
|
1371
1428
|
return value;
|
|
@@ -1391,8 +1448,8 @@ function read(el) {
|
|
|
1391
1448
|
const owner = el._firewall || el;
|
|
1392
1449
|
if (strictRead && owner._statusFlags & STATUS_PENDING) {
|
|
1393
1450
|
throw new Error(
|
|
1394
|
-
`Reading a pending async value in ${strictRead}. ` +
|
|
1395
|
-
`Async values must be read within a tracking scope (JSX,
|
|
1451
|
+
`Reading a pending async value directly in ${strictRead}. ` +
|
|
1452
|
+
`Async values must be read within a tracking scope (JSX, a memo, or an effect's compute function).`
|
|
1396
1453
|
);
|
|
1397
1454
|
}
|
|
1398
1455
|
if (c && tracking) {
|
|
@@ -1417,11 +1474,11 @@ function read(el) {
|
|
|
1417
1474
|
const pendingLane = owner._optimisticLane;
|
|
1418
1475
|
const lane = findLane(currentOptimisticLane);
|
|
1419
1476
|
if (pendingLane && findLane(pendingLane) === lane && !hasActiveOverride(owner)) {
|
|
1420
|
-
if (!tracking) link(el, c);
|
|
1477
|
+
if (!tracking && el !== c) link(el, c);
|
|
1421
1478
|
throw owner._error;
|
|
1422
1479
|
}
|
|
1423
1480
|
} else {
|
|
1424
|
-
if (!tracking) link(el, c);
|
|
1481
|
+
if (!tracking && el !== c) link(el, c);
|
|
1425
1482
|
throw owner._error;
|
|
1426
1483
|
}
|
|
1427
1484
|
} else if (!c && owner._statusFlags & STATUS_UNINITIALIZED) {
|
|
@@ -1445,12 +1502,14 @@ function read(el) {
|
|
|
1445
1502
|
}
|
|
1446
1503
|
if (strictRead)
|
|
1447
1504
|
console.warn(
|
|
1448
|
-
`Reactive value read
|
|
1449
|
-
`Move it into a tracking scope (JSX,
|
|
1505
|
+
`Reactive value read directly in ${strictRead} will not update. ` +
|
|
1506
|
+
`Move it into a tracking scope (JSX, a memo, or an effect's compute function).`
|
|
1450
1507
|
);
|
|
1508
|
+
if (el._overrideValue !== undefined && el._overrideValue !== NOT_PENDING)
|
|
1509
|
+
return el._overrideValue;
|
|
1451
1510
|
return !c ||
|
|
1452
1511
|
(currentOptimisticLane !== null &&
|
|
1453
|
-
(el.
|
|
1512
|
+
(el._overrideValue !== undefined ||
|
|
1454
1513
|
el._optimisticLane ||
|
|
1455
1514
|
owner === el ||
|
|
1456
1515
|
!!(owner._statusFlags & STATUS_PENDING))) ||
|
|
@@ -1464,9 +1523,12 @@ function setSignal(el, v) {
|
|
|
1464
1523
|
console.warn("A Signal was written to in an owned scope.");
|
|
1465
1524
|
if (el._transition && activeTransition !== el._transition)
|
|
1466
1525
|
globalQueue.initTransition(el._transition);
|
|
1467
|
-
const isOptimistic = el.
|
|
1526
|
+
const isOptimistic = el._overrideValue !== undefined && !projectionWriteActive;
|
|
1527
|
+
const hasOverride = el._overrideValue !== undefined && el._overrideValue !== NOT_PENDING;
|
|
1468
1528
|
const currentValue = isOptimistic
|
|
1469
|
-
?
|
|
1529
|
+
? hasOverride
|
|
1530
|
+
? el._overrideValue
|
|
1531
|
+
: el._value
|
|
1470
1532
|
: el._pendingValue === NOT_PENDING
|
|
1471
1533
|
? el._value
|
|
1472
1534
|
: el._pendingValue;
|
|
@@ -1474,27 +1536,23 @@ function setSignal(el, v) {
|
|
|
1474
1536
|
const valueChanged =
|
|
1475
1537
|
!el._equals || !el._equals(currentValue, v) || !!(el._statusFlags & STATUS_UNINITIALIZED);
|
|
1476
1538
|
if (!valueChanged) {
|
|
1477
|
-
if (isOptimistic &&
|
|
1539
|
+
if (isOptimistic && hasOverride && el._fn) {
|
|
1478
1540
|
insertSubs(el, true);
|
|
1479
1541
|
schedule();
|
|
1480
1542
|
}
|
|
1481
1543
|
return v;
|
|
1482
1544
|
}
|
|
1483
1545
|
if (isOptimistic) {
|
|
1484
|
-
const
|
|
1485
|
-
if (el._transition
|
|
1486
|
-
|
|
1487
|
-
}
|
|
1488
|
-
if (el._pendingValue === NOT_PENDING) {
|
|
1546
|
+
const firstOverride = el._overrideValue === NOT_PENDING;
|
|
1547
|
+
if (!firstOverride && el._transition) globalQueue.initTransition(el._transition);
|
|
1548
|
+
if (firstOverride) {
|
|
1489
1549
|
el._pendingValue = el._value;
|
|
1490
|
-
}
|
|
1491
|
-
if (!alreadyTracked) {
|
|
1492
1550
|
globalQueue._optimisticNodes.push(el);
|
|
1493
1551
|
}
|
|
1494
|
-
el.
|
|
1552
|
+
el._overrideSinceLane = true;
|
|
1495
1553
|
const lane = getOrCreateLane(el);
|
|
1496
1554
|
el._optimisticLane = lane;
|
|
1497
|
-
el.
|
|
1555
|
+
el._overrideValue = v;
|
|
1498
1556
|
} else {
|
|
1499
1557
|
if (el._pendingValue === NOT_PENDING) globalQueue._pendingNodes.push(el);
|
|
1500
1558
|
el._pendingValue = v;
|
|
@@ -1532,7 +1590,7 @@ function getPendingSignal(el) {
|
|
|
1532
1590
|
}
|
|
1533
1591
|
function computePendingState(el) {
|
|
1534
1592
|
const comp = el;
|
|
1535
|
-
if (el.
|
|
1593
|
+
if (el._overrideValue !== undefined && el._overrideValue !== NOT_PENDING) {
|
|
1536
1594
|
if (comp._statusFlags & STATUS_PENDING && !(comp._statusFlags & STATUS_UNINITIALIZED))
|
|
1537
1595
|
return true;
|
|
1538
1596
|
if (el._parentSource) {
|
|
@@ -1702,17 +1760,22 @@ function action(genFn) {
|
|
|
1702
1760
|
step();
|
|
1703
1761
|
});
|
|
1704
1762
|
}
|
|
1763
|
+
function accessor(node) {
|
|
1764
|
+
const fn = read.bind(null, node);
|
|
1765
|
+
fn.$r = true;
|
|
1766
|
+
return fn;
|
|
1767
|
+
}
|
|
1705
1768
|
function createSignal(first, second, third) {
|
|
1706
1769
|
if (typeof first === "function") {
|
|
1707
1770
|
const node = computed(first, second, third);
|
|
1708
|
-
return [
|
|
1771
|
+
return [accessor(node), setSignal.bind(null, node)];
|
|
1709
1772
|
}
|
|
1710
1773
|
const node = signal(first, second);
|
|
1711
|
-
return [
|
|
1774
|
+
return [accessor(node), setSignal.bind(null, node)];
|
|
1712
1775
|
}
|
|
1713
1776
|
function createMemo(compute, value, options) {
|
|
1714
1777
|
let node = computed(compute, value, options);
|
|
1715
|
-
return
|
|
1778
|
+
return accessor(node);
|
|
1716
1779
|
}
|
|
1717
1780
|
function createEffect(compute, effectFn, value, options) {
|
|
1718
1781
|
effect(compute, effectFn.effect || effectFn, effectFn.error, value, {
|
|
@@ -1769,7 +1832,7 @@ function createOptimistic(first, second, third) {
|
|
|
1769
1832
|
typeof first === "function"
|
|
1770
1833
|
? optimisticComputed(first, second, third)
|
|
1771
1834
|
: optimisticSignal(first, second);
|
|
1772
|
-
return [
|
|
1835
|
+
return [accessor(node), setSignal.bind(null, node)];
|
|
1773
1836
|
}
|
|
1774
1837
|
function onSettled(callback) {
|
|
1775
1838
|
getOwner()
|
|
@@ -1791,7 +1854,7 @@ function getAllKeys(value, override, next) {
|
|
|
1791
1854
|
const nextKeys = Object.keys(next);
|
|
1792
1855
|
return Array.from(new Set([...keys, ...nextKeys]));
|
|
1793
1856
|
}
|
|
1794
|
-
function applyState(next, state, keyFn
|
|
1857
|
+
function applyState(next, state, keyFn) {
|
|
1795
1858
|
const target = state?.[$TARGET];
|
|
1796
1859
|
if (!target) return;
|
|
1797
1860
|
const previous = target[STORE_VALUE];
|
|
@@ -1814,7 +1877,7 @@ function applyState(next, state, keyFn, all) {
|
|
|
1814
1877
|
(item && next[start] && keyFn(item) === keyFn(next[start])));
|
|
1815
1878
|
start++
|
|
1816
1879
|
) {
|
|
1817
|
-
applyState(next[start], wrap(item, target), keyFn
|
|
1880
|
+
applyState(next[start], wrap(item, target), keyFn);
|
|
1818
1881
|
}
|
|
1819
1882
|
const temp = new Array(next.length),
|
|
1820
1883
|
newIndices = new Map();
|
|
@@ -1837,7 +1900,7 @@ function applyState(next, state, keyFn, all) {
|
|
|
1837
1900
|
changed = true;
|
|
1838
1901
|
const wrapped = wrap(temp[j], target);
|
|
1839
1902
|
target[STORE_NODE][j] && setSignal(target[STORE_NODE][j], wrapped);
|
|
1840
|
-
applyState(next[j], wrapped, keyFn
|
|
1903
|
+
applyState(next[j], wrapped, keyFn);
|
|
1841
1904
|
}
|
|
1842
1905
|
changed && target[STORE_NODE][$TRACK] && setSignal(target[STORE_NODE][$TRACK], void 0);
|
|
1843
1906
|
prevLength !== next.length &&
|
|
@@ -1867,7 +1930,7 @@ function applyState(next, state, keyFn, all) {
|
|
|
1867
1930
|
if (j in temp) {
|
|
1868
1931
|
const wrapped = wrap(temp[j], target);
|
|
1869
1932
|
target[STORE_NODE][j] && setSignal(target[STORE_NODE][j], wrapped);
|
|
1870
|
-
applyState(next[j], wrapped, keyFn
|
|
1933
|
+
applyState(next[j], wrapped, keyFn);
|
|
1871
1934
|
} else target[STORE_NODE][j] && setSignal(target[STORE_NODE][j], wrap(next[j], target));
|
|
1872
1935
|
}
|
|
1873
1936
|
if (start < next.length) changed = true;
|
|
@@ -1875,7 +1938,7 @@ function applyState(next, state, keyFn, all) {
|
|
|
1875
1938
|
for (let i = 0, len = next.length; i < len; i++) {
|
|
1876
1939
|
const item = getOverrideValue(previous, override, nodes, i, optOverride);
|
|
1877
1940
|
isWrappable(item)
|
|
1878
|
-
? applyState(next[i], wrap(item, target), keyFn
|
|
1941
|
+
? applyState(next[i], wrap(item, target), keyFn)
|
|
1879
1942
|
: target[STORE_NODE][i] && setSignal(target[STORE_NODE][i], next[i]);
|
|
1880
1943
|
}
|
|
1881
1944
|
}
|
|
@@ -1888,7 +1951,7 @@ function applyState(next, state, keyFn, all) {
|
|
|
1888
1951
|
}
|
|
1889
1952
|
if (nodes) {
|
|
1890
1953
|
const tracked = nodes[$TRACK];
|
|
1891
|
-
const keys = tracked
|
|
1954
|
+
const keys = tracked ? getAllKeys(previous, override, next) : Object.keys(nodes);
|
|
1892
1955
|
for (let i = 0, len = keys.length; i < len; i++) {
|
|
1893
1956
|
const key = keys[i];
|
|
1894
1957
|
const node = nodes[key];
|
|
@@ -1903,7 +1966,7 @@ function applyState(next, state, keyFn, all) {
|
|
|
1903
1966
|
) {
|
|
1904
1967
|
tracked && setSignal(tracked, void 0);
|
|
1905
1968
|
node && setSignal(node, isWrappable(nextValue) ? wrap(nextValue, target) : nextValue);
|
|
1906
|
-
} else applyState(nextValue, wrap(previousValue, target), keyFn
|
|
1969
|
+
} else applyState(nextValue, wrap(previousValue, target), keyFn);
|
|
1907
1970
|
}
|
|
1908
1971
|
}
|
|
1909
1972
|
if ((nodes = target[STORE_HAS])) {
|
|
@@ -1914,14 +1977,14 @@ function applyState(next, state, keyFn, all) {
|
|
|
1914
1977
|
}
|
|
1915
1978
|
}
|
|
1916
1979
|
}
|
|
1917
|
-
function reconcile(value, key
|
|
1980
|
+
function reconcile(value, key) {
|
|
1918
1981
|
return state => {
|
|
1919
1982
|
if (state == null) throw new Error("Cannot reconcile null or undefined state");
|
|
1920
1983
|
const keyFn = typeof key === "string" ? item => item[key] : key;
|
|
1921
1984
|
const eq = keyFn(state);
|
|
1922
1985
|
if (eq !== undefined && keyFn(value) !== keyFn(state))
|
|
1923
1986
|
throw new Error("Cannot reconcile states with different identity");
|
|
1924
|
-
applyState(value, state, keyFn
|
|
1987
|
+
applyState(value, state, keyFn);
|
|
1925
1988
|
};
|
|
1926
1989
|
}
|
|
1927
1990
|
function createProjectionInternal(fn, initialValue = {}, options) {
|
|
@@ -1951,11 +2014,9 @@ function createProjectionInternal(fn, initialValue = {}, options) {
|
|
|
1951
2014
|
const value = handleAsync(owner, fn(s), value => {
|
|
1952
2015
|
value !== s &&
|
|
1953
2016
|
value !== undefined &&
|
|
1954
|
-
storeSetter(wrappedStore, reconcile(value, options?.key || "id"
|
|
2017
|
+
storeSetter(wrappedStore, reconcile(value, options?.key || "id"));
|
|
1955
2018
|
});
|
|
1956
|
-
value !== s &&
|
|
1957
|
-
value !== undefined &&
|
|
1958
|
-
reconcile(value, options?.key || "id", options?.all)(wrappedStore);
|
|
2019
|
+
value !== s && value !== undefined && reconcile(value, options?.key || "id")(wrappedStore);
|
|
1959
2020
|
});
|
|
1960
2021
|
});
|
|
1961
2022
|
node._preventAutoDisposal = true;
|
|
@@ -2001,11 +2062,9 @@ const writeTraps = {
|
|
|
2001
2062
|
}
|
|
2002
2063
|
};
|
|
2003
2064
|
const $TRACK = Symbol("STORE_TRACK"),
|
|
2004
|
-
$DEEP = Symbol("STORE_DEEP"),
|
|
2005
2065
|
$TARGET = Symbol("STORE_TARGET"),
|
|
2006
2066
|
$PROXY = Symbol("STORE_PROXY"),
|
|
2007
2067
|
$DELETED = Symbol("STORE_DELETED");
|
|
2008
|
-
const PARENTS = new WeakMap();
|
|
2009
2068
|
const STORE_VALUE = "v",
|
|
2010
2069
|
STORE_OVERRIDE = "o",
|
|
2011
2070
|
STORE_OPTIMISTIC_OVERRIDE = "x",
|
|
@@ -2058,7 +2117,9 @@ function getNode(nodes, property, value, firewall, equals = isEqual, optimistic,
|
|
|
2058
2117
|
},
|
|
2059
2118
|
firewall
|
|
2060
2119
|
);
|
|
2061
|
-
if (optimistic)
|
|
2120
|
+
if (optimistic) {
|
|
2121
|
+
s._overrideValue = NOT_PENDING;
|
|
2122
|
+
}
|
|
2062
2123
|
if (snapshotProps && property in snapshotProps) {
|
|
2063
2124
|
const sv = snapshotProps[property];
|
|
2064
2125
|
s._snapshotValue = sv === undefined ? NO_SNAPSHOT : sv;
|
|
@@ -2104,8 +2165,8 @@ const storeTraps = {
|
|
|
2104
2165
|
if (property === $TARGET) return target;
|
|
2105
2166
|
if (property === $PROXY) return receiver;
|
|
2106
2167
|
if (property === $REFRESH) return target[STORE_FIREWALL];
|
|
2107
|
-
if (property === $TRACK
|
|
2108
|
-
trackSelf(target
|
|
2168
|
+
if (property === $TRACK) {
|
|
2169
|
+
trackSelf(target);
|
|
2109
2170
|
return receiver;
|
|
2110
2171
|
}
|
|
2111
2172
|
const nodes = getNodes(target, STORE_NODE);
|
|
@@ -2127,11 +2188,11 @@ const storeTraps = {
|
|
|
2127
2188
|
if (writeOnly(receiver)) {
|
|
2128
2189
|
let value =
|
|
2129
2190
|
tracked && (overridden || !proxySource)
|
|
2130
|
-
? tracked.
|
|
2131
|
-
? tracked.
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2191
|
+
? tracked._overrideValue !== undefined && tracked._overrideValue !== NOT_PENDING
|
|
2192
|
+
? tracked._overrideValue
|
|
2193
|
+
: tracked._pendingValue !== NOT_PENDING
|
|
2194
|
+
? tracked._pendingValue
|
|
2195
|
+
: tracked._value
|
|
2135
2196
|
: storeValue[property];
|
|
2136
2197
|
value === $DELETED && (value = undefined);
|
|
2137
2198
|
if (!isWrappable(value)) return value;
|
|
@@ -2169,8 +2230,8 @@ const storeTraps = {
|
|
|
2169
2230
|
}
|
|
2170
2231
|
if (strictRead && typeof property === "string")
|
|
2171
2232
|
console.warn(
|
|
2172
|
-
`Reactive value read
|
|
2173
|
-
`Move it into a tracking scope (JSX,
|
|
2233
|
+
`Reactive value read directly in ${strictRead} will not update. ` +
|
|
2234
|
+
`Move it into a tracking scope (JSX, a memo, or an effect's compute function).`
|
|
2174
2235
|
);
|
|
2175
2236
|
return isWrappable(value) ? wrap(value, target) : value;
|
|
2176
2237
|
},
|
|
@@ -2207,7 +2268,11 @@ const storeTraps = {
|
|
|
2207
2268
|
untrack(() => {
|
|
2208
2269
|
const state = target[STORE_VALUE];
|
|
2209
2270
|
const base = state[property];
|
|
2210
|
-
if (
|
|
2271
|
+
if (
|
|
2272
|
+
snapshotCaptureActive &&
|
|
2273
|
+
typeof property !== "symbol" &&
|
|
2274
|
+
!((target[STORE_FIREWALL]?._statusFlags ?? 0) & STATUS_PENDING)
|
|
2275
|
+
) {
|
|
2211
2276
|
if (!target[STORE_SNAPSHOT_PROPS]) {
|
|
2212
2277
|
target[STORE_SNAPSHOT_PROPS] = Object.create(null);
|
|
2213
2278
|
snapshotSources?.add(target);
|
|
@@ -2234,11 +2299,6 @@ const storeTraps = {
|
|
|
2234
2299
|
if (value !== undefined && value === base) delete target[overrideKey][property];
|
|
2235
2300
|
else (target[overrideKey] || (target[overrideKey] = Object.create(null)))[property] = value;
|
|
2236
2301
|
const wrappable = isWrappable(value);
|
|
2237
|
-
if (isWrappable(prev)) {
|
|
2238
|
-
const parents = PARENTS.get(prev);
|
|
2239
|
-
parents && (parents instanceof Set ? parents.delete(store) : PARENTS.delete(prev));
|
|
2240
|
-
}
|
|
2241
|
-
if (recursivelyNotify(store, storeLookup) && wrappable) recursivelyAddParent(value, store);
|
|
2242
2302
|
target[STORE_HAS]?.[property] && setSignal(target[STORE_HAS][property], true);
|
|
2243
2303
|
const nodes = getNodes(target, STORE_NODE);
|
|
2244
2304
|
nodes[property] &&
|
|
@@ -2278,10 +2338,6 @@ const storeTraps = {
|
|
|
2278
2338
|
} else if (target[overrideKey] && property in target[overrideKey]) {
|
|
2279
2339
|
delete target[overrideKey][property];
|
|
2280
2340
|
} else return true;
|
|
2281
|
-
if (isWrappable(prev)) {
|
|
2282
|
-
const parents = PARENTS.get(prev);
|
|
2283
|
-
parents && (parents instanceof Set ? parents.delete(target) : PARENTS.delete(prev));
|
|
2284
|
-
}
|
|
2285
2341
|
if (target[STORE_HAS]?.[property]) setSignal(target[STORE_HAS][property], false);
|
|
2286
2342
|
const nodes = getNodes(target, STORE_NODE);
|
|
2287
2343
|
nodes[property] && setSignal(nodes[property], undefined);
|
|
@@ -2352,59 +2408,6 @@ function createStore(first, second, options) {
|
|
|
2352
2408
|
wrappedStore = derived ? createProjectionInternal(first, second, options).store : wrap(first);
|
|
2353
2409
|
return [wrappedStore, fn => storeSetter(wrappedStore, fn)];
|
|
2354
2410
|
}
|
|
2355
|
-
function recursivelyNotify(state, lookup) {
|
|
2356
|
-
let target = state[$TARGET] || lookup?.get(state)?.[$TARGET];
|
|
2357
|
-
let notified = false;
|
|
2358
|
-
if (target) {
|
|
2359
|
-
const deep = getNodes(target, STORE_NODE)[$DEEP];
|
|
2360
|
-
if (deep) {
|
|
2361
|
-
setSignal(deep, undefined);
|
|
2362
|
-
notified = true;
|
|
2363
|
-
}
|
|
2364
|
-
lookup = target[STORE_LOOKUP] || lookup;
|
|
2365
|
-
}
|
|
2366
|
-
const parents = PARENTS.get(target?.[STORE_VALUE] || state);
|
|
2367
|
-
if (!parents) return notified;
|
|
2368
|
-
if (parents instanceof Set) {
|
|
2369
|
-
for (let parent of parents) notified = recursivelyNotify(parent, lookup) || notified;
|
|
2370
|
-
} else notified = recursivelyNotify(parents, lookup) || notified;
|
|
2371
|
-
return notified;
|
|
2372
|
-
}
|
|
2373
|
-
function recursivelyAddParent(state, parent) {
|
|
2374
|
-
let override;
|
|
2375
|
-
const target = state[$TARGET];
|
|
2376
|
-
if (target) {
|
|
2377
|
-
override = target[STORE_OVERRIDE];
|
|
2378
|
-
state = target[STORE_VALUE];
|
|
2379
|
-
}
|
|
2380
|
-
if (parent) {
|
|
2381
|
-
let parents = PARENTS.get(state);
|
|
2382
|
-
if (!parents) PARENTS.set(state, parent);
|
|
2383
|
-
else if (parents !== parent) {
|
|
2384
|
-
if (!(parents instanceof Set)) PARENTS.set(state, (parents = new Set([parents])));
|
|
2385
|
-
else if (parents.has(parent)) return;
|
|
2386
|
-
parents.add(parent);
|
|
2387
|
-
} else return;
|
|
2388
|
-
}
|
|
2389
|
-
if (Array.isArray(state)) {
|
|
2390
|
-
const len = override?.length || state.length;
|
|
2391
|
-
for (let i = 0; i < len; i++) {
|
|
2392
|
-
const item = override && i in override ? override[i] : state[i];
|
|
2393
|
-
isWrappable(item) && recursivelyAddParent(item, state);
|
|
2394
|
-
}
|
|
2395
|
-
} else {
|
|
2396
|
-
const keys = getKeys(state, override);
|
|
2397
|
-
for (let i = 0; i < keys.length; i++) {
|
|
2398
|
-
const key = keys[i];
|
|
2399
|
-
const item = override && key in override ? override[key] : state[key];
|
|
2400
|
-
isWrappable(item) && recursivelyAddParent(item, state);
|
|
2401
|
-
}
|
|
2402
|
-
}
|
|
2403
|
-
}
|
|
2404
|
-
function deep(store) {
|
|
2405
|
-
recursivelyAddParent(store);
|
|
2406
|
-
return store[$DEEP];
|
|
2407
|
-
}
|
|
2408
2411
|
function createOptimisticStore(first, second, options) {
|
|
2409
2412
|
GlobalQueue._clearOptimisticStore ||= clearOptimisticStore;
|
|
2410
2413
|
const derived = typeof first === "function";
|
|
@@ -2475,14 +2478,14 @@ function createOptimisticProjectionInternal(fn, initialValue = {}, options) {
|
|
|
2475
2478
|
try {
|
|
2476
2479
|
value !== s &&
|
|
2477
2480
|
value !== undefined &&
|
|
2478
|
-
storeSetter(wrappedStore, reconcile(value, options?.key || "id"
|
|
2481
|
+
storeSetter(wrappedStore, reconcile(value, options?.key || "id"));
|
|
2479
2482
|
} finally {
|
|
2480
2483
|
setProjectionWriteActive(false);
|
|
2481
2484
|
}
|
|
2482
2485
|
});
|
|
2483
2486
|
value !== s &&
|
|
2484
2487
|
value !== undefined &&
|
|
2485
|
-
reconcile(value, options?.key || "id"
|
|
2488
|
+
reconcile(value, options?.key || "id")(wrappedStore);
|
|
2486
2489
|
});
|
|
2487
2490
|
} finally {
|
|
2488
2491
|
setProjectionWriteActive(false);
|
|
@@ -2557,12 +2560,13 @@ const storePath = Object.assign(
|
|
|
2557
2560
|
},
|
|
2558
2561
|
{ DELETE: DELETE }
|
|
2559
2562
|
);
|
|
2560
|
-
function
|
|
2563
|
+
function snapshotImpl(item, track, map, lookup) {
|
|
2561
2564
|
let target, isArray, override, result, unwrapped, v;
|
|
2562
2565
|
if (!isWrappable(item)) return item;
|
|
2563
2566
|
if (map && map.has(item)) return map.get(item);
|
|
2564
2567
|
if (!map) map = new Map();
|
|
2565
2568
|
if ((target = item[$TARGET] || lookup?.get(item)?.[$TARGET])) {
|
|
2569
|
+
if (track) trackSelf(target, $TRACK);
|
|
2566
2570
|
override = target[STORE_OVERRIDE];
|
|
2567
2571
|
isArray = Array.isArray(target[STORE_VALUE]);
|
|
2568
2572
|
map.set(
|
|
@@ -2582,7 +2586,8 @@ function snapshot(item, map, lookup) {
|
|
|
2582
2586
|
for (let i = 0; i < len; i++) {
|
|
2583
2587
|
v = override && i in override ? override[i] : item[i];
|
|
2584
2588
|
if (v === $DELETED) continue;
|
|
2585
|
-
if (
|
|
2589
|
+
if (track && isWrappable(v)) wrap(v, target);
|
|
2590
|
+
if ((unwrapped = snapshotImpl(v, track, map, lookup)) !== v || result) {
|
|
2586
2591
|
if (!result) map.set(item, (result = [...item]));
|
|
2587
2592
|
result[i] = unwrapped;
|
|
2588
2593
|
}
|
|
@@ -2594,7 +2599,8 @@ function snapshot(item, map, lookup) {
|
|
|
2594
2599
|
const desc = getPropertyDescriptor(item, override, prop);
|
|
2595
2600
|
if (desc.get) continue;
|
|
2596
2601
|
v = override && prop in override ? override[prop] : item[prop];
|
|
2597
|
-
if (
|
|
2602
|
+
if (track && isWrappable(v)) wrap(v, target);
|
|
2603
|
+
if ((unwrapped = snapshotImpl(v, track, map, lookup)) !== item[prop] || result) {
|
|
2598
2604
|
if (!result) {
|
|
2599
2605
|
result = Object.create(Object.getPrototypeOf(item));
|
|
2600
2606
|
Object.assign(result, item);
|
|
@@ -2605,6 +2611,12 @@ function snapshot(item, map, lookup) {
|
|
|
2605
2611
|
}
|
|
2606
2612
|
return result || item;
|
|
2607
2613
|
}
|
|
2614
|
+
function snapshot(item, map, lookup) {
|
|
2615
|
+
return snapshotImpl(item, false, map, lookup);
|
|
2616
|
+
}
|
|
2617
|
+
function deep(store) {
|
|
2618
|
+
return snapshotImpl(store, true);
|
|
2619
|
+
}
|
|
2608
2620
|
function trueFn() {
|
|
2609
2621
|
return true;
|
|
2610
2622
|
}
|
|
@@ -2780,15 +2792,15 @@ function updateKeyedMap() {
|
|
|
2780
2792
|
this._rows[j] = signal(newItems[j], pureOptions);
|
|
2781
2793
|
this._indexes && (this._indexes[j] = signal(j, pureOptions));
|
|
2782
2794
|
return this._map(
|
|
2783
|
-
|
|
2784
|
-
this._indexes ?
|
|
2795
|
+
accessor(this._rows[j]),
|
|
2796
|
+
this._indexes ? accessor(this._indexes[j]) : undefined
|
|
2785
2797
|
);
|
|
2786
2798
|
}
|
|
2787
2799
|
: this._indexes
|
|
2788
2800
|
? () => {
|
|
2789
2801
|
const item = newItems[j];
|
|
2790
2802
|
this._indexes[j] = signal(j, pureOptions);
|
|
2791
|
-
return this._map(() => item,
|
|
2803
|
+
return this._map(() => item, accessor(this._indexes[j]));
|
|
2792
2804
|
}
|
|
2793
2805
|
: () => {
|
|
2794
2806
|
const item = newItems[j];
|
|
@@ -2992,11 +3004,14 @@ function createBoundChildren(owner, fn, queue, mask) {
|
|
|
2992
3004
|
return boundaryComputed(() => staleValues(() => flatten(read(c))), mask);
|
|
2993
3005
|
});
|
|
2994
3006
|
}
|
|
3007
|
+
const ON_INIT = Symbol();
|
|
2995
3008
|
class CollectionQueue extends Queue {
|
|
2996
3009
|
_collectionType;
|
|
2997
3010
|
_sources = new Set();
|
|
2998
3011
|
_disabled = signal(false, { pureWrite: true });
|
|
2999
3012
|
_initialized = false;
|
|
3013
|
+
_onFn;
|
|
3014
|
+
_prevOn = ON_INIT;
|
|
3000
3015
|
constructor(type) {
|
|
3001
3016
|
super();
|
|
3002
3017
|
this._collectionType = type;
|
|
@@ -3006,10 +3021,22 @@ class CollectionQueue extends Queue {
|
|
|
3006
3021
|
return super.run(type);
|
|
3007
3022
|
}
|
|
3008
3023
|
notify(node, type, flags, error) {
|
|
3009
|
-
if (
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3024
|
+
if (!(type & this._collectionType)) return super.notify(node, type, flags, error);
|
|
3025
|
+
if (this._initialized && this._onFn) {
|
|
3026
|
+
const currentOn = untrack(() => {
|
|
3027
|
+
try {
|
|
3028
|
+
return this._onFn();
|
|
3029
|
+
} catch {
|
|
3030
|
+
return ON_INIT;
|
|
3031
|
+
}
|
|
3032
|
+
});
|
|
3033
|
+
if (currentOn !== this._prevOn) {
|
|
3034
|
+
this._prevOn = currentOn;
|
|
3035
|
+
this._initialized = false;
|
|
3036
|
+
this._sources.clear();
|
|
3037
|
+
}
|
|
3038
|
+
}
|
|
3039
|
+
if (this._collectionType & STATUS_PENDING && this._initialized)
|
|
3013
3040
|
return super.notify(node, type, flags, error);
|
|
3014
3041
|
if (flags & this._collectionType) {
|
|
3015
3042
|
const source = error?.source || node._error?.source;
|
|
@@ -3026,12 +3053,20 @@ class CollectionQueue extends Queue {
|
|
|
3026
3053
|
for (const source of this._sources) {
|
|
3027
3054
|
if (!(source._statusFlags & this._collectionType)) this._sources.delete(source);
|
|
3028
3055
|
}
|
|
3029
|
-
if (!this._sources.size)
|
|
3056
|
+
if (!this._sources.size) {
|
|
3057
|
+
setSignal(this._disabled, false);
|
|
3058
|
+
if (this._onFn) {
|
|
3059
|
+
try {
|
|
3060
|
+
this._prevOn = untrack(() => this._onFn());
|
|
3061
|
+
} catch {}
|
|
3062
|
+
}
|
|
3063
|
+
}
|
|
3030
3064
|
}
|
|
3031
3065
|
}
|
|
3032
|
-
function createCollectionBoundary(type, fn, fallback) {
|
|
3066
|
+
function createCollectionBoundary(type, fn, fallback, onFn) {
|
|
3033
3067
|
const owner = createOwner();
|
|
3034
3068
|
const queue = new CollectionQueue(type);
|
|
3069
|
+
if (onFn) queue._onFn = onFn;
|
|
3035
3070
|
const tree = createBoundChildren(owner, fn, queue, type);
|
|
3036
3071
|
const decision = computed(() => {
|
|
3037
3072
|
if (!read(queue._disabled)) {
|
|
@@ -3043,10 +3078,10 @@ function createCollectionBoundary(type, fn, fallback) {
|
|
|
3043
3078
|
}
|
|
3044
3079
|
return fallback(queue);
|
|
3045
3080
|
});
|
|
3046
|
-
return
|
|
3081
|
+
return accessor(decision);
|
|
3047
3082
|
}
|
|
3048
|
-
function
|
|
3049
|
-
return createCollectionBoundary(STATUS_PENDING, fn, () => fallback());
|
|
3083
|
+
function createLoadingBoundary(fn, fallback, options) {
|
|
3084
|
+
return createCollectionBoundary(STATUS_PENDING, fn, () => fallback(), options?.on);
|
|
3050
3085
|
}
|
|
3051
3086
|
function createErrorBoundary(fn, fallback) {
|
|
3052
3087
|
return createCollectionBoundary(STATUS_ERROR, fn, queue => {
|
|
@@ -3128,7 +3163,7 @@ export {
|
|
|
3128
3163
|
createContext,
|
|
3129
3164
|
createEffect,
|
|
3130
3165
|
createErrorBoundary,
|
|
3131
|
-
|
|
3166
|
+
createLoadingBoundary,
|
|
3132
3167
|
createMemo,
|
|
3133
3168
|
createOptimistic,
|
|
3134
3169
|
createOptimisticStore,
|
|
@@ -3141,6 +3176,8 @@ export {
|
|
|
3141
3176
|
createStore,
|
|
3142
3177
|
createTrackedEffect,
|
|
3143
3178
|
deep,
|
|
3179
|
+
enableExternalSource,
|
|
3180
|
+
enforceLoadingBoundary,
|
|
3144
3181
|
flatten,
|
|
3145
3182
|
flush,
|
|
3146
3183
|
getContext,
|
|
@@ -3167,7 +3204,6 @@ export {
|
|
|
3167
3204
|
resolve,
|
|
3168
3205
|
runWithOwner,
|
|
3169
3206
|
setContext,
|
|
3170
|
-
setOnUnhandledAsync,
|
|
3171
3207
|
setSnapshotCapture,
|
|
3172
3208
|
snapshot,
|
|
3173
3209
|
storePath,
|