@solidjs/signals 2.0.0-rc.0 → 2.0.0-rc.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/dev-shared.js +7138 -0
- package/dist/dev.attribution.js +3307 -0
- package/dist/dev.js +8076 -6692
- package/dist/observe/affects.js +129 -0
- package/dist/observe/attribution.js +7 -0
- package/dist/observe/boundaries.js +793 -0
- package/dist/observe/core/action.js +177 -0
- package/dist/observe/core/async.js +849 -0
- package/dist/observe/core/attribution-costs.js +66 -0
- package/dist/observe/core/attribution-feedback.js +280 -0
- package/dist/observe/core/attribution-hooks.js +83 -0
- package/dist/observe/core/attribution-queries.js +43 -0
- package/dist/observe/core/attribution.js +2904 -0
- package/dist/observe/core/constants.js +283 -0
- package/dist/{types-cjs/core/context.d.cts → observe/core/context.js} +37 -12
- package/dist/observe/core/core.js +1999 -0
- package/dist/observe/core/dev.js +343 -0
- package/dist/observe/core/effect.js +200 -0
- package/dist/observe/core/error-hooks.js +71 -0
- package/dist/observe/core/error.js +80 -0
- package/dist/observe/core/external.js +98 -0
- package/dist/observe/core/graph.js +155 -0
- package/dist/observe/core/heap.js +147 -0
- package/dist/observe/core/invariants.js +45 -0
- package/dist/observe/core/lanes.js +205 -0
- package/dist/observe/core/optimistic.js +627 -0
- package/dist/observe/core/owner.js +353 -0
- package/dist/observe/core/scheduler.js +1547 -0
- package/dist/observe/core/verdict.js +674 -0
- package/dist/observe/index.js +59 -0
- package/dist/observe/map.js +484 -0
- package/dist/observe/signals.js +731 -0
- package/dist/observe/store/index.js +44 -0
- package/dist/observe/store/next/optimistic.js +717 -0
- package/dist/observe/store/next/projection.js +266 -0
- package/dist/observe/store/next/reconcile.js +375 -0
- package/dist/observe/store/next/store.js +2480 -0
- package/dist/observe/store/next/target.js +51 -0
- package/dist/observe/store/store.js +331 -0
- package/dist/observe/store/storePath.js +103 -0
- package/dist/observe/store/utils.js +1070 -0
- package/dist/prod/affects.js +10 -9
- package/dist/prod/attribution.js +45 -0
- package/dist/prod/boundaries.js +388 -178
- package/dist/prod/core/action.js +65 -37
- package/dist/prod/core/async.js +477 -208
- package/dist/prod/core/attribution-hooks.js +3 -0
- package/dist/prod/core/constants.js +186 -1
- package/dist/prod/core/context.js +10 -16
- package/dist/prod/core/core.js +1556 -415
- package/dist/prod/core/dev.js +18 -1
- package/dist/prod/core/effect.js +119 -79
- package/dist/prod/core/error-hooks.js +71 -0
- package/dist/prod/core/error.js +13 -1
- package/dist/prod/core/external.js +4 -4
- package/dist/prod/core/graph.js +105 -54
- package/dist/prod/core/heap.js +72 -65
- package/dist/prod/core/invariants.js +3 -2
- package/dist/prod/core/lanes.js +117 -52
- package/dist/prod/core/optimistic.js +474 -103
- package/dist/prod/core/owner.js +131 -84
- package/dist/prod/core/scheduler.js +1013 -248
- package/dist/prod/core/verdict.js +418 -113
- package/dist/prod/index.js +25 -13
- package/dist/prod/map.js +314 -151
- package/dist/prod/signals.js +382 -32
- package/dist/prod/store/index.js +38 -0
- package/dist/prod/store/next/optimistic.js +710 -0
- package/dist/prod/store/next/projection.js +257 -0
- package/dist/prod/store/next/reconcile.js +373 -0
- package/dist/prod/store/next/store.js +2356 -0
- package/dist/prod/store/next/target.js +51 -0
- package/dist/prod/store/store.js +129 -881
- package/dist/prod/store/utils.js +982 -242
- package/dist/types/attribution.d.ts +19 -0
- package/dist/types/attribution.prod.d.ts +22 -0
- package/dist/types/boundaries.d.ts +78 -5
- package/dist/types/core/action.d.ts +12 -5
- package/dist/types/core/async.d.ts +3 -1
- package/dist/types/core/attribution-costs.d.ts +35 -0
- package/dist/types/core/attribution-feedback.d.ts +133 -0
- package/dist/types/core/attribution-hooks.d.ts +304 -0
- package/dist/types/core/attribution-queries.d.ts +24 -0
- package/dist/types/core/attribution.d.ts +892 -0
- package/dist/types/core/constants.d.ts +179 -0
- package/dist/types/core/core.d.ts +305 -23
- package/dist/types/core/dev.d.ts +421 -8
- package/dist/types/core/effect.d.ts +8 -1
- package/dist/types/core/error-hooks.d.ts +71 -0
- package/dist/types/core/error.d.ts +9 -0
- package/dist/types/core/graph.d.ts +23 -0
- package/dist/types/core/heap.d.ts +5 -3
- package/dist/types/core/index.d.ts +6 -3
- package/dist/types/core/invariants.d.ts +5 -1
- package/dist/types/core/lanes.d.ts +51 -19
- package/dist/types/core/owner.d.ts +15 -3
- package/dist/types/core/scheduler.d.ts +252 -3
- package/dist/types/core/types.d.ts +124 -41
- package/dist/types/index.d.ts +18 -5
- package/dist/types/map.d.ts +2 -0
- package/dist/types/signals.d.ts +164 -13
- package/dist/types/store/index.d.ts +16 -5
- package/dist/types/store/next/optimistic.d.ts +25 -0
- package/dist/types/store/next/projection.d.ts +27 -0
- package/dist/types/store/next/reconcile.d.ts +10 -0
- package/dist/types/store/next/store.d.ts +143 -0
- package/dist/types/store/next/target.d.ts +196 -0
- package/dist/types/store/store.d.ts +46 -112
- package/dist/types/store/utils.d.ts +188 -40
- package/package.json +32 -26
- package/dist/node.cjs +0 -7938
- package/dist/prod/store/optimistic.js +0 -217
- package/dist/prod/store/projection.js +0 -231
- package/dist/prod/store/reconcile.js +0 -707
- package/dist/types/store/optimistic.d.ts +0 -45
- package/dist/types/store/projection.d.ts +0 -70
- package/dist/types/store/reconcile.d.ts +0 -46
- package/dist/types-cjs/affects.d.cts +0 -47
- package/dist/types-cjs/boundaries.d.cts +0 -175
- package/dist/types-cjs/core/action.d.cts +0 -64
- package/dist/types-cjs/core/async.d.cts +0 -21
- package/dist/types-cjs/core/constants.d.cts +0 -71
- package/dist/types-cjs/core/core.d.cts +0 -148
- package/dist/types-cjs/core/dev.d.cts +0 -64
- package/dist/types-cjs/core/effect.d.cts +0 -30
- package/dist/types-cjs/core/error.d.cts +0 -47
- package/dist/types-cjs/core/external.d.cts +0 -15
- package/dist/types-cjs/core/graph.d.cts +0 -5
- package/dist/types-cjs/core/heap.d.cts +0 -22
- package/dist/types-cjs/core/index.d.cts +0 -13
- package/dist/types-cjs/core/invariants.d.cts +0 -59
- package/dist/types-cjs/core/lanes.d.cts +0 -56
- package/dist/types-cjs/core/optimistic.d.cts +0 -6
- package/dist/types-cjs/core/owner.d.cts +0 -124
- package/dist/types-cjs/core/scheduler.d.cts +0 -170
- package/dist/types-cjs/core/types.d.cts +0 -148
- package/dist/types-cjs/core/verdict.d.cts +0 -2
- package/dist/types-cjs/index.d.cts +0 -10
- package/dist/types-cjs/map.d.cts +0 -69
- package/dist/types-cjs/package.json +0 -3
- package/dist/types-cjs/signals.d.cts +0 -605
- package/dist/types-cjs/store/index.d.cts +0 -9
- package/dist/types-cjs/store/optimistic.d.cts +0 -45
- package/dist/types-cjs/store/projection.d.cts +0 -70
- package/dist/types-cjs/store/reconcile.d.cts +0 -46
- package/dist/types-cjs/store/store.d.cts +0 -213
- package/dist/types-cjs/store/storePath.d.cts +0 -58
- package/dist/types-cjs/store/utils.d.cts +0 -114
package/dist/prod/store/store.js
CHANGED
|
@@ -1,14 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
import "../core/core.js";
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
import { DEV } from "../core/dev.js";
|
|
6
|
-
|
|
7
|
-
import { NotReadyError } from "../core/error.js";
|
|
8
|
-
|
|
9
|
-
import { getObserver } from "../core/owner.js";
|
|
10
|
-
|
|
11
|
-
import { GlobalQueue, registerTransientStoreNode, projectionWriteActive, activeTransition, globalQueue } from "../core/scheduler.js";
|
|
3
|
+
import { GlobalQueue } from "../core/scheduler.js";
|
|
12
4
|
|
|
13
5
|
import "../core/invariants.js";
|
|
14
6
|
|
|
@@ -16,85 +8,31 @@ import "../core/verdict.js";
|
|
|
16
8
|
|
|
17
9
|
import "../core/effect.js";
|
|
18
10
|
|
|
19
|
-
import {
|
|
11
|
+
import { $OWNER, lookupTarget as lookupTarget$1 } from "./next/target.js";
|
|
20
12
|
|
|
21
13
|
/**
|
|
22
14
|
* Brand symbols used internally by the store proxy / projection plumbing.
|
|
23
15
|
* Cross-package wiring; not part of the user-facing API.
|
|
24
16
|
*
|
|
25
17
|
* @internal
|
|
26
|
-
*/ const $TRACK = Symbol(0), $TARGET = Symbol(0), $PROXY = Symbol(0),
|
|
27
|
-
//
|
|
18
|
+
*/ const $TRACK = Symbol(0), $TARGET = Symbol(0), $PROXY = Symbol(0),
|
|
19
|
+
// The view record behind a merge()/omit() proxy (a `MergeView` or an
|
|
20
|
+
// `OmitView`, utils.ts); a store answers `undefined` on its symbol fast
|
|
21
|
+
// path. One read classifies any `$PROXY`-marked object — store, view, or
|
|
22
|
+
// foreign — where asking `$TARGET` first and then each view kind was two
|
|
23
|
+
// to four trap hops (see `viewOf`).
|
|
24
|
+
$RECORD = Symbol(0), // Node-map slot carrying a record-level `affects()` mark: any read through
|
|
28
25
|
// the record witnesses it into the active isPending() probe.
|
|
29
26
|
$AFFECTS = Symbol(0);
|
|
30
27
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
// Every StoreNode field is initialized up front, in one fixed order, so all
|
|
36
|
-
// targets share a single hidden class. The traps and reconcile read these
|
|
37
|
-
// fields on their hottest paths; fields added lazily in varying orders made
|
|
38
|
-
// those loads megamorphic across a large store graph (dictionary-mode probes
|
|
39
|
-
// on every trap hit). Assignments elsewhere must never `delete` a field —
|
|
40
|
-
// write `undefined` instead, or the shape degrades again.
|
|
41
|
-
function initStoreFields(e) {
|
|
42
|
-
e[STORE_OVERRIDE] = undefined;
|
|
43
|
-
e[STORE_OPTIMISTIC_OVERRIDE] = undefined;
|
|
44
|
-
e[STORE_OPTIMISTIC_OWNERS] = undefined;
|
|
45
|
-
e[STORE_NODE] = undefined;
|
|
46
|
-
e[STORE_HAS] = undefined;
|
|
47
|
-
e[STORE_CUSTOM_PROTO] = undefined;
|
|
48
|
-
e[STORE_WRAP] = undefined;
|
|
49
|
-
e[STORE_LOOKUP] = undefined;
|
|
50
|
-
e[STORE_FIREWALL] = undefined;
|
|
51
|
-
e[STORE_OPTIMISTIC] = undefined;
|
|
52
|
-
e[STORE_SNAPSHOT_PROPS] = undefined;
|
|
53
|
-
e[STORE_PARENT] = undefined;
|
|
54
|
-
e[STORE_DESC] = undefined;
|
|
55
|
-
e[STORE_SHALLOW] = undefined;
|
|
56
|
-
e[$PROXY] = null;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function createStoreProxy(e, t = storeTraps, r) {
|
|
60
|
-
let n;
|
|
61
|
-
if (Array.isArray(e)) {
|
|
62
|
-
n = [];
|
|
63
|
-
n[STORE_VALUE] = e;
|
|
64
|
-
initStoreFields(n);
|
|
65
|
-
} else {
|
|
66
|
-
n = {
|
|
67
|
-
[STORE_VALUE]: e
|
|
68
|
-
};
|
|
69
|
-
initStoreFields(n);
|
|
70
|
-
const t = e?.[$TARGET]?.[STORE_VALUE] ?? e;
|
|
71
|
-
const r = Object.getPrototypeOf(t);
|
|
72
|
-
if (r !== null && r !== Object.prototype) {
|
|
73
|
-
n[STORE_CUSTOM_PROTO] = true;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
r && r(n);
|
|
77
|
-
return n[$PROXY] = new Proxy(n, t);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// The global lookup maps raw value -> StoreNode TARGET (not proxy): reconcile
|
|
81
|
-
// and the unwrap/snapshot walks resolve targets through it constantly, and a
|
|
82
|
-
// target hit is a plain field read away from its proxy while a proxy hit
|
|
83
|
-
// costs a trap to get back to the target. Per-family STORE_LOOKUP maps
|
|
84
|
-
// (projections/optimistic) still map raw -> proxy — their wrap functions own
|
|
85
|
-
// that contract — so mixed-lookup consumers resolve through lookupTarget().
|
|
86
|
-
const storeLookup = new WeakMap;
|
|
87
|
-
|
|
88
|
-
// Node records that hold at least one user (non-`$TRACK`) symbol-keyed node.
|
|
89
|
-
// Lets reconcile enumerate symbols only for records that need it (#2851).
|
|
90
|
-
const symbolKeyedRecords = new WeakSet;
|
|
28
|
+
// Structural field names of store targets (StoreNextTarget aliases these, so
|
|
29
|
+
// shared machinery — affects walks, tests — reads targets via the consts).
|
|
30
|
+
const STORE_VALUE = "v", STORE_NODE = "n", STORE_HAS = "h";
|
|
91
31
|
|
|
92
32
|
function lookupTarget(e, t) {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
return storeLookup.get(e);
|
|
33
|
+
// Family registrations (projections/optimistic) first, then the global
|
|
34
|
+
// next lookup. Proxies resolve through $TARGET directly.
|
|
35
|
+
return (t ? lookupTarget$1(e, t) : undefined) ?? lookupTarget$1(e, null);
|
|
98
36
|
}
|
|
99
37
|
|
|
100
38
|
// Values marked raw never acquire a proxy identity: wrap() serves them as-is
|
|
@@ -137,50 +75,12 @@ function markRawOne(e) {
|
|
|
137
75
|
|
|
138
76
|
function markRawIngest(e) {
|
|
139
77
|
if (Array.isArray(e)) {
|
|
140
|
-
for (let t = 0,
|
|
78
|
+
for (let t = 0, o = e.length; t < o; t++) markRawOne(e[t]);
|
|
141
79
|
} else {
|
|
142
80
|
for (const t in e) markRawOne(e[t]);
|
|
143
81
|
}
|
|
144
82
|
}
|
|
145
83
|
|
|
146
|
-
function wrap(e, t) {
|
|
147
|
-
// Raw is raw in every family: the mark must preempt family wrapping too,
|
|
148
|
-
// or a shallow projection/optimistic store would proxy its raw records.
|
|
149
|
-
if (rawValuesUsed && rawValues.has(e)) return e;
|
|
150
|
-
if (t?.[STORE_WRAP]) {
|
|
151
|
-
const r = t[STORE_WRAP](e, t);
|
|
152
|
-
const n = r[$TARGET];
|
|
153
|
-
if (n && !n[STORE_PARENT] && n !== t) n[STORE_PARENT] = t;
|
|
154
|
-
return r;
|
|
155
|
-
}
|
|
156
|
-
const r = storeLookup.get(e);
|
|
157
|
-
if (r !== undefined) return r[$PROXY];
|
|
158
|
-
let n = e[$PROXY];
|
|
159
|
-
if (!n) {
|
|
160
|
-
n = createStoreProxy(e);
|
|
161
|
-
const r = n[$TARGET];
|
|
162
|
-
storeLookup.set(e, r);
|
|
163
|
-
if (t) r[STORE_PARENT] = t;
|
|
164
|
-
}
|
|
165
|
-
return n;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// Shallow store root: the target itself is fully reactive (per-key nodes,
|
|
169
|
-
// membership, $TRACK); its values are served raw. Seed values are marked at
|
|
170
|
-
// creation; reconcile and the set trap mark on ingest.
|
|
171
|
-
function wrapShallow(e) {
|
|
172
|
-
const t = storeLookup.get(e);
|
|
173
|
-
if (t !== undefined) {
|
|
174
|
-
if (t[STORE_SHALLOW]) return t[$PROXY];
|
|
175
|
-
}
|
|
176
|
-
const r = createStoreProxy(e);
|
|
177
|
-
const n = r[$TARGET];
|
|
178
|
-
n[STORE_SHALLOW] = true;
|
|
179
|
-
storeLookup.set(e, n);
|
|
180
|
-
markRawIngest(e);
|
|
181
|
-
return r;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
84
|
const OBJECT_PROTO = Object.prototype;
|
|
185
85
|
|
|
186
86
|
// Per-prototype memo for the custom-proto branch of isWrappable: the verdict
|
|
@@ -204,16 +104,16 @@ function isWrappable(e) {
|
|
|
204
104
|
const t = Object.getPrototypeOf(e);
|
|
205
105
|
if (t === OBJECT_PROTO || t === null) return true;
|
|
206
106
|
if (Array.isArray(e)) return true;
|
|
207
|
-
let
|
|
208
|
-
if (
|
|
209
|
-
|
|
107
|
+
let o = wrappableProtos.get(t);
|
|
108
|
+
if (o === undefined) {
|
|
109
|
+
o = Object.prototype.toString.call(e) === "[object Object]" && (
|
|
210
110
|
// Dynamic Node check (kept dynamic so test/SSR overrides of
|
|
211
111
|
// `globalThis.Node` are observed at call time): shimmed DOMs implement
|
|
212
112
|
// nodes as plain user classes, which pass the tag check.
|
|
213
113
|
typeof Node === "undefined" || !(e instanceof Node));
|
|
214
|
-
wrappableProtos.set(t,
|
|
114
|
+
wrappableProtos.set(t, o);
|
|
215
115
|
}
|
|
216
|
-
return
|
|
116
|
+
return o;
|
|
217
117
|
}
|
|
218
118
|
|
|
219
119
|
let writeOverride = false;
|
|
@@ -222,33 +122,8 @@ function setWriteOverride(e) {
|
|
|
222
122
|
writeOverride = e;
|
|
223
123
|
}
|
|
224
124
|
|
|
225
|
-
function
|
|
226
|
-
return writeOverride
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
function unwrapStoreValue(e, t, r) {
|
|
230
|
-
const n = e?.[$TARGET] || lookupTarget(e, r);
|
|
231
|
-
if (!n) return e;
|
|
232
|
-
const o = n[STORE_OVERRIDE];
|
|
233
|
-
if (!o) return n[STORE_VALUE];
|
|
234
|
-
if (!t) t = new Map;
|
|
235
|
-
if (t.has(e)) return t.get(e);
|
|
236
|
-
const i = n[STORE_VALUE];
|
|
237
|
-
const O = Array.isArray(i);
|
|
238
|
-
const s = O ? [] : Object.create(Object.getPrototypeOf(i));
|
|
239
|
-
t.set(e, s);
|
|
240
|
-
r = n[STORE_LOOKUP] ?? storeLookup;
|
|
241
|
-
for (const e of getStoreKeys(i, o)) {
|
|
242
|
-
if (O && e === "length") continue;
|
|
243
|
-
const n = e in o ? o[e] : i[e];
|
|
244
|
-
if (n !== $DELETED) s[e] = unwrapStoreValue(n, t, r);
|
|
245
|
-
}
|
|
246
|
-
if (O) s.length = o.length ?? i.length;
|
|
247
|
-
return s;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
function isPrototypePollutionKey(e) {
|
|
251
|
-
return e === "__proto__" || e === "constructor" || e === "prototype";
|
|
125
|
+
function getWriteOverride() {
|
|
126
|
+
return writeOverride;
|
|
252
127
|
}
|
|
253
128
|
|
|
254
129
|
// Own enumerable keys including symbols (`Object.keys` drops symbol-keyed props). #2769
|
|
@@ -256,134 +131,45 @@ function ownEnumerableKeys(e) {
|
|
|
256
131
|
return Reflect.ownKeys(e).filter(t => Object.prototype.propertyIsEnumerable.call(e, t));
|
|
257
132
|
}
|
|
258
133
|
|
|
259
|
-
function ownEnumerableSymbols(e) {
|
|
260
|
-
const t = Object.getOwnPropertySymbols(e);
|
|
261
|
-
const r = [];
|
|
262
|
-
for (let n = 0, o = t.length; n < o; n++) {
|
|
263
|
-
const o = t[n];
|
|
264
|
-
if (Object.prototype.propertyIsEnumerable.call(e, o)) r.push(o);
|
|
265
|
-
}
|
|
266
|
-
return r;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
// Plain-object variant that keeps Object.keys() as the fast path and only pays
|
|
270
|
-
// descriptor checks for symbols. Do not use this on store proxies: splitting
|
|
271
|
-
// strings/symbols would invoke their ownKeys trap twice.
|
|
272
|
-
function ownEnumerableKeysPlain(e) {
|
|
273
|
-
return Object.keys(e).concat(ownEnumerableSymbols(e));
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
/**
|
|
277
|
-
* Single chokepoint for the store's layered value resolution: returns the
|
|
278
|
-
* override layer (optimistic first, then regular) that shadows `property`, or
|
|
279
|
-
* `undefined` when the base `STORE_VALUE` is authoritative. Every trap must
|
|
280
|
-
* resolve through this — hand-inlining the layer order is how the optimistic
|
|
281
|
-
* layer gets missed (#2850).
|
|
282
|
-
*/ function getOverlayLayer(e, t) {
|
|
283
|
-
const r = e[STORE_OPTIMISTIC_OVERRIDE];
|
|
284
|
-
if (r && t in r) return r;
|
|
285
|
-
const n = e[STORE_OVERRIDE];
|
|
286
|
-
if (n && t in n) return n;
|
|
287
|
-
return undefined;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
/**
|
|
291
|
-
* The value a store leaf's backing signal currently shows to readers: active
|
|
292
|
-
* override, else held pending value, else committed value.
|
|
293
|
-
*/ function visibleNodeValue(e) {
|
|
294
|
-
return e._e !== undefined && e._e !== NOT_PENDING ? unwrapOverride(e._e) : e.De !== NOT_PENDING ? e.De : e.Ue;
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
function hasOwnStoreProperty(e, t) {
|
|
298
|
-
// Override layers are null-prototype objects, so `in` is an own check.
|
|
299
|
-
const r = getOverlayLayer(e, t);
|
|
300
|
-
if (r) return r[t] !== $DELETED;
|
|
301
|
-
return Object.prototype.hasOwnProperty.call(unwrapStoreValue(e[STORE_VALUE]), t);
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
function hasInheritedAccessor(e, t) {
|
|
305
|
-
let r = Object.getPrototypeOf(e);
|
|
306
|
-
while (r && r !== Object.prototype) {
|
|
307
|
-
const e = Reflect.getOwnPropertyDescriptor(r, t);
|
|
308
|
-
if (e) return !!e.get;
|
|
309
|
-
r = Object.getPrototypeOf(r);
|
|
310
|
-
}
|
|
311
|
-
return false;
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
function getNodes(e, t) {
|
|
315
|
-
let r = e[t];
|
|
316
|
-
if (!r) e[t] = r = Object.create(null);
|
|
317
|
-
return r;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
function getNode(e, t, r, n, o = isEqual, i) {
|
|
321
|
-
if (t[r]) return t[r];
|
|
322
|
-
const O = signal(n, {
|
|
323
|
-
equals: o,
|
|
324
|
-
unobserved() {
|
|
325
|
-
if (t[r] === O) {
|
|
326
|
-
delete t[r];
|
|
327
|
-
// Drop the symbol-record mark once the last user symbol node is
|
|
328
|
-
// gone, so reconcile's fast path stops probing a now string-only
|
|
329
|
-
// record. Runs only on symbol-node cleanup (cold), never on reconcile.
|
|
330
|
-
if (typeof r === "symbol" && r !== $TRACK && r !== $AFFECTS && symbolKeyedRecords.has(t)) {
|
|
331
|
-
const e = Object.getOwnPropertySymbols(t);
|
|
332
|
-
let r = false;
|
|
333
|
-
for (let t = 0, n = e.length; t < n; t++) {
|
|
334
|
-
if (e[t] !== $TRACK && e[t] !== $AFFECTS) {
|
|
335
|
-
r = true;
|
|
336
|
-
break;
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
if (!r) symbolKeyedRecords.delete(t);
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
}, e[STORE_FIREWALL]);
|
|
344
|
-
if (e[STORE_OPTIMISTIC]) {
|
|
345
|
-
O._e = NOT_PENDING;
|
|
346
|
-
}
|
|
347
|
-
if (i && r in i) {
|
|
348
|
-
const e = i[r];
|
|
349
|
-
O.Le = e === undefined ? NO_SNAPSHOT : e;
|
|
350
|
-
snapshotSources?.add(O);
|
|
351
|
-
}
|
|
352
|
-
if (typeof r === "symbol" && r !== $TRACK && r !== $AFFECTS) symbolKeyedRecords.add(t);
|
|
353
|
-
// A node born inside a live mark's identity scope inherits the mark
|
|
354
|
-
// (the declaration walk could only cover nodes that existed then). The
|
|
355
|
-
// record's own $AFFECTS carrier is the mark's channel, never a member.
|
|
356
|
-
if (r !== $AFFECTS && affectsScopes.size) inheritAffectsMarks(O, e[STORE_VALUE], r);
|
|
357
|
-
// Node presence bubbles up the wrap chain (sticky), so reconcile can see
|
|
358
|
-
// "subscribers live somewhere below" through node-less intermediate
|
|
359
|
-
// records — the captured-proxy diff gate (#2902). Amortized O(1): stops at
|
|
360
|
-
// the first already-flagged ancestor.
|
|
361
|
-
let s = e;
|
|
362
|
-
while (s && !s[STORE_DESC]) {
|
|
363
|
-
s[STORE_DESC] = true;
|
|
364
|
-
s = s[STORE_PARENT];
|
|
365
|
-
}
|
|
366
|
-
return t[r] = O;
|
|
367
|
-
}
|
|
368
|
-
|
|
369
134
|
/**
|
|
370
135
|
* Scope inheritance for late-created nodes: every live mark whose identity
|
|
371
136
|
* scope contains the owning record's raw — and, for keyed marks, whose key
|
|
372
137
|
* is this property — gets counted on the new node. Inherited marks live
|
|
373
138
|
* exactly as long as the scope's carrier — the release hook below drops
|
|
374
139
|
* them with the entry.
|
|
375
|
-
*/ function inheritAffectsMarks(e, t,
|
|
140
|
+
*/ function inheritAffectsMarks(e, t, o) {
|
|
376
141
|
// A live scope exists, so affects.ts already installed the mark engine.
|
|
377
|
-
for (const [
|
|
378
|
-
if (
|
|
142
|
+
for (const [r, s] of affectsScopes) {
|
|
143
|
+
if (r.o?.t && s.scope.has(t) && (s.key === undefined || s.key === o)) {
|
|
379
144
|
GlobalQueue.M(e);
|
|
380
|
-
|
|
145
|
+
s.inherited.push(e);
|
|
381
146
|
}
|
|
382
147
|
}
|
|
383
148
|
}
|
|
384
149
|
|
|
385
150
|
const affectsScopes = new Map;
|
|
386
151
|
|
|
152
|
+
/** Next-store node factory for affects carriers/slots: injected by the
|
|
153
|
+
* rewrite module (next targets alias the legacy field names, so everything
|
|
154
|
+
* here EXCEPT node creation works on them structurally). */ let nextAffectsNodeResolver = null;
|
|
155
|
+
|
|
156
|
+
function setNextAffectsNodeResolver(e) {
|
|
157
|
+
nextAffectsNodeResolver = e;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/** Next-store optimistic view for the declaration walk (optimistic rows
|
|
161
|
+
* pushed before the declaration are in motion too — legacy reads its write
|
|
162
|
+
* overlays; next composes armed-node overrides). */ let nextOptimisticViewResolver = null;
|
|
163
|
+
|
|
164
|
+
function setNextOptimisticViewResolver(e) {
|
|
165
|
+
nextOptimisticViewResolver = e;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** @internal birth inheritance for nodes created inside a live mark window —
|
|
169
|
+
* exported for the rewrite's node factories. */ function affectsScopesLive() {
|
|
170
|
+
return affectsScopes.size > 0;
|
|
171
|
+
}
|
|
172
|
+
|
|
387
173
|
/**
|
|
388
174
|
* Snapshots the identities reachable from `value` into `scope`, reading
|
|
389
175
|
* through write overlays (an optimistic row pushed before the declaration is
|
|
@@ -393,61 +179,67 @@ const affectsScopes = new Map;
|
|
|
393
179
|
* readers subscribed through, so the mark registers on them directly and
|
|
394
180
|
* rides the status rails to everything derived. (Nodes born later inherit
|
|
395
181
|
* from the scope in `getNode`.)
|
|
396
|
-
*/ function walkAffectsScope(e, t,
|
|
182
|
+
*/ function walkAffectsScope(e, t, o, r,
|
|
397
183
|
// Cycle guard, fresh per declaration: the scope itself can't serve — a
|
|
398
184
|
// re-declaration on the same carrier unions into a scope that already
|
|
399
185
|
// holds the root, and must still descend to pick up records added since.
|
|
400
|
-
|
|
186
|
+
s) {
|
|
401
187
|
if (!isWrappable(e)) return;
|
|
402
|
-
const
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
188
|
+
const f = e[$TARGET] || lookupTarget(e, r);
|
|
189
|
+
// Next targets: walk the pending backing when present (a draft's writes are
|
|
190
|
+
// in motion too) and cover BOTH identities in the scope.
|
|
191
|
+
let n = f ? f.pb ?? f[STORE_VALUE] : e;
|
|
192
|
+
if (s.has(n)) return;
|
|
193
|
+
s.add(n);
|
|
194
|
+
t.scope.add(n);
|
|
195
|
+
if (f && f.pb) t.scope.add(f[STORE_VALUE]);
|
|
196
|
+
// Next optimistic families: enumerate the VISIBLE view (armed-node
|
|
197
|
+
// overrides compose membership/values the raw doesn't carry).
|
|
198
|
+
if (f && f.fam?.opt && nextOptimisticViewResolver) n = nextOptimisticViewResolver(f, n);
|
|
199
|
+
if (f) {
|
|
200
|
+
collectRecordNodes(f[STORE_NODE], o);
|
|
201
|
+
collectRecordNodes(f[STORE_HAS], o);
|
|
202
|
+
// The key-set and deep-witness nodes are record-level channels: a deep()
|
|
203
|
+
// probe reads ONLY these (one pair per record), so a declared affects
|
|
204
|
+
// scope must mark them like any property node.
|
|
205
|
+
if (f.k) o.push(f.k);
|
|
206
|
+
if (f.dk) o.push(f.dk);
|
|
207
|
+
// Carry the effective family into untouched descendants (projections/
|
|
208
|
+
// optimistic stores register children under their family).
|
|
209
|
+
r = f.fam ?? r;
|
|
416
210
|
}
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
211
|
+
// Overlays are gone (next has no layer): raw enumeration; the optimistic
|
|
212
|
+
// view composition above already folded armed-node membership/values in.
|
|
213
|
+
if (Array.isArray(n)) {
|
|
214
|
+
for (let e = 0, f = n.length; e < f; e++) {
|
|
215
|
+
walkAffectsScope(n[e], t, o, r, s);
|
|
422
216
|
}
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
const S = getPropertyDescriptor(O, s, i);
|
|
430
|
-
if (!S || S.get) continue;
|
|
431
|
-
walkAffectsScope(S.value, t, r, n, o);
|
|
217
|
+
const e = Object.getOwnPropertySymbols(n);
|
|
218
|
+
for (let f = 0, c = e.length; f < c; f++) {
|
|
219
|
+
if (e[f] === $OWNER) continue;
|
|
220
|
+
const c = Object.getOwnPropertyDescriptor(n, e[f]);
|
|
221
|
+
if (!c || c.get) continue;
|
|
222
|
+
walkAffectsScope(c.value, t, o, r, s);
|
|
432
223
|
}
|
|
433
224
|
} else {
|
|
434
|
-
const e =
|
|
435
|
-
for (let
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
225
|
+
const e = Reflect.ownKeys(n);
|
|
226
|
+
for (let f = 0, c = e.length; f < c; f++) {
|
|
227
|
+
if (e[f] === $OWNER) continue;
|
|
228
|
+
const c = Object.getOwnPropertyDescriptor(n, e[f]);
|
|
229
|
+
if (!c || c.get) continue;
|
|
230
|
+
walkAffectsScope(c.value, t, o, r, s);
|
|
439
231
|
}
|
|
440
232
|
}
|
|
441
233
|
}
|
|
442
234
|
|
|
443
235
|
/** All live signal nodes of one record's node map (string + symbol keyed). */ function collectRecordNodes(e, t) {
|
|
444
236
|
if (!e) return;
|
|
445
|
-
for (const
|
|
446
|
-
const
|
|
447
|
-
for (let
|
|
237
|
+
for (const o of Object.keys(e)) t.push(e[o]);
|
|
238
|
+
const o = Object.getOwnPropertySymbols(e);
|
|
239
|
+
for (let r = 0, s = o.length; r < s; r++) {
|
|
448
240
|
// Another mark's carrier is its own channel — counting it here would
|
|
449
241
|
// extend that sibling scope's lifetime to this declaration's.
|
|
450
|
-
if (r
|
|
242
|
+
if (o[r] !== $AFFECTS) t.push(e[o[r]]);
|
|
451
243
|
}
|
|
452
244
|
}
|
|
453
245
|
|
|
@@ -463,12 +255,28 @@ o) {
|
|
|
463
255
|
*/ function witnessAffectsMark(e, t) {
|
|
464
256
|
// Callers guard on `pendingCheckActive`, which only flips inside
|
|
465
257
|
// isPending() — the verdict layer is loaded and its hook installed.
|
|
466
|
-
const
|
|
467
|
-
if (
|
|
258
|
+
const o = e[STORE_NODE]?.[$AFFECTS];
|
|
259
|
+
if (o?.o?.t) GlobalQueue.Et(o);
|
|
468
260
|
if (affectsScopes.size) {
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
261
|
+
// Chained backings (§7b): a wrapper's STORE_VALUE can be another store's
|
|
262
|
+
// proxy — marks cover by identity of the BASE raw, so resolve the chain
|
|
263
|
+
// and check every identity along it.
|
|
264
|
+
let r = e[STORE_VALUE];
|
|
265
|
+
for (const [e, s] of affectsScopes) {
|
|
266
|
+
if (e !== o && e.o?.t && (s.key === undefined || s.key === t)) {
|
|
267
|
+
let t = r;
|
|
268
|
+
for (;;) {
|
|
269
|
+
if (s.scope.has(t)) {
|
|
270
|
+
GlobalQueue.Et(e);
|
|
271
|
+
break;
|
|
272
|
+
}
|
|
273
|
+
const o = t?.[$TARGET];
|
|
274
|
+
if (o === undefined) break;
|
|
275
|
+
const r = o.pb ?? o[STORE_VALUE];
|
|
276
|
+
if (r === t) break;
|
|
277
|
+
t = r;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
472
280
|
}
|
|
473
281
|
}
|
|
474
282
|
}
|
|
@@ -484,598 +292,38 @@ o) {
|
|
|
484
292
|
*
|
|
485
293
|
* @internal
|
|
486
294
|
*/ function getStoreAffectsNodes(e, t) {
|
|
487
|
-
const r = getNodes(e, STORE_NODE);
|
|
488
295
|
GlobalQueue.p ||= e => {
|
|
489
296
|
const t = affectsScopes.get(e);
|
|
490
297
|
if (!t) return;
|
|
491
298
|
affectsScopes.delete(e);
|
|
492
|
-
for (let e = 0; e < t.inherited.length; e++) GlobalQueue.
|
|
299
|
+
for (let e = 0; e < t.inherited.length; e++) GlobalQueue.N(t.inherited[e]);
|
|
493
300
|
};
|
|
494
301
|
if (t === undefined) {
|
|
495
|
-
const t =
|
|
496
|
-
let
|
|
497
|
-
if (!
|
|
302
|
+
const t = nextAffectsNodeResolver(e, $AFFECTS);
|
|
303
|
+
let o = affectsScopes.get(t);
|
|
304
|
+
if (!o) affectsScopes.set(t, o = {
|
|
498
305
|
scope: new Set,
|
|
499
306
|
inherited: []
|
|
500
307
|
});
|
|
501
|
-
const
|
|
502
|
-
walkAffectsScope(e[$PROXY],
|
|
503
|
-
return
|
|
504
|
-
}
|
|
505
|
-
let n = r[t];
|
|
506
|
-
if (!n) {
|
|
507
|
-
const o = getOverlayLayer(e, t);
|
|
508
|
-
const i = o ? o[t] : e[STORE_VALUE][t];
|
|
509
|
-
n = upsertStoreNode(e, r, t, i === $DELETED ? undefined : i, e[STORE_SNAPSHOT_PROPS]);
|
|
308
|
+
const r = [ t ];
|
|
309
|
+
walkAffectsScope(e[$PROXY], o, r, e.fam, new Set);
|
|
310
|
+
return r;
|
|
510
311
|
}
|
|
312
|
+
const o = e.n?.[t] ?? nextAffectsNodeResolver(e, t);
|
|
511
313
|
// Keyed marks resolve by identity too (#2904): another store family's
|
|
512
314
|
// proxy can share this record's raw (a derived store swaps its backing to
|
|
513
315
|
// the source's raw when its projection lands), and reads through it never
|
|
514
316
|
// touch this target's node map. Scope is exactly the owning record's raw,
|
|
515
317
|
// narrowed to this key for witness and birth inheritance.
|
|
516
|
-
let
|
|
517
|
-
if (!
|
|
318
|
+
let r = affectsScopes.get(o);
|
|
319
|
+
if (!r) affectsScopes.set(o, r = {
|
|
518
320
|
scope: new Set,
|
|
519
321
|
inherited: [],
|
|
520
322
|
key: t
|
|
521
323
|
});
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
function trackSelf(e, t = $TRACK) {
|
|
527
|
-
if (!getObserver()) return;
|
|
528
|
-
read(getNode(e, getNodes(e, STORE_NODE), t, undefined, false));
|
|
529
|
-
// Store-in-store: structural notifications (reconcile, notifySelf) land on
|
|
530
|
-
// the wrapped source's own self-node, never on this wrapper view's. Chain
|
|
531
|
-
// the read through so enumeration/$TRACK on the wrapper observes them
|
|
532
|
-
// (#2864). Property reads already chain naturally via the inner get trap.
|
|
533
|
-
// An override layer on the view is a hold (A17) — the shown structure is
|
|
534
|
-
// the overlay's, so don't subscribe through it; clearing the layer notifies
|
|
535
|
-
// this view's own self-node and the re-run re-establishes the chain.
|
|
536
|
-
if (t === $TRACK && !e[STORE_OVERRIDE] && !e[STORE_OPTIMISTIC_OVERRIDE] && e[STORE_VALUE][$TARGET]) e[STORE_VALUE][$TRACK];
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
function notifySelf(e) {
|
|
540
|
-
const t = e[STORE_NODE]?.[$TRACK];
|
|
541
|
-
t && setSignal(t, e[STORE_OPTIMISTIC] && !projectionWriteActive ? STORE_SELF_PENDING : undefined);
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
/**
|
|
545
|
-
* The write overlay a walk must read through: optimistic writes shadow
|
|
546
|
-
* regular pending writes, the same resolution order as every proxy trap and
|
|
547
|
-
* `reconcile` (#2850). Merging allocates only in the rare both-present case
|
|
548
|
-
* (a derived optimistic store with an in-flight projection commit).
|
|
549
|
-
*/ function mergedOverlay(e) {
|
|
550
|
-
const t = e[STORE_OVERRIDE];
|
|
551
|
-
const r = e[STORE_OPTIMISTIC_OVERRIDE];
|
|
552
|
-
return t && r ? {
|
|
553
|
-
...t,
|
|
554
|
-
...r
|
|
555
|
-
} : r ?? t;
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
function getKeysImpl(e, t, r, n) {
|
|
559
|
-
// Plain objects can't trigger proxy traps — only pay for the untrack
|
|
560
|
-
// closure when the source is itself a wrapped store (store-in-store).
|
|
561
|
-
const o = e[$TARGET] ? untrack(() => r ? n ? ownEnumerableKeys(e) : Object.keys(e) : Reflect.ownKeys(e)) : r ? n ? ownEnumerableKeysPlain(e) : Object.keys(e) : Reflect.ownKeys(e);
|
|
562
|
-
return t ? mergeOverrideKeys(o, t) : o;
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
function getKeys(e, t, r = true) {
|
|
566
|
-
return getKeysImpl(e, t, r, false);
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
function getStoreKeys(e, t) {
|
|
570
|
-
return getKeysImpl(e, t, true, true);
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
function getStoreSymbols(e, t) {
|
|
574
|
-
const r = e[$TARGET] ? untrack(() => ownEnumerableSymbols(e)) : ownEnumerableSymbols(e);
|
|
575
|
-
return t ? mergeOverrideKeys(r, t, true) : r;
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
// Shared override-layer merge for key enumeration: adds live override keys,
|
|
579
|
-
// drops $DELETED ones. `symbolsOnly` scopes the override scan for the
|
|
580
|
-
// array-metadata passes.
|
|
581
|
-
function mergeOverrideKeys(e, t, r) {
|
|
582
|
-
const n = new Set(e);
|
|
583
|
-
const o = r ? Object.getOwnPropertySymbols(t) : Reflect.ownKeys(t);
|
|
584
|
-
for (const e of o) {
|
|
585
|
-
if (t[e] !== $DELETED) n.add(e); else n.delete(e);
|
|
586
|
-
}
|
|
587
|
-
return Array.from(n);
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
function getPropertyDescriptor(e, t, r) {
|
|
591
|
-
if (t && r in t) {
|
|
592
|
-
if (t[r] === $DELETED) return void 0;
|
|
593
|
-
const n = Reflect.getOwnPropertyDescriptor(t, r);
|
|
594
|
-
if (n?.get || n?.set) return n;
|
|
595
|
-
// Plain writes live in the override while the source keeps its old value.
|
|
596
|
-
// Preserve the source descriptor flags, but report the current override
|
|
597
|
-
// value. Source accessors cannot be patched with a value, and inherited
|
|
598
|
-
// properties have no source own descriptor, so those keep their descriptor.
|
|
599
|
-
const o = Reflect.getOwnPropertyDescriptor(e, r);
|
|
600
|
-
if (!o) return n;
|
|
601
|
-
if (o.get || o.set) return o;
|
|
602
|
-
// Reflect returns a fresh descriptor, so patching in place is safe and
|
|
603
|
-
// avoids an allocation on Object.keys/spread over written stores.
|
|
604
|
-
o.value = t[r];
|
|
605
|
-
return o;
|
|
606
|
-
}
|
|
607
|
-
return Reflect.getOwnPropertyDescriptor(e, r);
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
function prepareStoreWrite(e, t, r) {
|
|
611
|
-
if (e[STORE_OPTIMISTIC]) {
|
|
612
|
-
const t = e[STORE_FIREWALL];
|
|
613
|
-
if (t?.Ne) {
|
|
614
|
-
globalQueue.initTransition(t.Ne);
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
const n = e[STORE_VALUE];
|
|
618
|
-
const o = n[r];
|
|
619
|
-
if (snapshotCaptureActive && typeof r !== "symbol" && !((e[STORE_FIREWALL]?.S ?? 0) & STATUS_PENDING)) {
|
|
620
|
-
if (!e[STORE_SNAPSHOT_PROPS]) {
|
|
621
|
-
e[STORE_SNAPSHOT_PROPS] = Object.create(null);
|
|
622
|
-
snapshotSources?.add(e);
|
|
623
|
-
}
|
|
624
|
-
if (!(r in e[STORE_SNAPSHOT_PROPS])) {
|
|
625
|
-
e[STORE_SNAPSHOT_PROPS][r] = o;
|
|
626
|
-
}
|
|
627
|
-
}
|
|
628
|
-
const i = e[STORE_OPTIMISTIC] && !projectionWriteActive;
|
|
629
|
-
const O = i ? STORE_OPTIMISTIC_OVERRIDE : STORE_OVERRIDE;
|
|
630
|
-
return {
|
|
631
|
-
base: o,
|
|
632
|
-
overrideKey: O,
|
|
633
|
-
state: n
|
|
634
|
-
};
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
/**
|
|
638
|
-
* Registers the store for transition reversion. Called only once a write is
|
|
639
|
-
* known to be effective — ineffective writes (same value, delete of an absent
|
|
640
|
-
* property) are no-ops and must not entangle the store. Optimistic writes are
|
|
641
|
-
* verdict-inert (question-scoped pending model): no mask is armed — the write
|
|
642
|
-
* neither pends its own slot nor silences anyone else's.
|
|
643
|
-
*/ function armOptimisticStoreWrite(e, t) {
|
|
644
|
-
// STORE_OPTIMISTIC is only set by createOptimisticStore, which installs the
|
|
645
|
-
// optimistic engine before wrapping.
|
|
646
|
-
if (e[STORE_OPTIMISTIC] && !projectionWriteActive) {
|
|
647
|
-
GlobalQueue.Nn(t);
|
|
648
|
-
}
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
/**
|
|
652
|
-
* Records which transition owns an optimistic layer entry (#2899), so a
|
|
653
|
-
* settling action only consumes its own keys — the layer is store-wide, but
|
|
654
|
-
* concurrent actions writing disjoint keys must revert independently, exactly
|
|
655
|
-
* like optimistic signal nodes do via the transition's _optimisticNodes.
|
|
656
|
-
* `activeTransition` is the write's transaction (action() opens it before the
|
|
657
|
-
* body runs); null marks an ambient write, which clears at plain flush end —
|
|
658
|
-
* unless its flush's transition is blocked on the store's own in-flight truth
|
|
659
|
-
* (pending firewall, #2951), in which case it rides that transaction to
|
|
660
|
-
* settle. Same-key writes across actions keep last-write-wins layer
|
|
661
|
-
* semantics.
|
|
662
|
-
*/ function stampOptimisticOwner(e, t, r) {
|
|
663
|
-
if (t === STORE_OPTIMISTIC_OVERRIDE) (e[STORE_OPTIMISTIC_OWNERS] ??= Object.create(null))[r] = activeTransition;
|
|
664
|
-
}
|
|
665
|
-
|
|
666
|
-
function upsertStoreNode(e, t, r, n, o) {
|
|
667
|
-
if (t[r]) return t[r];
|
|
668
|
-
const i = isWrappable(n) ? wrap(n, e) : n;
|
|
669
|
-
const O = getNode(e, t, r, i, isEqual, o);
|
|
670
|
-
registerTransientStoreNode(O);
|
|
671
|
-
return O;
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
function notifyStoreProperty(e, t, r, n, o, i) {
|
|
675
|
-
// Cold writes upsert a transient pending node so untracked reads batch like signals.
|
|
676
|
-
// Skip for projection writes (different commit semantics) and for optimistic stores
|
|
677
|
-
// (whose whole purpose is immediate visibility via STORE_OPTIMISTIC_OVERRIDE).
|
|
678
|
-
const O = projectionWriteActive || e[STORE_OPTIMISTIC];
|
|
679
|
-
const s = r !== "delete";
|
|
680
|
-
const E = e[STORE_HAS]?.[t];
|
|
681
|
-
if (E) {
|
|
682
|
-
setSignal(E, s);
|
|
683
|
-
} else if (!O && r !== "invalidate" && i !== s) {
|
|
684
|
-
const r = upsertStoreNode(e, getNodes(e, STORE_HAS), t, i);
|
|
685
|
-
setSignal(r, s);
|
|
686
|
-
}
|
|
687
|
-
const S = getNodes(e, STORE_NODE);
|
|
688
|
-
if (r === "set") {
|
|
689
|
-
if (S[t]) {
|
|
690
|
-
setSignal(S[t], () => isWrappable(n) ? wrap(n, e) : n);
|
|
691
|
-
} else if (!O) {
|
|
692
|
-
const r = upsertStoreNode(e, S, t, o, e[STORE_SNAPSHOT_PROPS]);
|
|
693
|
-
setSignal(r, () => isWrappable(n) ? wrap(n, e) : n);
|
|
694
|
-
}
|
|
695
|
-
} else if (r === "invalidate") {
|
|
696
|
-
if (S[t]) {
|
|
697
|
-
setSignal(S[t], {});
|
|
698
|
-
delete S[t];
|
|
699
|
-
}
|
|
700
|
-
} else {
|
|
701
|
-
if (S[t]) {
|
|
702
|
-
setSignal(S[t], undefined);
|
|
703
|
-
} else if (!O) {
|
|
704
|
-
const r = upsertStoreNode(e, S, t, o, e[STORE_SNAPSHOT_PROPS]);
|
|
705
|
-
setSignal(r, undefined);
|
|
706
|
-
}
|
|
707
|
-
}
|
|
708
|
-
notifySelf(e);
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
let Writing = null;
|
|
712
|
-
|
|
713
|
-
/**
|
|
714
|
-
* A derived store follows async memo rules (#2897 ruling): its seed is a
|
|
715
|
-
* draft for the derive function, never an observable value, and an errored
|
|
716
|
-
* derive is an error state, never a silent stale/seed serve. Until the
|
|
717
|
-
* firewall first resolves there is nothing to read, so every consumer path
|
|
718
|
-
* throws NotReady — tracked reads through their node (core read()), and the
|
|
719
|
-
* untracked fall-throughs in the traps through this guard. Returning the
|
|
720
|
-
* seed leaked it; returning `undefined` would break non-nullable types.
|
|
721
|
-
* Callers exempt the firewall itself (the derive function works its own
|
|
722
|
-
* draft while uninitialized).
|
|
723
|
-
*
|
|
724
|
-
* Error rail: a firewall carrying STATUS_ERROR throws its error for every
|
|
725
|
-
* late reader — memo parity, where read()'s error branch does the same for
|
|
726
|
-
* plain computeds. Rejection clears STATUS_UNINITIALIZED at commit, so
|
|
727
|
-
* without this check late readers silently got the seed while settle-time
|
|
728
|
-
* subscribers saw the error.
|
|
729
|
-
*
|
|
730
|
-
* Loading rail: the veto requires the firewall to still be in flight, not
|
|
731
|
-
* just flagged: STATUS_UNINITIALIZED's clear is deferred to batch commit,
|
|
732
|
-
* so during the settle flush a firewall that has already recomputed — and
|
|
733
|
-
* reconciled real values into STORE_VALUE — still carries the stale flag.
|
|
734
|
-
* STATUS_PENDING is the live bit (it clears eagerly at settle, mirroring
|
|
735
|
-
* core read()'s verdict), so gating on it stops the guard from throwing a
|
|
736
|
-
* fresh NotReadyError that nothing would ever sweep. #2944: mapArray's
|
|
737
|
-
* keyed diff reads items inside its internal owner (untracked by design)
|
|
738
|
-
* in exactly this window, and the stale throw wedged <For> permanently.
|
|
739
|
-
*/ function throwIfUnreadable(e) {
|
|
740
|
-
const t = e[STORE_FIREWALL];
|
|
741
|
-
if (!t) return;
|
|
742
|
-
const r = t.S;
|
|
743
|
-
if (r & STATUS_ERROR || r & STATUS_UNINITIALIZED && r & STATUS_PENDING) throw t._ ?? new NotReadyError(t);
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
const storeTraps = {
|
|
747
|
-
get(e, t, r) {
|
|
748
|
-
if (t === $TARGET) return e;
|
|
749
|
-
if (t === $PROXY) return r;
|
|
750
|
-
if (t === $REFRESH) return e[STORE_FIREWALL];
|
|
751
|
-
if (pendingCheckActive) witnessAffectsMark(e, t);
|
|
752
|
-
if (t === $TRACK) {
|
|
753
|
-
trackSelf(e);
|
|
754
|
-
return r;
|
|
755
|
-
}
|
|
756
|
-
// Hot path: an existing node on a plain target — no firewall (so neither
|
|
757
|
-
// selfRead nor the uninitialized guard can apply), no override layers,
|
|
758
|
-
// no write scope, and a raw (non-proxy) source. This is the shape of
|
|
759
|
-
// every effect re-read of a settled store; it pays one node read and the
|
|
760
|
-
// wrap check, nothing else. Any exotic bit falls through to the full
|
|
761
|
-
// resolution below, and dev strictRead keeps its warning path.
|
|
762
|
-
if (e[STORE_FIREWALL] === undefined && e[STORE_OVERRIDE] === undefined && e[STORE_OPTIMISTIC_OVERRIDE] === undefined && !writeOverride && (Writing === null || !Writing.has(r))) {
|
|
763
|
-
const r = e[STORE_NODE];
|
|
764
|
-
const n = r && r[t];
|
|
765
|
-
if (n !== undefined && e[STORE_VALUE][$TARGET] === undefined) {
|
|
766
|
-
// readNodeFast is read()'s plain-signal fast path hoisted over the
|
|
767
|
-
// call; READ_SLOW means a global read window (latest/pending-check/
|
|
768
|
-
// transition/lane/snapshot capture) or a node layer is active, and
|
|
769
|
-
// only then does the full read() resolution have anything to do.
|
|
770
|
-
let t = readNodeFast(n);
|
|
771
|
-
if (t === READ_SLOW) t = read(n);
|
|
772
|
-
if (t === $DELETED) t = undefined;
|
|
773
|
-
// Every node-writing site wraps wrappables before setSignal (see the
|
|
774
|
-
// dev assertion below), so re-wrapping on read is redundant — except
|
|
775
|
-
// during snapshot capture, where read() can surface a raw captured
|
|
776
|
-
// value seeded from snapshot props.
|
|
777
|
-
if (!snapshotCaptureActive) {
|
|
778
|
-
return t;
|
|
779
|
-
}
|
|
780
|
-
return isWrappable(t) ? wrap(t, e) : t;
|
|
781
|
-
}
|
|
782
|
-
}
|
|
783
|
-
const n = getObserver() === e[STORE_FIREWALL];
|
|
784
|
-
const o = getNodes(e, STORE_NODE);
|
|
785
|
-
const i = n ? undefined : o[t];
|
|
786
|
-
const O = e[STORE_VALUE];
|
|
787
|
-
if (!i && !e[STORE_OVERRIDE] && !e[STORE_OPTIMISTIC_OVERRIDE] && !e[STORE_CUSTOM_PROTO] && !e[STORE_OPTIMISTIC] && !e[STORE_SNAPSHOT_PROPS] && !O[$TARGET] && !(t in O) && getObserver() && !n && !writeOnly(r)) {
|
|
788
|
-
return read(getNode(e, o, t, undefined));
|
|
789
|
-
}
|
|
790
|
-
const s = getOverlayLayer(e, t);
|
|
791
|
-
const E = !!s;
|
|
792
|
-
const S = !!e[STORE_VALUE][$TARGET];
|
|
793
|
-
const T = s ?? e[STORE_VALUE];
|
|
794
|
-
if (!i) {
|
|
795
|
-
const n = Object.getOwnPropertyDescriptor(T, t);
|
|
796
|
-
if (n && n.get) return n.get.call(r);
|
|
797
|
-
if (!n && !E && e[STORE_CUSTOM_PROTO]) {
|
|
798
|
-
const e = unwrapStoreValue(T);
|
|
799
|
-
if (hasInheritedAccessor(e, t)) {
|
|
800
|
-
return Reflect.get(T, t, r);
|
|
801
|
-
}
|
|
802
|
-
}
|
|
803
|
-
}
|
|
804
|
-
if (writeOnly(r)) {
|
|
805
|
-
if (isPrototypePollutionKey(t) && !hasOwnStoreProperty(e, t)) return undefined;
|
|
806
|
-
let r = i && (E || !S) ? visibleNodeValue(i) : T[t];
|
|
807
|
-
r === $DELETED && (r = undefined);
|
|
808
|
-
if (!isWrappable(r)) return r;
|
|
809
|
-
// Shallow boundary: records are replaced, never edited in place. Reads
|
|
810
|
-
// inside a setter serve the raw so read-then-replace, filter/pop and
|
|
811
|
-
// projection derives all work; in-place mutation of a raw is inert by
|
|
812
|
-
// construction — the same contract as a markRaw child in a deep store.
|
|
813
|
-
if (e[STORE_SHALLOW]) return r;
|
|
814
|
-
const n = wrap(r, e);
|
|
815
|
-
Writing?.add(n);
|
|
816
|
-
return n;
|
|
817
|
-
}
|
|
818
|
-
let c = i ? E || !S ? read(o[t]) : (read(o[t]), T[t]) : T[t];
|
|
819
|
-
c === $DELETED && (c = undefined);
|
|
820
|
-
if (!i) {
|
|
821
|
-
if (!E && typeof c === "function" && !Object.prototype.hasOwnProperty.call(T, t)) {
|
|
822
|
-
let t;
|
|
823
|
-
return !Array.isArray(e[STORE_VALUE]) && (t = Object.getPrototypeOf(e[STORE_VALUE])) && t !== Object.prototype ? c.bind(T) : c;
|
|
824
|
-
} else if (getObserver() && !n) {
|
|
825
|
-
return read(getNode(e, o, t, isWrappable(c) ? wrap(c, e) : c, isEqual, e[STORE_SNAPSHOT_PROPS]));
|
|
826
|
-
}
|
|
827
|
-
}
|
|
828
|
-
// Untracked fall-through (tracked reads already threw via their node in
|
|
829
|
-
// read(); the dev strictRead error above wins first for memo parity).
|
|
830
|
-
// Observer-present reads must NOT re-consult the flag here: during the
|
|
831
|
-
// settle flush the firewall has recomputed (first values live on the
|
|
832
|
-
// pending rail, served by read() above) but its UNINITIALIZED clear is
|
|
833
|
-
// deferred to batch commit — vetoing read()'s verdict with the stale flag
|
|
834
|
-
// threw a fresh NotReadyError for an already-settled source, which no
|
|
835
|
-
// sweep would ever release (#2938: projection over an async store wedged
|
|
836
|
-
// its Loading boundary on `undefined`).
|
|
837
|
-
if (!n && !getObserver()) throwIfUnreadable(e);
|
|
838
|
-
return isWrappable(c) ? wrap(c, e) : c;
|
|
839
|
-
},
|
|
840
|
-
has(e, t) {
|
|
841
|
-
if (t === $PROXY || t === $TRACK || t === "__proto__") return true;
|
|
842
|
-
if (pendingCheckActive) witnessAffectsMark(e, t);
|
|
843
|
-
const r = getOverlayLayer(e, t);
|
|
844
|
-
const n = r ? r[t] !== $DELETED : t in e[STORE_VALUE];
|
|
845
|
-
if (writeOnly(e[$PROXY]) || getObserver() === e[STORE_FIREWALL]) return n;
|
|
846
|
-
const o = getNodes(e, STORE_HAS);
|
|
847
|
-
// If a has-node already exists, it carries the batched presence — `read()`
|
|
848
|
-
// returns `_value` (committed) for untracked reads and the pending value for
|
|
849
|
-
// downstream computes. This keeps `in` consistent with value reads.
|
|
850
|
-
if (o[t]) return read(o[t]);
|
|
851
|
-
// No node yet: `has` reflects committed presence (no pending write could change
|
|
852
|
-
// it without first upserting a has-node at the write site). Create + read only
|
|
853
|
-
// when tracking; leave untracked reads node-free.
|
|
854
|
-
if (getObserver()) {
|
|
855
|
-
return read(getNode(e, o, t, n));
|
|
856
|
-
}
|
|
857
|
-
throwIfUnreadable(e);
|
|
858
|
-
return n;
|
|
859
|
-
},
|
|
860
|
-
set(e, t, r) {
|
|
861
|
-
if (t === "__proto__") return true;
|
|
862
|
-
const n = e[$PROXY];
|
|
863
|
-
if (writeOnly(n)) {
|
|
864
|
-
untrack(() => {
|
|
865
|
-
const {base: o, overrideKey: i, state: O} = prepareStoreWrite(e, n, t);
|
|
866
|
-
const s = getOverlayLayer(e, t);
|
|
867
|
-
const E = s ? s[t] : o;
|
|
868
|
-
const S = s ? s[t] !== $DELETED : t in e[STORE_VALUE];
|
|
869
|
-
// Shallow slots hold store proxies verbatim (pass-through reference,
|
|
870
|
-
// never raw-marked — see markRawOne/#2932); everything else unwraps
|
|
871
|
-
// and marks as usual.
|
|
872
|
-
const T = !!e[STORE_SHALLOW] && r?.[$TARGET] !== undefined;
|
|
873
|
-
const c = T ? r : unwrapStoreValue(r);
|
|
874
|
-
if (e[STORE_SHALLOW] && !T && isWrappable(c)) {
|
|
875
|
-
// Flip the live gate too: a bare add was inert unless something else
|
|
876
|
-
// had already marked a raw somewhere (wrap() checks rawValuesUsed
|
|
877
|
-
// first), so the documented set-trap ingest mark silently no-oped in
|
|
878
|
-
// apps whose only shallow data arrived through writes.
|
|
879
|
-
rawValuesUsed = true;
|
|
880
|
-
rawValues.add(c);
|
|
881
|
-
}
|
|
882
|
-
// Symbol-keyed writes on arrays are metadata, not index writes — never run
|
|
883
|
-
// them through the numeric index/length machinery (`parseInt` on a symbol
|
|
884
|
-
// throws). #2769
|
|
885
|
-
const f = typeof t === "string" ? Number(t) : -1;
|
|
886
|
-
const R = Array.isArray(O) && Number.isInteger(f) && f >= 0 && f < 4294967295 && String(f) === t;
|
|
887
|
-
const u = R ? f + 1 : 0;
|
|
888
|
-
const a = R && (getOverlayLayer(e, "length") ?? O).length;
|
|
889
|
-
const l = R && u > a ? u : undefined;
|
|
890
|
-
if (E === c && l === undefined) return true;
|
|
891
|
-
armOptimisticStoreWrite(e, n);
|
|
892
|
-
if (c !== undefined && c === o && l === undefined) {
|
|
893
|
-
delete e[i]?.[t];
|
|
894
|
-
if (i === STORE_OPTIMISTIC_OVERRIDE) delete e[STORE_OPTIMISTIC_OWNERS]?.[t];
|
|
895
|
-
} else {
|
|
896
|
-
const r = e[i] || (e[i] = Object.create(null));
|
|
897
|
-
r[t] = c;
|
|
898
|
-
stampOptimisticOwner(e, i, t);
|
|
899
|
-
if (l !== undefined) {
|
|
900
|
-
r.length = l;
|
|
901
|
-
stampOptimisticOwner(e, i, "length");
|
|
902
|
-
}
|
|
903
|
-
}
|
|
904
|
-
notifyStoreProperty(e, t, "set", c, E, S);
|
|
905
|
-
// Shrinking an array's length must remove the truncated indices, otherwise
|
|
906
|
-
// they leak through `has`, `ownKeys`, and (tracked) index reads from the
|
|
907
|
-
// underlying value. Mark each as deleted and notify so reactive reads update. #2768
|
|
908
|
-
if (Array.isArray(O) && t === "length" && typeof c === "number" && typeof E === "number" && c < E) {
|
|
909
|
-
const t = e[i] || (e[i] = Object.create(null));
|
|
910
|
-
for (let r = c; r < E; r++) {
|
|
911
|
-
if (t[r] === $DELETED) continue;
|
|
912
|
-
const n = r in t ? t[r] : O[r];
|
|
913
|
-
if (!(r in t) && !(r in O)) continue;
|
|
914
|
-
t[r] = $DELETED;
|
|
915
|
-
stampOptimisticOwner(e, i, r);
|
|
916
|
-
notifyStoreProperty(e, r, "delete", undefined, n, true);
|
|
917
|
-
}
|
|
918
|
-
}
|
|
919
|
-
// notify length change
|
|
920
|
-
if (Array.isArray(O) && t !== "length" && l !== undefined) {
|
|
921
|
-
const t = getNodes(e, STORE_NODE);
|
|
922
|
-
if (t.length) {
|
|
923
|
-
setSignal(t.length, l);
|
|
924
|
-
} else if (!projectionWriteActive && !e[STORE_OPTIMISTIC]) {
|
|
925
|
-
const r = upsertStoreNode(e, t, "length", a, e[STORE_SNAPSHOT_PROPS]);
|
|
926
|
-
setSignal(r, l);
|
|
927
|
-
}
|
|
928
|
-
}
|
|
929
|
-
if (false) ;
|
|
930
|
-
});
|
|
931
|
-
}
|
|
932
|
-
return true;
|
|
933
|
-
},
|
|
934
|
-
defineProperty(e, t, r) {
|
|
935
|
-
if (t === "__proto__") return true;
|
|
936
|
-
const n = e[$PROXY];
|
|
937
|
-
if (writeOnly(n)) {
|
|
938
|
-
untrack(() => {
|
|
939
|
-
const {base: o, overrideKey: i} = prepareStoreWrite(e, n, t);
|
|
940
|
-
armOptimisticStoreWrite(e, n);
|
|
941
|
-
const O = "value" in r ? {
|
|
942
|
-
...r,
|
|
943
|
-
value: unwrapStoreValue(r.value)
|
|
944
|
-
} : r;
|
|
945
|
-
Object.defineProperty(e[i] || (e[i] = Object.create(null)), t, O);
|
|
946
|
-
stampOptimisticOwner(e, i, t);
|
|
947
|
-
notifyStoreProperty(e, t, "invalidate");
|
|
948
|
-
if (false) ;
|
|
949
|
-
});
|
|
950
|
-
}
|
|
951
|
-
return true;
|
|
952
|
-
},
|
|
953
|
-
deleteProperty(e, t) {
|
|
954
|
-
if (t === "__proto__") return true;
|
|
955
|
-
// Check both optimistic and regular override for existing $DELETED
|
|
956
|
-
const r = e[STORE_OPTIMISTIC_OVERRIDE]?.[t] === $DELETED;
|
|
957
|
-
const n = e[STORE_OVERRIDE]?.[t] === $DELETED;
|
|
958
|
-
if (writeOnly(e[$PROXY]) && !r && !n) {
|
|
959
|
-
untrack(() => {
|
|
960
|
-
const r = e[STORE_OPTIMISTIC] && !projectionWriteActive;
|
|
961
|
-
const n = r ? STORE_OPTIMISTIC_OVERRIDE : STORE_OVERRIDE;
|
|
962
|
-
const o = getOverlayLayer(e, t);
|
|
963
|
-
const i = o ? o[t] : e[STORE_VALUE][t];
|
|
964
|
-
if (t in e[STORE_VALUE] || e[STORE_OVERRIDE] && t in e[STORE_OVERRIDE]) {
|
|
965
|
-
armOptimisticStoreWrite(e, e[$PROXY]);
|
|
966
|
-
(e[n] || (e[n] = Object.create(null)))[t] = $DELETED;
|
|
967
|
-
stampOptimisticOwner(e, n, t);
|
|
968
|
-
} else if (e[n] && t in e[n]) {
|
|
969
|
-
armOptimisticStoreWrite(e, e[$PROXY]);
|
|
970
|
-
delete e[n][t];
|
|
971
|
-
if (n === STORE_OPTIMISTIC_OVERRIDE) delete e[STORE_OPTIMISTIC_OWNERS]?.[t];
|
|
972
|
-
} else return true;
|
|
973
|
-
notifyStoreProperty(e, t, "delete", undefined, i, true);
|
|
974
|
-
});
|
|
975
|
-
}
|
|
976
|
-
return true;
|
|
977
|
-
},
|
|
978
|
-
ownKeys(e) {
|
|
979
|
-
if (pendingCheckActive) witnessAffectsMark(e);
|
|
980
|
-
if (getObserver() !== e[STORE_FIREWALL]) {
|
|
981
|
-
trackSelf(e);
|
|
982
|
-
// trackSelf no-ops untracked, so enumeration of an unresolved derived
|
|
983
|
-
// store would otherwise leak the seed's structure (#2897). The write
|
|
984
|
-
// path is exempt (like the get/has traps' writeOnly early returns):
|
|
985
|
-
// the first landing's reconcile enumerates the store while
|
|
986
|
-
// STATUS_UNINITIALIZED is still set — it IS the initialization.
|
|
987
|
-
if (!getObserver() && !writeOnly(e[$PROXY])) throwIfUnreadable(e);
|
|
988
|
-
}
|
|
989
|
-
// Merge optimistic override with regular override for key enumeration
|
|
990
|
-
let t = getKeys(e[STORE_VALUE], e[STORE_OVERRIDE], false);
|
|
991
|
-
if (e[STORE_OPTIMISTIC_OVERRIDE]) {
|
|
992
|
-
const r = new Set(t);
|
|
993
|
-
for (const t of Reflect.ownKeys(e[STORE_OPTIMISTIC_OVERRIDE])) {
|
|
994
|
-
if (e[STORE_OPTIMISTIC_OVERRIDE][t] !== $DELETED) r.add(t); else r.delete(t);
|
|
995
|
-
}
|
|
996
|
-
t = Array.from(r);
|
|
997
|
-
}
|
|
998
|
-
return t;
|
|
999
|
-
},
|
|
1000
|
-
getOwnPropertyDescriptor(e, t) {
|
|
1001
|
-
if (t === $PROXY) return {
|
|
1002
|
-
value: e[$PROXY],
|
|
1003
|
-
writable: true,
|
|
1004
|
-
configurable: true
|
|
1005
|
-
};
|
|
1006
|
-
// Check optimistic override first, but use base descriptor structure for compatibility
|
|
1007
|
-
if (e[STORE_OPTIMISTIC_OVERRIDE] && t in e[STORE_OPTIMISTIC_OVERRIDE]) {
|
|
1008
|
-
if (e[STORE_OPTIMISTIC_OVERRIDE][t] === $DELETED) return undefined;
|
|
1009
|
-
const r = Reflect.getOwnPropertyDescriptor(e[STORE_OPTIMISTIC_OVERRIDE], t);
|
|
1010
|
-
if (r?.get || r?.set || !(t in e[STORE_VALUE])) return r;
|
|
1011
|
-
// Get base descriptor structure, override just the value
|
|
1012
|
-
const n = getPropertyDescriptor(e[STORE_VALUE], e[STORE_OVERRIDE], t);
|
|
1013
|
-
if (n) {
|
|
1014
|
-
const r = Reflect.getOwnPropertyDescriptor(e, t);
|
|
1015
|
-
const o = !r || r.configurable ? true : n.configurable;
|
|
1016
|
-
return {
|
|
1017
|
-
...n,
|
|
1018
|
-
configurable: o,
|
|
1019
|
-
value: e[STORE_OPTIMISTIC_OVERRIDE][t]
|
|
1020
|
-
};
|
|
1021
|
-
}
|
|
1022
|
-
return {
|
|
1023
|
-
value: e[STORE_OPTIMISTIC_OVERRIDE][t],
|
|
1024
|
-
writable: true,
|
|
1025
|
-
enumerable: true,
|
|
1026
|
-
configurable: true
|
|
1027
|
-
};
|
|
1028
|
-
}
|
|
1029
|
-
const r = getPropertyDescriptor(e[STORE_VALUE], e[STORE_OVERRIDE], t);
|
|
1030
|
-
// The proxy target is an internal node object, not the original source. When the
|
|
1031
|
-
// source has a non-configurable property that does not also exist as non-configurable
|
|
1032
|
-
// on the proxy target, the proxy invariant is violated: the engine requires that a
|
|
1033
|
-
// property reported as non-configurable must actually be non-configurable on the
|
|
1034
|
-
// target object. Override configurable to true only in that case.
|
|
1035
|
-
if (r && !r.configurable) {
|
|
1036
|
-
const n = Reflect.getOwnPropertyDescriptor(e, t);
|
|
1037
|
-
if (!n || n.configurable) return {
|
|
1038
|
-
...r,
|
|
1039
|
-
configurable: true
|
|
1040
|
-
};
|
|
1041
|
-
}
|
|
1042
|
-
return r;
|
|
1043
|
-
},
|
|
1044
|
-
getPrototypeOf(e) {
|
|
1045
|
-
return Object.getPrototypeOf(e[STORE_VALUE]);
|
|
1046
|
-
}
|
|
1047
|
-
};
|
|
1048
|
-
|
|
1049
|
-
function storeSetter(e, t) {
|
|
1050
|
-
const r = Writing;
|
|
1051
|
-
Writing = new Set;
|
|
1052
|
-
Writing.add(e);
|
|
1053
|
-
try {
|
|
1054
|
-
const r = t(e);
|
|
1055
|
-
if (r !== e && r !== undefined) {
|
|
1056
|
-
if (Array.isArray(r)) {
|
|
1057
|
-
for (let t = 0, n = r.length; t < n; t++) e[t] = r[t];
|
|
1058
|
-
e.length = r.length;
|
|
1059
|
-
} else {
|
|
1060
|
-
const t = new Set([ ...ownEnumerableKeys(e), ...ownEnumerableKeys(r) ]);
|
|
1061
|
-
t.forEach(t => {
|
|
1062
|
-
if (t in r) e[t] = r[t]; else delete e[t];
|
|
1063
|
-
});
|
|
1064
|
-
}
|
|
1065
|
-
}
|
|
1066
|
-
} finally {
|
|
1067
|
-
Writing.clear();
|
|
1068
|
-
Writing = r;
|
|
1069
|
-
}
|
|
1070
|
-
}
|
|
1071
|
-
|
|
1072
|
-
function createStore(e, t, r) {
|
|
1073
|
-
const n = typeof e === "function", o = n ? createProjectionInternal(e, t, r).store : t?.shallow ? wrapShallow(e) : wrap(e);
|
|
1074
|
-
return [ o, n ? e => {
|
|
1075
|
-
// Mark the projection as manually written before notifying property nodes.
|
|
1076
|
-
suppressComputedRecompute(o[$REFRESH]);
|
|
1077
|
-
storeSetter(o, e);
|
|
1078
|
-
} : e => storeSetter(o, e) ];
|
|
324
|
+
r.scope.add(e[STORE_VALUE]);
|
|
325
|
+
if (e.pb) r.scope.add(e.pb);
|
|
326
|
+
return [ o ];
|
|
1079
327
|
}
|
|
1080
328
|
|
|
1081
|
-
export { $AFFECTS, $
|
|
329
|
+
export { $AFFECTS, $PROXY, $RECORD, $TARGET, $TRACK, STORE_HAS, STORE_NODE, STORE_VALUE, affectsScopesLive, getStoreAffectsNodes, getWriteOverride, inheritAffectsMarks, isRawValue, isWrappable, markRawIngest, markRawOne, nextAffectsNodeResolver, nextOptimisticViewResolver, ownEnumerableKeys, rawValuesUsed, setNextAffectsNodeResolver, setNextOptimisticViewResolver, setWriteOverride, witnessAffectsMark };
|