@solidjs/signals 2.0.0-rc.13 → 2.0.0-rc.14

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 (118) hide show
  1. package/dist/dev-shared.js +2000 -3768
  2. package/dist/dev.attribution.js +132 -79
  3. package/dist/dev.js +7226 -8488
  4. package/dist/observe/affects.js +125 -104
  5. package/dist/observe/boundaries.js +458 -665
  6. package/dist/observe/core/action.js +63 -66
  7. package/dist/observe/core/async.js +240 -383
  8. package/dist/observe/core/attribution-queries.js +1 -1
  9. package/dist/observe/core/attribution.js +240 -183
  10. package/dist/observe/core/constants.js +115 -187
  11. package/dist/observe/core/context.js +3 -3
  12. package/dist/observe/core/core.js +840 -1438
  13. package/dist/observe/core/dev.js +3 -3
  14. package/dist/observe/core/effect.js +75 -86
  15. package/dist/observe/core/external.js +5 -5
  16. package/dist/observe/core/graph.js +61 -70
  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 +704 -181
  20. package/dist/observe/core/owner.js +80 -101
  21. package/dist/observe/core/scheduler.js +708 -1351
  22. package/dist/observe/core/verdict.js +302 -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 +133 -215
  28. package/dist/observe/store/affects.js +135 -0
  29. package/dist/observe/store/index.js +29 -24
  30. package/dist/observe/store/optimistic.js +538 -0
  31. package/dist/observe/store/projection.js +302 -0
  32. package/dist/observe/store/reconcile.js +257 -0
  33. package/dist/observe/store/store.js +1945 -277
  34. package/dist/observe/store/storePath.js +1 -1
  35. package/dist/{prod/store/next → observe/store}/target.js +17 -18
  36. package/dist/observe/store/types.js +73 -0
  37. package/dist/observe/store/utils.js +1 -13
  38. package/dist/prod/affects.js +127 -106
  39. package/dist/prod/boundaries.js +442 -654
  40. package/dist/prod/core/action.js +71 -74
  41. package/dist/prod/core/async.js +307 -442
  42. package/dist/prod/core/constants.js +112 -186
  43. package/dist/prod/core/context.js +3 -3
  44. package/dist/prod/core/core.js +852 -1458
  45. package/dist/prod/core/effect.js +88 -99
  46. package/dist/prod/core/external.js +5 -5
  47. package/dist/prod/core/graph.js +61 -70
  48. package/dist/prod/core/heap.js +75 -98
  49. package/dist/prod/core/invariants.js +1 -32
  50. package/dist/prod/core/lanes.js +666 -181
  51. package/dist/prod/core/owner.js +75 -96
  52. package/dist/prod/core/scheduler.js +677 -1332
  53. package/dist/prod/core/verdict.js +297 -621
  54. package/dist/prod/flatten.js +77 -0
  55. package/dist/prod/index.js +15 -13
  56. package/dist/prod/map.js +143 -146
  57. package/dist/prod/reveal.js +212 -0
  58. package/dist/prod/signals.js +144 -226
  59. package/dist/prod/store/affects.js +135 -0
  60. package/dist/prod/store/index.js +28 -19
  61. package/dist/prod/store/optimistic.js +533 -0
  62. package/dist/prod/store/projection.js +295 -0
  63. package/dist/prod/store/reconcile.js +257 -0
  64. package/dist/prod/store/store.js +1840 -272
  65. package/dist/prod/store/storePath.js +1 -1
  66. package/dist/{observe/store/next → prod/store}/target.js +13 -17
  67. package/dist/prod/store/types.js +73 -0
  68. package/dist/prod/store/utils.js +1 -11
  69. package/dist/types/affects.d.ts +11 -30
  70. package/dist/types/boundaries.d.ts +62 -176
  71. package/dist/types/carved.d.ts +1 -0
  72. package/dist/types/core/action.d.ts +5 -6
  73. package/dist/types/core/async.d.ts +10 -5
  74. package/dist/types/core/attribution-hooks.d.ts +20 -1
  75. package/dist/types/core/attribution.d.ts +20 -9
  76. package/dist/types/core/constants.d.ts +125 -180
  77. package/dist/types/core/core.d.ts +104 -264
  78. package/dist/types/core/dev.d.ts +2 -2
  79. package/dist/types/core/effect.d.ts +0 -7
  80. package/dist/types/core/graph.d.ts +7 -1
  81. package/dist/types/core/heap.d.ts +5 -7
  82. package/dist/types/core/index.d.ts +5 -5
  83. package/dist/types/core/invariants.d.ts +0 -29
  84. package/dist/types/core/lanes.d.ts +65 -87
  85. package/dist/types/core/owner.d.ts +3 -3
  86. package/dist/types/core/scheduler.d.ts +249 -331
  87. package/dist/types/core/types.d.ts +51 -85
  88. package/dist/types/core/verdict.d.ts +3 -0
  89. package/dist/types/flatten.d.ts +8 -0
  90. package/dist/types/index.d.ts +6 -4
  91. package/dist/types/reveal.d.ts +19 -0
  92. package/dist/types/signals.d.ts +35 -91
  93. package/dist/types/store/affects.d.ts +1 -0
  94. package/dist/types/store/index.d.ts +35 -15
  95. package/dist/types/store/optimistic.d.ts +23 -0
  96. package/dist/types/store/projection.d.ts +18 -0
  97. package/dist/types/store/reconcile.d.ts +3 -0
  98. package/dist/types/store/store.d.ts +165 -143
  99. package/dist/types/store/storePath.d.ts +1 -1
  100. package/dist/types/store/target.d.ts +151 -0
  101. package/dist/types/store/types.d.ts +84 -0
  102. package/package.json +1 -1
  103. package/dist/observe/core/optimistic.js +0 -669
  104. package/dist/observe/store/next/optimistic.js +0 -717
  105. package/dist/observe/store/next/projection.js +0 -266
  106. package/dist/observe/store/next/reconcile.js +0 -375
  107. package/dist/observe/store/next/store.js +0 -2608
  108. package/dist/prod/core/optimistic.js +0 -658
  109. package/dist/prod/store/next/optimistic.js +0 -710
  110. package/dist/prod/store/next/projection.js +0 -257
  111. package/dist/prod/store/next/reconcile.js +0 -373
  112. package/dist/prod/store/next/store.js +0 -2484
  113. package/dist/types/core/optimistic.d.ts +0 -6
  114. package/dist/types/store/next/optimistic.d.ts +0 -25
  115. package/dist/types/store/next/projection.d.ts +0 -27
  116. package/dist/types/store/next/reconcile.d.ts +0 -10
  117. package/dist/types/store/next/store.d.ts +0 -145
  118. 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,53 @@ 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
+ /** L2 — the transaction a first pass that went pending was born into (it
90
+ * read a held node, or a verdict lane's mount read a staging of the
91
+ * flush — the born-held arm's conditions): its first answer lands into it
92
+ * while it is live; the hold never waits for the node's first load (the
93
+ * direction rule, #3800). Consumed at the landing. */
94
+ _bornIn: Transaction | null;
95
+ /** The node's current flight re-asks the same question (a `refresh()`,
96
+ * A19 exc. 2 / A24): verdict-quiet — `isPending` reads false for it —
97
+ * through its landing until the commit. */
98
+ _reask: boolean;
99
+ /** A28: the staging the last flush left on a held node, kept across an
100
+ * unflushed rewrite — what `latest()` and a tracked reader see until the
101
+ * flush that carries the rewrite; valid while `_flushedAt` is the current
102
+ * clock (that flush advances it). */
103
+ _flushed: unknown;
104
+ _flushedAt: number;
105
+ /** Provenance (A18, #3331): the question this node's guess or latest
106
+ * flight answers (`scheduler.question`); 0 when unstamped. */
107
+ _q: number;
108
+ /** Lanes (plan sec. 28) — the lane's value for this node while CONFIG_OVERRIDE is
109
+ * set: a written guess, or a lane pass's derivation. `NOT_PENDING` when
110
+ * none. The screen shows it once the lane has revealed (`_shown`); a
111
+ * direct read sees it throughout; the committed truth stays `_value`. */
112
+ _lane: unknown;
113
+ /** `affects()` marks live on this node (affects.ts): declared in-flight
114
+ * changes — `isPending` reads true for it and its derivations while any
115
+ * is live. A count, never a hold. */
116
+ _marks: number;
128
117
  }
129
118
  export interface RawSignal<T> {
130
119
  _subs: Link | null;
@@ -145,10 +134,6 @@ export interface RawSignal<T> {
145
134
  _equals: false | ((a: T, b: T) => boolean);
146
135
  _config: number;
147
136
  _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
137
  /** Notify-epoch stamp of the last subscriber walk (§12d). A re-write to an
153
138
  * already-staged node whose stamp still equals the global epoch skips the
154
139
  * whole walk — marking is idempotent, and the epoch bumps on every
@@ -158,14 +143,7 @@ export interface RawSignal<T> {
158
143
  /** Cold extension — see NodeExtension. */
159
144
  _x: NodeExtension | null;
160
145
  }
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>;
146
+ export type Signal<T> = RawSignal<T>;
169
147
  export interface Owner {
170
148
  id?: string;
171
149
  _config: number;
@@ -176,11 +154,10 @@ export interface Owner {
176
154
  _parent: Owner | null;
177
155
  _context: Record<symbol | string, unknown>;
178
156
  _childCount: number;
179
- _queue: IQueue;
180
157
  _firstChild: Owner | null;
181
158
  _nextSibling: Owner | null;
182
159
  _prevSibling: Owner | null;
183
- /** Cold extension — see NodeExtension (owners use the zombie-pair slots). */
160
+ /** Cold extension — see NodeExtension. */
184
161
  _x: NodeExtension | null;
185
162
  /**
186
163
  * Observe-tier label: the `name` option, the node kind (`computed`,
@@ -200,22 +177,11 @@ export interface Computed<T> extends RawSignal<T>, Owner {
200
177
  _nextHeap: Computed<any> | undefined;
201
178
  _prevHeap: Computed<any>;
202
179
  _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
180
  /**
212
181
  * True while a `loadingValue` node's first real answer hasn't landed: the
213
182
  * node was born committed (commit #0 = the loading value) and `handleAsync`
214
183
  * 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
184
+ * flights never suspend readers or trip boundaries. Cleared by the first value landing on any path (sync
219
185
  * return, sync-resolved promise, first iterator yield, async settle); a
220
186
  * real error leaves it set — errors answer reads but don't enter the value
221
187
  * 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 @@
1
+ export {};
@@ -1,20 +1,40 @@
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 "./affects.js";
12
+ import { createOptimisticStore } from "./optimistic.js";
13
+ import { createProjection } from "./projection.js";
14
+ import type { NoFn, ProjectionOptions, ProjectionStoreReturn, Store, StoreOptions, StoreReturn } from "./types.js";
15
+ export { createOptimisticStore, createProjection };
16
+ /** The store's internal record behind a proxy (`store[$TARGET]`). Kept
17
+ * under `next`'s public name; its shape is the L2 target's (plan plan sec. 31–32:
18
+ * the symbol-keyed legacy record is gone with the representation). */
19
+ export type { StoreTarget as StoreNode } from "./target.js";
2
20
  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";
21
+ 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
22
  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>];
23
+ /**
24
+ * Create a reactive store: a proxy over plain data with fine-grained
25
+ * subscriptions per read path, written through its setter's draft — or, in
26
+ * the derived form, a projection with a setter.
27
+ */
28
+ export declare function createStore<T extends object = {}>(initialValue: NoFn<T>, options?: StoreOptions): StoreReturn<T>;
29
+ 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>;
30
+ /**
31
+ * A setter transform that reconciles `value` into the store by key
32
+ * (`"id"` by default; `null` positional), preserving store identity for
33
+ * surviving rows.
34
+ */
15
35
  export declare function reconcile<T extends U, U>(value: T, key?: string | ((item: NonNullable<any>) => any) | null): (state: U) => T;
36
+ /** Non-tracking snapshot of a store's current value (source identity for
37
+ * unmodified subtrees). */
16
38
  export declare function snapshot<T>(value: T): T;
39
+ /** Tracking snapshot: subscribes to every reachable record. */
17
40
  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 {};