@solidjs/signals 2.0.0-beta.22 → 2.0.0-beta.23
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 +28 -3
- package/dist/node.cjs +92 -71
- package/dist/prod/core/async.js +27 -11
- package/dist/prod/core/core.js +19 -19
- package/dist/prod/core/effect.js +3 -3
- package/dist/prod/core/graph.js +7 -2
- package/dist/prod/core/lanes.js +2 -2
- package/dist/prod/core/optimistic.js +5 -5
- package/dist/prod/core/owner.js +1 -1
- package/dist/prod/core/scheduler.js +5 -5
- package/dist/prod/core/verdict.js +29 -29
- package/dist/prod/store/optimistic.js +2 -2
- package/dist/prod/store/store.js +1 -1
- package/package.json +1 -1
package/dist/dev.js
CHANGED
|
@@ -1569,8 +1569,17 @@ function unlinkSubs(link) {
|
|
|
1569
1569
|
if (nextSub === null) {
|
|
1570
1570
|
dep._unobserved?.();
|
|
1571
1571
|
// No more subscribers; only tear down if CONFIG_AUTO_DISPOSE is set.
|
|
1572
|
+
// A pending node is exempt: its in-flight async work (or the
|
|
1573
|
+
// transition holding it) is an observer — tearing down would orphan
|
|
1574
|
+
// the work and re-execute it on the next read. The settle path runs
|
|
1575
|
+
// this same last-one-out check when that observer releases (the
|
|
1576
|
+
// untracked-read dispose in core.ts guards on pending identically).
|
|
1572
1577
|
const c = dep;
|
|
1573
|
-
c._fn &&
|
|
1578
|
+
c._fn &&
|
|
1579
|
+
c._config & CONFIG_AUTO_DISPOSE &&
|
|
1580
|
+
!(c._flags & REACTIVE_ZOMBIE) &&
|
|
1581
|
+
!(c._statusFlags & STATUS_PENDING) &&
|
|
1582
|
+
unobserved(c);
|
|
1574
1583
|
}
|
|
1575
1584
|
}
|
|
1576
1585
|
return nextDep;
|
|
@@ -1847,6 +1856,16 @@ function handleAsync(el, result, setter) {
|
|
|
1847
1856
|
flush();
|
|
1848
1857
|
then?.();
|
|
1849
1858
|
};
|
|
1859
|
+
// A pending node's in-flight promise is an observer: `unlinkSubs` skips
|
|
1860
|
+
// autodispose while STATUS_PENDING so subscriber churn can't orphan the
|
|
1861
|
+
// work (a lazy async memo would otherwise tear down and re-execute — one
|
|
1862
|
+
// fetch per suspended re-read). Settling is that observer's release, so
|
|
1863
|
+
// it runs the same last-one-out check the other release sites run.
|
|
1864
|
+
const settleAutodispose = () => {
|
|
1865
|
+
if (el._config & CONFIG_AUTO_DISPOSE && !el._subs && !(el._statusFlags & STATUS_PENDING)) {
|
|
1866
|
+
unobserved(el);
|
|
1867
|
+
}
|
|
1868
|
+
};
|
|
1850
1869
|
if (thenable) {
|
|
1851
1870
|
let resolved = false,
|
|
1852
1871
|
rejected = false,
|
|
@@ -1857,13 +1876,19 @@ function handleAsync(el, result, setter) {
|
|
|
1857
1876
|
if (isSync) {
|
|
1858
1877
|
syncValue = v;
|
|
1859
1878
|
resolved = true;
|
|
1860
|
-
} else
|
|
1879
|
+
} else {
|
|
1880
|
+
asyncWrite(v);
|
|
1881
|
+
settleAutodispose();
|
|
1882
|
+
}
|
|
1861
1883
|
},
|
|
1862
1884
|
e => {
|
|
1863
1885
|
if (isSync) {
|
|
1864
1886
|
syncError = e;
|
|
1865
1887
|
rejected = true;
|
|
1866
|
-
} else
|
|
1888
|
+
} else {
|
|
1889
|
+
handleError(e);
|
|
1890
|
+
settleAutodispose();
|
|
1891
|
+
}
|
|
1867
1892
|
}
|
|
1868
1893
|
);
|
|
1869
1894
|
isSync = false;
|
package/dist/node.cjs
CHANGED
|
@@ -214,7 +214,7 @@ const activeLanes = new Set;
|
|
|
214
214
|
l: [ [], [] ],
|
|
215
215
|
S: null,
|
|
216
216
|
T: activeTransition,
|
|
217
|
-
|
|
217
|
+
_: r
|
|
218
218
|
};
|
|
219
219
|
signalLanes.set(e, t);
|
|
220
220
|
activeLanes.add(t);
|
|
@@ -224,7 +224,7 @@ const activeLanes = new Set;
|
|
|
224
224
|
// parent-child is a property of the nodes, not of write order — otherwise
|
|
225
225
|
// the owner's write merges the companion's subscribers into this lane and
|
|
226
226
|
// their effects wait on its async instead of flushing immediately.
|
|
227
|
-
adoptCompanionLane(e.
|
|
227
|
+
adoptCompanionLane(e.p, t);
|
|
228
228
|
adoptCompanionLane(e.O, t);
|
|
229
229
|
return t;
|
|
230
230
|
}
|
|
@@ -236,7 +236,7 @@ function adoptCompanionLane(e, t) {
|
|
|
236
236
|
const r = findLane(n);
|
|
237
237
|
// Only the companion's own unmerged root is safely re-parentable: a root
|
|
238
238
|
// that absorbed other lanes carries work that is not a child of this owner.
|
|
239
|
-
if (r !== t && r.o === e && !r.
|
|
239
|
+
if (r !== t && r.o === e && !r._) r._ = t;
|
|
240
240
|
}
|
|
241
241
|
|
|
242
242
|
/**
|
|
@@ -315,9 +315,9 @@ function resolveTransition(e) {
|
|
|
315
315
|
if (i !== n && !hasActiveOverride(e)) {
|
|
316
316
|
// Parent-child lanes stay independent so isPending resolves without
|
|
317
317
|
// waiting for the parent's async. The child keeps ownership.
|
|
318
|
-
if (n.
|
|
318
|
+
if (n._ && findLane(n._) === i) {
|
|
319
319
|
e.i = t;
|
|
320
|
-
} else if (i.
|
|
320
|
+
} else if (i._ && findLane(i._) === n) ; else mergeLanes(n, i);
|
|
321
321
|
}
|
|
322
322
|
return;
|
|
323
323
|
}
|
|
@@ -596,8 +596,8 @@ class GlobalQueue extends Queue {
|
|
|
596
596
|
static Se=null;
|
|
597
597
|
static de=null;
|
|
598
598
|
static Te=null;
|
|
599
|
-
static pe=null;
|
|
600
599
|
static _e=null;
|
|
600
|
+
static pe=null;
|
|
601
601
|
// Optimistic-engine hooks (wired by core/optimistic.ts via
|
|
602
602
|
// installOptimisticEngine(), called from verdict.ts / createOptimistic /
|
|
603
603
|
// createOptimisticStore — every module that can create optimistic state).
|
|
@@ -809,7 +809,7 @@ function commitPendingNode(e) {
|
|
|
809
809
|
e.xe = e.V;
|
|
810
810
|
e.V = NOT_PENDING;
|
|
811
811
|
}
|
|
812
|
-
if (e.
|
|
812
|
+
if (e.p || e.O) GlobalQueue.fe(e);
|
|
813
813
|
return;
|
|
814
814
|
}
|
|
815
815
|
if (e.V !== NOT_PENDING) {
|
|
@@ -821,7 +821,7 @@ function commitPendingNode(e) {
|
|
|
821
821
|
t.Le &= ~REACTIVE_MANUAL_WRITE;
|
|
822
822
|
if (!(t.We & STATUS_PENDING)) t.We &= ~STATUS_UNINITIALIZED;
|
|
823
823
|
if (t.Me !== null || t.He !== null) GlobalQueue.J(t, false, true);
|
|
824
|
-
if (e.
|
|
824
|
+
if (e.p || e.O) GlobalQueue.fe(e);
|
|
825
825
|
}
|
|
826
826
|
|
|
827
827
|
function commitPendingNodes() {
|
|
@@ -1181,7 +1181,7 @@ function disposeChildren(e, t = false, n) {
|
|
|
1181
1181
|
// edge). Snap runs after the DISPOSED flag is set so the oracle reads
|
|
1182
1182
|
// false, and notifies subscribers still watching the companion.
|
|
1183
1183
|
const t = e;
|
|
1184
|
-
if (t.
|
|
1184
|
+
if (t.p || t.O) GlobalQueue.fe(t);
|
|
1185
1185
|
}
|
|
1186
1186
|
if (t && e.Ve) e.lt = null;
|
|
1187
1187
|
let i = n ? e.Me : e.ot;
|
|
@@ -1432,8 +1432,13 @@ function unlinkSubs(e) {
|
|
|
1432
1432
|
if (r === null) {
|
|
1433
1433
|
t.W?.();
|
|
1434
1434
|
// No more subscribers; only tear down if CONFIG_AUTO_DISPOSE is set.
|
|
1435
|
+
// A pending node is exempt: its in-flight async work (or the
|
|
1436
|
+
// transition holding it) is an observer — tearing down would orphan
|
|
1437
|
+
// the work and re-execute it on the next read. The settle path runs
|
|
1438
|
+
// this same last-one-out check when that observer releases (the
|
|
1439
|
+
// untracked-read dispose in core.ts guards on pending identically).
|
|
1435
1440
|
const e = t;
|
|
1436
|
-
e.Ve && e.ke & CONFIG_AUTO_DISPOSE && !(e.Le & REACTIVE_ZOMBIE) && unobserved(e);
|
|
1441
|
+
e.Ve && e.ke & CONFIG_AUTO_DISPOSE && !(e.Le & REACTIVE_ZOMBIE) && !(e.We & STATUS_PENDING) && unobserved(e);
|
|
1437
1442
|
}
|
|
1438
1443
|
}
|
|
1439
1444
|
return n;
|
|
@@ -1687,18 +1692,34 @@ function handleAsync(e, t, n) {
|
|
|
1687
1692
|
flush();
|
|
1688
1693
|
i?.();
|
|
1689
1694
|
};
|
|
1695
|
+
// A pending node's in-flight promise is an observer: `unlinkSubs` skips
|
|
1696
|
+
// autodispose while STATUS_PENDING so subscriber churn can't orphan the
|
|
1697
|
+
// work (a lazy async memo would otherwise tear down and re-execute — one
|
|
1698
|
+
// fetch per suspended re-read). Settling is that observer's release, so
|
|
1699
|
+
// it runs the same last-one-out check the other release sites run.
|
|
1700
|
+
const settleAutodispose = () => {
|
|
1701
|
+
if (e.ke & CONFIG_AUTO_DISPOSE && !e.k && !(e.We & STATUS_PENDING)) {
|
|
1702
|
+
unobserved(e);
|
|
1703
|
+
}
|
|
1704
|
+
};
|
|
1690
1705
|
if (i) {
|
|
1691
1706
|
let n = false, r = false, i, s = true;
|
|
1692
1707
|
t.then(e => {
|
|
1693
1708
|
if (s) {
|
|
1694
1709
|
o = e;
|
|
1695
1710
|
n = true;
|
|
1696
|
-
} else
|
|
1711
|
+
} else {
|
|
1712
|
+
asyncWrite(e);
|
|
1713
|
+
settleAutodispose();
|
|
1714
|
+
}
|
|
1697
1715
|
}, e => {
|
|
1698
1716
|
if (s) {
|
|
1699
1717
|
i = e;
|
|
1700
1718
|
r = true;
|
|
1701
|
-
} else
|
|
1719
|
+
} else {
|
|
1720
|
+
handleError(e);
|
|
1721
|
+
settleAutodispose();
|
|
1722
|
+
}
|
|
1702
1723
|
});
|
|
1703
1724
|
s = false;
|
|
1704
1725
|
if (r) {
|
|
@@ -1793,7 +1814,7 @@ function clearStatus(e, t = false) {
|
|
|
1793
1814
|
if (e.me) setPendingError(e);
|
|
1794
1815
|
// Update pending signal for isPending() reactivity (companions only exist
|
|
1795
1816
|
// once the verdict layer created them, which installs the hooks).
|
|
1796
|
-
if (e.
|
|
1817
|
+
if (e.p || e.O) GlobalQueue.ce(e);
|
|
1797
1818
|
if (e.rt && GlobalQueue.ae !== null) GlobalQueue.ae(e);
|
|
1798
1819
|
if (e.yt) e.yt();
|
|
1799
1820
|
}
|
|
@@ -2033,7 +2054,7 @@ function recompute(e, t = false) {
|
|
|
2033
2054
|
if (GlobalQueue.Te !== null) n = GlobalQueue.Te(e, s);
|
|
2034
2055
|
}
|
|
2035
2056
|
notifyStatus(e, t instanceof NotReadyError ? STATUS_PENDING : STATUS_ERROR, t, undefined, t instanceof NotReadyError ? e.i : undefined);
|
|
2036
|
-
if (n) GlobalQueue.
|
|
2057
|
+
if (n) GlobalQueue._e(e);
|
|
2037
2058
|
} finally {
|
|
2038
2059
|
tracking = a;
|
|
2039
2060
|
latestReadActive = E;
|
|
@@ -2806,9 +2827,9 @@ function resolveOptimisticNodes(e) {
|
|
|
2806
2827
|
// transition that produced them (A19 — pending is a property of the data).
|
|
2807
2828
|
for (let n = 0; n < t; n++) {
|
|
2808
2829
|
const t = e[n];
|
|
2809
|
-
if (t.
|
|
2830
|
+
if (t.p || t.O) GlobalQueue.fe(t);
|
|
2810
2831
|
const r = t.t;
|
|
2811
|
-
if (r && (r.
|
|
2832
|
+
if (r && (r.p === t || r.O === t)) GlobalQueue.fe(r);
|
|
2812
2833
|
}
|
|
2813
2834
|
e.splice(0, t);
|
|
2814
2835
|
}
|
|
@@ -2954,15 +2975,15 @@ let pendingProbe = null;
|
|
|
2954
2975
|
* Get or create the pending signal for a node (lazy).
|
|
2955
2976
|
* Used by isPending() to track pending state reactively.
|
|
2956
2977
|
*/ function getPendingSignal(e) {
|
|
2957
|
-
if (!e.
|
|
2978
|
+
if (!e.p) {
|
|
2958
2979
|
// Start false, write true if pending - ensures reversion returns to false
|
|
2959
|
-
e.
|
|
2980
|
+
e.p = optimisticSignal(false, {
|
|
2960
2981
|
ownedWrite: true
|
|
2961
2982
|
});
|
|
2962
|
-
e.
|
|
2963
|
-
if (computePendingState(e)) setSignal(e.
|
|
2983
|
+
e.p.t = e;
|
|
2984
|
+
if (computePendingState(e)) setSignal(e.p, true);
|
|
2964
2985
|
}
|
|
2965
|
-
return e.
|
|
2986
|
+
return e.p;
|
|
2966
2987
|
}
|
|
2967
2988
|
|
|
2968
2989
|
function collectPendingSources(e) {
|
|
@@ -3058,20 +3079,20 @@ function computePendingState(e) {
|
|
|
3058
3079
|
}
|
|
3059
3080
|
|
|
3060
3081
|
function syncCompanions(e, t) {
|
|
3061
|
-
if (e.
|
|
3082
|
+
if (e.p) updatePendingSignal(e);
|
|
3062
3083
|
if (e.O) setSignal(e.O, t);
|
|
3063
3084
|
}
|
|
3064
3085
|
|
|
3065
3086
|
function updatePendingSignal(e) {
|
|
3066
|
-
if (e.
|
|
3067
|
-
setSignal(e.
|
|
3087
|
+
if (e.p) {
|
|
3088
|
+
setSignal(e.p, computePendingState(e));
|
|
3068
3089
|
}
|
|
3069
3090
|
if (e.O) updatePendingSignal(e.O);
|
|
3070
3091
|
}
|
|
3071
3092
|
|
|
3072
3093
|
function updateChildCompanions(e) {
|
|
3073
3094
|
for (let t = e.rt; t !== null; t = t.it) {
|
|
3074
|
-
if (t.
|
|
3095
|
+
if (t.p || t.O) updatePendingSignal(t);
|
|
3075
3096
|
}
|
|
3076
3097
|
}
|
|
3077
3098
|
|
|
@@ -3089,7 +3110,7 @@ function updateChildCompanions(e) {
|
|
|
3089
3110
|
const visit = e => {
|
|
3090
3111
|
if (r.has(e)) return;
|
|
3091
3112
|
r.add(e);
|
|
3092
|
-
if (e.
|
|
3113
|
+
if (e.p || e.O) n(e);
|
|
3093
3114
|
for (let t = e.k; t !== null; t = t.Ge) visit(t.Ue);
|
|
3094
3115
|
for (let t = e.rt ?? null; t !== null; t = t.it) {
|
|
3095
3116
|
visit(t);
|
|
@@ -3099,7 +3120,7 @@ function updateChildCompanions(e) {
|
|
|
3099
3120
|
}
|
|
3100
3121
|
|
|
3101
3122
|
function snapCompanionsToState(e) {
|
|
3102
|
-
const t = e.
|
|
3123
|
+
const t = e.p;
|
|
3103
3124
|
if (t && (t.A === undefined || t.A === NOT_PENDING)) {
|
|
3104
3125
|
const n = computePendingState(e);
|
|
3105
3126
|
if (t.xe !== n || t.V !== NOT_PENDING) {
|
|
@@ -3273,9 +3294,9 @@ GlobalQueue.de = recordFreshRead;
|
|
|
3273
3294
|
|
|
3274
3295
|
GlobalQueue.Te = applyReask;
|
|
3275
3296
|
|
|
3276
|
-
GlobalQueue.
|
|
3297
|
+
GlobalQueue._e = repollDownstreamVerdicts;
|
|
3277
3298
|
|
|
3278
|
-
GlobalQueue.
|
|
3299
|
+
GlobalQueue.pe = witnessAffects;
|
|
3279
3300
|
|
|
3280
3301
|
/**
|
|
3281
3302
|
* Effects are the leaf nodes of our reactive graph. When their sources change, they are
|
|
@@ -4115,7 +4136,7 @@ function applyStateFast(e, t, n) {
|
|
|
4115
4136
|
for (c = 0, a = Math.min(s, e.length); c < a && keyedMatch(E = r[c], e[c], n); c++) {
|
|
4116
4137
|
isWrappable(E) && isWrappable(e[c]) && applyState(e[c], wrap(E, t), n);
|
|
4117
4138
|
}
|
|
4118
|
-
const T = new Array(e.length),
|
|
4139
|
+
const T = new Array(e.length), _ = new Map;
|
|
4119
4140
|
for (a = s - 1, f = e.length - 1; a >= c && f >= c && keyedMatch(E = r[a], e[f], n); a--,
|
|
4120
4141
|
f--) {
|
|
4121
4142
|
T[f] = E;
|
|
@@ -4138,18 +4159,18 @@ function applyStateFast(e, t, n) {
|
|
|
4138
4159
|
for (l = f; l >= c; l--) {
|
|
4139
4160
|
E = e[l];
|
|
4140
4161
|
d = itemKey(E, n);
|
|
4141
|
-
u =
|
|
4162
|
+
u = _.get(d);
|
|
4142
4163
|
S[l] = u === undefined ? -1 : u;
|
|
4143
|
-
|
|
4164
|
+
_.set(d, l);
|
|
4144
4165
|
}
|
|
4145
4166
|
for (u = c; u <= a; u++) {
|
|
4146
4167
|
E = r[u];
|
|
4147
4168
|
d = itemKey(E, n);
|
|
4148
|
-
l =
|
|
4169
|
+
l = _.get(d);
|
|
4149
4170
|
if (l !== undefined && l !== -1) {
|
|
4150
4171
|
T[l] = E;
|
|
4151
4172
|
l = S[l];
|
|
4152
|
-
|
|
4173
|
+
_.set(d, l);
|
|
4153
4174
|
}
|
|
4154
4175
|
}
|
|
4155
4176
|
for (l = c; l < e.length; l++) {
|
|
@@ -4218,14 +4239,14 @@ function applyStateSlow(e, t, n) {
|
|
|
4218
4239
|
let u = false;
|
|
4219
4240
|
const l = getOverrideValue(r, i, "length", o);
|
|
4220
4241
|
if (e.length && l && isWrappable(e[0]) && n(e[0]) != null) {
|
|
4221
|
-
let c, a, f, E, S, d, T,
|
|
4242
|
+
let c, a, f, E, S, d, T, _;
|
|
4222
4243
|
for (f = 0, E = Math.min(l, e.length); f < E && keyedMatch(d = getOverrideValue(r, i, f, o), e[f], n); f++) {
|
|
4223
4244
|
isWrappable(d) && isWrappable(e[f]) && applyState(e[f], wrap(d, t), n);
|
|
4224
4245
|
}
|
|
4225
|
-
const
|
|
4246
|
+
const p = new Array(e.length), O = new Map;
|
|
4226
4247
|
for (E = l - 1, S = e.length - 1; E >= f && S >= f && keyedMatch(d = getOverrideValue(r, i, E, o), e[S], n); E--,
|
|
4227
4248
|
S--) {
|
|
4228
|
-
|
|
4249
|
+
p[S] = d;
|
|
4229
4250
|
}
|
|
4230
4251
|
if (f > S || f > E) {
|
|
4231
4252
|
for (a = f; a <= S; a++) {
|
|
@@ -4234,7 +4255,7 @@ function applyStateSlow(e, t, n) {
|
|
|
4234
4255
|
}
|
|
4235
4256
|
for (;a < e.length; a++) {
|
|
4236
4257
|
u = true;
|
|
4237
|
-
applyArrayItem(e[a],
|
|
4258
|
+
applyArrayItem(e[a], p[a], t, s?.[a], n);
|
|
4238
4259
|
}
|
|
4239
4260
|
const r = e.length;
|
|
4240
4261
|
syncArrayNodeMembership(t, e);
|
|
@@ -4245,24 +4266,24 @@ function applyStateSlow(e, t, n) {
|
|
|
4245
4266
|
T = new Array(S + 1);
|
|
4246
4267
|
for (a = S; a >= f; a--) {
|
|
4247
4268
|
d = e[a];
|
|
4248
|
-
|
|
4249
|
-
c = O.get(
|
|
4269
|
+
_ = itemKey(d, n);
|
|
4270
|
+
c = O.get(_);
|
|
4250
4271
|
T[a] = c === undefined ? -1 : c;
|
|
4251
|
-
O.set(
|
|
4272
|
+
O.set(_, a);
|
|
4252
4273
|
}
|
|
4253
4274
|
for (c = f; c <= E; c++) {
|
|
4254
4275
|
d = getOverrideValue(r, i, c, o);
|
|
4255
|
-
|
|
4256
|
-
a = O.get(
|
|
4276
|
+
_ = itemKey(d, n);
|
|
4277
|
+
a = O.get(_);
|
|
4257
4278
|
if (a !== undefined && a !== -1) {
|
|
4258
|
-
|
|
4279
|
+
p[a] = d;
|
|
4259
4280
|
a = T[a];
|
|
4260
|
-
O.set(
|
|
4281
|
+
O.set(_, a);
|
|
4261
4282
|
}
|
|
4262
4283
|
}
|
|
4263
4284
|
for (a = f; a < e.length; a++) {
|
|
4264
|
-
if (a in
|
|
4265
|
-
applyArrayItem(e[a],
|
|
4285
|
+
if (a in p) {
|
|
4286
|
+
applyArrayItem(e[a], p[a], t, s?.[a], n);
|
|
4266
4287
|
} else s?.[a] && setSignal(s[a], wrapValue(e[a], t));
|
|
4267
4288
|
}
|
|
4268
4289
|
if (f < e.length) u = true;
|
|
@@ -4817,11 +4838,11 @@ i) {
|
|
|
4817
4838
|
// Callers guard on `pendingCheckActive`, which only flips inside
|
|
4818
4839
|
// isPending() — the verdict layer is loaded and its hook installed.
|
|
4819
4840
|
const n = e[STORE_NODE]?.[$AFFECTS];
|
|
4820
|
-
if (n?.F) GlobalQueue.
|
|
4841
|
+
if (n?.F) GlobalQueue.pe(n);
|
|
4821
4842
|
if (affectsScopes.size) {
|
|
4822
4843
|
const r = e[STORE_VALUE];
|
|
4823
4844
|
for (const [e, i] of affectsScopes) {
|
|
4824
|
-
if (e !== n && e.F && i.scope.has(r) && (i.key === undefined || i.key === t)) GlobalQueue.
|
|
4845
|
+
if (e !== n && e.F && i.scope.has(r) && (i.key === undefined || i.key === t)) GlobalQueue.pe(e);
|
|
4825
4846
|
}
|
|
4826
4847
|
}
|
|
4827
4848
|
}
|
|
@@ -5412,7 +5433,7 @@ function createStore(e, t, n) {
|
|
|
5412
5433
|
globalQueue.D.L.push(e);
|
|
5413
5434
|
// Companions only exist once the verdict layer (isPending/latest) loaded;
|
|
5414
5435
|
// without them there is no materialized verdict to poke.
|
|
5415
|
-
GlobalQueue.
|
|
5436
|
+
GlobalQueue._e !== null && GlobalQueue._e(e);
|
|
5416
5437
|
notifyMarkBoundaries(e);
|
|
5417
5438
|
schedule();
|
|
5418
5439
|
}
|
|
@@ -5426,7 +5447,7 @@ function createStore(e, t, n) {
|
|
|
5426
5447
|
shiftAffectsMarks(-1);
|
|
5427
5448
|
e.F--;
|
|
5428
5449
|
if (!e.F) {
|
|
5429
|
-
GlobalQueue.
|
|
5450
|
+
GlobalQueue._e !== null && GlobalQueue._e(e, true);
|
|
5430
5451
|
GlobalQueue.ne?.(e);
|
|
5431
5452
|
}
|
|
5432
5453
|
}
|
|
@@ -6130,7 +6151,7 @@ function updateKeyedMap() {
|
|
|
6130
6151
|
this.Ut = e.slice(0);
|
|
6131
6152
|
this.Gt = t;
|
|
6132
6153
|
} else {
|
|
6133
|
-
let u, l, c, a, f, E, S, d, T,
|
|
6154
|
+
let u, l, c, a, f, E, S, d, T, _ = new Array(t), p = new Array(t);
|
|
6134
6155
|
i = this.Ft ? new Array(t) : undefined;
|
|
6135
6156
|
o = this.Wt ? new Array(t) : undefined;
|
|
6136
6157
|
// skip common prefix
|
|
@@ -6140,8 +6161,8 @@ function updateKeyedMap() {
|
|
|
6140
6161
|
// common suffix
|
|
6141
6162
|
for (l = this.Gt - 1, c = t - 1; l >= u && c >= u && (this.Ut[l] === e[c] || this.Ft && compare(this.Qt, this.Ut[l], e[c])); l--,
|
|
6142
6163
|
c--) {
|
|
6143
|
-
|
|
6144
|
-
|
|
6164
|
+
_[c] = this.Vt[l];
|
|
6165
|
+
p[c] = this.xt[l];
|
|
6145
6166
|
i && (i[c] = this.Ft[l]);
|
|
6146
6167
|
o && (o[c] = this.Wt[l]);
|
|
6147
6168
|
}
|
|
@@ -6161,8 +6182,8 @@ function updateKeyedMap() {
|
|
|
6161
6182
|
f = this.Qt ? this.Qt(a) : a;
|
|
6162
6183
|
r = E.get(f);
|
|
6163
6184
|
if (r !== undefined && r !== -1) {
|
|
6164
|
-
|
|
6165
|
-
|
|
6185
|
+
_[r] = this.Vt[n];
|
|
6186
|
+
p[r] = this.xt[n];
|
|
6166
6187
|
i && (i[r] = this.Ft[n]);
|
|
6167
6188
|
o && (o[r] = this.Wt[n]);
|
|
6168
6189
|
r = S[r];
|
|
@@ -6172,9 +6193,9 @@ function updateKeyedMap() {
|
|
|
6172
6193
|
// 2) create new rows into the temp arrays; an abort disposes only these
|
|
6173
6194
|
try {
|
|
6174
6195
|
for (r = u; r < t; r++) {
|
|
6175
|
-
if (r in
|
|
6176
|
-
(T ??= []).push(
|
|
6177
|
-
|
|
6196
|
+
if (r in _) continue;
|
|
6197
|
+
(T ??= []).push(p[r] = createOwner());
|
|
6198
|
+
_[r] = runWithOwner(p[r], s);
|
|
6178
6199
|
}
|
|
6179
6200
|
} catch (e) {
|
|
6180
6201
|
if (T) for (n = 0; n < T.length; n++) T[n].dispose();
|
|
@@ -6182,8 +6203,8 @@ function updateKeyedMap() {
|
|
|
6182
6203
|
}
|
|
6183
6204
|
// 3) commit: land positions, then dispose exited rows
|
|
6184
6205
|
for (r = u; r < t; r++) {
|
|
6185
|
-
this.Vt[r] =
|
|
6186
|
-
this.xt[r] =
|
|
6206
|
+
this.Vt[r] = _[r];
|
|
6207
|
+
this.xt[r] = p[r];
|
|
6187
6208
|
if (i) {
|
|
6188
6209
|
this.Ft[r] = i[r];
|
|
6189
6210
|
setSignal(this.Ft[r], e[r]);
|
|
@@ -6519,7 +6540,7 @@ class RevealController {
|
|
|
6519
6540
|
class CollectionQueue extends Queue {
|
|
6520
6541
|
Tn;
|
|
6521
6542
|
Bt=new Set;
|
|
6522
|
-
|
|
6543
|
+
_n;
|
|
6523
6544
|
Zt=true;
|
|
6524
6545
|
zt=signal(false, {
|
|
6525
6546
|
ownedWrite: true,
|
|
@@ -6532,7 +6553,7 @@ class CollectionQueue extends Queue {
|
|
|
6532
6553
|
});
|
|
6533
6554
|
nn;
|
|
6534
6555
|
rn=false;
|
|
6535
|
-
|
|
6556
|
+
pn;
|
|
6536
6557
|
On=ON_INIT;
|
|
6537
6558
|
constructor(e) {
|
|
6538
6559
|
super();
|
|
@@ -6544,10 +6565,10 @@ class CollectionQueue extends Queue {
|
|
|
6544
6565
|
}
|
|
6545
6566
|
notify(e, t, n, r) {
|
|
6546
6567
|
if (!(t & this.Tn)) return super.notify(e, t, n, r);
|
|
6547
|
-
if (this.rn && this.
|
|
6568
|
+
if (this.rn && this.pn) {
|
|
6548
6569
|
const e = untrack(() => {
|
|
6549
6570
|
try {
|
|
6550
|
-
return this.
|
|
6571
|
+
return this.pn();
|
|
6551
6572
|
} catch {
|
|
6552
6573
|
return ON_INIT;
|
|
6553
6574
|
}
|
|
@@ -6593,16 +6614,16 @@ class CollectionQueue extends Queue {
|
|
|
6593
6614
|
if (e.Le & REACTIVE_DISPOSED || !e.F && !(e.We & this.Tn) && !(this.Tn & STATUS_ERROR && e.We & STATUS_PENDING)) this.Bt.delete(e);
|
|
6594
6615
|
}
|
|
6595
6616
|
if (!this.Bt.size) {
|
|
6596
|
-
if (this.Tn & STATUS_PENDING && this.Zt && !this.rn && this.
|
|
6597
|
-
this.Zt = !!(this.
|
|
6617
|
+
if (this.Tn & STATUS_PENDING && this.Zt && !this.rn && this._n) {
|
|
6618
|
+
this.Zt = !!(this._n.We & this.Tn);
|
|
6598
6619
|
} else {
|
|
6599
6620
|
this.Zt = false;
|
|
6600
6621
|
}
|
|
6601
6622
|
if (!this.Zt) {
|
|
6602
6623
|
setSignal(this.zt, false);
|
|
6603
|
-
if (this.
|
|
6624
|
+
if (this.pn) {
|
|
6604
6625
|
try {
|
|
6605
|
-
this.On = untrack(() => this.
|
|
6626
|
+
this.On = untrack(() => this.pn());
|
|
6606
6627
|
} catch {
|
|
6607
6628
|
/* value not yet committed — _prevOn stays stale, next notify will reset */}
|
|
6608
6629
|
}
|
|
@@ -6620,8 +6641,8 @@ function createCollectionBoundary(e, t, n, r) {
|
|
|
6620
6641
|
ownedWrite: true,
|
|
6621
6642
|
gt: true
|
|
6622
6643
|
});
|
|
6623
|
-
if (r) o.
|
|
6624
|
-
const s = o.
|
|
6644
|
+
if (r) o.pn = r;
|
|
6645
|
+
const s = o._n = createBoundChildren(i, t, o, e);
|
|
6625
6646
|
// Prime source tracking so reveal registration sees pending sources.
|
|
6626
6647
|
untrack(() => {
|
|
6627
6648
|
let t = false;
|
package/dist/prod/core/async.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { STATUS_UNINITIALIZED, STATUS_ERROR, STATUS_PENDING, REACTIVE_DIRTY, REACTIVE_OPTIMISTIC_DIRTY, NOT_PENDING } from "./constants.js";
|
|
1
|
+
import { STATUS_UNINITIALIZED, STATUS_ERROR, STATUS_PENDING, REACTIVE_DIRTY, REACTIVE_OPTIMISTIC_DIRTY, NOT_PENDING, CONFIG_AUTO_DISPOSE } from "./constants.js";
|
|
2
2
|
|
|
3
3
|
import { untrack, context, setSignal } from "./core.js";
|
|
4
4
|
|
|
@@ -6,7 +6,7 @@ import "./invariants.js";
|
|
|
6
6
|
|
|
7
7
|
import { NotReadyError, StatusError } from "./error.js";
|
|
8
8
|
|
|
9
|
-
import { trimStaleDeps } from "./graph.js";
|
|
9
|
+
import { trimStaleDeps, unobserved } from "./graph.js";
|
|
10
10
|
|
|
11
11
|
import { enqueueSub } from "./heap.js";
|
|
12
12
|
|
|
@@ -160,11 +160,11 @@ function handleAsync(e, n, r) {
|
|
|
160
160
|
} else if (l) {
|
|
161
161
|
// Route through lane's effect queue for independent flushing
|
|
162
162
|
const n = e.Ae;
|
|
163
|
-
const r = e.
|
|
164
|
-
const o = e.
|
|
163
|
+
const r = e.Pe;
|
|
164
|
+
const o = e.Re;
|
|
165
165
|
try {
|
|
166
166
|
if (!n && u || !o || !o(t, r)) {
|
|
167
|
-
e.
|
|
167
|
+
e.Pe = t;
|
|
168
168
|
e.ce = clock;
|
|
169
169
|
// The latest() shadow write gives latest() effects independent lanes; the
|
|
170
170
|
// _pendingSignal update is a no-op repeat of the clearStatus() call above
|
|
@@ -193,18 +193,34 @@ function handleAsync(e, n, r) {
|
|
|
193
193
|
flush();
|
|
194
194
|
o?.();
|
|
195
195
|
};
|
|
196
|
+
// A pending node's in-flight promise is an observer: `unlinkSubs` skips
|
|
197
|
+
// autodispose while STATUS_PENDING so subscriber churn can't orphan the
|
|
198
|
+
// work (a lazy async memo would otherwise tear down and re-execute — one
|
|
199
|
+
// fetch per suspended re-read). Settling is that observer's release, so
|
|
200
|
+
// it runs the same last-one-out check the other release sites run.
|
|
201
|
+
const settleAutodispose = () => {
|
|
202
|
+
if (e.T & CONFIG_AUTO_DISPOSE && !e.o && !(e.S & STATUS_PENDING)) {
|
|
203
|
+
unobserved(e);
|
|
204
|
+
}
|
|
205
|
+
};
|
|
196
206
|
if (o) {
|
|
197
207
|
let r = false, t = false, o, l = true;
|
|
198
208
|
n.then(e => {
|
|
199
209
|
if (l) {
|
|
200
210
|
u = e;
|
|
201
211
|
r = true;
|
|
202
|
-
} else
|
|
212
|
+
} else {
|
|
213
|
+
asyncWrite(e);
|
|
214
|
+
settleAutodispose();
|
|
215
|
+
}
|
|
203
216
|
}, e => {
|
|
204
217
|
if (l) {
|
|
205
218
|
o = e;
|
|
206
219
|
t = true;
|
|
207
|
-
} else
|
|
220
|
+
} else {
|
|
221
|
+
handleError(e);
|
|
222
|
+
settleAutodispose();
|
|
223
|
+
}
|
|
208
224
|
});
|
|
209
225
|
l = false;
|
|
210
226
|
if (t) {
|
|
@@ -294,13 +310,13 @@ function clearStatus(e, n = false) {
|
|
|
294
310
|
// The pending window is over; its quiet classification dies with it.
|
|
295
311
|
// (Unconditional: _reask is baked into the node literals, so this is a
|
|
296
312
|
// plain store to an existing slot — no shape change.)
|
|
297
|
-
e.
|
|
313
|
+
e._e = false;
|
|
298
314
|
e.S = n ? 0 : e.S & STATUS_UNINITIALIZED;
|
|
299
315
|
if (e._) setPendingError(e);
|
|
300
316
|
// Update pending signal for isPending() reactivity (companions only exist
|
|
301
317
|
// once the verdict layer created them, which installs the hooks).
|
|
302
|
-
if (e.
|
|
303
|
-
if (e.u && GlobalQueue.
|
|
318
|
+
if (e.be || e.ge) GlobalQueue.ae(e);
|
|
319
|
+
if (e.u && GlobalQueue.he !== null) GlobalQueue.he(e);
|
|
304
320
|
if (e.i) e.i();
|
|
305
321
|
}
|
|
306
322
|
|
|
@@ -324,7 +340,7 @@ function notifyStatus(e, n, r, t, o) {
|
|
|
324
340
|
e._ = r;
|
|
325
341
|
}
|
|
326
342
|
GlobalQueue.ae !== null && GlobalQueue.ae(e);
|
|
327
|
-
if (e.u && GlobalQueue.
|
|
343
|
+
if (e.u && GlobalQueue.he !== null) GlobalQueue.he(e);
|
|
328
344
|
}
|
|
329
345
|
if (o && !t) {
|
|
330
346
|
assignOrMergeLane(e, o);
|
package/dist/prod/core/core.js
CHANGED
|
@@ -130,7 +130,7 @@ function recompute(e, t = false) {
|
|
|
130
130
|
e.Ye++;
|
|
131
131
|
e.se = REACTIVE_RECOMPUTING_DEPS;
|
|
132
132
|
e.ce = clock;
|
|
133
|
-
let a = e.Ne === NOT_PENDING ? e.
|
|
133
|
+
let a = e.Ne === NOT_PENDING ? e.Pe : e.Ne;
|
|
134
134
|
let r = e.He;
|
|
135
135
|
let c = tracking;
|
|
136
136
|
let _ = currentOptimisticLane;
|
|
@@ -202,10 +202,10 @@ function recompute(e, t = false) {
|
|
|
202
202
|
}
|
|
203
203
|
if (!e._) {
|
|
204
204
|
trimStaleDeps(e);
|
|
205
|
-
const o = l ? unwrapOverride(e.Ee) : e.Ne === NOT_PENDING ? e.
|
|
205
|
+
const o = l ? unwrapOverride(e.Ee) : e.Ne === NOT_PENDING ? e.Pe : e.Ne;
|
|
206
206
|
let s = false;
|
|
207
207
|
try {
|
|
208
|
-
s = !n && u || !e.
|
|
208
|
+
s = !n && u || !e.Re || !e.Re(o, a);
|
|
209
209
|
} catch (t) {
|
|
210
210
|
// A throwing user comparator is an error of this node's computation.
|
|
211
211
|
// Route it through the same status path as a compute-phase throw so
|
|
@@ -227,7 +227,7 @@ function recompute(e, t = false) {
|
|
|
227
227
|
if (e._) ; else if (s) {
|
|
228
228
|
const u = l ? e.Ee : undefined;
|
|
229
229
|
if (t || n && activeTransition !== e.Ue || i) {
|
|
230
|
-
e.
|
|
230
|
+
e.Pe = a;
|
|
231
231
|
// Lane-propagated correction: upstream data is fresh, correct the
|
|
232
232
|
// override unconditionally. The direct _value commit is the lane's
|
|
233
233
|
// own reveal schedule; drop any superseded older hold so its queued
|
|
@@ -293,14 +293,14 @@ function computed(e, t) {
|
|
|
293
293
|
const i = {
|
|
294
294
|
id: inheritId(t, n, context),
|
|
295
295
|
T: (n ? CONFIG_TRANSPARENT : 0) | (t?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (!context || t?.lazy ? CONFIG_AUTO_DISPOSE : 0) | (t?.sync ? CONFIG_SYNC : 0) | (t?.V ? CONFIG_NO_SNAPSHOT : 0) | (snapshotCaptureActive && ownerInSnapshotScope(context) ? CONFIG_IN_SNAPSHOT_SCOPE : 0),
|
|
296
|
-
|
|
296
|
+
Re: t?.equals != null ? t.equals : isEqual,
|
|
297
297
|
it: t?.unobserved,
|
|
298
298
|
xe: null,
|
|
299
299
|
C: context?.C ?? globalQueue,
|
|
300
300
|
we: context?.we ?? defaultContext,
|
|
301
301
|
Qe: 0,
|
|
302
302
|
ke: e,
|
|
303
|
-
|
|
303
|
+
Pe: undefined,
|
|
304
304
|
He: 0,
|
|
305
305
|
u: null,
|
|
306
306
|
lt: undefined,
|
|
@@ -322,7 +322,7 @@ function computed(e, t) {
|
|
|
322
322
|
Le: null,
|
|
323
323
|
Te: null,
|
|
324
324
|
Ue: null,
|
|
325
|
-
|
|
325
|
+
_e: false
|
|
326
326
|
};
|
|
327
327
|
setupComputedNode(i, t);
|
|
328
328
|
return i;
|
|
@@ -338,14 +338,14 @@ function computed(e, t) {
|
|
|
338
338
|
const s = {
|
|
339
339
|
id: inheritId(u, o, context),
|
|
340
340
|
T: (o ? CONFIG_TRANSPARENT : 0) | (u?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (u?.sync ? CONFIG_SYNC : 0) | (snapshotCaptureActive && ownerInSnapshotScope(context) ? CONFIG_IN_SNAPSHOT_SCOPE : 0),
|
|
341
|
-
|
|
341
|
+
Re: false,
|
|
342
342
|
it: u?.unobserved,
|
|
343
343
|
xe: null,
|
|
344
344
|
C: context?.C ?? globalQueue,
|
|
345
345
|
we: context?.we ?? defaultContext,
|
|
346
346
|
Qe: 0,
|
|
347
347
|
ke: e,
|
|
348
|
-
|
|
348
|
+
Pe: undefined,
|
|
349
349
|
He: 0,
|
|
350
350
|
u: null,
|
|
351
351
|
lt: undefined,
|
|
@@ -367,7 +367,7 @@ function computed(e, t) {
|
|
|
367
367
|
Le: null,
|
|
368
368
|
Te: null,
|
|
369
369
|
Ue: null,
|
|
370
|
-
|
|
370
|
+
_e: false,
|
|
371
371
|
$e: false,
|
|
372
372
|
rt: undefined,
|
|
373
373
|
ct: t,
|
|
@@ -402,7 +402,7 @@ function setupComputedNode(e, t) {
|
|
|
402
402
|
!t?.lazy && recompute(e, true);
|
|
403
403
|
if (snapshotCaptureActive && !t?.lazy) {
|
|
404
404
|
if (!(e.S & STATUS_PENDING) && !(e.T & CONFIG_NO_SNAPSHOT)) {
|
|
405
|
-
e.Ve = e.
|
|
405
|
+
e.Ve = e.Pe === undefined ? NO_SNAPSHOT : e.Pe;
|
|
406
406
|
snapshotSources.add(e);
|
|
407
407
|
}
|
|
408
408
|
}
|
|
@@ -410,10 +410,10 @@ function setupComputedNode(e, t) {
|
|
|
410
410
|
|
|
411
411
|
function signal(e, t, n = null) {
|
|
412
412
|
const i = {
|
|
413
|
-
|
|
413
|
+
Re: t?.equals != null ? t.equals : isEqual,
|
|
414
414
|
T: (t?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (t?.V ? CONFIG_NO_SNAPSHOT : 0),
|
|
415
415
|
it: t?.unobserved,
|
|
416
|
-
|
|
416
|
+
Pe: e,
|
|
417
417
|
o: null,
|
|
418
418
|
ot: null,
|
|
419
419
|
ce: clock,
|
|
@@ -514,7 +514,7 @@ function read(e) {
|
|
|
514
514
|
}
|
|
515
515
|
if (!n.ke && l === e && e.Ee === undefined && e.Ve === undefined && activeTransition === null && currentOptimisticLane === null && !snapshotCaptureActive && true) {
|
|
516
516
|
if (t && tracking) link(e, t);
|
|
517
|
-
return !t || e.Ne === NOT_PENDING ? e.
|
|
517
|
+
return !t || e.Ne === NOT_PENDING ? e.Pe : e.Ne;
|
|
518
518
|
}
|
|
519
519
|
if (t && tracking) {
|
|
520
520
|
link(e, t, pendingCheckActive);
|
|
@@ -562,7 +562,7 @@ function read(e) {
|
|
|
562
562
|
const n = e.Ve;
|
|
563
563
|
if (n !== undefined) {
|
|
564
564
|
const i = n === NO_SNAPSHOT ? undefined : n;
|
|
565
|
-
const l = e.Ne !== NOT_PENDING ? e.Ne : e.
|
|
565
|
+
const l = e.Ne !== NOT_PENDING ? e.Ne : e.Pe;
|
|
566
566
|
if (l !== i) t.se |= REACTIVE_SNAPSHOT_STALE;
|
|
567
567
|
return i;
|
|
568
568
|
}
|
|
@@ -579,13 +579,13 @@ function read(e) {
|
|
|
579
579
|
// so it re-runs with the new committed view. (Gate details live with the
|
|
580
580
|
// engine — a non-null lane implies it is installed.)
|
|
581
581
|
if (currentOptimisticLane !== null && activeTransition !== null && t !== null && GlobalQueue.Ct(e, l, t)) {
|
|
582
|
-
return e.
|
|
582
|
+
return e.Pe;
|
|
583
583
|
}
|
|
584
584
|
// In optimistic lane context, return _value for optimistic/lane-assigned signals
|
|
585
585
|
// and for regular signals in stale mode (render effects). Non-stale readers (user
|
|
586
586
|
// effects) see _pendingValue so that latest() and direct reads stay consistent.
|
|
587
587
|
// (The lane-context clause lives with the engine.)
|
|
588
|
-
const u = !t || currentOptimisticLane !== null && GlobalQueue.Ot(e, l, t) || e.Ne === NOT_PENDING || stale && e.Ue && activeTransition !== e.Ue ? e.
|
|
588
|
+
const u = !t || currentOptimisticLane !== null && GlobalQueue.Ot(e, l, t) || e.Ne === NOT_PENDING || stale && e.Ue && activeTransition !== e.Ue ? e.Pe : e.Ne;
|
|
589
589
|
// Record that this isPending() probe observed the fresh pending value, so
|
|
590
590
|
// the probe doesn't pair "pending" with the new value (#2831).
|
|
591
591
|
if (pendingCheckActive) GlobalQueue.Rt(e, u);
|
|
@@ -602,11 +602,11 @@ function setSignal(e, t) {
|
|
|
602
602
|
// _overrideValue slot, and every module that creates one installs the
|
|
603
603
|
// engine first.
|
|
604
604
|
if (e.Ee !== undefined && !projectionWriteActive) return GlobalQueue.Pt(e, t);
|
|
605
|
-
const n = e.Ne === NOT_PENDING ? e.
|
|
605
|
+
const n = e.Ne === NOT_PENDING ? e.Pe : e.Ne;
|
|
606
606
|
if (typeof t === "function") t = t(n);
|
|
607
607
|
// Uninitialized check first: the first commit has no previous value, so the
|
|
608
608
|
// user comparator must not run against `undefined` (matches recompute).
|
|
609
|
-
const i = !!(e.S & STATUS_UNINITIALIZED) || !e.
|
|
609
|
+
const i = !!(e.S & STATUS_UNINITIALIZED) || !e.Re || !e.Re(n, t);
|
|
610
610
|
if (!i) return t;
|
|
611
611
|
if (e.Ne === NOT_PENDING) queuePendingNode(e);
|
|
612
612
|
e.Ne = t;
|
package/dist/prod/core/effect.js
CHANGED
|
@@ -62,7 +62,7 @@ function runEffect(t) {
|
|
|
62
62
|
// same flush must not be hijacked by a later-arriving error status.
|
|
63
63
|
if (t.S & STATUS_ERROR && t.Ae === EFFECT_USER) {
|
|
64
64
|
const E = unwrapStatusError(t._);
|
|
65
|
-
t.rt = t.
|
|
65
|
+
t.rt = t.Pe;
|
|
66
66
|
t.$e = false;
|
|
67
67
|
try {
|
|
68
68
|
t._t ? t._t(E, () => {
|
|
@@ -82,7 +82,7 @@ function runEffect(t) {
|
|
|
82
82
|
t.Et = undefined;
|
|
83
83
|
try {
|
|
84
84
|
E?.();
|
|
85
|
-
const e = t.ct(t.
|
|
85
|
+
const e = t.ct(t.Pe, t.rt);
|
|
86
86
|
if (false && e !== undefined && typeof e !== "function") ;
|
|
87
87
|
// The final cleanup is invoked by disposeChildren at true disposal.
|
|
88
88
|
t.Et = e;
|
|
@@ -94,7 +94,7 @@ function runEffect(t) {
|
|
|
94
94
|
throw E;
|
|
95
95
|
}
|
|
96
96
|
} finally {
|
|
97
|
-
t.rt = t.
|
|
97
|
+
t.rt = t.Pe;
|
|
98
98
|
t.$e = false;
|
|
99
99
|
}
|
|
100
100
|
}
|
package/dist/prod/core/graph.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CONFIG_AUTO_DISPOSE, REACTIVE_ZOMBIE, REACTIVE_RECOMPUTING_DEPS } from "./constants.js";
|
|
1
|
+
import { CONFIG_AUTO_DISPOSE, REACTIVE_ZOMBIE, STATUS_PENDING, REACTIVE_RECOMPUTING_DEPS } from "./constants.js";
|
|
2
2
|
|
|
3
3
|
import { deleteFromHeap, queueFor } from "./heap.js";
|
|
4
4
|
|
|
@@ -18,8 +18,13 @@ function unlinkSubs(l) {
|
|
|
18
18
|
if (u === null) {
|
|
19
19
|
n.it?.();
|
|
20
20
|
// No more subscribers; only tear down if CONFIG_AUTO_DISPOSE is set.
|
|
21
|
+
// A pending node is exempt: its in-flight async work (or the
|
|
22
|
+
// transition holding it) is an observer — tearing down would orphan
|
|
23
|
+
// the work and re-execute it on the next read. The settle path runs
|
|
24
|
+
// this same last-one-out check when that observer releases (the
|
|
25
|
+
// untracked-read dispose in core.ts guards on pending identically).
|
|
21
26
|
const l = n;
|
|
22
|
-
l.ke && l.T & CONFIG_AUTO_DISPOSE && !(l.se & REACTIVE_ZOMBIE) && unobserved(l);
|
|
27
|
+
l.ke && l.T & CONFIG_AUTO_DISPOSE && !(l.se & REACTIVE_ZOMBIE) && !(l.S & STATUS_PENDING) && unobserved(l);
|
|
23
28
|
}
|
|
24
29
|
}
|
|
25
30
|
return e;
|
package/dist/prod/core/lanes.js
CHANGED
|
@@ -36,8 +36,8 @@ const activeLanes = new Set;
|
|
|
36
36
|
// parent-child is a property of the nodes, not of write order — otherwise
|
|
37
37
|
// the owner's write merges the companion's subscribers into this lane and
|
|
38
38
|
// their effects wait on its async instead of flushing immediately.
|
|
39
|
-
adoptCompanionLane(n.
|
|
40
|
-
adoptCompanionLane(n.
|
|
39
|
+
adoptCompanionLane(n.be, e);
|
|
40
|
+
adoptCompanionLane(n.ge, e);
|
|
41
41
|
return e;
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -25,9 +25,9 @@ import { GlobalQueue, activeTransition, globalQueue, clock, insertSubs, schedule
|
|
|
25
25
|
*/
|
|
26
26
|
/** The optimistic half of setSignal, fired when `_overrideValue !== undefined`. */ function optimisticWrite(e, n) {
|
|
27
27
|
const t = e.Ee !== NOT_PENDING;
|
|
28
|
-
const i = t ? unwrapOverride(e.Ee) : e.
|
|
28
|
+
const i = t ? unwrapOverride(e.Ee) : e.Pe;
|
|
29
29
|
if (typeof n === "function") n = n(i);
|
|
30
|
-
const u = !!(e.S & STATUS_UNINITIALIZED) || !e.
|
|
30
|
+
const u = !!(e.S & STATUS_UNINITIALIZED) || !e.Re || !e.Re(i, n);
|
|
31
31
|
if (!u) {
|
|
32
32
|
// Same-value write with an active override still entangles the current
|
|
33
33
|
// action's transition — the hold must outlast all overlapping actions.
|
|
@@ -87,7 +87,7 @@ function resolveOptimisticNodes(e) {
|
|
|
87
87
|
if (!(n.S & STATUS_PENDING)) n.S &= ~STATUS_UNINITIALIZED;
|
|
88
88
|
const i = n.Ee;
|
|
89
89
|
n.Ee = NOT_PENDING;
|
|
90
|
-
if (i !== NOT_PENDING && n.
|
|
90
|
+
if (i !== NOT_PENDING && n.Pe !== unwrapOverride(i)) insertSubs(n, true);
|
|
91
91
|
n.Ue = null;
|
|
92
92
|
n.sn = null;
|
|
93
93
|
}
|
|
@@ -96,9 +96,9 @@ function resolveOptimisticNodes(e) {
|
|
|
96
96
|
// transition that produced them (A19 — pending is a property of the data).
|
|
97
97
|
for (let t = 0; t < n; t++) {
|
|
98
98
|
const n = e[t];
|
|
99
|
-
if (n.
|
|
99
|
+
if (n.be || n.ge) GlobalQueue.un(n);
|
|
100
100
|
const i = n.nn;
|
|
101
|
-
if (i && (i.
|
|
101
|
+
if (i && (i.be === n || i.ge === n)) GlobalQueue.un(i);
|
|
102
102
|
}
|
|
103
103
|
e.splice(0, n);
|
|
104
104
|
}
|
package/dist/prod/core/owner.js
CHANGED
|
@@ -51,7 +51,7 @@ function disposeChildren(e, n = false, t) {
|
|
|
51
51
|
// edge). Snap runs after the DISPOSED flag is set so the oracle reads
|
|
52
52
|
// false, and notifies subscribers still watching the companion.
|
|
53
53
|
const n = e;
|
|
54
|
-
if (n.
|
|
54
|
+
if (n.be || n.ge) GlobalQueue.un(n);
|
|
55
55
|
}
|
|
56
56
|
if (n && e.ke) e.Te = null;
|
|
57
57
|
let l = t ? e.Le : e.me;
|
|
@@ -279,7 +279,7 @@ class GlobalQueue extends Queue {
|
|
|
279
279
|
// isPending()/latest()).
|
|
280
280
|
static Ie=null;
|
|
281
281
|
static ae=null;
|
|
282
|
-
static
|
|
282
|
+
static he=null;
|
|
283
283
|
static un=null;
|
|
284
284
|
static St=null;
|
|
285
285
|
static dt=null;
|
|
@@ -495,14 +495,14 @@ function commitPendingNode(e) {
|
|
|
495
495
|
const t = e;
|
|
496
496
|
if (!t.ke) {
|
|
497
497
|
if (e.Ne !== NOT_PENDING) {
|
|
498
|
-
e.
|
|
498
|
+
e.Pe = e.Ne;
|
|
499
499
|
e.Ne = NOT_PENDING;
|
|
500
500
|
}
|
|
501
|
-
if (e.
|
|
501
|
+
if (e.be || e.ge) GlobalQueue.un(e);
|
|
502
502
|
return;
|
|
503
503
|
}
|
|
504
504
|
if (e.Ne !== NOT_PENDING) {
|
|
505
|
-
e.
|
|
505
|
+
e.Pe = e.Ne;
|
|
506
506
|
e.Ne = NOT_PENDING;
|
|
507
507
|
// Set _modified for effects, but not for tracked effects (they handle their own scheduling)
|
|
508
508
|
if (e.Ae && e.Ae !== EFFECT_TRACKED) e.$e = true;
|
|
@@ -510,7 +510,7 @@ function commitPendingNode(e) {
|
|
|
510
510
|
t.se &= ~REACTIVE_MANUAL_WRITE;
|
|
511
511
|
if (!(t.S & STATUS_PENDING)) t.S &= ~STATUS_UNINITIALIZED;
|
|
512
512
|
if (t.Le !== null || t.ye !== null) GlobalQueue.Ce(t, false, true);
|
|
513
|
-
if (e.
|
|
513
|
+
if (e.be || e.ge) GlobalQueue.un(e);
|
|
514
514
|
}
|
|
515
515
|
|
|
516
516
|
function commitPendingNodes() {
|
|
@@ -32,15 +32,15 @@ let pendingProbe = null;
|
|
|
32
32
|
* Get or create the pending signal for a node (lazy).
|
|
33
33
|
* Used by isPending() to track pending state reactively.
|
|
34
34
|
*/ function getPendingSignal(e) {
|
|
35
|
-
if (!e.
|
|
35
|
+
if (!e.be) {
|
|
36
36
|
// Start false, write true if pending - ensures reversion returns to false
|
|
37
|
-
e.
|
|
37
|
+
e.be = optimisticSignal(false, {
|
|
38
38
|
ownedWrite: true
|
|
39
39
|
});
|
|
40
|
-
e.
|
|
41
|
-
if (computePendingState(e)) setSignal(e.
|
|
40
|
+
e.be.nn = e;
|
|
41
|
+
if (computePendingState(e)) setSignal(e.be, true);
|
|
42
42
|
}
|
|
43
|
-
return e.
|
|
43
|
+
return e.be;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
function collectPendingSources(e) {
|
|
@@ -102,10 +102,10 @@ function collectPendingSources(e) {
|
|
|
102
102
|
|
|
103
103
|
function quietPending(e) {
|
|
104
104
|
if (e.oe) {
|
|
105
|
-
for (const t of e.oe) if (!t.
|
|
105
|
+
for (const t of e.oe) if (!t._e) return false;
|
|
106
106
|
return true;
|
|
107
107
|
}
|
|
108
|
-
return e.
|
|
108
|
+
return e._e;
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
function newQuestionInFlight(e) {
|
|
@@ -129,27 +129,27 @@ function computePendingState(e) {
|
|
|
129
129
|
return !!(n.se & REACTIVE_MANUAL_WRITE) || !n.Te && !(n.S & STATUS_PENDING) || !!(n.S & STATUS_PENDING) && quietPending(n);
|
|
130
130
|
}
|
|
131
131
|
if (e.Ne !== NOT_PENDING && !(t.S & STATUS_UNINITIALIZED)) {
|
|
132
|
-
if (hasActiveOverride(e)) return !e.
|
|
132
|
+
if (hasActiveOverride(e)) return !e.Re || !e.Re(e.Ne, unwrapOverride(e.Ee));
|
|
133
133
|
return true;
|
|
134
134
|
}
|
|
135
135
|
return newQuestionInFlight(t);
|
|
136
136
|
}
|
|
137
137
|
|
|
138
138
|
function syncCompanions(e, t) {
|
|
139
|
-
if (e.
|
|
140
|
-
if (e.
|
|
139
|
+
if (e.be) updatePendingSignal(e);
|
|
140
|
+
if (e.ge) setSignal(e.ge, t);
|
|
141
141
|
}
|
|
142
142
|
|
|
143
143
|
function updatePendingSignal(e) {
|
|
144
|
-
if (e.
|
|
145
|
-
setSignal(e.
|
|
144
|
+
if (e.be) {
|
|
145
|
+
setSignal(e.be, computePendingState(e));
|
|
146
146
|
}
|
|
147
|
-
if (e.
|
|
147
|
+
if (e.ge) updatePendingSignal(e.ge);
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
function updateChildCompanions(e) {
|
|
151
151
|
for (let t = e.u; t !== null; t = t.fe) {
|
|
152
|
-
if (t.
|
|
152
|
+
if (t.be || t.ge) updatePendingSignal(t);
|
|
153
153
|
}
|
|
154
154
|
}
|
|
155
155
|
|
|
@@ -167,7 +167,7 @@ function updateChildCompanions(e) {
|
|
|
167
167
|
const visit = e => {
|
|
168
168
|
if (i.has(e)) return;
|
|
169
169
|
i.add(e);
|
|
170
|
-
if (e.
|
|
170
|
+
if (e.be || e.ge) n(e);
|
|
171
171
|
for (let t = e.o; t !== null; t = t.ue) visit(t.le);
|
|
172
172
|
for (let t = e.u ?? null; t !== null; t = t.fe) {
|
|
173
173
|
visit(t);
|
|
@@ -177,20 +177,20 @@ function updateChildCompanions(e) {
|
|
|
177
177
|
}
|
|
178
178
|
|
|
179
179
|
function snapCompanionsToState(e) {
|
|
180
|
-
const t = e.
|
|
180
|
+
const t = e.be;
|
|
181
181
|
if (t && (t.Ee === undefined || t.Ee === NOT_PENDING)) {
|
|
182
182
|
const n = computePendingState(e);
|
|
183
|
-
if (t.
|
|
184
|
-
t.
|
|
183
|
+
if (t.Pe !== n || t.Ne !== NOT_PENDING) {
|
|
184
|
+
t.Pe = n;
|
|
185
185
|
t.Ne = NOT_PENDING;
|
|
186
186
|
t.ce = clock;
|
|
187
187
|
insertSubs(t);
|
|
188
188
|
schedule();
|
|
189
189
|
}
|
|
190
190
|
}
|
|
191
|
-
const n = e.
|
|
191
|
+
const n = e.ge;
|
|
192
192
|
if (n && !(n.se & REACTIVE_DISPOSED)) {
|
|
193
|
-
if ((n.Ee === undefined || n.Ee === NOT_PENDING) && n.Ne === NOT_PENDING && !Object.is(n.
|
|
193
|
+
if ((n.Ee === undefined || n.Ee === NOT_PENDING) && n.Ne === NOT_PENDING && !Object.is(n.Pe, e.Pe) && !(n.se & (REACTIVE_DIRTY | REACTIVE_CHECK))) {
|
|
194
194
|
n.se |= REACTIVE_DIRTY;
|
|
195
195
|
insertIntoHeap(n, queueFor(n));
|
|
196
196
|
insertSubs(n);
|
|
@@ -201,7 +201,7 @@ function snapCompanionsToState(e) {
|
|
|
201
201
|
}
|
|
202
202
|
|
|
203
203
|
function getLatestValueComputed(e) {
|
|
204
|
-
if (!e.
|
|
204
|
+
if (!e.ge) {
|
|
205
205
|
const t = latestReadActive;
|
|
206
206
|
setLatestReadActive(false);
|
|
207
207
|
const n = pendingCheckActive;
|
|
@@ -209,21 +209,21 @@ function getLatestValueComputed(e) {
|
|
|
209
209
|
const i = context;
|
|
210
210
|
setContextInternal(null);
|
|
211
211
|
// Detach from owner so it isn't disposed with effects
|
|
212
|
-
e.
|
|
213
|
-
e.
|
|
212
|
+
e.ge = optimisticComputed(() => read(e));
|
|
213
|
+
e.ge.nn = e;
|
|
214
214
|
// Parent-child lane relationship
|
|
215
215
|
setContextInternal(i);
|
|
216
216
|
setPendingCheckActive(n);
|
|
217
217
|
setLatestReadActive(t);
|
|
218
218
|
}
|
|
219
|
-
return e.
|
|
219
|
+
return e.ge;
|
|
220
220
|
}
|
|
221
221
|
|
|
222
222
|
/** The latest()-mode read path, installed as GlobalQueue._latestRead. */ function latestRead(e) {
|
|
223
223
|
const t = getLatestValueComputed(e);
|
|
224
224
|
const n = latestReadActive;
|
|
225
225
|
setLatestReadActive(false);
|
|
226
|
-
const i = e.Ee !== undefined && e.Ee !== NOT_PENDING ? unwrapOverride(e.Ee) : e.
|
|
226
|
+
const i = e.Ee !== undefined && e.Ee !== NOT_PENDING ? unwrapOverride(e.Ee) : e.Pe;
|
|
227
227
|
let r;
|
|
228
228
|
try {
|
|
229
229
|
// An untracked latest() read has no reading context, so read() never
|
|
@@ -279,9 +279,9 @@ function recordFreshRead(e, t) {
|
|
|
279
279
|
|
|
280
280
|
function applyReask(e, t) {
|
|
281
281
|
const n = !!(e.S & STATUS_PENDING);
|
|
282
|
-
const i = t && !(n && !e.
|
|
283
|
-
const r = n && e.
|
|
284
|
-
e.
|
|
282
|
+
const i = t && !(n && !e._e);
|
|
283
|
+
const r = n && e._e !== i;
|
|
284
|
+
e._e = i;
|
|
285
285
|
return r;
|
|
286
286
|
}
|
|
287
287
|
|
|
@@ -339,7 +339,7 @@ GlobalQueue.Ie = syncCompanions;
|
|
|
339
339
|
|
|
340
340
|
GlobalQueue.ae = updatePendingSignal;
|
|
341
341
|
|
|
342
|
-
GlobalQueue.
|
|
342
|
+
GlobalQueue.he = updateChildCompanions;
|
|
343
343
|
|
|
344
344
|
GlobalQueue.un = snapCompanionsToState;
|
|
345
345
|
|
package/dist/prod/store/store.js
CHANGED
|
@@ -154,7 +154,7 @@ function ownEnumerableKeysPlain(e) {
|
|
|
154
154
|
* The value a store leaf's backing signal currently shows to readers: active
|
|
155
155
|
* override, else held pending value, else committed value.
|
|
156
156
|
*/ function visibleNodeValue(e) {
|
|
157
|
-
return e.Ee !== undefined && e.Ee !== NOT_PENDING ? unwrapOverride(e.Ee) : e.Ne !== NOT_PENDING ? e.Ne : e.
|
|
157
|
+
return e.Ee !== undefined && e.Ee !== NOT_PENDING ? unwrapOverride(e.Ee) : e.Ne !== NOT_PENDING ? e.Ne : e.Pe;
|
|
158
158
|
}
|
|
159
159
|
|
|
160
160
|
function hasOwnStoreProperty(e, t) {
|
package/package.json
CHANGED