@solidjs/signals 0.11.3 → 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 +242 -194
- package/dist/node.cjs +942 -916
- package/dist/prod.js +787 -761
- package/dist/types/boundaries.d.ts +6 -2
- package/dist/types/core/core.d.ts +9 -3
- 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 -0
- 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,6 +151,14 @@ let clock = 0;
|
|
|
151
151
|
let activeTransition = null;
|
|
152
152
|
let scheduled = false;
|
|
153
153
|
let projectionWriteActive = false;
|
|
154
|
+
let _enforceLoadingBoundary = false;
|
|
155
|
+
let _hitUnhandledAsync = false;
|
|
156
|
+
function resetUnhandledAsync() {
|
|
157
|
+
_hitUnhandledAsync = false;
|
|
158
|
+
}
|
|
159
|
+
function enforceLoadingBoundary(enabled) {
|
|
160
|
+
_enforceLoadingBoundary = enabled;
|
|
161
|
+
}
|
|
154
162
|
function runLaneEffects(type) {
|
|
155
163
|
for (const lane of activeLanes) {
|
|
156
164
|
if (lane._mergedInto || lane._pendingAsync.size > 0) continue;
|
|
@@ -167,7 +175,7 @@ function setProjectionWriteActive(value) {
|
|
|
167
175
|
function schedule() {
|
|
168
176
|
if (scheduled) return;
|
|
169
177
|
scheduled = true;
|
|
170
|
-
if (!globalQueue._running) queueMicrotask(flush);
|
|
178
|
+
if (!globalQueue._running && !projectionWriteActive) queueMicrotask(flush);
|
|
171
179
|
}
|
|
172
180
|
class Queue {
|
|
173
181
|
_parent = null;
|
|
@@ -297,6 +305,7 @@ class GlobalQueue extends Queue {
|
|
|
297
305
|
activeTransition._asyncNodes.push(actualError.source);
|
|
298
306
|
schedule();
|
|
299
307
|
}
|
|
308
|
+
if (_enforceLoadingBoundary) _hitUnhandledAsync = true;
|
|
300
309
|
}
|
|
301
310
|
return true;
|
|
302
311
|
}
|
|
@@ -380,35 +389,40 @@ function insertSubs(node, optimistic = false) {
|
|
|
380
389
|
insertIntoHeap(s._sub, queue);
|
|
381
390
|
}
|
|
382
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
|
+
}
|
|
383
406
|
function finalizePureQueue(completingTransition = null, incomplete = false) {
|
|
384
407
|
let resolvePending = !incomplete;
|
|
408
|
+
if (resolvePending) commitPendingNodes();
|
|
385
409
|
if (!incomplete) checkBoundaryChildren(globalQueue);
|
|
386
410
|
if (dirtyQueue._max >= dirtyQueue._min) runHeap(dirtyQueue, GlobalQueue._update);
|
|
387
411
|
if (resolvePending) {
|
|
388
|
-
|
|
389
|
-
for (let i = 0; i < pendingNodes.length; i++) {
|
|
390
|
-
const n = pendingNodes[i];
|
|
391
|
-
if (n._pendingValue !== NOT_PENDING) {
|
|
392
|
-
n._value = n._pendingValue;
|
|
393
|
-
n._pendingValue = NOT_PENDING;
|
|
394
|
-
if (n._type && n._type !== EFFECT_TRACKED) n._modified = true;
|
|
395
|
-
}
|
|
396
|
-
if (!(n._statusFlags & STATUS_PENDING)) n._statusFlags &= ~STATUS_UNINITIALIZED;
|
|
397
|
-
if (n._fn) GlobalQueue._dispose(n, false, true);
|
|
398
|
-
}
|
|
399
|
-
pendingNodes.length = 0;
|
|
412
|
+
commitPendingNodes();
|
|
400
413
|
const optimisticNodes = completingTransition
|
|
401
414
|
? completingTransition._optimisticNodes
|
|
402
415
|
: globalQueue._optimisticNodes;
|
|
403
416
|
for (let i = 0; i < optimisticNodes.length; i++) {
|
|
404
417
|
const n = optimisticNodes[i];
|
|
405
|
-
const original = n._pendingValue;
|
|
406
418
|
n._optimisticLane = undefined;
|
|
407
|
-
if (
|
|
408
|
-
n._value =
|
|
409
|
-
|
|
419
|
+
if (n._pendingValue !== NOT_PENDING) {
|
|
420
|
+
n._value = n._pendingValue;
|
|
421
|
+
n._pendingValue = NOT_PENDING;
|
|
410
422
|
}
|
|
411
|
-
|
|
423
|
+
const prevOverride = n._overrideValue;
|
|
424
|
+
n._overrideValue = NOT_PENDING;
|
|
425
|
+
if (prevOverride !== NOT_PENDING && n._value !== prevOverride) insertSubs(n, true);
|
|
412
426
|
n._transition = null;
|
|
413
427
|
}
|
|
414
428
|
optimisticNodes.length = 0;
|
|
@@ -515,7 +529,7 @@ function getOrCreateLane(signal) {
|
|
|
515
529
|
};
|
|
516
530
|
signalLanes.set(signal, lane);
|
|
517
531
|
activeLanes.add(lane);
|
|
518
|
-
signal.
|
|
532
|
+
signal._overrideSinceLane = false;
|
|
519
533
|
return lane;
|
|
520
534
|
}
|
|
521
535
|
function findLane(lane) {
|
|
@@ -541,7 +555,7 @@ function resolveLane(el) {
|
|
|
541
555
|
return undefined;
|
|
542
556
|
}
|
|
543
557
|
function hasActiveOverride(el) {
|
|
544
|
-
return !!(el.
|
|
558
|
+
return !!(el._overrideValue !== undefined && el._overrideValue !== NOT_PENDING);
|
|
545
559
|
}
|
|
546
560
|
function assignOrMergeLane(el, sourceLane) {
|
|
547
561
|
const sourceRoot = findLane(sourceLane);
|
|
@@ -588,10 +602,10 @@ function handleAsync(el, result, setter) {
|
|
|
588
602
|
const lane = resolveLane(el);
|
|
589
603
|
if (lane) lane._pendingAsync.delete(el);
|
|
590
604
|
if (setter) setter(value);
|
|
591
|
-
else if (el.
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
605
|
+
else if (el._overrideValue !== undefined) {
|
|
606
|
+
if (el._overrideValue !== undefined && el._overrideValue !== NOT_PENDING)
|
|
607
|
+
el._pendingValue = value;
|
|
608
|
+
else {
|
|
595
609
|
el._value = value;
|
|
596
610
|
insertSubs(el);
|
|
597
611
|
}
|
|
@@ -647,6 +661,10 @@ function handleAsync(el, result, setter) {
|
|
|
647
661
|
syncResult = r;
|
|
648
662
|
resolved = true;
|
|
649
663
|
} else if (!r.done) asyncWrite(r.value, iterate);
|
|
664
|
+
else {
|
|
665
|
+
schedule();
|
|
666
|
+
flush();
|
|
667
|
+
}
|
|
650
668
|
},
|
|
651
669
|
e => {
|
|
652
670
|
if (!isSync) handleError(e);
|
|
@@ -682,7 +700,8 @@ function notifyStatus(el, status, error, blockStatus, lane) {
|
|
|
682
700
|
)
|
|
683
701
|
error = new StatusError(el, error);
|
|
684
702
|
const isSource = error instanceof NotReadyError && error.source === el;
|
|
685
|
-
const isOptimisticBoundary =
|
|
703
|
+
const isOptimisticBoundary =
|
|
704
|
+
status === STATUS_PENDING && el._overrideValue !== undefined && !isSource;
|
|
686
705
|
const startsBlocking = isOptimisticBoundary && hasActiveOverride(el);
|
|
687
706
|
if (!blockStatus) {
|
|
688
707
|
el._statusFlags =
|
|
@@ -833,7 +852,6 @@ function disposeChildren(node, self = false, zombie) {
|
|
|
833
852
|
node._pendingFirstChild = null;
|
|
834
853
|
} else {
|
|
835
854
|
node._firstChild = null;
|
|
836
|
-
node._nextSibling = null;
|
|
837
855
|
node._childCount = 0;
|
|
838
856
|
}
|
|
839
857
|
runDisposal(node, zombie);
|
|
@@ -967,8 +985,14 @@ function effect(compute, effect, error, initialValue, options) {
|
|
|
967
985
|
}
|
|
968
986
|
}
|
|
969
987
|
if (!node._queue.notify(node, STATUS_ERROR, STATUS_ERROR)) throw err;
|
|
970
|
-
} else if (node._type === EFFECT_RENDER)
|
|
988
|
+
} else if (node._type === EFFECT_RENDER) {
|
|
971
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
|
+
}
|
|
972
996
|
};
|
|
973
997
|
recompute(node, true);
|
|
974
998
|
!options?.defer &&
|
|
@@ -982,6 +1006,10 @@ function effect(compute, effect, error, initialValue, options) {
|
|
|
982
1006
|
}
|
|
983
1007
|
function runEffect() {
|
|
984
1008
|
if (!this._modified || this._flags & REACTIVE_DISPOSED) return;
|
|
1009
|
+
let prevStrictRead = false;
|
|
1010
|
+
{
|
|
1011
|
+
prevStrictRead = setStrictRead("an effect callback");
|
|
1012
|
+
}
|
|
985
1013
|
this._cleanup?.();
|
|
986
1014
|
this._cleanup = undefined;
|
|
987
1015
|
try {
|
|
@@ -989,6 +1017,7 @@ function runEffect() {
|
|
|
989
1017
|
} catch (error) {
|
|
990
1018
|
if (!this._queue.notify(this, STATUS_ERROR, STATUS_ERROR)) throw error;
|
|
991
1019
|
} finally {
|
|
1020
|
+
setStrictRead(prevStrictRead);
|
|
992
1021
|
this._prevValue = this._value;
|
|
993
1022
|
this._modified = false;
|
|
994
1023
|
}
|
|
@@ -1022,6 +1051,29 @@ function trackedEffect(fn, options) {
|
|
|
1022
1051
|
if (!node._parent)
|
|
1023
1052
|
console.warn("Effects created outside a reactive context will never be disposed");
|
|
1024
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
|
+
}
|
|
1025
1077
|
GlobalQueue._update = recompute;
|
|
1026
1078
|
GlobalQueue._dispose = disposeChildren;
|
|
1027
1079
|
let tracking = false;
|
|
@@ -1101,7 +1153,7 @@ function recompute(el, create = false) {
|
|
|
1101
1153
|
}
|
|
1102
1154
|
}
|
|
1103
1155
|
const isOptimisticDirty = !!(el._flags & REACTIVE_OPTIMISTIC_DIRTY);
|
|
1104
|
-
const hasOverride =
|
|
1156
|
+
const hasOverride = el._overrideValue !== undefined && el._overrideValue !== NOT_PENDING;
|
|
1105
1157
|
const wasPending = !!(el._statusFlags & STATUS_PENDING);
|
|
1106
1158
|
const oldcontext = context;
|
|
1107
1159
|
context = el;
|
|
@@ -1163,24 +1215,24 @@ function recompute(el, create = false) {
|
|
|
1163
1215
|
else el._deps = null;
|
|
1164
1216
|
}
|
|
1165
1217
|
const compareValue = hasOverride
|
|
1166
|
-
? el.
|
|
1218
|
+
? el._overrideValue
|
|
1167
1219
|
: el._pendingValue === NOT_PENDING
|
|
1168
1220
|
? el._value
|
|
1169
1221
|
: el._pendingValue;
|
|
1170
1222
|
const valueChanged = !el._equals || !el._equals(compareValue, value);
|
|
1171
1223
|
if (valueChanged) {
|
|
1172
|
-
const prevVisible = hasOverride ? el.
|
|
1173
|
-
if (create || (isEffect && activeTransition !== el._transition) || isOptimisticDirty)
|
|
1224
|
+
const prevVisible = hasOverride ? el._overrideValue : undefined;
|
|
1225
|
+
if (create || (isEffect && activeTransition !== el._transition) || isOptimisticDirty) {
|
|
1174
1226
|
el._value = value;
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
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)
|
|
1182
1235
|
insertSubs(el, isOptimisticDirty || hasOverride);
|
|
1183
|
-
}
|
|
1184
1236
|
} else if (hasOverride) {
|
|
1185
1237
|
el._pendingValue = value;
|
|
1186
1238
|
} else if (el._height != oldHeight) {
|
|
@@ -1192,7 +1244,7 @@ function recompute(el, create = false) {
|
|
|
1192
1244
|
currentOptimisticLane = prevLane;
|
|
1193
1245
|
(!create || el._statusFlags & STATUS_PENDING) &&
|
|
1194
1246
|
!el._transition &&
|
|
1195
|
-
!(activeTransition &&
|
|
1247
|
+
!(activeTransition && hasOverride) &&
|
|
1196
1248
|
globalQueue._pendingNodes.push(el);
|
|
1197
1249
|
el._transition &&
|
|
1198
1250
|
isEffect &&
|
|
@@ -1212,7 +1264,10 @@ function updateIfNecessary(el) {
|
|
|
1212
1264
|
}
|
|
1213
1265
|
}
|
|
1214
1266
|
}
|
|
1215
|
-
if (
|
|
1267
|
+
if (
|
|
1268
|
+
el._flags & (REACTIVE_DIRTY | REACTIVE_OPTIMISTIC_DIRTY) ||
|
|
1269
|
+
(el._error && el._time < clock && !el._inFlight)
|
|
1270
|
+
) {
|
|
1216
1271
|
recompute(el);
|
|
1217
1272
|
}
|
|
1218
1273
|
el._flags = REACTIVE_NONE | (el._flags & REACTIVE_SNAPSHOT_STALE);
|
|
@@ -1270,6 +1325,17 @@ function computed(fn, initialValue, options) {
|
|
|
1270
1325
|
}
|
|
1271
1326
|
if (parent) self._height = parent._height + 1;
|
|
1272
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
|
+
}
|
|
1273
1339
|
!options?.lazy && recompute(self, true);
|
|
1274
1340
|
if (snapshotCaptureActive && !options?.lazy) {
|
|
1275
1341
|
if (!(self._statusFlags & STATUS_PENDING)) {
|
|
@@ -1294,7 +1360,7 @@ function signal(v, options, firewall = null) {
|
|
|
1294
1360
|
};
|
|
1295
1361
|
s._name = options?.name ?? "signal";
|
|
1296
1362
|
firewall && (firewall._child = s);
|
|
1297
|
-
if (snapshotCaptureActive && !s._pureWrite) {
|
|
1363
|
+
if (snapshotCaptureActive && !s._pureWrite && !((firewall?._statusFlags ?? 0) & STATUS_PENDING)) {
|
|
1298
1364
|
s._snapshotValue = v === undefined ? NO_SNAPSHOT : v;
|
|
1299
1365
|
snapshotSources.add(s);
|
|
1300
1366
|
}
|
|
@@ -1302,12 +1368,12 @@ function signal(v, options, firewall = null) {
|
|
|
1302
1368
|
}
|
|
1303
1369
|
function optimisticSignal(v, options) {
|
|
1304
1370
|
const s = signal(v, options);
|
|
1305
|
-
s.
|
|
1371
|
+
s._overrideValue = NOT_PENDING;
|
|
1306
1372
|
return s;
|
|
1307
1373
|
}
|
|
1308
1374
|
function optimisticComputed(fn, initialValue, options) {
|
|
1309
1375
|
const c = computed(fn, initialValue, options);
|
|
1310
|
-
c.
|
|
1376
|
+
c._overrideValue = NOT_PENDING;
|
|
1311
1377
|
return c;
|
|
1312
1378
|
}
|
|
1313
1379
|
function isEqual(a, b) {
|
|
@@ -1319,23 +1385,18 @@ function setStrictRead(v) {
|
|
|
1319
1385
|
strictRead = v;
|
|
1320
1386
|
return prev;
|
|
1321
1387
|
}
|
|
1322
|
-
function untrack(fn) {
|
|
1323
|
-
if (!tracking && !strictRead) return fn();
|
|
1388
|
+
function untrack(fn, strictReadLabel) {
|
|
1389
|
+
if (!externalSourceConfig && !tracking && !strictRead && !strictReadLabel) return fn();
|
|
1390
|
+
const prevTracking = tracking;
|
|
1391
|
+
const prevStrictRead = strictRead;
|
|
1324
1392
|
tracking = false;
|
|
1325
|
-
|
|
1326
|
-
const prev = strictRead;
|
|
1327
|
-
strictRead = false;
|
|
1328
|
-
try {
|
|
1329
|
-
return fn();
|
|
1330
|
-
} finally {
|
|
1331
|
-
tracking = true;
|
|
1332
|
-
strictRead = prev;
|
|
1333
|
-
}
|
|
1334
|
-
}
|
|
1393
|
+
strictRead = strictReadLabel || false;
|
|
1335
1394
|
try {
|
|
1395
|
+
if (externalSourceConfig) return externalSourceConfig.untrack(fn);
|
|
1336
1396
|
return fn();
|
|
1337
1397
|
} finally {
|
|
1338
|
-
tracking =
|
|
1398
|
+
tracking = prevTracking;
|
|
1399
|
+
strictRead = prevStrictRead;
|
|
1339
1400
|
}
|
|
1340
1401
|
}
|
|
1341
1402
|
function read(el) {
|
|
@@ -1343,21 +1404,25 @@ function read(el) {
|
|
|
1343
1404
|
const pendingComputed = getLatestValueComputed(el);
|
|
1344
1405
|
const prevPending = latestReadActive;
|
|
1345
1406
|
latestReadActive = false;
|
|
1407
|
+
const visibleValue =
|
|
1408
|
+
el._overrideValue !== undefined && el._overrideValue !== NOT_PENDING
|
|
1409
|
+
? el._overrideValue
|
|
1410
|
+
: el._value;
|
|
1346
1411
|
let value;
|
|
1347
1412
|
try {
|
|
1348
1413
|
value = read(pendingComputed);
|
|
1349
1414
|
} catch (e) {
|
|
1350
|
-
if (!context && e instanceof NotReadyError) return
|
|
1415
|
+
if (!context && e instanceof NotReadyError) return visibleValue;
|
|
1351
1416
|
throw e;
|
|
1352
1417
|
} finally {
|
|
1353
1418
|
latestReadActive = prevPending;
|
|
1354
1419
|
}
|
|
1355
|
-
if (pendingComputed._statusFlags & STATUS_PENDING) return
|
|
1420
|
+
if (pendingComputed._statusFlags & STATUS_PENDING) return visibleValue;
|
|
1356
1421
|
if (stale && currentOptimisticLane && pendingComputed._optimisticLane) {
|
|
1357
1422
|
const pcLane = findLane(pendingComputed._optimisticLane);
|
|
1358
1423
|
const curLane = findLane(currentOptimisticLane);
|
|
1359
1424
|
if (pcLane !== curLane && pcLane._pendingAsync.size > 0) {
|
|
1360
|
-
return
|
|
1425
|
+
return visibleValue;
|
|
1361
1426
|
}
|
|
1362
1427
|
}
|
|
1363
1428
|
return value;
|
|
@@ -1383,8 +1448,8 @@ function read(el) {
|
|
|
1383
1448
|
const owner = el._firewall || el;
|
|
1384
1449
|
if (strictRead && owner._statusFlags & STATUS_PENDING) {
|
|
1385
1450
|
throw new Error(
|
|
1386
|
-
`Reading a pending async value in ${strictRead}. ` +
|
|
1387
|
-
`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).`
|
|
1388
1453
|
);
|
|
1389
1454
|
}
|
|
1390
1455
|
if (c && tracking) {
|
|
@@ -1409,11 +1474,11 @@ function read(el) {
|
|
|
1409
1474
|
const pendingLane = owner._optimisticLane;
|
|
1410
1475
|
const lane = findLane(currentOptimisticLane);
|
|
1411
1476
|
if (pendingLane && findLane(pendingLane) === lane && !hasActiveOverride(owner)) {
|
|
1412
|
-
if (!tracking) link(el, c);
|
|
1477
|
+
if (!tracking && el !== c) link(el, c);
|
|
1413
1478
|
throw owner._error;
|
|
1414
1479
|
}
|
|
1415
1480
|
} else {
|
|
1416
|
-
if (!tracking) link(el, c);
|
|
1481
|
+
if (!tracking && el !== c) link(el, c);
|
|
1417
1482
|
throw owner._error;
|
|
1418
1483
|
}
|
|
1419
1484
|
} else if (!c && owner._statusFlags & STATUS_UNINITIALIZED) {
|
|
@@ -1435,13 +1500,19 @@ function read(el) {
|
|
|
1435
1500
|
return snapshot;
|
|
1436
1501
|
}
|
|
1437
1502
|
}
|
|
1438
|
-
if (strictRead
|
|
1503
|
+
if (strictRead)
|
|
1439
1504
|
console.warn(
|
|
1440
|
-
`Reactive value read
|
|
1441
|
-
`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).`
|
|
1442
1507
|
);
|
|
1508
|
+
if (el._overrideValue !== undefined && el._overrideValue !== NOT_PENDING)
|
|
1509
|
+
return el._overrideValue;
|
|
1443
1510
|
return !c ||
|
|
1444
|
-
currentOptimisticLane !== null
|
|
1511
|
+
(currentOptimisticLane !== null &&
|
|
1512
|
+
(el._overrideValue !== undefined ||
|
|
1513
|
+
el._optimisticLane ||
|
|
1514
|
+
owner === el ||
|
|
1515
|
+
!!(owner._statusFlags & STATUS_PENDING))) ||
|
|
1445
1516
|
el._pendingValue === NOT_PENDING ||
|
|
1446
1517
|
(stale && el._transition && activeTransition !== el._transition)
|
|
1447
1518
|
? el._value
|
|
@@ -1452,9 +1523,12 @@ function setSignal(el, v) {
|
|
|
1452
1523
|
console.warn("A Signal was written to in an owned scope.");
|
|
1453
1524
|
if (el._transition && activeTransition !== el._transition)
|
|
1454
1525
|
globalQueue.initTransition(el._transition);
|
|
1455
|
-
const isOptimistic = el.
|
|
1526
|
+
const isOptimistic = el._overrideValue !== undefined && !projectionWriteActive;
|
|
1527
|
+
const hasOverride = el._overrideValue !== undefined && el._overrideValue !== NOT_PENDING;
|
|
1456
1528
|
const currentValue = isOptimistic
|
|
1457
|
-
?
|
|
1529
|
+
? hasOverride
|
|
1530
|
+
? el._overrideValue
|
|
1531
|
+
: el._value
|
|
1458
1532
|
: el._pendingValue === NOT_PENDING
|
|
1459
1533
|
? el._value
|
|
1460
1534
|
: el._pendingValue;
|
|
@@ -1462,27 +1536,23 @@ function setSignal(el, v) {
|
|
|
1462
1536
|
const valueChanged =
|
|
1463
1537
|
!el._equals || !el._equals(currentValue, v) || !!(el._statusFlags & STATUS_UNINITIALIZED);
|
|
1464
1538
|
if (!valueChanged) {
|
|
1465
|
-
if (isOptimistic &&
|
|
1539
|
+
if (isOptimistic && hasOverride && el._fn) {
|
|
1466
1540
|
insertSubs(el, true);
|
|
1467
1541
|
schedule();
|
|
1468
1542
|
}
|
|
1469
1543
|
return v;
|
|
1470
1544
|
}
|
|
1471
1545
|
if (isOptimistic) {
|
|
1472
|
-
const
|
|
1473
|
-
if (el._transition
|
|
1474
|
-
|
|
1475
|
-
}
|
|
1476
|
-
if (el._pendingValue === NOT_PENDING) {
|
|
1546
|
+
const firstOverride = el._overrideValue === NOT_PENDING;
|
|
1547
|
+
if (!firstOverride && el._transition) globalQueue.initTransition(el._transition);
|
|
1548
|
+
if (firstOverride) {
|
|
1477
1549
|
el._pendingValue = el._value;
|
|
1478
|
-
}
|
|
1479
|
-
if (!alreadyTracked) {
|
|
1480
1550
|
globalQueue._optimisticNodes.push(el);
|
|
1481
1551
|
}
|
|
1482
|
-
el.
|
|
1552
|
+
el._overrideSinceLane = true;
|
|
1483
1553
|
const lane = getOrCreateLane(el);
|
|
1484
1554
|
el._optimisticLane = lane;
|
|
1485
|
-
el.
|
|
1555
|
+
el._overrideValue = v;
|
|
1486
1556
|
} else {
|
|
1487
1557
|
if (el._pendingValue === NOT_PENDING) globalQueue._pendingNodes.push(el);
|
|
1488
1558
|
el._pendingValue = v;
|
|
@@ -1520,7 +1590,7 @@ function getPendingSignal(el) {
|
|
|
1520
1590
|
}
|
|
1521
1591
|
function computePendingState(el) {
|
|
1522
1592
|
const comp = el;
|
|
1523
|
-
if (el.
|
|
1593
|
+
if (el._overrideValue !== undefined && el._overrideValue !== NOT_PENDING) {
|
|
1524
1594
|
if (comp._statusFlags & STATUS_PENDING && !(comp._statusFlags & STATUS_UNINITIALIZED))
|
|
1525
1595
|
return true;
|
|
1526
1596
|
if (el._parentSource) {
|
|
@@ -1690,17 +1760,22 @@ function action(genFn) {
|
|
|
1690
1760
|
step();
|
|
1691
1761
|
});
|
|
1692
1762
|
}
|
|
1763
|
+
function accessor(node) {
|
|
1764
|
+
const fn = read.bind(null, node);
|
|
1765
|
+
fn.$r = true;
|
|
1766
|
+
return fn;
|
|
1767
|
+
}
|
|
1693
1768
|
function createSignal(first, second, third) {
|
|
1694
1769
|
if (typeof first === "function") {
|
|
1695
1770
|
const node = computed(first, second, third);
|
|
1696
|
-
return [
|
|
1771
|
+
return [accessor(node), setSignal.bind(null, node)];
|
|
1697
1772
|
}
|
|
1698
1773
|
const node = signal(first, second);
|
|
1699
|
-
return [
|
|
1774
|
+
return [accessor(node), setSignal.bind(null, node)];
|
|
1700
1775
|
}
|
|
1701
1776
|
function createMemo(compute, value, options) {
|
|
1702
1777
|
let node = computed(compute, value, options);
|
|
1703
|
-
return
|
|
1778
|
+
return accessor(node);
|
|
1704
1779
|
}
|
|
1705
1780
|
function createEffect(compute, effectFn, value, options) {
|
|
1706
1781
|
effect(compute, effectFn.effect || effectFn, effectFn.error, value, {
|
|
@@ -1757,7 +1832,7 @@ function createOptimistic(first, second, third) {
|
|
|
1757
1832
|
typeof first === "function"
|
|
1758
1833
|
? optimisticComputed(first, second, third)
|
|
1759
1834
|
: optimisticSignal(first, second);
|
|
1760
|
-
return [
|
|
1835
|
+
return [accessor(node), setSignal.bind(null, node)];
|
|
1761
1836
|
}
|
|
1762
1837
|
function onSettled(callback) {
|
|
1763
1838
|
getOwner()
|
|
@@ -1779,7 +1854,7 @@ function getAllKeys(value, override, next) {
|
|
|
1779
1854
|
const nextKeys = Object.keys(next);
|
|
1780
1855
|
return Array.from(new Set([...keys, ...nextKeys]));
|
|
1781
1856
|
}
|
|
1782
|
-
function applyState(next, state, keyFn
|
|
1857
|
+
function applyState(next, state, keyFn) {
|
|
1783
1858
|
const target = state?.[$TARGET];
|
|
1784
1859
|
if (!target) return;
|
|
1785
1860
|
const previous = target[STORE_VALUE];
|
|
@@ -1802,7 +1877,7 @@ function applyState(next, state, keyFn, all) {
|
|
|
1802
1877
|
(item && next[start] && keyFn(item) === keyFn(next[start])));
|
|
1803
1878
|
start++
|
|
1804
1879
|
) {
|
|
1805
|
-
applyState(next[start], wrap(item, target), keyFn
|
|
1880
|
+
applyState(next[start], wrap(item, target), keyFn);
|
|
1806
1881
|
}
|
|
1807
1882
|
const temp = new Array(next.length),
|
|
1808
1883
|
newIndices = new Map();
|
|
@@ -1825,7 +1900,7 @@ function applyState(next, state, keyFn, all) {
|
|
|
1825
1900
|
changed = true;
|
|
1826
1901
|
const wrapped = wrap(temp[j], target);
|
|
1827
1902
|
target[STORE_NODE][j] && setSignal(target[STORE_NODE][j], wrapped);
|
|
1828
|
-
applyState(next[j], wrapped, keyFn
|
|
1903
|
+
applyState(next[j], wrapped, keyFn);
|
|
1829
1904
|
}
|
|
1830
1905
|
changed && target[STORE_NODE][$TRACK] && setSignal(target[STORE_NODE][$TRACK], void 0);
|
|
1831
1906
|
prevLength !== next.length &&
|
|
@@ -1855,7 +1930,7 @@ function applyState(next, state, keyFn, all) {
|
|
|
1855
1930
|
if (j in temp) {
|
|
1856
1931
|
const wrapped = wrap(temp[j], target);
|
|
1857
1932
|
target[STORE_NODE][j] && setSignal(target[STORE_NODE][j], wrapped);
|
|
1858
|
-
applyState(next[j], wrapped, keyFn
|
|
1933
|
+
applyState(next[j], wrapped, keyFn);
|
|
1859
1934
|
} else target[STORE_NODE][j] && setSignal(target[STORE_NODE][j], wrap(next[j], target));
|
|
1860
1935
|
}
|
|
1861
1936
|
if (start < next.length) changed = true;
|
|
@@ -1863,7 +1938,7 @@ function applyState(next, state, keyFn, all) {
|
|
|
1863
1938
|
for (let i = 0, len = next.length; i < len; i++) {
|
|
1864
1939
|
const item = getOverrideValue(previous, override, nodes, i, optOverride);
|
|
1865
1940
|
isWrappable(item)
|
|
1866
|
-
? applyState(next[i], wrap(item, target), keyFn
|
|
1941
|
+
? applyState(next[i], wrap(item, target), keyFn)
|
|
1867
1942
|
: target[STORE_NODE][i] && setSignal(target[STORE_NODE][i], next[i]);
|
|
1868
1943
|
}
|
|
1869
1944
|
}
|
|
@@ -1876,7 +1951,7 @@ function applyState(next, state, keyFn, all) {
|
|
|
1876
1951
|
}
|
|
1877
1952
|
if (nodes) {
|
|
1878
1953
|
const tracked = nodes[$TRACK];
|
|
1879
|
-
const keys = tracked
|
|
1954
|
+
const keys = tracked ? getAllKeys(previous, override, next) : Object.keys(nodes);
|
|
1880
1955
|
for (let i = 0, len = keys.length; i < len; i++) {
|
|
1881
1956
|
const key = keys[i];
|
|
1882
1957
|
const node = nodes[key];
|
|
@@ -1891,7 +1966,7 @@ function applyState(next, state, keyFn, all) {
|
|
|
1891
1966
|
) {
|
|
1892
1967
|
tracked && setSignal(tracked, void 0);
|
|
1893
1968
|
node && setSignal(node, isWrappable(nextValue) ? wrap(nextValue, target) : nextValue);
|
|
1894
|
-
} else applyState(nextValue, wrap(previousValue, target), keyFn
|
|
1969
|
+
} else applyState(nextValue, wrap(previousValue, target), keyFn);
|
|
1895
1970
|
}
|
|
1896
1971
|
}
|
|
1897
1972
|
if ((nodes = target[STORE_HAS])) {
|
|
@@ -1902,14 +1977,14 @@ function applyState(next, state, keyFn, all) {
|
|
|
1902
1977
|
}
|
|
1903
1978
|
}
|
|
1904
1979
|
}
|
|
1905
|
-
function reconcile(value, key
|
|
1980
|
+
function reconcile(value, key) {
|
|
1906
1981
|
return state => {
|
|
1907
1982
|
if (state == null) throw new Error("Cannot reconcile null or undefined state");
|
|
1908
1983
|
const keyFn = typeof key === "string" ? item => item[key] : key;
|
|
1909
1984
|
const eq = keyFn(state);
|
|
1910
1985
|
if (eq !== undefined && keyFn(value) !== keyFn(state))
|
|
1911
1986
|
throw new Error("Cannot reconcile states with different identity");
|
|
1912
|
-
applyState(value, state, keyFn
|
|
1987
|
+
applyState(value, state, keyFn);
|
|
1913
1988
|
};
|
|
1914
1989
|
}
|
|
1915
1990
|
function createProjectionInternal(fn, initialValue = {}, options) {
|
|
@@ -1939,12 +2014,9 @@ function createProjectionInternal(fn, initialValue = {}, options) {
|
|
|
1939
2014
|
const value = handleAsync(owner, fn(s), value => {
|
|
1940
2015
|
value !== s &&
|
|
1941
2016
|
value !== undefined &&
|
|
1942
|
-
storeSetter(wrappedStore, reconcile(value, options?.key || "id"
|
|
1943
|
-
setSignal(owner, undefined);
|
|
2017
|
+
storeSetter(wrappedStore, reconcile(value, options?.key || "id"));
|
|
1944
2018
|
});
|
|
1945
|
-
value !== s &&
|
|
1946
|
-
value !== undefined &&
|
|
1947
|
-
reconcile(value, options?.key || "id", options?.all)(wrappedStore);
|
|
2019
|
+
value !== s && value !== undefined && reconcile(value, options?.key || "id")(wrappedStore);
|
|
1948
2020
|
});
|
|
1949
2021
|
});
|
|
1950
2022
|
node._preventAutoDisposal = true;
|
|
@@ -1990,11 +2062,9 @@ const writeTraps = {
|
|
|
1990
2062
|
}
|
|
1991
2063
|
};
|
|
1992
2064
|
const $TRACK = Symbol("STORE_TRACK"),
|
|
1993
|
-
$DEEP = Symbol("STORE_DEEP"),
|
|
1994
2065
|
$TARGET = Symbol("STORE_TARGET"),
|
|
1995
2066
|
$PROXY = Symbol("STORE_PROXY"),
|
|
1996
2067
|
$DELETED = Symbol("STORE_DELETED");
|
|
1997
|
-
const PARENTS = new WeakMap();
|
|
1998
2068
|
const STORE_VALUE = "v",
|
|
1999
2069
|
STORE_OVERRIDE = "o",
|
|
2000
2070
|
STORE_OPTIMISTIC_OVERRIDE = "x",
|
|
@@ -2047,7 +2117,9 @@ function getNode(nodes, property, value, firewall, equals = isEqual, optimistic,
|
|
|
2047
2117
|
},
|
|
2048
2118
|
firewall
|
|
2049
2119
|
);
|
|
2050
|
-
if (optimistic)
|
|
2120
|
+
if (optimistic) {
|
|
2121
|
+
s._overrideValue = NOT_PENDING;
|
|
2122
|
+
}
|
|
2051
2123
|
if (snapshotProps && property in snapshotProps) {
|
|
2052
2124
|
const sv = snapshotProps[property];
|
|
2053
2125
|
s._snapshotValue = sv === undefined ? NO_SNAPSHOT : sv;
|
|
@@ -2093,8 +2165,8 @@ const storeTraps = {
|
|
|
2093
2165
|
if (property === $TARGET) return target;
|
|
2094
2166
|
if (property === $PROXY) return receiver;
|
|
2095
2167
|
if (property === $REFRESH) return target[STORE_FIREWALL];
|
|
2096
|
-
if (property === $TRACK
|
|
2097
|
-
trackSelf(target
|
|
2168
|
+
if (property === $TRACK) {
|
|
2169
|
+
trackSelf(target);
|
|
2098
2170
|
return receiver;
|
|
2099
2171
|
}
|
|
2100
2172
|
const nodes = getNodes(target, STORE_NODE);
|
|
@@ -2116,11 +2188,11 @@ const storeTraps = {
|
|
|
2116
2188
|
if (writeOnly(receiver)) {
|
|
2117
2189
|
let value =
|
|
2118
2190
|
tracked && (overridden || !proxySource)
|
|
2119
|
-
? tracked.
|
|
2120
|
-
? tracked.
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2191
|
+
? tracked._overrideValue !== undefined && tracked._overrideValue !== NOT_PENDING
|
|
2192
|
+
? tracked._overrideValue
|
|
2193
|
+
: tracked._pendingValue !== NOT_PENDING
|
|
2194
|
+
? tracked._pendingValue
|
|
2195
|
+
: tracked._value
|
|
2124
2196
|
: storeValue[property];
|
|
2125
2197
|
value === $DELETED && (value = undefined);
|
|
2126
2198
|
if (!isWrappable(value)) return value;
|
|
@@ -2156,10 +2228,10 @@ const storeTraps = {
|
|
|
2156
2228
|
);
|
|
2157
2229
|
}
|
|
2158
2230
|
}
|
|
2159
|
-
if (strictRead &&
|
|
2231
|
+
if (strictRead && typeof property === "string")
|
|
2160
2232
|
console.warn(
|
|
2161
|
-
`Reactive value read
|
|
2162
|
-
`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).`
|
|
2163
2235
|
);
|
|
2164
2236
|
return isWrappable(value) ? wrap(value, target) : value;
|
|
2165
2237
|
},
|
|
@@ -2196,7 +2268,11 @@ const storeTraps = {
|
|
|
2196
2268
|
untrack(() => {
|
|
2197
2269
|
const state = target[STORE_VALUE];
|
|
2198
2270
|
const base = state[property];
|
|
2199
|
-
if (
|
|
2271
|
+
if (
|
|
2272
|
+
snapshotCaptureActive &&
|
|
2273
|
+
typeof property !== "symbol" &&
|
|
2274
|
+
!((target[STORE_FIREWALL]?._statusFlags ?? 0) & STATUS_PENDING)
|
|
2275
|
+
) {
|
|
2200
2276
|
if (!target[STORE_SNAPSHOT_PROPS]) {
|
|
2201
2277
|
target[STORE_SNAPSHOT_PROPS] = Object.create(null);
|
|
2202
2278
|
snapshotSources?.add(target);
|
|
@@ -2223,11 +2299,6 @@ const storeTraps = {
|
|
|
2223
2299
|
if (value !== undefined && value === base) delete target[overrideKey][property];
|
|
2224
2300
|
else (target[overrideKey] || (target[overrideKey] = Object.create(null)))[property] = value;
|
|
2225
2301
|
const wrappable = isWrappable(value);
|
|
2226
|
-
if (isWrappable(prev)) {
|
|
2227
|
-
const parents = PARENTS.get(prev);
|
|
2228
|
-
parents && (parents instanceof Set ? parents.delete(store) : PARENTS.delete(prev));
|
|
2229
|
-
}
|
|
2230
|
-
if (recursivelyNotify(store, storeLookup) && wrappable) recursivelyAddParent(value, store);
|
|
2231
2302
|
target[STORE_HAS]?.[property] && setSignal(target[STORE_HAS][property], true);
|
|
2232
2303
|
const nodes = getNodes(target, STORE_NODE);
|
|
2233
2304
|
nodes[property] &&
|
|
@@ -2267,10 +2338,6 @@ const storeTraps = {
|
|
|
2267
2338
|
} else if (target[overrideKey] && property in target[overrideKey]) {
|
|
2268
2339
|
delete target[overrideKey][property];
|
|
2269
2340
|
} else return true;
|
|
2270
|
-
if (isWrappable(prev)) {
|
|
2271
|
-
const parents = PARENTS.get(prev);
|
|
2272
|
-
parents && (parents instanceof Set ? parents.delete(target) : PARENTS.delete(prev));
|
|
2273
|
-
}
|
|
2274
2341
|
if (target[STORE_HAS]?.[property]) setSignal(target[STORE_HAS][property], false);
|
|
2275
2342
|
const nodes = getNodes(target, STORE_NODE);
|
|
2276
2343
|
nodes[property] && setSignal(nodes[property], undefined);
|
|
@@ -2341,59 +2408,6 @@ function createStore(first, second, options) {
|
|
|
2341
2408
|
wrappedStore = derived ? createProjectionInternal(first, second, options).store : wrap(first);
|
|
2342
2409
|
return [wrappedStore, fn => storeSetter(wrappedStore, fn)];
|
|
2343
2410
|
}
|
|
2344
|
-
function recursivelyNotify(state, lookup) {
|
|
2345
|
-
let target = state[$TARGET] || lookup?.get(state)?.[$TARGET];
|
|
2346
|
-
let notified = false;
|
|
2347
|
-
if (target) {
|
|
2348
|
-
const deep = getNodes(target, STORE_NODE)[$DEEP];
|
|
2349
|
-
if (deep) {
|
|
2350
|
-
setSignal(deep, undefined);
|
|
2351
|
-
notified = true;
|
|
2352
|
-
}
|
|
2353
|
-
lookup = target[STORE_LOOKUP] || lookup;
|
|
2354
|
-
}
|
|
2355
|
-
const parents = PARENTS.get(target?.[STORE_VALUE] || state);
|
|
2356
|
-
if (!parents) return notified;
|
|
2357
|
-
if (parents instanceof Set) {
|
|
2358
|
-
for (let parent of parents) notified = recursivelyNotify(parent, lookup) || notified;
|
|
2359
|
-
} else notified = recursivelyNotify(parents, lookup) || notified;
|
|
2360
|
-
return notified;
|
|
2361
|
-
}
|
|
2362
|
-
function recursivelyAddParent(state, parent) {
|
|
2363
|
-
let override;
|
|
2364
|
-
const target = state[$TARGET];
|
|
2365
|
-
if (target) {
|
|
2366
|
-
override = target[STORE_OVERRIDE];
|
|
2367
|
-
state = target[STORE_VALUE];
|
|
2368
|
-
}
|
|
2369
|
-
if (parent) {
|
|
2370
|
-
let parents = PARENTS.get(state);
|
|
2371
|
-
if (!parents) PARENTS.set(state, parent);
|
|
2372
|
-
else if (parents !== parent) {
|
|
2373
|
-
if (!(parents instanceof Set)) PARENTS.set(state, (parents = new Set([parents])));
|
|
2374
|
-
else if (parents.has(parent)) return;
|
|
2375
|
-
parents.add(parent);
|
|
2376
|
-
} else return;
|
|
2377
|
-
}
|
|
2378
|
-
if (Array.isArray(state)) {
|
|
2379
|
-
const len = override?.length || state.length;
|
|
2380
|
-
for (let i = 0; i < len; i++) {
|
|
2381
|
-
const item = override && i in override ? override[i] : state[i];
|
|
2382
|
-
isWrappable(item) && recursivelyAddParent(item, state);
|
|
2383
|
-
}
|
|
2384
|
-
} else {
|
|
2385
|
-
const keys = getKeys(state, override);
|
|
2386
|
-
for (let i = 0; i < keys.length; i++) {
|
|
2387
|
-
const key = keys[i];
|
|
2388
|
-
const item = override && key in override ? override[key] : state[key];
|
|
2389
|
-
isWrappable(item) && recursivelyAddParent(item, state);
|
|
2390
|
-
}
|
|
2391
|
-
}
|
|
2392
|
-
}
|
|
2393
|
-
function deep(store) {
|
|
2394
|
-
recursivelyAddParent(store);
|
|
2395
|
-
return store[$DEEP];
|
|
2396
|
-
}
|
|
2397
2411
|
function createOptimisticStore(first, second, options) {
|
|
2398
2412
|
GlobalQueue._clearOptimisticStore ||= clearOptimisticStore;
|
|
2399
2413
|
const derived = typeof first === "function";
|
|
@@ -2464,14 +2478,14 @@ function createOptimisticProjectionInternal(fn, initialValue = {}, options) {
|
|
|
2464
2478
|
try {
|
|
2465
2479
|
value !== s &&
|
|
2466
2480
|
value !== undefined &&
|
|
2467
|
-
storeSetter(wrappedStore, reconcile(value, options?.key || "id"
|
|
2481
|
+
storeSetter(wrappedStore, reconcile(value, options?.key || "id"));
|
|
2468
2482
|
} finally {
|
|
2469
2483
|
setProjectionWriteActive(false);
|
|
2470
2484
|
}
|
|
2471
2485
|
});
|
|
2472
2486
|
value !== s &&
|
|
2473
2487
|
value !== undefined &&
|
|
2474
|
-
reconcile(value, options?.key || "id"
|
|
2488
|
+
reconcile(value, options?.key || "id")(wrappedStore);
|
|
2475
2489
|
});
|
|
2476
2490
|
} finally {
|
|
2477
2491
|
setProjectionWriteActive(false);
|
|
@@ -2546,12 +2560,13 @@ const storePath = Object.assign(
|
|
|
2546
2560
|
},
|
|
2547
2561
|
{ DELETE: DELETE }
|
|
2548
2562
|
);
|
|
2549
|
-
function
|
|
2563
|
+
function snapshotImpl(item, track, map, lookup) {
|
|
2550
2564
|
let target, isArray, override, result, unwrapped, v;
|
|
2551
2565
|
if (!isWrappable(item)) return item;
|
|
2552
2566
|
if (map && map.has(item)) return map.get(item);
|
|
2553
2567
|
if (!map) map = new Map();
|
|
2554
2568
|
if ((target = item[$TARGET] || lookup?.get(item)?.[$TARGET])) {
|
|
2569
|
+
if (track) trackSelf(target, $TRACK);
|
|
2555
2570
|
override = target[STORE_OVERRIDE];
|
|
2556
2571
|
isArray = Array.isArray(target[STORE_VALUE]);
|
|
2557
2572
|
map.set(
|
|
@@ -2571,7 +2586,8 @@ function snapshot(item, map, lookup) {
|
|
|
2571
2586
|
for (let i = 0; i < len; i++) {
|
|
2572
2587
|
v = override && i in override ? override[i] : item[i];
|
|
2573
2588
|
if (v === $DELETED) continue;
|
|
2574
|
-
if (
|
|
2589
|
+
if (track && isWrappable(v)) wrap(v, target);
|
|
2590
|
+
if ((unwrapped = snapshotImpl(v, track, map, lookup)) !== v || result) {
|
|
2575
2591
|
if (!result) map.set(item, (result = [...item]));
|
|
2576
2592
|
result[i] = unwrapped;
|
|
2577
2593
|
}
|
|
@@ -2583,7 +2599,8 @@ function snapshot(item, map, lookup) {
|
|
|
2583
2599
|
const desc = getPropertyDescriptor(item, override, prop);
|
|
2584
2600
|
if (desc.get) continue;
|
|
2585
2601
|
v = override && prop in override ? override[prop] : item[prop];
|
|
2586
|
-
if (
|
|
2602
|
+
if (track && isWrappable(v)) wrap(v, target);
|
|
2603
|
+
if ((unwrapped = snapshotImpl(v, track, map, lookup)) !== item[prop] || result) {
|
|
2587
2604
|
if (!result) {
|
|
2588
2605
|
result = Object.create(Object.getPrototypeOf(item));
|
|
2589
2606
|
Object.assign(result, item);
|
|
@@ -2594,6 +2611,12 @@ function snapshot(item, map, lookup) {
|
|
|
2594
2611
|
}
|
|
2595
2612
|
return result || item;
|
|
2596
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
|
+
}
|
|
2597
2620
|
function trueFn() {
|
|
2598
2621
|
return true;
|
|
2599
2622
|
}
|
|
@@ -2769,15 +2792,15 @@ function updateKeyedMap() {
|
|
|
2769
2792
|
this._rows[j] = signal(newItems[j], pureOptions);
|
|
2770
2793
|
this._indexes && (this._indexes[j] = signal(j, pureOptions));
|
|
2771
2794
|
return this._map(
|
|
2772
|
-
|
|
2773
|
-
this._indexes ?
|
|
2795
|
+
accessor(this._rows[j]),
|
|
2796
|
+
this._indexes ? accessor(this._indexes[j]) : undefined
|
|
2774
2797
|
);
|
|
2775
2798
|
}
|
|
2776
2799
|
: this._indexes
|
|
2777
2800
|
? () => {
|
|
2778
2801
|
const item = newItems[j];
|
|
2779
2802
|
this._indexes[j] = signal(j, pureOptions);
|
|
2780
|
-
return this._map(() => item,
|
|
2803
|
+
return this._map(() => item, accessor(this._indexes[j]));
|
|
2781
2804
|
}
|
|
2782
2805
|
: () => {
|
|
2783
2806
|
const item = newItems[j];
|
|
@@ -2981,11 +3004,14 @@ function createBoundChildren(owner, fn, queue, mask) {
|
|
|
2981
3004
|
return boundaryComputed(() => staleValues(() => flatten(read(c))), mask);
|
|
2982
3005
|
});
|
|
2983
3006
|
}
|
|
3007
|
+
const ON_INIT = Symbol();
|
|
2984
3008
|
class CollectionQueue extends Queue {
|
|
2985
3009
|
_collectionType;
|
|
2986
3010
|
_sources = new Set();
|
|
2987
3011
|
_disabled = signal(false, { pureWrite: true });
|
|
2988
3012
|
_initialized = false;
|
|
3013
|
+
_onFn;
|
|
3014
|
+
_prevOn = ON_INIT;
|
|
2989
3015
|
constructor(type) {
|
|
2990
3016
|
super();
|
|
2991
3017
|
this._collectionType = type;
|
|
@@ -2995,10 +3021,22 @@ class CollectionQueue extends Queue {
|
|
|
2995
3021
|
return super.run(type);
|
|
2996
3022
|
}
|
|
2997
3023
|
notify(node, type, flags, error) {
|
|
2998
|
-
if (
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
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)
|
|
3002
3040
|
return super.notify(node, type, flags, error);
|
|
3003
3041
|
if (flags & this._collectionType) {
|
|
3004
3042
|
const source = error?.source || node._error?.source;
|
|
@@ -3015,12 +3053,20 @@ class CollectionQueue extends Queue {
|
|
|
3015
3053
|
for (const source of this._sources) {
|
|
3016
3054
|
if (!(source._statusFlags & this._collectionType)) this._sources.delete(source);
|
|
3017
3055
|
}
|
|
3018
|
-
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
|
+
}
|
|
3019
3064
|
}
|
|
3020
3065
|
}
|
|
3021
|
-
function createCollectionBoundary(type, fn, fallback) {
|
|
3066
|
+
function createCollectionBoundary(type, fn, fallback, onFn) {
|
|
3022
3067
|
const owner = createOwner();
|
|
3023
3068
|
const queue = new CollectionQueue(type);
|
|
3069
|
+
if (onFn) queue._onFn = onFn;
|
|
3024
3070
|
const tree = createBoundChildren(owner, fn, queue, type);
|
|
3025
3071
|
const decision = computed(() => {
|
|
3026
3072
|
if (!read(queue._disabled)) {
|
|
@@ -3032,10 +3078,10 @@ function createCollectionBoundary(type, fn, fallback) {
|
|
|
3032
3078
|
}
|
|
3033
3079
|
return fallback(queue);
|
|
3034
3080
|
});
|
|
3035
|
-
return
|
|
3081
|
+
return accessor(decision);
|
|
3036
3082
|
}
|
|
3037
|
-
function
|
|
3038
|
-
return createCollectionBoundary(STATUS_PENDING, fn, () => fallback());
|
|
3083
|
+
function createLoadingBoundary(fn, fallback, options) {
|
|
3084
|
+
return createCollectionBoundary(STATUS_PENDING, fn, () => fallback(), options?.on);
|
|
3039
3085
|
}
|
|
3040
3086
|
function createErrorBoundary(fn, fallback) {
|
|
3041
3087
|
return createCollectionBoundary(STATUS_ERROR, fn, queue => {
|
|
@@ -3105,6 +3151,7 @@ function flattenArray(children, results = [], options) {
|
|
|
3105
3151
|
}
|
|
3106
3152
|
export {
|
|
3107
3153
|
$PROXY,
|
|
3154
|
+
$REFRESH,
|
|
3108
3155
|
$TARGET,
|
|
3109
3156
|
$TRACK,
|
|
3110
3157
|
ContextNotFoundError,
|
|
@@ -3116,7 +3163,7 @@ export {
|
|
|
3116
3163
|
createContext,
|
|
3117
3164
|
createEffect,
|
|
3118
3165
|
createErrorBoundary,
|
|
3119
|
-
|
|
3166
|
+
createLoadingBoundary,
|
|
3120
3167
|
createMemo,
|
|
3121
3168
|
createOptimistic,
|
|
3122
3169
|
createOptimisticStore,
|
|
@@ -3129,6 +3176,8 @@ export {
|
|
|
3129
3176
|
createStore,
|
|
3130
3177
|
createTrackedEffect,
|
|
3131
3178
|
deep,
|
|
3179
|
+
enableExternalSource,
|
|
3180
|
+
enforceLoadingBoundary,
|
|
3132
3181
|
flatten,
|
|
3133
3182
|
flush,
|
|
3134
3183
|
getContext,
|
|
@@ -3156,7 +3205,6 @@ export {
|
|
|
3156
3205
|
runWithOwner,
|
|
3157
3206
|
setContext,
|
|
3158
3207
|
setSnapshotCapture,
|
|
3159
|
-
setStrictRead,
|
|
3160
3208
|
snapshot,
|
|
3161
3209
|
storePath,
|
|
3162
3210
|
untrack
|