@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
@@ -1,70 +1,19 @@
1
- import { type Computed, type Refreshable } from "../core/index.js";
2
- import { type NoFn, type ProjectionOptions, type Store } from "./store.js";
3
- export declare function createProjectionInternal<T extends object = {}>(fn: (draft: T) => void | T | Promise<void | T> | AsyncIterable<void | T>, seed: Partial<T>, options?: ProjectionOptions): {
4
- store: Refreshable<Store<T>>;
5
- node: Computed<void | T>;
6
- };
1
+ import type { Computed } from "../core/types.js";
2
+ import type { Refreshable } from "../core/index.js";
3
+ import { type NoArray, type NoFn, type ProjectionOptions, type Store } from "./types.js";
4
+ /** The derive's pass: run `fn` against a draft of the store; commit its
5
+ * result (sync, or each async landing) through the reconcile channel.
6
+ * Draft validity is per run (R37): live from here until the NEXT run starts
7
+ * — a sync derive that subscribes to an external source and pushes into
8
+ * the draft from the callback (#3585) is the model use. */
9
+ export declare function runProjectionComputed<T extends object>(wrappedStore: Store<T>, fn: (draft: T) => void | T | Promise<void | T> | AsyncIterable<void | T>, key: string | ((item: NonNullable<any>) => any) | null, wrapCommit?: (write: () => void, value: T) => void, aroundDraftWrite?: (op: () => void) => void): Computed<void | T>;
7
10
  /**
8
- * Creates a derived (projected) store. Like `createMemo` but for stores: the
9
- * derive function receives a mutable draft and either mutates it in place
10
- * (canonical) or returns a new value. Either way the result is reconciled
11
- * against the previous draft by `options.key` (default `"id"`), so surviving
12
- * items keep their proxy identity — only added/removed items are
13
- * created/disposed.
14
- *
15
- * If the derive returns a different entity than the one currently held (the
16
- * `/users/1` → `/users/2` shape), the store swaps to it rather than merging,
17
- * and nothing below it is treated as surviving.
18
- *
19
- * Returns the projected store directly (no setter — reads only).
20
- *
21
- * Use this when you want the structural-sharing / per-property tracking
22
- * behaviour of a store on top of a derived computation. For simple read-only
23
- * derivations, `createMemo` is lighter.
24
- *
25
- * @param fn receives the current draft; mutate it in place or return new
26
- * data. Return is convenient for filter/derive shapes where mutation is
27
- * awkward.
28
- * @param seed the backing store value to wrap and reconcile into
29
- * @param options `ProjectionOptions` — `name`, `key`. `key` defaults to
30
- * `"id"`; specify it only when your data uses a different identity field
31
- * (e.g. `{ key: "uuid" }` or `{ key: u => u.slug }`), or `null` to merge
32
- * positionally with no keyed pass.
33
- *
34
- * @example
35
- * ```ts
36
- * // Mutation form — update individual fields on the draft.
37
- * const summary = createProjection<{ total: number; active: number }>(
38
- * draft => {
39
- * draft.total = users().length;
40
- * draft.active = users().filter(u => u.active).length;
41
- * },
42
- * { total: 0, active: 0 }
43
- * );
44
- *
45
- * // Return form — produce a derived collection. Reconciled by `id` so each
46
- * // surviving user keeps the same store identity across recomputes.
47
- * const activeUsers = createProjection<User[]>(
48
- * () => allUsers().filter(u => u.active),
49
- * []
50
- * );
51
- * ```
52
- *
53
- * @see {@link https://github.com/solidjs/x-reactivity#createprojection}
11
+ * A derived store: `fn` runs in a computed and writes its draft; readers of
12
+ * the store's keys re-run only when the keys they read change (the
13
+ * firewall). `fn` may be async or an async iterator; the seed is a draft,
14
+ * never an observable value, until the first landing (A25).
54
15
  */
55
- export declare function createProjection<T extends object = {}>(fn: (draft: T) => void | T | Promise<void | T> | AsyncIterable<void | T>, seed: Partial<T> | Store<NoFn<T>>, options?: ProjectionOptions): Refreshable<Store<T>>;
56
- /**
57
- * Shared projection computed body used by both `createProjection` and the derived
58
- * form of `createOptimisticStore`. Encapsulates the write-trap draft, `storeSetter`
59
- * wrapping, the `handleAsync` subscription with a setter callback, and the commit
60
- * path (which must always go through `storeSetter` so the `writeOnly` guard is
61
- * engaged during `reconcile`'s property reads).
62
- *
63
- * `wrapCommit` is invoked for every commit (sync return and each async yield) and
64
- * lets callers layer extra context around the write — e.g. the optimistic store
65
- * re-enters `setProjectionWriteActive` so reconciles target `STORE_OVERRIDE`
66
- * instead of `STORE_OPTIMISTIC_OVERRIDE` even when an async yield fires outside
67
- * the outer `setProjectionWriteActive` scope.
68
- */
69
- export declare function runProjectionComputed<T extends object>(wrappedStore: Store<T>, fn: (draft: T) => void | T | Promise<void | T> | AsyncIterable<void | T>, key: string | ((item: NonNullable<any>) => any) | null, wrapCommit?: (write: () => void) => void, onDraftWrite?: () => void): Computed<void | T>;
70
- export declare function createWriteTraps(isActive?: () => boolean, onDraftWrite?: () => void): ProxyHandler<any>;
16
+ export declare function createProjection<T extends object = {}>(fn: (() => T | Promise<T> | AsyncIterable<T>) & NoArray<T>, seed?: null, options?: Omit<ProjectionOptions, "seedLoadingValue">): Refreshable<Store<T>>;
17
+ export declare function createProjection<T extends object = {}>(fn: (draft: T) => void | T | Promise<void | T> | AsyncIterable<void | T>, seed: NoFn<T> | Store<NoFn<T>>, options?: ProjectionOptions): Refreshable<Store<T>>;
18
+ /** `createStore(fn, seed, options)`: a projection with a user setter. */
19
+ export declare function createStoreDerived<T extends object = {}>(fn: (draft: T) => void | T | Promise<void | T> | AsyncIterable<void | T>, seed: T | null | undefined, options?: ProjectionOptions): [Refreshable<Store<T>>, (f: (draft: T) => T | void) => void];
@@ -1,46 +1,3 @@
1
- /**
2
- * Shared body of `reconcile()` and the projection commit. `replace` is the
3
- * only difference: a projection commit is a value swap, not a merge — its root
4
- * proxy is a cell handed out by `createProjection` that can never change
5
- * reference, so a derive returning a different entity is not the slot mistake
6
- * `reconcile()` throws on. Nothing below the root survives that swap, which is
7
- * the rule the keyed diff already applies at a nested slot on a key mismatch.
8
- *
9
- * @internal
10
- */
11
- export declare function reconcileState(value: any, state: any, key: any, replace: boolean): void;
12
- /**
13
- * Returns a draft-mutating function that smart-merges `value` into a store,
14
- * preserving fine-grained reactivity: only changed leaves trigger updates.
15
- *
16
- * With a `key` (default `"id"`), array items whose key matches between old
17
- * and new states keep their identity (updated in place, moves and removals
18
- * update the corresponding signals) — the shape for keyed server payloads.
19
- * Items without the key field fall back to positional matching.
20
- *
21
- * With `key: null`, matching is purely positional: index N of the new array
22
- * merges into index N of the old, and object properties merge recursively —
23
- * the classic pattern for fixed-shape data that churns in place (dashboards,
24
- * monitors), where no keyed diff pass is needed or wanted.
25
- *
26
- * Merging into a slot that holds a *different* entity throws — the caller
27
- * picked the slot, so a key mismatch there is a bug.
28
- *
29
- * @param value the next state to merge in
30
- * @param key property name (string) or extractor function for stable
31
- * identity (default `"id"`); pass `null` for positional merging
32
- *
33
- * @example
34
- * ```ts
35
- * const [todos, setTodos] = createStore<Todo[]>([]);
36
- *
37
- * async function refresh() {
38
- * const fresh = await api.getTodos();
39
- * setTodos(reconcile(fresh)); // diff-merge by `id`
40
- * }
41
- *
42
- * // fixed-shape polling data — positional merge
43
- * setStats(reconcile(nextStats, null));
44
- * ```
45
- */
46
- export declare function reconcile<T extends U, U>(value: T, key?: string | ((item: NonNullable<any>) => any) | null): (state: U) => void;
1
+ type KeyFn = (item: any) => any;
2
+ export declare function reconcileState(value: any, state: any, key: string | KeyFn | null | undefined, replace?: boolean): void;
3
+ export {};
@@ -1,138 +1,135 @@
1
- import { type Signal } from "../core/index.js";
2
- import type { Refreshable } from "../core/index.js";
3
- /** A read-only view of a store's value as seen by consumers. Mutate it via the paired `StoreSetter`. */
4
- export type Store<T> = Readonly<T>;
5
- /**
6
- * A store setter. The callback receives a writable **draft** of the store.
7
- *
8
- * - **Mutate in place (canonical):** `s.foo = 1`, `s.list.push(x)`,
9
- * `s.list.splice(i, 1)`. This is the default form for most updates.
10
- * - **Return a new value:** for shapes where mutation is awkward, most
11
- * commonly removing items (`s => s.list.filter(...)`). Arrays are replaced
12
- * by index (length adjusted); objects are shallow-diffed at the top level
13
- * (keys present in the returned value are written, missing keys deleted).
14
- *
15
- * The setter does **not** perform keyed reconciliation. If you need surviving
16
- * items to keep their store identity across full-array replacement, use the
17
- * projection form — `createStore(fn, seed, { key })` or `createProjection` —
18
- * whose derive function reconciles its return by `options.key`.
19
- */
20
- export type StoreSetter<T> = (fn: (state: T) => T | void) => void;
21
- /** Tuple returned by the plain `createStore(initialValue)` form. */
22
- export type StoreReturn<T> = [get: Store<T>, set: StoreSetter<T>];
23
- /** Tuple returned by the derived `createStore(fn, seed, options?)` form. */
24
- export type ProjectionStoreReturn<T> = [get: Refreshable<Store<T>>, set: StoreSetter<T>];
25
- /** Base options for store primitives. */
26
- export interface StoreOptions {
27
- /** Debug name (dev mode only) */
28
- name?: string;
29
- }
30
- /** Options for derived/projected stores created with `createStore(fn)`, `createProjection`, or `createOptimisticStore(fn)`. */
31
- export interface ProjectionOptions extends StoreOptions {
32
- /** Key property name or function for reconciliation identity; `null` merges positionally */
33
- key?: string | ((item: NonNullable<any>) => any) | null;
34
- /** Single-layer store: root keys reactive, values raw records replaced by reference */
35
- shallow?: boolean;
36
- /**
37
- * Treat the seed as commit #0: the store is born committed with the seed's
38
- * contents, shown until the derive's first real answer lands. While that
39
- * first answer is in flight, reads serve the seed everywhere — nothing
40
- * suspends to a `<Loading>` boundary, no transition is held, and
41
- * `isPending` stays false (the seed answers by declaration; first-load
42
- * affordances belong to the data, e.g. a `skeleton: true` field in the
43
- * seed). Once the first answer lands (reconciled into the seed), refetches
44
- * use normal pending semantics with `isPending` true.
45
- *
46
- * The store equivalent of `MemoOptions.loadingValue`; the seed already
47
- * carries the placeholder shape, so this is just the opt-in.
48
- */
49
- seedLoadingValue?: boolean;
1
+ import type { Signal } from "../core/types.js";
2
+ import { type StoreFamily, type StoreTarget } from "./target.js";
3
+ import { type StoreOptions } from "./types.js";
4
+ export { $PROXY, $TARGET, $TRACK, markRaw } from "./types.js";
5
+ export type SetStoreFunction<T> = (fn: (draft: T) => T | void) => void;
6
+ export declare function wrap<T extends Record<PropertyKey, any>>(value: T, parent?: StoreTarget | null, parentKey?: PropertyKey | null, fam?: StoreFamily | null): T;
7
+ /** Unwrap our own proxies to their current backing; leave everything else.
8
+ * A projection draft wrapper is registered as its target's alias
9
+ * (projection.ts `wrapDraft`) — adopted as a backing, it would forward to
10
+ * itself (#3767). */
11
+ export declare function unwrapValue(v: any): any;
12
+ export declare function sameKey(a: any, b: any): boolean;
13
+ /** The container node's arrangement guess: the rows (or keys) the setter
14
+ * left the container with, in order. Its comparator judges a landing or a
15
+ * revert against it by row identity — by key when the family has one
16
+ * (the server's object for a guessed row is the same row). */
17
+ export declare class LaneView {
18
+ rows: Record<PropertyKey, any>;
19
+ /** The backing the guess is shown over: the committed one at the
20
+ * guess, the composed arrangement after a re-base (optimistic.ts). */
21
+ base: Record<PropertyKey, any>;
22
+ /** Keys the setter REMOVED from the view it saw (a deliberate delete,
23
+ * not a row the truth has yet to show): a re-base does not restore
24
+ * them. `null` when none. */
25
+ removed: Set<unknown> | null;
26
+ constructor(rows: Record<PropertyKey, any>,
27
+ /** The backing the guess is shown over: the committed one at the
28
+ * guess, the composed arrangement after a re-base (optimistic.ts). */
29
+ base: Record<PropertyKey, any>,
30
+ /** Keys the setter REMOVED from the view it saw (a deliberate delete,
31
+ * not a row the truth has yet to show): a re-base does not restore
32
+ * them. `null` when none. */
33
+ removed?: Set<unknown> | null);
50
34
  }
51
- export type NoFn<T> = T extends Function ? never : T;
52
- type DataNode = Signal<any>;
53
- type DataNodes = Record<PropertyKey, DataNode>;
54
- /**
55
- * Brand symbols used internally by the store proxy / projection plumbing.
56
- * Cross-package wiring; not part of the user-facing API.
57
- *
58
- * @internal
59
- */
60
- export declare const $TRACK: unique symbol, $TARGET: unique symbol, $PROXY: unique symbol, $DELETED: unique symbol, $AFFECTS: unique symbol;
61
- export declare const STORE_VALUE = "v", STORE_NODE = "n", STORE_HAS = "h", STORE_PARENT = "u", STORE_DESC = "d", STORE_SHALLOW = "s";
62
- /** Structural view of a store target as shared machinery sees it (the real
63
- * shape is `StoreNextTarget` in ./next/target.ts). */
64
- export type StoreNode = {
65
- [$PROXY]: any;
66
- [STORE_VALUE]: Record<PropertyKey, any>;
67
- [STORE_NODE]?: DataNodes;
68
- [STORE_HAS]?: DataNodes;
69
- [STORE_PARENT]?: StoreNode;
70
- [STORE_SHALLOW]?: boolean;
71
- [STORE_DESC]?: boolean;
72
- };
73
- export declare namespace SolidStore {
74
- interface Unwrappable {
75
- }
76
- }
77
- export type NotWrappable = string | number | bigint | symbol | boolean | Function | null | undefined | SolidStore.Unwrappable[keyof SolidStore.Unwrappable];
78
- /**
79
- * Marks a value as raw: no store will ever wrap it — every store presents it
80
- * as-is, tracked by reference at whatever slot holds it and updated by
81
- * replacement. Useful for class instances and external objects (editors,
82
- * scene graphs, Maps) and for record-shaped data updated wholesale. Sticky
83
- * for the value's lifetime.
84
- */
85
- export declare let rawValuesUsed: boolean;
86
- export declare function isRawValue(value: any): boolean;
87
- export declare function markRaw<T>(value: T): T;
88
- export declare function markRawOne(v: any): void;
89
- export declare function markRawIngest(container: any): void;
90
- export declare function isWrappable<T>(obj: T | NotWrappable): obj is T;
91
- export declare function setWriteOverride(value: boolean): void;
92
- export declare function getWriteOverride(): boolean;
93
- export declare function ownEnumerableKeys(o: object): (string | symbol)[];
94
- /**
95
- * Scope inheritance for late-created nodes: every live mark whose identity
96
- * scope contains the owning record's raw — and, for keyed marks, whose key
97
- * is this property — gets counted on the new node. Inherited marks live
98
- * exactly as long as the scope's carrier — the release hook below drops
99
- * them with the entry.
100
- */
101
- export declare function inheritAffectsMarks(node: DataNode, raw: object, property: PropertyKey): void;
102
- /** Next-store node factory for affects carriers/slots: injected by the
103
- * rewrite module (next targets alias the legacy field names, so everything
104
- * here EXCEPT node creation works on them structurally). */
105
- export declare let nextAffectsNodeResolver: ((target: any, key: PropertyKey) => DataNode) | null;
106
- export declare function setNextAffectsNodeResolver(fn: (target: any, key: PropertyKey) => DataNode): void;
107
- /** Next-store optimistic view for the declaration walk (optimistic rows
108
- * pushed before the declaration are in motion too — legacy reads its write
109
- * overlays; next composes armed-node overrides). */
110
- export declare let nextOptimisticViewResolver: ((target: any, raw: any) => any) | null;
111
- export declare function setNextOptimisticViewResolver(fn: (target: any, raw: any) => any): void;
112
- /** @internal birth inheritance for nodes created inside a live mark window —
113
- * exported for the rewrite's node factories. */
114
- export declare function affectsScopesLive(): boolean;
115
- /**
116
- * Witness live mark coverage of a record into the active isPending() probe.
117
- * Tracked reads don't need this — they go through real signal nodes, which
118
- * carry marks directly (declaration walk or birth inheritance). This covers
119
- * UNTRACKED probes reading through records whose nodes never materialized
120
- * (no observer ever subscribed, so no node exists to carry the mark).
121
- * Callers guard on `pendingCheckActive`, so plain reads never pay for this.
122
- *
123
- * @internal
124
- */
125
- export declare function witnessAffectsMark(target: StoreNode, property?: PropertyKey): void;
126
- /**
127
- * Resolves the store nodes an `affects()` declaration marks: with a `key`,
128
- * the named slot's leaf node (upserted so the mark has an addressable
129
- * carrier); without, the record's $AFFECTS carrier plus every LIVE node in
130
- * its subtree (the edges existing readers subscribed through), with the
131
- * subtree's identities snapshotted into the mark's scope so nodes created
132
- * during the window — and untracked probes over captured proxies — resolve
133
- * against it (#2882).
35
+ /** A container node's value as a backing: the base an arrangement guess is
36
+ * shown over, else the value itself. */
37
+ export declare function asBacking(v: any): Record<PropertyKey, any>;
38
+ /** The container node's comparator: a staging is a backing (identity — a
39
+ * pending backing is never "equal" to the committed one); a lane value is
40
+ * an arrangement (`LaneView`), judged by the optimistic machinery. */
41
+ export declare const containerEquals: (this: any, a: any, b: any) => boolean;
42
+ export declare function getNode(target: StoreTarget, key: PropertyKey, accKnown?: -1 | 0 | 1): Signal<any>;
43
+ export declare function getHasNode(target: StoreTarget, key: PropertyKey): Signal<boolean>;
44
+ /** The container node (plan sec. 31.3): created by the first structural subscription
45
+ * or the first write that needs to stage. Its committed value is the
46
+ * committed backing. */
47
+ export declare function getContainerNode(target: StoreTarget): Signal<any>;
48
+ export declare function bumpDeep(t: StoreTarget): void;
49
+ export declare function nameStore(proxy: any, name: string | undefined, loc?: string): void;
50
+ /** Shallow clone into store ownership. Plain data (grade 2) spreads; anything
51
+ * else copies descriptors (accessors kept, everything made configurable). */
52
+ export declare function cloneRaw(source: Record<PropertyKey, any>, t: StoreTarget): Record<PropertyKey, any>;
53
+ /** Downgrade an overlay to a real clone (a consumer needs a container). */
54
+ export declare function materializePB(target: StoreTarget): Record<PropertyKey, any>;
55
+ /** Adoption (a setter's returned replacement; reconcile and projection
56
+ * landings in S3): the incoming object becomes the backing by reference at
57
+ * the fold — no clones, no user-object mutation, ownership resets to
58
+ * shared. It is the container's staging until then (signal parity: a
59
+ * handler reads the committed frame until the flush; a hold keeps it
60
+ * staged with the rest). The nodes are told now, diffed against the view
61
+ * they were LAST told (#3296): the draft's pending backing when one
62
+ * preceded the adoption this batch — its node writes were real, and the
63
+ * adoption's re-stage cancels or confirms each — else the committed
64
+ * backing. */
65
+ export declare function adoptPB(target: StoreTarget, incoming: Record<PropertyKey, any>, notify?: boolean): void;
66
+ export declare function runDirect(fn: () => void): void;
67
+ /** Is the open setter a user's? (reconcile.ts: a user's reconcile on an
68
+ * optimistic family writes the draft.) */
69
+ export declare function userWriting(): boolean;
70
+ /** Two raws that wrap to the same target are the same logical value. */
71
+ export declare function targetsEqual(ov: any, nv: any): boolean;
72
+ /** Positional identity IS content for arrays (R15). */
73
+ export declare function arrayStructureChanged(old: any[], neu: any[]): boolean;
74
+ export declare function membershipChanged(old: Record<PropertyKey, any>, neu: Record<PropertyKey, any>): boolean;
75
+ /** One leaf's notification for an adoption diff (descriptor-aware). */
76
+ export declare function notifyKeyDiff(node: Signal<any>, key: PropertyKey, old: Record<PropertyKey, any>, neu: Record<PropertyKey, any>, probe?: boolean): void;
77
+ export declare function hasAccessorFlag(node: Signal<any>): boolean;
78
+ /** One leaf's notification when the caller already has both values. */
79
+ export declare function notifyKeyValue(node: Signal<any>, key: PropertyKey, ov: any, nv: any, old: Record<PropertyKey, any>, neu: Record<PropertyKey, any>): void;
80
+ /** The structural half of an adoption's notifications (reconcile does the
81
+ * leaves itself): presence by `in`, the container by membership. Presence
82
+ * is DIFFED `old` → `neu` like the leaves (#3743): a presence node is
83
+ * written only where `in` changed between the view it was last told
84
+ * (#3296) and the adoption — `setSignal` joins a held node's transaction
85
+ * before its equality gate (A34 (1)), so repeating an unchanged absence to
86
+ * a node an action holds would make the whole tick the action's (an
87
+ * unrelated `a.value` stayed stale until the action settled). A real
88
+ * change still writes, and on a held node still proposes. A live chained
89
+ * `old` (a store proxy, §7b) reflects the inner store, not what the node
90
+ * was last told — written unconditionally, as before; its container too
91
+ * (#4361).
134
92
  *
135
- * @internal
136
- */
137
- export declare function getStoreAffectsNodes(target: StoreNode, key?: PropertyKey): DataNode[];
138
- export {};
93
+ * The container is told of an arrangement change when it has structural
94
+ * subscribers OR carries an arrangement guess (S4): for a guessed
95
+ * container the write is the landing that judges the guess (Q-D, plan
96
+ * sec. 39 — confirm, supersede, or hold beneath), not a subscriber
97
+ * notification, and a landing whose truth changed no guessed key's value
98
+ * or presence (a newer question's rows beneath an optimistic push) still
99
+ * answers the arrangement — before, only the presence write reached the
100
+ * lane, by accident of being unconditional. */
101
+ export declare function notifyFoldTail(t: StoreTarget, old: Record<PropertyKey, any>, neu: Record<PropertyKey, any>): void;
102
+ /** An adoption's notifications: every node of the target, diffed `old` →
103
+ * `neu` (value nodes by key, presence by `in`, the container by
104
+ * membership, the deep witness by identity). */
105
+ export declare function notifyFold(t: StoreTarget, old: Record<PropertyKey, any>, neu: Record<PropertyKey, any>): void;
106
+ /** The committed backing: the container node's committed value while a
107
+ * batch is staged on it (an adoption swaps `t.v` eagerly — INTERNALS §3,
108
+ * "adoption is eager by contract" — and the node keeps the frame committed
109
+ * readers under a hold still see), `t.v` otherwise. */
110
+ export declare function committed(t: StoreTarget): Record<PropertyKey, any>;
111
+ /** The same row at a slot, as the adoption pairs rows (reconcile.ts): two
112
+ * objects whose keys agree — positionally for an unkeyed family. */
113
+ export declare function sameRow(pv: any, nv: any, keyFn: ((item: any) => any) | null): boolean;
114
+ /** A chained backing's child (§7b): a raw the inner family owns, or holds
115
+ * at this key, is served as the inner store's wrapper — never a fresh
116
+ * raw-keyed one — so the chained targets are the same objects across
117
+ * settled and pending views. */
118
+ export declare function resolveChainedRaw(target: StoreTarget, key: PropertyKey, v: object): any;
119
+ export declare function storeSetter<T>(proxy: T, fn: (draft: T) => T | void, guard?: boolean): void;
120
+ export declare function createStore<T extends Record<PropertyKey, any>>(initialValue: T, options?: StoreOptions): [T, SetStoreFunction<T>];
121
+ /** True when `proxy` is a SHALLOW store (children served verbatim, slots
122
+ * replaced by reference — #2932). The list driver uses this to choose the
123
+ * slot-patch channel (collected row bodies) over per-record registration. */
124
+ export declare function storeIsShallow(proxy: any): boolean;
125
+ /** True when `proxy` belongs to a projection family (S3). */
126
+ export declare function storeHasFamily(proxy: any): boolean;
127
+ /** True when `proxy` belongs to an OPTIMISTIC family (S4). */
128
+ export declare function storeHasOptimisticFamily(proxy: any): boolean;
129
+ /** Tracking snapshot: subscribes every reachable record's container and deep
130
+ * witness (one node per record, not one per path), then snapshots. */
131
+ export declare function deep<T>(value: T): T;
132
+ /** Non-tracking snapshot: source identity for unowned subtrees (zero copy),
133
+ * a copy for owned ones (they are by definition modified relative to the
134
+ * source). Sees the pending backing (R27). */
135
+ export declare function snapshot<T>(value: T): T;
@@ -1,4 +1,4 @@
1
- import { type NotWrappable } from "./store.js";
1
+ import { type NotWrappable } from "./types.js";
2
2
  type W<T> = Exclude<T, NotWrappable>;
3
3
  type KeyOf<T> = number extends keyof T ? 0 extends 1 & T ? keyof T : [T] extends [never] ? never : [T] extends [readonly unknown[]] ? number : keyof T : keyof T;
4
4
  export type CustomPartial<T> = T extends readonly unknown[] ? "0" extends keyof T ? {
@@ -0,0 +1,166 @@
1
+ /**
2
+ * Store — target & ownership (INTERNALS-STORE-STATE.md §1, §5b; plan sec. 31).
3
+ *
4
+ * The proxy wraps this internal target, never the raw. `v` is the single
5
+ * committed home; the pending backing (`pb`) is the CoW overlay/clone the
6
+ * draft mutates natively — and, on L2, the **container node's staging**
7
+ * (plan sec. 31.3, Q-A): `k` is the `$TRACK` node given a value. Its `_value` is the
8
+ * committed backing, its `_pendingValue` the pending backing, so the
9
+ * scheduler owns the backing's lifetime (park, commit, revert) and the store
10
+ * keeps no fold ledger of its own. The fold at the flush's commit
11
+ * (`_storeCommit`) is the one mutation of owned raw.
12
+ *
13
+ * Creation budget (§5b): one minimal target + one proxy + one lookup entry
14
+ * per read-through object; nodes, presence nodes, the container node and
15
+ * the deep witness are lazy — materialized by subscription, or (the
16
+ * container) by the first write that needs to stage.
17
+ */
18
+ import type { Computed, Owner, Signal } from "../core/types.js";
19
+ /** Projection family (§7b; returns in S3): children wrap into the family's
20
+ * own map (writes land in the projection, never the source family), and the
21
+ * family's node is the firewall every read through it pulls first. */
22
+ export interface StoreFamily {
23
+ /** Optimistic family (S4): the setter's writes are guesses. */
24
+ opt?: boolean;
25
+ /** Targets carrying a lane value on one of their nodes (reads compose the
26
+ * view over the truth — optimistic.ts); dropped lazily once none is. */
27
+ overlaid?: Set<StoreTarget>;
28
+ /** The derive asked a new question over the family's guesses, stamped
29
+ * with that flush's clock (#4336, optimistic.ts `ask`): `clock + 1` from
30
+ * mainline over a live guess, `~clock` otherwise (a lane's work over no
31
+ * guess of its own, or no live guess left). */
32
+ asked?: number;
33
+ /** Normalized row-key fn (`options.key`, "id" default, null = unkeyed). */
34
+ key?: ((item: any) => any) | null;
35
+ map: WeakMap<object, StoreTarget>;
36
+ /** The projection computed — the firewall. Assigned after creation. */
37
+ node: Computed<any> | null;
38
+ /** Targets of the family that carry nodes: the derive's pending wakes
39
+ * their readers (A9) — the family's enumerable index, in place of a
40
+ * per-leaf chain; a target leaves it with its last node. */
41
+ live: Set<StoreTarget>;
42
+ /** A source's status reaching the derive by propagation (`familyStatus`). */
43
+ st?: (status: number) => void;
44
+ shallow?: boolean;
45
+ /** Derive run counter (proj R37): the run whose draft is live. */
46
+ run?: number;
47
+ /** The derive's pending reached the leaves' readers (`wakeFamily`) and no
48
+ * landing has settled them yet: the next commit walks the family
49
+ * (`settleFamily`). A sync commit with no wake behind it walks nothing. */
50
+ woke?: boolean;
51
+ }
52
+ /** One setter's written keys; `u` is the batch's earlier setters' (the
53
+ * fold's union), present only once a second setter writes the target. */
54
+ export interface WrittenKeys extends Set<PropertyKey> {
55
+ u?: WrittenKeys;
56
+ }
57
+ export interface StoreTarget {
58
+ /** Committed backing: source object (shared) or owned clone. */
59
+ v: Record<PropertyKey, any>;
60
+ /** Pending backing for the current batch (null when settled) — the same
61
+ * object the container node stages (`k._pendingValue`). */
62
+ pb: Record<PropertyKey, any> | null;
63
+ /** cached: committed backing is another store's proxy (§7b chained). */
64
+ ch: boolean;
65
+ /** live value-node count (deleted-key sweep fast-out in the fused walk). */
66
+ nc: number;
67
+ /** Lazy per-property subscription nodes (slot nodes). */
68
+ n: Record<PropertyKey, Signal<any>> | null;
69
+ /** Lazy per-key presence nodes (`in` tracks presence, not value — R13). */
70
+ h: Record<PropertyKey, Signal<boolean>> | null;
71
+ /** Lazy CONTAINER node: membership/iteration/`$TRACK`/`length`
72
+ * subscriptions (§6) and the backing's staging home (plan sec. 31.3). */
73
+ k: Signal<any> | null;
74
+ /** Keys written through the traps by the current setter, with the earlier
75
+ * setters' of the batch chained behind (`u`) until the fold commit. Bounds
76
+ * the setter notify/hold-check to O(written) instead of O(subscribed
77
+ * nodes) — a record with thousands of per-key subscriptions (selection
78
+ * maps) would otherwise pay a full node scan on every write — and to THIS
79
+ * setter's keys (D-8: a key an earlier setter of the batch wrote is told
80
+ * once, #3743). null = no trap writes this batch (bulk paths fall back to
81
+ * the full scan); WK_ALL = bound unusable (array length write).
82
+ * LOAD-BEARING SHAPE RULE: array proxy targets carry their fields as named
83
+ * properties on a real array, and V8
84
+ * normalizes an array to dictionary properties as the named count grows
85
+ * (empirically at counts ≡ 0 mod 3 from 18 up on V8 13.x) — every trap
86
+ * field read then becomes a hash lookup (~15% uibench, tree suites
87
+ * worst). Future write-side state MUST ride an extension object, not new
88
+ * named fields. */
89
+ wk: WrittenKeys | null;
90
+ /** Lazy deep-witness node: `deep()` subscribes ONE node per record instead
91
+ * of one per path; write paths bump it only when it exists. Separate from
92
+ * `k` so $TRACK/mapArray never rerun on leaf value changes (R9). */
93
+ dk: Signal<number> | null;
94
+ /** Parent target (path copying walks this at commit). */
95
+ u: StoreTarget | null;
96
+ /** Property key of this target in the parent's backing. */
97
+ pk: PropertyKey | null;
98
+ /** The proxy for this target (stable outward identity). */
99
+ px: any;
100
+ /** Sticky descendants flag (§6d). */
101
+ d: boolean;
102
+ /** Sticky accessors-seen flag: an own accessor property was observed on
103
+ * this target (first-read scan, defineProperty, or clone scan). Gates the
104
+ * fold diff's descriptor-safe path and the get trap's descriptor path. */
105
+ a: boolean;
106
+ /** Accessor scan grade: 0 = not yet scanned (adoption resets — adopted data
107
+ * is not rescanned until the next draft), 1 = scanned, 2 = scanned and
108
+ * PLAIN DATA — `Object.prototype` with every own key an enumerable data
109
+ * property. Grade 2 unlocks the spread clone (cloneRaw), bare-assignment
110
+ * overlay writes and flatten (#3360); a non-plain defineProperty through
111
+ * the draft downgrades it to 1. */
112
+ sc: 0 | 1 | 2;
113
+ /** Own-key count: exact at scan, then bumped by set-trap writes of keys new
114
+ * to the container (never decremented — an estimate for the overlay/clone
115
+ * choice only, #3360). */
116
+ kc: number;
117
+ /** Pending backing is a prototype-chain OVERLAY of the committed backing
118
+ * (`Object.create(v)` — own keys are this batch's writes, everything else
119
+ * reads through). O(written) per flush instead of O(container) clones
120
+ * (#3044); commit flattens own keys onto an owned committed backing in
121
+ * place. Plain-data non-array containers qualify; chained backings and
122
+ * accessor containers keep the descriptor clone. `materializePB`
123
+ * downgrades to the clone path when a consumer needs a real container
124
+ * (draft escape). */
125
+ ovl: boolean;
126
+ /** Keys deleted in the overlay window (a prototype overlay cannot shadow
127
+ * a delete); null when none. */
128
+ del: Set<PropertyKey> | null;
129
+ /** Projection family, null for plain stores (§7b). */
130
+ fam: StoreFamily | null;
131
+ /** Shallow store root (values served raw). */
132
+ s: boolean;
133
+ }
134
+ /**
135
+ * Ownership stamp (#3360): every backing the store ALLOCATES (CoW clones,
136
+ * privatized committed backings) carries its owning target under this
137
+ * enumerable symbol. One property write replaces the two weak-collection
138
+ * registrations (ownership set + raw→target map) a fresh object used to pay
139
+ * per draft — V8's identity-hash + ephemeron cost dominated the one-key
140
+ * write floor. Enumerable so a spread copy (the plain-data clone path) stays
141
+ * on the fast path and carries the stamp along.
142
+ *
143
+ * Owned backings are never user-reachable (`snapshot` copies them, the traps
144
+ * hide the key), so every raw key walk in the store must skip `$OWNER`, and
145
+ * ownership is answered by `isOwned` — a user object never carries it.
146
+ * Overlay drafts (`Object.create(v)` over an owned `v`) inherit the stamp.
147
+ */
148
+ export declare const $OWNER: unique symbol;
149
+ /** raw → target for plain (family-less) stores. Family stores use their own
150
+ * map so one raw can wrap once per family (§7b). */
151
+ export declare const storeLookup: WeakMap<object, StoreTarget>;
152
+ export declare function setLookup(raw: object, t: StoreTarget): void;
153
+ export declare function isOwned(raw: object): boolean;
154
+ /** The target wrapping `raw` in `fam` (or the plain lookup). An owned raw
155
+ * answers from its stamp; a user raw from the map. */
156
+ export declare function lookupTarget(raw: object, fam: StoreFamily | null): StoreTarget | undefined;
157
+ /** Test-tier oracle (INTERNALS §5): no write path ever mutates a
158
+ * user-provided (non-owned) object. */
159
+ export declare const ingestedRaw: WeakSet<object> | null;
160
+ export declare function devAssertNeverUserMutation(target: object): void;
161
+ /** Sticky descendants flag up the parent chain (§6d): adoption descends
162
+ * into a changed child pair only where a target with nodes exists below. */
163
+ export declare function markDescendants(target: StoreTarget): void;
164
+ /** Observe tier: the owner in scope at `createStore` (attribution names and
165
+ * owner paths); the `_owner` write never reaches the proxy. */
166
+ export declare const storeOwners: WeakMap<StoreTarget, Owner | null> | null;