@solidjs/signals 2.0.0-beta.18 → 2.0.0-beta.20

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.
Files changed (68) hide show
  1. package/dist/dev.js +3276 -928
  2. package/dist/node.cjs +6646 -4189
  3. package/dist/prod/affects.js +218 -0
  4. package/dist/prod/boundaries.js +568 -0
  5. package/dist/prod/core/action.js +96 -0
  6. package/dist/prod/core/async.js +380 -0
  7. package/dist/prod/core/constants.js +92 -0
  8. package/dist/prod/core/context.js +67 -0
  9. package/dist/prod/core/core.js +772 -0
  10. package/dist/prod/core/dev.js +3 -0
  11. package/dist/prod/core/effect.js +145 -0
  12. package/dist/prod/core/error.js +59 -0
  13. package/dist/prod/core/external.js +98 -0
  14. package/dist/prod/core/graph.js +91 -0
  15. package/dist/prod/core/heap.js +132 -0
  16. package/dist/prod/core/invariants.js +42 -0
  17. package/dist/prod/core/lanes.js +140 -0
  18. package/dist/prod/core/optimistic.js +273 -0
  19. package/dist/prod/core/owner.js +293 -0
  20. package/dist/prod/core/scheduler.js +689 -0
  21. package/dist/prod/core/verdict.js +292 -0
  22. package/dist/prod/index.js +45 -0
  23. package/dist/prod/map.js +293 -0
  24. package/dist/prod/signals.js +389 -0
  25. package/dist/prod/store/optimistic.js +184 -0
  26. package/dist/prod/store/projection.js +184 -0
  27. package/dist/prod/store/reconcile.js +426 -0
  28. package/dist/prod/store/store.js +870 -0
  29. package/dist/prod/store/storePath.js +103 -0
  30. package/dist/prod/store/utils.js +316 -0
  31. package/dist/types/affects.d.ts +1 -1
  32. package/dist/types/boundaries.d.ts +6 -6
  33. package/dist/types/core/action.d.ts +19 -6
  34. package/dist/types/core/async.d.ts +4 -38
  35. package/dist/types/core/constants.d.ts +12 -0
  36. package/dist/types/core/core.d.ts +12 -78
  37. package/dist/types/core/dev.d.ts +7 -0
  38. package/dist/types/core/external.d.ts +0 -30
  39. package/dist/types/core/heap.d.ts +8 -0
  40. package/dist/types/core/index.d.ts +3 -2
  41. package/dist/types/core/lanes.d.ts +2 -0
  42. package/dist/types/core/optimistic.d.ts +6 -0
  43. package/dist/types/core/owner.d.ts +8 -0
  44. package/dist/types/core/scheduler.d.ts +40 -39
  45. package/dist/types/core/types.d.ts +9 -1
  46. package/dist/types/core/verdict.d.ts +2 -0
  47. package/dist/types/store/projection.d.ts +0 -1
  48. package/dist/types/store/store.d.ts +8 -2
  49. package/dist/types-cjs/affects.d.cts +1 -1
  50. package/dist/types-cjs/boundaries.d.cts +6 -6
  51. package/dist/types-cjs/core/action.d.cts +19 -6
  52. package/dist/types-cjs/core/async.d.cts +4 -38
  53. package/dist/types-cjs/core/constants.d.cts +12 -0
  54. package/dist/types-cjs/core/core.d.cts +12 -78
  55. package/dist/types-cjs/core/dev.d.cts +7 -0
  56. package/dist/types-cjs/core/external.d.cts +0 -30
  57. package/dist/types-cjs/core/heap.d.cts +8 -0
  58. package/dist/types-cjs/core/index.d.cts +3 -2
  59. package/dist/types-cjs/core/lanes.d.cts +2 -0
  60. package/dist/types-cjs/core/optimistic.d.cts +6 -0
  61. package/dist/types-cjs/core/owner.d.cts +8 -0
  62. package/dist/types-cjs/core/scheduler.d.cts +40 -39
  63. package/dist/types-cjs/core/types.d.cts +9 -1
  64. package/dist/types-cjs/core/verdict.d.cts +2 -0
  65. package/dist/types-cjs/store/projection.d.cts +0 -1
  66. package/dist/types-cjs/store/store.d.cts +8 -2
  67. package/package.json +8 -6
  68. package/dist/prod.js +0 -4637
@@ -0,0 +1,870 @@
1
+ import { $REFRESH, STORE_SNAPSHOT_PROPS, NOT_PENDING, unwrapOverride, STATUS_UNINITIALIZED, STATUS_PENDING, NO_SNAPSHOT } from "../core/constants.js";
2
+
3
+ import { suppressComputedRecompute, isEqual, signal, pendingCheckActive, untrack, setSignal, read, snapshotCaptureActive, snapshotSources } from "../core/core.js";
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";
12
+
13
+ import "../core/invariants.js";
14
+
15
+ import "../core/verdict.js";
16
+
17
+ import "../core/effect.js";
18
+
19
+ import { createProjectionInternal } from "./projection.js";
20
+
21
+ /**
22
+ * Brand symbols used internally by the store proxy / projection plumbing.
23
+ * Cross-package wiring; not part of the user-facing API.
24
+ *
25
+ * @internal
26
+ */ const $TRACK = Symbol(0), $TARGET = Symbol(0), $PROXY = Symbol(0), $DELETED = Symbol(0),
27
+ // Node-map slot carrying a record-level `affects()` mark: any read through
28
+ // the record witnesses it into the active isPending() probe.
29
+ $AFFECTS = Symbol(0);
30
+
31
+ const STORE_VALUE = "v", STORE_OVERRIDE = "o", STORE_OPTIMISTIC_OVERRIDE = "x", STORE_NODE = "n", STORE_HAS = "h", STORE_CUSTOM_PROTO = "c", STORE_WRAP = "w", STORE_LOOKUP = "l", STORE_FIREWALL = "f", STORE_OPTIMISTIC = "p", STORE_OPTIMISTIC_OWNERS = "t", STORE_PARENT = "u", STORE_DESC = "d";
32
+
33
+ const STORE_SELF_PENDING = Symbol(0);
34
+
35
+ function createStoreProxy(e, t = storeTraps, r) {
36
+ let n;
37
+ if (Array.isArray(e)) {
38
+ n = [];
39
+ n.v = e;
40
+ } else {
41
+ n = {
42
+ v: e
43
+ };
44
+ const t = e?.[$TARGET]?.[STORE_VALUE] ?? e;
45
+ const r = Object.getPrototypeOf(t);
46
+ if (r !== null && r !== Object.prototype) {
47
+ n[STORE_CUSTOM_PROTO] = true;
48
+ }
49
+ }
50
+ r && r(n);
51
+ return n[$PROXY] = new Proxy(n, t);
52
+ }
53
+
54
+ const storeLookup = new WeakMap;
55
+
56
+ // Node records that hold at least one user (non-`$TRACK`) symbol-keyed node.
57
+ // Lets reconcile enumerate symbols only for records that need it (#2851).
58
+ const symbolKeyedRecords = new WeakSet;
59
+
60
+ function wrap(e, t) {
61
+ if (t?.[STORE_WRAP]) {
62
+ const r = t[STORE_WRAP](e, t);
63
+ const n = r[$TARGET];
64
+ if (n && !n[STORE_PARENT] && n !== t) n[STORE_PARENT] = t;
65
+ return r;
66
+ }
67
+ let r = e[$PROXY] || storeLookup.get(e);
68
+ if (!r) {
69
+ storeLookup.set(e, r = createStoreProxy(e));
70
+ if (t) r[$TARGET][STORE_PARENT] = t;
71
+ }
72
+ return r;
73
+ }
74
+
75
+ function isWrappable(e) {
76
+ if (e == null || typeof e !== "object" || Object.isFrozen(e)) return false;
77
+ // Dynamic Node check (kept dynamic so test/SSR overrides of `globalThis.Node`
78
+ // are observed at call time).
79
+ return typeof Node === "undefined" || !(e instanceof Node);
80
+ }
81
+
82
+ let writeOverride = false;
83
+
84
+ function setWriteOverride(e) {
85
+ writeOverride = e;
86
+ }
87
+
88
+ function writeOnly(e) {
89
+ return writeOverride || !!Writing?.has(e);
90
+ }
91
+
92
+ function unwrapStoreValue(e, t, r) {
93
+ const n = e?.[$TARGET] || r?.get(e)?.[$TARGET];
94
+ if (!n) return e;
95
+ const o = n[STORE_OVERRIDE];
96
+ if (!o) return n[STORE_VALUE];
97
+ if (!t) t = new Map;
98
+ if (t.has(e)) return t.get(e);
99
+ const i = n[STORE_VALUE];
100
+ const s = Array.isArray(i);
101
+ const E = s ? [] : Object.create(Object.getPrototypeOf(i));
102
+ t.set(e, E);
103
+ r = n[STORE_LOOKUP] ?? storeLookup;
104
+ for (const e of getStoreKeys(i, o)) {
105
+ if (s && e === "length") continue;
106
+ const n = e in o ? o[e] : i[e];
107
+ if (n !== $DELETED) E[e] = unwrapStoreValue(n, t, r);
108
+ }
109
+ if (s) E.length = o.length ?? i.length;
110
+ return E;
111
+ }
112
+
113
+ function isPrototypePollutionKey(e) {
114
+ return e === "__proto__" || e === "constructor" || e === "prototype";
115
+ }
116
+
117
+ // Own enumerable keys including symbols (`Object.keys` drops symbol-keyed props). #2769
118
+ function ownEnumerableKeys(e) {
119
+ return Reflect.ownKeys(e).filter(t => Object.prototype.propertyIsEnumerable.call(e, t));
120
+ }
121
+
122
+ function ownEnumerableSymbols(e) {
123
+ const t = Object.getOwnPropertySymbols(e);
124
+ const r = [];
125
+ for (let n = 0, o = t.length; n < o; n++) {
126
+ const o = t[n];
127
+ if (Object.prototype.propertyIsEnumerable.call(e, o)) r.push(o);
128
+ }
129
+ return r;
130
+ }
131
+
132
+ // Plain-object variant that keeps Object.keys() as the fast path and only pays
133
+ // descriptor checks for symbols. Do not use this on store proxies: splitting
134
+ // strings/symbols would invoke their ownKeys trap twice.
135
+ function ownEnumerableKeysPlain(e) {
136
+ return Object.keys(e).concat(ownEnumerableSymbols(e));
137
+ }
138
+
139
+ /**
140
+ * Single chokepoint for the store's layered value resolution: returns the
141
+ * override layer (optimistic first, then regular) that shadows `property`, or
142
+ * `undefined` when the base `STORE_VALUE` is authoritative. Every trap must
143
+ * resolve through this — hand-inlining the layer order is how the optimistic
144
+ * layer gets missed (#2850).
145
+ */ function getOverlayLayer(e, t) {
146
+ const r = e[STORE_OPTIMISTIC_OVERRIDE];
147
+ if (r && t in r) return r;
148
+ const n = e[STORE_OVERRIDE];
149
+ if (n && t in n) return n;
150
+ return undefined;
151
+ }
152
+
153
+ /**
154
+ * The value a store leaf's backing signal currently shows to readers: active
155
+ * override, else held pending value, else committed value.
156
+ */ function visibleNodeValue(e) {
157
+ return e.be !== undefined && e.be !== NOT_PENDING ? unwrapOverride(e.be) : e.ge !== NOT_PENDING ? e.ge : e.Ue;
158
+ }
159
+
160
+ function hasOwnStoreProperty(e, t) {
161
+ // Override layers are null-prototype objects, so `in` is an own check.
162
+ const r = getOverlayLayer(e, t);
163
+ if (r) return r[t] !== $DELETED;
164
+ return Object.prototype.hasOwnProperty.call(unwrapStoreValue(e[STORE_VALUE]), t);
165
+ }
166
+
167
+ function hasInheritedAccessor(e, t) {
168
+ let r = Object.getPrototypeOf(e);
169
+ while (r && r !== Object.prototype) {
170
+ const e = Reflect.getOwnPropertyDescriptor(r, t);
171
+ if (e) return !!e.get;
172
+ r = Object.getPrototypeOf(r);
173
+ }
174
+ return false;
175
+ }
176
+
177
+ function getNodes(e, t) {
178
+ let r = e[t];
179
+ if (!r) e[t] = r = Object.create(null);
180
+ return r;
181
+ }
182
+
183
+ function getNode(e, t, r, n, o = isEqual, i) {
184
+ if (t[r]) return t[r];
185
+ const s = signal(n, {
186
+ equals: o,
187
+ unobserved() {
188
+ if (t[r] === s) {
189
+ delete t[r];
190
+ // Drop the symbol-record mark once the last user symbol node is
191
+ // gone, so reconcile's fast path stops probing a now string-only
192
+ // record. Runs only on symbol-node cleanup (cold), never on reconcile.
193
+ if (typeof r === "symbol" && r !== $TRACK && r !== $AFFECTS && symbolKeyedRecords.has(t)) {
194
+ const e = Object.getOwnPropertySymbols(t);
195
+ let r = false;
196
+ for (let t = 0, n = e.length; t < n; t++) {
197
+ if (e[t] !== $TRACK && e[t] !== $AFFECTS) {
198
+ r = true;
199
+ break;
200
+ }
201
+ }
202
+ if (!r) symbolKeyedRecords.delete(t);
203
+ }
204
+ }
205
+ }
206
+ }, e[STORE_FIREWALL]);
207
+ if (e[STORE_OPTIMISTIC]) {
208
+ s.be = NOT_PENDING;
209
+ }
210
+ if (i && r in i) {
211
+ const e = i[r];
212
+ s.Ye = e === undefined ? NO_SNAPSHOT : e;
213
+ snapshotSources?.add(s);
214
+ }
215
+ if (typeof r === "symbol" && r !== $TRACK && r !== $AFFECTS) symbolKeyedRecords.add(t);
216
+ // A node born inside a live mark's identity scope inherits the mark
217
+ // (the declaration walk could only cover nodes that existed then). The
218
+ // record's own $AFFECTS carrier is the mark's channel, never a member.
219
+ if (r !== $AFFECTS && affectsScopes.size) inheritAffectsMarks(s, e[STORE_VALUE], r);
220
+ // Node presence bubbles up the wrap chain (sticky), so reconcile can see
221
+ // "subscribers live somewhere below" through node-less intermediate
222
+ // records — the captured-proxy diff gate (#2902). Amortized O(1): stops at
223
+ // the first already-flagged ancestor.
224
+ let E = e;
225
+ while (E && !E[STORE_DESC]) {
226
+ E[STORE_DESC] = true;
227
+ E = E[STORE_PARENT];
228
+ }
229
+ return t[r] = s;
230
+ }
231
+
232
+ /**
233
+ * Scope inheritance for late-created nodes: every live mark whose identity
234
+ * scope contains the owning record's raw — and, for keyed marks, whose key
235
+ * is this property — gets counted on the new node. Inherited marks live
236
+ * exactly as long as the scope's carrier — the release hook below drops
237
+ * them with the entry.
238
+ */ function inheritAffectsMarks(e, t, r) {
239
+ // A live scope exists, so affects.ts already installed the mark engine.
240
+ for (const [n, o] of affectsScopes) {
241
+ if (n.M && o.scope.has(t) && (o.key === undefined || o.key === r)) {
242
+ GlobalQueue.D(e);
243
+ o.inherited.push(e);
244
+ }
245
+ }
246
+ }
247
+
248
+ const affectsScopes = new Map;
249
+
250
+ /**
251
+ * Snapshots the identities reachable from `value` into `scope`, reading
252
+ * through write overlays (an optimistic row pushed before the declaration is
253
+ * in motion too). Untracked by construction: walks raw values, never traps.
254
+ * Every LIVE node under each reachable record — property leaves, `$TRACK`,
255
+ * and has-nodes — collects into `found`: those are the graph edges existing
256
+ * readers subscribed through, so the mark registers on them directly and
257
+ * rides the status rails to everything derived. (Nodes born later inherit
258
+ * from the scope in `getNode`.)
259
+ */ function walkAffectsScope(e, t, r, n,
260
+ // Cycle guard, fresh per declaration: the scope itself can't serve — a
261
+ // re-declaration on the same carrier unions into a scope that already
262
+ // holds the root, and must still descend to pick up records added since.
263
+ o) {
264
+ if (!isWrappable(e)) return;
265
+ const i = e[$TARGET] || (n ?? storeLookup).get(e)?.[$TARGET];
266
+ const s = i ? i[STORE_VALUE] : e;
267
+ if (o.has(s)) return;
268
+ o.add(s);
269
+ t.scope.add(s);
270
+ let E;
271
+ if (i) {
272
+ collectRecordNodes(i[STORE_NODE], r);
273
+ collectRecordNodes(i[STORE_HAS], r);
274
+ E = mergedOverlay(i);
275
+ // Carry the effective lookup into untouched descendants. Default stores
276
+ // use the global lookup just like snapshotImpl; without it, nested raw
277
+ // objects fall back to string-only enumeration and symbol branches vanish.
278
+ n = i[STORE_LOOKUP] ?? n ?? storeLookup;
279
+ }
280
+ if (Array.isArray(s)) {
281
+ const e = E?.length ?? s.length;
282
+ for (let i = 0; i < e; i++) {
283
+ const e = E && i in E ? E[i] : s[i];
284
+ if (e !== $DELETED) walkAffectsScope(e, t, r, n, o);
285
+ }
286
+ // Arrays can also carry symbol metadata. Enumerate symbols separately to
287
+ // avoid scanning large index lists twice. Outside a store tree, retain the
288
+ // existing index-only walk.
289
+ const O = i || n ? getStoreSymbols(s, E) : [];
290
+ for (let e = 0, i = O.length; e < i; e++) {
291
+ const i = O[e];
292
+ const c = getPropertyDescriptor(s, E, i);
293
+ if (!c || c.get) continue;
294
+ walkAffectsScope(c.value, t, r, n, o);
295
+ }
296
+ } else {
297
+ const e = i || n ? getStoreKeys(s, E) : getKeys(s, E);
298
+ for (let i = 0, O = e.length; i < O; i++) {
299
+ const O = getPropertyDescriptor(s, E, e[i]);
300
+ if (!O || O.get) continue;
301
+ walkAffectsScope(O.value, t, r, n, o);
302
+ }
303
+ }
304
+ }
305
+
306
+ /** All live signal nodes of one record's node map (string + symbol keyed). */ function collectRecordNodes(e, t) {
307
+ if (!e) return;
308
+ for (const r of Object.keys(e)) t.push(e[r]);
309
+ const r = Object.getOwnPropertySymbols(e);
310
+ for (let n = 0, o = r.length; n < o; n++) {
311
+ // Another mark's carrier is its own channel — counting it here would
312
+ // extend that sibling scope's lifetime to this declaration's.
313
+ if (r[n] !== $AFFECTS) t.push(e[r[n]]);
314
+ }
315
+ }
316
+
317
+ /**
318
+ * Witness live mark coverage of a record into the active isPending() probe.
319
+ * Tracked reads don't need this — they go through real signal nodes, which
320
+ * carry marks directly (declaration walk or birth inheritance). This covers
321
+ * UNTRACKED probes reading through records whose nodes never materialized
322
+ * (no observer ever subscribed, so no node exists to carry the mark).
323
+ * Callers guard on `pendingCheckActive`, so plain reads never pay for this.
324
+ *
325
+ * @internal
326
+ */ function witnessAffectsMark(e, t) {
327
+ // Callers guard on `pendingCheckActive`, which only flips inside
328
+ // isPending() — the verdict layer is loaded and its hook installed.
329
+ const r = e[STORE_NODE]?.[$AFFECTS];
330
+ if (r?.M) GlobalQueue.wt(r);
331
+ if (affectsScopes.size) {
332
+ const n = e[STORE_VALUE];
333
+ for (const [e, o] of affectsScopes) {
334
+ if (e !== r && e.M && o.scope.has(n) && (o.key === undefined || o.key === t)) GlobalQueue.wt(e);
335
+ }
336
+ }
337
+ }
338
+
339
+ /**
340
+ * Resolves the store nodes an `affects()` declaration marks: with a `key`,
341
+ * the named slot's leaf node (upserted so the mark has an addressable
342
+ * carrier); without, the record's $AFFECTS carrier plus every LIVE node in
343
+ * its subtree (the edges existing readers subscribed through), with the
344
+ * subtree's identities snapshotted into the mark's scope so nodes created
345
+ * during the window — and untracked probes over captured proxies — resolve
346
+ * against it (#2882).
347
+ *
348
+ * @internal
349
+ */ function getStoreAffectsNodes(e, t) {
350
+ const r = getNodes(e, STORE_NODE);
351
+ GlobalQueue.T ||= e => {
352
+ const t = affectsScopes.get(e);
353
+ if (!t) return;
354
+ affectsScopes.delete(e);
355
+ for (let e = 0; e < t.inherited.length; e++) GlobalQueue.F(t.inherited[e]);
356
+ };
357
+ if (t === undefined) {
358
+ const t = getNode(e, r, $AFFECTS, undefined, false);
359
+ let n = affectsScopes.get(t);
360
+ if (!n) affectsScopes.set(t, n = {
361
+ scope: new Set,
362
+ inherited: []
363
+ });
364
+ const o = [ t ];
365
+ walkAffectsScope(e[$PROXY], n, o, e[STORE_LOOKUP], new Set);
366
+ return o;
367
+ }
368
+ let n = r[t];
369
+ if (!n) {
370
+ const o = getOverlayLayer(e, t);
371
+ const i = o ? o[t] : e[STORE_VALUE][t];
372
+ n = upsertStoreNode(e, r, t, i === $DELETED ? undefined : i, e[STORE_SNAPSHOT_PROPS]);
373
+ }
374
+ // Keyed marks resolve by identity too (#2904): another store family's
375
+ // proxy can share this record's raw (a derived store swaps its backing to
376
+ // the source's raw when its projection lands), and reads through it never
377
+ // touch this target's node map. Scope is exactly the owning record's raw,
378
+ // narrowed to this key for witness and birth inheritance.
379
+ let o = affectsScopes.get(n);
380
+ if (!o) affectsScopes.set(n, o = {
381
+ scope: new Set,
382
+ inherited: [],
383
+ key: t
384
+ });
385
+ o.scope.add(e[STORE_VALUE]);
386
+ return [ n ];
387
+ }
388
+
389
+ function trackSelf(e, t = $TRACK) {
390
+ if (!getObserver()) return;
391
+ read(getNode(e, getNodes(e, STORE_NODE), t, undefined, false));
392
+ // Store-in-store: structural notifications (reconcile, notifySelf) land on
393
+ // the wrapped source's own self-node, never on this wrapper view's. Chain
394
+ // the read through so enumeration/$TRACK on the wrapper observes them
395
+ // (#2864). Property reads already chain naturally via the inner get trap.
396
+ // An override layer on the view is a hold (A17) — the shown structure is
397
+ // the overlay's, so don't subscribe through it; clearing the layer notifies
398
+ // this view's own self-node and the re-run re-establishes the chain.
399
+ if (t === $TRACK && !e[STORE_OVERRIDE] && !e[STORE_OPTIMISTIC_OVERRIDE] && e[STORE_VALUE][$TARGET]) e[STORE_VALUE][$TRACK];
400
+ }
401
+
402
+ function notifySelf(e) {
403
+ const t = e[STORE_NODE]?.[$TRACK];
404
+ t && setSignal(t, e[STORE_OPTIMISTIC] && !projectionWriteActive ? STORE_SELF_PENDING : undefined);
405
+ }
406
+
407
+ /**
408
+ * The write overlay a walk must read through: optimistic writes shadow
409
+ * regular pending writes, the same resolution order as every proxy trap and
410
+ * `reconcile` (#2850). Merging allocates only in the rare both-present case
411
+ * (a derived optimistic store with an in-flight projection commit).
412
+ */ function mergedOverlay(e) {
413
+ const t = e[STORE_OVERRIDE];
414
+ const r = e[STORE_OPTIMISTIC_OVERRIDE];
415
+ return t && r ? {
416
+ ...t,
417
+ ...r
418
+ } : r ?? t;
419
+ }
420
+
421
+ function getKeysImpl(e, t, r, n) {
422
+ // Plain objects can't trigger proxy traps — only pay for the untrack
423
+ // closure when the source is itself a wrapped store (store-in-store).
424
+ 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);
425
+ return t ? mergeOverrideKeys(o, t) : o;
426
+ }
427
+
428
+ function getKeys(e, t, r = true) {
429
+ return getKeysImpl(e, t, r, false);
430
+ }
431
+
432
+ function getStoreKeys(e, t) {
433
+ return getKeysImpl(e, t, true, true);
434
+ }
435
+
436
+ function getStoreSymbols(e, t) {
437
+ const r = e[$TARGET] ? untrack(() => ownEnumerableSymbols(e)) : ownEnumerableSymbols(e);
438
+ return t ? mergeOverrideKeys(r, t, true) : r;
439
+ }
440
+
441
+ // Shared override-layer merge for key enumeration: adds live override keys,
442
+ // drops $DELETED ones. `symbolsOnly` scopes the override scan for the
443
+ // array-metadata passes.
444
+ function mergeOverrideKeys(e, t, r) {
445
+ const n = new Set(e);
446
+ const o = r ? Object.getOwnPropertySymbols(t) : Reflect.ownKeys(t);
447
+ for (const e of o) {
448
+ if (t[e] !== $DELETED) n.add(e); else n.delete(e);
449
+ }
450
+ return Array.from(n);
451
+ }
452
+
453
+ function getPropertyDescriptor(e, t, r) {
454
+ if (t && r in t) {
455
+ if (t[r] === $DELETED) return void 0;
456
+ const n = Reflect.getOwnPropertyDescriptor(t, r);
457
+ if (n?.get || n?.set) return n;
458
+ // Plain writes live in the override while the source keeps its old value.
459
+ // Preserve the source descriptor flags, but report the current override
460
+ // value. Source accessors cannot be patched with a value, and inherited
461
+ // properties have no source own descriptor, so those keep their descriptor.
462
+ const o = Reflect.getOwnPropertyDescriptor(e, r);
463
+ if (!o) return n;
464
+ if (o.get || o.set) return o;
465
+ // Reflect returns a fresh descriptor, so patching in place is safe and
466
+ // avoids an allocation on Object.keys/spread over written stores.
467
+ o.value = t[r];
468
+ return o;
469
+ }
470
+ return Reflect.getOwnPropertyDescriptor(e, r);
471
+ }
472
+
473
+ function prepareStoreWrite(e, t, r) {
474
+ if (e[STORE_OPTIMISTIC]) {
475
+ const t = e[STORE_FIREWALL];
476
+ if (t?.ve) {
477
+ globalQueue.initTransition(t.ve);
478
+ }
479
+ }
480
+ const n = e[STORE_VALUE];
481
+ const o = n[r];
482
+ if (snapshotCaptureActive && typeof r !== "symbol" && !((e[STORE_FIREWALL]?.i ?? 0) & STATUS_PENDING)) {
483
+ if (!e[STORE_SNAPSHOT_PROPS]) {
484
+ e[STORE_SNAPSHOT_PROPS] = Object.create(null);
485
+ snapshotSources?.add(e);
486
+ }
487
+ if (!(r in e[STORE_SNAPSHOT_PROPS])) {
488
+ e[STORE_SNAPSHOT_PROPS][r] = o;
489
+ }
490
+ }
491
+ const i = e[STORE_OPTIMISTIC] && !projectionWriteActive;
492
+ const s = i ? STORE_OPTIMISTIC_OVERRIDE : STORE_OVERRIDE;
493
+ return {
494
+ base: o,
495
+ overrideKey: s,
496
+ state: n
497
+ };
498
+ }
499
+
500
+ /**
501
+ * Registers the store for transition reversion. Called only once a write is
502
+ * known to be effective — ineffective writes (same value, delete of an absent
503
+ * property) are no-ops and must not entangle the store. Optimistic writes are
504
+ * verdict-inert (question-scoped pending model): no mask is armed — the write
505
+ * neither pends its own slot nor silences anyone else's.
506
+ */ function armOptimisticStoreWrite(e, t) {
507
+ // STORE_OPTIMISTIC is only set by createOptimisticStore, which installs the
508
+ // optimistic engine before wrapping.
509
+ if (e[STORE_OPTIMISTIC] && !projectionWriteActive) {
510
+ GlobalQueue.mn(t);
511
+ }
512
+ }
513
+
514
+ /**
515
+ * Records which transition owns an optimistic layer entry (#2899), so a
516
+ * settling action only consumes its own keys — the layer is store-wide, but
517
+ * concurrent actions writing disjoint keys must revert independently, exactly
518
+ * like optimistic signal nodes do via the transition's _optimisticNodes.
519
+ * `activeTransition` is the write's transaction (action() opens it before the
520
+ * body runs); null marks an ambient write that clears at plain flush end.
521
+ * Same-key writes across actions keep last-write-wins layer semantics.
522
+ */ function stampOptimisticOwner(e, t, r) {
523
+ if (t === STORE_OPTIMISTIC_OVERRIDE) (e[STORE_OPTIMISTIC_OWNERS] ??= Object.create(null))[r] = activeTransition;
524
+ }
525
+
526
+ function upsertStoreNode(e, t, r, n, o) {
527
+ if (t[r]) return t[r];
528
+ const i = isWrappable(n) ? wrap(n, e) : n;
529
+ const s = getNode(e, t, r, i, isEqual, o);
530
+ registerTransientStoreNode(s);
531
+ return s;
532
+ }
533
+
534
+ function notifyStoreProperty(e, t, r, n, o, i) {
535
+ // Cold writes upsert a transient pending node so untracked reads batch like signals.
536
+ // Skip for projection writes (different commit semantics) and for optimistic stores
537
+ // (whose whole purpose is immediate visibility via STORE_OPTIMISTIC_OVERRIDE).
538
+ const s = projectionWriteActive || e[STORE_OPTIMISTIC];
539
+ const E = r !== "delete";
540
+ const O = e[STORE_HAS]?.[t];
541
+ if (O) {
542
+ setSignal(O, E);
543
+ } else if (!s && r !== "invalidate" && i !== E) {
544
+ const r = upsertStoreNode(e, getNodes(e, STORE_HAS), t, i);
545
+ setSignal(r, E);
546
+ }
547
+ const c = getNodes(e, STORE_NODE);
548
+ if (r === "set") {
549
+ if (c[t]) {
550
+ setSignal(c[t], () => isWrappable(n) ? wrap(n, e) : n);
551
+ } else if (!s) {
552
+ const r = upsertStoreNode(e, c, t, o, e[STORE_SNAPSHOT_PROPS]);
553
+ setSignal(r, () => isWrappable(n) ? wrap(n, e) : n);
554
+ }
555
+ } else if (r === "invalidate") {
556
+ if (c[t]) {
557
+ setSignal(c[t], {});
558
+ delete c[t];
559
+ }
560
+ } else {
561
+ if (c[t]) {
562
+ setSignal(c[t], undefined);
563
+ } else if (!s) {
564
+ const r = upsertStoreNode(e, c, t, o, e[STORE_SNAPSHOT_PROPS]);
565
+ setSignal(r, undefined);
566
+ }
567
+ }
568
+ notifySelf(e);
569
+ }
570
+
571
+ let Writing = null;
572
+
573
+ /**
574
+ * A derived store's seed is a draft for the derive function, never an
575
+ * observable value (#2897): until the firewall first resolves there is
576
+ * nothing to read, so every consumer path throws NotReady — tracked reads
577
+ * through their node (core read()), and the untracked fall-throughs in the
578
+ * traps through this guard. Returning the seed leaked it; returning
579
+ * `undefined` would break non-nullable types. Callers exempt the firewall
580
+ * itself (the derive function works its own draft while uninitialized).
581
+ */ function throwIfUninitialized(e) {
582
+ const t = e[STORE_FIREWALL];
583
+ if (t && t.i & STATUS_UNINITIALIZED) throw t.k ?? new NotReadyError(t);
584
+ }
585
+
586
+ const storeTraps = {
587
+ get(e, t, r) {
588
+ if (t === $TARGET) return e;
589
+ if (t === $PROXY) return r;
590
+ if (t === $REFRESH) return e[STORE_FIREWALL];
591
+ if (pendingCheckActive) witnessAffectsMark(e, t);
592
+ if (t === $TRACK) {
593
+ trackSelf(e);
594
+ return r;
595
+ }
596
+ const n = getObserver() === e[STORE_FIREWALL];
597
+ const o = getNodes(e, STORE_NODE);
598
+ const i = n ? undefined : o[t];
599
+ const s = e[STORE_VALUE];
600
+ if (!i && !e[STORE_OVERRIDE] && !e[STORE_OPTIMISTIC_OVERRIDE] && !e[STORE_CUSTOM_PROTO] && !e[STORE_OPTIMISTIC] && !e[STORE_SNAPSHOT_PROPS] && !s[$TARGET] && !(t in s) && getObserver() && !n && !writeOnly(r)) {
601
+ return read(getNode(e, o, t, undefined));
602
+ }
603
+ const E = getOverlayLayer(e, t);
604
+ const O = !!E;
605
+ const c = !!e[STORE_VALUE][$TARGET];
606
+ const S = E ?? e[STORE_VALUE];
607
+ if (!i) {
608
+ const n = Object.getOwnPropertyDescriptor(S, t);
609
+ if (n && n.get) return n.get.call(r);
610
+ if (!n && !O && e[STORE_CUSTOM_PROTO]) {
611
+ const e = unwrapStoreValue(S);
612
+ if (hasInheritedAccessor(e, t)) {
613
+ return Reflect.get(S, t, r);
614
+ }
615
+ }
616
+ }
617
+ if (writeOnly(r)) {
618
+ if (isPrototypePollutionKey(t) && !hasOwnStoreProperty(e, t)) return undefined;
619
+ let r = i && (O || !c) ? visibleNodeValue(i) : S[t];
620
+ r === $DELETED && (r = undefined);
621
+ if (!isWrappable(r)) return r;
622
+ const n = wrap(r, e);
623
+ Writing?.add(n);
624
+ return n;
625
+ }
626
+ let f = i ? O || !c ? read(o[t]) : (read(o[t]), S[t]) : S[t];
627
+ f === $DELETED && (f = undefined);
628
+ if (!i) {
629
+ if (!O && typeof f === "function" && !Object.prototype.hasOwnProperty.call(S, t)) {
630
+ let t;
631
+ return !Array.isArray(e[STORE_VALUE]) && (t = Object.getPrototypeOf(e[STORE_VALUE])) && t !== Object.prototype ? f.bind(S) : f;
632
+ } else if (getObserver() && !n) {
633
+ return read(getNode(e, o, t, isWrappable(f) ? wrap(f, e) : f, isEqual, e[STORE_SNAPSHOT_PROPS]));
634
+ }
635
+ }
636
+ // Untracked fall-through (tracked reads already threw via their node in
637
+ // read(); the dev strictRead error above wins first for memo parity).
638
+ if (!n) throwIfUninitialized(e);
639
+ return isWrappable(f) ? wrap(f, e) : f;
640
+ },
641
+ has(e, t) {
642
+ if (t === $PROXY || t === $TRACK || t === "__proto__") return true;
643
+ if (pendingCheckActive) witnessAffectsMark(e, t);
644
+ const r = getOverlayLayer(e, t);
645
+ const n = r ? r[t] !== $DELETED : t in e[STORE_VALUE];
646
+ if (writeOnly(e[$PROXY]) || getObserver() === e[STORE_FIREWALL]) return n;
647
+ const o = getNodes(e, STORE_HAS);
648
+ // If a has-node already exists, it carries the batched presence — `read()`
649
+ // returns `_value` (committed) for untracked reads and the pending value for
650
+ // downstream computes. This keeps `in` consistent with value reads.
651
+ if (o[t]) return read(o[t]);
652
+ // No node yet: `has` reflects committed presence (no pending write could change
653
+ // it without first upserting a has-node at the write site). Create + read only
654
+ // when tracking; leave untracked reads node-free.
655
+ if (getObserver()) {
656
+ return read(getNode(e, o, t, n));
657
+ }
658
+ throwIfUninitialized(e);
659
+ return n;
660
+ },
661
+ set(e, t, r) {
662
+ if (t === "__proto__") return true;
663
+ const n = e[$PROXY];
664
+ if (writeOnly(n)) {
665
+ untrack(() => {
666
+ const {base: o, overrideKey: i, state: s} = prepareStoreWrite(e, n, t);
667
+ const E = getOverlayLayer(e, t);
668
+ const O = E ? E[t] : o;
669
+ const c = E ? E[t] !== $DELETED : t in e[STORE_VALUE];
670
+ const S = unwrapStoreValue(r);
671
+ // Symbol-keyed writes on arrays are metadata, not index writes — never run
672
+ // them through the numeric index/length machinery (`parseInt` on a symbol
673
+ // throws). #2769
674
+ const f = typeof t === "string" ? Number(t) : -1;
675
+ const T = Array.isArray(s) && Number.isInteger(f) && f >= 0 && f < 4294967295 && String(f) === t;
676
+ const R = T ? f + 1 : 0;
677
+ const u = T && (getOverlayLayer(e, "length") ?? s).length;
678
+ const l = T && R > u ? R : undefined;
679
+ if (O === S && l === undefined) return true;
680
+ armOptimisticStoreWrite(e, n);
681
+ if (S !== undefined && S === o && l === undefined) {
682
+ delete e[i]?.[t];
683
+ if (i === STORE_OPTIMISTIC_OVERRIDE) delete e[STORE_OPTIMISTIC_OWNERS]?.[t];
684
+ } else {
685
+ const r = e[i] || (e[i] = Object.create(null));
686
+ r[t] = S;
687
+ stampOptimisticOwner(e, i, t);
688
+ if (l !== undefined) {
689
+ r.length = l;
690
+ stampOptimisticOwner(e, i, "length");
691
+ }
692
+ }
693
+ notifyStoreProperty(e, t, "set", S, O, c);
694
+ // Shrinking an array's length must remove the truncated indices, otherwise
695
+ // they leak through `has`, `ownKeys`, and (tracked) index reads from the
696
+ // underlying value. Mark each as deleted and notify so reactive reads update. #2768
697
+ if (Array.isArray(s) && t === "length" && typeof S === "number" && typeof O === "number" && S < O) {
698
+ const t = e[i] || (e[i] = Object.create(null));
699
+ for (let r = S; r < O; r++) {
700
+ if (t[r] === $DELETED) continue;
701
+ const n = r in t ? t[r] : s[r];
702
+ if (!(r in t) && !(r in s)) continue;
703
+ t[r] = $DELETED;
704
+ stampOptimisticOwner(e, i, r);
705
+ notifyStoreProperty(e, r, "delete", undefined, n, true);
706
+ }
707
+ }
708
+ // notify length change
709
+ if (Array.isArray(s) && t !== "length" && l !== undefined) {
710
+ const t = getNodes(e, STORE_NODE);
711
+ if (t.length) {
712
+ setSignal(t.length, l);
713
+ } else if (!projectionWriteActive && !e[STORE_OPTIMISTIC]) {
714
+ const r = upsertStoreNode(e, t, "length", u, e[STORE_SNAPSHOT_PROPS]);
715
+ setSignal(r, l);
716
+ }
717
+ }
718
+ if (false) ;
719
+ });
720
+ }
721
+ return true;
722
+ },
723
+ defineProperty(e, t, r) {
724
+ if (t === "__proto__") return true;
725
+ const n = e[$PROXY];
726
+ if (writeOnly(n)) {
727
+ untrack(() => {
728
+ const {base: o, overrideKey: i} = prepareStoreWrite(e, n, t);
729
+ armOptimisticStoreWrite(e, n);
730
+ const s = "value" in r ? {
731
+ ...r,
732
+ value: unwrapStoreValue(r.value)
733
+ } : r;
734
+ Object.defineProperty(e[i] || (e[i] = Object.create(null)), t, s);
735
+ stampOptimisticOwner(e, i, t);
736
+ notifyStoreProperty(e, t, "invalidate");
737
+ if (false) ;
738
+ });
739
+ }
740
+ return true;
741
+ },
742
+ deleteProperty(e, t) {
743
+ if (t === "__proto__") return true;
744
+ // Check both optimistic and regular override for existing $DELETED
745
+ const r = e[STORE_OPTIMISTIC_OVERRIDE]?.[t] === $DELETED;
746
+ const n = e[STORE_OVERRIDE]?.[t] === $DELETED;
747
+ if (writeOnly(e[$PROXY]) && !r && !n) {
748
+ untrack(() => {
749
+ const r = e[STORE_OPTIMISTIC] && !projectionWriteActive;
750
+ const n = r ? STORE_OPTIMISTIC_OVERRIDE : STORE_OVERRIDE;
751
+ const o = getOverlayLayer(e, t);
752
+ const i = o ? o[t] : e[STORE_VALUE][t];
753
+ if (t in e[STORE_VALUE] || e[STORE_OVERRIDE] && t in e[STORE_OVERRIDE]) {
754
+ armOptimisticStoreWrite(e, e[$PROXY]);
755
+ (e[n] || (e[n] = Object.create(null)))[t] = $DELETED;
756
+ stampOptimisticOwner(e, n, t);
757
+ } else if (e[n] && t in e[n]) {
758
+ armOptimisticStoreWrite(e, e[$PROXY]);
759
+ delete e[n][t];
760
+ if (n === STORE_OPTIMISTIC_OVERRIDE) delete e[STORE_OPTIMISTIC_OWNERS]?.[t];
761
+ } else return true;
762
+ notifyStoreProperty(e, t, "delete", undefined, i, true);
763
+ });
764
+ }
765
+ return true;
766
+ },
767
+ ownKeys(e) {
768
+ if (pendingCheckActive) witnessAffectsMark(e);
769
+ if (getObserver() !== e[STORE_FIREWALL]) {
770
+ trackSelf(e);
771
+ // trackSelf no-ops untracked, so enumeration of an unresolved derived
772
+ // store would otherwise leak the seed's structure (#2897). The write
773
+ // path is exempt (like the get/has traps' writeOnly early returns):
774
+ // the first landing's reconcile enumerates the store while
775
+ // STATUS_UNINITIALIZED is still set — it IS the initialization.
776
+ if (!getObserver() && !writeOnly(e[$PROXY])) throwIfUninitialized(e);
777
+ }
778
+ // Merge optimistic override with regular override for key enumeration
779
+ let t = getKeys(e[STORE_VALUE], e[STORE_OVERRIDE], false);
780
+ if (e[STORE_OPTIMISTIC_OVERRIDE]) {
781
+ const r = new Set(t);
782
+ for (const t of Reflect.ownKeys(e[STORE_OPTIMISTIC_OVERRIDE])) {
783
+ if (e[STORE_OPTIMISTIC_OVERRIDE][t] !== $DELETED) r.add(t); else r.delete(t);
784
+ }
785
+ t = Array.from(r);
786
+ }
787
+ return t;
788
+ },
789
+ getOwnPropertyDescriptor(e, t) {
790
+ if (t === $PROXY) return {
791
+ value: e[$PROXY],
792
+ writable: true,
793
+ configurable: true
794
+ };
795
+ // Check optimistic override first, but use base descriptor structure for compatibility
796
+ if (e[STORE_OPTIMISTIC_OVERRIDE] && t in e[STORE_OPTIMISTIC_OVERRIDE]) {
797
+ if (e[STORE_OPTIMISTIC_OVERRIDE][t] === $DELETED) return undefined;
798
+ const r = Reflect.getOwnPropertyDescriptor(e[STORE_OPTIMISTIC_OVERRIDE], t);
799
+ if (r?.get || r?.set || !(t in e[STORE_VALUE])) return r;
800
+ // Get base descriptor structure, override just the value
801
+ const n = getPropertyDescriptor(e[STORE_VALUE], e[STORE_OVERRIDE], t);
802
+ if (n) {
803
+ const r = Reflect.getOwnPropertyDescriptor(e, t);
804
+ const o = !r || r.configurable ? true : n.configurable;
805
+ return {
806
+ ...n,
807
+ configurable: o,
808
+ value: e[STORE_OPTIMISTIC_OVERRIDE][t]
809
+ };
810
+ }
811
+ return {
812
+ value: e[STORE_OPTIMISTIC_OVERRIDE][t],
813
+ writable: true,
814
+ enumerable: true,
815
+ configurable: true
816
+ };
817
+ }
818
+ const r = getPropertyDescriptor(e[STORE_VALUE], e[STORE_OVERRIDE], t);
819
+ // The proxy target is an internal node object, not the original source. When the
820
+ // source has a non-configurable property that does not also exist as non-configurable
821
+ // on the proxy target, the proxy invariant is violated: the engine requires that a
822
+ // property reported as non-configurable must actually be non-configurable on the
823
+ // target object. Override configurable to true only in that case.
824
+ if (r && !r.configurable) {
825
+ const n = Reflect.getOwnPropertyDescriptor(e, t);
826
+ if (!n || n.configurable) return {
827
+ ...r,
828
+ configurable: true
829
+ };
830
+ }
831
+ return r;
832
+ },
833
+ getPrototypeOf(e) {
834
+ return Object.getPrototypeOf(e[STORE_VALUE]);
835
+ }
836
+ };
837
+
838
+ function storeSetter(e, t) {
839
+ const r = Writing;
840
+ Writing = new Set;
841
+ Writing.add(e);
842
+ try {
843
+ const r = t(e);
844
+ if (r !== e && r !== undefined) {
845
+ if (Array.isArray(r)) {
846
+ for (let t = 0, n = r.length; t < n; t++) e[t] = r[t];
847
+ e.length = r.length;
848
+ } else {
849
+ const t = new Set([ ...ownEnumerableKeys(e), ...ownEnumerableKeys(r) ]);
850
+ t.forEach(t => {
851
+ if (t in r) e[t] = r[t]; else delete e[t];
852
+ });
853
+ }
854
+ }
855
+ } finally {
856
+ Writing.clear();
857
+ Writing = r;
858
+ }
859
+ }
860
+
861
+ function createStore(e, t, r) {
862
+ const n = typeof e === "function", o = n ? createProjectionInternal(e, t, r).store : wrap(e);
863
+ return [ o, n ? e => {
864
+ // Mark the projection as manually written before notifying property nodes.
865
+ suppressComputedRecompute(o[$REFRESH]);
866
+ storeSetter(o, e);
867
+ } : e => storeSetter(o, e) ];
868
+ }
869
+
870
+ export { $AFFECTS, $DELETED, $PROXY, $TARGET, $TRACK, STORE_CUSTOM_PROTO, STORE_DESC, STORE_FIREWALL, STORE_HAS, STORE_LOOKUP, STORE_NODE, STORE_OPTIMISTIC, STORE_OPTIMISTIC_OVERRIDE, STORE_OPTIMISTIC_OWNERS, STORE_OVERRIDE, STORE_PARENT, STORE_VALUE, STORE_WRAP, createStore, createStoreProxy, getKeys, getOverlayLayer, getPropertyDescriptor, getStoreAffectsNodes, getStoreKeys, getStoreSymbols, isWrappable, mergedOverlay, notifySelf, ownEnumerableKeys, setWriteOverride, storeLookup, storeSetter, storeTraps, symbolKeyedRecords, trackSelf, visibleNodeValue, witnessAffectsMark, wrap };