@solidjs/signals 2.0.0-rc.5 → 2.0.0-rc.7

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 (66) hide show
  1. package/dist/dev.js +2467 -1322
  2. package/dist/node.cjs +2037 -2428
  3. package/dist/node.dev.cjs +13724 -0
  4. package/dist/prod/boundaries.js +3 -1
  5. package/dist/prod/core/async.js +47 -20
  6. package/dist/prod/core/attribution-hooks.js +3 -0
  7. package/dist/prod/core/constants.js +9 -1
  8. package/dist/prod/core/context.js +10 -16
  9. package/dist/prod/core/core.js +260 -188
  10. package/dist/prod/core/dev.js +2 -0
  11. package/dist/prod/core/effect.js +41 -32
  12. package/dist/prod/core/external.js +2 -2
  13. package/dist/prod/core/graph.js +35 -31
  14. package/dist/prod/core/heap.js +34 -40
  15. package/dist/prod/core/lanes.js +44 -30
  16. package/dist/prod/core/optimistic.js +55 -45
  17. package/dist/prod/core/owner.js +35 -35
  18. package/dist/prod/core/scheduler.js +176 -177
  19. package/dist/prod/core/verdict.js +53 -52
  20. package/dist/prod/index.js +0 -2
  21. package/dist/prod/map.js +104 -94
  22. package/dist/prod/signals.js +119 -35
  23. package/dist/prod/store/next/optimistic.js +217 -163
  24. package/dist/prod/store/next/projection.js +2 -2
  25. package/dist/prod/store/next/reconcile.js +140 -288
  26. package/dist/prod/store/next/store.js +338 -252
  27. package/dist/prod/store/store.js +2 -2
  28. package/dist/types/core/attribution-hooks.d.ts +75 -0
  29. package/dist/types/core/attribution.d.ts +313 -9
  30. package/dist/types/core/constants.d.ts +8 -0
  31. package/dist/types/core/core.d.ts +12 -3
  32. package/dist/types/core/dev.d.ts +56 -9
  33. package/dist/types/core/heap.d.ts +5 -3
  34. package/dist/types/core/invariants.d.ts +1 -1
  35. package/dist/types/core/lanes.d.ts +10 -0
  36. package/dist/types/core/scheduler.d.ts +14 -4
  37. package/dist/types/signals.d.ts +10 -11
  38. package/dist/types/store/index.d.ts +3 -6
  39. package/dist/types/store/next/optimistic.d.ts +4 -2
  40. package/dist/types/store/next/reconcile.d.ts +5 -12
  41. package/dist/types/store/next/store.d.ts +3 -9
  42. package/dist/types/store/next/target.d.ts +30 -46
  43. package/dist/types/store/store.d.ts +14 -9
  44. package/dist/types-cjs/core/attribution-hooks.d.cts +75 -0
  45. package/dist/types-cjs/core/attribution.d.cts +313 -9
  46. package/dist/types-cjs/core/constants.d.cts +8 -0
  47. package/dist/types-cjs/core/core.d.cts +12 -3
  48. package/dist/types-cjs/core/dev.d.cts +56 -9
  49. package/dist/types-cjs/core/heap.d.cts +5 -3
  50. package/dist/types-cjs/core/invariants.d.cts +1 -1
  51. package/dist/types-cjs/core/lanes.d.cts +10 -0
  52. package/dist/types-cjs/core/scheduler.d.cts +14 -4
  53. package/dist/types-cjs/signals.d.cts +10 -11
  54. package/dist/types-cjs/store/index.d.cts +3 -6
  55. package/dist/types-cjs/store/next/optimistic.d.cts +4 -2
  56. package/dist/types-cjs/store/next/reconcile.d.cts +5 -12
  57. package/dist/types-cjs/store/next/store.d.cts +3 -9
  58. package/dist/types-cjs/store/next/target.d.cts +30 -46
  59. package/dist/types-cjs/store/store.d.cts +14 -9
  60. package/package.json +3 -2
  61. package/dist/prod/store/next/patch-hooks.js +0 -13
  62. package/dist/prod/store/next/patch.js +0 -614
  63. package/dist/types/store/next/patch-hooks.d.ts +0 -41
  64. package/dist/types/store/next/patch.d.ts +0 -91
  65. package/dist/types-cjs/store/next/patch-hooks.d.cts +0 -41
  66. package/dist/types-cjs/store/next/patch.d.cts +0 -91
@@ -1,5 +1,6 @@
1
+ import { type Refreshable } from "../../core/index.cjs";
1
2
  import { type Transition } from "../../core/scheduler.cjs";
2
- import { type NoFn, type ProjectionOptions, type Store, type StoreSetter } from "../store.cjs";
3
+ import { type NoFn, type ProjectionOptions, type Store, type StoreOptions, type StoreSetter } from "../store.cjs";
3
4
  import type { StoreNextTarget } from "./target.cjs";
4
5
  /** #3164 fold: a stamped truth is HELD (masked from ordinary readers until
5
6
  * the reveal) only while its transition is live AND retaining optimism —
@@ -8,7 +9,8 @@ import type { StoreNextTarget } from "./target.cjs";
8
9
  * staged values to converge (normal speculation). Resolves merges first:
9
10
  * merge unions optimistic nodes/stores into the target. */
10
11
  export declare function transitionHoldsOptimism(transition: Transition): boolean;
11
- export declare function createOptimisticStoreNext<T extends object = {}>(first: T | ((store: T) => void | T | Promise<void | T> | AsyncIterable<void | T>), second?: NoFn<T> | Store<NoFn<T>>, options?: ProjectionOptions): [get: Store<T>, set: StoreSetter<T>];
12
+ export declare function createOptimisticStoreNext<T extends object = {}>(initialValue: NoFn<T> | Store<NoFn<T>>, options?: StoreOptions): [get: Store<T>, set: StoreSetter<T>];
13
+ export declare function createOptimisticStoreNext<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>];
12
14
  /** Diff the draft against the current OPTIMISTIC VIEW (committed + active
13
15
  * overrides — the same view the draft was seeded from) and emit engine writes
14
16
  * for exactly the changed keys. Visible-view diffing keeps no-op writes from
@@ -1,17 +1,10 @@
1
- import type { RowOps } from "./patch.cjs";
2
- import { type StoreNextTarget } from "./target.cjs";
3
1
  type KeyFn = (item: any) => any;
4
2
  export declare function reconcileNextState(value: any, state: any, key: string | KeyFn | null | undefined, replace?: boolean): void;
3
+ /** Setter-channel row ops (the fold site calls this for array targets with
4
+ * ops consumers): structural mutation through the setter — push/splice/index
5
5
  /** Key equality for EVERY key comparison in this module (re-audit 2, P1-5):
6
- * SameValueZero, matching the Map-based matchers (buildRowOps, the adoption
7
- * window) — NaN keys are equal to themselves, so aligned NaN rows stay
8
- * aligned in the prefix walk instead of forever misaligning. Adoption and
9
- * row ops MUST agree on key equality or retained DOM rows go stale. */
6
+ * SameValueZero, matching the adoption window's Map-based matcher — NaN keys
7
+ * are equal to themselves, so aligned NaN rows stay aligned in the prefix
8
+ * walk instead of forever misaligning. */
10
9
  export declare function sameKey(a: any, b: any): boolean;
11
- export declare function emitSetterRowOps(t: StoreNextTarget, prevRows: any[], nextRows: any[]): void;
12
- /** Identity-keyed structural diff, returned rather than emitted: shared by
13
- * the setter channel (regular queue) and the OPTIMISTIC write channel (lane
14
- * queue) — same retention semantics, different dispatch timing. Returns
15
- * null when the lists are identity-aligned (no structure changed). */
16
- export declare function buildIdentityRowOps(prevRows: any[], nextRows: any[]): RowOps | null;
17
10
  export {};
@@ -1,20 +1,14 @@
1
1
  import type { Signal } from "../../core/types.cjs";
2
- import { type StoreNextFamily, type StoreNextTarget, type PatchChannel } from "./target.cjs";
3
- /** Lazily allocate the patch-channel extension (one literal shape). */
4
- export declare function pcOf(t: StoreNextTarget): PatchChannel;
2
+ import { type StoreNextFamily, type StoreNextTarget } from "./target.cjs";
5
3
  export declare function wrapNext<T extends Record<PropertyKey, any>>(value: T, parent?: StoreNextTarget | null, parentKey?: PropertyKey | null, fam?: StoreNextFamily | null): T;
6
4
  /** Unwrap our own proxies to their current backing; leave everything else. */
7
5
  export declare function unwrapValue(v: any): any;
8
- export declare function getNode(target: StoreNextTarget, key: PropertyKey, current: any): Signal<any>;
6
+ export declare function getNode(target: StoreNextTarget, key: PropertyKey, current: any, accKnown?: -1 | 0 | 1): Signal<any>;
9
7
  export declare function getHasNode(target: StoreNextTarget, key: PropertyKey, present: boolean): Signal<boolean>;
10
8
  export declare function getKeySetNode(target: StoreNextTarget): Signal<number>;
11
9
  /** Deep-witness bump: any value/shape change on a record with a live deep()
12
10
  * subscriber notifies it. One null check when unused. */
13
11
  export declare function bumpDeep(t: StoreNextTarget): void;
14
- /** Scanned plainness for patch admission (patchableRaw): runs the one-time
15
- * accessor scan if it hasn't happened yet — the sticky `a` flag alone is not
16
- * trustworthy before a scan (it starts false and is discovered lazily). */
17
- export declare function targetIsPlain(target: StoreNextTarget): boolean;
18
12
  /** Downgrade a prototype-overlay pending backing to the clone path: builds
19
13
  * the real container (committed + overlay writes − deletes) that fold will
20
14
  * SWAP in as the committed backing, exactly as if the draft had started on
@@ -90,7 +84,7 @@ export type SetStoreNextFunction<T> = (fn: (draft: T) => T | void) => void;
90
84
  * replacements as adoptions. `guard=false` skips the owned-scope dev guard —
91
85
  * projection recomputes legitimately write from inside their computed. */
92
86
  export declare function storeSetterNext<T>(proxy: T, fn: (draft: T) => T | void, guard?: boolean): void;
93
- export declare function createStoreNext<T extends Record<PropertyKey, any>>(init: T, shallow?: boolean): [T, SetStoreNextFunction<T>];
87
+ export declare function createStoreNext<T extends Record<PropertyKey, any>>(initialValue: T, shallow?: boolean): [T, SetStoreNextFunction<T>];
94
88
  /** True when `proxy` is a SHALLOW store (children served verbatim, slots
95
89
  * replaced by reference — #2932). The list driver uses this to choose the
96
90
  * slot-patch channel (collected row bodies) over per-record registration. */
@@ -12,7 +12,7 @@
12
12
  * entry per read-through object; zero layer slots; nodes, has-nodes, and the
13
13
  * key-set node are lazy, materialized only by subscription.
14
14
  */
15
- import type { Computed, Owner, Signal } from "../../core/types.cjs";
15
+ import type { Computed, Signal } from "../../core/types.cjs";
16
16
  /** Projection family (§7b): children wrap into the family's own map (writes
17
17
  * land in the projection, never the source family), and every node created
18
18
  * under the family carries the projection computed as its firewall. */
@@ -34,6 +34,16 @@ export interface StoreNextFamily {
34
34
  * landing under an active override. Dead members prune lazily at each
35
35
  * landing (retainingTransition). */
36
36
  rt?: Set<any>;
37
+ /** Flight-owned transaction (#3146): declared when a truth-flight
38
+ * registers (the ask's transaction — created by the flight's own pending
39
+ * throw when none was ambient, the causing write's when one was), renewed
40
+ * per settle event once the previous reveal committed. Bare optimistic
41
+ * writes and landings route into it BY DECLARATION; the transitionBlocked
42
+ * store-half checks it for ownership instead of reconstructing it from
43
+ * `_optimisticStores` membership. null = no flight declared one (sync
44
+ * derive, or a loading-window flight — the loading rail is
45
+ * transaction-invisible, #2933). */
46
+ ft?: any;
37
47
  /** Normalized row-key fn (same resolution as the projection channels:
38
48
  * `options.key`, "id" default, null = unkeyed). The staged-landing walk
39
49
  * reads it: key-matched rows keep their proxy identity across a fold. */
@@ -43,40 +53,6 @@ export interface StoreNextFamily {
43
53
  node: Computed<any> | null;
44
54
  shallow?: boolean;
45
55
  }
46
- /** Write-side patch-channel state (stage 2), grouped off the target's named
47
- * fields — see the shape rule on `StoreNextTarget.pc`. One literal shape,
48
- * allocated by `pcOf` on first use. */
49
- export interface PatchChannel {
50
- /** Slot-patch hooks for shallow arrays — the reconcile walk emits
51
- * (i, next, prev) for key-aligned value-replaced slots through the patch
52
- * apply queue (records are raw, no per-record targets exist).
53
- * MULTI-CONSUMER (external audit): one array can drive several lists. */
54
- sp: {
55
- fn: (index: number, next: any, prev: any) => void;
56
- owner: Owner | null;
57
- }[] | null;
58
- /** Patch-channel consumers (next/patch.ts): per-record compiled patch
59
- * entries, multi-consumer. null when unpatched (the common case). */
60
- p: object[] | null;
61
- /** Same-batch coalescing stamp (re-audit 2/3): the container array this
62
- * channel last pushed a non-forced SELF entry into, plus that entry. A
63
- * later same-batch emission UPDATES the queued entry's `next` in place
64
- * (latest state wins — adoption REPLACES the captured object, so dropping
65
- * the later emission would apply stale state) while `prev` stays the
66
- * batch's earliest. The drain clears both stamps so a quiet record
67
- * retains nothing from its last batch. */
68
- qa: unknown;
69
- qe: unknown;
70
- /** Row-ops consumers (next/patch.ts, PR-B): structural list ops —
71
- * (nextRows, { prefix, sources, removed }) at apply timing. */
72
- ro: object[] | null;
73
- /** Keys written through the traps since the last fold commit. Bounds the
74
- * setter notify/hold-check to O(written) instead of O(subscribed nodes) —
75
- * a record with thousands of per-key subscriptions (selection maps) would
76
- * otherwise pay a full node scan on every write. null = no trap writes
77
- * this batch (bulk paths fall back to the full scan). */
78
- wk: Set<PropertyKey> | null;
79
- }
80
56
  export interface StoreNextTarget {
81
57
  /** Committed backing: source object (shared) or owned clone. */
82
58
  v: Record<PropertyKey, any>;
@@ -92,15 +68,19 @@ export interface StoreNextTarget {
92
68
  h: Record<PropertyKey, Signal<boolean>> | null;
93
69
  /** Lazy key-set node: membership/iteration/$TRACK subscriptions (§6). */
94
70
  k: Signal<number> | null;
95
- /** Patch-channel extension (lazily allocated on first use): groups the
96
- * write-side stage-2 fields so they never widen the TARGET's own named
97
- * field count. LOAD-BEARING SHAPE RULE: array proxy targets carry their
98
- * fields as named properties on a real array, and V8 normalizes an array
99
- * to dictionary properties as the named count grows (empirically at
100
- * counts ≡ 0 mod 3 from 18 up on V8 13.x) — every trap field read then
101
- * becomes a hash lookup (~15% uibench, tree suites worst). New
102
- * patch-channel state MUST go inside this object, not on the target. */
103
- pc: PatchChannel | null;
71
+ /** Keys written through the traps since the last fold commit. Bounds the
72
+ * setter notify/hold-check to O(written) instead of O(subscribed nodes) —
73
+ * a record with thousands of per-key subscriptions (selection maps) would
74
+ * otherwise pay a full node scan on every write. null = no trap writes
75
+ * this batch (bulk paths fall back to the full scan); WK_ALL = bound
76
+ * unusable (array length write). LOAD-BEARING SHAPE RULE: array proxy
77
+ * targets carry their fields as named properties on a real array, and V8
78
+ * normalizes an array to dictionary properties as the named count grows
79
+ * (empirically at counts ≡ 0 mod 3 from 18 up on V8 13.x) — every trap
80
+ * field read then becomes a hash lookup (~15% uibench, tree suites
81
+ * worst). Future write-side state MUST ride an extension object, not new
82
+ * named fields. */
83
+ wk: Set<PropertyKey> | null;
104
84
  /** Lazy deep-witness node: `deep()` subscribes ONE node per record instead
105
85
  * of one per path; write paths bump it only when it exists. Separate from
106
86
  * `k` so $TRACK/mapArray never rerun on leaf value changes (R9). */
@@ -120,8 +100,12 @@ export interface StoreNextTarget {
120
100
  /** Accessor scan performed (scan-once on first trap read; adopted data is
121
101
  * not rescanned — legacy-parity behavior). */
122
102
  sc: boolean;
123
- /** Backing was swapped by adoption this batch (fold diff-notifies it). */
124
- adopted: boolean;
103
+ /** Adoption diff base, non-null when the backing was swapped by adoption
104
+ * this batch: the view the nodes were LAST TOLD — the pre-batch committed
105
+ * backing, or the draft's pending backing when a draft preceded the
106
+ * adoption (its setter-exit notifications already moved the nodes, #3296).
107
+ * The deferred fold diffs incoming against this, never against committed. */
108
+ ab: Record<PropertyKey, any> | null;
125
109
  /** Pending backing is a prototype-chain OVERLAY of the committed backing
126
110
  * (`Object.create(v)` — own keys are this batch's writes, everything else
127
111
  * reads through). O(written) per flush instead of O(container) clones
@@ -1,7 +1,7 @@
1
1
  import { type Signal } from "../core/index.cjs";
2
2
  import type { Refreshable } from "../core/index.cjs";
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>;
3
+ /** A reactive view of a store's value. Update it through the paired `StoreSetter`. */
4
+ export type Store<T> = T;
5
5
  /**
6
6
  * A store setter. The callback receives a writable **draft** of the store.
7
7
  *
@@ -14,25 +14,30 @@ export type Store<T> = Readonly<T>;
14
14
  *
15
15
  * The setter does **not** perform keyed reconciliation. If you need surviving
16
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`.
17
+ * projection form — `createStore(fn, seed, { key })` or
18
+ * `createProjection(fn, seed, { key })` — whose derive function reconciles
19
+ * its return by `options.key`.
19
20
  */
20
21
  export type StoreSetter<T> = (fn: (state: T) => T | void) => void;
21
- /** Tuple returned by the plain `createStore(initialValue)` form. */
22
+ /** Tuple returned by the plain `createStore(initialValue, options?)` form. */
22
23
  export type StoreReturn<T> = [get: Store<T>, set: StoreSetter<T>];
23
24
  /** Tuple returned by the derived `createStore(fn, seed, options?)` form. */
24
25
  export type ProjectionStoreReturn<T> = [get: Refreshable<Store<T>>, set: StoreSetter<T>];
25
- /** Base options for store primitives. */
26
+ /** Options shared by all store primitives. */
26
27
  export interface StoreOptions {
27
28
  /** Debug name (dev mode only) */
28
29
  name?: string;
30
+ /** Single-layer store: root keys reactive, values raw records replaced by reference */
31
+ shallow?: boolean;
29
32
  }
30
- /** Options for derived/projected stores created with `createStore(fn)`, `createProjection`, or `createOptimisticStore(fn)`. */
33
+ /**
34
+ * Options for derived/projected stores created with
35
+ * `createStore(fn, seed, options?)`, `createProjection(fn, seed, options?)`,
36
+ * or `createOptimisticStore(fn, seed, options?)`.
37
+ */
31
38
  export interface ProjectionOptions extends StoreOptions {
32
39
  /** Key property name or function for reconciliation identity; `null` merges positionally */
33
40
  key?: string | ((item: NonNullable<any>) => any) | null;
34
- /** Single-layer store: root keys reactive, values raw records replaced by reference */
35
- shallow?: boolean;
36
41
  /**
37
42
  * Treat the seed as commit #0: the store is born committed with the seed's
38
43
  * contents, shown until the derive's first real answer lands. While that
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solidjs/signals",
3
- "version": "2.0.0-rc.5",
3
+ "version": "2.0.0-rc.7",
4
4
  "description": "Solid's reactive primitives: signals, memos, effects, stores, and async-aware computations.",
5
5
  "author": "Ryan Carniato",
6
6
  "license": "MIT",
@@ -34,6 +34,7 @@
34
34
  },
35
35
  "require": {
36
36
  "types": "./dist/types-cjs/index.d.cts",
37
+ "development": "./dist/node.dev.cjs",
37
38
  "default": "./dist/node.cjs"
38
39
  }
39
40
  },
@@ -41,7 +42,7 @@
41
42
  },
42
43
  "scripts": {
43
44
  "build": "npm-run-all -nl build:* && pnpm types",
44
- "build:clean": "rimraf dist/dev dist/prod dist/node dist/dev.js dist/prod.js dist/node.cjs",
45
+ "build:clean": "rimraf dist/dev dist/prod dist/node dist/dev.js dist/prod.js dist/node.cjs dist/node.dev.cjs",
45
46
  "build:js": "rollup -c && node ./scripts/mangle-props.mjs dist/prod dist/node.cjs && node ./scripts/check-pure.mjs dist/prod",
46
47
  "types": "tsc -p tsconfig.build.json && node ../../scripts/sync-dual-types.mjs ./dist/types ./dist/types-cjs",
47
48
  "test": "vitest run",
@@ -1,13 +0,0 @@
1
- let patchHooks = null;
2
-
3
- let rowHooks = null;
4
-
5
- function installPatchHooks(o) {
6
- patchHooks = o;
7
- }
8
-
9
- function installRowHooks(o) {
10
- rowHooks = o;
11
- }
12
-
13
- export { installPatchHooks, installRowHooks, patchHooks, rowHooks };