@solidjs/signals 2.0.0-beta.7 → 2.0.0-beta.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dev.js +231 -122
- package/dist/node.cjs +1001 -905
- package/dist/prod.js +678 -580
- package/dist/types/boundaries.d.ts +44 -3
- package/dist/types/core/core.d.ts +2 -2
- package/dist/types/core/effect.d.ts +3 -2
- package/dist/types/core/scheduler.d.ts +1 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/signals.d.ts +19 -5
- package/dist/types/store/optimistic.d.ts +1 -1
- package/dist/types/store/projection.d.ts +15 -1
- package/dist/types/store/store.d.ts +2 -2
- package/dist/types-cjs/boundaries.d.cts +44 -3
- package/dist/types-cjs/core/core.d.cts +2 -2
- package/dist/types-cjs/core/effect.d.cts +3 -2
- package/dist/types-cjs/core/scheduler.d.cts +1 -0
- package/dist/types-cjs/index.d.cts +1 -1
- package/dist/types-cjs/signals.d.cts +19 -5
- package/dist/types-cjs/store/optimistic.d.cts +1 -1
- package/dist/types-cjs/store/projection.d.cts +15 -1
- package/dist/types-cjs/store/store.d.cts +2 -2
- package/package.json +1 -1
package/dist/dev.js
CHANGED
|
@@ -240,6 +240,23 @@ let inTrackedQueueCallback = false;
|
|
|
240
240
|
let _enforceLoadingBoundary = false;
|
|
241
241
|
let _hitUnhandledAsync = false;
|
|
242
242
|
let stashedOptimisticReads = null;
|
|
243
|
+
const transientStoreNodes = new Set();
|
|
244
|
+
function registerTransientStoreNode(node) {
|
|
245
|
+
transientStoreNodes.add(node);
|
|
246
|
+
}
|
|
247
|
+
function sweepTransientStoreNodes() {
|
|
248
|
+
if (transientStoreNodes.size === 0) return;
|
|
249
|
+
for (const node of transientStoreNodes) {
|
|
250
|
+
if (node._subs !== null) {
|
|
251
|
+
transientStoreNodes.delete(node);
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
if (node._pendingValue !== NOT_PENDING) continue;
|
|
255
|
+
if (node._overrideValue !== undefined && node._overrideValue !== NOT_PENDING) continue;
|
|
256
|
+
transientStoreNodes.delete(node);
|
|
257
|
+
node._unobserved?.();
|
|
258
|
+
}
|
|
259
|
+
}
|
|
243
260
|
function resetUnhandledAsync() {
|
|
244
261
|
_hitUnhandledAsync = false;
|
|
245
262
|
}
|
|
@@ -589,6 +606,7 @@ function finalizePureQueue(completingTransition = null, incomplete = false) {
|
|
|
589
606
|
optimisticStores.clear();
|
|
590
607
|
schedule();
|
|
591
608
|
}
|
|
609
|
+
sweepTransientStoreNodes();
|
|
592
610
|
cleanupCompletedLanes(completingTransition);
|
|
593
611
|
}
|
|
594
612
|
}
|
|
@@ -1383,7 +1401,9 @@ function recompute(el, create = false) {
|
|
|
1383
1401
|
if (lane) currentOptimisticLane = lane;
|
|
1384
1402
|
}
|
|
1385
1403
|
try {
|
|
1386
|
-
|
|
1404
|
+
const prevInFlight = el._inFlight;
|
|
1405
|
+
const fnResult = el._fn(value);
|
|
1406
|
+
value = el._inFlight !== prevInFlight ? fnResult : handleAsync(el, fnResult);
|
|
1387
1407
|
clearStatus(el, create);
|
|
1388
1408
|
const resolvedLane = resolveLane(el);
|
|
1389
1409
|
if (resolvedLane) {
|
|
@@ -1482,7 +1502,7 @@ function updateIfNecessary(el) {
|
|
|
1482
1502
|
}
|
|
1483
1503
|
el._flags = el._flags & (REACTIVE_SNAPSHOT_STALE | REACTIVE_IN_HEAP | REACTIVE_IN_HEAP_HEIGHT);
|
|
1484
1504
|
}
|
|
1485
|
-
function computed(fn,
|
|
1505
|
+
function computed(fn, options) {
|
|
1486
1506
|
const transparent = options?.transparent ?? false;
|
|
1487
1507
|
const self = {
|
|
1488
1508
|
id:
|
|
@@ -1497,7 +1517,7 @@ function computed(fn, initialValue, options) {
|
|
|
1497
1517
|
_context: context?._context ?? defaultContext,
|
|
1498
1518
|
_childCount: 0,
|
|
1499
1519
|
_fn: fn,
|
|
1500
|
-
_value:
|
|
1520
|
+
_value: undefined,
|
|
1501
1521
|
_height: 0,
|
|
1502
1522
|
_child: null,
|
|
1503
1523
|
_nextHeap: undefined,
|
|
@@ -1592,8 +1612,8 @@ function optimisticSignal(v, options) {
|
|
|
1592
1612
|
s._overrideValue = NOT_PENDING;
|
|
1593
1613
|
return s;
|
|
1594
1614
|
}
|
|
1595
|
-
function optimisticComputed(fn,
|
|
1596
|
-
const c = computed(fn,
|
|
1615
|
+
function optimisticComputed(fn, options) {
|
|
1616
|
+
const c = computed(fn, options);
|
|
1597
1617
|
c._overrideValue = NOT_PENDING;
|
|
1598
1618
|
return c;
|
|
1599
1619
|
}
|
|
@@ -2041,26 +2061,23 @@ function hasContext(context, owner) {
|
|
|
2041
2061
|
function isUndefined(value) {
|
|
2042
2062
|
return typeof value === "undefined";
|
|
2043
2063
|
}
|
|
2044
|
-
function effect(compute, effect, error,
|
|
2064
|
+
function effect(compute, effect, error, options) {
|
|
2045
2065
|
let initialized = false;
|
|
2046
|
-
const
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
{
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
}
|
|
2058
|
-
);
|
|
2059
|
-
node._prevValue = initialValue;
|
|
2066
|
+
const isUser = !!options?.user;
|
|
2067
|
+
const node = computed(isUser ? compute : p => staleValues(() => compute(p)), {
|
|
2068
|
+
...options,
|
|
2069
|
+
equals: () => {
|
|
2070
|
+
node._modified = !node._error;
|
|
2071
|
+
if (initialized) node._queue.enqueue(node._type, runEffect.bind(node));
|
|
2072
|
+
return false;
|
|
2073
|
+
},
|
|
2074
|
+
lazy: true
|
|
2075
|
+
});
|
|
2076
|
+
node._prevValue = undefined;
|
|
2060
2077
|
node._effectFn = effect;
|
|
2061
2078
|
node._errorFn = error;
|
|
2062
2079
|
node._cleanup = undefined;
|
|
2063
|
-
node._type =
|
|
2080
|
+
node._type = isUser ? EFFECT_USER : EFFECT_RENDER;
|
|
2064
2081
|
node._notifyStatus = (status, error) => {
|
|
2065
2082
|
const actualStatus = status !== undefined ? status : node._statusFlags;
|
|
2066
2083
|
const actualError = error !== undefined ? error : node._error;
|
|
@@ -2085,23 +2102,24 @@ function effect(compute, effect, error, initialValue, options) {
|
|
|
2085
2102
|
if (_hitUnhandledAsync) {
|
|
2086
2103
|
resetUnhandledAsync();
|
|
2087
2104
|
if (!node._queue.notify(node, STATUS_ERROR, STATUS_ERROR)) {
|
|
2088
|
-
const message =
|
|
2105
|
+
const message =
|
|
2106
|
+
"An async value was read outside a Loading boundary. The root mount will be deferred until all pending async settles.";
|
|
2089
2107
|
emitDiagnostic({
|
|
2090
2108
|
code: "ASYNC_OUTSIDE_LOADING_BOUNDARY",
|
|
2091
2109
|
kind: "async",
|
|
2092
|
-
severity: "
|
|
2110
|
+
severity: "warn",
|
|
2093
2111
|
message: message,
|
|
2094
2112
|
ownerId: node.id,
|
|
2095
2113
|
ownerName: node._name
|
|
2096
2114
|
});
|
|
2097
|
-
|
|
2115
|
+
console.warn(message);
|
|
2098
2116
|
}
|
|
2099
2117
|
}
|
|
2100
2118
|
}
|
|
2101
2119
|
};
|
|
2102
2120
|
recompute(node, true);
|
|
2103
2121
|
!options?.defer &&
|
|
2104
|
-
(node._type === EFFECT_USER
|
|
2122
|
+
(node._type === EFFECT_USER || options?.schedule
|
|
2105
2123
|
? node._queue.enqueue(node._type, runEffect.bind(node))
|
|
2106
2124
|
: runEffect.call(node));
|
|
2107
2125
|
initialized = true;
|
|
@@ -2169,7 +2187,6 @@ function trackedEffect(fn, options) {
|
|
|
2169
2187
|
}
|
|
2170
2188
|
node._cleanup = cleanup;
|
|
2171
2189
|
},
|
|
2172
|
-
undefined,
|
|
2173
2190
|
{ ...options, lazy: true }
|
|
2174
2191
|
);
|
|
2175
2192
|
node._cleanup = undefined;
|
|
@@ -2280,7 +2297,7 @@ function accessor(node) {
|
|
|
2280
2297
|
}
|
|
2281
2298
|
function createSignal(first, second) {
|
|
2282
2299
|
if (typeof first === "function") {
|
|
2283
|
-
const node = computed(first,
|
|
2300
|
+
const node = computed(first, second);
|
|
2284
2301
|
node._preventAutoDisposal = true;
|
|
2285
2302
|
return [accessor(node), setSignal.bind(null, node)];
|
|
2286
2303
|
}
|
|
@@ -2289,20 +2306,17 @@ function createSignal(first, second) {
|
|
|
2289
2306
|
return [accessor(node), setSignal.bind(null, node)];
|
|
2290
2307
|
}
|
|
2291
2308
|
function createMemo(compute, options) {
|
|
2292
|
-
let node = computed(compute,
|
|
2309
|
+
let node = computed(compute, options);
|
|
2293
2310
|
return accessor(node);
|
|
2294
2311
|
}
|
|
2295
2312
|
function createEffect(compute, effectFn, options) {
|
|
2296
|
-
effect(compute, effectFn.effect || effectFn, effectFn.error,
|
|
2297
|
-
|
|
2298
|
-
name: options?.name ?? "effect"
|
|
2313
|
+
effect(compute, effectFn.effect || effectFn, effectFn.error, {
|
|
2314
|
+
user: true,
|
|
2315
|
+
...{ ...options, name: options?.name ?? "effect" }
|
|
2299
2316
|
});
|
|
2300
2317
|
}
|
|
2301
2318
|
function createRenderEffect(compute, effectFn, options) {
|
|
2302
|
-
effect(compute, effectFn, undefined,
|
|
2303
|
-
render: true,
|
|
2304
|
-
...{ ...options, name: options?.name ?? "effect" }
|
|
2305
|
-
});
|
|
2319
|
+
effect(compute, effectFn, undefined, { ...options, name: options?.name ?? "effect" });
|
|
2306
2320
|
}
|
|
2307
2321
|
function createTrackedEffect(compute, options) {
|
|
2308
2322
|
trackedEffect(compute, { ...options, name: options?.name ?? "trackedEffect" });
|
|
@@ -2327,8 +2341,11 @@ function createReaction(effectFn, options) {
|
|
|
2327
2341
|
dispose(node);
|
|
2328
2342
|
},
|
|
2329
2343
|
effectFn.error,
|
|
2330
|
-
|
|
2331
|
-
|
|
2344
|
+
{
|
|
2345
|
+
...(true ? { ...options, name: options?.name ?? "effect" } : options),
|
|
2346
|
+
user: true,
|
|
2347
|
+
defer: true
|
|
2348
|
+
}
|
|
2332
2349
|
);
|
|
2333
2350
|
});
|
|
2334
2351
|
};
|
|
@@ -2355,7 +2372,7 @@ function resolve(fn) {
|
|
|
2355
2372
|
}
|
|
2356
2373
|
function createOptimistic(first, second) {
|
|
2357
2374
|
if (typeof first === "function") {
|
|
2358
|
-
const node = optimisticComputed(first,
|
|
2375
|
+
const node = optimisticComputed(first, second);
|
|
2359
2376
|
node._preventAutoDisposal = true;
|
|
2360
2377
|
return [accessor(node), setSignal.bind(null, node)];
|
|
2361
2378
|
}
|
|
@@ -2543,31 +2560,39 @@ function createProjectionInternal(fn, seed, options) {
|
|
|
2543
2560
|
return wrapped;
|
|
2544
2561
|
};
|
|
2545
2562
|
const wrappedStore = wrapProjection(seed);
|
|
2546
|
-
node = computed(
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
);
|
|
2554
|
-
storeSetter(draft, s => {
|
|
2555
|
-
result = fn(s);
|
|
2556
|
-
settled = true;
|
|
2557
|
-
const value = handleAsync(owner, result, value => {
|
|
2558
|
-
value !== s &&
|
|
2559
|
-
value !== undefined &&
|
|
2560
|
-
storeSetter(wrappedStore, reconcile(value, options?.key || "id"));
|
|
2561
|
-
});
|
|
2562
|
-
value !== s && value !== undefined && reconcile(value, options?.key || "id")(wrappedStore);
|
|
2563
|
-
});
|
|
2564
|
-
});
|
|
2563
|
+
node = computed(
|
|
2564
|
+
() => {
|
|
2565
|
+
if (!node) node = getOwner();
|
|
2566
|
+
runProjectionComputed(wrappedStore, fn, options?.key || "id");
|
|
2567
|
+
},
|
|
2568
|
+
options?.name ? { name: options.name } : undefined
|
|
2569
|
+
);
|
|
2565
2570
|
node._preventAutoDisposal = true;
|
|
2566
2571
|
return { store: wrappedStore, node: node };
|
|
2567
2572
|
}
|
|
2568
2573
|
function createProjection(fn, seed, options) {
|
|
2569
2574
|
return createProjectionInternal(fn, seed, options).store;
|
|
2570
2575
|
}
|
|
2576
|
+
function runProjectionComputed(wrappedStore, fn, key, wrapCommit) {
|
|
2577
|
+
const owner = getOwner();
|
|
2578
|
+
let settled = false;
|
|
2579
|
+
let result;
|
|
2580
|
+
const draft = new Proxy(
|
|
2581
|
+
wrappedStore,
|
|
2582
|
+
createWriteTraps(() => !settled || owner._inFlight === result)
|
|
2583
|
+
);
|
|
2584
|
+
storeSetter(draft, s => {
|
|
2585
|
+
result = fn(s);
|
|
2586
|
+
settled = true;
|
|
2587
|
+
const commit = v => {
|
|
2588
|
+
if (v === s || v === undefined) return;
|
|
2589
|
+
const write = () => storeSetter(wrappedStore, reconcile(v, key));
|
|
2590
|
+
wrapCommit ? wrapCommit(write) : write();
|
|
2591
|
+
};
|
|
2592
|
+
commit(handleAsync(owner, result, commit));
|
|
2593
|
+
});
|
|
2594
|
+
return owner;
|
|
2595
|
+
}
|
|
2571
2596
|
function createWriteTraps(isActive) {
|
|
2572
2597
|
const traps = {
|
|
2573
2598
|
get(_, prop) {
|
|
@@ -2677,7 +2702,7 @@ function getNode(nodes, property, value, firewall, equals = isEqual, optimistic,
|
|
|
2677
2702
|
{
|
|
2678
2703
|
equals: equals,
|
|
2679
2704
|
unobserved() {
|
|
2680
|
-
delete nodes[property];
|
|
2705
|
+
if (nodes[property] === s) delete nodes[property];
|
|
2681
2706
|
}
|
|
2682
2707
|
},
|
|
2683
2708
|
firewall
|
|
@@ -2751,19 +2776,51 @@ function prepareStoreWrite(target, store, property) {
|
|
|
2751
2776
|
if (useOptimistic) trackOptimisticStore(store);
|
|
2752
2777
|
return { base: base, overrideKey: overrideKey, state: state };
|
|
2753
2778
|
}
|
|
2754
|
-
function
|
|
2755
|
-
if (
|
|
2779
|
+
function upsertStoreNode(target, nodes, property, prev, snapshotProps) {
|
|
2780
|
+
if (nodes[property]) return nodes[property];
|
|
2781
|
+
const initial = isWrappable(prev) ? wrap(prev, target) : prev;
|
|
2782
|
+
const node = getNode(
|
|
2783
|
+
nodes,
|
|
2784
|
+
property,
|
|
2785
|
+
initial,
|
|
2786
|
+
target[STORE_FIREWALL],
|
|
2787
|
+
isEqual,
|
|
2788
|
+
target[STORE_OPTIMISTIC],
|
|
2789
|
+
snapshotProps
|
|
2790
|
+
);
|
|
2791
|
+
registerTransientStoreNode(node);
|
|
2792
|
+
return node;
|
|
2793
|
+
}
|
|
2794
|
+
function notifyStoreProperty(target, property, mode, value, prev, prevHas) {
|
|
2795
|
+
const skipUpsert = projectionWriteActive || target[STORE_OPTIMISTIC];
|
|
2796
|
+
const newHas = mode !== "delete";
|
|
2797
|
+
const existingHas = target[STORE_HAS]?.[property];
|
|
2798
|
+
if (existingHas) {
|
|
2799
|
+
setSignal(existingHas, newHas);
|
|
2800
|
+
} else if (!skipUpsert && mode !== "invalidate" && prevHas !== newHas) {
|
|
2801
|
+
const hasNode = upsertStoreNode(target, getNodes(target, STORE_HAS), property, prevHas);
|
|
2802
|
+
setSignal(hasNode, newHas);
|
|
2803
|
+
}
|
|
2756
2804
|
const nodes = getNodes(target, STORE_NODE);
|
|
2757
2805
|
if (mode === "set") {
|
|
2758
|
-
nodes[property]
|
|
2806
|
+
if (nodes[property]) {
|
|
2759
2807
|
setSignal(nodes[property], () => (isWrappable(value) ? wrap(value, target) : value));
|
|
2808
|
+
} else if (!skipUpsert) {
|
|
2809
|
+
const node = upsertStoreNode(target, nodes, property, prev, target[STORE_SNAPSHOT_PROPS]);
|
|
2810
|
+
setSignal(node, () => (isWrappable(value) ? wrap(value, target) : value));
|
|
2811
|
+
}
|
|
2760
2812
|
} else if (mode === "invalidate") {
|
|
2761
2813
|
if (nodes[property]) {
|
|
2762
2814
|
setSignal(nodes[property], {});
|
|
2763
2815
|
delete nodes[property];
|
|
2764
2816
|
}
|
|
2765
2817
|
} else {
|
|
2766
|
-
|
|
2818
|
+
if (nodes[property]) {
|
|
2819
|
+
setSignal(nodes[property], undefined);
|
|
2820
|
+
} else if (!skipUpsert) {
|
|
2821
|
+
const node = upsertStoreNode(target, nodes, property, prev, target[STORE_SNAPSHOT_PROPS]);
|
|
2822
|
+
setSignal(node, undefined);
|
|
2823
|
+
}
|
|
2767
2824
|
}
|
|
2768
2825
|
nodes[$TRACK] && setSignal(nodes[$TRACK], undefined);
|
|
2769
2826
|
}
|
|
@@ -2860,18 +2917,13 @@ const storeTraps = {
|
|
|
2860
2917
|
: target[STORE_OVERRIDE] && property in target[STORE_OVERRIDE]
|
|
2861
2918
|
? target[STORE_OVERRIDE][property] !== $DELETED
|
|
2862
2919
|
: property in target[STORE_VALUE];
|
|
2863
|
-
if (
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
target[STORE_FIREWALL],
|
|
2871
|
-
isEqual,
|
|
2872
|
-
target[STORE_OPTIMISTIC]
|
|
2873
|
-
)
|
|
2874
|
-
);
|
|
2920
|
+
if (writeOnly(target[$PROXY])) return has;
|
|
2921
|
+
const nodes = getNodes(target, STORE_HAS);
|
|
2922
|
+
if (nodes[property]) return read(nodes[property]);
|
|
2923
|
+
if (getObserver()) {
|
|
2924
|
+
return read(
|
|
2925
|
+
getNode(nodes, property, has, target[STORE_FIREWALL], isEqual, target[STORE_OPTIMISTIC])
|
|
2926
|
+
);
|
|
2875
2927
|
}
|
|
2876
2928
|
return has;
|
|
2877
2929
|
},
|
|
@@ -2890,6 +2942,12 @@ const storeTraps = {
|
|
|
2890
2942
|
: target[STORE_OVERRIDE] && property in target[STORE_OVERRIDE]
|
|
2891
2943
|
? target[STORE_OVERRIDE][property]
|
|
2892
2944
|
: base;
|
|
2945
|
+
const prevHas =
|
|
2946
|
+
target[STORE_OPTIMISTIC_OVERRIDE] && property in target[STORE_OPTIMISTIC_OVERRIDE]
|
|
2947
|
+
? target[STORE_OPTIMISTIC_OVERRIDE][property] !== $DELETED
|
|
2948
|
+
: target[STORE_OVERRIDE] && property in target[STORE_OVERRIDE]
|
|
2949
|
+
? target[STORE_OVERRIDE][property] !== $DELETED
|
|
2950
|
+
: property in target[STORE_VALUE];
|
|
2893
2951
|
const value = rawValue?.[$TARGET]?.[STORE_VALUE] ?? rawValue;
|
|
2894
2952
|
const isArrayIndexWrite = Array.isArray(state) && property !== "length";
|
|
2895
2953
|
const nextIndex = isArrayIndexWrite ? parseInt(property) + 1 : 0;
|
|
@@ -2909,11 +2967,21 @@ const storeTraps = {
|
|
|
2909
2967
|
override[property] = value;
|
|
2910
2968
|
if (nextLength !== undefined) override.length = nextLength;
|
|
2911
2969
|
}
|
|
2912
|
-
notifyStoreProperty(target, property, "set", value);
|
|
2913
|
-
if (Array.isArray(state)) {
|
|
2970
|
+
notifyStoreProperty(target, property, "set", value, prev, prevHas);
|
|
2971
|
+
if (Array.isArray(state) && property !== "length" && nextLength !== undefined) {
|
|
2914
2972
|
const nodes = getNodes(target, STORE_NODE);
|
|
2915
|
-
|
|
2916
|
-
|
|
2973
|
+
if (nodes.length) {
|
|
2974
|
+
setSignal(nodes.length, nextLength);
|
|
2975
|
+
} else if (!projectionWriteActive && !target[STORE_OPTIMISTIC]) {
|
|
2976
|
+
const node = upsertStoreNode(
|
|
2977
|
+
target,
|
|
2978
|
+
nodes,
|
|
2979
|
+
"length",
|
|
2980
|
+
len,
|
|
2981
|
+
target[STORE_SNAPSHOT_PROPS]
|
|
2982
|
+
);
|
|
2983
|
+
setSignal(node, nextLength);
|
|
2984
|
+
}
|
|
2917
2985
|
}
|
|
2918
2986
|
if (true) DEV$1.hooks.onStoreNodeUpdate?.(target[$PROXY], property, value, prev);
|
|
2919
2987
|
});
|
|
@@ -2971,7 +3039,7 @@ const storeTraps = {
|
|
|
2971
3039
|
} else if (target[overrideKey] && property in target[overrideKey]) {
|
|
2972
3040
|
delete target[overrideKey][property];
|
|
2973
3041
|
} else return true;
|
|
2974
|
-
notifyStoreProperty(target, property, "delete");
|
|
3042
|
+
notifyStoreProperty(target, property, "delete", undefined, prev, true);
|
|
2975
3043
|
});
|
|
2976
3044
|
}
|
|
2977
3045
|
return true;
|
|
@@ -3101,37 +3169,25 @@ function createOptimisticProjectionInternal(fn, initialValue, options) {
|
|
|
3101
3169
|
};
|
|
3102
3170
|
const wrappedStore = wrapProjection(initialValue);
|
|
3103
3171
|
if (fn) {
|
|
3104
|
-
|
|
3105
|
-
const owner = getOwner();
|
|
3106
|
-
let settled = false;
|
|
3107
|
-
let result;
|
|
3108
|
-
const draft = new Proxy(
|
|
3109
|
-
wrappedStore,
|
|
3110
|
-
createWriteTraps(() => !settled || owner._inFlight === result)
|
|
3111
|
-
);
|
|
3172
|
+
const wrapCommit = write => {
|
|
3112
3173
|
setProjectionWriteActive(true);
|
|
3113
3174
|
try {
|
|
3114
|
-
|
|
3115
|
-
result = fn(s);
|
|
3116
|
-
settled = true;
|
|
3117
|
-
const value = handleAsync(owner, result, value => {
|
|
3118
|
-
setProjectionWriteActive(true);
|
|
3119
|
-
try {
|
|
3120
|
-
value !== s &&
|
|
3121
|
-
value !== undefined &&
|
|
3122
|
-
storeSetter(wrappedStore, reconcile(value, options?.key || "id"));
|
|
3123
|
-
} finally {
|
|
3124
|
-
setProjectionWriteActive(false);
|
|
3125
|
-
}
|
|
3126
|
-
});
|
|
3127
|
-
value !== s &&
|
|
3128
|
-
value !== undefined &&
|
|
3129
|
-
reconcile(value, options?.key || "id")(wrappedStore);
|
|
3130
|
-
});
|
|
3175
|
+
write();
|
|
3131
3176
|
} finally {
|
|
3132
3177
|
setProjectionWriteActive(false);
|
|
3133
3178
|
}
|
|
3134
|
-
}
|
|
3179
|
+
};
|
|
3180
|
+
node = computed(
|
|
3181
|
+
() => {
|
|
3182
|
+
setProjectionWriteActive(true);
|
|
3183
|
+
try {
|
|
3184
|
+
runProjectionComputed(wrappedStore, fn, options?.key || "id", wrapCommit);
|
|
3185
|
+
} finally {
|
|
3186
|
+
setProjectionWriteActive(false);
|
|
3187
|
+
}
|
|
3188
|
+
},
|
|
3189
|
+
options?.name ? { name: options.name } : undefined
|
|
3190
|
+
);
|
|
3135
3191
|
node._preventAutoDisposal = true;
|
|
3136
3192
|
}
|
|
3137
3193
|
return { store: wrappedStore, node: node };
|
|
@@ -3635,7 +3691,7 @@ function compare(key, a, b) {
|
|
|
3635
3691
|
return key ? key(a) === key(b) : true;
|
|
3636
3692
|
}
|
|
3637
3693
|
function boundaryComputed(fn, propagationMask) {
|
|
3638
|
-
const node = computed(fn,
|
|
3694
|
+
const node = computed(fn, { lazy: true });
|
|
3639
3695
|
node._notifyStatus = (status, error) => {
|
|
3640
3696
|
const flags = status !== undefined ? status : node._statusFlags;
|
|
3641
3697
|
const actualError = error !== undefined ? error : node._error;
|
|
@@ -3660,12 +3716,16 @@ const ON_INIT = Symbol();
|
|
|
3660
3716
|
const RevealControllerContext = createContext(null);
|
|
3661
3717
|
let _revealUsed = false;
|
|
3662
3718
|
const FALSE_ACCESSOR = () => false;
|
|
3719
|
+
const SEQUENTIAL_ACCESSOR = () => "sequential";
|
|
3663
3720
|
function isRevealController(slot) {
|
|
3664
3721
|
return slot instanceof RevealController;
|
|
3665
3722
|
}
|
|
3666
3723
|
function isSlotReady(slot) {
|
|
3667
3724
|
return isRevealController(slot) ? slot.isReady() : slot._sources.size === 0 && !slot._pending;
|
|
3668
3725
|
}
|
|
3726
|
+
function isSlotMinimallyReady(slot) {
|
|
3727
|
+
return isRevealController(slot) ? slot.isMinimallyReady() : isSlotReady(slot);
|
|
3728
|
+
}
|
|
3669
3729
|
function setSlotState(slot, controller, disabled, collapsed) {
|
|
3670
3730
|
setSignal(slot._disabled, disabled);
|
|
3671
3731
|
setSignal(slot._collapsed, collapsed);
|
|
@@ -3677,16 +3737,17 @@ function setSlotState(slot, controller, disabled, collapsed) {
|
|
|
3677
3737
|
slot._revealController = undefined;
|
|
3678
3738
|
}
|
|
3679
3739
|
class RevealController {
|
|
3680
|
-
|
|
3740
|
+
_orderAccessor;
|
|
3681
3741
|
_collapsedAccessor;
|
|
3682
3742
|
_slots = [];
|
|
3683
3743
|
_parentController;
|
|
3684
3744
|
_disabled = signal(false, { ownedWrite: true, _noSnapshot: true });
|
|
3685
3745
|
_collapsed = signal(false, { ownedWrite: true, _noSnapshot: true });
|
|
3686
3746
|
_ready = true;
|
|
3747
|
+
_minimallyReady = true;
|
|
3687
3748
|
_evaluating = false;
|
|
3688
|
-
constructor(
|
|
3689
|
-
this.
|
|
3749
|
+
constructor(order, collapsed) {
|
|
3750
|
+
this._orderAccessor = order;
|
|
3690
3751
|
this._collapsedAccessor = collapsed;
|
|
3691
3752
|
}
|
|
3692
3753
|
_forEachOwnedSlot(fn) {
|
|
@@ -3701,12 +3762,37 @@ class RevealController {
|
|
|
3701
3762
|
isReady() {
|
|
3702
3763
|
return this._forEachOwnedSlot(isSlotReady);
|
|
3703
3764
|
}
|
|
3765
|
+
isMinimallyReady() {
|
|
3766
|
+
const order = untrack(this._orderAccessor);
|
|
3767
|
+
if (order === "together") return this.isReady();
|
|
3768
|
+
if (order === "natural") {
|
|
3769
|
+
let hasSlot = false;
|
|
3770
|
+
let anyReady = false;
|
|
3771
|
+
this._forEachOwnedSlot(slot => {
|
|
3772
|
+
hasSlot = true;
|
|
3773
|
+
if (isSlotMinimallyReady(slot)) {
|
|
3774
|
+
anyReady = true;
|
|
3775
|
+
return false;
|
|
3776
|
+
}
|
|
3777
|
+
});
|
|
3778
|
+
return !hasSlot || anyReady;
|
|
3779
|
+
}
|
|
3780
|
+
let firstReady = true;
|
|
3781
|
+
this._forEachOwnedSlot(slot => {
|
|
3782
|
+
firstReady = isSlotMinimallyReady(slot);
|
|
3783
|
+
return false;
|
|
3784
|
+
});
|
|
3785
|
+
return firstReady;
|
|
3786
|
+
}
|
|
3704
3787
|
register(slot) {
|
|
3705
3788
|
if (this._slots.includes(slot)) return;
|
|
3706
3789
|
this._slots.push(slot);
|
|
3707
|
-
const
|
|
3790
|
+
const order = untrack(this._orderAccessor);
|
|
3708
3791
|
(setSignal(slot._disabled, true),
|
|
3709
|
-
setSignal(
|
|
3792
|
+
setSignal(
|
|
3793
|
+
slot._collapsed,
|
|
3794
|
+
order === "sequential" ? !!untrack(this._collapsedAccessor) : false
|
|
3795
|
+
));
|
|
3710
3796
|
untrack(() => this.evaluate());
|
|
3711
3797
|
}
|
|
3712
3798
|
unregister(slot) {
|
|
@@ -3718,29 +3804,52 @@ class RevealController {
|
|
|
3718
3804
|
if (this._evaluating) return;
|
|
3719
3805
|
this._evaluating = true;
|
|
3720
3806
|
const wasReady = this._ready;
|
|
3807
|
+
const wasMinReady = this._minimallyReady;
|
|
3721
3808
|
try {
|
|
3722
3809
|
const disabled = disabledOverride ?? read(this._disabled),
|
|
3723
|
-
|
|
3810
|
+
order = untrack(this._orderAccessor),
|
|
3811
|
+
collapseTail = order === "sequential" && !!untrack(this._collapsedAccessor),
|
|
3724
3812
|
collapsed = collapsedOverride ?? collapseTail;
|
|
3725
|
-
if (disabled
|
|
3726
|
-
this._forEachOwnedSlot(slot => setSlotState(slot, this, true,
|
|
3727
|
-
else if (
|
|
3728
|
-
|
|
3729
|
-
|
|
3813
|
+
if (disabled) {
|
|
3814
|
+
this._forEachOwnedSlot(slot => setSlotState(slot, this, true, collapsed));
|
|
3815
|
+
} else if (order === "natural") {
|
|
3816
|
+
this._forEachOwnedSlot(slot => {
|
|
3817
|
+
if (isRevealController(slot)) {
|
|
3818
|
+
setSignal(slot._collapsed, false);
|
|
3819
|
+
setSignal(slot._disabled, false);
|
|
3820
|
+
slot.evaluate(false, false);
|
|
3821
|
+
} else {
|
|
3822
|
+
setSlotState(slot, this, !isSlotReady(slot), false);
|
|
3823
|
+
}
|
|
3824
|
+
});
|
|
3825
|
+
} else if (order === "together") {
|
|
3826
|
+
const minReady = this._forEachOwnedSlot(isSlotMinimallyReady);
|
|
3827
|
+
this._forEachOwnedSlot(slot => setSlotState(slot, this, !minReady, false));
|
|
3730
3828
|
} else {
|
|
3731
3829
|
let pendingSeen = false;
|
|
3732
3830
|
this._forEachOwnedSlot(slot => {
|
|
3733
3831
|
if (pendingSeen) return setSlotState(slot, this, true, collapseTail);
|
|
3734
3832
|
if (isSlotReady(slot)) return setSlotState(slot, this, false, false);
|
|
3735
3833
|
pendingSeen = true;
|
|
3736
|
-
|
|
3834
|
+
if (isRevealController(slot)) {
|
|
3835
|
+
setSignal(slot._collapsed, false);
|
|
3836
|
+
setSignal(slot._disabled, false);
|
|
3837
|
+
slot.evaluate(false, false);
|
|
3838
|
+
} else {
|
|
3839
|
+
setSlotState(slot, this, true, false);
|
|
3840
|
+
}
|
|
3737
3841
|
});
|
|
3738
3842
|
}
|
|
3739
3843
|
} finally {
|
|
3740
3844
|
this._ready = this.isReady();
|
|
3845
|
+
this._minimallyReady = this.isMinimallyReady();
|
|
3741
3846
|
this._evaluating = false;
|
|
3742
3847
|
}
|
|
3743
|
-
if (
|
|
3848
|
+
if (
|
|
3849
|
+
this._parentController &&
|
|
3850
|
+
(wasReady !== this._ready || wasMinReady !== this._minimallyReady)
|
|
3851
|
+
)
|
|
3852
|
+
this._parentController.evaluate();
|
|
3744
3853
|
}
|
|
3745
3854
|
}
|
|
3746
3855
|
class CollectionQueue extends Queue {
|
|
@@ -3889,14 +3998,14 @@ function createRevealOrder(fn, options) {
|
|
|
3889
3998
|
_revealUsed = true;
|
|
3890
3999
|
const owner = createOwner();
|
|
3891
4000
|
const parentController = getContext(RevealControllerContext);
|
|
3892
|
-
const
|
|
4001
|
+
const order = options?.order || SEQUENTIAL_ACCESSOR,
|
|
3893
4002
|
collapsed = options?.collapsed || FALSE_ACCESSOR;
|
|
3894
|
-
const controller = new RevealController(
|
|
4003
|
+
const controller = new RevealController(order, collapsed);
|
|
3895
4004
|
setContext(RevealControllerContext, controller, owner);
|
|
3896
4005
|
return runWithOwner(owner, () => {
|
|
3897
4006
|
const value = fn();
|
|
3898
4007
|
computed(() => {
|
|
3899
|
-
|
|
4008
|
+
order();
|
|
3900
4009
|
collapsed();
|
|
3901
4010
|
controller.evaluate();
|
|
3902
4011
|
});
|