@solidjs/signals 0.12.0 → 0.13.1
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 +228 -184
- package/dist/node.cjs +902 -873
- package/dist/prod.js +787 -753
- 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,46 @@ 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) {
|
|
402
|
+
const _src = n._error?.source;
|
|
403
|
+
if (_src && !(_src._statusFlags & STATUS_PENDING)) {
|
|
404
|
+
n._statusFlags &= -6;
|
|
405
|
+
n._error = null;
|
|
406
|
+
}
|
|
407
|
+
} else n._statusFlags &= ~STATUS_UNINITIALIZED;
|
|
408
|
+
if (n._fn) GlobalQueue._dispose(n, false, true);
|
|
409
|
+
}
|
|
410
|
+
pendingNodes.length = 0;
|
|
411
|
+
}
|
|
390
412
|
function finalizePureQueue(completingTransition = null, incomplete = false) {
|
|
391
413
|
let resolvePending = !incomplete;
|
|
414
|
+
if (resolvePending) commitPendingNodes();
|
|
392
415
|
if (!incomplete) checkBoundaryChildren(globalQueue);
|
|
393
416
|
if (dirtyQueue._max >= dirtyQueue._min) runHeap(dirtyQueue, GlobalQueue._update);
|
|
394
417
|
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;
|
|
418
|
+
commitPendingNodes();
|
|
407
419
|
const optimisticNodes = completingTransition
|
|
408
420
|
? completingTransition._optimisticNodes
|
|
409
421
|
: globalQueue._optimisticNodes;
|
|
410
422
|
for (let i = 0; i < optimisticNodes.length; i++) {
|
|
411
423
|
const n = optimisticNodes[i];
|
|
412
|
-
const original = n._pendingValue;
|
|
413
424
|
n._optimisticLane = undefined;
|
|
414
|
-
if (
|
|
415
|
-
n._value =
|
|
416
|
-
|
|
425
|
+
if (n._pendingValue !== NOT_PENDING) {
|
|
426
|
+
n._value = n._pendingValue;
|
|
427
|
+
n._pendingValue = NOT_PENDING;
|
|
417
428
|
}
|
|
418
|
-
|
|
429
|
+
const prevOverride = n._overrideValue;
|
|
430
|
+
n._overrideValue = NOT_PENDING;
|
|
431
|
+
if (prevOverride !== NOT_PENDING && n._value !== prevOverride) insertSubs(n, true);
|
|
419
432
|
n._transition = null;
|
|
420
433
|
}
|
|
421
434
|
optimisticNodes.length = 0;
|
|
@@ -522,7 +535,7 @@ function getOrCreateLane(signal) {
|
|
|
522
535
|
};
|
|
523
536
|
signalLanes.set(signal, lane);
|
|
524
537
|
activeLanes.add(lane);
|
|
525
|
-
signal.
|
|
538
|
+
signal._overrideSinceLane = false;
|
|
526
539
|
return lane;
|
|
527
540
|
}
|
|
528
541
|
function findLane(lane) {
|
|
@@ -548,7 +561,7 @@ function resolveLane(el) {
|
|
|
548
561
|
return undefined;
|
|
549
562
|
}
|
|
550
563
|
function hasActiveOverride(el) {
|
|
551
|
-
return !!(el.
|
|
564
|
+
return !!(el._overrideValue !== undefined && el._overrideValue !== NOT_PENDING);
|
|
552
565
|
}
|
|
553
566
|
function assignOrMergeLane(el, sourceLane) {
|
|
554
567
|
const sourceRoot = findLane(sourceLane);
|
|
@@ -595,10 +608,10 @@ function handleAsync(el, result, setter) {
|
|
|
595
608
|
const lane = resolveLane(el);
|
|
596
609
|
if (lane) lane._pendingAsync.delete(el);
|
|
597
610
|
if (setter) setter(value);
|
|
598
|
-
else if (el.
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
611
|
+
else if (el._overrideValue !== undefined) {
|
|
612
|
+
if (el._overrideValue !== undefined && el._overrideValue !== NOT_PENDING)
|
|
613
|
+
el._pendingValue = value;
|
|
614
|
+
else {
|
|
602
615
|
el._value = value;
|
|
603
616
|
insertSubs(el);
|
|
604
617
|
}
|
|
@@ -693,7 +706,8 @@ function notifyStatus(el, status, error, blockStatus, lane) {
|
|
|
693
706
|
)
|
|
694
707
|
error = new StatusError(el, error);
|
|
695
708
|
const isSource = error instanceof NotReadyError && error.source === el;
|
|
696
|
-
const isOptimisticBoundary =
|
|
709
|
+
const isOptimisticBoundary =
|
|
710
|
+
status === STATUS_PENDING && el._overrideValue !== undefined && !isSource;
|
|
697
711
|
const startsBlocking = isOptimisticBoundary && hasActiveOverride(el);
|
|
698
712
|
if (!blockStatus) {
|
|
699
713
|
el._statusFlags =
|
|
@@ -844,7 +858,6 @@ function disposeChildren(node, self = false, zombie) {
|
|
|
844
858
|
node._pendingFirstChild = null;
|
|
845
859
|
} else {
|
|
846
860
|
node._firstChild = null;
|
|
847
|
-
node._nextSibling = null;
|
|
848
861
|
node._childCount = 0;
|
|
849
862
|
}
|
|
850
863
|
runDisposal(node, zombie);
|
|
@@ -978,8 +991,14 @@ function effect(compute, effect, error, initialValue, options) {
|
|
|
978
991
|
}
|
|
979
992
|
}
|
|
980
993
|
if (!node._queue.notify(node, STATUS_ERROR, STATUS_ERROR)) throw err;
|
|
981
|
-
} else if (node._type === EFFECT_RENDER)
|
|
994
|
+
} else if (node._type === EFFECT_RENDER) {
|
|
982
995
|
node._queue.notify(node, STATUS_PENDING | STATUS_ERROR, actualStatus, actualError);
|
|
996
|
+
if (_hitUnhandledAsync) {
|
|
997
|
+
resetUnhandledAsync();
|
|
998
|
+
const err = new Error("An async value must be rendered inside a Loading boundary.");
|
|
999
|
+
if (!node._queue.notify(node, STATUS_ERROR, STATUS_ERROR)) throw err;
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
983
1002
|
};
|
|
984
1003
|
recompute(node, true);
|
|
985
1004
|
!options?.defer &&
|
|
@@ -993,6 +1012,10 @@ function effect(compute, effect, error, initialValue, options) {
|
|
|
993
1012
|
}
|
|
994
1013
|
function runEffect() {
|
|
995
1014
|
if (!this._modified || this._flags & REACTIVE_DISPOSED) return;
|
|
1015
|
+
let prevStrictRead = false;
|
|
1016
|
+
{
|
|
1017
|
+
prevStrictRead = setStrictRead("an effect callback");
|
|
1018
|
+
}
|
|
996
1019
|
this._cleanup?.();
|
|
997
1020
|
this._cleanup = undefined;
|
|
998
1021
|
try {
|
|
@@ -1000,6 +1023,7 @@ function runEffect() {
|
|
|
1000
1023
|
} catch (error) {
|
|
1001
1024
|
if (!this._queue.notify(this, STATUS_ERROR, STATUS_ERROR)) throw error;
|
|
1002
1025
|
} finally {
|
|
1026
|
+
setStrictRead(prevStrictRead);
|
|
1003
1027
|
this._prevValue = this._value;
|
|
1004
1028
|
this._modified = false;
|
|
1005
1029
|
}
|
|
@@ -1033,6 +1057,29 @@ function trackedEffect(fn, options) {
|
|
|
1033
1057
|
if (!node._parent)
|
|
1034
1058
|
console.warn("Effects created outside a reactive context will never be disposed");
|
|
1035
1059
|
}
|
|
1060
|
+
let externalSourceConfig = null;
|
|
1061
|
+
function enableExternalSource(config) {
|
|
1062
|
+
const { factory: factory, untrack: untrackFn = fn => fn() } = config;
|
|
1063
|
+
if (externalSourceConfig) {
|
|
1064
|
+
const { factory: oldFactory, untrack: oldUntrack } = externalSourceConfig;
|
|
1065
|
+
externalSourceConfig = {
|
|
1066
|
+
factory: (fn, trigger) => {
|
|
1067
|
+
const oldSource = oldFactory(fn, trigger);
|
|
1068
|
+
const source = factory(x => oldSource.track(x), trigger);
|
|
1069
|
+
return {
|
|
1070
|
+
track: x => source.track(x),
|
|
1071
|
+
dispose() {
|
|
1072
|
+
source.dispose();
|
|
1073
|
+
oldSource.dispose();
|
|
1074
|
+
}
|
|
1075
|
+
};
|
|
1076
|
+
},
|
|
1077
|
+
untrack: fn => oldUntrack(() => untrackFn(fn))
|
|
1078
|
+
};
|
|
1079
|
+
} else {
|
|
1080
|
+
externalSourceConfig = { factory: factory, untrack: untrackFn };
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1036
1083
|
GlobalQueue._update = recompute;
|
|
1037
1084
|
GlobalQueue._dispose = disposeChildren;
|
|
1038
1085
|
let tracking = false;
|
|
@@ -1112,7 +1159,7 @@ function recompute(el, create = false) {
|
|
|
1112
1159
|
}
|
|
1113
1160
|
}
|
|
1114
1161
|
const isOptimisticDirty = !!(el._flags & REACTIVE_OPTIMISTIC_DIRTY);
|
|
1115
|
-
const hasOverride =
|
|
1162
|
+
const hasOverride = el._overrideValue !== undefined && el._overrideValue !== NOT_PENDING;
|
|
1116
1163
|
const wasPending = !!(el._statusFlags & STATUS_PENDING);
|
|
1117
1164
|
const oldcontext = context;
|
|
1118
1165
|
context = el;
|
|
@@ -1174,24 +1221,24 @@ function recompute(el, create = false) {
|
|
|
1174
1221
|
else el._deps = null;
|
|
1175
1222
|
}
|
|
1176
1223
|
const compareValue = hasOverride
|
|
1177
|
-
? el.
|
|
1224
|
+
? el._overrideValue
|
|
1178
1225
|
: el._pendingValue === NOT_PENDING
|
|
1179
1226
|
? el._value
|
|
1180
1227
|
: el._pendingValue;
|
|
1181
1228
|
const valueChanged = !el._equals || !el._equals(compareValue, value);
|
|
1182
1229
|
if (valueChanged) {
|
|
1183
|
-
const prevVisible = hasOverride ? el.
|
|
1184
|
-
if (create || (isEffect && activeTransition !== el._transition) || isOptimisticDirty)
|
|
1230
|
+
const prevVisible = hasOverride ? el._overrideValue : undefined;
|
|
1231
|
+
if (create || (isEffect && activeTransition !== el._transition) || isOptimisticDirty) {
|
|
1185
1232
|
el._value = value;
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1233
|
+
if (hasOverride && isOptimisticDirty) {
|
|
1234
|
+
el._overrideValue = value;
|
|
1235
|
+
el._pendingValue = value;
|
|
1236
|
+
}
|
|
1237
|
+
} else el._pendingValue = value;
|
|
1238
|
+
if (hasOverride && !isOptimisticDirty && wasPending && !el._overrideSinceLane)
|
|
1239
|
+
el._overrideValue = value;
|
|
1240
|
+
if (!hasOverride || isOptimisticDirty || el._overrideValue !== prevVisible)
|
|
1193
1241
|
insertSubs(el, isOptimisticDirty || hasOverride);
|
|
1194
|
-
}
|
|
1195
1242
|
} else if (hasOverride) {
|
|
1196
1243
|
el._pendingValue = value;
|
|
1197
1244
|
} else if (el._height != oldHeight) {
|
|
@@ -1203,7 +1250,7 @@ function recompute(el, create = false) {
|
|
|
1203
1250
|
currentOptimisticLane = prevLane;
|
|
1204
1251
|
(!create || el._statusFlags & STATUS_PENDING) &&
|
|
1205
1252
|
!el._transition &&
|
|
1206
|
-
!(activeTransition &&
|
|
1253
|
+
!(activeTransition && hasOverride) &&
|
|
1207
1254
|
globalQueue._pendingNodes.push(el);
|
|
1208
1255
|
el._transition &&
|
|
1209
1256
|
isEffect &&
|
|
@@ -1284,6 +1331,17 @@ function computed(fn, initialValue, options) {
|
|
|
1284
1331
|
}
|
|
1285
1332
|
if (parent) self._height = parent._height + 1;
|
|
1286
1333
|
if (snapshotCaptureActive && ownerInSnapshotScope(context)) self._inSnapshotScope = true;
|
|
1334
|
+
if (externalSourceConfig) {
|
|
1335
|
+
const bridgeSignal = signal(undefined, { equals: false, pureWrite: true });
|
|
1336
|
+
const source = externalSourceConfig.factory(self._fn, () => {
|
|
1337
|
+
setSignal(bridgeSignal, undefined);
|
|
1338
|
+
});
|
|
1339
|
+
onCleanup(() => source.dispose());
|
|
1340
|
+
self._fn = prev => {
|
|
1341
|
+
read(bridgeSignal);
|
|
1342
|
+
return source.track(prev);
|
|
1343
|
+
};
|
|
1344
|
+
}
|
|
1287
1345
|
!options?.lazy && recompute(self, true);
|
|
1288
1346
|
if (snapshotCaptureActive && !options?.lazy) {
|
|
1289
1347
|
if (!(self._statusFlags & STATUS_PENDING)) {
|
|
@@ -1308,7 +1366,7 @@ function signal(v, options, firewall = null) {
|
|
|
1308
1366
|
};
|
|
1309
1367
|
s._name = options?.name ?? "signal";
|
|
1310
1368
|
firewall && (firewall._child = s);
|
|
1311
|
-
if (snapshotCaptureActive && !s._pureWrite) {
|
|
1369
|
+
if (snapshotCaptureActive && !s._pureWrite && !((firewall?._statusFlags ?? 0) & STATUS_PENDING)) {
|
|
1312
1370
|
s._snapshotValue = v === undefined ? NO_SNAPSHOT : v;
|
|
1313
1371
|
snapshotSources.add(s);
|
|
1314
1372
|
}
|
|
@@ -1316,12 +1374,12 @@ function signal(v, options, firewall = null) {
|
|
|
1316
1374
|
}
|
|
1317
1375
|
function optimisticSignal(v, options) {
|
|
1318
1376
|
const s = signal(v, options);
|
|
1319
|
-
s.
|
|
1377
|
+
s._overrideValue = NOT_PENDING;
|
|
1320
1378
|
return s;
|
|
1321
1379
|
}
|
|
1322
1380
|
function optimisticComputed(fn, initialValue, options) {
|
|
1323
1381
|
const c = computed(fn, initialValue, options);
|
|
1324
|
-
c.
|
|
1382
|
+
c._overrideValue = NOT_PENDING;
|
|
1325
1383
|
return c;
|
|
1326
1384
|
}
|
|
1327
1385
|
function isEqual(a, b) {
|
|
@@ -1334,12 +1392,13 @@ function setStrictRead(v) {
|
|
|
1334
1392
|
return prev;
|
|
1335
1393
|
}
|
|
1336
1394
|
function untrack(fn, strictReadLabel) {
|
|
1337
|
-
if (!tracking && !strictRead && !strictReadLabel) return fn();
|
|
1395
|
+
if (!externalSourceConfig && !tracking && !strictRead && !strictReadLabel) return fn();
|
|
1338
1396
|
const prevTracking = tracking;
|
|
1339
1397
|
const prevStrictRead = strictRead;
|
|
1340
1398
|
tracking = false;
|
|
1341
1399
|
strictRead = strictReadLabel || false;
|
|
1342
1400
|
try {
|
|
1401
|
+
if (externalSourceConfig) return externalSourceConfig.untrack(fn);
|
|
1343
1402
|
return fn();
|
|
1344
1403
|
} finally {
|
|
1345
1404
|
tracking = prevTracking;
|
|
@@ -1351,21 +1410,25 @@ function read(el) {
|
|
|
1351
1410
|
const pendingComputed = getLatestValueComputed(el);
|
|
1352
1411
|
const prevPending = latestReadActive;
|
|
1353
1412
|
latestReadActive = false;
|
|
1413
|
+
const visibleValue =
|
|
1414
|
+
el._overrideValue !== undefined && el._overrideValue !== NOT_PENDING
|
|
1415
|
+
? el._overrideValue
|
|
1416
|
+
: el._value;
|
|
1354
1417
|
let value;
|
|
1355
1418
|
try {
|
|
1356
1419
|
value = read(pendingComputed);
|
|
1357
1420
|
} catch (e) {
|
|
1358
|
-
if (!context && e instanceof NotReadyError) return
|
|
1421
|
+
if (!context && e instanceof NotReadyError) return visibleValue;
|
|
1359
1422
|
throw e;
|
|
1360
1423
|
} finally {
|
|
1361
1424
|
latestReadActive = prevPending;
|
|
1362
1425
|
}
|
|
1363
|
-
if (pendingComputed._statusFlags & STATUS_PENDING) return
|
|
1426
|
+
if (pendingComputed._statusFlags & STATUS_PENDING) return visibleValue;
|
|
1364
1427
|
if (stale && currentOptimisticLane && pendingComputed._optimisticLane) {
|
|
1365
1428
|
const pcLane = findLane(pendingComputed._optimisticLane);
|
|
1366
1429
|
const curLane = findLane(currentOptimisticLane);
|
|
1367
1430
|
if (pcLane !== curLane && pcLane._pendingAsync.size > 0) {
|
|
1368
|
-
return
|
|
1431
|
+
return visibleValue;
|
|
1369
1432
|
}
|
|
1370
1433
|
}
|
|
1371
1434
|
return value;
|
|
@@ -1391,8 +1454,8 @@ function read(el) {
|
|
|
1391
1454
|
const owner = el._firewall || el;
|
|
1392
1455
|
if (strictRead && owner._statusFlags & STATUS_PENDING) {
|
|
1393
1456
|
throw new Error(
|
|
1394
|
-
`Reading a pending async value in ${strictRead}. ` +
|
|
1395
|
-
`Async values must be read within a tracking scope (JSX,
|
|
1457
|
+
`Reading a pending async value directly in ${strictRead}. ` +
|
|
1458
|
+
`Async values must be read within a tracking scope (JSX, a memo, or an effect's compute function).`
|
|
1396
1459
|
);
|
|
1397
1460
|
}
|
|
1398
1461
|
if (c && tracking) {
|
|
@@ -1412,16 +1475,18 @@ function read(el) {
|
|
|
1412
1475
|
}
|
|
1413
1476
|
}
|
|
1414
1477
|
if (owner._statusFlags & STATUS_PENDING) {
|
|
1415
|
-
|
|
1478
|
+
const _errSource = owner._error?.source;
|
|
1479
|
+
if (_errSource && !(_errSource._statusFlags & STATUS_PENDING)) clearStatus(owner);
|
|
1480
|
+
else if (c && !(stale && owner._transition && activeTransition !== owner._transition)) {
|
|
1416
1481
|
if (currentOptimisticLane) {
|
|
1417
1482
|
const pendingLane = owner._optimisticLane;
|
|
1418
1483
|
const lane = findLane(currentOptimisticLane);
|
|
1419
1484
|
if (pendingLane && findLane(pendingLane) === lane && !hasActiveOverride(owner)) {
|
|
1420
|
-
if (!tracking) link(el, c);
|
|
1485
|
+
if (!tracking && el !== c) link(el, c);
|
|
1421
1486
|
throw owner._error;
|
|
1422
1487
|
}
|
|
1423
1488
|
} else {
|
|
1424
|
-
if (!tracking) link(el, c);
|
|
1489
|
+
if (!tracking && el !== c) link(el, c);
|
|
1425
1490
|
throw owner._error;
|
|
1426
1491
|
}
|
|
1427
1492
|
} else if (!c && owner._statusFlags & STATUS_UNINITIALIZED) {
|
|
@@ -1445,12 +1510,14 @@ function read(el) {
|
|
|
1445
1510
|
}
|
|
1446
1511
|
if (strictRead)
|
|
1447
1512
|
console.warn(
|
|
1448
|
-
`Reactive value read
|
|
1449
|
-
`Move it into a tracking scope (JSX,
|
|
1513
|
+
`Reactive value read directly in ${strictRead} will not update. ` +
|
|
1514
|
+
`Move it into a tracking scope (JSX, a memo, or an effect's compute function).`
|
|
1450
1515
|
);
|
|
1516
|
+
if (el._overrideValue !== undefined && el._overrideValue !== NOT_PENDING)
|
|
1517
|
+
return el._overrideValue;
|
|
1451
1518
|
return !c ||
|
|
1452
1519
|
(currentOptimisticLane !== null &&
|
|
1453
|
-
(el.
|
|
1520
|
+
(el._overrideValue !== undefined ||
|
|
1454
1521
|
el._optimisticLane ||
|
|
1455
1522
|
owner === el ||
|
|
1456
1523
|
!!(owner._statusFlags & STATUS_PENDING))) ||
|
|
@@ -1464,9 +1531,12 @@ function setSignal(el, v) {
|
|
|
1464
1531
|
console.warn("A Signal was written to in an owned scope.");
|
|
1465
1532
|
if (el._transition && activeTransition !== el._transition)
|
|
1466
1533
|
globalQueue.initTransition(el._transition);
|
|
1467
|
-
const isOptimistic = el.
|
|
1534
|
+
const isOptimistic = el._overrideValue !== undefined && !projectionWriteActive;
|
|
1535
|
+
const hasOverride = el._overrideValue !== undefined && el._overrideValue !== NOT_PENDING;
|
|
1468
1536
|
const currentValue = isOptimistic
|
|
1469
|
-
?
|
|
1537
|
+
? hasOverride
|
|
1538
|
+
? el._overrideValue
|
|
1539
|
+
: el._value
|
|
1470
1540
|
: el._pendingValue === NOT_PENDING
|
|
1471
1541
|
? el._value
|
|
1472
1542
|
: el._pendingValue;
|
|
@@ -1474,27 +1544,23 @@ function setSignal(el, v) {
|
|
|
1474
1544
|
const valueChanged =
|
|
1475
1545
|
!el._equals || !el._equals(currentValue, v) || !!(el._statusFlags & STATUS_UNINITIALIZED);
|
|
1476
1546
|
if (!valueChanged) {
|
|
1477
|
-
if (isOptimistic &&
|
|
1547
|
+
if (isOptimistic && hasOverride && el._fn) {
|
|
1478
1548
|
insertSubs(el, true);
|
|
1479
1549
|
schedule();
|
|
1480
1550
|
}
|
|
1481
1551
|
return v;
|
|
1482
1552
|
}
|
|
1483
1553
|
if (isOptimistic) {
|
|
1484
|
-
const
|
|
1485
|
-
if (el._transition
|
|
1486
|
-
|
|
1487
|
-
}
|
|
1488
|
-
if (el._pendingValue === NOT_PENDING) {
|
|
1554
|
+
const firstOverride = el._overrideValue === NOT_PENDING;
|
|
1555
|
+
if (!firstOverride && el._transition) globalQueue.initTransition(el._transition);
|
|
1556
|
+
if (firstOverride) {
|
|
1489
1557
|
el._pendingValue = el._value;
|
|
1490
|
-
}
|
|
1491
|
-
if (!alreadyTracked) {
|
|
1492
1558
|
globalQueue._optimisticNodes.push(el);
|
|
1493
1559
|
}
|
|
1494
|
-
el.
|
|
1560
|
+
el._overrideSinceLane = true;
|
|
1495
1561
|
const lane = getOrCreateLane(el);
|
|
1496
1562
|
el._optimisticLane = lane;
|
|
1497
|
-
el.
|
|
1563
|
+
el._overrideValue = v;
|
|
1498
1564
|
} else {
|
|
1499
1565
|
if (el._pendingValue === NOT_PENDING) globalQueue._pendingNodes.push(el);
|
|
1500
1566
|
el._pendingValue = v;
|
|
@@ -1532,7 +1598,7 @@ function getPendingSignal(el) {
|
|
|
1532
1598
|
}
|
|
1533
1599
|
function computePendingState(el) {
|
|
1534
1600
|
const comp = el;
|
|
1535
|
-
if (el.
|
|
1601
|
+
if (el._overrideValue !== undefined && el._overrideValue !== NOT_PENDING) {
|
|
1536
1602
|
if (comp._statusFlags & STATUS_PENDING && !(comp._statusFlags & STATUS_UNINITIALIZED))
|
|
1537
1603
|
return true;
|
|
1538
1604
|
if (el._parentSource) {
|
|
@@ -1702,17 +1768,22 @@ function action(genFn) {
|
|
|
1702
1768
|
step();
|
|
1703
1769
|
});
|
|
1704
1770
|
}
|
|
1771
|
+
function accessor(node) {
|
|
1772
|
+
const fn = read.bind(null, node);
|
|
1773
|
+
fn.$r = true;
|
|
1774
|
+
return fn;
|
|
1775
|
+
}
|
|
1705
1776
|
function createSignal(first, second, third) {
|
|
1706
1777
|
if (typeof first === "function") {
|
|
1707
1778
|
const node = computed(first, second, third);
|
|
1708
|
-
return [
|
|
1779
|
+
return [accessor(node), setSignal.bind(null, node)];
|
|
1709
1780
|
}
|
|
1710
1781
|
const node = signal(first, second);
|
|
1711
|
-
return [
|
|
1782
|
+
return [accessor(node), setSignal.bind(null, node)];
|
|
1712
1783
|
}
|
|
1713
1784
|
function createMemo(compute, value, options) {
|
|
1714
1785
|
let node = computed(compute, value, options);
|
|
1715
|
-
return
|
|
1786
|
+
return accessor(node);
|
|
1716
1787
|
}
|
|
1717
1788
|
function createEffect(compute, effectFn, value, options) {
|
|
1718
1789
|
effect(compute, effectFn.effect || effectFn, effectFn.error, value, {
|
|
@@ -1769,7 +1840,7 @@ function createOptimistic(first, second, third) {
|
|
|
1769
1840
|
typeof first === "function"
|
|
1770
1841
|
? optimisticComputed(first, second, third)
|
|
1771
1842
|
: optimisticSignal(first, second);
|
|
1772
|
-
return [
|
|
1843
|
+
return [accessor(node), setSignal.bind(null, node)];
|
|
1773
1844
|
}
|
|
1774
1845
|
function onSettled(callback) {
|
|
1775
1846
|
getOwner()
|
|
@@ -1791,7 +1862,7 @@ function getAllKeys(value, override, next) {
|
|
|
1791
1862
|
const nextKeys = Object.keys(next);
|
|
1792
1863
|
return Array.from(new Set([...keys, ...nextKeys]));
|
|
1793
1864
|
}
|
|
1794
|
-
function applyState(next, state, keyFn
|
|
1865
|
+
function applyState(next, state, keyFn) {
|
|
1795
1866
|
const target = state?.[$TARGET];
|
|
1796
1867
|
if (!target) return;
|
|
1797
1868
|
const previous = target[STORE_VALUE];
|
|
@@ -1814,7 +1885,7 @@ function applyState(next, state, keyFn, all) {
|
|
|
1814
1885
|
(item && next[start] && keyFn(item) === keyFn(next[start])));
|
|
1815
1886
|
start++
|
|
1816
1887
|
) {
|
|
1817
|
-
applyState(next[start], wrap(item, target), keyFn
|
|
1888
|
+
applyState(next[start], wrap(item, target), keyFn);
|
|
1818
1889
|
}
|
|
1819
1890
|
const temp = new Array(next.length),
|
|
1820
1891
|
newIndices = new Map();
|
|
@@ -1837,7 +1908,7 @@ function applyState(next, state, keyFn, all) {
|
|
|
1837
1908
|
changed = true;
|
|
1838
1909
|
const wrapped = wrap(temp[j], target);
|
|
1839
1910
|
target[STORE_NODE][j] && setSignal(target[STORE_NODE][j], wrapped);
|
|
1840
|
-
applyState(next[j], wrapped, keyFn
|
|
1911
|
+
applyState(next[j], wrapped, keyFn);
|
|
1841
1912
|
}
|
|
1842
1913
|
changed && target[STORE_NODE][$TRACK] && setSignal(target[STORE_NODE][$TRACK], void 0);
|
|
1843
1914
|
prevLength !== next.length &&
|
|
@@ -1867,7 +1938,7 @@ function applyState(next, state, keyFn, all) {
|
|
|
1867
1938
|
if (j in temp) {
|
|
1868
1939
|
const wrapped = wrap(temp[j], target);
|
|
1869
1940
|
target[STORE_NODE][j] && setSignal(target[STORE_NODE][j], wrapped);
|
|
1870
|
-
applyState(next[j], wrapped, keyFn
|
|
1941
|
+
applyState(next[j], wrapped, keyFn);
|
|
1871
1942
|
} else target[STORE_NODE][j] && setSignal(target[STORE_NODE][j], wrap(next[j], target));
|
|
1872
1943
|
}
|
|
1873
1944
|
if (start < next.length) changed = true;
|
|
@@ -1875,7 +1946,7 @@ function applyState(next, state, keyFn, all) {
|
|
|
1875
1946
|
for (let i = 0, len = next.length; i < len; i++) {
|
|
1876
1947
|
const item = getOverrideValue(previous, override, nodes, i, optOverride);
|
|
1877
1948
|
isWrappable(item)
|
|
1878
|
-
? applyState(next[i], wrap(item, target), keyFn
|
|
1949
|
+
? applyState(next[i], wrap(item, target), keyFn)
|
|
1879
1950
|
: target[STORE_NODE][i] && setSignal(target[STORE_NODE][i], next[i]);
|
|
1880
1951
|
}
|
|
1881
1952
|
}
|
|
@@ -1888,7 +1959,7 @@ function applyState(next, state, keyFn, all) {
|
|
|
1888
1959
|
}
|
|
1889
1960
|
if (nodes) {
|
|
1890
1961
|
const tracked = nodes[$TRACK];
|
|
1891
|
-
const keys = tracked
|
|
1962
|
+
const keys = tracked ? getAllKeys(previous, override, next) : Object.keys(nodes);
|
|
1892
1963
|
for (let i = 0, len = keys.length; i < len; i++) {
|
|
1893
1964
|
const key = keys[i];
|
|
1894
1965
|
const node = nodes[key];
|
|
@@ -1903,7 +1974,7 @@ function applyState(next, state, keyFn, all) {
|
|
|
1903
1974
|
) {
|
|
1904
1975
|
tracked && setSignal(tracked, void 0);
|
|
1905
1976
|
node && setSignal(node, isWrappable(nextValue) ? wrap(nextValue, target) : nextValue);
|
|
1906
|
-
} else applyState(nextValue, wrap(previousValue, target), keyFn
|
|
1977
|
+
} else applyState(nextValue, wrap(previousValue, target), keyFn);
|
|
1907
1978
|
}
|
|
1908
1979
|
}
|
|
1909
1980
|
if ((nodes = target[STORE_HAS])) {
|
|
@@ -1914,14 +1985,14 @@ function applyState(next, state, keyFn, all) {
|
|
|
1914
1985
|
}
|
|
1915
1986
|
}
|
|
1916
1987
|
}
|
|
1917
|
-
function reconcile(value, key
|
|
1988
|
+
function reconcile(value, key) {
|
|
1918
1989
|
return state => {
|
|
1919
1990
|
if (state == null) throw new Error("Cannot reconcile null or undefined state");
|
|
1920
1991
|
const keyFn = typeof key === "string" ? item => item[key] : key;
|
|
1921
1992
|
const eq = keyFn(state);
|
|
1922
1993
|
if (eq !== undefined && keyFn(value) !== keyFn(state))
|
|
1923
1994
|
throw new Error("Cannot reconcile states with different identity");
|
|
1924
|
-
applyState(value, state, keyFn
|
|
1995
|
+
applyState(value, state, keyFn);
|
|
1925
1996
|
};
|
|
1926
1997
|
}
|
|
1927
1998
|
function createProjectionInternal(fn, initialValue = {}, options) {
|
|
@@ -1951,11 +2022,9 @@ function createProjectionInternal(fn, initialValue = {}, options) {
|
|
|
1951
2022
|
const value = handleAsync(owner, fn(s), value => {
|
|
1952
2023
|
value !== s &&
|
|
1953
2024
|
value !== undefined &&
|
|
1954
|
-
storeSetter(wrappedStore, reconcile(value, options?.key || "id"
|
|
2025
|
+
storeSetter(wrappedStore, reconcile(value, options?.key || "id"));
|
|
1955
2026
|
});
|
|
1956
|
-
value !== s &&
|
|
1957
|
-
value !== undefined &&
|
|
1958
|
-
reconcile(value, options?.key || "id", options?.all)(wrappedStore);
|
|
2027
|
+
value !== s && value !== undefined && reconcile(value, options?.key || "id")(wrappedStore);
|
|
1959
2028
|
});
|
|
1960
2029
|
});
|
|
1961
2030
|
node._preventAutoDisposal = true;
|
|
@@ -2001,11 +2070,9 @@ const writeTraps = {
|
|
|
2001
2070
|
}
|
|
2002
2071
|
};
|
|
2003
2072
|
const $TRACK = Symbol("STORE_TRACK"),
|
|
2004
|
-
$DEEP = Symbol("STORE_DEEP"),
|
|
2005
2073
|
$TARGET = Symbol("STORE_TARGET"),
|
|
2006
2074
|
$PROXY = Symbol("STORE_PROXY"),
|
|
2007
2075
|
$DELETED = Symbol("STORE_DELETED");
|
|
2008
|
-
const PARENTS = new WeakMap();
|
|
2009
2076
|
const STORE_VALUE = "v",
|
|
2010
2077
|
STORE_OVERRIDE = "o",
|
|
2011
2078
|
STORE_OPTIMISTIC_OVERRIDE = "x",
|
|
@@ -2058,7 +2125,9 @@ function getNode(nodes, property, value, firewall, equals = isEqual, optimistic,
|
|
|
2058
2125
|
},
|
|
2059
2126
|
firewall
|
|
2060
2127
|
);
|
|
2061
|
-
if (optimistic)
|
|
2128
|
+
if (optimistic) {
|
|
2129
|
+
s._overrideValue = NOT_PENDING;
|
|
2130
|
+
}
|
|
2062
2131
|
if (snapshotProps && property in snapshotProps) {
|
|
2063
2132
|
const sv = snapshotProps[property];
|
|
2064
2133
|
s._snapshotValue = sv === undefined ? NO_SNAPSHOT : sv;
|
|
@@ -2104,8 +2173,8 @@ const storeTraps = {
|
|
|
2104
2173
|
if (property === $TARGET) return target;
|
|
2105
2174
|
if (property === $PROXY) return receiver;
|
|
2106
2175
|
if (property === $REFRESH) return target[STORE_FIREWALL];
|
|
2107
|
-
if (property === $TRACK
|
|
2108
|
-
trackSelf(target
|
|
2176
|
+
if (property === $TRACK) {
|
|
2177
|
+
trackSelf(target);
|
|
2109
2178
|
return receiver;
|
|
2110
2179
|
}
|
|
2111
2180
|
const nodes = getNodes(target, STORE_NODE);
|
|
@@ -2127,11 +2196,11 @@ const storeTraps = {
|
|
|
2127
2196
|
if (writeOnly(receiver)) {
|
|
2128
2197
|
let value =
|
|
2129
2198
|
tracked && (overridden || !proxySource)
|
|
2130
|
-
? tracked.
|
|
2131
|
-
? tracked.
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2199
|
+
? tracked._overrideValue !== undefined && tracked._overrideValue !== NOT_PENDING
|
|
2200
|
+
? tracked._overrideValue
|
|
2201
|
+
: tracked._pendingValue !== NOT_PENDING
|
|
2202
|
+
? tracked._pendingValue
|
|
2203
|
+
: tracked._value
|
|
2135
2204
|
: storeValue[property];
|
|
2136
2205
|
value === $DELETED && (value = undefined);
|
|
2137
2206
|
if (!isWrappable(value)) return value;
|
|
@@ -2169,8 +2238,8 @@ const storeTraps = {
|
|
|
2169
2238
|
}
|
|
2170
2239
|
if (strictRead && typeof property === "string")
|
|
2171
2240
|
console.warn(
|
|
2172
|
-
`Reactive value read
|
|
2173
|
-
`Move it into a tracking scope (JSX,
|
|
2241
|
+
`Reactive value read directly in ${strictRead} will not update. ` +
|
|
2242
|
+
`Move it into a tracking scope (JSX, a memo, or an effect's compute function).`
|
|
2174
2243
|
);
|
|
2175
2244
|
return isWrappable(value) ? wrap(value, target) : value;
|
|
2176
2245
|
},
|
|
@@ -2207,7 +2276,11 @@ const storeTraps = {
|
|
|
2207
2276
|
untrack(() => {
|
|
2208
2277
|
const state = target[STORE_VALUE];
|
|
2209
2278
|
const base = state[property];
|
|
2210
|
-
if (
|
|
2279
|
+
if (
|
|
2280
|
+
snapshotCaptureActive &&
|
|
2281
|
+
typeof property !== "symbol" &&
|
|
2282
|
+
!((target[STORE_FIREWALL]?._statusFlags ?? 0) & STATUS_PENDING)
|
|
2283
|
+
) {
|
|
2211
2284
|
if (!target[STORE_SNAPSHOT_PROPS]) {
|
|
2212
2285
|
target[STORE_SNAPSHOT_PROPS] = Object.create(null);
|
|
2213
2286
|
snapshotSources?.add(target);
|
|
@@ -2234,11 +2307,6 @@ const storeTraps = {
|
|
|
2234
2307
|
if (value !== undefined && value === base) delete target[overrideKey][property];
|
|
2235
2308
|
else (target[overrideKey] || (target[overrideKey] = Object.create(null)))[property] = value;
|
|
2236
2309
|
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
2310
|
target[STORE_HAS]?.[property] && setSignal(target[STORE_HAS][property], true);
|
|
2243
2311
|
const nodes = getNodes(target, STORE_NODE);
|
|
2244
2312
|
nodes[property] &&
|
|
@@ -2278,10 +2346,6 @@ const storeTraps = {
|
|
|
2278
2346
|
} else if (target[overrideKey] && property in target[overrideKey]) {
|
|
2279
2347
|
delete target[overrideKey][property];
|
|
2280
2348
|
} 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
2349
|
if (target[STORE_HAS]?.[property]) setSignal(target[STORE_HAS][property], false);
|
|
2286
2350
|
const nodes = getNodes(target, STORE_NODE);
|
|
2287
2351
|
nodes[property] && setSignal(nodes[property], undefined);
|
|
@@ -2352,59 +2416,6 @@ function createStore(first, second, options) {
|
|
|
2352
2416
|
wrappedStore = derived ? createProjectionInternal(first, second, options).store : wrap(first);
|
|
2353
2417
|
return [wrappedStore, fn => storeSetter(wrappedStore, fn)];
|
|
2354
2418
|
}
|
|
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
2419
|
function createOptimisticStore(first, second, options) {
|
|
2409
2420
|
GlobalQueue._clearOptimisticStore ||= clearOptimisticStore;
|
|
2410
2421
|
const derived = typeof first === "function";
|
|
@@ -2475,14 +2486,14 @@ function createOptimisticProjectionInternal(fn, initialValue = {}, options) {
|
|
|
2475
2486
|
try {
|
|
2476
2487
|
value !== s &&
|
|
2477
2488
|
value !== undefined &&
|
|
2478
|
-
storeSetter(wrappedStore, reconcile(value, options?.key || "id"
|
|
2489
|
+
storeSetter(wrappedStore, reconcile(value, options?.key || "id"));
|
|
2479
2490
|
} finally {
|
|
2480
2491
|
setProjectionWriteActive(false);
|
|
2481
2492
|
}
|
|
2482
2493
|
});
|
|
2483
2494
|
value !== s &&
|
|
2484
2495
|
value !== undefined &&
|
|
2485
|
-
reconcile(value, options?.key || "id"
|
|
2496
|
+
reconcile(value, options?.key || "id")(wrappedStore);
|
|
2486
2497
|
});
|
|
2487
2498
|
} finally {
|
|
2488
2499
|
setProjectionWriteActive(false);
|
|
@@ -2557,12 +2568,13 @@ const storePath = Object.assign(
|
|
|
2557
2568
|
},
|
|
2558
2569
|
{ DELETE: DELETE }
|
|
2559
2570
|
);
|
|
2560
|
-
function
|
|
2571
|
+
function snapshotImpl(item, track, map, lookup) {
|
|
2561
2572
|
let target, isArray, override, result, unwrapped, v;
|
|
2562
2573
|
if (!isWrappable(item)) return item;
|
|
2563
2574
|
if (map && map.has(item)) return map.get(item);
|
|
2564
2575
|
if (!map) map = new Map();
|
|
2565
2576
|
if ((target = item[$TARGET] || lookup?.get(item)?.[$TARGET])) {
|
|
2577
|
+
if (track) trackSelf(target, $TRACK);
|
|
2566
2578
|
override = target[STORE_OVERRIDE];
|
|
2567
2579
|
isArray = Array.isArray(target[STORE_VALUE]);
|
|
2568
2580
|
map.set(
|
|
@@ -2582,7 +2594,8 @@ function snapshot(item, map, lookup) {
|
|
|
2582
2594
|
for (let i = 0; i < len; i++) {
|
|
2583
2595
|
v = override && i in override ? override[i] : item[i];
|
|
2584
2596
|
if (v === $DELETED) continue;
|
|
2585
|
-
if (
|
|
2597
|
+
if (track && isWrappable(v)) wrap(v, target);
|
|
2598
|
+
if ((unwrapped = snapshotImpl(v, track, map, lookup)) !== v || result) {
|
|
2586
2599
|
if (!result) map.set(item, (result = [...item]));
|
|
2587
2600
|
result[i] = unwrapped;
|
|
2588
2601
|
}
|
|
@@ -2594,7 +2607,8 @@ function snapshot(item, map, lookup) {
|
|
|
2594
2607
|
const desc = getPropertyDescriptor(item, override, prop);
|
|
2595
2608
|
if (desc.get) continue;
|
|
2596
2609
|
v = override && prop in override ? override[prop] : item[prop];
|
|
2597
|
-
if (
|
|
2610
|
+
if (track && isWrappable(v)) wrap(v, target);
|
|
2611
|
+
if ((unwrapped = snapshotImpl(v, track, map, lookup)) !== item[prop] || result) {
|
|
2598
2612
|
if (!result) {
|
|
2599
2613
|
result = Object.create(Object.getPrototypeOf(item));
|
|
2600
2614
|
Object.assign(result, item);
|
|
@@ -2605,6 +2619,12 @@ function snapshot(item, map, lookup) {
|
|
|
2605
2619
|
}
|
|
2606
2620
|
return result || item;
|
|
2607
2621
|
}
|
|
2622
|
+
function snapshot(item, map, lookup) {
|
|
2623
|
+
return snapshotImpl(item, false, map, lookup);
|
|
2624
|
+
}
|
|
2625
|
+
function deep(store) {
|
|
2626
|
+
return snapshotImpl(store, true);
|
|
2627
|
+
}
|
|
2608
2628
|
function trueFn() {
|
|
2609
2629
|
return true;
|
|
2610
2630
|
}
|
|
@@ -2780,15 +2800,15 @@ function updateKeyedMap() {
|
|
|
2780
2800
|
this._rows[j] = signal(newItems[j], pureOptions);
|
|
2781
2801
|
this._indexes && (this._indexes[j] = signal(j, pureOptions));
|
|
2782
2802
|
return this._map(
|
|
2783
|
-
|
|
2784
|
-
this._indexes ?
|
|
2803
|
+
accessor(this._rows[j]),
|
|
2804
|
+
this._indexes ? accessor(this._indexes[j]) : undefined
|
|
2785
2805
|
);
|
|
2786
2806
|
}
|
|
2787
2807
|
: this._indexes
|
|
2788
2808
|
? () => {
|
|
2789
2809
|
const item = newItems[j];
|
|
2790
2810
|
this._indexes[j] = signal(j, pureOptions);
|
|
2791
|
-
return this._map(() => item,
|
|
2811
|
+
return this._map(() => item, accessor(this._indexes[j]));
|
|
2792
2812
|
}
|
|
2793
2813
|
: () => {
|
|
2794
2814
|
const item = newItems[j];
|
|
@@ -2992,11 +3012,14 @@ function createBoundChildren(owner, fn, queue, mask) {
|
|
|
2992
3012
|
return boundaryComputed(() => staleValues(() => flatten(read(c))), mask);
|
|
2993
3013
|
});
|
|
2994
3014
|
}
|
|
3015
|
+
const ON_INIT = Symbol();
|
|
2995
3016
|
class CollectionQueue extends Queue {
|
|
2996
3017
|
_collectionType;
|
|
2997
3018
|
_sources = new Set();
|
|
2998
3019
|
_disabled = signal(false, { pureWrite: true });
|
|
2999
3020
|
_initialized = false;
|
|
3021
|
+
_onFn;
|
|
3022
|
+
_prevOn = ON_INIT;
|
|
3000
3023
|
constructor(type) {
|
|
3001
3024
|
super();
|
|
3002
3025
|
this._collectionType = type;
|
|
@@ -3006,10 +3029,22 @@ class CollectionQueue extends Queue {
|
|
|
3006
3029
|
return super.run(type);
|
|
3007
3030
|
}
|
|
3008
3031
|
notify(node, type, flags, error) {
|
|
3009
|
-
if (
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3032
|
+
if (!(type & this._collectionType)) return super.notify(node, type, flags, error);
|
|
3033
|
+
if (this._initialized && this._onFn) {
|
|
3034
|
+
const currentOn = untrack(() => {
|
|
3035
|
+
try {
|
|
3036
|
+
return this._onFn();
|
|
3037
|
+
} catch {
|
|
3038
|
+
return ON_INIT;
|
|
3039
|
+
}
|
|
3040
|
+
});
|
|
3041
|
+
if (currentOn !== this._prevOn) {
|
|
3042
|
+
this._prevOn = currentOn;
|
|
3043
|
+
this._initialized = false;
|
|
3044
|
+
this._sources.clear();
|
|
3045
|
+
}
|
|
3046
|
+
}
|
|
3047
|
+
if (this._collectionType & STATUS_PENDING && this._initialized)
|
|
3013
3048
|
return super.notify(node, type, flags, error);
|
|
3014
3049
|
if (flags & this._collectionType) {
|
|
3015
3050
|
const source = error?.source || node._error?.source;
|
|
@@ -3026,12 +3061,20 @@ class CollectionQueue extends Queue {
|
|
|
3026
3061
|
for (const source of this._sources) {
|
|
3027
3062
|
if (!(source._statusFlags & this._collectionType)) this._sources.delete(source);
|
|
3028
3063
|
}
|
|
3029
|
-
if (!this._sources.size)
|
|
3064
|
+
if (!this._sources.size) {
|
|
3065
|
+
setSignal(this._disabled, false);
|
|
3066
|
+
if (this._onFn) {
|
|
3067
|
+
try {
|
|
3068
|
+
this._prevOn = untrack(() => this._onFn());
|
|
3069
|
+
} catch {}
|
|
3070
|
+
}
|
|
3071
|
+
}
|
|
3030
3072
|
}
|
|
3031
3073
|
}
|
|
3032
|
-
function createCollectionBoundary(type, fn, fallback) {
|
|
3074
|
+
function createCollectionBoundary(type, fn, fallback, onFn) {
|
|
3033
3075
|
const owner = createOwner();
|
|
3034
3076
|
const queue = new CollectionQueue(type);
|
|
3077
|
+
if (onFn) queue._onFn = onFn;
|
|
3035
3078
|
const tree = createBoundChildren(owner, fn, queue, type);
|
|
3036
3079
|
const decision = computed(() => {
|
|
3037
3080
|
if (!read(queue._disabled)) {
|
|
@@ -3043,10 +3086,10 @@ function createCollectionBoundary(type, fn, fallback) {
|
|
|
3043
3086
|
}
|
|
3044
3087
|
return fallback(queue);
|
|
3045
3088
|
});
|
|
3046
|
-
return
|
|
3089
|
+
return accessor(decision);
|
|
3047
3090
|
}
|
|
3048
|
-
function
|
|
3049
|
-
return createCollectionBoundary(STATUS_PENDING, fn, () => fallback());
|
|
3091
|
+
function createLoadingBoundary(fn, fallback, options) {
|
|
3092
|
+
return createCollectionBoundary(STATUS_PENDING, fn, () => fallback(), options?.on);
|
|
3050
3093
|
}
|
|
3051
3094
|
function createErrorBoundary(fn, fallback) {
|
|
3052
3095
|
return createCollectionBoundary(STATUS_ERROR, fn, queue => {
|
|
@@ -3128,7 +3171,7 @@ export {
|
|
|
3128
3171
|
createContext,
|
|
3129
3172
|
createEffect,
|
|
3130
3173
|
createErrorBoundary,
|
|
3131
|
-
|
|
3174
|
+
createLoadingBoundary,
|
|
3132
3175
|
createMemo,
|
|
3133
3176
|
createOptimistic,
|
|
3134
3177
|
createOptimisticStore,
|
|
@@ -3141,6 +3184,8 @@ export {
|
|
|
3141
3184
|
createStore,
|
|
3142
3185
|
createTrackedEffect,
|
|
3143
3186
|
deep,
|
|
3187
|
+
enableExternalSource,
|
|
3188
|
+
enforceLoadingBoundary,
|
|
3144
3189
|
flatten,
|
|
3145
3190
|
flush,
|
|
3146
3191
|
getContext,
|
|
@@ -3167,7 +3212,6 @@ export {
|
|
|
3167
3212
|
resolve,
|
|
3168
3213
|
runWithOwner,
|
|
3169
3214
|
setContext,
|
|
3170
|
-
setOnUnhandledAsync,
|
|
3171
3215
|
setSnapshotCapture,
|
|
3172
3216
|
snapshot,
|
|
3173
3217
|
storePath,
|