@solidjs/signals 2.0.0-rc.13 → 2.0.0-rc.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dev-shared.js +2059 -3768
- package/dist/dev.attribution.js +237 -101
- package/dist/dev.js +7466 -8497
- package/dist/observe/affects.js +128 -104
- package/dist/observe/boundaries.js +492 -665
- package/dist/observe/core/action.js +63 -66
- package/dist/observe/core/async.js +243 -379
- package/dist/observe/core/attribution-queries.js +1 -1
- package/dist/observe/core/attribution.js +394 -253
- package/dist/observe/core/constants.js +120 -187
- package/dist/observe/core/context.js +3 -3
- package/dist/observe/core/core.js +874 -1440
- package/dist/observe/core/dev.js +3 -3
- package/dist/observe/core/effect.js +73 -84
- package/dist/observe/core/external.js +5 -5
- package/dist/observe/core/graph.js +62 -71
- package/dist/observe/core/heap.js +75 -98
- package/dist/observe/core/invariants.js +1 -34
- package/dist/observe/core/lanes.js +750 -181
- package/dist/observe/core/owner.js +80 -101
- package/dist/observe/core/scheduler.js +719 -1356
- package/dist/observe/core/verdict.js +314 -621
- package/dist/observe/flatten.js +79 -0
- package/dist/observe/index.js +15 -13
- package/dist/observe/map.js +232 -235
- package/dist/observe/reveal.js +212 -0
- package/dist/observe/signals.js +144 -216
- package/dist/observe/store/affects.js +142 -0
- package/dist/observe/store/hooks.js +13 -0
- package/dist/observe/store/index.js +27 -24
- package/dist/observe/store/optimistic.js +571 -0
- package/dist/observe/store/projection.js +308 -0
- package/dist/observe/store/reconcile.js +259 -0
- package/dist/observe/store/store.js +1988 -277
- package/dist/observe/store/storePath.js +1 -1
- package/dist/{prod/store/next → observe/store}/target.js +17 -18
- package/dist/observe/store/types.js +73 -0
- package/dist/observe/store/utils.js +1 -13
- package/dist/prod/affects.js +130 -106
- package/dist/prod/boundaries.js +476 -654
- package/dist/prod/core/action.js +71 -74
- package/dist/prod/core/async.js +306 -444
- package/dist/prod/core/constants.js +117 -186
- package/dist/prod/core/context.js +3 -3
- package/dist/prod/core/core.js +888 -1462
- package/dist/prod/core/effect.js +88 -99
- package/dist/prod/core/external.js +5 -5
- package/dist/prod/core/graph.js +62 -71
- package/dist/prod/core/heap.js +75 -98
- package/dist/prod/core/invariants.js +1 -32
- package/dist/prod/core/lanes.js +712 -181
- package/dist/prod/core/owner.js +75 -96
- package/dist/prod/core/scheduler.js +686 -1335
- package/dist/prod/core/verdict.js +309 -621
- package/dist/prod/flatten.js +77 -0
- package/dist/prod/index.js +15 -13
- package/dist/prod/map.js +142 -145
- package/dist/prod/reveal.js +212 -0
- package/dist/prod/signals.js +155 -227
- package/dist/prod/store/affects.js +142 -0
- package/dist/prod/store/hooks.js +13 -0
- package/dist/prod/store/index.js +26 -19
- package/dist/prod/store/optimistic.js +566 -0
- package/dist/prod/store/projection.js +301 -0
- package/dist/prod/store/reconcile.js +259 -0
- package/dist/prod/store/store.js +1883 -272
- package/dist/prod/store/storePath.js +1 -1
- package/dist/{observe/store/next → prod/store}/target.js +13 -17
- package/dist/prod/store/types.js +73 -0
- package/dist/prod/store/utils.js +1 -11
- package/dist/types/affects.d.ts +11 -30
- package/dist/types/boundaries.d.ts +66 -176
- package/dist/types/carved.d.ts +1 -0
- package/dist/types/core/action.d.ts +5 -6
- package/dist/types/core/async.d.ts +10 -5
- package/dist/types/core/attribution-hooks.d.ts +20 -1
- package/dist/types/core/attribution.d.ts +26 -11
- package/dist/types/core/constants.d.ts +130 -180
- package/dist/types/core/core.d.ts +134 -264
- package/dist/types/core/dev.d.ts +2 -2
- package/dist/types/core/effect.d.ts +0 -7
- package/dist/types/core/graph.d.ts +7 -1
- package/dist/types/core/heap.d.ts +5 -7
- package/dist/types/core/index.d.ts +5 -5
- package/dist/types/core/invariants.d.ts +0 -29
- package/dist/types/core/lanes.d.ts +74 -86
- package/dist/types/core/owner.d.ts +3 -3
- package/dist/types/core/scheduler.d.ts +255 -331
- package/dist/types/core/types.d.ts +45 -85
- package/dist/types/core/verdict.d.ts +3 -0
- package/dist/types/flatten.d.ts +8 -0
- package/dist/types/index.d.ts +6 -4
- package/dist/types/reveal.d.ts +19 -0
- package/dist/types/signals.d.ts +35 -91
- package/dist/types/store/affects.d.ts +12 -0
- package/dist/types/store/hooks.d.ts +48 -0
- package/dist/types/store/index.d.ts +34 -15
- package/dist/types/store/optimistic.d.ts +23 -0
- package/dist/types/store/projection.d.ts +18 -0
- package/dist/types/store/reconcile.d.ts +3 -0
- package/dist/types/store/store.d.ts +132 -145
- package/dist/types/store/storePath.d.ts +1 -1
- package/dist/types/store/target.d.ts +151 -0
- package/dist/types/store/types.d.ts +84 -0
- package/package.json +1 -1
- package/dist/observe/core/optimistic.js +0 -669
- package/dist/observe/store/next/optimistic.js +0 -717
- package/dist/observe/store/next/projection.js +0 -266
- package/dist/observe/store/next/reconcile.js +0 -375
- package/dist/observe/store/next/store.js +0 -2608
- package/dist/prod/core/optimistic.js +0 -658
- package/dist/prod/store/next/optimistic.js +0 -710
- package/dist/prod/store/next/projection.js +0 -257
- package/dist/prod/store/next/reconcile.js +0 -373
- package/dist/prod/store/next/store.js +0 -2484
- package/dist/types/core/optimistic.d.ts +0 -6
- package/dist/types/store/next/optimistic.d.ts +0 -25
- package/dist/types/store/next/projection.d.ts +0 -27
- package/dist/types/store/next/reconcile.d.ts +0 -10
- package/dist/types/store/next/store.d.ts +0 -145
- package/dist/types/store/next/target.d.ts +0 -196
|
@@ -1,147 +1,134 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type
|
|
3
|
-
|
|
4
|
-
export
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
*
|
|
32
|
-
*/
|
|
33
|
-
|
|
34
|
-
/** Single-layer store: root keys reactive, values raw records replaced by reference */
|
|
35
|
-
shallow?: boolean;
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Options for derived/projected stores created with
|
|
39
|
-
* `createStore(fn, seed, options?)`, `createProjection(fn, seed, options?)`,
|
|
40
|
-
* or `createOptimisticStore(fn, seed, options?)`.
|
|
41
|
-
*/
|
|
42
|
-
export interface ProjectionOptions extends StoreOptions {
|
|
43
|
-
/** Key property name or function for reconciliation identity; `null` merges positionally */
|
|
44
|
-
key?: string | ((item: NonNullable<any>) => any) | null;
|
|
45
|
-
/**
|
|
46
|
-
* Treat the seed as commit #0: the store is born committed with the seed's
|
|
47
|
-
* contents, shown until the derive's first real answer lands. While that
|
|
48
|
-
* first answer is in flight, reads serve the seed everywhere — nothing
|
|
49
|
-
* suspends to a `<Loading>` boundary, no transition is held, and
|
|
50
|
-
* `isPending` stays false (the seed answers by declaration; first-load
|
|
51
|
-
* affordances belong to the data, e.g. a `skeleton: true` field in the
|
|
52
|
-
* seed). Once the first answer lands (reconciled into the seed), refetches
|
|
53
|
-
* use normal pending semantics with `isPending` true.
|
|
54
|
-
*
|
|
55
|
-
* The store equivalent of `MemoOptions.loadingValue`; the seed already
|
|
56
|
-
* carries the placeholder shape, so this is just the opt-in.
|
|
57
|
-
*/
|
|
58
|
-
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);
|
|
59
34
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
export
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
*/
|
|
94
|
-
export declare
|
|
95
|
-
|
|
96
|
-
export declare function
|
|
97
|
-
|
|
98
|
-
export declare function
|
|
99
|
-
export declare function
|
|
100
|
-
|
|
101
|
-
export declare function
|
|
102
|
-
export declare function
|
|
103
|
-
/**
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
/** Next-store optimistic view for the declaration walk (optimistic rows
|
|
117
|
-
* pushed before the declaration are in motion too — legacy reads its write
|
|
118
|
-
* overlays; next composes armed-node overrides). */
|
|
119
|
-
export declare let nextOptimisticViewResolver: ((target: any, raw: any) => any) | null;
|
|
120
|
-
export declare function setNextOptimisticViewResolver(fn: (target: any, raw: any) => any): void;
|
|
121
|
-
/** @internal birth inheritance for nodes created inside a live mark window —
|
|
122
|
-
* exported for the rewrite's node factories. */
|
|
123
|
-
export declare function affectsScopesLive(): boolean;
|
|
124
|
-
/**
|
|
125
|
-
* Witness live mark coverage of a record into the active isPending() probe.
|
|
126
|
-
* Tracked reads don't need this — they go through real signal nodes, which
|
|
127
|
-
* carry marks directly (declaration walk or birth inheritance). This covers
|
|
128
|
-
* UNTRACKED probes reading through records whose nodes never materialized
|
|
129
|
-
* (no observer ever subscribed, so no node exists to carry the mark).
|
|
130
|
-
* Callers guard on `pendingCheckActive`, so plain reads never pay for this.
|
|
131
|
-
*
|
|
132
|
-
* @internal
|
|
133
|
-
*/
|
|
134
|
-
export declare function witnessAffectsMark(target: StoreNode, property?: PropertyKey): void;
|
|
135
|
-
/**
|
|
136
|
-
* Resolves the store nodes an `affects()` declaration marks: with a `key`,
|
|
137
|
-
* the named slot's leaf node (upserted so the mark has an addressable
|
|
138
|
-
* carrier); without, the record's $AFFECTS carrier plus every LIVE node in
|
|
139
|
-
* its subtree (the edges existing readers subscribed through), with the
|
|
140
|
-
* subtree's identities snapshotted into the mark's scope so nodes created
|
|
141
|
-
* during the window — and untracked probes over captured proxies — resolve
|
|
142
|
-
* 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): 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.
|
|
143
91
|
*
|
|
144
|
-
*
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
92
|
+
* The container is told of an arrangement change when it has structural
|
|
93
|
+
* subscribers OR carries an arrangement guess (S4): for a guessed
|
|
94
|
+
* container the write is the landing that judges the guess (Q-D, plan
|
|
95
|
+
* sec. 39 — confirm, supersede, or hold beneath), not a subscriber
|
|
96
|
+
* notification, and a landing whose truth changed no guessed key's value
|
|
97
|
+
* or presence (a newer question's rows beneath an optimistic push) still
|
|
98
|
+
* answers the arrangement — before, only the presence write reached the
|
|
99
|
+
* lane, by accident of being unconditional. */
|
|
100
|
+
export declare function notifyFoldTail(t: StoreTarget, old: Record<PropertyKey, any>, neu: Record<PropertyKey, any>): void;
|
|
101
|
+
/** An adoption's notifications: every node of the target, diffed `old` →
|
|
102
|
+
* `neu` (value nodes by key, presence by `in`, the container by
|
|
103
|
+
* membership, the deep witness by identity). */
|
|
104
|
+
export declare function notifyFold(t: StoreTarget, old: Record<PropertyKey, any>, neu: Record<PropertyKey, any>): void;
|
|
105
|
+
/** The committed backing: the container node's committed value while a
|
|
106
|
+
* batch is staged on it (an adoption swaps `t.v` eagerly — INTERNALS §3,
|
|
107
|
+
* "adoption is eager by contract" — and the node keeps the frame committed
|
|
108
|
+
* readers under a hold still see), `t.v` otherwise. */
|
|
109
|
+
export declare function committed(t: StoreTarget): Record<PropertyKey, any>;
|
|
110
|
+
/** The same row at a slot, as the adoption pairs rows (reconcile.ts): two
|
|
111
|
+
* objects whose keys agree — positionally for an unkeyed family. */
|
|
112
|
+
export declare function sameRow(pv: any, nv: any, keyFn: ((item: any) => any) | null): boolean;
|
|
113
|
+
/** A chained backing's child (§7b): a raw the inner family owns, or holds
|
|
114
|
+
* at this key, is served as the inner store's wrapper — never a fresh
|
|
115
|
+
* raw-keyed one — so the chained targets are the same objects across
|
|
116
|
+
* settled and pending views. */
|
|
117
|
+
export declare function resolveChainedRaw(target: StoreTarget, key: PropertyKey, v: object): any;
|
|
118
|
+
export declare function storeSetter<T>(proxy: T, fn: (draft: T) => T | void, guard?: boolean): void;
|
|
119
|
+
export declare function createStore<T extends Record<PropertyKey, any>>(initialValue: T, options?: StoreOptions): [T, SetStoreFunction<T>];
|
|
120
|
+
/** True when `proxy` is a SHALLOW store (children served verbatim, slots
|
|
121
|
+
* replaced by reference — #2932). The list driver uses this to choose the
|
|
122
|
+
* slot-patch channel (collected row bodies) over per-record registration. */
|
|
123
|
+
export declare function storeIsShallow(proxy: any): boolean;
|
|
124
|
+
/** True when `proxy` belongs to a projection family (S3). */
|
|
125
|
+
export declare function storeHasFamily(proxy: any): boolean;
|
|
126
|
+
/** True when `proxy` belongs to an OPTIMISTIC family (S4). */
|
|
127
|
+
export declare function storeHasOptimisticFamily(proxy: any): boolean;
|
|
128
|
+
/** Tracking snapshot: subscribes every reachable record's container and deep
|
|
129
|
+
* witness (one node per record, not one per path), then snapshots. */
|
|
130
|
+
export declare function deep<T>(value: T): T;
|
|
131
|
+
/** Non-tracking snapshot: source identity for unowned subtrees (zero copy),
|
|
132
|
+
* a copy for owned ones (they are by definition modified relative to the
|
|
133
|
+
* source). Sees the pending backing (R27). */
|
|
134
|
+
export declare function snapshot<T>(value: T): T;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type NotWrappable } from "./
|
|
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,151 @@
|
|
|
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
|
+
/** Normalized row-key fn (`options.key`, "id" default, null = unkeyed). */
|
|
29
|
+
key?: ((item: any) => any) | null;
|
|
30
|
+
map: WeakMap<object, StoreTarget>;
|
|
31
|
+
/** The projection computed — the firewall. Assigned after creation. */
|
|
32
|
+
node: Computed<any> | null;
|
|
33
|
+
/** Targets of the family that carry nodes: the derive's pending wakes
|
|
34
|
+
* their readers (A9) — the family's enumerable index, in place of a
|
|
35
|
+
* per-leaf chain; a target leaves it with its last node. */
|
|
36
|
+
live: Set<StoreTarget>;
|
|
37
|
+
shallow?: boolean;
|
|
38
|
+
/** Derive run counter (proj R37): the run whose draft is live. */
|
|
39
|
+
run?: number;
|
|
40
|
+
/** The derive's pending reached the leaves' readers (`wakeFamily`) and no
|
|
41
|
+
* landing has settled them yet: the next commit walks the family
|
|
42
|
+
* (`settleFamily`). A sync commit with no wake behind it walks nothing. */
|
|
43
|
+
woke?: boolean;
|
|
44
|
+
}
|
|
45
|
+
export interface StoreTarget {
|
|
46
|
+
/** Committed backing: source object (shared) or owned clone. */
|
|
47
|
+
v: Record<PropertyKey, any>;
|
|
48
|
+
/** Pending backing for the current batch (null when settled) — the same
|
|
49
|
+
* object the container node stages (`k._pendingValue`). */
|
|
50
|
+
pb: Record<PropertyKey, any> | null;
|
|
51
|
+
/** cached: committed backing is another store's proxy (§7b chained). */
|
|
52
|
+
ch: boolean;
|
|
53
|
+
/** live value-node count (deleted-key sweep fast-out in the fused walk). */
|
|
54
|
+
nc: number;
|
|
55
|
+
/** Lazy per-property subscription nodes (slot nodes). */
|
|
56
|
+
n: Record<PropertyKey, Signal<any>> | null;
|
|
57
|
+
/** Lazy per-key presence nodes (`in` tracks presence, not value — R13). */
|
|
58
|
+
h: Record<PropertyKey, Signal<boolean>> | null;
|
|
59
|
+
/** Lazy CONTAINER node: membership/iteration/`$TRACK`/`length`
|
|
60
|
+
* subscriptions (§6) and the backing's staging home (plan sec. 31.3). */
|
|
61
|
+
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
|
|
69
|
+
* normalizes an array to dictionary properties as the named count grows
|
|
70
|
+
* (empirically at counts ≡ 0 mod 3 from 18 up on V8 13.x) — every trap
|
|
71
|
+
* field read then becomes a hash lookup (~15% uibench, tree suites
|
|
72
|
+
* worst). Future write-side state MUST ride an extension object, not new
|
|
73
|
+
* named fields. */
|
|
74
|
+
wk: Set<PropertyKey> | null;
|
|
75
|
+
/** Lazy deep-witness node: `deep()` subscribes ONE node per record instead
|
|
76
|
+
* of one per path; write paths bump it only when it exists. Separate from
|
|
77
|
+
* `k` so $TRACK/mapArray never rerun on leaf value changes (R9). */
|
|
78
|
+
dk: Signal<number> | null;
|
|
79
|
+
/** Parent target (path copying walks this at commit). */
|
|
80
|
+
u: StoreTarget | null;
|
|
81
|
+
/** Property key of this target in the parent's backing. */
|
|
82
|
+
pk: PropertyKey | null;
|
|
83
|
+
/** The proxy for this target (stable outward identity). */
|
|
84
|
+
px: any;
|
|
85
|
+
/** Sticky descendants flag (§6d). */
|
|
86
|
+
d: boolean;
|
|
87
|
+
/** Sticky accessors-seen flag: an own accessor property was observed on
|
|
88
|
+
* this target (first-read scan, defineProperty, or clone scan). Gates the
|
|
89
|
+
* fold diff's descriptor-safe path and the get trap's descriptor path. */
|
|
90
|
+
a: boolean;
|
|
91
|
+
/** Accessor scan grade: 0 = not yet scanned (adoption resets — adopted data
|
|
92
|
+
* is not rescanned until the next draft), 1 = scanned, 2 = scanned and
|
|
93
|
+
* PLAIN DATA — `Object.prototype` with every own key an enumerable data
|
|
94
|
+
* property. Grade 2 unlocks the spread clone (cloneRaw), bare-assignment
|
|
95
|
+
* overlay writes and flatten (#3360); a non-plain defineProperty through
|
|
96
|
+
* the draft downgrades it to 1. */
|
|
97
|
+
sc: 0 | 1 | 2;
|
|
98
|
+
/** Own-key count: exact at scan, then bumped by set-trap writes of keys new
|
|
99
|
+
* to the container (never decremented — an estimate for the overlay/clone
|
|
100
|
+
* choice only, #3360). */
|
|
101
|
+
kc: number;
|
|
102
|
+
/** Pending backing is a prototype-chain OVERLAY of the committed backing
|
|
103
|
+
* (`Object.create(v)` — own keys are this batch's writes, everything else
|
|
104
|
+
* reads through). O(written) per flush instead of O(container) clones
|
|
105
|
+
* (#3044); commit flattens own keys onto an owned committed backing in
|
|
106
|
+
* place. Plain-data non-array containers qualify; chained backings and
|
|
107
|
+
* accessor containers keep the descriptor clone. `materializePB`
|
|
108
|
+
* downgrades to the clone path when a consumer needs a real container
|
|
109
|
+
* (draft escape). */
|
|
110
|
+
ovl: boolean;
|
|
111
|
+
/** Keys deleted in the overlay window (a prototype overlay cannot shadow
|
|
112
|
+
* a delete); null when none. */
|
|
113
|
+
del: Set<PropertyKey> | null;
|
|
114
|
+
/** Projection family, null for plain stores (§7b). */
|
|
115
|
+
fam: StoreFamily | null;
|
|
116
|
+
/** Shallow store root (values served raw). */
|
|
117
|
+
s: boolean;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Ownership stamp (#3360): every backing the store ALLOCATES (CoW clones,
|
|
121
|
+
* privatized committed backings) carries its owning target under this
|
|
122
|
+
* enumerable symbol. One property write replaces the two weak-collection
|
|
123
|
+
* registrations (ownership set + raw→target map) a fresh object used to pay
|
|
124
|
+
* per draft — V8's identity-hash + ephemeron cost dominated the one-key
|
|
125
|
+
* write floor. Enumerable so a spread copy (the plain-data clone path) stays
|
|
126
|
+
* on the fast path and carries the stamp along.
|
|
127
|
+
*
|
|
128
|
+
* Owned backings are never user-reachable (`snapshot` copies them, the traps
|
|
129
|
+
* hide the key), so every raw key walk in the store must skip `$OWNER`, and
|
|
130
|
+
* ownership is answered by `isOwned` — a user object never carries it.
|
|
131
|
+
* Overlay drafts (`Object.create(v)` over an owned `v`) inherit the stamp.
|
|
132
|
+
*/
|
|
133
|
+
export declare const $OWNER: unique symbol;
|
|
134
|
+
/** raw → target for plain (family-less) stores. Family stores use their own
|
|
135
|
+
* map so one raw can wrap once per family (§7b). */
|
|
136
|
+
export declare const storeLookup: WeakMap<object, StoreTarget>;
|
|
137
|
+
export declare function setLookup(raw: object, t: StoreTarget): void;
|
|
138
|
+
export declare function isOwned(raw: object): boolean;
|
|
139
|
+
/** The target wrapping `raw` in `fam` (or the plain lookup). An owned raw
|
|
140
|
+
* answers from its stamp; a user raw from the map. */
|
|
141
|
+
export declare function lookupTarget(raw: object, fam: StoreFamily | null): StoreTarget | undefined;
|
|
142
|
+
/** Test-tier oracle (INTERNALS §5): no write path ever mutates a
|
|
143
|
+
* user-provided (non-owned) object. */
|
|
144
|
+
export declare const ingestedRaw: WeakSet<object> | null;
|
|
145
|
+
export declare function devAssertNeverUserMutation(target: object): void;
|
|
146
|
+
/** Sticky descendants flag up the parent chain (§6d): adoption descends
|
|
147
|
+
* into a changed child pair only where a target with nodes exists below. */
|
|
148
|
+
export declare function markDescendants(target: StoreTarget): void;
|
|
149
|
+
/** Observe tier: the owner in scope at `createStore` (attribution names and
|
|
150
|
+
* owner paths); the `_owner` write never reaches the proxy. */
|
|
151
|
+
export declare const storeOwners: WeakMap<StoreTarget, Owner | null> | null;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Store — public types, brand symbols, wrappability and raw marking. Shared
|
|
3
|
+
* by every store module; carries no reactive machinery of its own.
|
|
4
|
+
*/
|
|
5
|
+
import type { Refreshable } from "../core/index.js";
|
|
6
|
+
/** A reactive view of a store's value. Update it through the paired `StoreSetter`. */
|
|
7
|
+
export type Store<T> = T;
|
|
8
|
+
/**
|
|
9
|
+
* A store setter. The callback receives a writable **draft** of the store.
|
|
10
|
+
*
|
|
11
|
+
* - **Mutate in place (canonical):** `s.foo = 1`, `s.list.push(x)`,
|
|
12
|
+
* `s.list.splice(i, 1)`. This is the default form for most updates.
|
|
13
|
+
* - **Return a new value:** for shapes where mutation is awkward, most
|
|
14
|
+
* commonly removing items (`s => s.list.filter(...)`). Arrays are replaced
|
|
15
|
+
* by index (length adjusted); objects are shallow-diffed at the top level
|
|
16
|
+
* (keys present in the returned value are written, missing keys deleted).
|
|
17
|
+
*
|
|
18
|
+
* The setter does **not** perform keyed reconciliation. If you need surviving
|
|
19
|
+
* items to keep their store identity across full-array replacement, use the
|
|
20
|
+
* projection form — `createStore(fn, seed, { key })` or
|
|
21
|
+
* `createProjection(fn, seed, { key })` — whose derive function reconciles
|
|
22
|
+
* its return by `options.key`.
|
|
23
|
+
*/
|
|
24
|
+
export type StoreSetter<T> = (fn: (state: T) => T | void) => void;
|
|
25
|
+
/** Tuple returned by the plain `createStore(initialValue, options?)` form. */
|
|
26
|
+
export type StoreReturn<T> = [get: Store<T>, set: StoreSetter<T>];
|
|
27
|
+
/** Tuple returned by the derived `createStore(fn, seed, options?)` form. */
|
|
28
|
+
export type ProjectionStoreReturn<T> = [get: Refreshable<Store<T>>, set: StoreSetter<T>];
|
|
29
|
+
/** Options shared by all store primitives. */
|
|
30
|
+
export interface StoreOptions {
|
|
31
|
+
/**
|
|
32
|
+
* Debug name (dev and observe builds). Property nodes are labelled
|
|
33
|
+
* `<name>.<key>` in attribution output (`todos.title`); a derived store's
|
|
34
|
+
* projection node carries the name itself.
|
|
35
|
+
*/
|
|
36
|
+
name?: string;
|
|
37
|
+
/** Single-layer store: root keys reactive, values raw records replaced by reference */
|
|
38
|
+
shallow?: boolean;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Options for derived/projected stores created with
|
|
42
|
+
* `createStore(fn, seed, options?)`, `createProjection(fn, seed, options?)`,
|
|
43
|
+
* or `createOptimisticStore(fn, seed, options?)`.
|
|
44
|
+
*/
|
|
45
|
+
export interface ProjectionOptions extends StoreOptions {
|
|
46
|
+
/** Key property name or function for reconciliation identity; `null` merges positionally */
|
|
47
|
+
key?: string | ((item: NonNullable<any>) => any) | null;
|
|
48
|
+
/**
|
|
49
|
+
* Treat the seed as commit #0: the store is born committed with the seed's
|
|
50
|
+
* contents, shown until the derive's first real answer lands. While that
|
|
51
|
+
* first answer is in flight, reads serve the seed everywhere — nothing
|
|
52
|
+
* suspends to a `<Loading>` boundary, no transition is held, and
|
|
53
|
+
* `isPending` stays false (the seed answers by declaration; first-load
|
|
54
|
+
* affordances belong to the data, e.g. a `skeleton: true` field in the
|
|
55
|
+
* seed). Once the first answer lands (reconciled into the seed), refetches
|
|
56
|
+
* use normal pending semantics with `isPending` true.
|
|
57
|
+
*
|
|
58
|
+
* The store equivalent of `MemoOptions.loadingValue`; the seed already
|
|
59
|
+
* carries the placeholder shape, so this is just the opt-in.
|
|
60
|
+
*/
|
|
61
|
+
seedLoadingValue?: boolean;
|
|
62
|
+
}
|
|
63
|
+
export type NoFn<T> = T extends Function ? never : T;
|
|
64
|
+
/** Brand keys the proxy answers directly (never user data). */
|
|
65
|
+
export declare const $TRACK: unique symbol, $TARGET: unique symbol, $PROXY: unique symbol, $RECORD: unique symbol;
|
|
66
|
+
export declare namespace SolidStore {
|
|
67
|
+
interface Unwrappable {
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
export type NotWrappable = string | number | bigint | symbol | boolean | Function | null | undefined | SolidStore.Unwrappable[keyof SolidStore.Unwrappable];
|
|
71
|
+
export declare let rawValuesUsed: boolean;
|
|
72
|
+
export declare function isRawValue(value: any): boolean;
|
|
73
|
+
/** Mark a value so no store ever wraps it (sticky; it reads as a leaf). */
|
|
74
|
+
export declare function markRaw<T>(value: T): T;
|
|
75
|
+
/** A shallow store's ingested record: raw by contract (values served
|
|
76
|
+
* verbatim, slots replaced by reference). */
|
|
77
|
+
export declare function markRawOne(v: any): void;
|
|
78
|
+
export declare function markRawIngest(container: any): void;
|
|
79
|
+
/** Plain objects and arrays wrap; class instances, DOM nodes, frozen objects
|
|
80
|
+
* and markRaw'd values are leaves. Per-prototype verdict cached. */
|
|
81
|
+
export declare function isWrappable<T>(obj: T | NotWrappable): obj is T;
|
|
82
|
+
export declare function ownEnumerableKeys(o: object): (string | symbol)[];
|
|
83
|
+
export declare let writeOverride: boolean;
|
|
84
|
+
export declare function setWriteOverride(value: boolean): void;
|
package/package.json
CHANGED