@solidjs/signals 2.0.0-beta.17 → 2.0.0-beta.18
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 +4 -3
- package/dist/dev.js +343 -82
- package/dist/node.cjs +1856 -1619
- package/dist/prod.js +1719 -1488
- package/dist/types/affects.d.ts +47 -0
- package/dist/types/boundaries.d.ts +2 -2
- package/dist/types/core/async.d.ts +39 -2
- package/dist/types/core/constants.d.ts +8 -0
- package/dist/types/core/core.d.ts +9 -0
- package/dist/types/core/dev.d.ts +1 -1
- package/dist/types/core/index.d.ts +1 -1
- package/dist/types/core/invariants.d.ts +10 -0
- package/dist/types/core/scheduler.d.ts +43 -0
- package/dist/types/core/types.d.ts +22 -5
- package/dist/types/index.d.ts +1 -0
- package/dist/types/store/store.d.ts +32 -14
- package/dist/types-cjs/affects.d.cts +47 -0
- package/dist/types-cjs/boundaries.d.cts +2 -2
- package/dist/types-cjs/core/async.d.cts +39 -2
- package/dist/types-cjs/core/constants.d.cts +8 -0
- package/dist/types-cjs/core/core.d.cts +9 -0
- package/dist/types-cjs/core/dev.d.cts +1 -1
- package/dist/types-cjs/core/index.d.cts +1 -1
- package/dist/types-cjs/core/invariants.d.cts +10 -0
- package/dist/types-cjs/core/scheduler.d.cts +43 -0
- package/dist/types-cjs/core/types.d.cts +22 -5
- package/dist/types-cjs/index.d.cts +1 -0
- package/dist/types-cjs/store/store.d.cts +32 -14
- package/package.json +1 -1
package/dist/dev.js
CHANGED
|
@@ -39,6 +39,7 @@ const REACTIVE_OPTIMISTIC_DIRTY = 1 << 7;
|
|
|
39
39
|
const REACTIVE_SNAPSHOT_STALE = 1 << 8;
|
|
40
40
|
const REACTIVE_LAZY = 1 << 9;
|
|
41
41
|
const REACTIVE_MANUAL_WRITE = 1 << 10;
|
|
42
|
+
const REACTIVE_REASK = 1 << 11;
|
|
42
43
|
const CONFIG_OWNED_WRITE = 1 << 0;
|
|
43
44
|
const CONFIG_NO_SNAPSHOT = 1 << 1;
|
|
44
45
|
const CONFIG_TRANSPARENT = 1 << 2;
|
|
@@ -256,6 +257,7 @@ function canUseSimpleSyncFlush(queue) {
|
|
|
256
257
|
activeLanes.size === 0 &&
|
|
257
258
|
queue._children.length === 0 &&
|
|
258
259
|
queue._optimisticNodes.length === 0 &&
|
|
260
|
+
queue._affectsNodes.length === 0 &&
|
|
259
261
|
queue._optimisticStores.size === 0 &&
|
|
260
262
|
transientStoreNodes.size === 0
|
|
261
263
|
);
|
|
@@ -269,6 +271,7 @@ function sweepTransientStoreNodes() {
|
|
|
269
271
|
}
|
|
270
272
|
if (node._pendingValue !== NOT_PENDING) continue;
|
|
271
273
|
if (node._overrideValue !== undefined && node._overrideValue !== NOT_PENDING) continue;
|
|
274
|
+
if (node._affectsCount) continue;
|
|
272
275
|
transientStoreNodes.delete(node);
|
|
273
276
|
node._unobserved?.();
|
|
274
277
|
}
|
|
@@ -319,6 +322,10 @@ function mergeTransitionState(target, outgoing) {
|
|
|
319
322
|
target._actions.push(...outgoing._actions);
|
|
320
323
|
for (const lane of activeLanes) if (lane._transition === outgoing) lane._transition = target;
|
|
321
324
|
target._optimisticNodes.push(...outgoing._optimisticNodes);
|
|
325
|
+
if (outgoing._affectsNodes.length) {
|
|
326
|
+
target._affectsNodes.push(...outgoing._affectsNodes);
|
|
327
|
+
outgoing._affectsNodes.length = 0;
|
|
328
|
+
}
|
|
322
329
|
for (const store of outgoing._optimisticStores) target._optimisticStores.add(store);
|
|
323
330
|
for (const [source, reporters] of outgoing._asyncReporters) {
|
|
324
331
|
let targetReporters = target._asyncReporters.get(source);
|
|
@@ -469,11 +476,15 @@ class GlobalQueue extends Queue {
|
|
|
469
476
|
_pendingNode = null;
|
|
470
477
|
_pendingNodes = [];
|
|
471
478
|
_optimisticNodes = [];
|
|
479
|
+
_affectsNodes = [];
|
|
472
480
|
_optimisticStores = new Set();
|
|
473
481
|
static _update;
|
|
474
482
|
static _dispose;
|
|
475
483
|
static _runEffect;
|
|
476
484
|
static _clearOptimisticStore = null;
|
|
485
|
+
static _releaseAffectsScope = null;
|
|
486
|
+
static _propagateAffects = null;
|
|
487
|
+
static _settleAffects = null;
|
|
477
488
|
flush() {
|
|
478
489
|
if (this._running) return;
|
|
479
490
|
this._running = true;
|
|
@@ -488,6 +499,7 @@ class GlobalQueue extends Queue {
|
|
|
488
499
|
this._pendingNode = null;
|
|
489
500
|
this._pendingNodes = [];
|
|
490
501
|
this._optimisticNodes = [];
|
|
502
|
+
this._affectsNodes = [];
|
|
491
503
|
this._optimisticStores = new Set();
|
|
492
504
|
runLaneEffects(EFFECT_RENDER);
|
|
493
505
|
runLaneEffects(EFFECT_USER);
|
|
@@ -593,6 +605,7 @@ class GlobalQueue extends Queue {
|
|
|
593
605
|
_pendingNodes: [],
|
|
594
606
|
_asyncReporters: createAsyncReporters(),
|
|
595
607
|
_optimisticNodes: [],
|
|
608
|
+
_affectsNodes: [],
|
|
596
609
|
_optimisticStores: new Set(),
|
|
597
610
|
_actions: [],
|
|
598
611
|
_queueStash: { _queues: [[], []], _children: [] },
|
|
@@ -628,6 +641,10 @@ class GlobalQueue extends Queue {
|
|
|
628
641
|
}
|
|
629
642
|
this._optimisticNodes = activeTransition._optimisticNodes;
|
|
630
643
|
}
|
|
644
|
+
if (this._affectsNodes !== activeTransition._affectsNodes) {
|
|
645
|
+
activeTransition._affectsNodes.push(...this._affectsNodes);
|
|
646
|
+
this._affectsNodes = activeTransition._affectsNodes;
|
|
647
|
+
}
|
|
631
648
|
for (const lane of activeLanes) {
|
|
632
649
|
if (!lane._transition) lane._transition = activeTransition;
|
|
633
650
|
}
|
|
@@ -652,10 +669,16 @@ function queuePendingNode(node) {
|
|
|
652
669
|
}
|
|
653
670
|
globalQueue._pendingNodes.push(node);
|
|
654
671
|
}
|
|
672
|
+
let reaskArmed = false;
|
|
673
|
+
function armReaskClear() {
|
|
674
|
+
reaskArmed = true;
|
|
675
|
+
}
|
|
655
676
|
function insertSubs(node, optimistic = false) {
|
|
656
677
|
const sourceLane = node._optimisticLane || currentOptimisticLane;
|
|
657
678
|
const hasSnapshot = node._snapshotValue !== undefined;
|
|
679
|
+
const clearReask = reaskArmed;
|
|
658
680
|
for (let s = node._subs; s !== null; s = s._nextSub) {
|
|
681
|
+
if (clearReask) s._sub._flags &= ~REACTIVE_REASK;
|
|
659
682
|
if (hasSnapshot && s._sub._config & CONFIG_IN_SNAPSHOT_SCOPE) {
|
|
660
683
|
s._sub._flags |= REACTIVE_SNAPSHOT_STALE;
|
|
661
684
|
continue;
|
|
@@ -739,6 +762,9 @@ function finalizePureQueue(completingTransition = null, incomplete = false) {
|
|
|
739
762
|
}
|
|
740
763
|
completingTransition._gatedSubs.clear();
|
|
741
764
|
}
|
|
765
|
+
releaseAffectsMarks(
|
|
766
|
+
completingTransition ? completingTransition._affectsNodes : globalQueue._affectsNodes
|
|
767
|
+
);
|
|
742
768
|
const optimisticStores = completingTransition
|
|
743
769
|
? completingTransition._optimisticStores
|
|
744
770
|
: globalQueue._optimisticStores;
|
|
@@ -763,6 +789,32 @@ function trackOptimisticStore(store) {
|
|
|
763
789
|
globalQueue._optimisticStores.add(store);
|
|
764
790
|
schedule();
|
|
765
791
|
}
|
|
792
|
+
let activeAffectsMarks = 0;
|
|
793
|
+
function markAffects(node) {
|
|
794
|
+
node._affectsCount = (node._affectsCount || 0) + 1;
|
|
795
|
+
activeAffectsMarks++;
|
|
796
|
+
if (node._affectsCount === 1) updatePendingSignal(node);
|
|
797
|
+
}
|
|
798
|
+
function registerAffectsMark(node) {
|
|
799
|
+
markAffects(node);
|
|
800
|
+
globalQueue._affectsNodes.push(node);
|
|
801
|
+
GlobalQueue._propagateAffects?.(node);
|
|
802
|
+
schedule();
|
|
803
|
+
}
|
|
804
|
+
function releaseAffectsMark(node) {
|
|
805
|
+
activeAffectsMarks--;
|
|
806
|
+
node._affectsCount--;
|
|
807
|
+
if (!node._affectsCount) {
|
|
808
|
+
GlobalQueue._settleAffects?.(node);
|
|
809
|
+
snapCompanionsToState(node);
|
|
810
|
+
GlobalQueue._releaseAffectsScope?.(node);
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
function releaseAffectsMarks(nodes) {
|
|
814
|
+
if (!nodes.length) return;
|
|
815
|
+
for (let i = 0; i < nodes.length; i++) releaseAffectsMark(nodes[i]);
|
|
816
|
+
nodes.length = 0;
|
|
817
|
+
}
|
|
766
818
|
function reassignPendingTransition(pendingNodes) {
|
|
767
819
|
for (let i = 0; i < pendingNodes.length; i++) {
|
|
768
820
|
pendingNodes[i]._transition = activeTransition;
|
|
@@ -842,7 +894,8 @@ function transitionComplete(transition) {
|
|
|
842
894
|
hasActiveOverride(node) &&
|
|
843
895
|
"_statusFlags" in node &&
|
|
844
896
|
node._statusFlags & STATUS_PENDING &&
|
|
845
|
-
node._error instanceof NotReadyError
|
|
897
|
+
node._error instanceof NotReadyError &&
|
|
898
|
+
!node._error.source?._affectsFor
|
|
846
899
|
) {
|
|
847
900
|
done = false;
|
|
848
901
|
break;
|
|
@@ -1279,7 +1332,7 @@ function setPendingError(el, source, error) {
|
|
|
1279
1332
|
}
|
|
1280
1333
|
function forEachDependent(el, fn) {
|
|
1281
1334
|
for (let s = el._subs; s !== null; s = s._nextSub) fn(s._sub, s);
|
|
1282
|
-
for (let child = el._child; child !== null; child = child._nextChild) {
|
|
1335
|
+
for (let child = el._child ?? null; child !== null; child = child._nextChild) {
|
|
1283
1336
|
for (let s = child._subs; s !== null; s = s._nextSub) fn(s._sub, s);
|
|
1284
1337
|
}
|
|
1285
1338
|
}
|
|
@@ -1296,21 +1349,22 @@ function enqueueForRerun(node) {
|
|
|
1296
1349
|
insertIntoHeap(node, queue);
|
|
1297
1350
|
}
|
|
1298
1351
|
}
|
|
1299
|
-
function settlePendingSource(el) {
|
|
1352
|
+
function settlePendingSource(el, source = el, snap = false) {
|
|
1300
1353
|
let scheduled = false;
|
|
1301
1354
|
const visited = new Set();
|
|
1355
|
+
const updateCompanions = snap ? snapCompanionsToState : updatePendingSignal;
|
|
1302
1356
|
const settle = node => {
|
|
1303
|
-
if (visited.has(node) || !removePendingSource(node,
|
|
1357
|
+
if (visited.has(node) || !removePendingSource(node, source)) return;
|
|
1304
1358
|
visited.add(node);
|
|
1305
1359
|
node._time = clock;
|
|
1306
|
-
const
|
|
1307
|
-
if (
|
|
1308
|
-
setPendingError(node,
|
|
1309
|
-
|
|
1360
|
+
const remaining = node._pendingSource ?? node._pendingSources?.values().next().value;
|
|
1361
|
+
if (remaining) {
|
|
1362
|
+
setPendingError(node, remaining);
|
|
1363
|
+
updateCompanions(node);
|
|
1310
1364
|
} else {
|
|
1311
1365
|
node._statusFlags &= ~STATUS_PENDING;
|
|
1312
1366
|
setPendingError(node);
|
|
1313
|
-
|
|
1367
|
+
updateCompanions(node);
|
|
1314
1368
|
if (node._blocked) {
|
|
1315
1369
|
enqueueForRerun(node);
|
|
1316
1370
|
scheduled = true;
|
|
@@ -1510,6 +1564,7 @@ function handleAsync(el, result, setter) {
|
|
|
1510
1564
|
function clearStatus(el, clearUninitialized = false) {
|
|
1511
1565
|
if (el._pendingSource || el._pendingSources) clearPendingSources(el);
|
|
1512
1566
|
if (el._blocked) el._blocked = false;
|
|
1567
|
+
el._reask = false;
|
|
1513
1568
|
el._statusFlags = clearUninitialized ? 0 : el._statusFlags & STATUS_UNINITIALIZED;
|
|
1514
1569
|
if (el._error) setPendingError(el);
|
|
1515
1570
|
if (el._pendingSignal || el._latestValueComputed) updatePendingSignal(el);
|
|
@@ -1579,6 +1634,48 @@ function notifyStatus(el, status, error, blockStatus, lane) {
|
|
|
1579
1634
|
}
|
|
1580
1635
|
});
|
|
1581
1636
|
}
|
|
1637
|
+
function getAffectsSentinel(node) {
|
|
1638
|
+
return (node._affectsSentinel ??= {
|
|
1639
|
+
_name: "affects-sentinel",
|
|
1640
|
+
_affectsFor: node,
|
|
1641
|
+
_flags: 0,
|
|
1642
|
+
_statusFlags: 0,
|
|
1643
|
+
_reask: false,
|
|
1644
|
+
_error: undefined,
|
|
1645
|
+
_subs: null,
|
|
1646
|
+
_deps: null
|
|
1647
|
+
});
|
|
1648
|
+
}
|
|
1649
|
+
function propagateAffectsMark(node) {
|
|
1650
|
+
if (!node._subs && !node._child) return;
|
|
1651
|
+
const sentinel = getAffectsSentinel(node);
|
|
1652
|
+
const error = new NotReadyError(sentinel);
|
|
1653
|
+
forEachDependent(node, sub => {
|
|
1654
|
+
if (sub._pendingSource !== sentinel && !sub._pendingSources?.has(sentinel)) {
|
|
1655
|
+
if (!sub._transition) queuePendingNode(sub);
|
|
1656
|
+
notifyStatus(sub, STATUS_PENDING, error);
|
|
1657
|
+
}
|
|
1658
|
+
});
|
|
1659
|
+
}
|
|
1660
|
+
function applyAffectsReads(el, sources) {
|
|
1661
|
+
let applied = false;
|
|
1662
|
+
for (let i = 0; i < sources.length; i++) {
|
|
1663
|
+
const src = sources[i];
|
|
1664
|
+
if (!src._affectsCount) continue;
|
|
1665
|
+
const sentinel = getAffectsSentinel(src);
|
|
1666
|
+
if (addPendingSource(el, sentinel)) {
|
|
1667
|
+
el._statusFlags |= STATUS_PENDING;
|
|
1668
|
+
setPendingError(el, sentinel);
|
|
1669
|
+
applied = true;
|
|
1670
|
+
}
|
|
1671
|
+
}
|
|
1672
|
+
if (applied) updatePendingSignal(el);
|
|
1673
|
+
}
|
|
1674
|
+
GlobalQueue._propagateAffects = propagateAffectsMark;
|
|
1675
|
+
GlobalQueue._settleAffects = node => {
|
|
1676
|
+
const sentinel = node._affectsSentinel;
|
|
1677
|
+
if (sentinel) settlePendingSource(node, sentinel, true);
|
|
1678
|
+
};
|
|
1582
1679
|
let externalSourceConfig = null;
|
|
1583
1680
|
function enableExternalSource(config) {
|
|
1584
1681
|
const { factory: factory, untrack: untrackFn = fn => fn() } = config;
|
|
@@ -1619,6 +1716,7 @@ let latestReadActive = false;
|
|
|
1619
1716
|
let context = null;
|
|
1620
1717
|
let currentOptimisticLane = null;
|
|
1621
1718
|
let pendingProbe = null;
|
|
1719
|
+
let affectsReads = null;
|
|
1622
1720
|
let snapshotCaptureActive = false;
|
|
1623
1721
|
let snapshotSources = null;
|
|
1624
1722
|
function ownerInSnapshotScope(owner) {
|
|
@@ -1691,8 +1789,9 @@ function recompute(el, create = false) {
|
|
|
1691
1789
|
}
|
|
1692
1790
|
let isOptimisticDirty = !!(el._flags & REACTIVE_OPTIMISTIC_DIRTY);
|
|
1693
1791
|
const hasOverride = el._overrideValue !== undefined && el._overrideValue !== NOT_PENDING;
|
|
1694
|
-
!!(el._statusFlags & STATUS_PENDING);
|
|
1792
|
+
const wasPending = !!(el._statusFlags & STATUS_PENDING);
|
|
1695
1793
|
const wasUninitialized = !!(el._statusFlags & STATUS_UNINITIALIZED);
|
|
1794
|
+
const isReask = !!(el._flags & REACTIVE_REASK) && !(wasPending && !el._reask);
|
|
1696
1795
|
const oldcontext = context;
|
|
1697
1796
|
context = el;
|
|
1698
1797
|
el._depsTail = null;
|
|
@@ -1702,6 +1801,9 @@ function recompute(el, create = false) {
|
|
|
1702
1801
|
let value = el._pendingValue === NOT_PENDING ? el._value : el._pendingValue;
|
|
1703
1802
|
let oldHeight = el._height;
|
|
1704
1803
|
let prevTracking = tracking;
|
|
1804
|
+
const prevAffectsReads = affectsReads;
|
|
1805
|
+
affectsReads = null;
|
|
1806
|
+
let markedReads = null;
|
|
1705
1807
|
let prevLane = currentOptimisticLane;
|
|
1706
1808
|
let prevStrictRead = false;
|
|
1707
1809
|
{
|
|
@@ -1757,7 +1859,12 @@ function recompute(el, create = false) {
|
|
|
1757
1859
|
updatePendingSignal(lane._source);
|
|
1758
1860
|
}
|
|
1759
1861
|
}
|
|
1760
|
-
|
|
1862
|
+
let reaskChanged = false;
|
|
1863
|
+
if (e instanceof NotReadyError) {
|
|
1864
|
+
el._blocked = true;
|
|
1865
|
+
reaskChanged = wasPending && el._reask !== isReask;
|
|
1866
|
+
el._reask = isReask;
|
|
1867
|
+
}
|
|
1761
1868
|
notifyStatus(
|
|
1762
1869
|
el,
|
|
1763
1870
|
e instanceof NotReadyError ? STATUS_PENDING : STATUS_ERROR,
|
|
@@ -1765,12 +1872,15 @@ function recompute(el, create = false) {
|
|
|
1765
1872
|
undefined,
|
|
1766
1873
|
e instanceof NotReadyError ? el._optimisticLane : undefined
|
|
1767
1874
|
);
|
|
1875
|
+
if (reaskChanged) repollDownstreamVerdicts(el);
|
|
1768
1876
|
} finally {
|
|
1769
1877
|
tracking = prevTracking;
|
|
1770
1878
|
strictRead = prevStrictRead;
|
|
1771
1879
|
if (isStaleEffect) stale = prevStale;
|
|
1772
1880
|
el._flags = REACTIVE_NONE | (create ? el._flags & REACTIVE_SNAPSHOT_STALE : 0);
|
|
1773
1881
|
context = oldcontext;
|
|
1882
|
+
markedReads = affectsReads;
|
|
1883
|
+
affectsReads = prevAffectsReads;
|
|
1774
1884
|
}
|
|
1775
1885
|
if (!el._error) {
|
|
1776
1886
|
trimStaleDeps(el);
|
|
@@ -1816,6 +1926,7 @@ function recompute(el, create = false) {
|
|
|
1816
1926
|
}
|
|
1817
1927
|
}
|
|
1818
1928
|
currentOptimisticLane = prevLane;
|
|
1929
|
+
if (markedReads) applyAffectsReads(el, markedReads);
|
|
1819
1930
|
const needsPendingCommit =
|
|
1820
1931
|
el._pendingValue !== NOT_PENDING ||
|
|
1821
1932
|
el._pendingFirstChild !== null ||
|
|
@@ -1892,7 +2003,8 @@ function computed(fn, options) {
|
|
|
1892
2003
|
_pendingDisposal: null,
|
|
1893
2004
|
_pendingFirstChild: null,
|
|
1894
2005
|
_inFlight: null,
|
|
1895
|
-
_transition: null
|
|
2006
|
+
_transition: null,
|
|
2007
|
+
_reask: false
|
|
1896
2008
|
};
|
|
1897
2009
|
self._name = options?.name ?? "computed";
|
|
1898
2010
|
setupComputedNode(self, options);
|
|
@@ -1938,6 +2050,7 @@ function createEffectNode(fn, effectFn, errorFn, type, notifyStatus, options) {
|
|
|
1938
2050
|
_pendingFirstChild: null,
|
|
1939
2051
|
_inFlight: null,
|
|
1940
2052
|
_transition: null,
|
|
2053
|
+
_reask: false,
|
|
1941
2054
|
_modified: false,
|
|
1942
2055
|
_prevValue: undefined,
|
|
1943
2056
|
_effectFn: effectFn,
|
|
@@ -2127,7 +2240,11 @@ function read(el) {
|
|
|
2127
2240
|
!snapshotCaptureActive &&
|
|
2128
2241
|
!strictRead
|
|
2129
2242
|
) {
|
|
2130
|
-
if (c && tracking)
|
|
2243
|
+
if (c && tracking) {
|
|
2244
|
+
link(el, c);
|
|
2245
|
+
if (activeAffectsMarks !== 0 && el._affectsCount && !pendingCheckActive)
|
|
2246
|
+
(affectsReads ??= []).push(el);
|
|
2247
|
+
}
|
|
2131
2248
|
return !c || el._pendingValue === NOT_PENDING ? el._value : el._pendingValue;
|
|
2132
2249
|
}
|
|
2133
2250
|
if (strictRead && owner._statusFlags & STATUS_PENDING) {
|
|
@@ -2148,6 +2265,8 @@ function read(el) {
|
|
|
2148
2265
|
}
|
|
2149
2266
|
if (c && tracking) {
|
|
2150
2267
|
link(el, c, pendingCheckActive);
|
|
2268
|
+
if (activeAffectsMarks !== 0 && el._affectsCount && !pendingCheckActive)
|
|
2269
|
+
(affectsReads ??= []).push(el);
|
|
2151
2270
|
if (owner._fn) {
|
|
2152
2271
|
const isZombie = el._flags & REACTIVE_ZOMBIE;
|
|
2153
2272
|
if (owner._height >= (isZombie ? zombieQueue._min : dirtyQueue._min)) {
|
|
@@ -2382,29 +2501,48 @@ function collectPendingSources(el) {
|
|
|
2382
2501
|
const owner = el._firewall || el;
|
|
2383
2502
|
if (owner !== el) pendingProbe.sources.add(owner);
|
|
2384
2503
|
}
|
|
2504
|
+
function witnessAffects(node) {
|
|
2505
|
+
pendingProbe?.sources.add(node);
|
|
2506
|
+
}
|
|
2507
|
+
function quietPending(el) {
|
|
2508
|
+
if (el._pendingSources) {
|
|
2509
|
+
for (const source of el._pendingSources) if (!source._reask) return false;
|
|
2510
|
+
return true;
|
|
2511
|
+
}
|
|
2512
|
+
if (el._pendingSource) return el._pendingSource._reask;
|
|
2513
|
+
return el._reask;
|
|
2514
|
+
}
|
|
2515
|
+
function newQuestionInFlight(comp) {
|
|
2516
|
+
return (
|
|
2517
|
+
!!(comp._statusFlags & STATUS_PENDING) &&
|
|
2518
|
+
!(comp._statusFlags & STATUS_UNINITIALIZED) &&
|
|
2519
|
+
!quietPending(comp)
|
|
2520
|
+
);
|
|
2521
|
+
}
|
|
2385
2522
|
function computePendingState(el) {
|
|
2386
2523
|
const comp = el;
|
|
2387
2524
|
if (comp._flags & REACTIVE_DISPOSED) return false;
|
|
2525
|
+
if (el._affectsCount) return true;
|
|
2388
2526
|
const firewall = el._firewall;
|
|
2389
|
-
if ((firewall || comp)._optimisticMask) return false;
|
|
2390
2527
|
if (el._parentSource) {
|
|
2391
2528
|
const parentNode = el._parentSource;
|
|
2392
|
-
if (
|
|
2529
|
+
if (parentNode._affectsCount) return true;
|
|
2393
2530
|
const parent = parentNode._firewall || parentNode;
|
|
2394
|
-
|
|
2395
|
-
return !!(
|
|
2396
|
-
parent._statusFlags & STATUS_PENDING && !(parent._statusFlags & STATUS_UNINITIALIZED)
|
|
2397
|
-
);
|
|
2531
|
+
return newQuestionInFlight(parent);
|
|
2398
2532
|
}
|
|
2399
|
-
if (hasActiveOverride(el))
|
|
2400
|
-
if (firewall && el._pendingValue !== NOT_PENDING) {
|
|
2533
|
+
if (firewall && el._pendingValue !== NOT_PENDING && !hasActiveOverride(el)) {
|
|
2401
2534
|
return (
|
|
2402
2535
|
!!(firewall._flags & REACTIVE_MANUAL_WRITE) ||
|
|
2403
|
-
(!firewall._inFlight && !(firewall._statusFlags & STATUS_PENDING))
|
|
2536
|
+
(!firewall._inFlight && !(firewall._statusFlags & STATUS_PENDING)) ||
|
|
2537
|
+
(!!(firewall._statusFlags & STATUS_PENDING) && quietPending(firewall))
|
|
2404
2538
|
);
|
|
2405
2539
|
}
|
|
2406
|
-
if (el._pendingValue !== NOT_PENDING && !(comp._statusFlags & STATUS_UNINITIALIZED))
|
|
2407
|
-
|
|
2540
|
+
if (el._pendingValue !== NOT_PENDING && !(comp._statusFlags & STATUS_UNINITIALIZED)) {
|
|
2541
|
+
if (hasActiveOverride(el))
|
|
2542
|
+
return !el._equals || !el._equals(el._pendingValue, el._overrideValue);
|
|
2543
|
+
return true;
|
|
2544
|
+
}
|
|
2545
|
+
return newQuestionInFlight(comp);
|
|
2408
2546
|
}
|
|
2409
2547
|
function syncCompanions(el, value) {
|
|
2410
2548
|
if (el._pendingSignal) updatePendingSignal(el);
|
|
@@ -2421,6 +2559,19 @@ function updateChildCompanions(el) {
|
|
|
2421
2559
|
if (child._pendingSignal || child._latestValueComputed) updatePendingSignal(child);
|
|
2422
2560
|
}
|
|
2423
2561
|
}
|
|
2562
|
+
function repollDownstreamVerdicts(el) {
|
|
2563
|
+
const visited = new Set();
|
|
2564
|
+
const visit = node => {
|
|
2565
|
+
if (visited.has(node)) return;
|
|
2566
|
+
visited.add(node);
|
|
2567
|
+
if (node._pendingSignal || node._latestValueComputed) updatePendingSignal(node);
|
|
2568
|
+
for (let s = node._subs; s !== null; s = s._nextSub) visit(s._sub);
|
|
2569
|
+
for (let child = node._child ?? null; child !== null; child = child._nextChild) {
|
|
2570
|
+
visit(child);
|
|
2571
|
+
}
|
|
2572
|
+
};
|
|
2573
|
+
visit(el);
|
|
2574
|
+
}
|
|
2424
2575
|
function snapCompanionsToState(owner) {
|
|
2425
2576
|
const sig = owner._pendingSignal;
|
|
2426
2577
|
if (sig && (sig._overrideValue === undefined || sig._overrideValue === NOT_PENDING)) {
|
|
@@ -2508,8 +2659,9 @@ function isPending(fn) {
|
|
|
2508
2659
|
} catch (e) {
|
|
2509
2660
|
collectPending();
|
|
2510
2661
|
if (e instanceof NotReadyError) {
|
|
2511
|
-
|
|
2512
|
-
if (
|
|
2662
|
+
const uninitialized = !!(e.source?._statusFlags & STATUS_UNINITIALIZED);
|
|
2663
|
+
if (probe.found && !uninitialized) return true;
|
|
2664
|
+
if (context && uninitialized) throw e;
|
|
2513
2665
|
}
|
|
2514
2666
|
return probe.found;
|
|
2515
2667
|
} finally {
|
|
@@ -2554,6 +2706,10 @@ function refresh(target) {
|
|
|
2554
2706
|
typeof node._fn === "function" &&
|
|
2555
2707
|
!(node._flags & (REACTIVE_DISPOSED | REACTIVE_MANUAL_WRITE))
|
|
2556
2708
|
) {
|
|
2709
|
+
if (!(node._flags & (REACTIVE_DIRTY | REACTIVE_CHECK | REACTIVE_IN_HEAP))) {
|
|
2710
|
+
node._flags |= REACTIVE_REASK;
|
|
2711
|
+
armReaskClear();
|
|
2712
|
+
}
|
|
2557
2713
|
node._flags = (node._flags & ~REACTIVE_CHECK) | REACTIVE_DIRTY;
|
|
2558
2714
|
insertIntoHeap(node, node._flags & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue);
|
|
2559
2715
|
schedule();
|
|
@@ -3451,7 +3607,8 @@ function createWriteTraps(isActive, onDraftWrite) {
|
|
|
3451
3607
|
const $TRACK = Symbol("STORE_TRACK"),
|
|
3452
3608
|
$TARGET = Symbol("STORE_TARGET"),
|
|
3453
3609
|
$PROXY = Symbol("STORE_PROXY"),
|
|
3454
|
-
$DELETED = Symbol("STORE_DELETED")
|
|
3610
|
+
$DELETED = Symbol("STORE_DELETED"),
|
|
3611
|
+
$AFFECTS = Symbol("STORE_AFFECTS");
|
|
3455
3612
|
const STORE_VALUE = "v",
|
|
3456
3613
|
STORE_OVERRIDE = "o",
|
|
3457
3614
|
STORE_OPTIMISTIC_OVERRIDE = "x",
|
|
@@ -3461,8 +3618,7 @@ const STORE_VALUE = "v",
|
|
|
3461
3618
|
STORE_WRAP = "w",
|
|
3462
3619
|
STORE_LOOKUP = "l",
|
|
3463
3620
|
STORE_FIREWALL = "f",
|
|
3464
|
-
STORE_OPTIMISTIC = "p"
|
|
3465
|
-
STORE_MASKED = "m";
|
|
3621
|
+
STORE_OPTIMISTIC = "p";
|
|
3466
3622
|
const STORE_SELF_PENDING = Symbol("STORE_SELF_PENDING");
|
|
3467
3623
|
function createStoreProxy(value, traps = storeTraps, extend) {
|
|
3468
3624
|
let newTarget;
|
|
@@ -3558,7 +3714,7 @@ function getNodes(target, type) {
|
|
|
3558
3714
|
if (!nodes) target[type] = nodes = Object.create(null);
|
|
3559
3715
|
return nodes;
|
|
3560
3716
|
}
|
|
3561
|
-
function getNode(nodes, property, value,
|
|
3717
|
+
function getNode(target, nodes, property, value, equals = isEqual, snapshotProps) {
|
|
3562
3718
|
if (nodes[property]) return nodes[property];
|
|
3563
3719
|
const s = signal(
|
|
3564
3720
|
value,
|
|
@@ -3570,12 +3726,13 @@ function getNode(nodes, property, value, firewall, equals = isEqual, optimistic,
|
|
|
3570
3726
|
if (
|
|
3571
3727
|
typeof property === "symbol" &&
|
|
3572
3728
|
property !== $TRACK &&
|
|
3729
|
+
property !== $AFFECTS &&
|
|
3573
3730
|
symbolKeyedRecords.has(nodes)
|
|
3574
3731
|
) {
|
|
3575
3732
|
const syms = Object.getOwnPropertySymbols(nodes);
|
|
3576
3733
|
let hasUserSymbol = false;
|
|
3577
3734
|
for (let i = 0, len = syms.length; i < len; i++) {
|
|
3578
|
-
if (syms[i] !== $TRACK) {
|
|
3735
|
+
if (syms[i] !== $TRACK && syms[i] !== $AFFECTS) {
|
|
3579
3736
|
hasUserSymbol = true;
|
|
3580
3737
|
break;
|
|
3581
3738
|
}
|
|
@@ -3585,9 +3742,9 @@ function getNode(nodes, property, value, firewall, equals = isEqual, optimistic,
|
|
|
3585
3742
|
}
|
|
3586
3743
|
}
|
|
3587
3744
|
},
|
|
3588
|
-
|
|
3745
|
+
target[STORE_FIREWALL]
|
|
3589
3746
|
);
|
|
3590
|
-
if (
|
|
3747
|
+
if (target[STORE_OPTIMISTIC]) {
|
|
3591
3748
|
s._overrideValue = NOT_PENDING;
|
|
3592
3749
|
}
|
|
3593
3750
|
if (snapshotProps && property in snapshotProps) {
|
|
@@ -3595,21 +3752,92 @@ function getNode(nodes, property, value, firewall, equals = isEqual, optimistic,
|
|
|
3595
3752
|
s._snapshotValue = sv === undefined ? NO_SNAPSHOT : sv;
|
|
3596
3753
|
snapshotSources?.add(s);
|
|
3597
3754
|
}
|
|
3598
|
-
if (typeof property === "symbol" && property !== $TRACK
|
|
3755
|
+
if (typeof property === "symbol" && property !== $TRACK && property !== $AFFECTS)
|
|
3756
|
+
symbolKeyedRecords.add(nodes);
|
|
3757
|
+
if (property !== $AFFECTS && affectsScopes.size) inheritAffectsMarks(s, target[STORE_VALUE]);
|
|
3599
3758
|
return (nodes[property] = s);
|
|
3600
3759
|
}
|
|
3760
|
+
function inheritAffectsMarks(node, raw) {
|
|
3761
|
+
for (const [carrier, entry] of affectsScopes) {
|
|
3762
|
+
if (carrier._affectsCount && entry.scope.has(raw)) {
|
|
3763
|
+
markAffects(node);
|
|
3764
|
+
entry.inherited.push(node);
|
|
3765
|
+
}
|
|
3766
|
+
}
|
|
3767
|
+
}
|
|
3768
|
+
const affectsScopes = new Map();
|
|
3769
|
+
function walkAffectsScope(value, entry, found, lookup, visited) {
|
|
3770
|
+
if (!isWrappable(value)) return;
|
|
3771
|
+
const target = value[$TARGET] || (lookup ?? storeLookup).get(value)?.[$TARGET];
|
|
3772
|
+
const raw = target ? target[STORE_VALUE] : value;
|
|
3773
|
+
if (visited.has(raw)) return;
|
|
3774
|
+
visited.add(raw);
|
|
3775
|
+
entry.scope.add(raw);
|
|
3776
|
+
let override;
|
|
3777
|
+
if (target) {
|
|
3778
|
+
collectRecordNodes(target[STORE_NODE], found);
|
|
3779
|
+
collectRecordNodes(target[STORE_HAS], found);
|
|
3780
|
+
override = mergedOverlay(target);
|
|
3781
|
+
lookup = target[STORE_LOOKUP] ?? lookup;
|
|
3782
|
+
}
|
|
3783
|
+
if (Array.isArray(raw)) {
|
|
3784
|
+
const len = override?.length ?? raw.length;
|
|
3785
|
+
for (let i = 0; i < len; i++) {
|
|
3786
|
+
const v = override && i in override ? override[i] : raw[i];
|
|
3787
|
+
if (v !== $DELETED) walkAffectsScope(v, entry, found, lookup, visited);
|
|
3788
|
+
}
|
|
3789
|
+
} else {
|
|
3790
|
+
const keys = getKeys(raw, override);
|
|
3791
|
+
for (let i = 0, l = keys.length; i < l; i++) {
|
|
3792
|
+
const desc = getPropertyDescriptor(raw, override, keys[i]);
|
|
3793
|
+
if (!desc || desc.get) continue;
|
|
3794
|
+
walkAffectsScope(desc.value, entry, found, lookup, visited);
|
|
3795
|
+
}
|
|
3796
|
+
}
|
|
3797
|
+
}
|
|
3798
|
+
function collectRecordNodes(nodes, found) {
|
|
3799
|
+
if (!nodes) return;
|
|
3800
|
+
for (const key of Object.keys(nodes)) found.push(nodes[key]);
|
|
3801
|
+
const syms = Object.getOwnPropertySymbols(nodes);
|
|
3802
|
+
for (let i = 0, l = syms.length; i < l; i++) {
|
|
3803
|
+
if (syms[i] !== $AFFECTS) found.push(nodes[syms[i]]);
|
|
3804
|
+
}
|
|
3805
|
+
}
|
|
3806
|
+
function witnessAffectsMark(target) {
|
|
3807
|
+
const own = target[STORE_NODE]?.[$AFFECTS];
|
|
3808
|
+
if (own?._affectsCount) witnessAffects(own);
|
|
3809
|
+
if (affectsScopes.size) {
|
|
3810
|
+
const raw = target[STORE_VALUE];
|
|
3811
|
+
for (const [carrier, entry] of affectsScopes) {
|
|
3812
|
+
if (carrier !== own && carrier._affectsCount && entry.scope.has(raw)) witnessAffects(carrier);
|
|
3813
|
+
}
|
|
3814
|
+
}
|
|
3815
|
+
}
|
|
3816
|
+
function getStoreAffectsNodes(target, key) {
|
|
3817
|
+
const nodes = getNodes(target, STORE_NODE);
|
|
3818
|
+
if (key === undefined) {
|
|
3819
|
+
const carrier = getNode(target, nodes, $AFFECTS, undefined, false);
|
|
3820
|
+
GlobalQueue._releaseAffectsScope ||= node => {
|
|
3821
|
+
const entry = affectsScopes.get(node);
|
|
3822
|
+
if (!entry) return;
|
|
3823
|
+
affectsScopes.delete(node);
|
|
3824
|
+
for (let i = 0; i < entry.inherited.length; i++) releaseAffectsMark(entry.inherited[i]);
|
|
3825
|
+
};
|
|
3826
|
+
let entry = affectsScopes.get(carrier);
|
|
3827
|
+
if (!entry) affectsScopes.set(carrier, (entry = { scope: new Set(), inherited: [] }));
|
|
3828
|
+
const result = [carrier];
|
|
3829
|
+
walkAffectsScope(target[$PROXY], entry, result, target[STORE_LOOKUP], new Set());
|
|
3830
|
+
return result;
|
|
3831
|
+
}
|
|
3832
|
+
if (nodes[key]) return [nodes[key]];
|
|
3833
|
+
const layer = getOverlayLayer(target, key);
|
|
3834
|
+
const raw = layer ? layer[key] : target[STORE_VALUE][key];
|
|
3835
|
+
const prev = raw === $DELETED ? undefined : raw;
|
|
3836
|
+
return [upsertStoreNode(target, nodes, key, prev, target[STORE_SNAPSHOT_PROPS])];
|
|
3837
|
+
}
|
|
3601
3838
|
function trackSelf(target, symbol = $TRACK) {
|
|
3602
3839
|
if (!getObserver()) return;
|
|
3603
|
-
read(
|
|
3604
|
-
getNode(
|
|
3605
|
-
getNodes(target, STORE_NODE),
|
|
3606
|
-
symbol,
|
|
3607
|
-
undefined,
|
|
3608
|
-
target[STORE_FIREWALL],
|
|
3609
|
-
false,
|
|
3610
|
-
target[STORE_OPTIMISTIC]
|
|
3611
|
-
)
|
|
3612
|
-
);
|
|
3840
|
+
read(getNode(target, getNodes(target, STORE_NODE), symbol, undefined, false));
|
|
3613
3841
|
if (
|
|
3614
3842
|
symbol === $TRACK &&
|
|
3615
3843
|
!target[STORE_OVERRIDE] &&
|
|
@@ -3626,6 +3854,11 @@ function notifySelf(target) {
|
|
|
3626
3854
|
target[STORE_OPTIMISTIC] && !projectionWriteActive ? STORE_SELF_PENDING : undefined
|
|
3627
3855
|
);
|
|
3628
3856
|
}
|
|
3857
|
+
function mergedOverlay(target) {
|
|
3858
|
+
const override = target[STORE_OVERRIDE];
|
|
3859
|
+
const opt = target[STORE_OPTIMISTIC_OVERRIDE];
|
|
3860
|
+
return override && opt ? { ...override, ...opt } : (opt ?? override);
|
|
3861
|
+
}
|
|
3629
3862
|
function getKeys(source, override, enumerable = true) {
|
|
3630
3863
|
const baseKeys = source[$TARGET]
|
|
3631
3864
|
? untrack(() => (enumerable ? Object.keys(source) : Reflect.ownKeys(source)))
|
|
@@ -3654,17 +3887,6 @@ function getPropertyDescriptor(source, override, property) {
|
|
|
3654
3887
|
}
|
|
3655
3888
|
return Reflect.getOwnPropertyDescriptor(source, property);
|
|
3656
3889
|
}
|
|
3657
|
-
function maskStoreTarget(target, on) {
|
|
3658
|
-
const firewall = target[STORE_FIREWALL];
|
|
3659
|
-
if (!firewall) return;
|
|
3660
|
-
if (!!target[STORE_MASKED] === on) return;
|
|
3661
|
-
target[STORE_MASKED] = on;
|
|
3662
|
-
const count = (firewall._optimisticMask = (firewall._optimisticMask || 0) + (on ? 1 : -1));
|
|
3663
|
-
if ((on && count === 1) || (!on && count === 0)) {
|
|
3664
|
-
updatePendingSignal(firewall);
|
|
3665
|
-
updateChildCompanions(firewall);
|
|
3666
|
-
}
|
|
3667
|
-
}
|
|
3668
3890
|
function prepareStoreWrite(target, store, property) {
|
|
3669
3891
|
if (target[STORE_OPTIMISTIC]) {
|
|
3670
3892
|
const firewall = target[STORE_FIREWALL];
|
|
@@ -3694,21 +3916,12 @@ function prepareStoreWrite(target, store, property) {
|
|
|
3694
3916
|
function armOptimisticStoreWrite(target, store) {
|
|
3695
3917
|
if (target[STORE_OPTIMISTIC] && !projectionWriteActive) {
|
|
3696
3918
|
trackOptimisticStore(store);
|
|
3697
|
-
maskStoreTarget(target, true);
|
|
3698
3919
|
}
|
|
3699
3920
|
}
|
|
3700
3921
|
function upsertStoreNode(target, nodes, property, prev, snapshotProps) {
|
|
3701
3922
|
if (nodes[property]) return nodes[property];
|
|
3702
3923
|
const initial = isWrappable(prev) ? wrap(prev, target) : prev;
|
|
3703
|
-
const node = getNode(
|
|
3704
|
-
nodes,
|
|
3705
|
-
property,
|
|
3706
|
-
initial,
|
|
3707
|
-
target[STORE_FIREWALL],
|
|
3708
|
-
isEqual,
|
|
3709
|
-
target[STORE_OPTIMISTIC],
|
|
3710
|
-
snapshotProps
|
|
3711
|
-
);
|
|
3924
|
+
const node = getNode(target, nodes, property, initial, isEqual, snapshotProps);
|
|
3712
3925
|
registerTransientStoreNode(node);
|
|
3713
3926
|
return node;
|
|
3714
3927
|
}
|
|
@@ -3751,6 +3964,7 @@ const storeTraps = {
|
|
|
3751
3964
|
if (property === $TARGET) return target;
|
|
3752
3965
|
if (property === $PROXY) return receiver;
|
|
3753
3966
|
if (property === $REFRESH) return target[STORE_FIREWALL];
|
|
3967
|
+
if (pendingCheckActive) witnessAffectsMark(target);
|
|
3754
3968
|
if (property === $TRACK) {
|
|
3755
3969
|
trackSelf(target);
|
|
3756
3970
|
return receiver;
|
|
@@ -3772,7 +3986,7 @@ const storeTraps = {
|
|
|
3772
3986
|
!selfRead &&
|
|
3773
3987
|
!writeOnly(receiver)
|
|
3774
3988
|
) {
|
|
3775
|
-
return read(getNode(nodes, property, undefined
|
|
3989
|
+
return read(getNode(target, nodes, property, undefined));
|
|
3776
3990
|
}
|
|
3777
3991
|
const overlay = getOverlayLayer(target, property);
|
|
3778
3992
|
const overridden = !!overlay;
|
|
@@ -3820,12 +4034,11 @@ const storeTraps = {
|
|
|
3820
4034
|
} else if (getObserver() && !selfRead) {
|
|
3821
4035
|
return read(
|
|
3822
4036
|
getNode(
|
|
4037
|
+
target,
|
|
3823
4038
|
nodes,
|
|
3824
4039
|
property,
|
|
3825
4040
|
isWrappable(value) ? wrap(value, target) : value,
|
|
3826
|
-
target[STORE_FIREWALL],
|
|
3827
4041
|
isEqual,
|
|
3828
|
-
target[STORE_OPTIMISTIC],
|
|
3829
4042
|
target[STORE_SNAPSHOT_PROPS]
|
|
3830
4043
|
)
|
|
3831
4044
|
);
|
|
@@ -3849,15 +4062,14 @@ const storeTraps = {
|
|
|
3849
4062
|
},
|
|
3850
4063
|
has(target, property) {
|
|
3851
4064
|
if (property === $PROXY || property === $TRACK || property === "__proto__") return true;
|
|
4065
|
+
if (pendingCheckActive) witnessAffectsMark(target);
|
|
3852
4066
|
const hasLayer = getOverlayLayer(target, property);
|
|
3853
4067
|
const has = hasLayer ? hasLayer[property] !== $DELETED : property in target[STORE_VALUE];
|
|
3854
4068
|
if (writeOnly(target[$PROXY]) || getObserver() === target[STORE_FIREWALL]) return has;
|
|
3855
4069
|
const nodes = getNodes(target, STORE_HAS);
|
|
3856
4070
|
if (nodes[property]) return read(nodes[property]);
|
|
3857
4071
|
if (getObserver()) {
|
|
3858
|
-
return read(
|
|
3859
|
-
getNode(nodes, property, has, target[STORE_FIREWALL], isEqual, target[STORE_OPTIMISTIC])
|
|
3860
|
-
);
|
|
4072
|
+
return read(getNode(target, nodes, property, has));
|
|
3861
4073
|
}
|
|
3862
4074
|
return has;
|
|
3863
4075
|
},
|
|
@@ -3987,6 +4199,7 @@ const storeTraps = {
|
|
|
3987
4199
|
return true;
|
|
3988
4200
|
},
|
|
3989
4201
|
ownKeys(target) {
|
|
4202
|
+
if (pendingCheckActive) witnessAffectsMark(target);
|
|
3990
4203
|
if (getObserver() !== target[STORE_FIREWALL]) trackSelf(target);
|
|
3991
4204
|
let keys = getKeys(target[STORE_VALUE], target[STORE_OVERRIDE], false);
|
|
3992
4205
|
if (target[STORE_OPTIMISTIC_OVERRIDE]) {
|
|
@@ -4070,6 +4283,58 @@ function createStore(first, second, options) {
|
|
|
4070
4283
|
: fn => storeSetter(wrappedStore, fn)
|
|
4071
4284
|
];
|
|
4072
4285
|
}
|
|
4286
|
+
function affects(target, key) {
|
|
4287
|
+
if (arguments.length > 2) {
|
|
4288
|
+
const message =
|
|
4289
|
+
"[INVALID_AFFECTS_TARGET] affects() takes a single optional key — extra keys are " +
|
|
4290
|
+
"not a path. Mark each slot with its own affects(record, key) call, or pass the " +
|
|
4291
|
+
'nested record itself: affects(state.user, "name").';
|
|
4292
|
+
emitDiagnostic({
|
|
4293
|
+
code: "INVALID_AFFECTS_TARGET",
|
|
4294
|
+
kind: "write",
|
|
4295
|
+
severity: "error",
|
|
4296
|
+
message: message
|
|
4297
|
+
});
|
|
4298
|
+
throw new Error(message);
|
|
4299
|
+
}
|
|
4300
|
+
const storeTarget = target?.[$TARGET];
|
|
4301
|
+
if (storeTarget) {
|
|
4302
|
+
const nodes = getStoreAffectsNodes(storeTarget, key);
|
|
4303
|
+
for (let i = 0; i < nodes.length; i++) registerAffectsMark(nodes[i]);
|
|
4304
|
+
return;
|
|
4305
|
+
}
|
|
4306
|
+
const node = target?.[$REFRESH];
|
|
4307
|
+
if (node) {
|
|
4308
|
+
if (key !== undefined) {
|
|
4309
|
+
const message =
|
|
4310
|
+
"[INVALID_AFFECTS_TARGET] affects() keys are only valid on store targets. " +
|
|
4311
|
+
"An accessor is a single slot — pass it alone, or target the store record that owns the property.";
|
|
4312
|
+
emitDiagnostic({
|
|
4313
|
+
code: "INVALID_AFFECTS_TARGET",
|
|
4314
|
+
kind: "write",
|
|
4315
|
+
severity: "error",
|
|
4316
|
+
message: message,
|
|
4317
|
+
nodeName: node._name
|
|
4318
|
+
});
|
|
4319
|
+
throw new Error(message);
|
|
4320
|
+
}
|
|
4321
|
+
registerAffectsMark(node);
|
|
4322
|
+
return;
|
|
4323
|
+
}
|
|
4324
|
+
{
|
|
4325
|
+
const message =
|
|
4326
|
+
"[INVALID_AFFECTS_TARGET] affects() expects a Solid source accessor or a store node. " +
|
|
4327
|
+
"Pass the store proxy (optionally with a property key) or the original accessor, " +
|
|
4328
|
+
"not a wrapper function or an already-read value.";
|
|
4329
|
+
emitDiagnostic({
|
|
4330
|
+
code: "INVALID_AFFECTS_TARGET",
|
|
4331
|
+
kind: "write",
|
|
4332
|
+
severity: "error",
|
|
4333
|
+
message: message
|
|
4334
|
+
});
|
|
4335
|
+
throw new Error(message);
|
|
4336
|
+
}
|
|
4337
|
+
}
|
|
4073
4338
|
function createOptimisticStore(first, second, options) {
|
|
4074
4339
|
GlobalQueue._clearOptimisticStore ||= clearOptimisticStore;
|
|
4075
4340
|
const derived = typeof first === "function";
|
|
@@ -4080,15 +4345,12 @@ function createOptimisticStore(first, second, options) {
|
|
|
4080
4345
|
}
|
|
4081
4346
|
function clearOptimisticStore(store) {
|
|
4082
4347
|
const target = store[$TARGET];
|
|
4083
|
-
if (!target) return;
|
|
4084
|
-
maskStoreTarget(target, false);
|
|
4085
|
-
if (!target[STORE_OPTIMISTIC_OVERRIDE]) return;
|
|
4348
|
+
if (!target?.[STORE_OPTIMISTIC_OVERRIDE]) return;
|
|
4086
4349
|
clearOptimisticOverride(target);
|
|
4087
4350
|
}
|
|
4088
4351
|
function clearOptimisticOverride(target) {
|
|
4089
4352
|
const override = target[STORE_OPTIMISTIC_OVERRIDE];
|
|
4090
4353
|
if (!override) return;
|
|
4091
|
-
maskStoreTarget(target, false);
|
|
4092
4354
|
const nodes = target[STORE_NODE];
|
|
4093
4355
|
delete target[STORE_OPTIMISTIC_OVERRIDE];
|
|
4094
4356
|
const wasProjectionWriteActive = projectionWriteActive;
|
|
@@ -4255,18 +4517,16 @@ const storePath = Object.assign(
|
|
|
4255
4517
|
},
|
|
4256
4518
|
{ DELETE: DELETE }
|
|
4257
4519
|
);
|
|
4258
|
-
function mergedOverlay(target) {
|
|
4259
|
-
const override = target[STORE_OVERRIDE];
|
|
4260
|
-
const opt = target[STORE_OPTIMISTIC_OVERRIDE];
|
|
4261
|
-
return override && opt ? { ...override, ...opt } : (opt ?? override);
|
|
4262
|
-
}
|
|
4263
4520
|
function snapshotImpl(item, track, map, lookup) {
|
|
4264
4521
|
let target, isArray, override, result, unwrapped, v;
|
|
4265
4522
|
if (!isWrappable(item)) return item;
|
|
4266
4523
|
if (map && map.has(item)) return map.get(item);
|
|
4267
4524
|
if (!map) map = new Map();
|
|
4268
4525
|
if ((target = item[$TARGET] || lookup?.get(item)?.[$TARGET])) {
|
|
4269
|
-
if (track)
|
|
4526
|
+
if (track) {
|
|
4527
|
+
trackSelf(target, $TRACK);
|
|
4528
|
+
if (pendingCheckActive) witnessAffectsMark(target);
|
|
4529
|
+
}
|
|
4270
4530
|
override = mergedOverlay(target);
|
|
4271
4531
|
isArray = Array.isArray(target[STORE_VALUE]);
|
|
4272
4532
|
map.set(
|
|
@@ -4808,7 +5068,7 @@ class RevealController {
|
|
|
4808
5068
|
}
|
|
4809
5069
|
isMinimallyReady() {
|
|
4810
5070
|
const order = untrack(this._orderAccessor);
|
|
4811
|
-
if (order === "together") return this.
|
|
5071
|
+
if (order === "together") return this._forEachOwnedSlot(isSlotMinimallyReady);
|
|
4812
5072
|
if (order === "natural") {
|
|
4813
5073
|
let hasSlot = false;
|
|
4814
5074
|
let anyReady = false;
|
|
@@ -5135,6 +5395,7 @@ export {
|
|
|
5135
5395
|
NotReadyError,
|
|
5136
5396
|
SUPPORTS_PROXY,
|
|
5137
5397
|
action,
|
|
5398
|
+
affects,
|
|
5138
5399
|
clearSnapshots,
|
|
5139
5400
|
createContext,
|
|
5140
5401
|
createEffect,
|