@solidjs/signals 2.0.0-rc.6 → 2.0.0-rc.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/dist/dev-shared.js +5243 -0
  2. package/dist/dev.attribution.js +2333 -0
  3. package/dist/dev.js +1758 -6621
  4. package/dist/observe/affects.js +127 -0
  5. package/dist/observe/attribution.js +1 -0
  6. package/dist/observe/boundaries.js +586 -0
  7. package/dist/observe/core/action.js +167 -0
  8. package/dist/observe/core/async.js +736 -0
  9. package/dist/observe/core/attribution-hooks.js +60 -0
  10. package/dist/observe/core/attribution.js +2318 -0
  11. package/dist/{types-cjs/core/constants.d.cts → observe/core/constants.js} +135 -71
  12. package/dist/{types-cjs/core/context.d.cts → observe/core/context.js} +37 -12
  13. package/dist/observe/core/core.js +1289 -0
  14. package/dist/observe/core/dev.js +232 -0
  15. package/dist/observe/core/effect.js +179 -0
  16. package/dist/observe/core/error.js +80 -0
  17. package/dist/observe/core/external.js +98 -0
  18. package/dist/observe/core/graph.js +155 -0
  19. package/dist/observe/core/heap.js +147 -0
  20. package/dist/observe/core/invariants.js +43 -0
  21. package/dist/observe/core/lanes.js +168 -0
  22. package/dist/observe/core/optimistic.js +438 -0
  23. package/dist/observe/core/owner.js +308 -0
  24. package/dist/observe/core/scheduler.js +1190 -0
  25. package/dist/observe/core/verdict.js +551 -0
  26. package/dist/observe/index.js +55 -0
  27. package/dist/observe/map.js +482 -0
  28. package/dist/{types-cjs/signals.d.cts → observe/signals.js} +305 -317
  29. package/dist/observe/store/index.js +38 -0
  30. package/dist/observe/store/next/optimistic.js +651 -0
  31. package/dist/observe/store/next/projection.js +242 -0
  32. package/dist/observe/store/next/reconcile.js +373 -0
  33. package/dist/observe/store/next/store.js +2213 -0
  34. package/dist/observe/store/next/target.js +51 -0
  35. package/dist/observe/store/store.js +323 -0
  36. package/dist/observe/store/storePath.js +103 -0
  37. package/dist/observe/store/utils.js +210 -0
  38. package/dist/prod/attribution.js +32 -0
  39. package/dist/prod/boundaries.js +3 -1
  40. package/dist/prod/core/action.js +52 -32
  41. package/dist/prod/core/async.js +177 -128
  42. package/dist/prod/core/attribution-hooks.js +3 -0
  43. package/dist/prod/core/constants.js +32 -1
  44. package/dist/prod/core/context.js +10 -16
  45. package/dist/prod/core/core.js +505 -286
  46. package/dist/prod/core/dev.js +2 -0
  47. package/dist/prod/core/effect.js +72 -43
  48. package/dist/prod/core/external.js +2 -2
  49. package/dist/prod/core/graph.js +40 -36
  50. package/dist/prod/core/heap.js +50 -51
  51. package/dist/prod/core/lanes.js +43 -22
  52. package/dist/prod/core/optimistic.js +224 -80
  53. package/dist/prod/core/owner.js +43 -39
  54. package/dist/prod/core/scheduler.js +347 -232
  55. package/dist/prod/core/verdict.js +71 -74
  56. package/dist/prod/index.js +9 -5
  57. package/dist/prod/map.js +311 -150
  58. package/dist/prod/signals.js +52 -38
  59. package/dist/prod/store/next/optimistic.js +127 -131
  60. package/dist/prod/store/next/projection.js +3 -3
  61. package/dist/prod/store/next/reconcile.js +149 -294
  62. package/dist/prod/store/next/store.js +694 -380
  63. package/dist/prod/store/next/target.js +32 -10
  64. package/dist/prod/store/store.js +12 -14
  65. package/dist/prod/store/utils.js +36 -27
  66. package/dist/types/attribution.d.ts +15 -0
  67. package/dist/types/attribution.prod.d.ts +13 -0
  68. package/dist/types/core/async.d.ts +1 -1
  69. package/dist/types/core/attribution-hooks.d.ts +183 -6
  70. package/dist/types/core/attribution.d.ts +435 -24
  71. package/dist/types/core/constants.d.ts +31 -0
  72. package/dist/types/core/core.d.ts +19 -3
  73. package/dist/types/core/dev.d.ts +165 -26
  74. package/dist/types/core/effect.d.ts +8 -1
  75. package/dist/types/core/heap.d.ts +5 -3
  76. package/dist/types/core/index.d.ts +2 -1
  77. package/dist/types/core/invariants.d.ts +1 -1
  78. package/dist/types/core/lanes.d.ts +17 -0
  79. package/dist/types/core/scheduler.d.ts +69 -4
  80. package/dist/types/core/types.d.ts +29 -9
  81. package/dist/types/index.d.ts +9 -2
  82. package/dist/types/map.d.ts +2 -0
  83. package/dist/types/signals.d.ts +10 -0
  84. package/dist/types/store/index.d.ts +4 -6
  85. package/dist/types/store/next/optimistic.d.ts +4 -2
  86. package/dist/types/store/next/reconcile.d.ts +5 -12
  87. package/dist/types/store/next/store.d.ts +8 -9
  88. package/dist/types/store/next/target.d.ts +56 -55
  89. package/dist/types/store/store.d.ts +14 -9
  90. package/dist/types/store/utils.d.ts +7 -0
  91. package/package.json +21 -16
  92. package/dist/node.cjs +0 -11121
  93. package/dist/prod/store/next/patch-hooks.js +0 -13
  94. package/dist/prod/store/next/patch.js +0 -614
  95. package/dist/types/store/next/patch-hooks.d.ts +0 -41
  96. package/dist/types/store/next/patch.d.ts +0 -91
  97. package/dist/types-cjs/affects.d.cts +0 -47
  98. package/dist/types-cjs/boundaries.d.cts +0 -175
  99. package/dist/types-cjs/core/action.d.cts +0 -64
  100. package/dist/types-cjs/core/async.d.cts +0 -23
  101. package/dist/types-cjs/core/attribution-hooks.d.cts +0 -63
  102. package/dist/types-cjs/core/attribution.d.cts +0 -239
  103. package/dist/types-cjs/core/core.d.cts +0 -176
  104. package/dist/types-cjs/core/dev.d.cts +0 -95
  105. package/dist/types-cjs/core/effect.d.cts +0 -30
  106. package/dist/types-cjs/core/error.d.cts +0 -56
  107. package/dist/types-cjs/core/external.d.cts +0 -15
  108. package/dist/types-cjs/core/graph.d.cts +0 -28
  109. package/dist/types-cjs/core/heap.d.cts +0 -22
  110. package/dist/types-cjs/core/index.d.cts +0 -13
  111. package/dist/types-cjs/core/invariants.d.cts +0 -59
  112. package/dist/types-cjs/core/lanes.d.cts +0 -44
  113. package/dist/types-cjs/core/optimistic.d.cts +0 -6
  114. package/dist/types-cjs/core/owner.d.cts +0 -124
  115. package/dist/types-cjs/core/scheduler.d.cts +0 -231
  116. package/dist/types-cjs/core/types.d.cts +0 -204
  117. package/dist/types-cjs/core/verdict.d.cts +0 -2
  118. package/dist/types-cjs/index.d.cts +0 -10
  119. package/dist/types-cjs/map.d.cts +0 -69
  120. package/dist/types-cjs/package.json +0 -3
  121. package/dist/types-cjs/store/index.d.cts +0 -21
  122. package/dist/types-cjs/store/next/optimistic.d.cts +0 -23
  123. package/dist/types-cjs/store/next/patch-hooks.d.cts +0 -41
  124. package/dist/types-cjs/store/next/patch.d.cts +0 -91
  125. package/dist/types-cjs/store/next/projection.d.cts +0 -8
  126. package/dist/types-cjs/store/next/reconcile.d.cts +0 -17
  127. package/dist/types-cjs/store/next/store.d.cts +0 -127
  128. package/dist/types-cjs/store/next/target.d.cts +0 -192
  129. package/dist/types-cjs/store/store.d.cts +0 -138
  130. package/dist/types-cjs/store/storePath.d.cts +0 -58
  131. package/dist/types-cjs/store/utils.d.cts +0 -74
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Ownership stamp (#3360): every backing the store ALLOCATES (CoW clones,
3
+ * privatized committed backings) carries its owning target under this
4
+ * enumerable symbol. One property write replaces the two weak-collection
5
+ * registrations (ownership set + raw→target map) a fresh object used to pay
6
+ * per draft — V8's identity-hash + ephemeron cost dominated the one-key
7
+ * write floor. Enumerable so a spread copy (the plain-data clone path) stays
8
+ * on the fast path and carries the stamp along.
9
+ *
10
+ * Owned backings are never user-reachable (`snapshot` copies them, the traps
11
+ * hide the key), so every raw key walk in the store must skip `$OWNER`, and
12
+ * ownership is answered by `isOwned` — a user object never carries it.
13
+ * Overlay drafts (`Object.create(v)` over an owned `v`) inherit the stamp.
14
+ */
15
+ const $OWNER = Symbol(0);
16
+
17
+ /** raw → target for UNOWNED backings (user-ingested, adopted); owned
18
+ * backings resolve through their `$OWNER` stamp. Boundary mechanism (O8). */ const storeNextLookup = new WeakMap;
19
+
20
+ /** A backing the store allocated and may mutate in place. */ function isOwned(e) {
21
+ return e[$OWNER] !== undefined;
22
+ }
23
+
24
+ /** raw → target within a family (`null` = plain stores / the global map).
25
+ * The stamp answers for backings owned by a target OF THAT FAMILY; anything
26
+ * else (user objects, adoptees, another family's backings the family
27
+ * re-registered for its own wrapper) resolves through the family's map. */ function lookupTarget(e, o) {
28
+ const t = e[$OWNER];
29
+ return t !== undefined && t.fam === o ? t : (o?.map ?? storeNextLookup).get(e);
30
+ }
31
+
32
+ function devAssertNeverUserMutation(e) {
33
+ return;
34
+ }
35
+
36
+ let optHooks = null;
37
+
38
+ function setOptHooks(e) {
39
+ optHooks = e;
40
+ }
41
+
42
+ /** Sticky descendants flag walk (§6d): reconcile's keyed pruning descends
43
+ * only where subscriptions exist at/below. Nodes AND patches count. */ function markDescendants(e) {
44
+ let o = e;
45
+ while (o && !o.d) {
46
+ o.d = true;
47
+ o = o.u;
48
+ }
49
+ }
50
+
51
+ export { $OWNER, devAssertNeverUserMutation, isOwned, lookupTarget, markDescendants, optHooks, setOptHooks, storeNextLookup };
@@ -0,0 +1,323 @@
1
+ import "../core/core.js";
2
+
3
+ import { GlobalQueue } from "../core/scheduler.js";
4
+
5
+ import "../core/invariants.js";
6
+
7
+ import "../core/verdict.js";
8
+
9
+ import "../core/effect.js";
10
+
11
+ import { $OWNER, lookupTarget as lookupTarget$1 } from "./next/target.js";
12
+
13
+ /**
14
+ * Brand symbols used internally by the store proxy / projection plumbing.
15
+ * Cross-package wiring; not part of the user-facing API.
16
+ *
17
+ * @internal
18
+ */ const $TRACK = Symbol(0), $TARGET = Symbol(0), $PROXY = Symbol(0), // Node-map slot carrying a record-level `affects()` mark: any read through
19
+ // the record witnesses it into the active isPending() probe.
20
+ $AFFECTS = Symbol(0);
21
+
22
+ // Structural field names of store targets (StoreNextTarget aliases these, so
23
+ // shared machinery — affects walks, tests — reads targets via the consts).
24
+ const STORE_VALUE = "v", STORE_NODE = "n", STORE_HAS = "h";
25
+
26
+ function lookupTarget(e, t) {
27
+ // Family registrations (projections/optimistic) first, then the global
28
+ // next lookup. Proxies resolve through $TARGET directly.
29
+ return (t ? lookupTarget$1(e, t) : undefined) ?? lookupTarget$1(e, null);
30
+ }
31
+
32
+ // Values marked raw never acquire a proxy identity: wrap() serves them as-is
33
+ // everywhere — deep stores hold them as leaf values replaced by reference.
34
+ // Once raw, always raw (identity stays single, just unwrapped). Consulted
35
+ // only on wrap-creation and ingest paths; reads never touch it.
36
+ const rawValues = new WeakSet;
37
+
38
+ /**
39
+ * Marks a value as raw: no store will ever wrap it — every store presents it
40
+ * as-is, tracked by reference at whatever slot holds it and updated by
41
+ * replacement. Useful for class instances and external objects (editors,
42
+ * scene graphs, Maps) and for record-shaped data updated wholesale. Sticky
43
+ * for the value's lifetime.
44
+ */
45
+ // Flipped on the first mark and exported as a LIVE binding: reconcile
46
+ // consults it on every recursable pair, and importing the boolean directly
47
+ // lets those sites skip even the function call when no shallow store or raw
48
+ // mark exists anywhere in the app.
49
+ let rawValuesUsed = false;
50
+
51
+ function isRawValue(e) {
52
+ return rawValuesUsed && rawValues.has(e);
53
+ }
54
+
55
+ function markRawOne(e) {
56
+ if (isWrappable(e)) {
57
+ // A store proxy is already tracked elsewhere: the shallow boundary passes
58
+ // it through by reference (replaced, never edited — same slot semantics
59
+ // as a raw) instead of claiming it raw. The sticky mark is global, so
60
+ // marking a live proxy would make wrap() serve it verbatim through every
61
+ // OTHER store too — downstream deep stores then captured it instead of
62
+ // wrapping it in their own family, and their writes landed in the
63
+ // upstream store's override layer (#2932).
64
+ if (e[$TARGET] !== undefined) return;
65
+ rawValuesUsed = true;
66
+ rawValues.add(e);
67
+ }
68
+ }
69
+
70
+ function markRawIngest(e) {
71
+ if (Array.isArray(e)) {
72
+ for (let t = 0, o = e.length; t < o; t++) markRawOne(e[t]);
73
+ } else {
74
+ for (const t in e) markRawOne(e[t]);
75
+ }
76
+ }
77
+
78
+ const OBJECT_PROTO = Object.prototype;
79
+
80
+ // Per-prototype memo for the custom-proto branch of isWrappable: the verdict
81
+ // is fully determined by the prototype (tag and Node lineage both live on
82
+ // the chain), so each class pays the tag call once — not per read.
83
+ const wrappableProtos = new WeakMap;
84
+
85
+ function isWrappable(e) {
86
+ if (e == null || typeof e !== "object" || Object.isFrozen(e)) return false;
87
+ // Plain data and user class instances wrap; platform objects never do
88
+ // (#2952). Native code brand-checks internal slots and throws through a
89
+ // proxy (`Map.prototype.size`, `Date.prototype.getTime`, ...), so
90
+ // collections and other built-ins can't honestly be stores — they get the
91
+ // markRaw-children contract automatically: served raw, mutations land raw,
92
+ // the property holding them still tracks (reassignment notifies). The tag
93
+ // check separates them structurally: user classes stringify as
94
+ // `[object Object]` while every native/host object carries its own brand
95
+ // (`[object Map]`, `[object Date]`, `[object Headers]`, ...), including
96
+ // subclasses, which inherit the tag. getPrototypeOf keeps the hot path
97
+ // (plain and null-proto objects) intrinsic-only — no property lookup.
98
+ const t = Object.getPrototypeOf(e);
99
+ if (t === OBJECT_PROTO || t === null) return true;
100
+ if (Array.isArray(e)) return true;
101
+ let o = wrappableProtos.get(t);
102
+ if (o === undefined) {
103
+ o = Object.prototype.toString.call(e) === "[object Object]" && (
104
+ // Dynamic Node check (kept dynamic so test/SSR overrides of
105
+ // `globalThis.Node` are observed at call time): shimmed DOMs implement
106
+ // nodes as plain user classes, which pass the tag check.
107
+ typeof Node === "undefined" || !(e instanceof Node));
108
+ wrappableProtos.set(t, o);
109
+ }
110
+ return o;
111
+ }
112
+
113
+ let writeOverride = false;
114
+
115
+ function setWriteOverride(e) {
116
+ writeOverride = e;
117
+ }
118
+
119
+ function getWriteOverride() {
120
+ return writeOverride;
121
+ }
122
+
123
+ // Own enumerable keys including symbols (`Object.keys` drops symbol-keyed props). #2769
124
+ function ownEnumerableKeys(e) {
125
+ return Reflect.ownKeys(e).filter(t => Object.prototype.propertyIsEnumerable.call(e, t));
126
+ }
127
+
128
+ /**
129
+ * Scope inheritance for late-created nodes: every live mark whose identity
130
+ * scope contains the owning record's raw — and, for keyed marks, whose key
131
+ * is this property — gets counted on the new node. Inherited marks live
132
+ * exactly as long as the scope's carrier — the release hook below drops
133
+ * them with the entry.
134
+ */ function inheritAffectsMarks(e, t, o) {
135
+ // A live scope exists, so affects.ts already installed the mark engine.
136
+ for (const [r, s] of affectsScopes) {
137
+ if (r.o?.t && s.scope.has(t) && (s.key === undefined || s.key === o)) {
138
+ GlobalQueue.M(e);
139
+ s.inherited.push(e);
140
+ }
141
+ }
142
+ }
143
+
144
+ const affectsScopes = new Map;
145
+
146
+ /** Next-store node factory for affects carriers/slots: injected by the
147
+ * rewrite module (next targets alias the legacy field names, so everything
148
+ * here EXCEPT node creation works on them structurally). */ let nextAffectsNodeResolver = null;
149
+
150
+ function setNextAffectsNodeResolver(e) {
151
+ nextAffectsNodeResolver = e;
152
+ }
153
+
154
+ /** Next-store optimistic view for the declaration walk (optimistic rows
155
+ * pushed before the declaration are in motion too — legacy reads its write
156
+ * overlays; next composes armed-node overrides). */ let nextOptimisticViewResolver = null;
157
+
158
+ function setNextOptimisticViewResolver(e) {
159
+ nextOptimisticViewResolver = e;
160
+ }
161
+
162
+ /** @internal birth inheritance for nodes created inside a live mark window —
163
+ * exported for the rewrite's node factories. */ function affectsScopesLive() {
164
+ return affectsScopes.size > 0;
165
+ }
166
+
167
+ /**
168
+ * Snapshots the identities reachable from `value` into `scope`, reading
169
+ * through write overlays (an optimistic row pushed before the declaration is
170
+ * in motion too). Untracked by construction: walks raw values, never traps.
171
+ * Every LIVE node under each reachable record — property leaves, `$TRACK`,
172
+ * and has-nodes — collects into `found`: those are the graph edges existing
173
+ * readers subscribed through, so the mark registers on them directly and
174
+ * rides the status rails to everything derived. (Nodes born later inherit
175
+ * from the scope in `getNode`.)
176
+ */ function walkAffectsScope(e, t, o, r,
177
+ // Cycle guard, fresh per declaration: the scope itself can't serve — a
178
+ // re-declaration on the same carrier unions into a scope that already
179
+ // holds the root, and must still descend to pick up records added since.
180
+ s) {
181
+ if (!isWrappable(e)) return;
182
+ const f = e[$TARGET] || lookupTarget(e, r);
183
+ // Next targets: walk the pending backing when present (a draft's writes are
184
+ // in motion too) and cover BOTH identities in the scope.
185
+ let n = f ? f.pb ?? f[STORE_VALUE] : e;
186
+ if (s.has(n)) return;
187
+ s.add(n);
188
+ t.scope.add(n);
189
+ if (f && f.pb) t.scope.add(f[STORE_VALUE]);
190
+ // Next optimistic families: enumerate the VISIBLE view (armed-node
191
+ // overrides compose membership/values the raw doesn't carry).
192
+ if (f && f.fam?.opt && nextOptimisticViewResolver) n = nextOptimisticViewResolver(f, n);
193
+ if (f) {
194
+ collectRecordNodes(f[STORE_NODE], o);
195
+ collectRecordNodes(f[STORE_HAS], o);
196
+ // The key-set and deep-witness nodes are record-level channels: a deep()
197
+ // probe reads ONLY these (one pair per record), so a declared affects
198
+ // scope must mark them like any property node.
199
+ if (f.k) o.push(f.k);
200
+ if (f.dk) o.push(f.dk);
201
+ // Carry the effective family into untouched descendants (projections/
202
+ // optimistic stores register children under their family).
203
+ r = f.fam ?? r;
204
+ }
205
+ // Overlays are gone (next has no layer): raw enumeration; the optimistic
206
+ // view composition above already folded armed-node membership/values in.
207
+ if (Array.isArray(n)) {
208
+ for (let e = 0, f = n.length; e < f; e++) {
209
+ walkAffectsScope(n[e], t, o, r, s);
210
+ }
211
+ const e = Object.getOwnPropertySymbols(n);
212
+ for (let f = 0, c = e.length; f < c; f++) {
213
+ if (e[f] === $OWNER) continue;
214
+ const c = Object.getOwnPropertyDescriptor(n, e[f]);
215
+ if (!c || c.get) continue;
216
+ walkAffectsScope(c.value, t, o, r, s);
217
+ }
218
+ } else {
219
+ const e = Reflect.ownKeys(n);
220
+ for (let f = 0, c = e.length; f < c; f++) {
221
+ if (e[f] === $OWNER) continue;
222
+ const c = Object.getOwnPropertyDescriptor(n, e[f]);
223
+ if (!c || c.get) continue;
224
+ walkAffectsScope(c.value, t, o, r, s);
225
+ }
226
+ }
227
+ }
228
+
229
+ /** All live signal nodes of one record's node map (string + symbol keyed). */ function collectRecordNodes(e, t) {
230
+ if (!e) return;
231
+ for (const o of Object.keys(e)) t.push(e[o]);
232
+ const o = Object.getOwnPropertySymbols(e);
233
+ for (let r = 0, s = o.length; r < s; r++) {
234
+ // Another mark's carrier is its own channel — counting it here would
235
+ // extend that sibling scope's lifetime to this declaration's.
236
+ if (o[r] !== $AFFECTS) t.push(e[o[r]]);
237
+ }
238
+ }
239
+
240
+ /**
241
+ * Witness live mark coverage of a record into the active isPending() probe.
242
+ * Tracked reads don't need this — they go through real signal nodes, which
243
+ * carry marks directly (declaration walk or birth inheritance). This covers
244
+ * UNTRACKED probes reading through records whose nodes never materialized
245
+ * (no observer ever subscribed, so no node exists to carry the mark).
246
+ * Callers guard on `pendingCheckActive`, so plain reads never pay for this.
247
+ *
248
+ * @internal
249
+ */ function witnessAffectsMark(e, t) {
250
+ // Callers guard on `pendingCheckActive`, which only flips inside
251
+ // isPending() — the verdict layer is loaded and its hook installed.
252
+ const o = e[STORE_NODE]?.[$AFFECTS];
253
+ if (o?.o?.t) GlobalQueue.oi(o);
254
+ if (affectsScopes.size) {
255
+ // Chained backings (§7b): a wrapper's STORE_VALUE can be another store's
256
+ // proxy — marks cover by identity of the BASE raw, so resolve the chain
257
+ // and check every identity along it.
258
+ let r = e[STORE_VALUE];
259
+ for (const [e, s] of affectsScopes) {
260
+ if (e !== o && e.o?.t && (s.key === undefined || s.key === t)) {
261
+ let t = r;
262
+ for (;;) {
263
+ if (s.scope.has(t)) {
264
+ GlobalQueue.oi(e);
265
+ break;
266
+ }
267
+ const o = t?.[$TARGET];
268
+ if (o === undefined) break;
269
+ const r = o.pb ?? o[STORE_VALUE];
270
+ if (r === t) break;
271
+ t = r;
272
+ }
273
+ }
274
+ }
275
+ }
276
+ }
277
+
278
+ /**
279
+ * Resolves the store nodes an `affects()` declaration marks: with a `key`,
280
+ * the named slot's leaf node (upserted so the mark has an addressable
281
+ * carrier); without, the record's $AFFECTS carrier plus every LIVE node in
282
+ * its subtree (the edges existing readers subscribed through), with the
283
+ * subtree's identities snapshotted into the mark's scope so nodes created
284
+ * during the window — and untracked probes over captured proxies — resolve
285
+ * against it (#2882).
286
+ *
287
+ * @internal
288
+ */ function getStoreAffectsNodes(e, t) {
289
+ GlobalQueue.p ||= e => {
290
+ const t = affectsScopes.get(e);
291
+ if (!t) return;
292
+ affectsScopes.delete(e);
293
+ for (let e = 0; e < t.inherited.length; e++) GlobalQueue.N(t.inherited[e]);
294
+ };
295
+ if (t === undefined) {
296
+ const t = nextAffectsNodeResolver(e, $AFFECTS);
297
+ let o = affectsScopes.get(t);
298
+ if (!o) affectsScopes.set(t, o = {
299
+ scope: new Set,
300
+ inherited: []
301
+ });
302
+ const r = [ t ];
303
+ walkAffectsScope(e[$PROXY], o, r, e.fam, new Set);
304
+ return r;
305
+ }
306
+ const o = e.n?.[t] ?? nextAffectsNodeResolver(e, t);
307
+ // Keyed marks resolve by identity too (#2904): another store family's
308
+ // proxy can share this record's raw (a derived store swaps its backing to
309
+ // the source's raw when its projection lands), and reads through it never
310
+ // touch this target's node map. Scope is exactly the owning record's raw,
311
+ // narrowed to this key for witness and birth inheritance.
312
+ let r = affectsScopes.get(o);
313
+ if (!r) affectsScopes.set(o, r = {
314
+ scope: new Set,
315
+ inherited: [],
316
+ key: t
317
+ });
318
+ r.scope.add(e[STORE_VALUE]);
319
+ if (e.pb) r.scope.add(e.pb);
320
+ return [ o ];
321
+ }
322
+
323
+ export { $AFFECTS, $PROXY, $TARGET, $TRACK, STORE_HAS, STORE_NODE, STORE_VALUE, affectsScopesLive, getStoreAffectsNodes, getWriteOverride, inheritAffectsMarks, isRawValue, isWrappable, markRawIngest, markRawOne, nextAffectsNodeResolver, nextOptimisticViewResolver, ownEnumerableKeys, rawValuesUsed, setNextAffectsNodeResolver, setNextOptimisticViewResolver, setWriteOverride, witnessAffectsMark };
@@ -0,0 +1,103 @@
1
+ import { isWrappable, ownEnumerableKeys } from "./store.js";
2
+
3
+ const DELETE = Symbol(0);
4
+
5
+ function isPrototypePollutionKey(t) {
6
+ return t === "__proto__" || t === "constructor" || t === "prototype";
7
+ }
8
+
9
+ function updatePath(t, e, o = 0) {
10
+ let r, n = t;
11
+ if (o < e.length - 1) {
12
+ r = e[o];
13
+ const i = typeof r;
14
+ const f = Array.isArray(t);
15
+ if (i === "string" && isPrototypePollutionKey(r)) return;
16
+ if (Array.isArray(r)) {
17
+ for (let n = 0; n < r.length; n++) {
18
+ e[o] = r[n];
19
+ updatePath(t, e, o);
20
+ }
21
+ e[o] = r;
22
+ return;
23
+ } else if (f && i === "function") {
24
+ for (let n = 0; n < t.length; n++) {
25
+ if (r(t[n], n)) {
26
+ e[o] = n;
27
+ updatePath(t, e, o);
28
+ }
29
+ }
30
+ e[o] = r;
31
+ return;
32
+ } else if (f && i === "object") {
33
+ const {from: n = 0, to: i = t.length - 1, by: f = 1} = r;
34
+ for (let r = n; r <= i; r += f) {
35
+ e[o] = r;
36
+ updatePath(t, e, o);
37
+ }
38
+ e[o] = r;
39
+ return;
40
+ } else if (o < e.length - 2) {
41
+ updatePath(t[r], e, o + 1);
42
+ return;
43
+ }
44
+ n = t[r];
45
+ }
46
+ let i = e[e.length - 1];
47
+ if (typeof i === "function") {
48
+ i = i(n);
49
+ if (i === n) return;
50
+ }
51
+ if (r === undefined && i == undefined) return;
52
+ if (i === DELETE) {
53
+ delete t[r];
54
+ } else if (r === undefined || isWrappable(n) && isWrappable(i) && !Array.isArray(i)) {
55
+ const e = r !== undefined ? t[r] : t;
56
+ const o = ownEnumerableKeys(i);
57
+ for (let t = 0; t < o.length; t++) {
58
+ const r = o[t];
59
+ if (typeof r === "string" && isPrototypePollutionKey(r)) continue;
60
+ const n = Object.getOwnPropertyDescriptor(i, r);
61
+ if (n.get || n.set) Object.defineProperty(e, r, n); else e[r] = n.value;
62
+ }
63
+ } else {
64
+ t[r] = i;
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Path-based setter helper for `createStore`. Call `storePath(...path, value)`
70
+ * to produce a draft-mutating function suitable for passing to `setStore`.
71
+ *
72
+ * The canonical setter form in Solid 2.0 is the draft-mutating callback
73
+ * (`setStore(s => { s.user.name = "Ada"; })`). `storePath` is a backwards-
74
+ * compatibility helper for users porting from Solid 1.x's
75
+ * `setStore("user", "name", "Ada")` style — it's optional and you can mix the
76
+ * two styles freely.
77
+ *
78
+ * Path parts can be:
79
+ * - a single key — `"user"`, `0`
80
+ * - an array of keys — `[0, 1, 2]`
81
+ * - a range over an array — `{ from?, to?, by? }`
82
+ * - a filter `(item, index) => boolean` for arrays
83
+ *
84
+ * The final argument is the new value or an updater `(prev) => next`. Use
85
+ * `storePath.DELETE` to remove a property.
86
+ *
87
+ * @example
88
+ * ```ts
89
+ * const [state, setState] = createStore({ user: { name: "Ada" }, todos: [] });
90
+ *
91
+ * setState(storePath("user", "name", "Grace"));
92
+ * setState(storePath("todos", t => !t.done, "done", true)); // mark all undone as done
93
+ * setState(storePath("user", "nickname", storePath.DELETE));
94
+ * ```
95
+ */ const storePath = /* @__PURE__ */ Object.assign(function storePath(...t) {
96
+ return e => {
97
+ updatePath(e, t);
98
+ };
99
+ }, {
100
+ DELETE: DELETE
101
+ });
102
+
103
+ export { storePath };
@@ -0,0 +1,210 @@
1
+ import "../core/core.js";
2
+
3
+ import { SUPPORTS_PROXY } from "../core/constants.js";
4
+
5
+ import "../core/scheduler.js";
6
+
7
+ import "../core/invariants.js";
8
+
9
+ import "../core/verdict.js";
10
+
11
+ import "../core/effect.js";
12
+
13
+ import { createMemo } from "../signals.js";
14
+
15
+ import { ownEnumerableKeys, $PROXY } from "./store.js";
16
+
17
+ function trueFn() {
18
+ return true;
19
+ }
20
+
21
+ const propTraps = {
22
+ get(e, r, t) {
23
+ if (r === $PROXY) return t;
24
+ return e.get(r);
25
+ },
26
+ has(e, r) {
27
+ if (r === $PROXY) return true;
28
+ return e.has(r);
29
+ },
30
+ set: trueFn,
31
+ deleteProperty: trueFn,
32
+ getOwnPropertyDescriptor(e, r) {
33
+ return {
34
+ configurable: true,
35
+ enumerable: true,
36
+ get() {
37
+ return e.get(r);
38
+ },
39
+ set: trueFn,
40
+ deleteProperty: trueFn
41
+ };
42
+ },
43
+ ownKeys(e) {
44
+ return e.keys();
45
+ }
46
+ };
47
+
48
+ function resolveSource(e) {
49
+ return !(e = typeof e === "function" ? e() : e) ? {} : e;
50
+ }
51
+
52
+ const $SOURCES = Symbol(0);
53
+
54
+ /** @internal The flattened sources behind a `merge()` PROXY, or undefined.
55
+ * Only the proxy form: its writes are no-ops, so the sources are the whole
56
+ * truth. merge()'s plain-object form also records `$SOURCES` (so nested
57
+ * merges flatten), but it is a real object callers may mutate afterwards
58
+ * (html's tagged templates assign props after spreading) — those own writes
59
+ * live on the object, not in the sources, so it must be read directly. */ function mergeSources(e) {
60
+ return e != null && e[$PROXY] === e ? e[$SOURCES] : undefined;
61
+ }
62
+
63
+ /**
64
+ * Merges multiple props-like objects into a single proxy that *preserves
65
+ * reactivity*. Reads are forwarded to the right-most source that defines the
66
+ * property, so later sources override earlier ones (like `Object.assign`).
67
+ *
68
+ * Function arguments are treated as memo-backed sources — useful for passing
69
+ * derived defaults whose computation should track reactively.
70
+ *
71
+ * Use this in component bodies to merge defaults / overrides without losing
72
+ * Solid's per-property tracking.
73
+ *
74
+ * @example
75
+ * ```tsx
76
+ * function Button(_props: { label: string; type?: string; disabled?: boolean }) {
77
+ * const props = merge({ type: "button", disabled: false }, _props);
78
+ *
79
+ * return <button type={props.type} disabled={props.disabled}>{props.label}</button>;
80
+ * }
81
+ * ```
82
+ */ function merge(...e) {
83
+ if (e.length === 1 && typeof e[0] !== "function") return e[0];
84
+ let r = false;
85
+ const t = [];
86
+ for (let n = 0; n < e.length; n++) {
87
+ const o = e[n];
88
+ r = r || !!o && $PROXY in o;
89
+ const u = !!o && o[$SOURCES];
90
+ if (u) {
91
+ for (let e = 0; e < u.length; e++) t.push(u[e]);
92
+ } else t.push(typeof o === "function" ? (r = true, createMemo(o)) : o);
93
+ }
94
+ if (SUPPORTS_PROXY && r) {
95
+ return new Proxy({
96
+ get(e) {
97
+ if (e === $SOURCES) return t;
98
+ for (let r = t.length - 1; r >= 0; r--) {
99
+ const n = resolveSource(t[r]);
100
+ if (e in n) return n[e];
101
+ }
102
+ },
103
+ has(e) {
104
+ for (let r = t.length - 1; r >= 0; r--) {
105
+ if (e in resolveSource(t[r])) return true;
106
+ }
107
+ return false;
108
+ },
109
+ keys() {
110
+ const e = new Set;
111
+ for (let r = 0; r < t.length; r++) {
112
+ const n = ownEnumerableKeys(resolveSource(t[r]));
113
+ for (let r = 0; r < n.length; r++) e.add(n[r]);
114
+ }
115
+ return [ ...e ];
116
+ }
117
+ }, propTraps);
118
+ }
119
+ const n = Object.create(null);
120
+ let o = false;
121
+ let u = t.length - 1;
122
+ for (let e = u; e >= 0; e--) {
123
+ const r = t[e];
124
+ if (!r) {
125
+ e === u && u--;
126
+ continue;
127
+ }
128
+ const c = Object.getOwnPropertyNames(r);
129
+ for (let t = c.length - 1; t >= 0; t--) {
130
+ const s = c[t];
131
+ if (s === "__proto__" || s === "constructor") continue;
132
+ if (!n[s]) {
133
+ o = o || e !== u;
134
+ const t = Object.getOwnPropertyDescriptor(r, s);
135
+ n[s] = t.get ? {
136
+ enumerable: true,
137
+ configurable: true,
138
+ get: t.get.bind(r)
139
+ } : t;
140
+ }
141
+ }
142
+ }
143
+ if (!o) return t[u];
144
+ const c = {};
145
+ const s = Object.keys(n);
146
+ for (let e = s.length - 1; e >= 0; e--) {
147
+ const r = s[e], t = n[r];
148
+ if (t.get) Object.defineProperty(c, r, t); else c[r] = t.value;
149
+ }
150
+ c[$SOURCES] = t;
151
+ return c;
152
+ }
153
+
154
+ /**
155
+ * Returns a reactive proxy of `props` with the listed keys hidden. Tracking
156
+ * on the remaining keys is preserved.
157
+ *
158
+ * Use it to forward "rest" props to a child element while pulling out the
159
+ * keys your component handles itself — the equivalent of `splitProps(p, ["a","b"])[1]`.
160
+ *
161
+ * @example
162
+ * ```tsx
163
+ * function Input(props: { label: string; value: string; onInput: (v: string) => void } & JSX.HTMLAttributes<HTMLInputElement>) {
164
+ * const rest = omit(props, "label", "value", "onInput");
165
+ *
166
+ * return (
167
+ * <label>
168
+ * {props.label}
169
+ * <input
170
+ * {...rest}
171
+ * value={props.value}
172
+ * onInput={e => props.onInput(e.currentTarget.value)}
173
+ * />
174
+ * </label>
175
+ * );
176
+ * }
177
+ * ```
178
+ */ function omit(e, ...r) {
179
+ if (SUPPORTS_PROXY && $PROXY in e) {
180
+ return new Proxy({
181
+ get(t) {
182
+ // $SOURCES must not tunnel through the filter: merge() flattens
183
+ // whatever answers it, so forwarding would hand a re-merge the
184
+ // UNFILTERED sources of an underlying merge proxy and the omitted
185
+ // keys leak back in (#3014 — the SSR element-spread path re-merges
186
+ // static attributes with the rest object). Opaque here: merge
187
+ // composes omit proxies through their traps instead.
188
+ return t === $SOURCES || r.includes(t) ? undefined : e[t];
189
+ },
190
+ has(t) {
191
+ return t !== $SOURCES && !r.includes(t) && t in e;
192
+ },
193
+ keys() {
194
+ return ownEnumerableKeys(e).filter(e => !r.includes(e));
195
+ }
196
+ }, propTraps);
197
+ }
198
+ const t = {};
199
+ const n = Object.getOwnPropertyNames(e);
200
+ const o = r.length > 4 && n.length > r.length ? new Set(r) : undefined;
201
+ for (const u of n) {
202
+ if (o ? !o.has(u) : !r.includes(u)) {
203
+ const r = Object.getOwnPropertyDescriptor(e, u);
204
+ !r.get && !r.set && r.enumerable && r.writable && r.configurable ? t[u] = r.value : Object.defineProperty(t, u, r);
205
+ }
206
+ }
207
+ return t;
208
+ }
209
+
210
+ export { merge, mergeSources, omit };