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