@solidjs/signals 2.0.0-rc.2 → 2.0.0-rc.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 (198) hide show
  1. package/dist/dev-shared.js +6505 -0
  2. package/dist/dev.attribution.js +3484 -0
  3. package/dist/dev.js +10227 -9508
  4. package/dist/observe/affects-marks.js +86 -0
  5. package/dist/observe/affects.js +112 -0
  6. package/dist/observe/attribution.js +7 -0
  7. package/dist/observe/boundaries.js +696 -0
  8. package/dist/observe/core/action.js +182 -0
  9. package/dist/observe/core/async.js +824 -0
  10. package/dist/observe/core/attribution-costs.js +66 -0
  11. package/dist/observe/core/attribution-feedback.js +280 -0
  12. package/dist/observe/core/attribution-hooks.js +83 -0
  13. package/dist/observe/core/attribution-queries.js +43 -0
  14. package/dist/observe/core/attribution.js +3079 -0
  15. package/dist/observe/core/constants.js +269 -0
  16. package/dist/observe/core/context.js +63 -0
  17. package/dist/observe/core/copies.js +10 -0
  18. package/dist/observe/core/core.js +1707 -0
  19. package/dist/observe/core/dev.js +394 -0
  20. package/dist/observe/core/effect.js +193 -0
  21. package/dist/observe/core/error-hooks.js +71 -0
  22. package/dist/observe/core/error.js +82 -0
  23. package/dist/observe/core/external.js +97 -0
  24. package/dist/observe/core/graph.js +162 -0
  25. package/dist/observe/core/heap.js +124 -0
  26. package/dist/observe/core/identities.js +62 -0
  27. package/dist/observe/core/invariants.js +12 -0
  28. package/dist/observe/core/lanes.js +972 -0
  29. package/dist/observe/core/owner.js +371 -0
  30. package/dist/observe/core/scheduler.js +1157 -0
  31. package/dist/observe/core/truth.js +47 -0
  32. package/dist/observe/core/verdict.js +470 -0
  33. package/dist/observe/deferred.js +186 -0
  34. package/dist/observe/flatten.js +79 -0
  35. package/dist/observe/from.js +248 -0
  36. package/dist/observe/index.js +71 -0
  37. package/dist/observe/map.js +593 -0
  38. package/dist/observe/reveal.js +212 -0
  39. package/dist/observe/signals.js +717 -0
  40. package/dist/observe/store/affects.js +142 -0
  41. package/dist/observe/store/edges.js +39 -0
  42. package/dist/observe/store/hooks.js +16 -0
  43. package/dist/observe/store/index.js +47 -0
  44. package/dist/observe/store/optimistic.js +713 -0
  45. package/dist/observe/store/projection.js +345 -0
  46. package/dist/observe/store/reconcile.js +281 -0
  47. package/dist/observe/store/store.js +2127 -0
  48. package/dist/observe/store/storePath.js +103 -0
  49. package/dist/observe/store/target.js +46 -0
  50. package/dist/observe/store/types.js +83 -0
  51. package/dist/observe/store/utils.js +1063 -0
  52. package/dist/prod/affects-marks.js +86 -0
  53. package/dist/prod/affects.js +98 -112
  54. package/dist/prod/attribution.js +45 -0
  55. package/dist/prod/boundaries.js +578 -468
  56. package/dist/prod/core/action.js +92 -59
  57. package/dist/prod/core/async.js +522 -336
  58. package/dist/prod/core/attribution-hooks.js +3 -0
  59. package/dist/prod/core/constants.js +168 -44
  60. package/dist/prod/core/context.js +12 -16
  61. package/dist/prod/core/copies.js +10 -0
  62. package/dist/prod/core/core.js +1345 -627
  63. package/dist/prod/core/dev.js +123 -1
  64. package/dist/prod/core/effect.js +113 -80
  65. package/dist/prod/core/error-hooks.js +71 -0
  66. package/dist/prod/core/error.js +18 -4
  67. package/dist/prod/core/external.js +6 -7
  68. package/dist/prod/core/graph.js +119 -72
  69. package/dist/prod/core/heap.js +85 -109
  70. package/dist/prod/core/identities.js +62 -0
  71. package/dist/prod/core/invariants.js +1 -32
  72. package/dist/prod/core/lanes.js +931 -132
  73. package/dist/prod/core/owner.js +192 -129
  74. package/dist/prod/core/scheduler.js +948 -642
  75. package/dist/prod/core/truth.js +47 -0
  76. package/dist/prod/core/verdict.js +409 -420
  77. package/dist/prod/deferred.js +184 -0
  78. package/dist/prod/flatten.js +77 -0
  79. package/dist/prod/from.js +248 -0
  80. package/dist/prod/index.js +40 -16
  81. package/dist/prod/map.js +481 -211
  82. package/dist/prod/reveal.js +212 -0
  83. package/dist/prod/signals.js +401 -84
  84. package/dist/prod/store/affects.js +142 -0
  85. package/dist/prod/store/edges.js +39 -0
  86. package/dist/prod/store/hooks.js +16 -0
  87. package/dist/prod/store/index.js +27 -18
  88. package/dist/prod/store/optimistic.js +707 -0
  89. package/dist/prod/store/projection.js +331 -0
  90. package/dist/prod/store/reconcile.js +281 -0
  91. package/dist/prod/store/store.js +1952 -267
  92. package/dist/prod/store/storePath.js +1 -1
  93. package/dist/prod/store/target.js +43 -0
  94. package/dist/prod/store/types.js +83 -0
  95. package/dist/prod/store/utils.js +997 -138
  96. package/dist/types/affects-marks.d.ts +14 -0
  97. package/dist/types/affects.d.ts +12 -30
  98. package/dist/types/attribution.d.ts +19 -0
  99. package/dist/types/attribution.prod.d.ts +22 -0
  100. package/dist/types/boundaries.d.ts +99 -124
  101. package/dist/types/carved.d.ts +1 -0
  102. package/dist/types/core/action.d.ts +23 -9
  103. package/dist/types/core/async.d.ts +34 -6
  104. package/dist/types/core/attribution-costs.d.ts +35 -0
  105. package/dist/types/core/attribution-feedback.d.ts +133 -0
  106. package/dist/types/core/attribution-hooks.d.ts +307 -8
  107. package/dist/types/core/attribution-queries.d.ts +24 -0
  108. package/dist/types/core/attribution.d.ts +802 -72
  109. package/dist/types/core/constants.d.ts +195 -38
  110. package/dist/types/core/copies.d.ts +54 -0
  111. package/dist/types/core/core.d.ts +295 -65
  112. package/dist/types/core/dev.d.ts +509 -22
  113. package/dist/types/core/effect.d.ts +1 -1
  114. package/dist/types/core/error-hooks.d.ts +71 -0
  115. package/dist/types/core/error.d.ts +18 -1
  116. package/dist/types/core/graph.d.ts +40 -1
  117. package/dist/types/core/heap.d.ts +5 -5
  118. package/dist/types/core/identities.d.ts +17 -0
  119. package/dist/types/core/index.d.ts +11 -7
  120. package/dist/types/core/invariants.d.ts +1 -26
  121. package/dist/types/core/lanes.d.ts +74 -43
  122. package/dist/types/core/owner.d.ts +27 -9
  123. package/dist/types/core/scheduler.d.ts +353 -102
  124. package/dist/types/core/truth.d.ts +18 -0
  125. package/dist/types/core/types.d.ts +97 -71
  126. package/dist/types/core/verdict.d.ts +35 -0
  127. package/dist/types/deferred.d.ts +28 -0
  128. package/dist/types/flatten.d.ts +8 -0
  129. package/dist/types/from.d.ts +47 -0
  130. package/dist/types/index.d.ts +33 -7
  131. package/dist/types/map.d.ts +4 -2
  132. package/dist/types/reveal.d.ts +19 -0
  133. package/dist/types/signals.d.ts +196 -45
  134. package/dist/types/store/affects.d.ts +12 -0
  135. package/dist/types/store/edges.d.ts +9 -0
  136. package/dist/types/store/hooks.d.ts +62 -0
  137. package/dist/types/store/index.d.ts +42 -15
  138. package/dist/types/store/optimistic.d.ts +24 -45
  139. package/dist/types/store/projection.d.ts +17 -68
  140. package/dist/types/store/reconcile.d.ts +3 -46
  141. package/dist/types/store/store.d.ts +133 -136
  142. package/dist/types/store/storePath.d.ts +1 -1
  143. package/dist/types/store/target.d.ts +166 -0
  144. package/dist/types/store/types.d.ts +105 -0
  145. package/dist/types/store/utils.d.ts +188 -0
  146. package/package.json +31 -26
  147. package/dist/node.cjs +0 -8745
  148. package/dist/prod/core/optimistic.js +0 -265
  149. package/dist/prod/store/next/optimistic.js +0 -385
  150. package/dist/prod/store/next/projection.js +0 -172
  151. package/dist/prod/store/next/reconcile.js +0 -331
  152. package/dist/prod/store/next/store.js +0 -1499
  153. package/dist/prod/store/next/target.js +0 -20
  154. package/dist/types/core/optimistic.d.ts +0 -6
  155. package/dist/types/store/next/optimistic.d.ts +0 -20
  156. package/dist/types/store/next/projection.d.ts +0 -8
  157. package/dist/types/store/next/reconcile.d.ts +0 -3
  158. package/dist/types/store/next/store.d.ts +0 -77
  159. package/dist/types/store/next/target.d.ts +0 -117
  160. package/dist/types-cjs/affects.d.cts +0 -47
  161. package/dist/types-cjs/boundaries.d.cts +0 -175
  162. package/dist/types-cjs/core/action.d.cts +0 -64
  163. package/dist/types-cjs/core/async.d.cts +0 -21
  164. package/dist/types-cjs/core/attribution-hooks.d.cts +0 -52
  165. package/dist/types-cjs/core/attribution.d.cts +0 -186
  166. package/dist/types-cjs/core/constants.d.cts +0 -97
  167. package/dist/types-cjs/core/context.d.cts +0 -36
  168. package/dist/types-cjs/core/core.d.cts +0 -163
  169. package/dist/types-cjs/core/dev.d.cts +0 -81
  170. package/dist/types-cjs/core/effect.d.cts +0 -30
  171. package/dist/types-cjs/core/error.d.cts +0 -47
  172. package/dist/types-cjs/core/external.d.cts +0 -15
  173. package/dist/types-cjs/core/graph.d.cts +0 -6
  174. package/dist/types-cjs/core/heap.d.cts +0 -22
  175. package/dist/types-cjs/core/index.d.cts +0 -13
  176. package/dist/types-cjs/core/invariants.d.cts +0 -59
  177. package/dist/types-cjs/core/lanes.d.cts +0 -44
  178. package/dist/types-cjs/core/optimistic.d.cts +0 -6
  179. package/dist/types-cjs/core/owner.d.cts +0 -124
  180. package/dist/types-cjs/core/scheduler.d.cts +0 -180
  181. package/dist/types-cjs/core/types.d.cts +0 -192
  182. package/dist/types-cjs/core/verdict.d.cts +0 -2
  183. package/dist/types-cjs/index.d.cts +0 -10
  184. package/dist/types-cjs/map.d.cts +0 -69
  185. package/dist/types-cjs/package.json +0 -3
  186. package/dist/types-cjs/signals.d.cts +0 -624
  187. package/dist/types-cjs/store/index.d.cts +0 -19
  188. package/dist/types-cjs/store/next/optimistic.d.cts +0 -20
  189. package/dist/types-cjs/store/next/projection.d.cts +0 -8
  190. package/dist/types-cjs/store/next/reconcile.d.cts +0 -3
  191. package/dist/types-cjs/store/next/store.d.cts +0 -77
  192. package/dist/types-cjs/store/next/target.d.cts +0 -117
  193. package/dist/types-cjs/store/optimistic.d.cts +0 -45
  194. package/dist/types-cjs/store/projection.d.cts +0 -70
  195. package/dist/types-cjs/store/reconcile.d.cts +0 -46
  196. package/dist/types-cjs/store/store.d.cts +0 -138
  197. package/dist/types-cjs/store/storePath.d.cts +0 -58
  198. package/dist/types-cjs/store/utils.d.cts +0 -74
@@ -0,0 +1,1063 @@
1
+ import { SUPPORTS_PROXY, CONFIG_KEY_BAG } from "../core/constants.js";
2
+
3
+ import { createMemo } from "../signals.js";
4
+
5
+ import { $PROXY, $RECORD, $TARGET, ownEnumerableKeys } from "./types.js";
6
+
7
+ function trueFn() {
8
+ return true;
9
+ }
10
+
11
+ /** @internal What a source ENTRY is, decided once when the view is built
12
+ * (`merge()` learns it while flattening; `omit()` from its argument) and
13
+ * carried beside the entry — `MergeView.kinds[i]`, `OmitView.kind` — so no
14
+ * read has to ask. Asking is the cost: any brand check on a Proxy is a trap
15
+ * (`instanceof` is a `getPrototypeOf` trap, ~20 ns on a store — as much as
16
+ * the read itself), and a merge over a store did two per read. */ const SOURCE_PLAIN = 0;
17
+
18
+ // a plain object: own keys fixed, data is data
19
+ const SOURCE_OMIT = 1;
20
+
21
+ // an `OmitView` record (only as a merge entry)
22
+ const SOURCE_PROXY = 2;
23
+
24
+ // a store or foreign proxy: everything is a trap
25
+ const SOURCE_MEMO = 3;
26
+
27
+ // a function source (merge's memo): swaps objects
28
+ const SOURCE_MERGE = 4;
29
+
30
+ // a `MergeView` record (only as an omit's source)
31
+ const EMPTY = Object.freeze({});
32
+
33
+ // The object behind a LEAF entry (any kind but OMIT): a memo is read
34
+ // (tracked, as merge's own reads are) and a nullish result has no keys.
35
+ function leafOf(e, n) {
36
+ return n === SOURCE_MEMO ? (e = e()) == null ? EMPTY : e : e;
37
+ }
38
+
39
+ /** @internal The record behind an `omit()` proxy: `source` with `hidden`
40
+ * keys removed. It is the proxy's TARGET, so the shared handler reads it as
41
+ * plain fields — no per-instance closures — and it is what props consumers
42
+ * walk directly (`merge`, `spread`, `ssrElement`): a view never materializes
43
+ * a copy, and a consumer that knows the record never goes through its traps
44
+ * (a `getOwnPropertyDescriptor` trap per key allocates a descriptor and a
45
+ * getter, so enumerating a proxy costs more than the copy it was avoiding).
46
+ * `hidden` is a key list or a predicate (`omit(props, k => k[0] === "$")`).
47
+ *
48
+ * An omit over a `merge()` holds the merge's RECORD (`MergeView`, kind
49
+ * `SOURCE_MERGE`) — never its proxy, so no read hops through a trap — and is
50
+ * one record however many leaves the merge has. A consumer walks it as ONE
51
+ * filtered entry (`sourceKeys` / `sourceGet` recurse into the merge's
52
+ * sources by function call), and a later `merge()` over it carries the
53
+ * record as one entry instead of copying its leaves: on a component chain of
54
+ * defaults + omit + spread (`merge(omit(merge(omit(props))))`) the layers
55
+ * nest as records, each a few fields, where a flatten to leaf views built a
56
+ * view and a combined key list per leaf per layer — the largest allocation
57
+ * of a Kobalte-shaped render. A merge leaf may be merge's memo for a
58
+ * function source; it is resolved on access. */ class OmitView {
59
+ source;
60
+ kind;
61
+ hidden;
62
+ /** see `MergeView.table` */
63
+ table=0;
64
+ /** see `tableOwnKeys` / `tableDescriptor` */
65
+ keys=undefined;
66
+ descs=undefined;
67
+ constructor(e,
68
+ /** of `source` — PLAIN, PROXY (a store or a foreign proxy), MEMO, or
69
+ * MERGE (a `MergeView` record); never OMIT, a view over a view folds
70
+ * into one. */
71
+ n, t) {
72
+ this.source = e;
73
+ this.kind = n;
74
+ this.hidden = t;
75
+ }
76
+ }
77
+
78
+ function isHidden(e, n) {
79
+ const t = e.hidden;
80
+ return typeof t === "function" ? t(n) : t.includes(n);
81
+ }
82
+
83
+ // Both filters as one. Two key lists stay a key list (one `includes`, no
84
+ // closure); a predicate on either side needs a closure. An omit over a
85
+ // merge builds one combined list per leaf, per component layer, so the
86
+ // copy's form matters in every tier: `concat` runs the species/spreadable
87
+ // protocol (2–3× the cost of a copy once optimized), a hand loop is 2–4×
88
+ // `concat` in the interpreter and baseline tiers (a bytecode per element
89
+ // against one builtin), and a presized `new Array(n)` is holey, which takes
90
+ // `includes` off its fast path. `slice` + `push` of the (short) second list
91
+ // is within a third of the best form in every tier, and packed.
92
+ function combineHidden(e, n) {
93
+ if (typeof e !== "function" && typeof n !== "function") {
94
+ const t = e.slice();
95
+ for (let e = 0; e < n.length; e++) t.push(n[e]);
96
+ return t;
97
+ }
98
+ return t => (typeof e === "function" ? e(t) : e.includes(t)) || (typeof n === "function" ? n(t) : n.includes(t));
99
+ }
100
+
101
+ // The object a view filters (see `leafOf`).
102
+ function viewSource(e) {
103
+ return leafOf(e.source, e.kind);
104
+ }
105
+
106
+ // The record behind a `$PROXY`-marked object that is one of OUR views, else
107
+ // undefined for a store or a foreign proxy. ONE read: the view traps answer
108
+ // `$RECORD` first thing and a store's `get` trap answers it `undefined` on
109
+ // its symbol fast path, so the question never reaches a store's generic
110
+ // read path (firewall gate, tracked key read), which is what an unknown
111
+ // symbol would take — and a foreign proxy forwards it to a target that has
112
+ // no such key. Asking `$TARGET` first and then each view kind was two to
113
+ // four trap hops per source at every `merge()`, `omit()` and `ssrElement`.
114
+ // Call only after `$PROXY in o` is known true.
115
+ function recordOf(e) {
116
+ return e[$RECORD];
117
+ }
118
+
119
+ /** @internal The `OmitView` behind an `omit()` proxy, or undefined. */ function omitView(e) {
120
+ if (e == null || !($PROXY in e)) return undefined;
121
+ const n = e[$RECORD];
122
+ return n instanceof OmitView ? n : undefined;
123
+ }
124
+
125
+ // A props SOURCE ENTRY is a plain object, a proxy (store, merge, omit — the
126
+ // last two are normally unwrapped first: `mergeView` / `omitView`), a memo,
127
+ // or an `OmitView` record, and travels with its kind. These three answer for
128
+ // an entry what `Object.keys` / `in` / `[]` answer for an object, so every
129
+ // consumer walks entries with one code path, an `OmitView` is filtered
130
+ // rather than materialized, and nothing is asked of a proxy but the read.
131
+ // Own keys of a leaf: a proxy answers through ONE `ownKeys` trap (a store's
132
+ // keeps the key set tracked; `Object.keys` on a proxy would add a descriptor
133
+ // trap per key); a plain object its enumerable string keys. What a memo
134
+ // holds is only known once read.
135
+ function leafKeys(e, n) {
136
+ if (n === SOURCE_PLAIN) return Object.keys(e);
137
+ if (n === SOURCE_PROXY || e[$PROXY] === e) return Reflect.ownKeys(e);
138
+ return Object.keys(e);
139
+ }
140
+
141
+ /** @internal Own string keys of a source entry — every consumer skips
142
+ * symbols itself. */ function sourceKeys(e, n) {
143
+ if (n === SOURCE_OMIT) {
144
+ if (e.kind === SOURCE_MERGE) return mergeKeysOf(e.source, false, e);
145
+ const n = leafKeys(viewSource(e), e.kind);
146
+ const t = [];
147
+ for (let r = 0; r < n.length; r++) if (!isHidden(e, n[r])) t.push(n[r]);
148
+ return t;
149
+ }
150
+ return leafKeys(leafOf(e, n), n);
151
+ }
152
+
153
+ /** @internal `key in entry`. */ function sourceHas(e, n, t) {
154
+ if (n === SOURCE_OMIT) {
155
+ if (isHidden(e, t)) return false;
156
+ return e.kind === SOURCE_MERGE ? mergeHas(e.source, t) : t in viewSource(e);
157
+ }
158
+ return t in leafOf(e, n);
159
+ }
160
+
161
+ /** @internal `entry[key]` — the source's getter runs once, here. */ function sourceGet(e, n, t) {
162
+ if (n === SOURCE_OMIT) {
163
+ if (isHidden(e, t)) return undefined;
164
+ return e.kind === SOURCE_MERGE ? mergeGet(e.source, t) : viewSource(e)[t];
165
+ }
166
+ return leafOf(e, n)[t];
167
+ }
168
+
169
+ // An entry whose own key set is fixed: a plain object, or a view over one —
170
+ // an omit of a plain object, or of a merge whose entries all are. Not a
171
+ // store (its key set is a tracked signal), not a merge memo source (it
172
+ // swaps whole objects), and not any proxy that declares itself with
173
+ // `$PROXY in s` — a frames slot proxy answers `has` for every key and lists
174
+ // none, so only the `in` walk is right for it.
175
+ function entryHasStaticKeys(e, n) {
176
+ if (n === SOURCE_PLAIN) return true;
177
+ if (n !== SOURCE_OMIT) return false;
178
+ if (e.kind === SOURCE_PLAIN) return true;
179
+ return e.kind === SOURCE_MERGE && mergeHasStaticKeys(e.source);
180
+ }
181
+
182
+ function mergeHasStaticKeys(e) {
183
+ const n = e.sources, t = e.kinds;
184
+ for (let e = 0; e < n.length; e++) if (!entryHasStaticKeys(n[e], t[e])) return false;
185
+ return true;
186
+ }
187
+
188
+ /** @internal Whether the own key set of a props object cannot change
189
+ * reactively: a plain object, or a merge/omit view over plain objects only.
190
+ * A consumer may then decide from `Object.getOwnPropertyDescriptor` once —
191
+ * "no `children` key" or "a data `children`" holds for the object's lifetime,
192
+ * so no tracking scope is needed for it (#3388). For a store, or a view with
193
+ * a store or memo leaf, keys can appear later and the reactive path is the
194
+ * only correct one. */ function hasStaticKeys(e) {
195
+ if (!($PROXY in e)) return true;
196
+ const n = recordOf(e);
197
+ if (n instanceof MergeView) return mergeHasStaticKeys(n);
198
+ return n !== undefined && entryHasStaticKeys(n, SOURCE_OMIT);
199
+ }
200
+
201
+ /**
202
+ * Whether `o[key]` can never change for the lifetime of `o`: the key is a
203
+ * data property of a plain object, or is absent from an object whose key set
204
+ * is fixed. A getter, a key on a store, a memo-backed `merge()` source, or
205
+ * any key of an object whose keys can appear later (a store) is not static.
206
+ *
207
+ * Looks through `merge()`/`omit()` views to the leaf that owns the key. Any
208
+ * object will do, but props are the case it exists for: the compiler encodes
209
+ * a literal at the call site (`as="button"`) as a data property and an
210
+ * expression (`as={isLink() ? "a" : "button"}`) as a getter, so a component
211
+ * library reads the caller's own static/dynamic classification of a prop at
212
+ * runtime — identically on server and client, the compiler emitting the same
213
+ * own DESCRIPTORS on both (the object behind them may differ: the server
214
+ * builds props as a plain-prototype instance with shared getters) — and can
215
+ * take a no-computation path for the literal:
216
+ *
217
+ * ```tsx
218
+ * const Tag = dynamic(() => props.as, { static: isStatic(props, "as") });
219
+ * ```
220
+ *
221
+ * One descriptor lookup; no read of the value, nothing tracked.
222
+ */ function isStatic(e, n) {
223
+ if ($PROXY in e) {
224
+ // A store answers its descriptor trap with a value; through a view the
225
+ // descriptor is truthful (see `sourceDescriptor`). A foreign proxy is
226
+ // opaque: nothing about it is known to be fixed.
227
+ if (viewOf(e) === undefined) return false;
228
+ const t = Reflect.getOwnPropertyDescriptor(e, n);
229
+ return t === undefined ? hasStaticKeys(e) : t.get === undefined;
230
+ }
231
+ const t = Reflect.getOwnPropertyDescriptor(e, n);
232
+ return t === undefined || t.get === undefined && t.set === undefined;
233
+ }
234
+
235
+ function accessorDescriptor(e, n = true) {
236
+ return {
237
+ configurable: true,
238
+ enumerable: n,
239
+ get: e,
240
+ set: trueFn
241
+ };
242
+ }
243
+
244
+ /** The descriptor a consumer should see for `key` on an entry —
245
+ * the view proxies answer `getOwnPropertyDescriptor` with it, so it tells the
246
+ * truth through any depth of merge/omit layers.
247
+ *
248
+ * A DATA descriptor means "nothing reactive can hide behind this value": the
249
+ * key is a data property of a plain-object leaf — the compiler's own
250
+ * encoding of a static attribute. Everything else is an accessor: a getter
251
+ * on a leaf, a key on a store proxy (its "data" is a signal), or a key on a
252
+ * merge memo source (the whole object is reactive). That is what lets a
253
+ * consumer skip a reactive node for a static prop at the bottom of a
254
+ * component chain, and it is why the store case must NOT forward the store's
255
+ * own descriptor, which reports a value.
256
+ *
257
+ * `configurable: true` always — the target has no such property, and the
258
+ * Proxy invariants forbid reporting a non-configurable one. */
259
+ // `present` says the caller has already established `key in s` (a trap's
260
+ // shadowing walk did), so a store is not asked a second time.
261
+ function sourceDescriptor(e, n, t, r = false) {
262
+ if (n === SOURCE_OMIT) {
263
+ if (isHidden(e, t)) return undefined;
264
+ return sourceDescriptor(e.source, e.kind, t, r);
265
+ }
266
+ // An omit's merge record: the descriptor of the last entry that has the
267
+ // key, as the merge proxy's own trap answers (see `mergeDescriptor`).
268
+ if (n === SOURCE_MERGE) return mergeDescriptor(e, t);
269
+ // A memo source (`merge(() => …)`) is reactive wholesale: whatever shape
270
+ // the memo's current object has, the key is an accessor here.
271
+ if (n === SOURCE_MEMO) {
272
+ return r || t in leafOf(e, n) ? accessorDescriptor(() => leafOf(e, n)[t]) : undefined;
273
+ }
274
+ if (n === SOURCE_PROXY) {
275
+ // Another view (an omit's source may be a merge proxy) already answers
276
+ // truthfully. A store's reported "data" is a signal, and a foreign proxy
277
+ // (frames slot props) has no own descriptors: for both, existence is
278
+ // `in` and the kind is accessor — one trap, and never the store's
279
+ // descriptor path.
280
+ if (recordOf(e) !== undefined) return Reflect.getOwnPropertyDescriptor(e, t);
281
+ return r || t in e ? accessorDescriptor(() => e[t]) : undefined;
282
+ }
283
+ const i = Reflect.getOwnPropertyDescriptor(e, t);
284
+ if (i === undefined) return undefined;
285
+ if (i.get !== undefined || i.set !== undefined) return accessorDescriptor(() => e[t], i.enumerable);
286
+ // The proxy target has no such key, so the descriptor must be configurable;
287
+ // Reflect's is a fresh object, so a configurable one is handed out as is.
288
+ if (i.configurable) return i;
289
+ return {
290
+ configurable: true,
291
+ enumerable: i.enumerable,
292
+ writable: true,
293
+ value: i.value
294
+ };
295
+ }
296
+
297
+ // Own ENUMERABLE keys, symbols included, of an entry — the user-facing key
298
+ // set (`Object.keys(merged)`), where enumerability matters (#2769).
299
+ function sourceEnumerableKeys(e, n) {
300
+ {
301
+ if (e.kind === SOURCE_MERGE) return mergeEnumerableKeys(e.source, e);
302
+ const n = ownEnumerableKeys(viewSource(e));
303
+ const t = [];
304
+ for (let r = 0; r < n.length; r++) if (!isHidden(e, n[r])) t.push(n[r]);
305
+ return t;
306
+ }
307
+ }
308
+
309
+ // The target of a merge() proxy: the flattened sources, read by one shared
310
+ // handler — like OmitView, no per-instance closures. `sources` is what
311
+ // `mergeSources` answers.
312
+ /** @internal */ class MergeView {
313
+ sources;
314
+ kinds;
315
+ /** key → the plain leaf that owns it (later sources win), built by an
316
+ * enumeration or once the reads have paid for it (see `resolvedTable`)
317
+ * when every leaf has static keys; `null` when one doesn't. Until then
318
+ * the slot counts the per-key trap reads so far. One slot rather than a
319
+ * counter field of its own: a view is built per source per component
320
+ * layer, and each field initializer is a measurable share of a
321
+ * constructor that small in the lower JIT tiers. */
322
+ table=0;
323
+ /** see `tableOwnKeys` / `tableDescriptor` */
324
+ keys=undefined;
325
+ descs=undefined;
326
+ constructor(e,
327
+ /** `kinds[i]` is what `sources[i]` is (see `SourceKind`). */
328
+ n) {
329
+ this.sources = e;
330
+ this.kinds = n;
331
+ }
332
+ }
333
+
334
+ /** @internal The `MergeView` behind a `merge()` proxy — its flattened
335
+ * `sources` with their `kinds` — or undefined. */ function mergeView(e) {
336
+ if (e == null || !($PROXY in e)) return undefined;
337
+ const n = e[$RECORD];
338
+ return n instanceof MergeView ? n : undefined;
339
+ }
340
+
341
+ /** @internal The record behind a merge() or omit() proxy — a `MergeView`
342
+ * (flattened `sources` with their `kinds`) or an `OmitView` — or undefined
343
+ * for anything else (a plain object, a store, a foreign proxy). Two fast
344
+ * traps on a proxy (`has`, then `$RECORD`), none on a plain object. */ function viewOf(e) {
345
+ return e != null && $PROXY in e ? e[$RECORD] : undefined;
346
+ }
347
+
348
+ /** @internal The resolved key table of a merge/omit view — every own key of
349
+ * the view mapped to the plain object that owns it, in merged order (a key
350
+ * at the position of the last source that carries it, see `tableSet`) — or
351
+ * undefined when it has none: a leaf is a store or a memo source, whose
352
+ * keys can change, or the object is not a view at all.
353
+ *
354
+ * This is the flat object the eager copy used to build, made lazily and
355
+ * without copying: one pass over the leaves' own keys, then every
356
+ * `get`/`has`/descriptor is one lookup plus one read of the owning leaf, and
357
+ * a consumer (`spread` rerunning its effect) walks the table instead of
358
+ * re-deriving shadowing from the leaves each time. Own keys only, as the
359
+ * copy's were: a plain source's key set is fixed once merged (keys added to
360
+ * it later are not seen — the copy didn't see them either).
361
+ *
362
+ * It is built by an ENUMERATION — the `ownKeys` trap, or a consumer asking
363
+ * for it here — or once per-key reads have paid for it (`READS_FOR_TABLE`),
364
+ * not on the first read. A per-key read has a direct answer (a walk of the
365
+ * sources, last to first, one `in` each) whose cost is the source count,
366
+ * while the table's is every key of every leaf, so the walk wins until a
367
+ * view has been read about as many times as it has keys. On the server it
368
+ * never is: a component reads its props a few times, the element enumerates
369
+ * them once through its own source walk, and the view is gone — building on
370
+ * first read there cost a component chain a table per layer (profiled on
371
+ * the Kobalte-shaped chain: a third of SSR time in the table code and its
372
+ * garbage). On the
373
+ * client a view read on every reactive rerun crosses the threshold in its
374
+ * first few updates and is one lookup per read from then on, as before.
375
+ * Once built — by a `spread`, `Object.keys`, `{...props}`, or the count —
376
+ * every trap uses it. */ function resolvedTable(e) {
377
+ if (e == null || !($PROXY in e)) return undefined;
378
+ const n = recordOf(e);
379
+ if (n instanceof OmitView) return omitTable(n);
380
+ return n === undefined ? undefined : mergeTable(n);
381
+ }
382
+
383
+ function mergeTable(e) {
384
+ let n = e.table;
385
+ if (typeof n !== "object") {
386
+ // a read count: not decided yet
387
+ const t = e.sources, r = e.kinds;
388
+ for (let n = 0; n < t.length; n++) {
389
+ if (!entryHasStaticKeys(t[n], r[n])) {
390
+ e.table = null;
391
+ return undefined;
392
+ }
393
+ }
394
+ n = new Map;
395
+ collectTable(n, e, undefined);
396
+ e.table = n;
397
+ }
398
+ return n === null ? undefined : n;
399
+ }
400
+
401
+ // One pass over a merge record's leaves into `table`, through the nested
402
+ // omit-over-merge entries — the filters enclosing the current leaf are the
403
+ // `filters` stack — so a component chain builds ONE table at the view that
404
+ // asked, not one per layer. A key an entry hides that an EARLIER entry owned
405
+ // must stay: a filter applies to its own entry's contribution, not to the
406
+ // merge, which is exactly what the stack expresses. Every entry has static
407
+ // keys (the caller checked), so a leaf's own keys are the truth.
408
+ function collectTable(e, n, t) {
409
+ const r = n.sources, i = n.kinds;
410
+ for (let n = 0; n < r.length; n++) {
411
+ const f = r[n];
412
+ if (i[n] === SOURCE_OMIT) {
413
+ if (f.kind === SOURCE_MERGE) {
414
+ if (t === undefined) t = [ f ]; else t.push(f);
415
+ collectTable(e, f.source, t);
416
+ t.pop();
417
+ continue;
418
+ }
419
+ const n = f.source;
420
+ const r = Reflect.ownKeys(n);
421
+ for (let i = 0; i < r.length; i++) {
422
+ const u = r[i];
423
+ if (!isHidden(f, u) && !hiddenByAny(t, u)) tableSet(e, u, n);
424
+ }
425
+ } else {
426
+ const n = Reflect.ownKeys(f);
427
+ for (let r = 0; r < n.length; r++) {
428
+ const i = n[r];
429
+ if (!hiddenByAny(t, i)) tableSet(e, i, f);
430
+ }
431
+ }
432
+ }
433
+ }
434
+
435
+ function hiddenByAny(e, n) {
436
+ if (e !== undefined) for (let t = e.length - 1; t >= 0; t--) if (isHidden(e[t], n)) return true;
437
+ return false;
438
+ }
439
+
440
+ // Key order is the merged one — every key at the position of the LAST source
441
+ // that carries it — the order `ssrElement`'s array form serializes in and the
442
+ // eager copy enumerated in, so a spread through a view and a spread over the
443
+ // sources emit the same attribute order.
444
+ function tableSet(e, n, t) {
445
+ if (e.has(n)) e.delete(n);
446
+ e.set(n, t);
447
+ }
448
+
449
+ // An omit view's table: its source's (a merge's table, or a plain object's
450
+ // own keys) minus the hidden keys. Cached on the record.
451
+ function omitTable(e) {
452
+ let n = e.table;
453
+ if (typeof n !== "object") {
454
+ const t = e.source;
455
+ if (e.kind === SOURCE_MERGE) {
456
+ // One pass over the merge's leaves with this filter on the stack —
457
+ // the merge record builds no table of its own for it.
458
+ if (!mergeHasStaticKeys(t)) {
459
+ e.table = null;
460
+ return undefined;
461
+ }
462
+ n = new Map;
463
+ collectTable(n, t, [ e ]);
464
+ } else if (e.kind === SOURCE_PLAIN) {
465
+ n = new Map;
466
+ const r = Reflect.ownKeys(t);
467
+ for (let i = 0; i < r.length; i++) {
468
+ const f = r[i];
469
+ if (!isHidden(e, f)) n.set(f, t);
470
+ }
471
+ } else {
472
+ // a store or a memo: keys can change, no table
473
+ e.table = null;
474
+ return undefined;
475
+ }
476
+ e.table = n;
477
+ }
478
+ return n === null ? undefined : n;
479
+ }
480
+
481
+ // The user-facing key set of a resolved table: its keys that are enumerable
482
+ // on the leaf that owns them (`Object.keys(merged)`, #2769). Fixed, like the
483
+ // table, so it is built once per view: an `ownKeys` trap may hand back the
484
+ // same array every time (the engine copies it).
485
+ const propertyIsEnumerable = Object.prototype.propertyIsEnumerable;
486
+
487
+ function tableOwnKeys(e, n) {
488
+ let t = e.keys;
489
+ if (t === undefined) {
490
+ t = e.keys = [];
491
+ for (const [e, r] of n) if (propertyIsEnumerable.call(r, e)) t.push(e);
492
+ }
493
+ return t;
494
+ }
495
+
496
+ // The descriptor for a table key — its owning leaf's, truthful (see
497
+ // `sourceDescriptor`) — with the shape cached per key so an enumeration
498
+ // (`for…in`, `Object.keys`, `{...props}`: a descriptor trap per key, on
499
+ // every pass) does not re-read the leaf's descriptor and re-allocate a
500
+ // getter each time. An accessor reads live, so its descriptor is reused as
501
+ // is; a data descriptor is rebuilt with the current value.
502
+ function tableDescriptor(e, n, t) {
503
+ const r = n.get(t);
504
+ if (r === undefined) return undefined;
505
+ let i = e.descs;
506
+ if (i === undefined) i = e.descs = new Map;
507
+ let f = i.get(t);
508
+ if (f === undefined) {
509
+ f = sourceDescriptor(r, SOURCE_PLAIN, t);
510
+ if (f === undefined) return undefined;
511
+ i.set(t, f);
512
+ return f;
513
+ }
514
+ if (f.get !== undefined) return f;
515
+ return {
516
+ configurable: true,
517
+ enumerable: f.enumerable,
518
+ writable: f.writable,
519
+ value: r[t]
520
+ };
521
+ }
522
+
523
+ // Per-key trap reads a view takes before building its table, from the
524
+ // break-even: a build is ~60 ns per key (an `ownKeys` share, a `has`, a
525
+ // `set`), a walk ~20 ns per source (an `in`, a hidden-list check), and a
526
+ // leaf carries about five keys — so the table has paid for itself after
527
+ // ~15 reads. Measured on the Kobalte-shaped chain: a walk is 2× a lookup at
528
+ // depth 1 and up to 10× for a first-source key at depth 7 (a walk through
529
+ // seven nested layers, a hidden-list check at each), so a view read on
530
+ // every update wants the table; a view read a handful of times (every
531
+ // server-side view) never wants it.
532
+ const READS_FOR_TABLE = 16;
533
+
534
+ // The table for a per-key trap: the one a view HAS (built by an enumeration
535
+ // or an earlier read, see `resolvedTable`), or the one this read pays for,
536
+ // or none — a walk answers. One per view type, so a trap pays no type check.
537
+ // A settled slot is an object (the Map, or `null`); a number is the count.
538
+ function mergeReadTable(e) {
539
+ const n = e.table;
540
+ if (typeof n === "object") return n === null ? undefined : n;
541
+ if (n + 1 < READS_FOR_TABLE) {
542
+ e.table = n + 1;
543
+ return undefined;
544
+ }
545
+ return mergeTable(e);
546
+ }
547
+
548
+ // Only for an omit over a merge (`kind === SOURCE_MERGE`; the caller checks,
549
+ // inline — a call is not free in every tier): an omit over one object reads
550
+ // it directly — a list check and a property read, nothing a table would
551
+ // shorten.
552
+ function omitReadTable(e) {
553
+ const n = e.table;
554
+ if (typeof n === "object") return n === null ? undefined : n;
555
+ if (n + 1 < READS_FOR_TABLE) {
556
+ e.table = n + 1;
557
+ return undefined;
558
+ }
559
+ return omitTable(e);
560
+ }
561
+
562
+ // The table a record HAS — built already by an enumeration or a trap's read
563
+ // count — or undefined. What a nested walk asks: a record reached through an
564
+ // outer view's entry counts no reads of its own (the outer view decides for
565
+ // the whole tree, and its table build then builds the inner ones), so the
566
+ // inner merges of a component chain build nothing on the server where the
567
+ // leaves are read a few times each.
568
+ function tableOf(e) {
569
+ const n = e.table;
570
+ return typeof n === "object" && n !== null ? n : undefined;
571
+ }
572
+
573
+ // "no entry has the key" — distinct from an entry that holds `undefined`.
574
+ const MISSING = Symbol();
575
+
576
+ // The read: the value of the last entry that has the key, or MISSING. ONE
577
+ // walk — a nested omit-over-merge entry answers presence and value together,
578
+ // so a chain of layers is walked once per read, not once per layer per
579
+ // level.
580
+ function mergeLookup(e, n) {
581
+ const t = tableOf(e);
582
+ if (t !== undefined) {
583
+ const e = t.get(n);
584
+ return e === undefined ? MISSING : e[n];
585
+ }
586
+ const r = e.sources, i = e.kinds;
587
+ for (let e = r.length - 1; e >= 0; e--) {
588
+ const t = i[e];
589
+ // The common leaf first, read in place: a component's props view is a
590
+ // few plain objects, read once per key on the server.
591
+ if (t === SOURCE_PLAIN) {
592
+ const t = r[e];
593
+ if (n in t) return t[n];
594
+ continue;
595
+ }
596
+ if (t === SOURCE_OMIT) {
597
+ const t = r[e];
598
+ if (isHidden(t, n)) continue;
599
+ if (t.kind === SOURCE_MERGE) {
600
+ const e = mergeLookup(t.source, n);
601
+ if (e !== MISSING) return e;
602
+ continue;
603
+ }
604
+ const i = viewSource(t);
605
+ if (n in i) return i[n];
606
+ } else {
607
+ const i = leafOf(r[e], t);
608
+ if (n in i) return i[n];
609
+ }
610
+ }
611
+ return MISSING;
612
+ }
613
+
614
+ function mergeGet(e, n) {
615
+ const t = mergeLookup(e, n);
616
+ return t === MISSING ? undefined : t;
617
+ }
618
+
619
+ // `key in merge`, on the record.
620
+ function mergeHas(e, n) {
621
+ const t = tableOf(e);
622
+ if (t !== undefined) return t.has(n);
623
+ const r = e.sources, i = e.kinds;
624
+ for (let e = r.length - 1; e >= 0; e--) if (sourceHas(r[e], i[e], n)) return true;
625
+ return false;
626
+ }
627
+
628
+ // The proxy's `getOwnPropertyDescriptor`, on the record.
629
+ function mergeDescriptor(e, n) {
630
+ const t = tableOf(e);
631
+ if (t !== undefined) return tableDescriptor(e, t, n);
632
+ const r = e.sources, i = e.kinds;
633
+ for (let t = r.length - 1; t >= 0; t--) {
634
+ if (!sourceHas(r[t], i[t], n)) continue;
635
+ // `in` also answers for inherited keys, which have no own descriptor.
636
+ return sourceDescriptor(r[t], i[t], n, true) ?? accessorDescriptor(() => mergeGet(e, n));
637
+ }
638
+ return undefined;
639
+ }
640
+
641
+ // Own keys of a merge record in merged order — every key at the position
642
+ // of the LAST entry that carries it, the order the table keeps and
643
+ // `ssrElement` serializes in. `enumerable` selects the user-facing set
644
+ // (`Object.keys`, #2769) over every own string key (a consumer's walk);
645
+ // `filter` is the omit this record is read through, applied as the keys
646
+ // are gathered so an omit over a merge builds ONE list per layer. A list
647
+ // with `indexOf` rather than a Set: a props object has a dozen keys, and a
648
+ // Set's hash store was 2 KB per row on the Kobalte-shaped chain.
649
+ function mergeKeysOf(e, n, t) {
650
+ const r = [];
651
+ collectKeys(e, t === undefined ? undefined : [ t ], n, r, null);
652
+ return r;
653
+ }
654
+
655
+ // One pass over a merge record's leaves — through its nested omit-over-merge
656
+ // entries, `filters` the omits enclosing the current leaf (see
657
+ // `collectTable`) — appending each leaf's keys to `keys` in merged order
658
+ // (a key already listed moves to the end: later wins) and, when `owners` is
659
+ // given, the object that owns the key at the same index. A consumer that
660
+ // reads every key once (`ssrElement`) then reads `owners[i][keys[i]]`: no
661
+ // `in` walk per key, no table. A memo leaf is resolved once here.
662
+ function collectKeys(e, n, t, r, i) {
663
+ const f = e.sources, u = e.kinds;
664
+ for (let e = 0; e < f.length; e++) {
665
+ let o = f[e], c = u[e];
666
+ let s;
667
+ if (c === SOURCE_OMIT) {
668
+ if (o.kind === SOURCE_MERGE) {
669
+ if (n === undefined) n = [ o ]; else n.push(o);
670
+ collectKeys(o.source, n, t, r, i);
671
+ n.pop();
672
+ continue;
673
+ }
674
+ s = o;
675
+ c = o.kind;
676
+ o = o.source;
677
+ }
678
+ o = leafOf(o, c);
679
+ const d = t ? ownEnumerableKeys(o) : leafKeys(o, c);
680
+ for (let e = 0; e < d.length; e++) {
681
+ const t = d[e];
682
+ if (s !== undefined && isHidden(s, t)) continue;
683
+ if (hiddenByAny(n, t)) continue;
684
+ addKey(r, i, t, o);
685
+ }
686
+ }
687
+ }
688
+
689
+ // Append `key` owned by `owner`, moving an earlier listing to the end: later
690
+ // wins, and the position is the last owner's (the merged order).
691
+ function addKey(e, n, t, r) {
692
+ const i = e.indexOf(t);
693
+ if (i !== -1) {
694
+ e.splice(i, 1);
695
+ if (n !== null) n.splice(i, 1);
696
+ }
697
+ e.push(t);
698
+ if (n !== null) n.push(r);
699
+ }
700
+
701
+ /** @internal Every own string key of a props SOURCE — a plain object, a
702
+ * store or foreign proxy, or a merge/omit view — appended to `keys` in
703
+ * merged order with the object that owns each at the same index of
704
+ * `owners`: a key already listed (by this source or an earlier one) moves
705
+ * to the end, so several sources collected in turn give the order and the
706
+ * winners a merge of them would. A consumer that reads each key once
707
+ * (`ssrElement`) then reads `owners[i][keys[i]]` — the owner's getter runs
708
+ * there, once — and asks nothing else of a view: no table, no `in` walk per
709
+ * key through the merge/omit layers, no key list per leaf. One pass,
710
+ * however deep the layers nest. Symbols are listed; the consumer skips
711
+ * them. */ function sourceOwners(e, n, t) {
712
+ if ($PROXY in e) {
713
+ const r = viewOf(e);
714
+ if (r === undefined) {
715
+ // a store: one `ownKeys` trap, reads through `[]`
716
+ const r = Reflect.ownKeys(e);
717
+ for (let i = 0; i < r.length; i++) addKey(n, t, r[i], e);
718
+ return;
719
+ }
720
+ if (r instanceof OmitView) {
721
+ if (r.kind === SOURCE_MERGE) return collectKeys(r.source, [ r ], false, n, t);
722
+ const e = viewSource(r);
723
+ const i = leafKeys(e, r.kind);
724
+ for (let f = 0; f < i.length; f++) if (!isHidden(r, i[f])) addKey(n, t, i[f], e);
725
+ return;
726
+ }
727
+ return collectKeys(r, undefined, false, n, t);
728
+ }
729
+ const r = Object.keys(e);
730
+ for (let i = 0; i < r.length; i++) addKey(n, t, r[i], e);
731
+ }
732
+
733
+ // The user-facing key set of a merge record, read through `filter` if given.
734
+ function mergeEnumerableKeys(e, n) {
735
+ const t = mergeTable(e);
736
+ if (t === undefined) return mergeKeysOf(e, true, n);
737
+ const r = tableOwnKeys(e, t);
738
+ if (n === undefined) return r;
739
+ const i = [];
740
+ for (let e = 0; e < r.length; e++) if (!isHidden(n, r[e])) i.push(r[e]);
741
+ return i;
742
+ }
743
+
744
+ const mergeTraps = {
745
+ get(e, n, t) {
746
+ // The private keys are symbols; a string read (every prop) skips the
747
+ // compares. `$TARGET` is answered so a store check never walks the
748
+ // sources (a leaf that is a store would answer it).
749
+ if (typeof n === "symbol") {
750
+ if (n === $PROXY) return t;
751
+ if (n === $RECORD) return e;
752
+ if (n === $TARGET) return undefined;
753
+ }
754
+ // A trap read counts toward the table (see `mergeReadTable`); the walk
755
+ // itself is the record's. `mergeReadTable` and the plain walk of
756
+ // `mergeLookup` are inlined here: a trap is entered from the runtime, so
757
+ // nothing below it is inlined for it, and a component's props view is a
758
+ // few plain objects read once per key on the server — the walk is the
759
+ // whole read. A leaf that is not plain hands the walk to `mergeGet`,
760
+ // which starts over (a plain leaf walked twice is two `in` checks).
761
+ const r = e.table;
762
+ let i;
763
+ if (typeof r !== "object") {
764
+ if (r + 1 < READS_FOR_TABLE) {
765
+ e.table = r + 1;
766
+ const t = e.sources, i = e.kinds;
767
+ for (let r = t.length - 1; r >= 0; r--) {
768
+ if (i[r] !== SOURCE_PLAIN) return mergeGet(e, n);
769
+ // Read first, `in` only to tell a missing key from one holding
770
+ // undefined: the last source is the one that usually has the key.
771
+ const f = t[r][n];
772
+ if (f !== undefined || n in t[r]) return f;
773
+ }
774
+ return undefined;
775
+ }
776
+ i = mergeTable(e);
777
+ if (i === undefined) return mergeGet(e, n);
778
+ } else if (r === null) return mergeGet(e, n); else i = r;
779
+ const f = i.get(n);
780
+ return f === undefined ? undefined : f[n];
781
+ },
782
+ has(e, n) {
783
+ if (n === $PROXY) return true;
784
+ if (n === $TARGET || n === $RECORD) return false;
785
+ const t = mergeReadTable(e);
786
+ if (t !== undefined) return t.has(n);
787
+ return mergeHas(e, n);
788
+ },
789
+ set: trueFn,
790
+ deleteProperty: trueFn,
791
+ getOwnPropertyDescriptor(e, n) {
792
+ if (n === $PROXY || n === $TARGET || n === $RECORD) return undefined;
793
+ const t = mergeReadTable(e);
794
+ if (t !== undefined) return tableDescriptor(e, t, n);
795
+ return mergeDescriptor(e, n);
796
+ },
797
+ ownKeys(e) {
798
+ return mergeEnumerableKeys(e);
799
+ }
800
+ };
801
+
802
+ // An omit view reads its source directly — a hidden-key check and one
803
+ // property read; over a merge record, the merge's own walk by function call,
804
+ // never a trap. Once an enumeration or the read count has built its table
805
+ // (over a merge with plain leaves only: the merge's, filtered) every trap
806
+ // answers from that instead.
807
+ const omitTraps = {
808
+ get(e, n, t) {
809
+ if (n === $PROXY) return t;
810
+ // `$RECORD` is THIS view — never the underlying merge's record, which is
811
+ // unfiltered: handing a re-merge the merge's own sources would leak the
812
+ // omitted keys (#3014). A consumer walks the omit record as ONE filtered
813
+ // entry (`recordOf` tells the two records apart by class).
814
+ if (n === $RECORD) return e;
815
+ if (n === $TARGET) return undefined;
816
+ if (e.kind === SOURCE_MERGE) {
817
+ const t = omitReadTable(e);
818
+ if (t !== undefined) {
819
+ const e = t.get(n);
820
+ return e === undefined ? undefined : e[n];
821
+ }
822
+ if (isHidden(e, n)) return undefined;
823
+ return mergeGet(e.source, n);
824
+ }
825
+ if (isHidden(e, n)) return undefined;
826
+ return viewSource(e)[n];
827
+ },
828
+ has(e, n) {
829
+ if (n === $PROXY) return true;
830
+ if (n === $TARGET || n === $RECORD) return false;
831
+ if (e.kind === SOURCE_MERGE) {
832
+ const t = omitReadTable(e);
833
+ if (t !== undefined) return t.has(n);
834
+ if (isHidden(e, n)) return false;
835
+ return mergeHas(e.source, n);
836
+ }
837
+ if (isHidden(e, n)) return false;
838
+ return n in viewSource(e);
839
+ },
840
+ set: trueFn,
841
+ deleteProperty: trueFn,
842
+ getOwnPropertyDescriptor(e, n) {
843
+ if (n === $PROXY || n === $TARGET || n === $RECORD) return undefined;
844
+ if (e.kind === SOURCE_MERGE) {
845
+ const t = omitReadTable(e);
846
+ if (t !== undefined) return tableDescriptor(e, t, n);
847
+ }
848
+ return sourceDescriptor(e, SOURCE_OMIT, n);
849
+ },
850
+ ownKeys(e) {
851
+ if (e.kind === SOURCE_MERGE) {
852
+ const n = omitTable(e);
853
+ if (n !== undefined) return tableOwnKeys(e, n);
854
+ // No table (a store or memo leaf): the merge's own key set, filtered.
855
+ return sourceEnumerableKeys(e);
856
+ }
857
+ const n = Reflect.ownKeys(viewSource(e));
858
+ const t = [];
859
+ for (let r = 0; r < n.length; r++) if (!isHidden(e, n[r])) t.push(n[r]);
860
+ return t;
861
+ }
862
+ };
863
+
864
+ /** @internal The flattened sources behind a `merge()` proxy, or undefined.
865
+ * A merge's writes are no-ops, so its sources are the whole truth. A COPY of
866
+ * a merge (`{...merged}`, a descriptor copy) is a plain object that carries
867
+ * no sources — `ownKeys` never lists $RECORD — so what is on the copy is
868
+ * the truth there and every consumer reads it directly (#3384). */ function mergeSources(e) {
869
+ const n = mergeView(e);
870
+ return n === undefined ? undefined : n.sources;
871
+ }
872
+
873
+ /**
874
+ * Merges multiple props-like objects into a single proxy that *preserves
875
+ * reactivity*. Reads are forwarded to the right-most source that defines the
876
+ * property, so later sources override earlier ones (like `Object.assign`).
877
+ *
878
+ * Function arguments are treated as memo-backed sources — useful for passing
879
+ * derived defaults whose computation should track reactively.
880
+ *
881
+ * The result is a live VIEW of its sources, never a copy: creating it costs
882
+ * nothing per key, every read goes to the source that owns the key (a getter
883
+ * runs there, a data property is read live), and writing to it is a no-op.
884
+ * A single non-function source is returned as is. To own a mutable object,
885
+ * copy it: `{ ...merged }` snapshots the current values.
886
+ *
887
+ * Use this in component bodies to merge defaults / overrides without losing
888
+ * Solid's per-property tracking.
889
+ *
890
+ * Reading props, here and anywhere: a prop's getter is defined only for a
891
+ * read through its own object (`props.x`, `{ ...props }`, `Reflect.get`,
892
+ * these views). Forwarding its descriptor onto another object and reading it
893
+ * there is not supported — the compiler's server-side props keep their state
894
+ * on the instance, so the getter needs its object as receiver. A copy that
895
+ * must stay live defines its own getter that reads through the source, as
896
+ * the no-Proxy paths of merge() and omit() do.
897
+ *
898
+ * @example
899
+ * ```tsx
900
+ * function Button(_props: { label: string; type?: string; disabled?: boolean }) {
901
+ * const props = merge({ type: "button", disabled: false }, _props);
902
+ *
903
+ * return <button type={props.type} disabled={props.disabled}>{props.label}</button>;
904
+ * }
905
+ * ```
906
+ */ function merge(...e) {
907
+ if (e.length === 1 && typeof e[0] !== "function") return e[0];
908
+ // Sized to the argument count up front: a view is built per source per
909
+ // component layer, and growing two empty arrays by `push` was a third of
910
+ // its construction. A nested view's sources may run past the count (the
911
+ // array grows), a falsy source leaves it short (trimmed below).
912
+ const n = new Array(e.length);
913
+ const t = new Array(e.length);
914
+ let r = 0;
915
+ // The one non-falsy source, if there is exactly one: it IS the merge.
916
+ let i = undefined;
917
+ let f = 0;
918
+ for (let u = 0; u < e.length; u++) {
919
+ const o = e[u];
920
+ if (!o) continue;
921
+ f++;
922
+ i = o;
923
+ if (typeof o === "function") {
924
+ // Observe tiers name it and exempt it from UNSTABLE_MEMO_OUTPUT (see
925
+ // CONFIG_KEY_BAG); prod passes no options.
926
+ n[r] = createMemo(o, {
927
+ name: "merge",
928
+ ct: CONFIG_KEY_BAG
929
+ });
930
+ t[r++] = SOURCE_MEMO;
931
+ continue;
932
+ }
933
+ if ($PROXY in o) {
934
+ // A store (or a foreign proxy) is a leaf as it is. A merge() proxy is
935
+ // flattened through: its writes are no-ops, so its sources are exactly
936
+ // what it reads. An omit() proxy joins as its view record — ONE entry,
937
+ // its filter travelling with it, whether it is over a plain object or
938
+ // a whole merge (never the merge's own sources, which would leak the
939
+ // omitted keys, #3014). A consumer's walk recurses into the record.
940
+ const e = recordOf(o);
941
+ if (e instanceof MergeView) {
942
+ for (let i = 0; i < e.sources.length; i++) {
943
+ n[r] = e.sources[i];
944
+ t[r++] = e.kinds[i];
945
+ }
946
+ } else if (e !== undefined) {
947
+ n[r] = e;
948
+ t[r++] = SOURCE_OMIT;
949
+ } else {
950
+ n[r] = o;
951
+ t[r++] = SOURCE_PROXY;
952
+ }
953
+ continue;
954
+ }
955
+ n[r] = o;
956
+ t[r++] = SOURCE_PLAIN;
957
+ }
958
+ if (r !== n.length) {
959
+ n.length = r;
960
+ t.length = r;
961
+ }
962
+ if (SUPPORTS_PROXY) {
963
+ if (f === 1 && typeof i !== "function") return i;
964
+ // Always a view, never a copy. Building a plain object here costs a
965
+ // descriptor read, a bound getter and a defineProperty per key per
966
+ // layer, and component libraries stack several layers per element
967
+ // (defaults → omit → call-site statics → …), so the copies dominated
968
+ // their render cost while every consumer that matters — `spread`,
969
+ // `ssrElement`, a nested merge — reads the flattened sources directly
970
+ // anyway (#3448). The view is O(1) to create and reads through to the
971
+ // sources, so a data property on a source is read live, like a getter.
972
+ // Writes to the result are no-ops (a consumer that needs its own object
973
+ // copies: `{...merged}`, which the traps answer truthfully). Copies of
974
+ // the result never carry $RECORD (#3384): `ownKeys` answers only the
975
+ // sources' keys.
976
+ return new Proxy(new MergeView(n, t), mergeTraps);
977
+ }
978
+ // No Proxy: an eager descriptor copy, semantics as close to the view as a
979
+ // plain object allows (getters stay live; data properties are snapshots).
980
+ const u = Object.create(null);
981
+ let o = false;
982
+ let c = n.length - 1;
983
+ for (let e = c; e >= 0; e--) {
984
+ const t = n[e];
985
+ if (!t) {
986
+ e === c && c--;
987
+ continue;
988
+ }
989
+ const r = Object.getOwnPropertyNames(t);
990
+ for (let n = r.length - 1; n >= 0; n--) {
991
+ const i = r[n];
992
+ if (i === "__proto__" || i === "constructor") continue;
993
+ if (!u[i]) {
994
+ o = o || e !== c;
995
+ const n = Object.getOwnPropertyDescriptor(t, i);
996
+ u[i] = n.get ? {
997
+ enumerable: true,
998
+ configurable: true,
999
+ get: n.get.bind(t)
1000
+ } : n;
1001
+ }
1002
+ }
1003
+ }
1004
+ if (!o) return n[c];
1005
+ const s = {};
1006
+ const d = Object.keys(u);
1007
+ for (let e = d.length - 1; e >= 0; e--) {
1008
+ const n = d[e], t = u[n];
1009
+ if (t.get) Object.defineProperty(s, n, t); else s[n] = t.value;
1010
+ }
1011
+ return s;
1012
+ }
1013
+
1014
+ function omit(e, ...n) {
1015
+ let t = n.length === 1 && typeof n[0] === "function" ? n[0] : n;
1016
+ if (SUPPORTS_PROXY) {
1017
+ // A view over a view folds: one record, both filters, the original
1018
+ // source — so a consumer walks the real object however deep the omits go.
1019
+ // Over a merge() proxy the source is the merge's RECORD (see OmitView):
1020
+ // one record whatever the leaf count, read by function call.
1021
+ let n = e;
1022
+ let r = SOURCE_PLAIN;
1023
+ if (typeof e === "function") r = SOURCE_MEMO; else if ($PROXY in e) {
1024
+ r = SOURCE_PROXY;
1025
+ const i = recordOf(e);
1026
+ if (i instanceof OmitView) {
1027
+ n = i.source;
1028
+ r = i.kind;
1029
+ t = combineHidden(i.hidden, t);
1030
+ } else if (i !== undefined) {
1031
+ n = i;
1032
+ r = SOURCE_MERGE;
1033
+ }
1034
+ }
1035
+ return new Proxy(new OmitView(n, r, t), omitTraps);
1036
+ }
1037
+ const r = {};
1038
+ const i = Object.getOwnPropertyNames(e);
1039
+ const f = typeof t === "function" ? t : t.length > 4 && i.length > t.length ? (e => n => e.has(n))(new Set(t)) : e => t.includes(e);
1040
+ for (const n of i) {
1041
+ if (!f(n)) {
1042
+ const t = Object.getOwnPropertyDescriptor(e, n);
1043
+ if (!t.get && !t.set && t.enumerable && t.writable && t.configurable) {
1044
+ r[n] = t.value;
1045
+ } else if (t.get || t.set) {
1046
+ // An accessor is re-homed with its source as receiver, never copied
1047
+ // as-is: a props getter is only defined for a read THROUGH its own
1048
+ // object (the compiler's server props keep their state on the
1049
+ // instance, so a forwarded descriptor read on the copy throws). Same
1050
+ // rule as merge()'s copy path above.
1051
+ Object.defineProperty(r, n, {
1052
+ enumerable: t.enumerable,
1053
+ configurable: true,
1054
+ get: t.get && t.get.bind(e),
1055
+ set: t.set && t.set.bind(e)
1056
+ });
1057
+ } else Object.defineProperty(r, n, t);
1058
+ }
1059
+ }
1060
+ return r;
1061
+ }
1062
+
1063
+ export { MergeView, OmitView, SOURCE_MEMO, SOURCE_MERGE, SOURCE_OMIT, SOURCE_PLAIN, SOURCE_PROXY, hasStaticKeys, isStatic, merge, mergeSources, mergeView, omit, omitView, resolvedTable, sourceGet, sourceHas, sourceKeys, sourceOwners, viewOf };