@solidjs/signals 2.0.0-rc.15 → 2.0.0-rc.17

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 (90) hide show
  1. package/dist/dev-shared.js +2268 -1734
  2. package/dist/dev.attribution.js +75 -52
  3. package/dist/dev.js +1348 -658
  4. package/dist/observe/affects-marks.js +86 -0
  5. package/dist/observe/affects.js +22 -73
  6. package/dist/observe/boundaries.js +192 -190
  7. package/dist/observe/core/async.js +177 -131
  8. package/dist/observe/core/attribution-queries.js +1 -1
  9. package/dist/observe/core/attribution.js +176 -159
  10. package/dist/observe/core/constants.js +17 -3
  11. package/dist/observe/core/context.js +5 -3
  12. package/dist/observe/core/core.js +520 -364
  13. package/dist/observe/core/dev.js +66 -38
  14. package/dist/observe/core/effect.js +50 -48
  15. package/dist/observe/core/error.js +5 -3
  16. package/dist/observe/core/external.js +5 -6
  17. package/dist/observe/core/graph.js +60 -44
  18. package/dist/observe/core/heap.js +33 -33
  19. package/dist/observe/core/identities.js +62 -0
  20. package/dist/observe/core/lanes.js +238 -260
  21. package/dist/observe/core/owner.js +117 -79
  22. package/dist/observe/core/scheduler.js +381 -217
  23. package/dist/observe/core/truth.js +45 -0
  24. package/dist/observe/core/verdict.js +91 -50
  25. package/dist/observe/deferred.js +184 -0
  26. package/dist/observe/index.js +7 -1
  27. package/dist/observe/map.js +345 -260
  28. package/dist/observe/reveal.js +76 -76
  29. package/dist/observe/signals.js +47 -31
  30. package/dist/observe/store/affects.js +18 -18
  31. package/dist/observe/store/edges.js +39 -0
  32. package/dist/observe/store/optimistic.js +146 -100
  33. package/dist/observe/store/projection.js +68 -55
  34. package/dist/observe/store/store.js +180 -118
  35. package/dist/prod/affects-marks.js +86 -0
  36. package/dist/prod/affects.js +23 -72
  37. package/dist/prod/boundaries.js +156 -154
  38. package/dist/prod/core/async.js +173 -127
  39. package/dist/prod/core/constants.js +17 -3
  40. package/dist/prod/core/context.js +5 -3
  41. package/dist/prod/core/core.js +495 -343
  42. package/dist/prod/core/effect.js +70 -68
  43. package/dist/prod/core/error.js +5 -3
  44. package/dist/prod/core/external.js +5 -6
  45. package/dist/prod/core/graph.js +60 -44
  46. package/dist/prod/core/heap.js +38 -38
  47. package/dist/prod/core/identities.js +62 -0
  48. package/dist/prod/core/lanes.js +230 -252
  49. package/dist/prod/core/owner.js +114 -77
  50. package/dist/prod/core/scheduler.js +327 -163
  51. package/dist/prod/core/truth.js +45 -0
  52. package/dist/prod/core/verdict.js +90 -49
  53. package/dist/prod/deferred.js +182 -0
  54. package/dist/prod/index.js +7 -1
  55. package/dist/prod/map.js +360 -275
  56. package/dist/prod/reveal.js +76 -76
  57. package/dist/prod/signals.js +42 -26
  58. package/dist/prod/store/affects.js +6 -6
  59. package/dist/prod/store/edges.js +39 -0
  60. package/dist/prod/store/optimistic.js +143 -98
  61. package/dist/prod/store/projection.js +25 -19
  62. package/dist/prod/store/store.js +157 -100
  63. package/dist/types/affects-marks.d.ts +14 -0
  64. package/dist/types/boundaries.d.ts +1 -1
  65. package/dist/types/core/async.d.ts +10 -0
  66. package/dist/types/core/constants.d.ts +13 -1
  67. package/dist/types/core/core.d.ts +54 -5
  68. package/dist/types/core/dev.d.ts +51 -13
  69. package/dist/types/core/error.d.ts +9 -1
  70. package/dist/types/core/graph.d.ts +11 -0
  71. package/dist/types/core/identities.d.ts +17 -0
  72. package/dist/types/core/index.d.ts +2 -1
  73. package/dist/types/core/lanes.d.ts +2 -14
  74. package/dist/types/core/owner.d.ts +9 -3
  75. package/dist/types/core/scheduler.d.ts +70 -32
  76. package/dist/types/core/truth.d.ts +16 -0
  77. package/dist/types/core/types.d.ts +21 -0
  78. package/dist/types/core/verdict.d.ts +32 -0
  79. package/dist/types/deferred.d.ts +28 -0
  80. package/dist/types/index.d.ts +6 -0
  81. package/dist/types/map.d.ts +2 -2
  82. package/dist/types/signals.d.ts +28 -7
  83. package/dist/types/store/edges.d.ts +9 -0
  84. package/dist/types/store/index.d.ts +10 -3
  85. package/dist/types/store/optimistic.d.ts +3 -2
  86. package/dist/types/store/projection.d.ts +4 -3
  87. package/dist/types/store/store.d.ts +1 -1
  88. package/dist/types/store/target.d.ts +16 -8
  89. package/dist/types/store/types.d.ts +14 -0
  90. package/package.json +1 -1
@@ -20,6 +20,13 @@ export interface Link {
20
20
  export interface NodeOptions<T> {
21
21
  id?: string;
22
22
  name?: string;
23
+ /**
24
+ * Source location (`file:line:col`, root-relative) written by the
25
+ * compiler's `sourceNames` `locations` kind; dev and observe builds keep it
26
+ * for console reports and diagnostic events, production ignores it. Not
27
+ * meant to be written by hand.
28
+ */
29
+ loc?: string;
23
30
  transparent?: boolean;
24
31
  equals?: ((prev: T, next: T) => boolean) | false;
25
32
  ownedWrite?: boolean;
@@ -108,6 +115,11 @@ export interface NodeExtension {
108
115
  * changes — `isPending` reads true for it and its derivations while any
109
116
  * is live. A count, never a hold. */
110
117
  _marks: number;
118
+ /** D-41: the error a node showed when a re-ask made it pending — still
119
+ * the display (D-39) until a new answer commits: an untracked read throws
120
+ * it, `isPending` reads a staged answer as a change over it, and a
121
+ * recovery equal to the last good value is still a new answer. */
122
+ _shownError: unknown;
111
123
  }
112
124
  export interface RawSignal<T> {
113
125
  _subs: Link | null;
@@ -141,6 +153,8 @@ export type Signal<T> = RawSignal<T>;
141
153
  export interface Owner {
142
154
  id?: string;
143
155
  _config: number;
156
+ /** Lifecycle flags (REACTIVE_*); roots carry only REACTIVE_DISPOSED. */
157
+ _flags: number;
144
158
  _snapshotScope?: boolean;
145
159
  /** Effect-returned cleanup; managed across reruns, invoked at true disposal */
146
160
  _cleanup?: () => void;
@@ -159,6 +173,13 @@ export interface Owner {
159
173
  * (`<App>`). A slot in the observe/dev literals; absent from prod.
160
174
  */
161
175
  _name?: string;
176
+ /**
177
+ * Observe-tier source location (`file:line:col`): the `loc` option, or
178
+ * the JSX site the rendering layer writes on a component root. A slot
179
+ * beside `_name`; absent from prod. Reserved from property mangling, like
180
+ * `_name`, because solid-js writes it and the core's diagnostics read it.
181
+ */
182
+ _loc?: string;
162
183
  }
163
184
  export interface Computed<T> extends RawSignal<T>, Owner {
164
185
  _deps: Link | null;
@@ -2,4 +2,36 @@
2
2
  * restores the dispatch it found — none inside a memo's pass a window
3
3
  * pulled (`verdictValue`). */
4
4
  export declare function latest<T>(fn: () => T): T;
5
+ /**
6
+ * Reports whether what `fn` reads is still waiting on an update. Read the
7
+ * values in question inside `fn`: the probe answers `true` while any of
8
+ * them depends on a change that is in flight — a write or an async source
9
+ * that has started producing a new value whose result has not landed yet —
10
+ * and `false` once the latest value is the one on screen. The answer is
11
+ * tracked like any read, so a memo or effect that calls `isPending` re-runs
12
+ * when it flips.
13
+ *
14
+ * A read that has no value yet is loading, not pending: inside `fn` it
15
+ * follows the surrounding `Loading` path like any other read, and the probe
16
+ * reports only updates to a value that already exists. A bare `refresh()`
17
+ * does not flip `isPending`; pair it with `affects()` to make the re-ask
18
+ * visible.
19
+ *
20
+ * @param fn expression to probe; read the values in question inside it
21
+ *
22
+ * @returns `true` while a read inside `fn` depends on a change that has not committed yet
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * const [query, setQuery] = createSignal("");
27
+ * const results = createMemo(() => searchProducts(query()));
28
+ * const stale = createMemo(() => isPending(results));
29
+ *
30
+ * setQuery("shoes");
31
+ * // stale() is true until the new results land, while results() keeps
32
+ * // serving the previous list — dim it instead of showing a spinner.
33
+ * ```
34
+ *
35
+ * @description https://v2.solidjs.com/reference/solid-js/reactivity/is-pending
36
+ */
5
37
  export declare function isPending(fn: () => any): boolean;
@@ -0,0 +1,28 @@
1
+ import { type MemoOptions, type SourceAccessor } from "./signals.js";
2
+ /**
3
+ * Creates an async memo that may lag, but never leads. Before its first
4
+ * answer it is an ordinary async memo: readers suspend to the nearest
5
+ * `<Loading>`. After it, a refetch holds nothing: readers keep the last
6
+ * committed value until the new one lands, and the rest of the screen moves
7
+ * on without it. `isPending` reports the refetch, on the node and on what
8
+ * derives from it. Use it for independent widgets (dashboards, feeds,
9
+ * search results) where the previous answer with a "refreshing" indicator is
10
+ * better than waiting with everything else.
11
+ *
12
+ * - It never shows a value ahead of a held change: a refetch that read a
13
+ * held value lands with that hold.
14
+ * - A rejected refetch errors like any memo; the stale value never masks it.
15
+ * - `refresh(d)` is a quiet re-ask, and `await refresh(d)` and `until`
16
+ * wait for the landing rather than the stale value.
17
+ * - Combine with `loadingValue` for a node that never suspends at all.
18
+ *
19
+ * @example
20
+ * ```tsx
21
+ * const rows = createDeferred(() => fetchRows(store.period));
22
+ *
23
+ * <section class={{ stale: isPending(() => rows()) }}>
24
+ * <For each={rows()}>{row => <Row row={row} />}</For>
25
+ * </section>
26
+ * ```
27
+ */
28
+ export declare function createDeferred<T>(fn: (prev?: T) => T | PromiseLike<T> | AsyncIterable<T>, options?: MemoOptions<T>): SourceAccessor<T>;
@@ -5,6 +5,11 @@ export { $REFRESH, action, ContextNotFoundError, NoOwnerError, NotReadyError, Ti
5
5
  * outside dev builds.
6
6
  */
7
7
  export { setConsoleFooter } from "./core/index.js";
8
+ /** @internal The pre-write hook (`setWriteHook` in core/core.ts); the server-components client's deferred hydration. */
9
+ /** @internal Plain-signal identities and the dev read watch (dependency edges; the server-components client). */
10
+ export { setWriteHook, setSignalIdentities, setReadWatch, signalName } from "./core/index.js";
11
+ /** @internal Store dependency edges: the name a store proxy's writes go by (the server-components client). */
12
+ export { storeName } from "./store/edges.js";
8
13
  import { type Dev, type Observe } from "./core/index.js";
9
14
  /**
10
15
  * Observe tier (diagnostics channel, attribution hook slot + interaction
@@ -20,6 +25,7 @@ export type { Truthy, UntilOptions, Accessor, SourceAccessor, Setter, Signal, Co
20
25
  export { mapArray, repeat, type Maybe } from "./map.js";
21
26
  export * from "./store/index.js";
22
27
  export { affects } from "./affects.js";
28
+ export { createDeferred } from "./deferred.js";
23
29
  export { flatten } from "./flatten.js";
24
30
  export { createLoadingBoundary, createErrorBoundary } from "./boundaries.js";
25
31
  export { createRevealOrder, type RevealOrder } from "./reveal.js";
@@ -30,7 +30,7 @@ export type Maybe<T> = T | void | null | undefined | false;
30
30
  * );
31
31
  * ```
32
32
  *
33
- * @description https://docs.solidjs.com/reference/reactive-utilities/map-array
33
+ * @description https://v2.solidjs.com/reference/solid-js/advanced/jsx-component-primitives/map-array
34
34
  */
35
35
  export declare function mapArray<Item, MappedItem>(list: Accessor<Maybe<readonly Item[]>>, map: (value: Item, index: Accessor<number>) => MappedItem, options?: {
36
36
  keyed?: true;
@@ -62,7 +62,7 @@ export declare function __smallMoveHits(): number;
62
62
  * const view = repeat(count, i => `Item ${i}`, { fallback: () => "empty" });
63
63
  * ```
64
64
  *
65
- * @description https://docs.solidjs.com/reference/reactive-utilities/repeat
65
+ * @description https://v2.solidjs.com/reference/solid-js/advanced/jsx-component-primitives/repeat
66
66
  */
67
67
  export declare function repeat(count: Accessor<number>, map: (index: number) => any, options?: {
68
68
  from?: Accessor<number | undefined>;
@@ -92,6 +92,13 @@ export type EffectBundle<Prev, Next extends Prev = Prev> = {
92
92
  interface BaseEffectOptions {
93
93
  /** Debug name (dev mode only) */
94
94
  name?: string;
95
+ /**
96
+ * Source location (`file:line:col`, root-relative) written by the
97
+ * compiler's `sourceNames` `locations` kind beside `name`; dev and observe
98
+ * builds keep it for console reports and diagnostic events, production
99
+ * ignores it. Not meant to be written by hand.
100
+ */
101
+ loc?: string;
95
102
  }
96
103
  /** Options for effect primitives that support deferring/scheduling their initial run (`createEffect`, `createRenderEffect`, `createReaction`). */
97
104
  export interface EffectOptions extends BaseEffectOptions {
@@ -144,6 +151,13 @@ export interface EffectOptions extends BaseEffectOptions {
144
151
  export interface SignalOptions<T> {
145
152
  /** Debug name (dev mode only) */
146
153
  name?: string;
154
+ /**
155
+ * Source location (`file:line:col`, root-relative) written by the
156
+ * compiler's `sourceNames` `locations` kind beside `name`; dev and observe
157
+ * builds keep it for console reports and diagnostic events, production
158
+ * ignores it. Not meant to be written by hand.
159
+ */
160
+ loc?: string;
147
161
  /**
148
162
  * Custom equality function, or `false` to always notify subscribers.
149
163
  * Defaults to reference equality (`isEqual`). Pass a comparator (e.g.
@@ -166,6 +180,13 @@ export interface MemoOptions<T> {
166
180
  id?: string;
167
181
  /** Debug name (dev mode only) */
168
182
  name?: string;
183
+ /**
184
+ * Source location (`file:line:col`, root-relative) written by the
185
+ * compiler's `sourceNames` `locations` kind beside `name`; dev and observe
186
+ * builds keep it for console reports and diagnostic events, production
187
+ * ignores it. Not meant to be written by hand.
188
+ */
189
+ loc?: string;
169
190
  /**
170
191
  * Advanced (integration tier). When true, the memo is invisible to the
171
192
  * hydration id scheme: it inherits its parent's id instead of consuming a
@@ -275,7 +296,7 @@ export type NoInfer<T extends any> = [T][T extends any ? 0 : never];
275
296
  * setUser({ ...user(), name: "Alice" });
276
297
  * ```
277
298
  *
278
- * @description https://docs.solidjs.com/reference/basic-reactivity/create-signal
299
+ * @description https://v2.solidjs.com/reference/solid-js/reactivity/create-signal
279
300
  */
280
301
  export declare function createSignal<T>(): Signal<T | undefined>;
281
302
  export declare function createSignal<T>(value: Exclude<T, Function>, options?: SignalOptions<T>): Signal<T>;
@@ -296,7 +317,7 @@ export declare function createSignal<T>(fn: ComputeFunction<T>, options?: Signal
296
317
  * const [state, setState] = createOptimistic<T>(fn, options?: SignalOptions<T> & MemoOptions<T>);
297
318
  * ```
298
319
  *
299
- * @description https://docs.solidjs.com/reference/basic-reactivity/create-optimistic-signal
320
+ * @description https://v2.solidjs.com/reference/solid-js/reactivity/create-optimistic
300
321
  */
301
322
  export declare function createOptimistic<T>(): Signal<T | undefined>;
302
323
  export declare function createOptimistic<T>(value: Exclude<T, Function>, options?: SignalOptions<T>): Signal<T>;
@@ -329,7 +350,7 @@ export declare function createOptimistic<T>(fn: ComputeFunction<T>, options?: Si
329
350
  * });
330
351
  * ```
331
352
  *
332
- * @description https://docs.solidjs.com/reference/basic-reactivity/create-memo
353
+ * @description https://v2.solidjs.com/reference/solid-js/reactivity/create-memo
333
354
  */
334
355
  export declare function createMemo<T>(compute: ComputeFunction<NoInfer<T>, T>, options: MemoOptions<T> & {
335
356
  loadingValue: T;
@@ -401,7 +422,7 @@ export declare function createMemo<T>(compute: ComputeFunction<undefined | NoInf
401
422
  * );
402
423
  * ```
403
424
  *
404
- * @description https://docs.solidjs.com/reference/basic-reactivity/create-effect
425
+ * @description https://v2.solidjs.com/reference/solid-js/reactivity/create-effect
405
426
  */
406
427
  export declare function createEffect<const T>(compute: ComputeFunction<undefined | NoInfer<T>, T>, effectFn: EffectFunction<NoInfer<T>, T> | EffectBundle<NoInfer<T>, T>, options?: EffectOptions): void;
407
428
  /**
@@ -431,7 +452,7 @@ export declare function createEffect<const T>(compute: ComputeFunction<undefined
431
452
  * }
432
453
  * ```
433
454
  *
434
- * @description https://docs.solidjs.com/reference/secondary-primitives/create-render-effect
455
+ * @description https://v2.solidjs.com/reference/solid-js/advanced/specialized-reactivity/create-render-effect
435
456
  */
436
457
  export declare function createRenderEffect<const T>(compute: ComputeFunction<undefined | NoInfer<T>, T>, effectFn: EffectFunction<NoInfer<T>, T>, options?: EffectOptions): void;
437
458
  /**
@@ -477,7 +498,7 @@ export declare function createRenderEffect<const T>(compute: ComputeFunction<und
477
498
  * });
478
499
  * ```
479
500
  *
480
- * @description https://docs.solidjs.com/reference/secondary-primitives/create-tracked-effect
501
+ * @description https://v2.solidjs.com/reference/solid-js/advanced/specialized-reactivity/create-tracked-effect
481
502
  */
482
503
  export declare function createTrackedEffect(compute: () => void | (() => void), options?: BaseEffectOptions): void;
483
504
  /**
@@ -504,7 +525,7 @@ export declare function createTrackedEffect(compute: () => void | (() => void),
504
525
  * setCount(1); // logs once, reaction re-armed for next change
505
526
  * ```
506
527
  *
507
- * @description https://docs.solidjs.com/reference/secondary-primitives/create-reaction
528
+ * @description https://v2.solidjs.com/reference/solid-js/advanced/specialized-reactivity/create-reaction
508
529
  */
509
530
  export declare function createReaction(effectFn: EffectFunction<undefined> | EffectBundle<undefined>, options?: EffectOptions): (tracking: () => void) => void;
510
531
  /**
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @internal The name of the store `x` belongs to — `x` a store proxy (a
3
+ * setter's entry) or one of its property nodes (the setter notifying it) —
4
+ * or undefined when it has none or it cannot be placed: a projection or
5
+ * optimistic family, a store chained over another store's proxy, a root
6
+ * named twice, or a proxy reached through a store other than the one it
7
+ * was named as the root of.
8
+ */
9
+ export declare function storeName(x: object | undefined): string | undefined;
@@ -3,14 +3,14 @@
3
3
  * (`createStore(fn, seed)`), projections, optimistic stores and reconcile
4
4
  * return on later steps (plan sec. 31.5).
5
5
  */
6
- export type { NoFn, NotWrappable, ProjectionOptions, ProjectionStoreReturn, SolidStore, Store, StoreOptions, StoreReturn, StoreSetter } from "./types.js";
6
+ export type { NoArray, NoFn, NotWrappable, ProjectionOptions, ProjectionStoreReturn, SolidStore, Store, StoreOptions, StoreReturn, StoreSetter } from "./types.js";
7
7
  export { $PROXY, $RECORD, $TARGET, $TRACK, isWrappable, markRaw } from "./types.js";
8
8
  export { storeIsShallow, storeHasFamily, storeHasOptimisticFamily } from "./store.js";
9
9
  export { storePath } from "./storePath.js";
10
10
  export type { StorePathRange, PathSetter, Part, CustomPartial, ArrayFilterFn } from "./storePath.js";
11
11
  import { createOptimisticStore } from "./optimistic.js";
12
12
  import { createProjection } from "./projection.js";
13
- import type { NoFn, ProjectionOptions, ProjectionStoreReturn, Store, StoreOptions, StoreReturn } from "./types.js";
13
+ import type { NoArray, NoFn, ProjectionOptions, ProjectionStoreReturn, Store, StoreOptions, StoreReturn } from "./types.js";
14
14
  export { createOptimisticStore, createProjection };
15
15
  /** The store's internal record behind a proxy (`store[$TARGET]`). Kept
16
16
  * under `next`'s public name; its shape is the L2 target's (plan plan sec. 31–32:
@@ -23,9 +23,16 @@ export type { SourceKind } from "./utils.js";
23
23
  * Create a reactive store: a proxy over plain data with fine-grained
24
24
  * subscriptions per read path, written through its setter's draft — or, in
25
25
  * the derived form, a projection with a setter.
26
+ *
27
+ * The derived form comes in two shapes. Seedless, `createStore(fn)`: `fn`
28
+ * takes no draft and every answer is a complete `T` (plain-object roots only;
29
+ * pass `undefined` for the seed to reach the options). Seeded,
30
+ * `createStore(fn, seed)`: the seed is a complete `T` the derive drafts
31
+ * against — `[]` for an array.
26
32
  */
27
33
  export declare function createStore<T extends object = {}>(initialValue: NoFn<T>, options?: StoreOptions): StoreReturn<T>;
28
- export declare function createStore<T extends object = {}>(fn: (draft: T) => void | T | Promise<void | T> | AsyncIterable<void | T>, seed: Partial<T> | Store<NoFn<T>>, options?: ProjectionOptions): ProjectionStoreReturn<T>;
34
+ export declare function createStore<T extends object = {}>(fn: (() => T | Promise<T> | AsyncIterable<T>) & NoArray<T>, seed?: null, options?: Omit<ProjectionOptions, "seedLoadingValue">): ProjectionStoreReturn<T>;
35
+ export declare function createStore<T extends object = {}>(fn: (draft: T) => void | T | Promise<void | T> | AsyncIterable<void | T>, seed: NoFn<T> | Store<NoFn<T>>, options?: ProjectionOptions): ProjectionStoreReturn<T>;
29
36
  /**
30
37
  * A setter transform that reconciles `value` into the store by key
31
38
  * (`"id"` by default; `null` positional), preserving store identity for
@@ -1,6 +1,6 @@
1
1
  import type { Refreshable } from "../core/index.js";
2
2
  import { type StoreTarget } from "./target.js";
3
- import { type NoFn, type ProjectionOptions, type Store, type StoreOptions, type StoreSetter } from "./types.js";
3
+ import { type NoArray, type NoFn, type ProjectionOptions, type Store, type StoreOptions, type StoreSetter } from "./types.js";
4
4
  export declare function notifyOptimisticWrites(t: StoreTarget, pb: Record<PropertyKey, any>): Record<PropertyKey, any> | null;
5
5
  export declare function sweepOverlaid(): void;
6
6
  /** An untracked `key in store` on an optimistic family: the presence guess
@@ -20,4 +20,5 @@ export declare function optimisticView(t: StoreTarget, src: Record<PropertyKey,
20
20
  * guess is what lands). */
21
21
  export declare function latestView(t: StoreTarget, src: Record<PropertyKey, any>): Record<PropertyKey, any>;
22
22
  export declare function createOptimisticStore<T extends object = {}>(initialValue: NoFn<T> | Store<NoFn<T>>, options?: StoreOptions): [get: Store<T>, set: StoreSetter<T>];
23
- export declare function createOptimisticStore<T extends object = {}>(fn: (draft: T) => void | T | Promise<void | T> | AsyncIterable<void | T>, seed: Partial<T> | Store<NoFn<T>>, options?: ProjectionOptions): [get: Refreshable<Store<T>>, set: StoreSetter<T>];
23
+ export declare function createOptimisticStore<T extends object = {}>(fn: (() => T | Promise<T> | AsyncIterable<T>) & NoArray<T>, seed?: null, options?: Omit<ProjectionOptions, "seedLoadingValue">): [get: Refreshable<Store<T>>, set: StoreSetter<T>];
24
+ export declare function createOptimisticStore<T extends object = {}>(fn: (draft: T) => void | T | Promise<void | T> | AsyncIterable<void | T>, seed: NoFn<T> | Store<NoFn<T>>, options?: ProjectionOptions): [get: Refreshable<Store<T>>, set: StoreSetter<T>];
@@ -1,6 +1,6 @@
1
1
  import type { Computed } from "../core/types.js";
2
2
  import type { Refreshable } from "../core/index.js";
3
- import { type NoFn, type ProjectionOptions, type Store } from "./types.js";
3
+ import { type NoArray, type NoFn, type ProjectionOptions, type Store } from "./types.js";
4
4
  /** The derive's pass: run `fn` against a draft of the store; commit its
5
5
  * result (sync, or each async landing) through the reconcile channel.
6
6
  * Draft validity is per run (R37): live from here until the NEXT run starts
@@ -13,6 +13,7 @@ export declare function runProjectionComputed<T extends object>(wrappedStore: St
13
13
  * firewall). `fn` may be async or an async iterator; the seed is a draft,
14
14
  * never an observable value, until the first landing (A25).
15
15
  */
16
- 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>>;
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>>;
17
18
  /** `createStore(fn, seed, options)`: a projection with a user setter. */
18
- export declare function createStoreDerived<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>>, (f: (draft: T) => T | void) => void];
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];
@@ -46,7 +46,7 @@ export declare function getHasNode(target: StoreTarget, key: PropertyKey): Signa
46
46
  * committed backing. */
47
47
  export declare function getContainerNode(target: StoreTarget): Signal<any>;
48
48
  export declare function bumpDeep(t: StoreTarget): void;
49
- export declare function nameStore(proxy: any, name: string | undefined): void;
49
+ export declare function nameStore(proxy: any, name: string | undefined, loc?: string): void;
50
50
  /** Shallow clone into store ownership. Plain data (grade 2) spreads; anything
51
51
  * else copies descriptors (accessors kept, everything made configurable). */
52
52
  export declare function cloneRaw(source: Record<PropertyKey, any>, t: StoreTarget): Record<PropertyKey, any>;
@@ -42,6 +42,11 @@ export interface StoreFamily {
42
42
  * (`settleFamily`). A sync commit with no wake behind it walks nothing. */
43
43
  woke?: boolean;
44
44
  }
45
+ /** One setter's written keys; `u` is the batch's earlier setters' (the
46
+ * fold's union), present only once a second setter writes the target. */
47
+ export interface WrittenKeys extends Set<PropertyKey> {
48
+ u?: WrittenKeys;
49
+ }
45
50
  export interface StoreTarget {
46
51
  /** Committed backing: source object (shared) or owned clone. */
47
52
  v: Record<PropertyKey, any>;
@@ -59,19 +64,22 @@ export interface StoreTarget {
59
64
  /** Lazy CONTAINER node: membership/iteration/`$TRACK`/`length`
60
65
  * subscriptions (§6) and the backing's staging home (plan sec. 31.3). */
61
66
  k: Signal<any> | null;
62
- /** Keys written through the traps since the last fold commit. Bounds the
63
- * setter notify/hold-check to O(written) instead of O(subscribed nodes) —
64
- * a record with thousands of per-key subscriptions (selection maps) would
65
- * otherwise pay a full node scan on every write. null = no trap writes
66
- * this batch (bulk paths fall back to the full scan); WK_ALL = bound
67
- * unusable (array length write). LOAD-BEARING SHAPE RULE: array proxy
68
- * targets carry their fields as named properties on a real array, and V8
67
+ /** Keys written through the traps by the current setter, with the earlier
68
+ * setters' of the batch chained behind (`u`) until the fold commit. Bounds
69
+ * the setter notify/hold-check to O(written) instead of O(subscribed
70
+ * nodes) — a record with thousands of per-key subscriptions (selection
71
+ * maps) would otherwise pay a full node scan on every write — and to THIS
72
+ * setter's keys (D-8: a key an earlier setter of the batch wrote is told
73
+ * once, #3743). null = no trap writes this batch (bulk paths fall back to
74
+ * the full scan); WK_ALL = bound unusable (array length write).
75
+ * LOAD-BEARING SHAPE RULE: array proxy targets carry their fields as named
76
+ * properties on a real array, and V8
69
77
  * normalizes an array to dictionary properties as the named count grows
70
78
  * (empirically at counts ≡ 0 mod 3 from 18 up on V8 13.x) — every trap
71
79
  * field read then becomes a hash lookup (~15% uibench, tree suites
72
80
  * worst). Future write-side state MUST ride an extension object, not new
73
81
  * named fields. */
74
- wk: Set<PropertyKey> | null;
82
+ wk: WrittenKeys | null;
75
83
  /** Lazy deep-witness node: `deep()` subscribes ONE node per record instead
76
84
  * of one per path; write paths bump it only when it exists. Separate from
77
85
  * `k` so $TRACK/mapArray never rerun on leaf value changes (R9). */
@@ -34,6 +34,13 @@ export interface StoreOptions {
34
34
  * projection node carries the name itself.
35
35
  */
36
36
  name?: string;
37
+ /**
38
+ * Source location (`file:line:col`, root-relative) written by the
39
+ * compiler's `sourceNames` `locations` kind; dev and observe builds keep it
40
+ * for console reports and diagnostic events, production ignores it. Not
41
+ * meant to be written by hand.
42
+ */
43
+ loc?: string;
37
44
  /** Single-layer store: root keys reactive, values raw records replaced by reference */
38
45
  shallow?: boolean;
39
46
  }
@@ -60,7 +67,14 @@ export interface ProjectionOptions extends StoreOptions {
60
67
  */
61
68
  seedLoadingValue?: boolean;
62
69
  }
70
+ /** @internal */
63
71
  export type NoFn<T> = T extends Function ? never : T;
72
+ /**
73
+ * Rejects array roots on the seedless derived form: a store's root shape is
74
+ * fixed when it is created, and `[]` is already a complete seed for an array.
75
+ * @internal
76
+ */
77
+ export type NoArray<T> = Extract<T, readonly unknown[]> extends never ? unknown : never;
64
78
  /** Brand keys the proxy answers directly (never user data). */
65
79
  export declare const $TRACK: unique symbol, $TARGET: unique symbol, $PROXY: unique symbol, $RECORD: unique symbol;
66
80
  export declare namespace SolidStore {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solidjs/signals",
3
- "version": "2.0.0-rc.15",
3
+ "version": "2.0.0-rc.17",
4
4
  "description": "Solid's reactive primitives: signals, memos, effects, stores, and async-aware computations.",
5
5
  "author": "Ryan Carniato",
6
6
  "license": "MIT",