@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.
Files changed (134) hide show
  1. package/dist/dev-shared.js +6357 -0
  2. package/dist/dev.attribution.js +2485 -0
  3. package/dist/dev.js +2851 -7027
  4. package/dist/observe/affects.js +129 -0
  5. package/dist/observe/attribution.js +7 -0
  6. package/dist/observe/boundaries.js +641 -0
  7. package/dist/observe/core/action.js +177 -0
  8. package/dist/observe/core/async.js +846 -0
  9. package/dist/observe/core/attribution-costs.js +66 -0
  10. package/dist/observe/core/attribution-feedback.js +282 -0
  11. package/dist/observe/core/attribution-hooks.js +82 -0
  12. package/dist/observe/core/attribution-queries.js +28 -0
  13. package/dist/observe/core/attribution.js +2095 -0
  14. package/dist/observe/core/constants.js +248 -0
  15. package/dist/{types-cjs/core/context.d.cts → observe/core/context.js} +37 -12
  16. package/dist/observe/core/core.js +1789 -0
  17. package/dist/observe/core/dev.js +293 -0
  18. package/dist/observe/core/effect.js +195 -0
  19. package/dist/observe/core/error-hooks.js +71 -0
  20. package/dist/observe/core/error.js +80 -0
  21. package/dist/observe/core/external.js +98 -0
  22. package/dist/observe/core/graph.js +155 -0
  23. package/dist/observe/core/heap.js +147 -0
  24. package/dist/observe/core/invariants.js +45 -0
  25. package/dist/observe/core/lanes.js +205 -0
  26. package/dist/observe/core/optimistic.js +585 -0
  27. package/dist/observe/core/owner.js +322 -0
  28. package/dist/observe/core/scheduler.js +1428 -0
  29. package/dist/observe/core/verdict.js +669 -0
  30. package/dist/observe/index.js +59 -0
  31. package/dist/observe/map.js +484 -0
  32. package/dist/{types-cjs/signals.d.cts → observe/signals.js} +311 -317
  33. package/dist/observe/store/index.js +40 -0
  34. package/dist/observe/store/next/optimistic.js +660 -0
  35. package/dist/observe/store/next/projection.js +255 -0
  36. package/dist/observe/store/next/reconcile.js +375 -0
  37. package/dist/observe/store/next/store.js +2327 -0
  38. package/dist/observe/store/next/target.js +51 -0
  39. package/dist/observe/store/store.js +325 -0
  40. package/dist/observe/store/storePath.js +103 -0
  41. package/dist/observe/store/utils.js +1023 -0
  42. package/dist/prod/attribution.js +41 -0
  43. package/dist/prod/boundaries.js +128 -76
  44. package/dist/prod/core/action.js +65 -37
  45. package/dist/prod/core/async.js +324 -172
  46. package/dist/prod/core/constants.js +57 -1
  47. package/dist/prod/core/context.js +3 -3
  48. package/dist/prod/core/core.js +1003 -364
  49. package/dist/prod/core/dev.js +17 -1
  50. package/dist/prod/core/effect.js +76 -42
  51. package/dist/prod/core/error-hooks.js +71 -0
  52. package/dist/prod/core/external.js +4 -4
  53. package/dist/prod/core/graph.js +37 -37
  54. package/dist/prod/core/heap.js +61 -56
  55. package/dist/prod/core/lanes.js +107 -63
  56. package/dist/prod/core/optimistic.js +374 -93
  57. package/dist/prod/core/owner.js +62 -46
  58. package/dist/prod/core/scheduler.js +653 -286
  59. package/dist/prod/core/verdict.js +245 -127
  60. package/dist/prod/index.js +15 -5
  61. package/dist/prod/map.js +292 -141
  62. package/dist/prod/signals.js +29 -16
  63. package/dist/prod/store/next/optimistic.js +77 -55
  64. package/dist/prod/store/next/projection.js +31 -20
  65. package/dist/prod/store/next/reconcile.js +87 -84
  66. package/dist/prod/store/next/store.js +718 -401
  67. package/dist/prod/store/next/target.js +32 -10
  68. package/dist/prod/store/store.js +12 -14
  69. package/dist/prod/store/utils.js +950 -130
  70. package/dist/types/attribution.d.ts +20 -0
  71. package/dist/types/attribution.prod.d.ts +22 -0
  72. package/dist/types/boundaries.d.ts +10 -1
  73. package/dist/types/core/action.d.ts +12 -5
  74. package/dist/types/core/async.d.ts +1 -1
  75. package/dist/types/core/attribution-costs.d.ts +35 -0
  76. package/dist/types/core/attribution-feedback.d.ts +133 -0
  77. package/dist/types/core/attribution-hooks.d.ts +147 -9
  78. package/dist/types/core/attribution-queries.d.ts +10 -0
  79. package/dist/types/core/attribution.d.ts +216 -182
  80. package/dist/types/core/constants.d.ts +56 -0
  81. package/dist/types/core/core.d.ts +190 -2
  82. package/dist/types/core/dev.d.ts +246 -28
  83. package/dist/types/core/effect.d.ts +8 -1
  84. package/dist/types/core/error-hooks.d.ts +71 -0
  85. package/dist/types/core/index.d.ts +4 -1
  86. package/dist/types/core/invariants.d.ts +4 -0
  87. package/dist/types/core/lanes.d.ts +39 -5
  88. package/dist/types/core/scheduler.d.ts +153 -0
  89. package/dist/types/core/types.d.ts +32 -9
  90. package/dist/types/index.d.ts +10 -3
  91. package/dist/types/map.d.ts +2 -0
  92. package/dist/types/signals.d.ts +8 -0
  93. package/dist/types/store/index.d.ts +2 -0
  94. package/dist/types/store/next/optimistic.d.ts +1 -1
  95. package/dist/types/store/next/store.d.ts +11 -5
  96. package/dist/types/store/next/target.d.ts +37 -10
  97. package/dist/types/store/utils.d.ts +178 -0
  98. package/package.json +21 -17
  99. package/dist/node.cjs +0 -10541
  100. package/dist/node.dev.cjs +0 -13724
  101. package/dist/types-cjs/affects.d.cts +0 -47
  102. package/dist/types-cjs/boundaries.d.cts +0 -175
  103. package/dist/types-cjs/core/action.d.cts +0 -64
  104. package/dist/types-cjs/core/async.d.cts +0 -23
  105. package/dist/types-cjs/core/attribution-hooks.d.cts +0 -127
  106. package/dist/types-cjs/core/attribution.d.cts +0 -495
  107. package/dist/types-cjs/core/constants.d.cts +0 -159
  108. package/dist/types-cjs/core/core.d.cts +0 -185
  109. package/dist/types-cjs/core/dev.d.cts +0 -136
  110. package/dist/types-cjs/core/effect.d.cts +0 -30
  111. package/dist/types-cjs/core/error.d.cts +0 -56
  112. package/dist/types-cjs/core/external.d.cts +0 -15
  113. package/dist/types-cjs/core/graph.d.cts +0 -28
  114. package/dist/types-cjs/core/heap.d.cts +0 -24
  115. package/dist/types-cjs/core/index.d.cts +0 -13
  116. package/dist/types-cjs/core/invariants.d.cts +0 -59
  117. package/dist/types-cjs/core/lanes.d.cts +0 -54
  118. package/dist/types-cjs/core/optimistic.d.cts +0 -6
  119. package/dist/types-cjs/core/owner.d.cts +0 -124
  120. package/dist/types-cjs/core/scheduler.d.cts +0 -236
  121. package/dist/types-cjs/core/types.d.cts +0 -204
  122. package/dist/types-cjs/core/verdict.d.cts +0 -2
  123. package/dist/types-cjs/index.d.cts +0 -10
  124. package/dist/types-cjs/map.d.cts +0 -69
  125. package/dist/types-cjs/package.json +0 -3
  126. package/dist/types-cjs/store/index.d.cts +0 -18
  127. package/dist/types-cjs/store/next/optimistic.d.cts +0 -25
  128. package/dist/types-cjs/store/next/projection.d.cts +0 -8
  129. package/dist/types-cjs/store/next/reconcile.d.cts +0 -10
  130. package/dist/types-cjs/store/next/store.d.cts +0 -121
  131. package/dist/types-cjs/store/next/target.d.cts +0 -166
  132. package/dist/types-cjs/store/store.d.cts +0 -143
  133. package/dist/types-cjs/store/storePath.d.cts +0 -58
  134. package/dist/types-cjs/store/utils.d.cts +0 -74
@@ -97,9 +97,17 @@ export interface StoreNextTarget {
97
97
  * this target (first-read scan, defineProperty, or clone scan). Gates the
98
98
  * fold diff's descriptor-safe path and the get trap's descriptor path. */
99
99
  a: boolean;
100
- /** Accessor scan performed (scan-once on first trap read; adopted data is
101
- * not rescanned legacy-parity behavior). */
102
- sc: boolean;
100
+ /** Accessor scan grade: 0 = not yet scanned (adoption resets — adopted data
101
+ * is not rescanned until the next draft), 1 = scanned, 2 = scanned and
102
+ * PLAIN DATA — `Object.prototype` with every own key an enumerable data
103
+ * property. Grade 2 unlocks the spread clone (cloneRaw), bare-assignment
104
+ * overlay writes and flatten (#3360); a non-plain defineProperty through
105
+ * the draft downgrades it to 1. */
106
+ sc: 0 | 1 | 2;
107
+ /** Own-key count: exact at scan, then bumped by set-trap writes of keys new
108
+ * to the container (never decremented — an estimate for the overlay/clone
109
+ * choice only, #3360). */
110
+ kc: number;
103
111
  /** Adoption diff base, non-null when the backing was swapped by adoption
104
112
  * this batch: the view the nodes were LAST TOLD — the pre-batch committed
105
113
  * backing, or the draft's pending backing when a draft preceded the
@@ -110,7 +118,9 @@ export interface StoreNextTarget {
110
118
  * (`Object.create(v)` — own keys are this batch's writes, everything else
111
119
  * reads through). O(written) per flush instead of O(container) clones
112
120
  * (#3044); commit flattens own keys onto an owned committed backing in
113
- * place. Only plain-data non-array non-family containers qualify;
121
+ * place. Plain-data non-array containers qualify, including projection
122
+ * and derived-store families (#3352); optimistic families, chained
123
+ * backings, and accessor containers keep the descriptor clone.
114
124
  * `materializePB` downgrades to the clone path when a consumer needs a
115
125
  * real container (reconcile, draft escape). */
116
126
  ovl: boolean;
@@ -134,13 +144,30 @@ export interface StoreNextTarget {
134
144
  ht: any;
135
145
  }
136
146
  /**
137
- * Ownership (first cut, decision 2026-08-16d): one WeakSet of store-owned
138
- * backings serving both the production identity-skip guard and the __TEST__
139
- * no-mutation oracle.
147
+ * Ownership stamp (#3360): every backing the store ALLOCATES (CoW clones,
148
+ * privatized committed backings) carries its owning target under this
149
+ * enumerable symbol. One property write replaces the two weak-collection
150
+ * registrations (ownership set + raw→target map) a fresh object used to pay
151
+ * per draft — V8's identity-hash + ephemeron cost dominated the one-key
152
+ * write floor. Enumerable so a spread copy (the plain-data clone path) stays
153
+ * on the fast path and carries the stamp along.
154
+ *
155
+ * Owned backings are never user-reachable (`snapshot` copies them, the traps
156
+ * hide the key), so every raw key walk in the store must skip `$OWNER`, and
157
+ * ownership is answered by `isOwned` — a user object never carries it.
158
+ * Overlay drafts (`Object.create(v)` over an owned `v`) inherit the stamp.
140
159
  */
141
- export declare const ownedRaw: WeakSet<object>;
142
- /** raw → target. The only raw-keyed lookup; boundary mechanism (O8). */
160
+ export declare const $OWNER: unique symbol;
161
+ /** raw → target for UNOWNED backings (user-ingested, adopted); owned
162
+ * backings resolve through their `$OWNER` stamp. Boundary mechanism (O8). */
143
163
  export declare const storeNextLookup: WeakMap<object, StoreNextTarget>;
164
+ /** A backing the store allocated and may mutate in place. */
165
+ export declare function isOwned(raw: object): boolean;
166
+ /** raw → target within a family (`null` = plain stores / the global map).
167
+ * The stamp answers for backings owned by a target OF THAT FAMILY; anything
168
+ * else (user objects, adoptees, another family's backings the family
169
+ * re-registered for its own wrapper) resolves through the family's map. */
170
+ export declare function lookupTarget(raw: object, fam: StoreNextFamily | null): StoreNextTarget | undefined;
144
171
  /** __TEST__ oracle: every object ingested from a user (never mutate). */
145
172
  export declare const ingestedRaw: WeakSet<object> | null;
146
173
  export declare function devAssertNeverUserMutation(target: object): void;
@@ -152,7 +179,7 @@ export declare function devAssertNeverUserMutation(target: object): void;
152
179
  * the optimistic channel entirely. */
153
180
  export interface OptStoreHooks {
154
181
  notifyOptimisticWrites(t: any, pb: Record<PropertyKey, any>): void;
155
- optimisticView(t: any, src: Record<PropertyKey, any>): Record<PropertyKey, any>;
182
+ optimisticView(t: any, src: Record<PropertyKey, any>, draft?: boolean): Record<PropertyKey, any>;
156
183
  applyTentative(t: any, incoming: any, keyFn: ((item: any) => any) | null): void;
157
184
  /** #3164 fold: does this live transaction still retain optimism (armed
158
185
  * nodes or tracked stores)? Backs the held-truth masks in next/store.ts so
@@ -21,6 +21,171 @@ type _Merge<T extends unknown[], Curr = {}> = T extends [
21
21
  ...infer Rest
22
22
  ] ? _Merge<Rest, Override<Curr, Next>> : T extends [...infer Rest, infer Next | (() => infer Next)] ? Override<_Merge<Rest, Curr>, Next> : T extends [] ? Curr : T extends (infer I | (() => infer I))[] ? OverrideSpread<Curr, I> : Curr;
23
23
  export type Merge<T extends unknown[]> = Simplify<_Merge<T>>;
24
+ /** @internal What a source ENTRY is, decided once when the view is built
25
+ * (`merge()` learns it while flattening; `omit()` from its argument) and
26
+ * carried beside the entry — `MergeView.kinds[i]`, `OmitView.kind` — so no
27
+ * read has to ask. Asking is the cost: any brand check on a Proxy is a trap
28
+ * (`instanceof` is a `getPrototypeOf` trap, ~20 ns on a store — as much as
29
+ * the read itself), and a merge over a store did two per read. */
30
+ export declare const SOURCE_PLAIN = 0;
31
+ export declare const SOURCE_OMIT = 1;
32
+ export declare const SOURCE_PROXY = 2;
33
+ export declare const SOURCE_MEMO = 3;
34
+ export declare const SOURCE_MERGE = 4;
35
+ export type SourceKind = 0 | 1 | 2 | 3 | 4;
36
+ /** @internal The record behind an `omit()` proxy: `source` with `hidden`
37
+ * keys removed. It is the proxy's TARGET, so the shared handler reads it as
38
+ * plain fields — no per-instance closures — and it is what props consumers
39
+ * walk directly (`merge`, `spread`, `ssrElement`): a view never materializes
40
+ * a copy, and a consumer that knows the record never goes through its traps
41
+ * (a `getOwnPropertyDescriptor` trap per key allocates a descriptor and a
42
+ * getter, so enumerating a proxy costs more than the copy it was avoiding).
43
+ * `hidden` is a key list or a predicate (`omit(props, k => k[0] === "$")`).
44
+ *
45
+ * An omit over a `merge()` holds the merge's RECORD (`MergeView`, kind
46
+ * `SOURCE_MERGE`) — never its proxy, so no read hops through a trap — and is
47
+ * one record however many leaves the merge has. A consumer walks it as ONE
48
+ * filtered entry (`sourceKeys` / `sourceGet` recurse into the merge's
49
+ * sources by function call), and a later `merge()` over it carries the
50
+ * record as one entry instead of copying its leaves: on a component chain of
51
+ * defaults + omit + spread (`merge(omit(merge(omit(props))))`) the layers
52
+ * nest as records, each a few fields, where a flatten to leaf views built a
53
+ * view and a combined key list per leaf per layer — the largest allocation
54
+ * of a Kobalte-shaped render. A merge leaf may be merge's memo for a
55
+ * function source; it is resolved on access. */
56
+ export declare class OmitView {
57
+ source: any;
58
+ /** of `source` — PLAIN, PROXY (a store or a foreign proxy), MEMO, or
59
+ * MERGE (a `MergeView` record); never OMIT, a view over a view folds
60
+ * into one. */
61
+ kind: SourceKind;
62
+ hidden: Hidden;
63
+ /** see `MergeView.table` */
64
+ table: Map<PropertyKey, any> | null | number;
65
+ /** see `tableOwnKeys` / `tableDescriptor` */
66
+ keys: (string | symbol)[] | undefined;
67
+ descs: Map<PropertyKey, PropertyDescriptor> | undefined;
68
+ constructor(source: any,
69
+ /** of `source` — PLAIN, PROXY (a store or a foreign proxy), MEMO, or
70
+ * MERGE (a `MergeView` record); never OMIT, a view over a view folds
71
+ * into one. */
72
+ kind: SourceKind, hidden: Hidden);
73
+ }
74
+ type Hidden = PropertyKey[] | ((key: PropertyKey) => boolean);
75
+ /** @internal The `OmitView` behind an `omit()` proxy, or undefined. */
76
+ export declare function omitView(o: any): OmitView | undefined;
77
+ /** @internal Own string keys of a source entry — every consumer skips
78
+ * symbols itself. */
79
+ export declare function sourceKeys(s: any, kind: SourceKind): (string | symbol)[];
80
+ /** @internal `key in entry`. */
81
+ export declare function sourceHas(s: any, kind: SourceKind, key: PropertyKey): boolean;
82
+ /** @internal `entry[key]` — the source's getter runs once, here. */
83
+ export declare function sourceGet(s: any, kind: SourceKind, key: PropertyKey): any;
84
+ /** @internal Whether the own key set of a props object cannot change
85
+ * reactively: a plain object, or a merge/omit view over plain objects only.
86
+ * A consumer may then decide from `Object.getOwnPropertyDescriptor` once —
87
+ * "no `children` key" or "a data `children`" holds for the object's lifetime,
88
+ * so no tracking scope is needed for it (#3388). For a store, or a view with
89
+ * a store or memo leaf, keys can appear later and the reactive path is the
90
+ * only correct one. */
91
+ export declare function hasStaticKeys(o: any): boolean;
92
+ /**
93
+ * Whether `o[key]` can never change for the lifetime of `o`: the key is a
94
+ * data property of a plain object, or is absent from an object whose key set
95
+ * is fixed. A getter, a key on a store, a memo-backed `merge()` source, or
96
+ * any key of an object whose keys can appear later (a store) is not static.
97
+ *
98
+ * Looks through `merge()`/`omit()` views to the leaf that owns the key. Any
99
+ * object will do, but props are the case it exists for: the compiler encodes
100
+ * a literal at the call site (`as="button"`) as a data property and an
101
+ * expression (`as={isLink() ? "a" : "button"}`) as a getter, so a component
102
+ * library reads the caller's own static/dynamic classification of a prop at
103
+ * runtime — identically on server and client, the compiled shape being the
104
+ * same on both — and can take a no-computation path for the literal:
105
+ *
106
+ * ```tsx
107
+ * const Tag = dynamic(() => props.as, { static: isStatic(props, "as") });
108
+ * ```
109
+ *
110
+ * One descriptor lookup; no read of the value, nothing tracked.
111
+ */
112
+ export declare function isStatic(o: object, key: PropertyKey): boolean;
113
+ /** @internal */
114
+ export declare class MergeView {
115
+ sources: any[];
116
+ /** `kinds[i]` is what `sources[i]` is (see `SourceKind`). */
117
+ kinds: SourceKind[];
118
+ /** key → the plain leaf that owns it (later sources win), built by an
119
+ * enumeration or once the reads have paid for it (see `resolvedTable`)
120
+ * when every leaf has static keys; `null` when one doesn't. Until then
121
+ * the slot counts the per-key trap reads so far. One slot rather than a
122
+ * counter field of its own: a view is built per source per component
123
+ * layer, and each field initializer is a measurable share of a
124
+ * constructor that small in the lower JIT tiers. */
125
+ table: Map<PropertyKey, any> | null | number;
126
+ /** see `tableOwnKeys` / `tableDescriptor` */
127
+ keys: (string | symbol)[] | undefined;
128
+ descs: Map<PropertyKey, PropertyDescriptor> | undefined;
129
+ constructor(sources: any[],
130
+ /** `kinds[i]` is what `sources[i]` is (see `SourceKind`). */
131
+ kinds: SourceKind[]);
132
+ }
133
+ /** @internal The `MergeView` behind a `merge()` proxy — its flattened
134
+ * `sources` with their `kinds` — or undefined. */
135
+ export declare function mergeView(o: any): MergeView | undefined;
136
+ /** @internal The record behind a merge() or omit() proxy — a `MergeView`
137
+ * (flattened `sources` with their `kinds`) or an `OmitView` — or undefined
138
+ * for anything else (a plain object, a store, a foreign proxy). Two fast
139
+ * traps on a store, none on a plain object. */
140
+ export declare function viewOf(o: any): MergeView | OmitView | undefined;
141
+ /** @internal The resolved key table of a merge/omit view — every own key of
142
+ * the view mapped to the plain object that owns it, in merged order (a key
143
+ * at the position of the last source that carries it, see `tableSet`) — or
144
+ * undefined when it has none: a leaf is a store or a memo source, whose
145
+ * keys can change, or the object is not a view at all.
146
+ *
147
+ * This is the flat object the eager copy used to build, made lazily and
148
+ * without copying: one pass over the leaves' own keys, then every
149
+ * `get`/`has`/descriptor is one lookup plus one read of the owning leaf, and
150
+ * a consumer (`spread` rerunning its effect) walks the table instead of
151
+ * re-deriving shadowing from the leaves each time. Own keys only, as the
152
+ * copy's were: a plain source's key set is fixed once merged (keys added to
153
+ * it later are not seen — the copy didn't see them either).
154
+ *
155
+ * It is built by an ENUMERATION — the `ownKeys` trap, or a consumer asking
156
+ * for it here — or once per-key reads have paid for it (`READS_FOR_TABLE`),
157
+ * not on the first read. A per-key read has a direct answer (a walk of the
158
+ * sources, last to first, one `in` each) whose cost is the source count,
159
+ * while the table's is every key of every leaf, so the walk wins until a
160
+ * view has been read about as many times as it has keys. On the server it
161
+ * never is: a component reads its props a few times, the element enumerates
162
+ * them once through its own source walk, and the view is gone — building on
163
+ * first read there cost a component chain a table per layer (profiled on
164
+ * the Kobalte-shaped chain: a third of SSR time in the table code and its
165
+ * garbage). On the
166
+ * client a view read on every reactive rerun crosses the threshold in its
167
+ * first few updates and is one lookup per read from then on, as before.
168
+ * Once built — by a `spread`, `Object.keys`, `{...props}`, or the count —
169
+ * every trap uses it. */
170
+ export declare function resolvedTable(o: any): Map<PropertyKey, any> | undefined;
171
+ /** @internal Every own string key of a props SOURCE — a plain object, a
172
+ * store or foreign proxy, or a merge/omit view — appended to `keys` in
173
+ * merged order with the object that owns each at the same index of
174
+ * `owners`: a key already listed (by this source or an earlier one) moves
175
+ * to the end, so several sources collected in turn give the order and the
176
+ * winners a merge of them would. A consumer that reads each key once
177
+ * (`ssrElement`) then reads `owners[i][keys[i]]` — the owner's getter runs
178
+ * there, once — and asks nothing else of a view: no table, no `in` walk per
179
+ * key through the merge/omit layers, no key list per leaf. One pass,
180
+ * however deep the layers nest. Symbols are listed; the consumer skips
181
+ * them. */
182
+ export declare function sourceOwners(s: any, keys: (string | symbol)[], owners: any[]): void;
183
+ /** @internal The flattened sources behind a `merge()` proxy, or undefined.
184
+ * A merge's writes are no-ops, so its sources are the whole truth. A COPY of
185
+ * a merge (`{...merged}`, a descriptor copy) is a plain object that carries
186
+ * no sources — `ownKeys` never answers $SOURCES — so what is on the copy is
187
+ * the truth there and every consumer reads it directly (#3384). */
188
+ export declare function mergeSources(o: any): any[] | undefined;
24
189
  /**
25
190
  * Merges multiple props-like objects into a single proxy that *preserves
26
191
  * reactivity*. Reads are forwarded to the right-most source that defines the
@@ -29,6 +194,12 @@ export type Merge<T extends unknown[]> = Simplify<_Merge<T>>;
29
194
  * Function arguments are treated as memo-backed sources — useful for passing
30
195
  * derived defaults whose computation should track reactively.
31
196
  *
197
+ * The result is a live VIEW of its sources, never a copy: creating it costs
198
+ * nothing per key, every read goes to the source that owns the key (a getter
199
+ * runs there, a data property is read live), and writing to it is a no-op.
200
+ * A single non-function source is returned as is. To own a mutable object,
201
+ * copy it: `{ ...merged }` snapshots the current values.
202
+ *
32
203
  * Use this in component bodies to merge defaults / overrides without losing
33
204
  * Solid's per-property tracking.
34
205
  *
@@ -52,6 +223,12 @@ export type Omit<T, K extends readonly (keyof T)[]> = {
52
223
  * Use it to forward "rest" props to a child element while pulling out the
53
224
  * keys your component handles itself — the equivalent of `splitProps(p, ["a","b"])[1]`.
54
225
  *
226
+ * The result is a live VIEW of `props`, not a copy: nothing is read or
227
+ * materialized until a key is used, and a spread (`{...rest}`) or a later
228
+ * `merge()` walks the underlying object directly. A predicate hides keys by
229
+ * rule instead of by name — `omit(props, k => k[0] === "$")` — without
230
+ * enumerating first.
231
+ *
55
232
  * @example
56
233
  * ```tsx
57
234
  * function Input(props: { label: string; value: string; onInput: (v: string) => void } & JSX.HTMLAttributes<HTMLInputElement>) {
@@ -71,4 +248,5 @@ export type Omit<T, K extends readonly (keyof T)[]> = {
71
248
  * ```
72
249
  */
73
250
  export declare function omit<T extends Record<any, any>, K extends readonly (keyof T)[]>(props: T, ...keys: K): Omit<T, K>;
251
+ export declare function omit<T extends Record<any, any>>(props: T, hidden: (key: keyof T & (string | symbol)) => boolean): Partial<T>;
74
252
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solidjs/signals",
3
- "version": "2.0.0-rc.7",
3
+ "version": "2.0.0-rc.9",
4
4
  "description": "Solid's reactive primitives: signals, memos, effects, stores, and async-aware computations.",
5
5
  "author": "Ryan Carniato",
6
6
  "license": "MIT",
@@ -13,12 +13,15 @@
13
13
  "publishConfig": {
14
14
  "access": "public"
15
15
  },
16
- "main": "./dist/node.cjs",
16
+ "main": "./dist/prod/index.js",
17
17
  "module": "./dist/prod/index.js",
18
18
  "unpkg": "./dist/prod/index.js",
19
19
  "jsdelivr": "./dist/prod/index.js",
20
20
  "types": "./dist/types/index.d.ts",
21
21
  "type": "module",
22
+ "engines": {
23
+ "node": ">=22.12.0"
24
+ },
22
25
  "sideEffects": false,
23
26
  "files": [
24
27
  "dist",
@@ -26,25 +29,26 @@
26
29
  ],
27
30
  "exports": {
28
31
  ".": {
29
- "import": {
30
- "types": "./dist/types/index.d.ts",
31
- "test": "./dist/dev.js",
32
- "development": "./dist/dev.js",
33
- "default": "./dist/prod/index.js"
34
- },
35
- "require": {
36
- "types": "./dist/types-cjs/index.d.cts",
37
- "development": "./dist/node.dev.cjs",
38
- "default": "./dist/node.cjs"
39
- }
32
+ "types": "./dist/types/index.d.ts",
33
+ "test": "./dist/dev.js",
34
+ "development": "./dist/dev.js",
35
+ "observe": "./dist/observe/index.js",
36
+ "default": "./dist/prod/index.js"
37
+ },
38
+ "./attribution": {
39
+ "types": "./dist/types/attribution.d.ts",
40
+ "test": "./dist/dev.attribution.js",
41
+ "development": "./dist/dev.attribution.js",
42
+ "observe": "./dist/observe/attribution.js",
43
+ "default": "./dist/prod/attribution.js"
40
44
  },
41
45
  "./package.json": "./package.json"
42
46
  },
43
47
  "scripts": {
44
48
  "build": "npm-run-all -nl build:* && pnpm types",
45
- "build:clean": "rimraf dist/dev dist/prod dist/node dist/dev.js dist/prod.js dist/node.cjs dist/node.dev.cjs",
46
- "build:js": "rollup -c && node ./scripts/mangle-props.mjs dist/prod dist/node.cjs && node ./scripts/check-pure.mjs dist/prod",
47
- "types": "tsc -p tsconfig.build.json && node ../../scripts/sync-dual-types.mjs ./dist/types ./dist/types-cjs",
49
+ "build:clean": "rimraf dist/dev dist/prod dist/observe dist/*.js",
50
+ "build:js": "rollup -c && node ./scripts/mangle-props.mjs dist/prod dist/observe && node ./scripts/check-pure.mjs dist/prod && node ./scripts/check-pure.mjs dist/observe",
51
+ "types": "tsc -p tsconfig.build.json",
48
52
  "test": "vitest run",
49
53
  "test:watch": "vitest watch tests",
50
54
  "test:gc": "node --expose-gc ./vitest.js",
@@ -67,4 +71,4 @@
67
71
  "vite": "^7.0.0",
68
72
  "vitest": "^4.1.6"
69
73
  }
70
- }
74
+ }