@solidjs/signals 2.0.0-rc.11 → 2.0.0-rc.14
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-shared.js +2056 -3773
- package/dist/dev.attribution.js +159 -91
- package/dist/dev.js +7263 -8384
- package/dist/observe/affects.js +125 -104
- package/dist/observe/boundaries.js +458 -665
- package/dist/observe/core/action.js +63 -66
- package/dist/observe/core/async.js +240 -383
- package/dist/observe/core/attribution-queries.js +1 -1
- package/dist/observe/core/attribution.js +271 -199
- package/dist/observe/core/constants.js +115 -178
- package/dist/observe/core/context.js +3 -3
- package/dist/observe/core/core.js +840 -1428
- package/dist/observe/core/dev.js +41 -18
- package/dist/observe/core/effect.js +75 -86
- package/dist/observe/core/external.js +5 -5
- package/dist/observe/core/graph.js +61 -70
- package/dist/observe/core/heap.js +75 -98
- package/dist/observe/core/invariants.js +1 -34
- package/dist/observe/core/lanes.js +704 -181
- package/dist/observe/core/owner.js +80 -101
- package/dist/observe/core/scheduler.js +708 -1351
- package/dist/observe/core/verdict.js +302 -621
- package/dist/observe/flatten.js +79 -0
- package/dist/observe/index.js +15 -13
- package/dist/observe/map.js +232 -235
- package/dist/observe/reveal.js +212 -0
- package/dist/observe/signals.js +133 -215
- package/dist/observe/store/affects.js +135 -0
- package/dist/observe/store/index.js +29 -24
- package/dist/observe/store/optimistic.js +538 -0
- package/dist/observe/store/projection.js +302 -0
- package/dist/observe/store/reconcile.js +257 -0
- package/dist/observe/store/store.js +1945 -277
- package/dist/observe/store/storePath.js +1 -1
- package/dist/{prod/store/next → observe/store}/target.js +17 -18
- package/dist/observe/store/types.js +73 -0
- package/dist/observe/store/utils.js +1 -13
- package/dist/prod/affects.js +127 -106
- package/dist/prod/boundaries.js +442 -654
- package/dist/prod/core/action.js +71 -74
- package/dist/prod/core/async.js +307 -442
- package/dist/prod/core/constants.js +112 -177
- package/dist/prod/core/context.js +3 -3
- package/dist/prod/core/core.js +852 -1448
- package/dist/prod/core/effect.js +88 -99
- package/dist/prod/core/external.js +5 -5
- package/dist/prod/core/graph.js +61 -70
- package/dist/prod/core/heap.js +75 -98
- package/dist/prod/core/invariants.js +1 -32
- package/dist/prod/core/lanes.js +666 -181
- package/dist/prod/core/owner.js +75 -96
- package/dist/prod/core/scheduler.js +677 -1332
- package/dist/prod/core/verdict.js +297 -621
- package/dist/prod/flatten.js +77 -0
- package/dist/prod/index.js +15 -13
- package/dist/prod/map.js +143 -146
- package/dist/prod/reveal.js +212 -0
- package/dist/prod/signals.js +144 -226
- package/dist/prod/store/affects.js +135 -0
- package/dist/prod/store/index.js +28 -19
- package/dist/prod/store/optimistic.js +533 -0
- package/dist/prod/store/projection.js +295 -0
- package/dist/prod/store/reconcile.js +257 -0
- package/dist/prod/store/store.js +1840 -272
- package/dist/prod/store/storePath.js +1 -1
- package/dist/{observe/store/next → prod/store}/target.js +13 -17
- package/dist/prod/store/types.js +73 -0
- package/dist/prod/store/utils.js +1 -11
- package/dist/types/affects.d.ts +11 -30
- package/dist/types/boundaries.d.ts +62 -176
- package/dist/types/carved.d.ts +1 -0
- package/dist/types/core/action.d.ts +5 -6
- package/dist/types/core/async.d.ts +10 -5
- package/dist/types/core/attribution-hooks.d.ts +48 -1
- package/dist/types/core/attribution.d.ts +29 -9
- package/dist/types/core/constants.d.ts +125 -171
- package/dist/types/core/core.d.ts +104 -264
- package/dist/types/core/dev.d.ts +60 -7
- package/dist/types/core/effect.d.ts +0 -7
- package/dist/types/core/graph.d.ts +7 -1
- package/dist/types/core/heap.d.ts +5 -7
- package/dist/types/core/index.d.ts +6 -6
- package/dist/types/core/invariants.d.ts +0 -29
- package/dist/types/core/lanes.d.ts +65 -87
- package/dist/types/core/owner.d.ts +3 -3
- package/dist/types/core/scheduler.d.ts +249 -331
- package/dist/types/core/types.d.ts +51 -85
- package/dist/types/core/verdict.d.ts +3 -0
- package/dist/types/flatten.d.ts +8 -0
- package/dist/types/index.d.ts +7 -5
- package/dist/types/reveal.d.ts +19 -0
- package/dist/types/signals.d.ts +53 -92
- package/dist/types/store/affects.d.ts +1 -0
- package/dist/types/store/index.d.ts +35 -15
- package/dist/types/store/optimistic.d.ts +23 -0
- package/dist/types/store/projection.d.ts +18 -0
- package/dist/types/store/reconcile.d.ts +3 -0
- package/dist/types/store/store.d.ts +165 -143
- package/dist/types/store/storePath.d.ts +1 -1
- package/dist/types/store/target.d.ts +151 -0
- package/dist/types/store/types.d.ts +84 -0
- package/package.json +1 -1
- package/dist/observe/core/optimistic.js +0 -669
- package/dist/observe/store/next/optimistic.js +0 -717
- package/dist/observe/store/next/projection.js +0 -266
- package/dist/observe/store/next/reconcile.js +0 -375
- package/dist/observe/store/next/store.js +0 -2480
- package/dist/prod/core/optimistic.js +0 -658
- package/dist/prod/store/next/optimistic.js +0 -710
- package/dist/prod/store/next/projection.js +0 -257
- package/dist/prod/store/next/reconcile.js +0 -373
- package/dist/prod/store/next/store.js +0 -2356
- package/dist/types/core/optimistic.d.ts +0 -6
- package/dist/types/store/next/optimistic.d.ts +0 -25
- package/dist/types/store/next/projection.d.ts +0 -27
- package/dist/types/store/next/reconcile.d.ts +0 -10
- package/dist/types/store/next/store.d.ts +0 -143
- package/dist/types/store/next/target.d.ts +0 -196
|
@@ -1,44 +1,49 @@
|
|
|
1
|
-
import "
|
|
1
|
+
import { createStore as createStore$1, deep as deep$1, snapshot as snapshot$1 } from "./store.js";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
export { storeHasFamily, storeHasOptimisticFamily, storeIsShallow } from "./store.js";
|
|
4
4
|
|
|
5
|
-
import "
|
|
5
|
+
import "./affects.js";
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
export { createOptimisticStore } from "./optimistic.js";
|
|
8
8
|
|
|
9
|
-
import "
|
|
9
|
+
import { createStoreDerived } from "./projection.js";
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
export { createProjection } from "./projection.js";
|
|
12
|
+
|
|
13
|
+
import { reconcileState } from "./reconcile.js";
|
|
12
14
|
|
|
13
|
-
import
|
|
15
|
+
import "../core/verdict.js";
|
|
16
|
+
|
|
17
|
+
import "../core/core.js";
|
|
14
18
|
|
|
15
|
-
|
|
19
|
+
import "../core/dev.js";
|
|
16
20
|
|
|
17
|
-
import
|
|
21
|
+
import "../core/scheduler.js";
|
|
18
22
|
|
|
19
|
-
import
|
|
23
|
+
import "../core/effect.js";
|
|
20
24
|
|
|
21
|
-
|
|
25
|
+
import "../core/lanes.js";
|
|
22
26
|
|
|
23
|
-
function createStore(e,
|
|
24
|
-
if (typeof e === "function") return
|
|
25
|
-
|
|
26
|
-
const r = createStoreNext(e, !!t?.shallow);
|
|
27
|
-
if (t?.name) nameStore(r[0], t.name);
|
|
28
|
-
return r;
|
|
29
|
-
}
|
|
27
|
+
function createStore(e, r, t) {
|
|
28
|
+
if (typeof e === "function") return createStoreDerived(e, r, t);
|
|
29
|
+
return createStore$1(e, r);
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
/**
|
|
33
|
+
* A setter transform that reconciles `value` into the store by key
|
|
34
|
+
* (`"id"` by default; `null` positional), preserving store identity for
|
|
35
|
+
* surviving rows.
|
|
36
|
+
*/ function reconcile(e, r = "id") {
|
|
37
|
+
return t => reconcileState(e, t, r);
|
|
34
38
|
}
|
|
35
39
|
|
|
36
|
-
|
|
37
|
-
|
|
40
|
+
/** Non-tracking snapshot of a store's current value (source identity for
|
|
41
|
+
* unmodified subtrees). */ function snapshot(e) {
|
|
42
|
+
return snapshot$1(e);
|
|
38
43
|
}
|
|
39
44
|
|
|
40
|
-
function deep(e) {
|
|
41
|
-
return
|
|
45
|
+
/** Tracking snapshot: subscribes to every reachable record. */ function deep(e) {
|
|
46
|
+
return deep$1(e);
|
|
42
47
|
}
|
|
43
48
|
|
|
44
49
|
export { createStore, deep, reconcile, snapshot };
|
|
@@ -0,0 +1,538 @@
|
|
|
1
|
+
import { CONFIG_OVERRIDE, CONFIG_AUTO_DISPOSE, NOT_PENDING } from "../core/constants.js";
|
|
2
|
+
|
|
3
|
+
import { computed, ext, untrack, read, isEqual } from "../core/core.js";
|
|
4
|
+
|
|
5
|
+
import { pendingGuessOf, laneValueOf, optimisticWrite } from "../core/lanes.js";
|
|
6
|
+
|
|
7
|
+
import { getOwner } from "../core/owner.js";
|
|
8
|
+
|
|
9
|
+
import { GlobalQueue, txOf, list, insertSubs, laneDirty, notifyEpoch, schedule } from "../core/scheduler.js";
|
|
10
|
+
|
|
11
|
+
import { runProjectionComputed } from "./projection.js";
|
|
12
|
+
|
|
13
|
+
import { wrap, nameStore, storeSetter, LaneView, committed, getNode, unwrapValue, sameKey, installOptHooks, resolveChainedRaw, getHasNode, targetsEqual, getContainerNode, cloneRaw } from "./store.js";
|
|
14
|
+
|
|
15
|
+
import { $OWNER } from "./target.js";
|
|
16
|
+
|
|
17
|
+
import { $TARGET, markRawIngest, $TRACK, isWrappable } from "./types.js";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Store — optimistic stores on lanes (plan sec. 31, S4; INTERNALS §3/§7, RUL-3).
|
|
21
|
+
*
|
|
22
|
+
* No store-side layer, no backup snapshots, no retaining ledger: a user
|
|
23
|
+
* write to an optimistic store is a GUESS on the written key's node
|
|
24
|
+
* (`optimisticWrite` — the same write `createOptimistic`'s setter makes),
|
|
25
|
+
* a presence guess on its presence node, and, when membership or
|
|
26
|
+
* arrangement changed, an arrangement guess on the container node. Lanes
|
|
27
|
+
* do the rest: the guess shows under the action's hold, a landing beneath
|
|
28
|
+
* it stages as truth and confirms it when equal (A18/A24), the action's
|
|
29
|
+
* settle dissolves it (a revert to the value it covered, or the landed
|
|
30
|
+
* truth). The committed backing is never touched by a guess.
|
|
31
|
+
*
|
|
32
|
+
* Reads compose: a reader of an overlaid target sees the truth it is served
|
|
33
|
+
* with the lanes' values over it (`optimisticView` — per node, by the same
|
|
34
|
+
* rule a leaf read follows: what the lane shows).
|
|
35
|
+
*
|
|
36
|
+
* Landings (Q-D, plan sec. 31.7): the derive's output is reconciled against the
|
|
37
|
+
* optimistic VIEW — a row the guess added and the server returns with the
|
|
38
|
+
* same key in the same position keeps its proxy (the row target adopts the
|
|
39
|
+
* server object), its leaves write truth beneath their guesses, and the
|
|
40
|
+
* container's arrangement guess is confirmed silently (`LaneView`'s
|
|
41
|
+
* comparator) — `For` does not run. Retained-setter replay (the
|
|
42
|
+
* 2026-08-31b continuation half) is not built here; the matrix decides.
|
|
43
|
+
*/ const hasOwn = Object.prototype.hasOwnProperty;
|
|
44
|
+
|
|
45
|
+
/** A user setter's writes on an optimistic family, as guesses: one per
|
|
46
|
+
* changed key's leaf, one per presence change, the container's arrangement
|
|
47
|
+
* when membership or order changed. `pb` is the draft (a clone of the view
|
|
48
|
+
* the user saw); `old` the view it composed on. */
|
|
49
|
+
/** An optimistic setter's targets whose staging was set aside (`draft`),
|
|
50
|
+
* restored when the setter's writes become guesses (`writes`). */ const optStaged = new Map;
|
|
51
|
+
|
|
52
|
+
// A chained backing is a proxy: reading it as a handler can expose a
|
|
53
|
+
// derived store's staging. Compose the writer's view on the committed
|
|
54
|
+
// backing of each link, retaining any optimistic guesses on that link.
|
|
55
|
+
function writerBacking(e) {
|
|
56
|
+
const n = committed(e);
|
|
57
|
+
const t = n[$TARGET];
|
|
58
|
+
return t === undefined ? n : optimisticView(t, writerBacking(t), laneValueOf, true);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** The user's draft on an optimistic family: a clone of the view the user
|
|
62
|
+
* saw — the committed frame with the lanes' values and the tick's own
|
|
63
|
+
* unflushed guesses over it (#3665). A staging already on the target (a
|
|
64
|
+
* landing adopted this flush) is set aside for the setter's duration: the
|
|
65
|
+
* guesses go over it, it stays the truth beneath. */ function optimisticDraft(e) {
|
|
66
|
+
if (e.pb !== null) optStaged.set(e, e.pb);
|
|
67
|
+
return cloneRaw(optimisticView(e, writerBacking(e), laneValueOf, true), e);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function notifyOptimisticWrites(e, n) {
|
|
71
|
+
// The view the user saw: the committed frame (a staging adopted eagerly
|
|
72
|
+
// is not it) with the lanes' values and the tick's own guesses over it.
|
|
73
|
+
const t = writerBacking(e);
|
|
74
|
+
const i = optimisticView(e, t, laneValueOf, true);
|
|
75
|
+
const r = Array.isArray(n);
|
|
76
|
+
// A chained target's nodes are links (§7b): their committed value is
|
|
77
|
+
// never served and never learns the inner store's commits — yet a guess
|
|
78
|
+
// is judged against it, and reverts to it (#3672). Hand the node the
|
|
79
|
+
// inner store's truth for its key before guessing over it.
|
|
80
|
+
const o = e.ch ? e.v : null;
|
|
81
|
+
const guess = (e, n, i, r) => {
|
|
82
|
+
if (o !== null) e.pe = i ? n in t : unwrapValue(t[n]);
|
|
83
|
+
// By value: a function leaf is a value, not an updater (#3017).
|
|
84
|
+
optimisticWrite(e, () => r);
|
|
85
|
+
};
|
|
86
|
+
let s = false;
|
|
87
|
+
for (const t of Reflect.ownKeys(n)) {
|
|
88
|
+
if (r && t === "length" || t === $OWNER) continue;
|
|
89
|
+
// A chained draft holds the inner store's raws; a raw is the inner slot it
|
|
90
|
+
// resolves to (as a read of it serves) — the row a held write staged is
|
|
91
|
+
// the same row, not a guess over the slot (#3796).
|
|
92
|
+
const a = n[t];
|
|
93
|
+
const f = unwrapValue(o && a ? resolveChainedRaw(e, t, a) : a);
|
|
94
|
+
if (!(t in i)) {
|
|
95
|
+
guess(getNode(e, t), t, false, f);
|
|
96
|
+
guess(getHasNode(e, t), t, true, true);
|
|
97
|
+
s = true;
|
|
98
|
+
} else {
|
|
99
|
+
const n = i[t];
|
|
100
|
+
const a = unwrapValue(o && n ? resolveChainedRaw(e, t, n) : n);
|
|
101
|
+
if (!isEqual(a, f) && !targetsEqual(a, f)) {
|
|
102
|
+
guess(getNode(e, t), t, false, f);
|
|
103
|
+
if (r) s = true;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
for (const t of Reflect.ownKeys(i)) {
|
|
108
|
+
if (r && t === "length" || t === $OWNER) continue;
|
|
109
|
+
if (t in n) continue;
|
|
110
|
+
guess(getNode(e, t), t, false, undefined);
|
|
111
|
+
guess(getHasNode(e, t), t, true, false);
|
|
112
|
+
s = true;
|
|
113
|
+
}
|
|
114
|
+
if (r && i.length !== n.length) {
|
|
115
|
+
guess(getNode(e, "length"), "length", false, n.length);
|
|
116
|
+
s = true;
|
|
117
|
+
}
|
|
118
|
+
if (s) {
|
|
119
|
+
const o = r ? n.map(unwrapValue) : shallowKeys(n);
|
|
120
|
+
// The rows the setter removed from the view it saw, by key: a later
|
|
121
|
+
// re-base over another action's truth must not bring them back.
|
|
122
|
+
let s = null;
|
|
123
|
+
const a = e.fam.key;
|
|
124
|
+
if (r && a !== null && a !== undefined) {
|
|
125
|
+
const e = new Set;
|
|
126
|
+
for (let n = 0; n < o.length; n++) {
|
|
127
|
+
const t = isWrappable(o[n]) ? a(o[n]) : undefined;
|
|
128
|
+
if (t !== undefined) e.add(t);
|
|
129
|
+
}
|
|
130
|
+
for (let n = 0; n < i.length; n++) {
|
|
131
|
+
const t = unwrapValue(i[n]);
|
|
132
|
+
const r = isWrappable(t) ? a(t) : undefined;
|
|
133
|
+
if (r !== undefined && !e.has(r)) (s ??= new Set).add(r);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
optimisticWrite(getContainerNode(e), new LaneView(o, t, s));
|
|
137
|
+
}
|
|
138
|
+
if (e.dk !== null) optimisticWrite(e.dk, {});
|
|
139
|
+
markOverlaid(e);
|
|
140
|
+
const a = optStaged.get(e);
|
|
141
|
+
if (a === undefined) return null;
|
|
142
|
+
optStaged.delete(e);
|
|
143
|
+
return a;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/** The container comparator's lane arm (store.ts `containerEquals`): an
|
|
147
|
+
* arrangement guess (`LaneView`) against a landing or another arrangement,
|
|
148
|
+
* by row identity — by key when the family has one. */ function arrangement(e, n, t) {
|
|
149
|
+
const i = n instanceof LaneView;
|
|
150
|
+
const r = t instanceof LaneView;
|
|
151
|
+
if (!i && !r) return false;
|
|
152
|
+
return arrangementEqual(i ? n.rows : n, r ? t.rows : t, e.fam?.key ?? null);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function rowSame(e, n, t) {
|
|
156
|
+
if (isEqual(e, n) || targetsEqual(e, n)) return true;
|
|
157
|
+
if (t === null || !isWrappable(e) || !isWrappable(n)) return false;
|
|
158
|
+
const i = t(unwrapValue(e));
|
|
159
|
+
const r = t(unwrapValue(n));
|
|
160
|
+
return i !== undefined && sameKey(i, r);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function arrangementEqual(e, n, t) {
|
|
164
|
+
if (Array.isArray(e) !== Array.isArray(n)) return false;
|
|
165
|
+
if (Array.isArray(e)) {
|
|
166
|
+
if (e.length !== n.length) return false;
|
|
167
|
+
for (let i = 0; i < e.length; i++) if (!rowSame(e[i], n[i], t)) return false;
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
const i = Reflect.ownKeys(e).filter(e => e !== $OWNER);
|
|
171
|
+
const r = Reflect.ownKeys(n).filter(e => e !== $OWNER);
|
|
172
|
+
if (i.length !== r.length) return false;
|
|
173
|
+
for (const e of i) if (!(e in n)) return false;
|
|
174
|
+
return true;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/** Write `incoming` into the draft `draft` (a store proxy inside a user's
|
|
178
|
+
* setter): arrays match rows by key (position when unkeyed) and recurse into
|
|
179
|
+
* the matched row's draft; objects recurse into a wrappable pair, assign
|
|
180
|
+
* otherwise; keys `incoming` lacks are deleted. */ function reconcileDraft(e, n, t) {
|
|
181
|
+
if (Array.isArray(n)) {
|
|
182
|
+
const i = e.length;
|
|
183
|
+
const r = new Array(i);
|
|
184
|
+
for (let n = 0; n < i; n++) r[n] = e[n];
|
|
185
|
+
let o = null;
|
|
186
|
+
if (t !== null) {
|
|
187
|
+
o = new Map;
|
|
188
|
+
for (let e = 0; e < i; e++) {
|
|
189
|
+
const n = unwrapValue(r[e]);
|
|
190
|
+
if (!isWrappable(n)) continue;
|
|
191
|
+
const i = t(n);
|
|
192
|
+
if (i !== undefined && !o.has(i)) o.set(i, r[e]);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
for (let s = 0; s < n.length; s++) {
|
|
196
|
+
const a = n[s];
|
|
197
|
+
let f;
|
|
198
|
+
if (isWrappable(a)) {
|
|
199
|
+
if (o !== null) {
|
|
200
|
+
const e = t(a);
|
|
201
|
+
if (e !== undefined) f = o.get(e);
|
|
202
|
+
} else if (s < i && isWrappable(unwrapValue(r[s]))) f = r[s];
|
|
203
|
+
}
|
|
204
|
+
if (f !== undefined) {
|
|
205
|
+
if (unwrapValue(f) !== a) reconcileDraft(f, a, t);
|
|
206
|
+
if (e[s] !== f) e[s] = f;
|
|
207
|
+
} else if (unwrapValue(e[s]) !== a) e[s] = a;
|
|
208
|
+
}
|
|
209
|
+
if (e.length !== n.length) e.length = n.length;
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
for (const i of Object.keys(n)) {
|
|
213
|
+
const r = n[i];
|
|
214
|
+
const o = e[i];
|
|
215
|
+
const s = unwrapValue(o);
|
|
216
|
+
if (isWrappable(r) && isWrappable(s) && Array.isArray(r) === Array.isArray(s) && (t === null || Array.isArray(r) || sameKey(t(r), t(s)))) {
|
|
217
|
+
if (s !== r) reconcileDraft(o, r, t);
|
|
218
|
+
} else if (s !== r) e[i] = r;
|
|
219
|
+
}
|
|
220
|
+
for (const t of Object.keys(e)) if (!(t in n)) delete e[t];
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/** Q-D (plan sec. 39): an OLDER question's truth landed beneath an arrangement
|
|
224
|
+
* guess (`laneWrite` held it — another action's landing is not this guess's
|
|
225
|
+
* answer). The guess is re-based over it: order from the guess, rows from
|
|
226
|
+
* the truth by key (a guessed row the truth has is the truth's object — the
|
|
227
|
+
* row target adopted it, its proxy survives), guessed rows the truth lacks
|
|
228
|
+
* kept (the guess's own landing judges them), truth rows the guess lacks
|
|
229
|
+
* appended. The composed arrangement becomes the lane's value on every
|
|
230
|
+
* index whose row the committed backing does not already show — compared
|
|
231
|
+
* BY KEY, never by raw identity: the same key's new object is the same row
|
|
232
|
+
* (its target adopted it) and the slot stays the committed backing's — (a
|
|
233
|
+
* node is born for it as the lane's derivation), on `length` only when the
|
|
234
|
+
* committed length differs, and as the `LaneView`'s base for structural
|
|
235
|
+
* reads. Unkeyed families compose
|
|
236
|
+
* positionally — the guess stands as written (the documented residue). */ GlobalQueue.In = (e, n) => {
|
|
237
|
+
const t = e.yt;
|
|
238
|
+
if (t === undefined || e.bt !== $TRACK) return;
|
|
239
|
+
const i = e.m.Z;
|
|
240
|
+
if (!(i instanceof LaneView)) return;
|
|
241
|
+
if (!Array.isArray(n) || !Array.isArray(i.rows)) {
|
|
242
|
+
i.base = n;
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
const r = t.fam?.key ?? null;
|
|
246
|
+
if (r === null) return;
|
|
247
|
+
const o = new Map;
|
|
248
|
+
for (let e = 0; e < n.length; e++) {
|
|
249
|
+
const t = n[e];
|
|
250
|
+
const i = isWrappable(t) ? r(t) : undefined;
|
|
251
|
+
if (i !== undefined && !o.has(i)) o.set(i, t);
|
|
252
|
+
}
|
|
253
|
+
const s = new Set;
|
|
254
|
+
const a = [];
|
|
255
|
+
const f = i.rows;
|
|
256
|
+
for (let e = 0; e < f.length; e++) {
|
|
257
|
+
const n = f[e];
|
|
258
|
+
const t = isWrappable(n) ? r(n) : undefined;
|
|
259
|
+
const i = t !== undefined ? o.get(t) : undefined;
|
|
260
|
+
if (i !== undefined) {
|
|
261
|
+
a.push(i);
|
|
262
|
+
s.add(t);
|
|
263
|
+
} else a.push(n);
|
|
264
|
+
}
|
|
265
|
+
const l = i.removed;
|
|
266
|
+
for (let e = 0; e < n.length; e++) {
|
|
267
|
+
const t = n[e];
|
|
268
|
+
const i = isWrappable(t) ? r(t) : undefined;
|
|
269
|
+
if (i !== undefined && !s.has(i) && (l === null || !l.has(i))) a.push(t);
|
|
270
|
+
}
|
|
271
|
+
i.rows = a;
|
|
272
|
+
i.base = a;
|
|
273
|
+
const u = txOf(e);
|
|
274
|
+
const c = committed(t);
|
|
275
|
+
const d = t.n;
|
|
276
|
+
for (let e = 0; e < a.length; e++) {
|
|
277
|
+
const n = d?.[e];
|
|
278
|
+
// A slot the lane does not own shows the committed row: it becomes the
|
|
279
|
+
// lane's only where the composed row is another row (by key — the same
|
|
280
|
+
// key's new object is the same row, its target adopted it).
|
|
281
|
+
if (n === undefined) {
|
|
282
|
+
if (!sameRow(c[e], a[e], r)) laneSet(getNode(t, e), a[e], u);
|
|
283
|
+
} else if (!sameRow(n.u & CONFIG_OVERRIDE ? n.m.Z : c[e], a[e], r)) laneSet(n, a[e], u);
|
|
284
|
+
}
|
|
285
|
+
if (d !== null) {
|
|
286
|
+
for (let e = a.length; ;e++) {
|
|
287
|
+
const n = d[e];
|
|
288
|
+
if (n === undefined) break;
|
|
289
|
+
laneSet(n, undefined, u);
|
|
290
|
+
}
|
|
291
|
+
const e = d.length;
|
|
292
|
+
if (e !== undefined && (e.u & CONFIG_OVERRIDE || c.length !== a.length)) laneSet(e, a.length, u);
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
function sameRow(e, n, t) {
|
|
297
|
+
if (e === n) return true;
|
|
298
|
+
if (!isWrappable(e) || !isWrappable(n)) return false;
|
|
299
|
+
const i = t(unwrapValue(e));
|
|
300
|
+
return i !== undefined && sameKey(i, t(unwrapValue(n)));
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/** A composed value becomes the lane's on `node`: a guess re-based, or a
|
|
304
|
+
* node that was not the lane's becomes its derivation (its committed value
|
|
305
|
+
* untouched beneath; the lane's end commits the latest). */ function laneSet(e, n, t) {
|
|
306
|
+
const i = ext(e);
|
|
307
|
+
if (!(e.u & CONFIG_OVERRIDE)) {
|
|
308
|
+
e.u |= CONFIG_OVERRIDE;
|
|
309
|
+
list(e, t);
|
|
310
|
+
} else if (i.Z === n) return;
|
|
311
|
+
i.Z = n;
|
|
312
|
+
if (e.t !== null) {
|
|
313
|
+
insertSubs(e);
|
|
314
|
+
laneDirty(e, t);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
installOptHooks({
|
|
319
|
+
draft: optimisticDraft,
|
|
320
|
+
writes: notifyOptimisticWrites,
|
|
321
|
+
arrangement: arrangement,
|
|
322
|
+
reconcile: reconcileDraft,
|
|
323
|
+
view: (e, n, t = false) => t ? optimisticView(e, n, laneValueOf, true) : optimisticView(e, n),
|
|
324
|
+
has: optimisticHas,
|
|
325
|
+
descriptor: optimisticOwnDescriptor,
|
|
326
|
+
sweep: sweepOverlaid
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
function shallowKeys(e) {
|
|
330
|
+
const n = {};
|
|
331
|
+
for (const t of Reflect.ownKeys(e)) if (t !== $OWNER) n[t] = unwrapValue(e[t]);
|
|
332
|
+
return n;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/** Families with a target carrying a lane value — swept at the flush's
|
|
336
|
+
* commit (`sweepOverlaid`): a target none of whose nodes is a lane's any
|
|
337
|
+
* more leaves its family's `overlaid`. (Not on the read path: a guess is
|
|
338
|
+
* pending between the setter and the seam, and a read in between must not
|
|
339
|
+
* take the target for clean.) */ const overlaidFamilies = new Set;
|
|
340
|
+
|
|
341
|
+
function markOverlaid(e) {
|
|
342
|
+
const n = e.fam;
|
|
343
|
+
(n.overlaid ??= new Set).add(e);
|
|
344
|
+
overlaidFamilies.add(n);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
function sweepOverlaid() {
|
|
348
|
+
if (overlaidFamilies.size === 0) return;
|
|
349
|
+
for (const e of overlaidFamilies) {
|
|
350
|
+
const n = e.overlaid;
|
|
351
|
+
for (const e of n) if (!carriesLane(e)) {
|
|
352
|
+
n.delete(e);
|
|
353
|
+
if (e.ch) rebaseChained(e);
|
|
354
|
+
// The container shows its backing again (a shown arrangement guess
|
|
355
|
+
// that ended without a landing left its `LaneView` as the value).
|
|
356
|
+
const t = e.k;
|
|
357
|
+
if (t !== null && t.pe instanceof LaneView) t.pe = t.pe.base;
|
|
358
|
+
}
|
|
359
|
+
if (n.size === 0) overlaidFamilies.delete(e);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/** A chained view's lanes ended: its nodes are links (§7b) whose committed
|
|
364
|
+
* value is the inner store's at the guess, not now — the inner may have
|
|
365
|
+
* moved underneath the guess (the base committed while the view showed
|
|
366
|
+
* its arrangement, #3672/F1). Re-base each node on the inner's truth and
|
|
367
|
+
* re-derive the readers whose shown value it is not. */ function rebaseChained(e) {
|
|
368
|
+
const n = e.v;
|
|
369
|
+
let t = false;
|
|
370
|
+
const i = e.n;
|
|
371
|
+
if (i !== null) for (const e of Reflect.ownKeys(i)) {
|
|
372
|
+
const r = i[e];
|
|
373
|
+
const o = untrack(() => unwrapValue(n[e]));
|
|
374
|
+
if (r.tn && r.tn(r.pe, o)) continue;
|
|
375
|
+
r.pe = o;
|
|
376
|
+
// (The lane's end notified it this epoch when the shown value and the
|
|
377
|
+
// covered one differed — its readers re-derive already.)
|
|
378
|
+
if (r.t !== null && r.Pt !== notifyEpoch) {
|
|
379
|
+
insertSubs(r);
|
|
380
|
+
t = true;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
const r = e.h;
|
|
384
|
+
if (r !== null) for (const e of Reflect.ownKeys(r)) {
|
|
385
|
+
const i = r[e];
|
|
386
|
+
const o = untrack(() => e in n);
|
|
387
|
+
if (i.pe === o) continue;
|
|
388
|
+
i.pe = o;
|
|
389
|
+
if (i.t !== null && i.Pt !== notifyEpoch) {
|
|
390
|
+
insertSubs(i);
|
|
391
|
+
t = true;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
// The arrangement the readers saw (the shown guess) against the inner's
|
|
395
|
+
// now: a structural reader re-derives when they differ.
|
|
396
|
+
const o = e.k;
|
|
397
|
+
if (o !== null && o.t !== null && o.pe instanceof LaneView && o.Pt !== notifyEpoch) {
|
|
398
|
+
const i = Array.isArray(n) ? untrack(() => n.map(unwrapValue)) : n;
|
|
399
|
+
if (!arrangementEqual(o.pe.rows, i, e.fam?.key ?? null)) {
|
|
400
|
+
insertSubs(o);
|
|
401
|
+
t = true;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
if (t) schedule();
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
function carriesLane(e) {
|
|
408
|
+
if (e.k !== null && e.k.u & CONFIG_OVERRIDE) return true;
|
|
409
|
+
if (e.dk !== null && e.dk.u & CONFIG_OVERRIDE) return true;
|
|
410
|
+
const n = e.n;
|
|
411
|
+
if (n !== null) for (const e of Reflect.ownKeys(n)) if (n[e].u & CONFIG_OVERRIDE) return true;
|
|
412
|
+
const t = e.h;
|
|
413
|
+
if (t !== null) for (const e of Reflect.ownKeys(t)) if (t[e].u & CONFIG_OVERRIDE) return true;
|
|
414
|
+
return false;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
function overlaid(e) {
|
|
418
|
+
const n = e.fam;
|
|
419
|
+
return n !== null && n.opt === true && n.overlaid !== undefined && n.overlaid.has(e);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/** What a lane node shows an untracked reader here: core's rule (`read`
|
|
423
|
+
* without a link — the lane's world inside its own pass, the screen
|
|
424
|
+
* outside, a verdict window's answer under one). */ const shown = e => untrack(() => read(e));
|
|
425
|
+
|
|
426
|
+
/** An untracked `key in store` on an optimistic family: the presence guess
|
|
427
|
+
* (what its lane shows) when the key carries one; `undefined` when not —
|
|
428
|
+
* the backing answers. */ function optimisticHas(e, n) {
|
|
429
|
+
if (!overlaid(e)) return undefined;
|
|
430
|
+
const t = e.h?.[n];
|
|
431
|
+
if (t !== undefined && t.u & CONFIG_OVERRIDE) return !!shown(t);
|
|
432
|
+
const i = e.n?.[n];
|
|
433
|
+
if (i !== undefined && i.u & CONFIG_OVERRIDE) return shown(i) !== undefined;
|
|
434
|
+
return undefined;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
/** A descriptor read of a guessed key: synthesized from the lane's value
|
|
438
|
+
* (`null`: the guess removed the key; `undefined`: no guess — the backing
|
|
439
|
+
* describes it). */ function optimisticOwnDescriptor(e, n) {
|
|
440
|
+
const t = optimisticHas(e, n);
|
|
441
|
+
if (t === undefined) return undefined;
|
|
442
|
+
if (!t) return null;
|
|
443
|
+
const i = e.n?.[n];
|
|
444
|
+
const r = i !== undefined && i.u & CONFIG_OVERRIDE ? shown(i) : e.v[n];
|
|
445
|
+
// An array's `length` is reported as the array has it (non-configurable).
|
|
446
|
+
if (n === "length" && Array.isArray(e.v)) return {
|
|
447
|
+
value: r,
|
|
448
|
+
writable: true,
|
|
449
|
+
enumerable: false,
|
|
450
|
+
configurable: false
|
|
451
|
+
};
|
|
452
|
+
return {
|
|
453
|
+
value: r,
|
|
454
|
+
writable: true,
|
|
455
|
+
enumerable: true,
|
|
456
|
+
configurable: true
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
/** The truth `src` with the target's lane values over it: each overlaid
|
|
461
|
+
* leaf's value (`pick`: what the lane shows, or — for `latest` — the lane's
|
|
462
|
+
* latest), each presence guess as a key added or removed, the array
|
|
463
|
+
* length. Returns `src` itself when nothing is overlaid. */ function optimisticView(e, n, t = shown,
|
|
464
|
+
// The writer's view: the unflushed guesses too (on nodes that are no
|
|
465
|
+
// lane's yet) — what the next write composes on (#3665).
|
|
466
|
+
i = false) {
|
|
467
|
+
if (!i && !overlaid(e)) return n;
|
|
468
|
+
let r = null;
|
|
469
|
+
const ensure = () => r ??= Array.isArray(n) ? [ ...n ] : {
|
|
470
|
+
...n
|
|
471
|
+
};
|
|
472
|
+
const o = e.n;
|
|
473
|
+
if (o !== null) {
|
|
474
|
+
for (const e of Reflect.ownKeys(o)) {
|
|
475
|
+
const r = o[e];
|
|
476
|
+
let s;
|
|
477
|
+
if (r.u & CONFIG_OVERRIDE) s = t(r); else if (!i || (s = pendingGuessOf(r)) === NOT_PENDING) continue;
|
|
478
|
+
if (e === "length" && Array.isArray(n)) {
|
|
479
|
+
if (n.length !== s) ensure().length = s;
|
|
480
|
+
} else if (!isEqual(n[e], s) || !hasOwn.call(n, e)) {
|
|
481
|
+
ensure()[e] = s;
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
const s = e.h;
|
|
486
|
+
if (s !== null) {
|
|
487
|
+
for (const e of Reflect.ownKeys(s)) {
|
|
488
|
+
const o = s[e];
|
|
489
|
+
let a;
|
|
490
|
+
if (o.u & CONFIG_OVERRIDE) a = t(o); else if (!i || (a = pendingGuessOf(o)) === NOT_PENDING) continue;
|
|
491
|
+
const f = !!a;
|
|
492
|
+
const l = r ?? n;
|
|
493
|
+
if (!f && e in l) delete ensure()[e];
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
return r ?? n;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
function createOptimisticStore(e, n, t) {
|
|
500
|
+
const i = typeof e === "function";
|
|
501
|
+
const r = i ? t : n;
|
|
502
|
+
const o = i ? n : e;
|
|
503
|
+
const s = r?.key === undefined ? "id" : r.key;
|
|
504
|
+
const a = {
|
|
505
|
+
map: new WeakMap,
|
|
506
|
+
node: null,
|
|
507
|
+
live: new Set,
|
|
508
|
+
shallow: !!r?.shallow,
|
|
509
|
+
opt: true,
|
|
510
|
+
key: typeof s === "function" ? s : s === null ? null : e => isWrappable(e) ? e[s] : undefined
|
|
511
|
+
};
|
|
512
|
+
const f = wrap(o, null, null, a);
|
|
513
|
+
nameStore(f, r?.name);
|
|
514
|
+
if (a.shallow) {
|
|
515
|
+
f[$TARGET].s = true;
|
|
516
|
+
markRawIngest(o);
|
|
517
|
+
}
|
|
518
|
+
if (i) {
|
|
519
|
+
const n = e;
|
|
520
|
+
let t;
|
|
521
|
+
if (r?.seedLoadingValue) t = {
|
|
522
|
+
loadingValue: undefined
|
|
523
|
+
};
|
|
524
|
+
if (r?.name) t = {
|
|
525
|
+
...t,
|
|
526
|
+
name: r.name
|
|
527
|
+
};
|
|
528
|
+
const i = computed(() => {
|
|
529
|
+
if (!a.node) a.node = getOwner();
|
|
530
|
+
runProjectionComputed(f, n, s);
|
|
531
|
+
}, t);
|
|
532
|
+
i.u &= ~CONFIG_AUTO_DISPOSE;
|
|
533
|
+
a.node = i;
|
|
534
|
+
}
|
|
535
|
+
return [ f, e => storeSetter(f, e) ];
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
export { createOptimisticStore, notifyOptimisticWrites, optimisticHas, optimisticOwnDescriptor, optimisticView, sweepOverlaid };
|