@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.
Files changed (121) hide show
  1. package/dist/dev-shared.js +2059 -3768
  2. package/dist/dev.attribution.js +237 -101
  3. package/dist/dev.js +7466 -8497
  4. package/dist/observe/affects.js +128 -104
  5. package/dist/observe/boundaries.js +492 -665
  6. package/dist/observe/core/action.js +63 -66
  7. package/dist/observe/core/async.js +243 -379
  8. package/dist/observe/core/attribution-queries.js +1 -1
  9. package/dist/observe/core/attribution.js +394 -253
  10. package/dist/observe/core/constants.js +120 -187
  11. package/dist/observe/core/context.js +3 -3
  12. package/dist/observe/core/core.js +874 -1440
  13. package/dist/observe/core/dev.js +3 -3
  14. package/dist/observe/core/effect.js +73 -84
  15. package/dist/observe/core/external.js +5 -5
  16. package/dist/observe/core/graph.js +62 -71
  17. package/dist/observe/core/heap.js +75 -98
  18. package/dist/observe/core/invariants.js +1 -34
  19. package/dist/observe/core/lanes.js +750 -181
  20. package/dist/observe/core/owner.js +80 -101
  21. package/dist/observe/core/scheduler.js +719 -1356
  22. package/dist/observe/core/verdict.js +314 -621
  23. package/dist/observe/flatten.js +79 -0
  24. package/dist/observe/index.js +15 -13
  25. package/dist/observe/map.js +232 -235
  26. package/dist/observe/reveal.js +212 -0
  27. package/dist/observe/signals.js +144 -216
  28. package/dist/observe/store/affects.js +142 -0
  29. package/dist/observe/store/hooks.js +13 -0
  30. package/dist/observe/store/index.js +27 -24
  31. package/dist/observe/store/optimistic.js +571 -0
  32. package/dist/observe/store/projection.js +308 -0
  33. package/dist/observe/store/reconcile.js +259 -0
  34. package/dist/observe/store/store.js +1988 -277
  35. package/dist/observe/store/storePath.js +1 -1
  36. package/dist/{prod/store/next → observe/store}/target.js +17 -18
  37. package/dist/observe/store/types.js +73 -0
  38. package/dist/observe/store/utils.js +1 -13
  39. package/dist/prod/affects.js +130 -106
  40. package/dist/prod/boundaries.js +476 -654
  41. package/dist/prod/core/action.js +71 -74
  42. package/dist/prod/core/async.js +306 -444
  43. package/dist/prod/core/constants.js +117 -186
  44. package/dist/prod/core/context.js +3 -3
  45. package/dist/prod/core/core.js +888 -1462
  46. package/dist/prod/core/effect.js +88 -99
  47. package/dist/prod/core/external.js +5 -5
  48. package/dist/prod/core/graph.js +62 -71
  49. package/dist/prod/core/heap.js +75 -98
  50. package/dist/prod/core/invariants.js +1 -32
  51. package/dist/prod/core/lanes.js +712 -181
  52. package/dist/prod/core/owner.js +75 -96
  53. package/dist/prod/core/scheduler.js +686 -1335
  54. package/dist/prod/core/verdict.js +309 -621
  55. package/dist/prod/flatten.js +77 -0
  56. package/dist/prod/index.js +15 -13
  57. package/dist/prod/map.js +142 -145
  58. package/dist/prod/reveal.js +212 -0
  59. package/dist/prod/signals.js +155 -227
  60. package/dist/prod/store/affects.js +142 -0
  61. package/dist/prod/store/hooks.js +13 -0
  62. package/dist/prod/store/index.js +26 -19
  63. package/dist/prod/store/optimistic.js +566 -0
  64. package/dist/prod/store/projection.js +301 -0
  65. package/dist/prod/store/reconcile.js +259 -0
  66. package/dist/prod/store/store.js +1883 -272
  67. package/dist/prod/store/storePath.js +1 -1
  68. package/dist/{observe/store/next → prod/store}/target.js +13 -17
  69. package/dist/prod/store/types.js +73 -0
  70. package/dist/prod/store/utils.js +1 -11
  71. package/dist/types/affects.d.ts +11 -30
  72. package/dist/types/boundaries.d.ts +66 -176
  73. package/dist/types/carved.d.ts +1 -0
  74. package/dist/types/core/action.d.ts +5 -6
  75. package/dist/types/core/async.d.ts +10 -5
  76. package/dist/types/core/attribution-hooks.d.ts +20 -1
  77. package/dist/types/core/attribution.d.ts +26 -11
  78. package/dist/types/core/constants.d.ts +130 -180
  79. package/dist/types/core/core.d.ts +134 -264
  80. package/dist/types/core/dev.d.ts +2 -2
  81. package/dist/types/core/effect.d.ts +0 -7
  82. package/dist/types/core/graph.d.ts +7 -1
  83. package/dist/types/core/heap.d.ts +5 -7
  84. package/dist/types/core/index.d.ts +5 -5
  85. package/dist/types/core/invariants.d.ts +0 -29
  86. package/dist/types/core/lanes.d.ts +74 -86
  87. package/dist/types/core/owner.d.ts +3 -3
  88. package/dist/types/core/scheduler.d.ts +255 -331
  89. package/dist/types/core/types.d.ts +45 -85
  90. package/dist/types/core/verdict.d.ts +3 -0
  91. package/dist/types/flatten.d.ts +8 -0
  92. package/dist/types/index.d.ts +6 -4
  93. package/dist/types/reveal.d.ts +19 -0
  94. package/dist/types/signals.d.ts +35 -91
  95. package/dist/types/store/affects.d.ts +12 -0
  96. package/dist/types/store/hooks.d.ts +48 -0
  97. package/dist/types/store/index.d.ts +34 -15
  98. package/dist/types/store/optimistic.d.ts +23 -0
  99. package/dist/types/store/projection.d.ts +18 -0
  100. package/dist/types/store/reconcile.d.ts +3 -0
  101. package/dist/types/store/store.d.ts +132 -145
  102. package/dist/types/store/storePath.d.ts +1 -1
  103. package/dist/types/store/target.d.ts +151 -0
  104. package/dist/types/store/types.d.ts +84 -0
  105. package/package.json +1 -1
  106. package/dist/observe/core/optimistic.js +0 -669
  107. package/dist/observe/store/next/optimistic.js +0 -717
  108. package/dist/observe/store/next/projection.js +0 -266
  109. package/dist/observe/store/next/reconcile.js +0 -375
  110. package/dist/observe/store/next/store.js +0 -2608
  111. package/dist/prod/core/optimistic.js +0 -658
  112. package/dist/prod/store/next/optimistic.js +0 -710
  113. package/dist/prod/store/next/projection.js +0 -257
  114. package/dist/prod/store/next/reconcile.js +0 -373
  115. package/dist/prod/store/next/store.js +0 -2484
  116. package/dist/types/core/optimistic.d.ts +0 -6
  117. package/dist/types/store/next/optimistic.d.ts +0 -25
  118. package/dist/types/store/next/projection.d.ts +0 -27
  119. package/dist/types/store/next/reconcile.d.ts +0 -10
  120. package/dist/types/store/next/store.d.ts +0 -145
  121. package/dist/types/store/next/target.d.ts +0 -196
@@ -1,6 +1,5 @@
1
1
  import type { NOT_PENDING } from "./constants.js";
2
- import type { OptimisticLane } from "./lanes.js";
3
- import type { IQueue, Transition } from "./scheduler.js";
2
+ import type { Transaction } from "./scheduler.js";
4
3
  export interface Disposable {
5
4
  (): void;
6
5
  }
@@ -17,7 +16,6 @@ export interface Link {
17
16
  * scanning the dep list to answer membership (see `link()`).
18
17
  */
19
18
  _gen: number;
20
- _pendingObserver?: boolean;
21
19
  }
22
20
  export interface NodeOptions<T> {
23
21
  id?: string;
@@ -28,14 +26,21 @@ export interface NodeOptions<T> {
28
26
  /** Exclude this signal from snapshot capture (internal — not part of public API) */
29
27
  _noSnapshot?: boolean;
30
28
  /** Extra CONFIG_* bits OR'd into the node's config at creation (internal —
31
- * not part of public API). Used by resolve()/until() for
32
- * CONFIG_DIRECT_COMMIT / CONFIG_AUTHORITATIVE_READ, keeping the per-flag
33
- * option arms out of the core creation path. */
29
+ * not part of public API). Used by refresh() for CONFIG_FRESH_READ,
30
+ * keeping the per-flag option arms out of the core creation path. */
34
31
  _extraConfig?: number;
35
32
  /** Observe tiers: framework plumbing — no name, no owner-path segment, no
36
33
  * attribution records of its own; its children stay observed (internal —
37
34
  * not part of public API; see CONFIG_PLUMBING). */
38
35
  _plumbing?: boolean;
36
+ /** Observe tiers: a framework scope wide by construction — exempt from
37
+ * WIDE_SCOPE_DEPS, never from HUGE_FAN_IN (internal — not part of public
38
+ * API; see CONFIG_WIDE). */
39
+ _wide?: boolean;
40
+ /** Observe tiers: a framework async node that supersedes its own flights by
41
+ * design — exempt from ABANDONED_FLIGHTS (internal — not part of public
42
+ * API; see CONFIG_SUPERSEDES). */
43
+ _supersedes?: boolean;
39
44
  unobserved?: () => void;
40
45
  lazy?: boolean;
41
46
  sync?: boolean;
@@ -62,69 +67,47 @@ export interface NodeOptions<T> {
62
67
  * hot-path gates — a bit says "consult _x", never the reverse.
63
68
  */
64
69
  export interface NodeExtension {
65
- _overrideValue: unknown | typeof NOT_PENDING;
66
- /**
67
- * The transaction that owns the active override (stamped at optimistic
68
- * write, cleared at settle). Ownership must live on the node: a lane's
69
- * _transition is a scheduling affinity that a shared subscriber can merge
70
- * across transactions (#2912) — following it would let one action's settle
71
- * revert another action's live override. Node-level sibling of the store
72
- * layer's STORE_OPTIMISTIC_OWNERS stamps (#2899). `null` = ambient write.
73
- */
74
- _overrideOwner: Transition | null | undefined;
75
- /** `clock` at the active override's write. A sync recompute in the same
76
- * tick derives from inputs that predate the override and does not
77
- * supersede it (A18 supersession ordering, #3331). */
78
- _overrideTime: number;
79
- /** A28: the staged value the last flush left on a HELD node that has since
80
- * been rewritten (latest() keeps answering with it); NOT_PENDING otherwise. */
81
- _flushedStaged: unknown;
82
- /** Provenance of the active override's write: the scheduler's `origin` (the
83
- * asking action's invocation sequence; 0 = mainline). An arriving answer
84
- * whose flight an older action issued asked a question the override has
85
- * since changed: it holds to commit instead of superseding (A18
86
- * supersession provenance, #3331). */
87
- _overrideStamp: number;
88
- _optimisticLane: OptimisticLane | undefined;
89
- _pendingSignal: Signal<boolean> | undefined;
90
- _latestValueComputed: Computed<any> | undefined;
91
- _parentSource: Signal<any> | Computed<any> | undefined;
92
- /**
93
- * Live `affects()` marks on this node (refcount). Non-zero is declared
94
- * motion — see affects(); the count is the mark's only graph state.
95
- */
96
- _affectsCount: number;
97
70
  _inFlight: PromiseLike<any> | AsyncIterable<any> | null;
98
71
  /** Cancellation for the CURRENT iterator flight (#3122): closes the
99
72
  * iterator (`it.return()`), idempotent. Fired at the sites that release
100
- * `_inFlight` so a superseded stream stops at supersede time — its owner
101
- * cleanup registration may ride the zombie-disposal channel, which a held
102
- * transition defers until the SUPERSEDING flight settles. Null for plain
103
- * promise flights (no cancellation hook exists). */
73
+ * `_inFlight` so a superseded stream stops at supersede time. Null for
74
+ * plain promise flights (no cancellation hook exists). */
104
75
  _flightTeardown: (() => void) | null;
105
76
  _error: unknown;
106
77
  _blocked: boolean | undefined;
107
78
  _pendingSources: Set<Computed<any>> | undefined;
108
- _notifyStatus: ((status?: number, error?: any) => void) | undefined;
109
- /** Question-scoped re-ask classification of the current pending window
110
- * (see the former Computed._x?._reask doc): set by recompute from
111
- * REACTIVE_REASK, cleared on landing; meaningless while not pending. */
112
- _reask: boolean;
113
- _child: FirewallSignal<any> | null;
114
79
  _unobserved: (() => void) | undefined;
115
80
  _snapshotValue: any;
116
- /** Zombie staging (staged disposal): a recompute of an owner that HAS
117
- * children/disposal parks them here until the flush commits (or a
118
- * transition reverts). Childless nodes — the common case — never write
119
- * these. */
120
- _pendingDisposal: Disposable | Disposable[] | null;
81
+ /** L2 — the previous pass's frame, parked for this node's commit: its child
82
+ * chain and `_disposal` list, still reacting until the commit disposes
83
+ * them (or the owner's death does). */
121
84
  _pendingFirstChild: Owner | null;
122
- /** #3038: the firewall children that actually carry isPending()/latest()
123
- * companions. The post-recompute companion snap iterates THIS set —
124
- * O(companions asked for) — never the full `_child` chain (one entry per
125
- * materialized leaf). Populated at companion creation; entries live as
126
- * long as their companions (which are permanent once created). */
127
- _companionChildren: Set<FirewallSignal<any>> | undefined;
85
+ _pendingDisposal: Disposable | Disposable[] | null;
86
+ /** L2 — the transaction holding this node while CONFIG_HELD is set
87
+ * (`holdNode`); resolved through merges by `txOf`. */
88
+ _transaction: Transaction | null;
89
+ /** The node's current flight re-asks the same question (a `refresh()`,
90
+ * A19 exc. 2 / A24): verdict-quiet — `isPending` reads false for it —
91
+ * through its landing until the commit. */
92
+ _reask: boolean;
93
+ /** A28: the staging the last flush left on a held node, kept across an
94
+ * unflushed rewrite — what `latest()` and a tracked reader see until the
95
+ * flush that carries the rewrite; valid while `_flushedAt` is the current
96
+ * clock (that flush advances it). */
97
+ _flushed: unknown;
98
+ _flushedAt: number;
99
+ /** Provenance (A18, #3331): the question this node's guess or latest
100
+ * flight answers (`scheduler.question`); 0 when unstamped. */
101
+ _q: number;
102
+ /** Lanes (plan sec. 28) — the lane's value for this node while CONFIG_OVERRIDE is
103
+ * set: a written guess, or a lane pass's derivation. `NOT_PENDING` when
104
+ * none. The screen shows it once the lane has revealed (`_shown`); a
105
+ * direct read sees it throughout; the committed truth stays `_value`. */
106
+ _lane: unknown;
107
+ /** `affects()` marks live on this node (affects.ts): declared in-flight
108
+ * changes — `isPending` reads true for it and its derivations while any
109
+ * is live. A count, never a hold. */
110
+ _marks: number;
128
111
  }
129
112
  export interface RawSignal<T> {
130
113
  _subs: Link | null;
@@ -145,10 +128,6 @@ export interface RawSignal<T> {
145
128
  _equals: false | ((a: T, b: T) => boolean);
146
129
  _config: number;
147
130
  _time: number;
148
- /** IN CORE, not the extension (stage-3 §12c): consulted on EVERY write
149
- * (setSignal's transition-init check) and on recompute scheduling — the
150
- * per-write extension chase measurably taxed propagation chains. */
151
- _transition: Transition | null;
152
131
  /** Notify-epoch stamp of the last subscriber walk (§12d). A re-write to an
153
132
  * already-staged node whose stamp still equals the global epoch skips the
154
133
  * whole walk — marking is idempotent, and the epoch bumps on every
@@ -158,14 +137,7 @@ export interface RawSignal<T> {
158
137
  /** Cold extension — see NodeExtension. */
159
138
  _x: NodeExtension | null;
160
139
  }
161
- export interface FirewallSignal<T> extends RawSignal<T> {
162
- _firewall: Computed<any>;
163
- /** Doubly-linked child chain on the firewall's extension (`_x._child` is
164
- * the head): released leaves unlink in O(1) (#3351). */
165
- _nextChild: FirewallSignal<unknown> | null;
166
- _prevChild: FirewallSignal<unknown> | null;
167
- }
168
- export type Signal<T> = RawSignal<T> | FirewallSignal<T>;
140
+ export type Signal<T> = RawSignal<T>;
169
141
  export interface Owner {
170
142
  id?: string;
171
143
  _config: number;
@@ -176,11 +148,10 @@ export interface Owner {
176
148
  _parent: Owner | null;
177
149
  _context: Record<symbol | string, unknown>;
178
150
  _childCount: number;
179
- _queue: IQueue;
180
151
  _firstChild: Owner | null;
181
152
  _nextSibling: Owner | null;
182
153
  _prevSibling: Owner | null;
183
- /** Cold extension — see NodeExtension (owners use the zombie-pair slots). */
154
+ /** Cold extension — see NodeExtension. */
184
155
  _x: NodeExtension | null;
185
156
  /**
186
157
  * Observe-tier label: the `name` option, the node kind (`computed`,
@@ -200,22 +171,11 @@ export interface Computed<T> extends RawSignal<T>, Owner {
200
171
  _nextHeap: Computed<any> | undefined;
201
172
  _prevHeap: Computed<any>;
202
173
  _fn: (prev?: T) => T;
203
- /**
204
- * Clock tick at which REACTIVE_MANUAL_WRITE was last applied
205
- * (`suppressComputedRecompute`). Lets `refresh()` distinguish a same-tick
206
- * manual write (which wins over the refresh, #2692) from a mask carried
207
- * across ticks by a transaction (which an explicit refresh lifts, #3026).
208
- * Only meaningful while REACTIVE_MANUAL_WRITE is set.
209
- */
210
- _manualWriteTime?: number;
211
174
  /**
212
175
  * True while a `loadingValue` node's first real answer hasn't landed: the
213
176
  * node was born committed (commit #0 = the loading value) and `handleAsync`
214
177
  * serves that committed value instead of throwing NotReadyError, so first
215
- * flights never suspend readers, trip boundaries, or hold transitions.
216
- * The window is verdict-quiet: `isPending` stays false, because commit #0
217
- * answers the question by declaration (first-load affordances belong to
218
- * the value channel). Cleared by the first value landing on any path (sync
178
+ * flights never suspend readers or trip boundaries. Cleared by the first value landing on any path (sync
219
179
  * return, sync-resolved promise, first iterator yield, async settle); a
220
180
  * real error leaves it set — errors answer reads but don't enter the value
221
181
  * lineage, so a retry serves the loading value again. Once cleared, normal
@@ -1,2 +1,5 @@
1
+ /** The windows. `read` dispatches to `verdictValue` while one is open; each
2
+ * restores the dispatch it found — none inside a memo's pass a window
3
+ * pulled (`verdictValue`). */
1
4
  export declare function latest<T>(fn: () => T): T;
2
5
  export declare function isPending(fn: () => any): boolean;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Resolves nested accessors and arrays in a children tree to their rendered
3
+ * values. See the `children()` helper in solid-js for the memoized form.
4
+ */
5
+ export declare function flatten(children: any, options?: {
6
+ skipNonRendered?: boolean;
7
+ doNotUnwrap?: boolean;
8
+ }): any;
@@ -1,4 +1,4 @@
1
- export { $REFRESH, ContextNotFoundError, NoOwnerError, NotReadyError, TimeoutError, action, createContext, createOwner, createRoot, runWithOwner, flush, getNextChildId, peekNextChildId, getContext, setContext, getOwner, isDisposed, getObserver, isEqual, untrack, isPending, latest, SUPPORTS_PROXY, setSnapshotCapture, markSnapshotScope, releaseSnapshotScope, clearSnapshots, enforceLoadingBoundary, enableExternalSource, resetErrorHalt, configureClientErrors, ROOT_ERROR_HOOK } from "./core/index.js";
1
+ export { $REFRESH, action, ContextNotFoundError, NoOwnerError, NotReadyError, TimeoutError, createContext, createOwner, createRoot, runWithOwner, flush, getNextChildId, peekNextChildId, getContext, setContext, getOwner, isDisposed, getObserver, isEqual, untrack, isPending, latest, SUPPORTS_PROXY, setSnapshotCapture, markSnapshotScope, releaseSnapshotScope, clearSnapshots, enforceLoadingBoundary, enableExternalSource, resetErrorHalt, configureClientErrors, ROOT_ERROR_HOOK } from "./core/index.js";
2
2
  /**
3
3
  * @internal The dev console footer seam — registered by `solid-js`, which
4
4
  * owns the repair skill the footer points at. Not part of `DEV`; a no-op
@@ -15,9 +15,11 @@ export declare const OBSERVE: Observe | undefined;
15
15
  /** Dev tier (devtools hooks, graph traversal, console reporting): dev builds only. */
16
16
  export declare const DEV: Dev | undefined;
17
17
  export type { Owner, Context, ContextRecord, IQueue, ExternalSourceFactory, ExternalSource, ExternalSourceConfig, Refreshable, AttributionSlot, ClientErrorContext, ClientErrorHook, ClientErrorsConfig, InteractionRef, NavigationRef, Dev, Observe, ServerObserve, Records, RecordTypes, HostRecordTypes, RecordType, RecordEvent, RecordLive, RecordListener, RecordSubscribeOptions, DevHooks, DiagnosticCapture, DiagnosticCode, DiagnosticEvent, DiagnosticKind, DiagnosticListener, Diagnostics, DiagnosticSeverity, DiagnosticSubject } from "./core/index.js";
18
- export { createSignal, createMemo, createEffect, createRenderEffect, createTrackedEffect, createReaction, createOptimistic, refresh, resolve, until, onSettled, onCleanup } from "./signals.js";
18
+ export { createSignal, createOptimistic, createMemo, createEffect, createRenderEffect, createTrackedEffect, createReaction, refresh, resolve, until, onSettled, onCleanup } from "./signals.js";
19
19
  export type { Truthy, UntilOptions, Accessor, SourceAccessor, Setter, Signal, ComputeFunction, EffectFunction, EffectBundle, EffectOptions, SignalOptions, MemoOptions, NoInfer } from "./signals.js";
20
- export { affects } from "./affects.js";
21
20
  export { mapArray, repeat, type Maybe } from "./map.js";
22
21
  export * from "./store/index.js";
23
- export { createLoadingBoundary, createErrorBoundary, createRevealOrder, flatten, type RevealOrder } from "./boundaries.js";
22
+ export { affects } from "./affects.js";
23
+ export { flatten } from "./flatten.js";
24
+ export { createLoadingBoundary, createErrorBoundary } from "./boundaries.js";
25
+ export { createRevealOrder, type RevealOrder } from "./reveal.js";
@@ -0,0 +1,19 @@
1
+ export type RevealOrder = "sequential" | "together" | "natural";
2
+ type OrderAccessor = () => RevealOrder;
3
+ type BoolAccessor = () => boolean;
4
+ /**
5
+ * Lower-level primitive behind `<Reveal>`: coordinates the order in which the
6
+ * Loading boundaries created directly inside `fn` reveal their content.
7
+ *
8
+ * @param fn the subtree; the Loading boundaries it creates directly are the
9
+ * group's slots, a nested `createRevealOrder` a composite slot
10
+ * @param options `order` — `"sequential"` (default: front to back, the
11
+ * first unready slot showing its fallback), `"together"` (all at once),
12
+ * `"natural"` (each on its own); `collapsed` — in a sequential group, the
13
+ * slots behind the frontier render nothing instead of their fallbacks
14
+ */
15
+ export declare function createRevealOrder<T>(fn: () => T, options?: {
16
+ order?: OrderAccessor;
17
+ collapsed?: BoolAccessor;
18
+ }): T;
19
+ export {};
@@ -267,10 +267,11 @@ export type NoInfer<T extends any> = [T][T extends any ? 0 : never];
267
267
  * // Writable memo: derives from `fn()` and can be written like a signal.
268
268
  * const [user, setUser] = createSignal(() => fetchUser(userId()));
269
269
  *
270
- * // Within the frame the write wins over a same-tick recompute; the next
271
- * // change to `userId` re-derives (the compute receives the written value
272
- * // as `prev`). While a transaction holds a re-derived value, a write from
273
- * // outside it does not replace that derivation — it becomes its `prev`.
270
+ * // A write lands at once and never re-runs `fn` on its own; when `userId`
271
+ * // changes, in the same update or later, `fn` re-runs and receives the
272
+ * // written value as `prev`. While a transaction holds a re-derived value, a
273
+ * // write from outside it does not replace that derivation — it becomes its
274
+ * // `prev`.
274
275
  * setUser({ ...user(), name: "Alice" });
275
276
  * ```
276
277
  *
@@ -279,6 +280,27 @@ export type NoInfer<T extends any> = [T][T extends any ? 0 : never];
279
280
  export declare function createSignal<T>(): Signal<T | undefined>;
280
281
  export declare function createSignal<T>(value: Exclude<T, Function>, options?: SignalOptions<T>): Signal<T>;
281
282
  export declare function createSignal<T>(fn: ComputeFunction<T>, options?: SignalOptions<T> & MemoOptions<T>): Signal<T>;
283
+ /**
284
+ * Creates an optimistic signal: a value that can be set optimistically inside
285
+ * a transition and reverts to the value it covered when the transition ends.
286
+ *
287
+ * The write is a guess over the transition of the frame it is made in — the
288
+ * frame's held writes are its base, and it shows at once while they wait.
289
+ * Outside such a frame (nothing is held) the write is as if it never
290
+ * happened. With a function, the memo form: its own recompute is the truth
291
+ * — equal to the guess it confirms silently, different it corrects at the
292
+ * transition's commit.
293
+ *
294
+ * ```typescript
295
+ * const [state, setState] = createOptimistic<T>(value, options?: SignalOptions<T>);
296
+ * const [state, setState] = createOptimistic<T>(fn, options?: SignalOptions<T> & MemoOptions<T>);
297
+ * ```
298
+ *
299
+ * @description https://docs.solidjs.com/reference/basic-reactivity/create-optimistic-signal
300
+ */
301
+ export declare function createOptimistic<T>(): Signal<T | undefined>;
302
+ export declare function createOptimistic<T>(value: Exclude<T, Function>, options?: SignalOptions<T>): Signal<T>;
303
+ export declare function createOptimistic<T>(fn: ComputeFunction<T>, options?: SignalOptions<T> & MemoOptions<T>): Signal<T>;
282
304
  /**
283
305
  * Creates a readonly derived reactive memoized signal.
284
306
  *
@@ -381,7 +403,7 @@ export declare function createMemo<T>(compute: ComputeFunction<undefined | NoInf
381
403
  *
382
404
  * @description https://docs.solidjs.com/reference/basic-reactivity/create-effect
383
405
  */
384
- export declare function createEffect<T>(compute: ComputeFunction<undefined | NoInfer<T>, T>, effectFn: EffectFunction<NoInfer<T>, T> | EffectBundle<NoInfer<T>, T>, options?: EffectOptions): void;
406
+ export declare function createEffect<const T>(compute: ComputeFunction<undefined | NoInfer<T>, T>, effectFn: EffectFunction<NoInfer<T>, T> | EffectBundle<NoInfer<T>, T>, options?: EffectOptions): void;
385
407
  /**
386
408
  * Creates a reactive computation that runs during the render phase as DOM elements
387
409
  * are created and updated but not necessarily connected.
@@ -411,7 +433,7 @@ export declare function createEffect<T>(compute: ComputeFunction<undefined | NoI
411
433
  *
412
434
  * @description https://docs.solidjs.com/reference/secondary-primitives/create-render-effect
413
435
  */
414
- export declare function createRenderEffect<T>(compute: ComputeFunction<undefined | NoInfer<T>, T>, effectFn: EffectFunction<NoInfer<T>, T>, options?: EffectOptions): void;
436
+ export declare function createRenderEffect<const T>(compute: ComputeFunction<undefined | NoInfer<T>, T>, effectFn: EffectFunction<NoInfer<T>, T>, options?: EffectOptions): void;
415
437
  /**
416
438
  * Creates a tracked reactive effect where dependency tracking and side effects happen
417
439
  * in the same scope.
@@ -523,19 +545,10 @@ export declare function resolve<T>(fn: () => T): Promise<T>;
523
545
  * read:
524
546
  * - Accessor targets resolve with the settled value; store targets resolve
525
547
  * with the store node passed (reads through it are fresh after the await).
526
- * - A failed re-ask rejects with the error (inside an action's generator,
527
- * `yield refresh(x)` throws back at the yield point and the action reverts
528
- * like any other failure).
548
+ * - A failed re-ask rejects with the error.
529
549
  * - Semantics are quiescence, not flight identity: if another refresh (or
530
550
  * any invalidation) supersedes this one mid-flight, the promise waits for
531
551
  * — and delivers — whatever finally lands.
532
- * - Inside an action, truth landing into the held transaction is STAGED;
533
- * the promise still settles then (matching `resolve()`/`until()`, #2930)
534
- * and delivers the staged value — the caller's own optimistic override is
535
- * never the delivered value.
536
- * - The re-ask itself stays verdict-quiet exactly as before: `isPending`
537
- * does not flip for a bare refresh (pair with `affects()` for a visible
538
- * pending window).
539
552
  *
540
553
  * @example
541
554
  * ```ts
@@ -585,96 +598,27 @@ export interface UntilOptions {
585
598
  *
586
599
  * Where {@link resolve} answers "what is this value" (first settled value,
587
600
  * whatever it is), `until` answers "when does the world confirm this
588
- * condition". The difference matters inside an `action()`: `yield until(...)`
589
- * holds the action's transaction — and any optimistic state riding it — open
590
- * until the condition is independently true.
591
- *
592
- * To make that sound, `until`'s predicate reads the AUTHORITATIVE view — and
593
- * this is the one read-semantics difference from `resolve`, which reads the
594
- * normal (transaction's own) view where overrides are visible:
595
- *
596
- * - **Optimistic overrides are invisible** to the predicate. Your own
597
- * tentative write can never satisfy your own ack, even on the
598
- * single-primitive shape where the optimistic store IS the live-fed store.
599
- * (Derived computeds serve their normal cached values — express the
600
- * condition over sources of truth, not derived views of the overlay.)
601
- * - **Everything else reads normally, including uncommitted transition-staged
602
- * data.** Real data is real wherever it currently lives. This is
603
- * load-bearing, not a loophole: truth that arrives *into* the open
604
- * transaction (a `refresh()` this action issued, an entangled landing)
605
- * stages and cannot commit until the hold releases — a predicate that
606
- * refused staged reads would deadlock on the very data it is waiting for.
601
+ * condition".
607
602
  *
608
603
  * This is the acknowledgment mechanism for mutations confirmed on a live data
609
604
  * channel (sockets, subscriptions, live queries) rather than by the mutation's
610
605
  * own response: correlate by a client-generated id or version in the predicate,
611
606
  * and let truth arrive however it arrives — push, refetch, or another tab.
612
607
  *
613
- * Failure composes with action semantics: a rejection is thrown back into the
614
- * generator at the `yield` point — catchable there, or the action fails and
615
- * its optimistic state reverts.
616
- *
617
608
  * Must be called *outside* a tracking scope.
618
609
  *
619
- * Inside an action, call it from a step: after an `await`, put a bare `yield`
620
- * before `yield until(...)`. The runtime cannot hook an async generator's
621
- * `await` continuation, so the `until(...)` expression — which CREATES the
622
- * predicate's reader — would otherwise run outside the transaction; created
623
- * there it is born held (A29) and replays only at the commit its own promise
624
- * holds open (#3482). See {@link action}.
625
- *
626
610
  * @example
627
611
  * ```ts
628
- * const send = action(async function* (text: string) {
629
- * const clientId = crypto.randomUUID();
630
- * setMessages(m => { m.push({ clientId, text, pending: true }); }); // optimistic
631
- * await socket.send({ clientId, text }); // fire-and-forget transport
632
- * yield; // re-enter the transaction after the await
633
- * // Hold until the live source echoes the write (authoritative view —
634
- * // the optimistic row above cannot satisfy this):
635
- * yield until(() => messages.some(m => m.clientId === clientId), { timeout: 10_000 });
636
- * });
612
+ * const clientId = crypto.randomUUID();
613
+ * await socket.send({ clientId, text }); // fire-and-forget transport
614
+ * // Wait until the live source echoes the write:
615
+ * await until(() => messages.some(m => m.clientId === clientId), { timeout: 10_000 });
637
616
  * ```
638
617
  *
639
- * @param fn a reactive predicate over authoritative state
618
+ * @param fn a reactive predicate
640
619
  * @param options optional `timeout` (ms) and abort `signal`
641
620
  */
642
621
  export declare function until<T>(fn: () => T, options?: UntilOptions): Promise<Truthy<T>>;
643
- /**
644
- * Creates an optimistic signal that can be used to optimistically update a value
645
- * and then revert it back to the previous value at end of transition.
646
- *
647
- * When called with a plain value, creates an optimistic signal with `SignalOptions` (name, equals, ownedWrite, unobserved).
648
- * When called with a function, creates a writable optimistic memo with `SignalOptions & MemoOptions` (adds id, lazy).
649
- *
650
- * ```typescript
651
- * // Plain optimistic signal
652
- * const [state, setState] = createOptimistic<T>(value, options?: SignalOptions<T>);
653
- * // Writable optimistic memo (function overload)
654
- * const [state, setState] = createOptimistic<T>(fn, options?: SignalOptions<T> & MemoOptions<T>);
655
- * ```
656
- * @param value initial value of the signal; if empty, the signal's type will automatically extended with undefined
657
- * @param options optional object with a name for debugging purposes and equals, a comparator function for the previous and next value to allow fine-grained control over the reactivity
658
- *
659
- * @returns `[state: Accessor<T>, setState: Setter<T>]`
660
- *
661
- * @example
662
- * ```ts
663
- * const [todos, setTodos] = createOptimistic(initialTodos);
664
- *
665
- * const addTodo = action(function* (text: string) {
666
- * const tempId = crypto.randomUUID();
667
- * setTodos(t => [...t, { id: tempId, text, pending: true }]); // optimistic
668
- * const saved = yield api.createTodo(text);
669
- * setTodos(t => t.map(x => (x.id === tempId ? saved : x))); // reconcile
670
- * });
671
- * ```
672
- *
673
- * @description https://docs.solidjs.com/reference/basic-reactivity/create-optimistic-signal
674
- */
675
- export declare function createOptimistic<T>(): Signal<T | undefined>;
676
- export declare function createOptimistic<T>(value: Exclude<T, Function>, options?: SignalOptions<T>): Signal<T>;
677
- export declare function createOptimistic<T>(fn: ComputeFunction<T>, options?: SignalOptions<T> & MemoOptions<T>): Signal<T>;
678
622
  /**
679
623
  * Schedules `callback` to run **once** after the reactive graph has fully
680
624
  * settled — i.e. once every pending async read inside the current owner has
@@ -0,0 +1,12 @@
1
+ import type { Computed, Signal } from "../core/types.js";
2
+ import { type StoreTarget } from "./target.js";
3
+ type Marked = Signal<any> | Computed<any>;
4
+ /** The nodes an `affects(store[, key])` declaration marks (affects.ts
5
+ * registers each). */
6
+ export declare function storeMarks(t: StoreTarget, key: PropertyKey | undefined): Marked[];
7
+ /** `affects()` calls it before a store-targeted declaration (idempotent). */
8
+ export declare function installStoreAffects(): void;
9
+ /** The carrier's last mark released (affects.ts): its scope dies, and the
10
+ * nodes that inherited the mark release theirs. */
11
+ export declare function releaseMarkScope(carrier: Marked): void;
12
+ export {};
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Store — the engine's optional-machinery slots, in a module of their own so
3
+ * an installer reaches them without importing store.ts (whose top level
4
+ * installs the engine): the store half of `affects()` installs through here
5
+ * from `affects()`, and an app without stores carries none of the engine.
6
+ * A slot no installer reaches stays `null`, and a bundler folds its sites.
7
+ */
8
+ import type { Signal } from "../core/types.js";
9
+ import type { StoreTarget } from "./target.js";
10
+ /** The optimistic machinery (optimistic.ts, S4), installed when it loads
11
+ * — a plain store pays nothing for it (#2883): the plain paths reach it
12
+ * only through a family with `opt` set, which only `createOptimisticStore`
13
+ * sets. */
14
+ export interface OptHooks {
15
+ /** A user setter's draft on an optimistic family: a clone of the
16
+ * writer's view (a staging already on the target is set aside). */
17
+ draft(t: StoreTarget): Record<PropertyKey, any>;
18
+ /** The setter's exit: the draft becomes guesses; returns the staging the
19
+ * draft set aside (`null`: none). */
20
+ writes(t: StoreTarget, pb: Record<PropertyKey, any>): Record<PropertyKey, any> | null;
21
+ /** `src` with the lanes' values over it (`writer`: the next write's base
22
+ * — the unflushed guesses too). */
23
+ view(t: StoreTarget, src: Record<PropertyKey, any>, writer?: boolean): Record<PropertyKey, any>;
24
+ /** An untracked `key in store`: the presence guess, or `undefined`. */
25
+ has(t: StoreTarget, key: PropertyKey): boolean | undefined;
26
+ /** A guessed key's descriptor (`null`: removed; `undefined`: no guess). */
27
+ descriptor(t: StoreTarget, key: PropertyKey): PropertyDescriptor | null | undefined;
28
+ /** The flush's commit: targets no lane holds leave `overlaid`. */
29
+ sweep(): void;
30
+ /** The container comparator's lane arm: an arrangement guess against a
31
+ * landing (or another arrangement), by row identity. */
32
+ arrangement(t: StoreTarget, a: any, b: any): boolean;
33
+ /** A user's `reconcile` on an optimistic family: the keyed diff written
34
+ * into the draft. */
35
+ reconcile(draft: any, incoming: any, keyFn: ((item: any) => any) | null): void;
36
+ }
37
+ export declare let optHooks: OptHooks | null;
38
+ export declare function installOptHooks(hooks: OptHooks): void;
39
+ /** The store half of `affects()` (store/affects.ts), installed by the first
40
+ * store-targeted declaration: a node born on a covered record inherits the
41
+ * live mark; an untracked verdict probe through a record with no node is
42
+ * witnessed. */
43
+ export interface AffectsHooks {
44
+ _born(t: StoreTarget, node: Signal<any>, key: PropertyKey): void;
45
+ _witness(t: StoreTarget, key: PropertyKey | undefined): void;
46
+ }
47
+ export declare let affectsHooks: AffectsHooks | null;
48
+ export declare function installAffectsHooks(hooks: AffectsHooks): void;
@@ -1,20 +1,39 @@
1
- export type { Store, StoreReturn, ProjectionStoreReturn, StoreSetter, StoreNode, StoreOptions, ProjectionOptions, NotWrappable, SolidStore } from "./store.js";
1
+ /**
2
+ * Store — public surface. Plain stores (S1) are live; the derived form
3
+ * (`createStore(fn, seed)`), projections, optimistic stores and reconcile
4
+ * return on later steps (plan sec. 31.5).
5
+ */
6
+ export type { NoFn, NotWrappable, ProjectionOptions, ProjectionStoreReturn, SolidStore, Store, StoreOptions, StoreReturn, StoreSetter } from "./types.js";
7
+ export { $PROXY, $RECORD, $TARGET, $TRACK, isWrappable, markRaw } from "./types.js";
8
+ export { storeIsShallow, storeHasFamily, storeHasOptimisticFamily } from "./store.js";
9
+ export { storePath } from "./storePath.js";
10
+ export type { StorePathRange, PathSetter, Part, CustomPartial, ArrayFilterFn } from "./storePath.js";
11
+ import { createOptimisticStore } from "./optimistic.js";
12
+ import { createProjection } from "./projection.js";
13
+ import type { NoFn, ProjectionOptions, ProjectionStoreReturn, Store, StoreOptions, StoreReturn } from "./types.js";
14
+ export { createOptimisticStore, createProjection };
15
+ /** The store's internal record behind a proxy (`store[$TARGET]`). Kept
16
+ * under `next`'s public name; its shape is the L2 target's (plan plan sec. 31–32:
17
+ * the symbol-keyed legacy record is gone with the representation). */
18
+ export type { StoreTarget as StoreNode } from "./target.js";
2
19
  export type { Merge, Omit } from "./utils.js";
3
- export { isWrappable, $TRACK, $PROXY, $TARGET, $RECORD } from "./store.js";
4
- export { mergeSources, mergeView, viewOf, omitView, sourceKeys, sourceHas, sourceGet, hasStaticKeys, isStatic, resolvedTable, OmitView, MergeView, SOURCE_PLAIN, SOURCE_OMIT, SOURCE_PROXY, SOURCE_MEMO, SOURCE_MERGE, sourceOwners } from "./utils.js";
20
+ export { mergeSources, mergeView, viewOf, omitView, sourceKeys, sourceHas, sourceGet, hasStaticKeys, isStatic, resolvedTable, OmitView, MergeView, SOURCE_PLAIN, SOURCE_OMIT, SOURCE_PROXY, SOURCE_MEMO, SOURCE_MERGE, sourceOwners, merge, omit } from "./utils.js";
5
21
  export type { SourceKind } from "./utils.js";
6
- import type { NoFn, ProjectionOptions, Store, StoreOptions, StoreSetter } from "./store.js";
7
- import type { Refreshable } from "../core/index.js";
8
- export { createProjectionNext as createProjection } from "./next/projection.js";
9
- export { storeIsShallow, storeHasFamily, storeHasOptimisticFamily } from "./next/store.js";
10
- export { createOptimisticStoreNext as createOptimisticStore } from "./next/optimistic.js";
11
- /** Public createStore: plain form `(initialValue, options?)` and derived writable
12
- * form `(fn, seed, options?)`. */
13
- export declare function createStore<T extends object = {}>(initialValue: NoFn<T> | Store<NoFn<T>>, options?: StoreOptions): [get: Store<T>, set: StoreSetter<T>];
14
- 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): [get: Refreshable<Store<T>>, set: StoreSetter<T>];
22
+ /**
23
+ * Create a reactive store: a proxy over plain data with fine-grained
24
+ * subscriptions per read path, written through its setter's draft — or, in
25
+ * the derived form, a projection with a setter.
26
+ */
27
+ 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>;
29
+ /**
30
+ * A setter transform that reconciles `value` into the store by key
31
+ * (`"id"` by default; `null` positional), preserving store identity for
32
+ * surviving rows.
33
+ */
15
34
  export declare function reconcile<T extends U, U>(value: T, key?: string | ((item: NonNullable<any>) => any) | null): (state: U) => T;
35
+ /** Non-tracking snapshot of a store's current value (source identity for
36
+ * unmodified subtrees). */
16
37
  export declare function snapshot<T>(value: T): T;
38
+ /** Tracking snapshot: subscribes to every reachable record. */
17
39
  export declare function deep<T>(value: T): T;
18
- export { storePath } from "./storePath.js";
19
- export type { PathSetter, Part, StorePathRange, ArrayFilterFn, CustomPartial } from "./storePath.js";
20
- export { merge, omit } from "./utils.js";
@@ -0,0 +1,23 @@
1
+ import type { Refreshable } from "../core/index.js";
2
+ import { type StoreTarget } from "./target.js";
3
+ import { type NoFn, type ProjectionOptions, type Store, type StoreOptions, type StoreSetter } from "./types.js";
4
+ export declare function notifyOptimisticWrites(t: StoreTarget, pb: Record<PropertyKey, any>): Record<PropertyKey, any> | null;
5
+ export declare function sweepOverlaid(): void;
6
+ /** An untracked `key in store` on an optimistic family: the presence guess
7
+ * (what its lane shows) when the key carries one; `undefined` when not —
8
+ * the backing answers. */
9
+ export declare function optimisticHas(t: StoreTarget, key: PropertyKey): boolean | undefined;
10
+ /** A descriptor read of a guessed key: synthesized from the lane's value
11
+ * (`null`: the guess removed the key; `undefined`: no guess — the backing
12
+ * describes it). */
13
+ export declare function optimisticOwnDescriptor(t: StoreTarget, key: PropertyKey): PropertyDescriptor | null | undefined;
14
+ /** The truth `src` with the target's lane values over it: each overlaid
15
+ * leaf's value (`pick`: what the lane shows, or — for `latest` — the lane's
16
+ * latest), each presence guess as a key added or removed, the array
17
+ * length. Returns `src` itself when nothing is overlaid. */
18
+ export declare function optimisticView(t: StoreTarget, src: Record<PropertyKey, any>, pick?: (n: any) => unknown, writer?: boolean): Record<PropertyKey, any>;
19
+ /** `latest()`'s view: the lanes' latest values (a landing staged beneath a
20
+ * guess is what lands). */
21
+ export declare function latestView(t: StoreTarget, src: Record<PropertyKey, any>): Record<PropertyKey, any>;
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>];
@@ -0,0 +1,18 @@
1
+ import type { Computed } from "../core/types.js";
2
+ import type { Refreshable } from "../core/index.js";
3
+ import { 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>;
10
+ /**
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).
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>>;
17
+ /** `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];
@@ -0,0 +1,3 @@
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 {};