@solidjs/signals 2.0.0-rc.6 → 2.0.0-rc.8

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 (131) hide show
  1. package/dist/dev-shared.js +5243 -0
  2. package/dist/dev.attribution.js +2333 -0
  3. package/dist/dev.js +1758 -6621
  4. package/dist/observe/affects.js +127 -0
  5. package/dist/observe/attribution.js +1 -0
  6. package/dist/observe/boundaries.js +586 -0
  7. package/dist/observe/core/action.js +167 -0
  8. package/dist/observe/core/async.js +736 -0
  9. package/dist/observe/core/attribution-hooks.js +60 -0
  10. package/dist/observe/core/attribution.js +2318 -0
  11. package/dist/{types-cjs/core/constants.d.cts → observe/core/constants.js} +135 -71
  12. package/dist/{types-cjs/core/context.d.cts → observe/core/context.js} +37 -12
  13. package/dist/observe/core/core.js +1289 -0
  14. package/dist/observe/core/dev.js +232 -0
  15. package/dist/observe/core/effect.js +179 -0
  16. package/dist/observe/core/error.js +80 -0
  17. package/dist/observe/core/external.js +98 -0
  18. package/dist/observe/core/graph.js +155 -0
  19. package/dist/observe/core/heap.js +147 -0
  20. package/dist/observe/core/invariants.js +43 -0
  21. package/dist/observe/core/lanes.js +168 -0
  22. package/dist/observe/core/optimistic.js +438 -0
  23. package/dist/observe/core/owner.js +308 -0
  24. package/dist/observe/core/scheduler.js +1190 -0
  25. package/dist/observe/core/verdict.js +551 -0
  26. package/dist/observe/index.js +55 -0
  27. package/dist/observe/map.js +482 -0
  28. package/dist/{types-cjs/signals.d.cts → observe/signals.js} +305 -317
  29. package/dist/observe/store/index.js +38 -0
  30. package/dist/observe/store/next/optimistic.js +651 -0
  31. package/dist/observe/store/next/projection.js +242 -0
  32. package/dist/observe/store/next/reconcile.js +373 -0
  33. package/dist/observe/store/next/store.js +2213 -0
  34. package/dist/observe/store/next/target.js +51 -0
  35. package/dist/observe/store/store.js +323 -0
  36. package/dist/observe/store/storePath.js +103 -0
  37. package/dist/observe/store/utils.js +210 -0
  38. package/dist/prod/attribution.js +32 -0
  39. package/dist/prod/boundaries.js +3 -1
  40. package/dist/prod/core/action.js +52 -32
  41. package/dist/prod/core/async.js +177 -128
  42. package/dist/prod/core/attribution-hooks.js +3 -0
  43. package/dist/prod/core/constants.js +32 -1
  44. package/dist/prod/core/context.js +10 -16
  45. package/dist/prod/core/core.js +505 -286
  46. package/dist/prod/core/dev.js +2 -0
  47. package/dist/prod/core/effect.js +72 -43
  48. package/dist/prod/core/external.js +2 -2
  49. package/dist/prod/core/graph.js +40 -36
  50. package/dist/prod/core/heap.js +50 -51
  51. package/dist/prod/core/lanes.js +43 -22
  52. package/dist/prod/core/optimistic.js +224 -80
  53. package/dist/prod/core/owner.js +43 -39
  54. package/dist/prod/core/scheduler.js +347 -232
  55. package/dist/prod/core/verdict.js +71 -74
  56. package/dist/prod/index.js +9 -5
  57. package/dist/prod/map.js +311 -150
  58. package/dist/prod/signals.js +52 -38
  59. package/dist/prod/store/next/optimistic.js +127 -131
  60. package/dist/prod/store/next/projection.js +3 -3
  61. package/dist/prod/store/next/reconcile.js +149 -294
  62. package/dist/prod/store/next/store.js +694 -380
  63. package/dist/prod/store/next/target.js +32 -10
  64. package/dist/prod/store/store.js +12 -14
  65. package/dist/prod/store/utils.js +36 -27
  66. package/dist/types/attribution.d.ts +15 -0
  67. package/dist/types/attribution.prod.d.ts +13 -0
  68. package/dist/types/core/async.d.ts +1 -1
  69. package/dist/types/core/attribution-hooks.d.ts +183 -6
  70. package/dist/types/core/attribution.d.ts +435 -24
  71. package/dist/types/core/constants.d.ts +31 -0
  72. package/dist/types/core/core.d.ts +19 -3
  73. package/dist/types/core/dev.d.ts +165 -26
  74. package/dist/types/core/effect.d.ts +8 -1
  75. package/dist/types/core/heap.d.ts +5 -3
  76. package/dist/types/core/index.d.ts +2 -1
  77. package/dist/types/core/invariants.d.ts +1 -1
  78. package/dist/types/core/lanes.d.ts +17 -0
  79. package/dist/types/core/scheduler.d.ts +69 -4
  80. package/dist/types/core/types.d.ts +29 -9
  81. package/dist/types/index.d.ts +9 -2
  82. package/dist/types/map.d.ts +2 -0
  83. package/dist/types/signals.d.ts +10 -0
  84. package/dist/types/store/index.d.ts +4 -6
  85. package/dist/types/store/next/optimistic.d.ts +4 -2
  86. package/dist/types/store/next/reconcile.d.ts +5 -12
  87. package/dist/types/store/next/store.d.ts +8 -9
  88. package/dist/types/store/next/target.d.ts +56 -55
  89. package/dist/types/store/store.d.ts +14 -9
  90. package/dist/types/store/utils.d.ts +7 -0
  91. package/package.json +21 -16
  92. package/dist/node.cjs +0 -11121
  93. package/dist/prod/store/next/patch-hooks.js +0 -13
  94. package/dist/prod/store/next/patch.js +0 -614
  95. package/dist/types/store/next/patch-hooks.d.ts +0 -41
  96. package/dist/types/store/next/patch.d.ts +0 -91
  97. package/dist/types-cjs/affects.d.cts +0 -47
  98. package/dist/types-cjs/boundaries.d.cts +0 -175
  99. package/dist/types-cjs/core/action.d.cts +0 -64
  100. package/dist/types-cjs/core/async.d.cts +0 -23
  101. package/dist/types-cjs/core/attribution-hooks.d.cts +0 -63
  102. package/dist/types-cjs/core/attribution.d.cts +0 -239
  103. package/dist/types-cjs/core/core.d.cts +0 -176
  104. package/dist/types-cjs/core/dev.d.cts +0 -95
  105. package/dist/types-cjs/core/effect.d.cts +0 -30
  106. package/dist/types-cjs/core/error.d.cts +0 -56
  107. package/dist/types-cjs/core/external.d.cts +0 -15
  108. package/dist/types-cjs/core/graph.d.cts +0 -28
  109. package/dist/types-cjs/core/heap.d.cts +0 -22
  110. package/dist/types-cjs/core/index.d.cts +0 -13
  111. package/dist/types-cjs/core/invariants.d.cts +0 -59
  112. package/dist/types-cjs/core/lanes.d.cts +0 -44
  113. package/dist/types-cjs/core/optimistic.d.cts +0 -6
  114. package/dist/types-cjs/core/owner.d.cts +0 -124
  115. package/dist/types-cjs/core/scheduler.d.cts +0 -231
  116. package/dist/types-cjs/core/types.d.cts +0 -204
  117. package/dist/types-cjs/core/verdict.d.cts +0 -2
  118. package/dist/types-cjs/index.d.cts +0 -10
  119. package/dist/types-cjs/map.d.cts +0 -69
  120. package/dist/types-cjs/package.json +0 -3
  121. package/dist/types-cjs/store/index.d.cts +0 -21
  122. package/dist/types-cjs/store/next/optimistic.d.cts +0 -23
  123. package/dist/types-cjs/store/next/patch-hooks.d.cts +0 -41
  124. package/dist/types-cjs/store/next/patch.d.cts +0 -91
  125. package/dist/types-cjs/store/next/projection.d.cts +0 -8
  126. package/dist/types-cjs/store/next/reconcile.d.cts +0 -17
  127. package/dist/types-cjs/store/next/store.d.cts +0 -127
  128. package/dist/types-cjs/store/next/target.d.cts +0 -192
  129. package/dist/types-cjs/store/store.d.cts +0 -138
  130. package/dist/types-cjs/store/storePath.d.cts +0 -58
  131. package/dist/types-cjs/store/utils.d.cts +0 -74
@@ -1,5 +1,5 @@
1
- import { type Attribution } from "./attribution.js";
2
- import type { Computed, Link, Owner, Signal } from "./types.js";
1
+ import { type AttributionHooks, type InteractionRef, type OriginRef } from "./attribution-hooks.js";
2
+ import type { Computed, Owner, Signal } from "./types.js";
3
3
  export interface DevHooks {
4
4
  onOwner?: (owner: Owner) => void;
5
5
  onGraph?: (value: any, owner: Owner | null) => void;
@@ -13,11 +13,13 @@ export interface DevHooks {
13
13
  * `warn`/`error` as failures unless they opt in to `info`.
14
14
  */
15
15
  export type DiagnosticSeverity = "info" | "warn" | "error";
16
- export type DiagnosticCode = "STRICT_READ_UNTRACKED" | "PENDING_ASYNC_UNTRACKED_READ" | "PENDING_ASYNC_FORBIDDEN_SCOPE" | "REACTIVE_WRITE_IN_OWNED_SCOPE" | "ACTION_CALLED_IN_OWNED_SCOPE" | "RUN_WITH_DISPOSED_OWNER" | "NO_OWNER_CLEANUP" | "CLEANUP_IN_FORBIDDEN_SCOPE" | "SETTLED_CLEANUP_UNOWNED" | "SETTLE_WALK_UNINITIALIZED_SOURCE" | "FLUSH_IN_EFFECT_CALLBACK" | "PRIMITIVE_IN_FORBIDDEN_SCOPE" | "NO_OWNER_EFFECT" | "NO_OWNER_BOUNDARY" | "ASYNC_OUTSIDE_LOADING_BOUNDARY" | "INVALID_REFRESH_TARGET" | "INVALID_AFFECTS_TARGET" | "MISSING_EFFECT_FN" | "SYNC_NODE_RECEIVED_ASYNC" | "REACTIVITY_HALTED" | "INVARIANT_VIOLATION" | "HUGE_FAN_OUT" | "HUGE_FAN_IN" | "HOT_SCOPE_RERUNS" | "HOT_SCOPE_TIME" | "WIDE_SCOPE_DEPS" | "UNSTABLE_MEMO_OUTPUT" | "WIDE_WRITE" | "ASYNC_WATERFALL" | "HOT_SCOPE_FANOUT";
17
- export type DiagnosticKind = "strict-read" | "async" | "write" | "lifecycle" | "owner" | "error" | "perf" | "graph";
18
- /** First warning when a node's live edge count reaches this size. */
16
+ export type DiagnosticCode = "STRICT_READ_UNTRACKED" | "PENDING_ASYNC_UNTRACKED_READ" | "PENDING_ASYNC_FORBIDDEN_SCOPE" | "REACTIVE_WRITE_IN_OWNED_SCOPE" | "ACTION_CALLED_IN_OWNED_SCOPE" | "RUN_WITH_DISPOSED_OWNER" | "NO_OWNER_CLEANUP" | "CLEANUP_IN_FORBIDDEN_SCOPE" | "SETTLED_CLEANUP_UNOWNED" | "SETTLE_WALK_UNINITIALIZED_SOURCE" | "FLUSH_IN_EFFECT_CALLBACK" | "PRIMITIVE_IN_FORBIDDEN_SCOPE" | "NO_OWNER_EFFECT" | "NO_OWNER_BOUNDARY" | "ASYNC_OUTSIDE_LOADING_BOUNDARY" | "INVALID_REFRESH_TARGET" | "INVALID_AFFECTS_TARGET" | "MISSING_EFFECT_FN" | "SYNC_NODE_RECEIVED_ASYNC" | "REACTIVITY_HALTED" | "INVARIANT_VIOLATION" | "HUGE_FAN_OUT" | "HUGE_FAN_IN" | "HOT_SCOPE_RERUNS" | "HOT_SCOPE_TIME" | "WIDE_SCOPE_DEPS" | "UNSTABLE_MEMO_OUTPUT" | "WIDE_WRITE" | "ASYNC_WATERFALL" | "HOT_SCOPE_FANOUT" | "SILENT_HOLD" | "LONG_HOLD" | "EFFECT_WRITES_OWN_SOURCE" | "EFFECT_RELAY_TEAR" | "IMMUTABLE_UPDATE_IN_STORE" | "UNSTABLE_LIST_IDENTITY";
17
+ export type DiagnosticKind = "strict-read" | "async" | "write" | "lifecycle" | "owner" | "error" | "perf" | "graph"
18
+ /** Perceived responsiveness: the runtime behaved correctly but the user saw no feedback. */
19
+ | "responsiveness";
20
+ /** First warning when a change reaches (or a pass tracks) this many edges. */
19
21
  export declare const GRAPH_SIZE_WARN_AT = 2000;
20
- /** Repeat the warning at this interval after the first. */
22
+ /** Re-warn once the count has grown by this much since the last warning. */
21
23
  export declare const GRAPH_SIZE_WARN_EVERY = 500;
22
24
  export interface DiagnosticEvent {
23
25
  sequence: number;
@@ -28,6 +30,15 @@ export interface DiagnosticEvent {
28
30
  ownerId?: string;
29
31
  ownerName?: string;
30
32
  nodeName?: string;
33
+ /**
34
+ * Root-first chain of named owners enclosing the subject of the event —
35
+ * component roots as `<Name>`, computations by their `name` option (or
36
+ * the `effect`/`computed` default) — e.g. `["<App>", "<TodoRow>", "effect"]`.
37
+ * Unnamed owners (plain roots) are skipped. Absent when the subject has no
38
+ * named owner at all (a top-level scope, or an unowned primitive — which
39
+ * is usually the finding itself).
40
+ */
41
+ ownerPath?: string[];
31
42
  data?: Record<string, unknown>;
32
43
  }
33
44
  export type DiagnosticListener = (event: DiagnosticEvent) => void;
@@ -40,25 +51,109 @@ export interface Diagnostics {
40
51
  subscribe(listener: DiagnosticListener): () => void;
41
52
  capture(): DiagnosticCapture;
42
53
  /**
43
- * Registers a console footer printed after the first console report of
44
- * each diagnostic code a discovery pointer to deeper guidance (e.g.
45
- * solid-js registers its shipped repair skill). Returning undefined for
46
- * an event suppresses the footer. Passing undefined unregisters and
47
- * resets the once-per-code memory.
54
+ * Records an event on the channel from outside the reactive core a host
55
+ * runtime reporting its own findings (hydration mismatches, server render
56
+ * faults) so consumers see one stream. `subject` locates it like the
57
+ * internal sites do; a host whose owners are not signals' owners passes
58
+ * `ownerPath` on the event instead and it is used as-is.
48
59
  */
49
- setConsoleFooter(footer: ((event: DiagnosticEvent) => string | undefined) | undefined): void;
60
+ emit(event: Omit<DiagnosticEvent, "sequence">, subject?: DiagnosticSubject | null): DiagnosticEvent;
61
+ }
62
+ /**
63
+ * The core's side of attribution: the hook slot an engine installs into, and
64
+ * the interaction frame the rendering runtime opens around event dispatch.
65
+ * The engine itself — "why did this run", costs, holds, feedback — is
66
+ * `@solidjs/signals/attribution`, a separate entry so an observe build pays
67
+ * for it only when something imports it.
68
+ */
69
+ export interface AttributionSlot {
70
+ /**
71
+ * Installs `hooks` as the engine the core reports facts to (`null`
72
+ * uninstalls). One engine at a time; the built-in engine's `enable()` calls
73
+ * this, and an external consumer (devtools) may install its own instead.
74
+ */
75
+ install(hooks: AttributionHooks | null): void;
76
+ /** The installed engine's hooks, or `null` when none is installed. */
77
+ readonly installed: AttributionHooks | null;
78
+ /**
79
+ * Run `fn` as a user interaction's handler: root writes inside stamp it as
80
+ * their origin, and actions/effects/flights it causes carry it. The web
81
+ * runtime wraps every event dispatch in this; custom renderers and test
82
+ * harnesses call it themselves. `fn()` when no engine is installed.
83
+ */
84
+ withInteraction<T>(ref: InteractionRef, fn: () => T): T;
85
+ /**
86
+ * Run `fn` as a declared unit of work — a router's navigation, described
87
+ * by the parametrized route it matched: root writes inside are attributed
88
+ * to it (under the enclosing interaction, if any), so the hold behind the
89
+ * route's data, the re-runs and the verdicts carry the route's name. Any
90
+ * router calls this around its location write; nothing else is
91
+ * router-specific. `fn()` when no engine is installed.
92
+ */
93
+ withOrigin<T>(ref: OriginRef, fn: () => T): T;
94
+ }
95
+ /**
96
+ * The observe tier: the structured channel and the attribution wiring —
97
+ * everything a production observability consumer needs, and nothing that
98
+ * assumes a developer at a console. Present in dev and observe builds
99
+ * (`__OBSERVE__`); `undefined` in prod.
100
+ */
101
+ export interface Observe {
102
+ diagnostics: Diagnostics;
103
+ /** The attribution hook slot and interaction frame — see `AttributionSlot`. */
104
+ attribution: AttributionSlot;
105
+ /**
106
+ * The live node an emitted event was about, when the emitter knew it.
107
+ * Events are serializable records and never carry the node; consumers that
108
+ * run in-process (devtools, the console reporter) look it up here.
109
+ */
110
+ subjectOf(event: DiagnosticEvent): DiagnosticSubject | undefined;
111
+ /**
112
+ * Marks `owner`'s subtree as the observer's own. A consumer that renders
113
+ * inside the app it watches — an APM adapter's panel, devtools — would
114
+ * otherwise see its own effects, stores and holds reported as findings about
115
+ * the app. Under an excluded owner: diagnostics whose subject sits in the
116
+ * subtree are neither delivered nor reported (the entry is still built, so
117
+ * a site that throws its message still throws), and the attribution engine
118
+ * records no runs for its computations. Mark the root as it is created
119
+ * (`createRoot(() => { OBSERVE.exclude(getOwner()!); … })`) and perform
120
+ * writes from outside the graph under it (`runWithOwner`), so the writer's
121
+ * context is excluded too. Irrevocable for the owner's lifetime.
122
+ */
123
+ exclude(owner: Owner): void;
124
+ /** Whether `subject` sits under an excluded owner (itself included). */
125
+ isExcluded(subject: DiagnosticSubject | null | undefined): boolean;
50
126
  }
127
+ /**
128
+ * The dev tier: devtools hooks, graph traversal, and the console face of the
129
+ * diagnostics channel. Present only in dev builds (`__DEV__`).
130
+ */
51
131
  export interface Dev {
52
132
  hooks: DevHooks;
53
- diagnostics: Diagnostics;
54
- /** "Why did this run" re-run attribution — see attribution.ts. */
55
- attribution: Attribution;
56
133
  getChildren: typeof getChildren;
57
134
  getSignals: typeof getSignals;
58
135
  getParent: typeof getParent;
59
136
  getSources: typeof getSources;
60
137
  getObservers: typeof getObservers;
138
+ /** Console face of an emitted event — see `reportDiagnostic`. */
139
+ report(entry: DiagnosticEvent): void;
140
+ /**
141
+ * Registers a console footer appended to the first console report of
142
+ * each diagnostic code — a discovery pointer to deeper guidance (e.g.
143
+ * solid-js registers its shipped repair skill). Reported events carry
144
+ * it as trailing lines of the same console entry; events that surface as
145
+ * a thrown error instead get it as a follow-up line. Returning undefined
146
+ * for an event suppresses the footer. Passing undefined unregisters and
147
+ * resets the once-per-code memory.
148
+ */
149
+ setConsoleFooter(footer: ((event: DiagnosticEvent) => string | undefined) | undefined): void;
61
150
  }
151
+ export declare const OBSERVE: Observe;
152
+ export declare function isExcluded(subject: DiagnosticSubject | null | undefined): boolean;
153
+ /** For engines that cache the verdict per node: is anything excluded at all? */
154
+ export declare function anyExcluded(): boolean;
155
+ /** Was `entry` built for an excluded subject? Once-per-key reporters must not spend their slot on it. */
156
+ export declare function isSuppressed(entry: DiagnosticEvent): boolean;
62
157
  export declare const DEV: Dev;
63
158
  /**
64
159
  * Dev-mode internal consistency check. A failure means the reactive system
@@ -68,14 +163,51 @@ export declare const DEV: Dev;
68
163
  * dev builds so user apps degrade instead of crashing.
69
164
  */
70
165
  export declare function assertInvariant(condition: boolean, name: string, message: string): void;
71
- export declare function emitDiagnostic(event: Omit<DiagnosticEvent, "sequence">): DiagnosticEvent;
166
+ /** Anything a diagnostic can be about: an owner (root, computed, effect) or a signal. */
167
+ export type DiagnosticSubject = Owner | Signal<any> | Computed<any>;
168
+ /**
169
+ * Root-first names of the owners enclosing `subject` (inclusive when the
170
+ * subject is itself a named owner). Signals hop to their registering owner
171
+ * (`_owner`, set by registerGraph). Unnamed owners are skipped so the path
172
+ * reads as the component tree plus the scope: `<App> › <TodoRow> › effect`.
173
+ */
174
+ export declare function ownerPath(subject: DiagnosticSubject | null | undefined): string[] | undefined;
175
+ /**
176
+ * Records a diagnostic on the structured channel (listeners, captures) and
177
+ * returns the entry. `subject` locates it: the current reactive `context` by
178
+ * default (right for the synchronous rule checks — they fire inside the
179
+ * scope that misbehaved); pass the node for scheduler-time findings whose
180
+ * ambient context is the flush, or `null` for events that have no location
181
+ * by nature. An `ownerPath` already on the event wins over the subject walk
182
+ * (hosts whose owners are not signals' owners compute their own). Console
183
+ * output is a separate, dev-tier step — see `reportDiagnostic`.
184
+ */
185
+ export declare function emitDiagnostic(event: Omit<DiagnosticEvent, "sequence">, subject?: DiagnosticSubject | null | undefined): DiagnosticEvent;
186
+ /**
187
+ * The console face of a diagnostic — ONE entry per finding: the message, the
188
+ * owner path (`in <App> › <TodoRow> › effect`) so a human can locate it, the
189
+ * once-per-code footer as trailing lines, and — when the subject is a
190
+ * binding effect the rendering runtime tagged — the element it writes, as a
191
+ * second console argument (hover highlights it, click jumps to Elements).
192
+ * Severity picks the console method. Call sites report the entry
193
+ * `emitDiagnostic` returned so the structured and console channels never
194
+ * disagree. Dev-tier: in an observe build this is a no-op, so wiring paths
195
+ * that both emit and report (graph-size warnings) reach the channel only —
196
+ * production observability never writes to the console.
197
+ */
198
+ export declare function reportDiagnostic(entry: DiagnosticEvent): void;
72
199
  /**
73
200
  * Shared strict-read diagnostics for core read() and the store proxy traps.
74
201
  * Single source for the message text — the #2897 safeguard parity between
75
202
  * memos and stores is exactly these firing identically from both paths.
76
203
  */
77
- export declare function throwPendingUntrackedRead(strictReadLabel: string, fields?: Partial<Omit<DiagnosticEvent, "sequence" | "data">>): never;
78
- export declare function warnStrictReadUntracked(strictReadLabel: string, fields?: Partial<Omit<DiagnosticEvent, "sequence">>): void;
204
+ export declare function throwPendingUntrackedRead(strictReadLabel: string, fields?: Partial<Omit<DiagnosticEvent, "sequence" | "data" | "ownerPath">>): never;
205
+ export declare function warnStrictReadUntracked(strictReadLabel: string, fields?: Partial<Omit<DiagnosticEvent, "sequence" | "ownerPath">>): void;
206
+ /**
207
+ * Observe-tier: stamp a signal with its creating owner so `ownerPath` can
208
+ * locate signal subjects. The per-owner `_signals` list and the devtools
209
+ * `onGraph` hook are dev-tier — the observe build pays one property write.
210
+ */
79
211
  export declare function registerGraph(value: any, owner: Owner | null): void;
80
212
  export declare function clearSignals(node: Owner): void;
81
213
  export declare function getChildren(owner: Owner): Owner[];
@@ -84,12 +216,19 @@ export declare function getParent(owner: Owner): Owner | null;
84
216
  export declare function getSources(computation: Computed<any>): (Signal<any> | Computed<any>)[];
85
217
  export declare function getObservers(node: Signal<any> | Computed<any>): Computed<any>[];
86
218
  /**
87
- * DEV-only: bump live edge counts after a new graph link and warn when a
88
- * node grows an unusually large fan-out (many subscribers on one source) or
89
- * fan-in (many sources on one computation). Repeat-reads that `link()`
90
- * dedupes never reach here. Always-on in dev unlike the opt-in attribution
91
- * engine, a graph-size pathology should surface without asking.
219
+ * Observe-tier: a committed change on `node` is about to re-run `count`
220
+ * subscribers (the notify walk in `insertSubs` counted them as it went
221
+ * fan-out costs exactly one local increment in a loop that already visits
222
+ * every edge, and nothing at link time). Fires from GRAPH_SIZE_WARN_AT up,
223
+ * on the write rather than the link: a fan-out that is never written costs
224
+ * nothing, and one that is re-runs every subscriber this flush. Always-on
225
+ * wherever the channel exists — unlike the opt-in attribution engine, a
226
+ * graph-size pathology should surface without asking.
227
+ */
228
+ export declare function noteFanOut(node: Signal<any> | Computed<any>, count: number): void;
229
+ /**
230
+ * Observe-tier: a recompute pass of `node` tracked `count` distinct sources
231
+ * (its trimmed dep list, walked once at the end of the pass — see recompute;
232
+ * no per-link work, no pass bracket). Fires from GRAPH_SIZE_WARN_AT up.
92
233
  */
93
- export declare function noteGraphLink(dep: Signal<any> | Computed<any>, sub: Computed<any>): void;
94
- /** DEV-only: drop live edge counts when a link is removed. */
95
- export declare function unnoteGraphLink(link: Link): void;
234
+ export declare function noteFanIn(node: Computed<any>, count: number): void;
@@ -1,3 +1,4 @@
1
+ import { type Transition } from "./scheduler.js";
1
2
  import type { Computed, NodeOptions, Owner } from "./types.js";
2
3
  export interface Effect<T> extends Computed<T>, Owner {
3
4
  _effectFn: (val: T, prev: T | undefined) => void | (() => void);
@@ -5,7 +6,13 @@ export interface Effect<T> extends Computed<T>, Owner {
5
6
  _modified: boolean;
6
7
  _prevValue: T | undefined;
7
8
  _type: number;
8
- _boundRunEffect?: () => void;
9
+ _boundRunEffect?: (type: number) => void;
10
+ /** The transaction whose staged view produced `_value` (null = committed
11
+ * view). Effects have one value slot and do not entangle transactions, so
12
+ * a second transaction recomputing the same effect overwrites a value the
13
+ * first one still owes a run for; see the contested-effect arm of recompute
14
+ * (#3322). */
15
+ _valueTransition: Transition | null;
9
16
  }
10
17
  /**
11
18
  * Effects are the leaf nodes of our reactive graph. When their sources change, they are
@@ -2,9 +2,11 @@ import type { Computed } from "./types.js";
2
2
  /** The queue a node belongs to, picked from its own zombie flag. */
3
3
  export declare function queueFor(n: Computed<any>): Heap;
4
4
  /**
5
- * Schedule one subscriber to re-run on the next flush: tracked effects bypass
6
- * the heap and go directly to their effect queue; everything else is inserted
7
- * into its own (zombie-flag-routed) heap with the `_min` cursor pulled down.
5
+ * Schedule one subscriber to re-run on the next flush: inserted into its own
6
+ * (zombie-flag-routed) heap with the `_min` cursor pulled down. Tracked
7
+ * effects ride the heap too the heap visit is their (empty) compute phase,
8
+ * which hands the callback to the user queue once the pass has committed
9
+ * (see GlobalQueue._update, #3291).
8
10
  */
9
11
  export declare function enqueueSub(node: Computed<any>): void;
10
12
  export interface Heap {
@@ -9,5 +9,6 @@ export type { Computed, Disposable, FirewallSignal, Link, Owner, Root, Signal, N
9
9
  export { effect, trackedEffect, type Effect, type TrackedEffect } from "./effect.js";
10
10
  export { action } from "./action.js";
11
11
  export { flush, Queue, GlobalQueue, enforceLoadingBoundary, resetErrorHalt, type IQueue, type QueueCallback } from "./scheduler.js";
12
- export { DEV, type Dev, type DevHooks, type DiagnosticCapture, type DiagnosticCode, type DiagnosticEvent, type DiagnosticKind, type Diagnostics, type DiagnosticSeverity } from "./dev.js";
12
+ export type { AttributionHooks, InteractionRef, NavigationRef, OriginRef } from "./attribution-hooks.js";
13
+ export { DEV, OBSERVE, type AttributionSlot, type Dev, type Observe, type DevHooks, type DiagnosticCapture, type DiagnosticCode, type DiagnosticEvent, type DiagnosticKind, type DiagnosticListener, type Diagnostics, type DiagnosticSeverity, type DiagnosticSubject } from "./dev.js";
13
14
  export * from "./constants.js";
@@ -2,7 +2,7 @@ import type { OptimisticLane } from "./lanes.js";
2
2
  import type { Computed, Signal } from "./types.js";
3
3
  /**
4
4
  * Test-mode invariant checks for the async/transition/lane machinery.
5
- * Catalog and rationale: packages/signals/INTERNALS-ASYNC-STATE.md.
5
+ * Catalog and rationale: packages/signals/docs/INTERNALS-ASYNC-STATE.md.
6
6
  *
7
7
  * These are implementation self-consistency checks, not semantic rules: a
8
8
  * violation means the reactive system contradicted itself.
@@ -24,6 +24,23 @@ export declare function getOrCreateLane(signal: Signal<any>): OptimisticLane;
24
24
  * Union-find: find the root lane.
25
25
  */
26
26
  export declare function findLane(lane: OptimisticLane): OptimisticLane;
27
+ /**
28
+ * Is the lane held? `_pendingAsync` records the async the lane OWNS (derived
29
+ * under it); a transaction's reporter map records the async a render effect
30
+ * OBSERVED pending with no boundary taking it (INV-3, the one registration
31
+ * site). A hold needs both — the same rule the transaction itself uses, so a
32
+ * memo nobody renders, or one a fallback-showing boundary caught, cannot tear
33
+ * a frame and holds nothing (#3289). An orphan lane has no observation record
34
+ * and never holds.
35
+ *
36
+ * The observation is looked up per NODE, in whichever live transaction
37
+ * recorded it — not in this lane's transaction. Lanes merge across
38
+ * transactions (#2912: ownership never travels through lanes), so after a
39
+ * merge the root's transaction holds the observations of only one member;
40
+ * the async the other member's transaction observed must hold the merged
41
+ * reveal just the same (A15 for lanes, #3335).
42
+ */
43
+ export declare function laneHeld(lane: OptimisticLane): boolean;
27
44
  /**
28
45
  * Merge two lanes when their dependency graphs overlap.
29
46
  */
@@ -8,8 +8,17 @@ export declare const zombieQueue: Heap;
8
8
  export declare let clock: number;
9
9
  export declare let activeTransition: Transition | null;
10
10
  export declare let projectionWriteActive: boolean;
11
+ /** > 0 while an action's generator body is on the stack (the synchronous
12
+ * slice between yields). Maintained by action.ts around `it.next()`. */
13
+ export declare let actionStepDepth: number;
14
+ export declare function enterActionStep(): void;
15
+ export declare function exitActionStep(): void;
11
16
  export declare let _hitUnhandledAsync: boolean;
12
- export declare function resetUnhandledAsync(): void;
17
+ /**
18
+ * Consume the unhandled-async hit. Returns whether this is the first report
19
+ * of the current enforcement window — the caller warns only then.
20
+ */
21
+ export declare function resetUnhandledAsync(): boolean;
13
22
  /**
14
23
  * Toggles the dev-mode "must be inside a `<Loading>` boundary" enforcement
15
24
  * window. Only `render()` calls this — wrapping the initial mount so that a
@@ -39,6 +48,11 @@ export interface Transition {
39
48
  _queueStash: QueueStub;
40
49
  _done: boolean | Transition;
41
50
  _gatedSubs: Set<Computed<any>>;
51
+ /** Effects whose single value slot was written under this transaction AND
52
+ * another live one (#3322). Re-dirtied at commit, ahead of the effect
53
+ * phase, so the run publishes a value derived from the committed world
54
+ * rather than whichever transaction's staged view wrote last. */
55
+ _contested: Computed<any>[] | null;
42
56
  }
43
57
  /**
44
58
  * Flip-entanglement (#3164 follow-up): `until()` is a declaration of
@@ -127,14 +141,40 @@ export declare class GlobalQueue extends Queue {
127
141
  static _drainPatchOptimistic: (() => void) | null;
128
142
  static _gatedRead: ((el: Signal<any>, owner: OptimisticNode, c: Computed<any>) => boolean) | null;
129
143
  static _laneSuspends: ((owner: OptimisticNode) => boolean) | null;
144
+ /** Is the node routed through a LIVE lane (`resolveLane`)? read()'s reveal
145
+ * carve-out asks before showing a foreign-held pending node's committed
146
+ * value: a lane-derived flight's inputs are already revealed through the
147
+ * lane (#3334). Gated on CONFIG_HAS_LANE, which only the engine sets. */
148
+ static _laneLive: ((el: Computed<any>) => boolean) | null;
130
149
  static _laneReadsCommitted: ((el: OptimisticNode, owner: OptimisticNode, c: Computed<any>) => boolean) | null;
131
150
  static _recomputeLane: ((el: Computed<any>, own: boolean) => OptimisticLane | null | false) | null;
132
151
  static _laneAsyncPending: ((el: Computed<any>) => void) | null;
133
- /** Authoritative-view reader wakeup (until()): installed at first until() call.
134
- * Call sites are gated by CONFIG_AUTHORITATIVE_OBSERVED, which only until()'s
135
- * carve-out read can set, so `!` invocations are safe once the gate holds. */
152
+ /** Authoritative-view reader wakeup: installed by until() and refresh() before
153
+ * their first read. Call sites are gated by CONFIG_AUTHORITATIVE_OBSERVED, which
154
+ * only such a reader's carve-out read can set, so `!` invocations are safe once
155
+ * the gate holds (#3303). */
136
156
  static _notifyAuthoritativeObservers: ((el: Signal<any> | Computed<any>) => void) | null;
137
157
  static _laneAsyncSettled: ((el: Computed<any>) => void) | null;
158
+ /** A18 supersession (#3331): own-source truth `value` landed under an active
159
+ * override. The engine decides whether the graph re-derives — the value
160
+ * differs from the override and is not a stale (older-action) answer (mark
161
+ * the node, demote its lane cascade, notify), or returns to it after an
162
+ * earlier differing arrival (clear the mark, notify) — and owns the
163
+ * authoritative-observer wake for a silent confirm. Installed with the
164
+ * optimistic engine; only reachable on a node that has an override. */
165
+ static _supersedeOverride: ((el: Signal<any> | Computed<any>, value: unknown) => void) | null;
166
+ /** read()'s value for a TRACKED reader of a superseded node (#3331): the
167
+ * staged truth, unless the reader is a stale (render) reader of another
168
+ * transaction — then the displayed override, as it keeps a foreign
169
+ * transaction's committed value over its staged write. */
170
+ static _supersededRead: ((el: Signal<any> | Computed<any>) => unknown) | null;
171
+ /** setSignal's authoritative (projection-write) landing on an override-
172
+ * covered node (#3331 store twin): stage the truth for its transaction's
173
+ * commit whatever its relation to the committed value — a landing equal to
174
+ * committed still differs from the override — then _supersedeOverride
175
+ * decides. Installed with the optimistic engine; only reachable on a node
176
+ * that has an override. */
177
+ static _landOnOverride: (<T>(el: Signal<T> | Computed<T>, v: T | ((prev: T) => T)) => T) | null;
138
178
  static _trackOptimisticStore: ((store: any) => void) | null;
139
179
  flush(): void;
140
180
  notify(node: Computed<any>, mask: number, flags: number, error?: any): boolean;
@@ -149,6 +189,21 @@ export declare let reaskArmed: boolean;
149
189
  export declare let notifyEpoch: number;
150
190
  export declare function bumpNotifyEpoch(): void;
151
191
  export declare function armReaskClear(): void;
192
+ /** Provenance of the work currently running (A18 supersession, #3331): the
193
+ * invocation sequence of the action whose ambient window this is — set by
194
+ * action() for each slice; the flush that ends the window clears it — or,
195
+ * inside an async landing, the sequence captured when that flight was
196
+ * registered (asyncWrite sets it for the landing's synchronous propagation,
197
+ * so a sync recompute downstream of the landing — an optimistic wrapper over
198
+ * the async source — derives under the flight's provenance, and flights it
199
+ * registers inherit it). 0 is mainline: no action, always the current
200
+ * question. An override stamps this at its write (`_overrideStamp`); an
201
+ * answer whose flight an OLDER action issued is a stale question the user
202
+ * has since changed — it holds silently to commit instead of superseding. A
203
+ * slow source must not leak back in over a newer intent. Transactions merge,
204
+ * so the transition object cannot say WHICH action asked; this can. */
205
+ export declare let origin: number;
206
+ export declare function setOrigin(seq: number): number;
152
207
  export declare function insertSubs(node: Signal<any> | Computed<any>, optimistic?: boolean): void;
153
208
  export declare let storeCommitHook: (() => void) | null;
154
209
  export declare function setStoreCommitHook(fn: () => void): void;
@@ -215,6 +270,16 @@ export declare function flush<T>(fn: () => T): T;
215
270
  * initTransition; it is a plain batch until then. */
216
271
  export declare function createTransition(): Transition;
217
272
  export declare function currentTransition(transition: Transition): Transition;
273
+ /**
274
+ * The live transition blocked on `source` — the one whose render reader
275
+ * observed it pending (INV-3 records the observation in whichever transaction
276
+ * was active when the reader was notified). The observation is a fact about
277
+ * the node, so a hold check must not assume it was recorded in the transaction
278
+ * it happens to hold — lanes merge across transactions (#2912), and a merged
279
+ * root's transaction knows nothing of the async its members' transactions
280
+ * observed (#3335). Null when nobody is waiting.
281
+ */
282
+ export declare function waitingTransition(source: Computed<any>): Transition | null;
218
283
  export declare function setActiveTransition(transition: Transition | null): void;
219
284
  export declare function runInTransition<T>(transition: Transition, fn: () => T): T;
220
285
  /** Run `fn` with `transition` as BOTH the ambient transaction and the
@@ -68,6 +68,16 @@ export interface NodeExtension {
68
68
  * layer's STORE_OPTIMISTIC_OWNERS stamps (#2899). `null` = ambient write.
69
69
  */
70
70
  _overrideOwner: Transition | null | undefined;
71
+ /** `clock` at the active override's write. A sync recompute in the same
72
+ * tick derives from inputs that predate the override and does not
73
+ * supersede it (A18 supersession ordering, #3331). */
74
+ _overrideTime: number;
75
+ /** Provenance of the active override's write: the scheduler's `origin` (the
76
+ * asking action's invocation sequence; 0 = mainline). An arriving answer
77
+ * whose flight an older action issued asked a question the override has
78
+ * since changed: it holds to commit instead of superseding (A18
79
+ * supersession provenance, #3331). */
80
+ _overrideStamp: number;
71
81
  _optimisticLane: OptimisticLane | undefined;
72
82
  _pendingSignal: Signal<boolean> | undefined;
73
83
  _latestValueComputed: Computed<any> | undefined;
@@ -112,13 +122,19 @@ export interface NodeExtension {
112
122
  export interface RawSignal<T> {
113
123
  _subs: Link | null;
114
124
  _subsTail: Link | null;
125
+ _value: T;
115
126
  /**
116
- * DEV-only live subscriber count. Maintained by `link`/`unlinkSubs` for
117
- * graph-size diagnostics; undefined in production.
127
+ * Observe-tier label (`name` option, or the node kind: `signal`,
128
+ * `computed`, `effect`…). A slot in the observe/dev literals — never a
129
+ * post-construction write — and absent from the prod literals entirely.
118
130
  */
119
- _subCount?: number;
120
- _value: T;
121
131
  _name?: string;
132
+ /**
133
+ * Observe-tier: the owner in scope when a user-facing signal was created
134
+ * (`registerGraph`), so diagnostics about the signal get an owner path.
135
+ * A slot in the observe/dev `signal()` literal; absent from prod.
136
+ */
137
+ _owner?: Owner | null;
122
138
  _equals: false | ((a: T, b: T) => boolean);
123
139
  _config: number;
124
140
  _time: number;
@@ -137,7 +153,10 @@ export interface RawSignal<T> {
137
153
  }
138
154
  export interface FirewallSignal<T> extends RawSignal<T> {
139
155
  _firewall: Computed<any>;
156
+ /** Doubly-linked child chain on the firewall's extension (`_x._child` is
157
+ * the head): released leaves unlink in O(1) (#3351). */
140
158
  _nextChild: FirewallSignal<unknown> | null;
159
+ _prevChild: FirewallSignal<unknown> | null;
141
160
  }
142
161
  export type Signal<T> = RawSignal<T> | FirewallSignal<T>;
143
162
  export interface Owner {
@@ -156,15 +175,16 @@ export interface Owner {
156
175
  _prevSibling: Owner | null;
157
176
  /** Cold extension — see NodeExtension (owners use the zombie-pair slots). */
158
177
  _x: NodeExtension | null;
178
+ /**
179
+ * Observe-tier label: the `name` option, the node kind (`computed`,
180
+ * `effect`…), or the component label the rendering layer writes on a root
181
+ * (`<App>`). A slot in the observe/dev literals; absent from prod.
182
+ */
183
+ _name?: string;
159
184
  }
160
185
  export interface Computed<T> extends RawSignal<T>, Owner {
161
186
  _deps: Link | null;
162
187
  _depsTail: Link | null;
163
- /**
164
- * DEV-only live source count. Maintained by `link`/`unlinkSubs` for
165
- * graph-size diagnostics; undefined in production.
166
- */
167
- _depCount?: number;
168
188
  /** Recompute-pass counter; bumped when dep revalidation starts. */
169
189
  _depGen: number;
170
190
  _flags: number;
@@ -1,7 +1,14 @@
1
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 } from "./core/index.js";
2
- import { type Dev } from "./core/index.js";
2
+ import { type Dev, type Observe } from "./core/index.js";
3
+ /**
4
+ * Observe tier (diagnostics channel, attribution hook slot + interaction
5
+ * frame): dev and observe builds. The attribution engine itself is the
6
+ * `@solidjs/signals/attribution` entry.
7
+ */
8
+ export declare const OBSERVE: Observe | undefined;
9
+ /** Dev tier (devtools hooks, graph traversal, console reporting): dev builds only. */
3
10
  export declare const DEV: Dev | undefined;
4
- export type { Owner, Context, ContextRecord, IQueue, ExternalSourceFactory, ExternalSource, ExternalSourceConfig, Refreshable, Dev, DevHooks, DiagnosticCapture, DiagnosticCode, DiagnosticEvent, DiagnosticKind, Diagnostics, DiagnosticSeverity } from "./core/index.js";
11
+ export type { Owner, Context, ContextRecord, IQueue, ExternalSourceFactory, ExternalSource, ExternalSourceConfig, Refreshable, AttributionHooks, AttributionSlot, InteractionRef, NavigationRef, OriginRef, Dev, Observe, DevHooks, DiagnosticCapture, DiagnosticCode, DiagnosticEvent, DiagnosticKind, DiagnosticListener, Diagnostics, DiagnosticSeverity, DiagnosticSubject } from "./core/index.js";
5
12
  export { createSignal, createMemo, createEffect, createRenderEffect, createTrackedEffect, createReaction, createOptimistic, refresh, resolve, until, onSettled, onCleanup } from "./signals.js";
6
13
  export type { Truthy, UntilOptions, Accessor, SourceAccessor, Setter, Signal, ComputeFunction, EffectFunction, EffectBundle, EffectOptions, SignalOptions, MemoOptions, NoInfer } from "./signals.js";
7
14
  export { affects } from "./affects.js";
@@ -47,6 +47,8 @@ export declare function mapArray<Item, MappedItem>(list: Accessor<Maybe<readonly
47
47
  fallback?: Accessor<any>;
48
48
  name?: string;
49
49
  }): Accessor<MappedItem[]>;
50
+ /** @internal */
51
+ export declare function __smallMoveHits(): number;
50
52
  /**
51
53
  * Reactively renders a callback `count` times, reusing previously-rendered
52
54
  * entries when only the count changes. Underlying helper for `<Repeat>`.
@@ -399,6 +399,16 @@ export declare function createRenderEffect<T>(compute: ComputeFunction<undefined
399
399
  * Creates a tracked reactive effect where dependency tracking and side effects happen
400
400
  * in the same scope.
401
401
  *
402
+ * @deprecated Do not use in new code. For a side effect that follows reactive
403
+ * state, use `createEffect(compute, effect)` — it separates tracking from the
404
+ * side effect, knows its dependencies before it runs, and participates in
405
+ * async and transitions. For one-time DOM work after render (measuring,
406
+ * attaching third-party widgets to a ref), use `onSettled`. Tracking from
407
+ * inside the effect phase — the only thing this primitive adds — is retained
408
+ * solely to ease 1.x migration: it runs beside user-effect callbacks after
409
+ * values commit, never holds a transition, and cannot observe a write staged
410
+ * earlier in the same flush by a signal it has not read yet.
411
+ *
402
412
  * WARNING: Because tracking and effects happen in the same scope, this primitive
403
413
  * may run multiple times for a single change or show tearing (reading inconsistent
404
414
  * state). Use only when dynamic subscription patterns require same-scope tracking.
@@ -1,18 +1,16 @@
1
1
  export type { Store, StoreReturn, ProjectionStoreReturn, StoreSetter, StoreNode, StoreOptions, ProjectionOptions, NotWrappable, SolidStore } from "./store.js";
2
2
  export type { Merge, Omit } from "./utils.js";
3
3
  export { isWrappable, $TRACK, $PROXY, $TARGET } from "./store.js";
4
+ export { mergeSources } from "./utils.js";
4
5
  import type { NoFn, ProjectionOptions, Store, StoreOptions, StoreSetter } from "./store.js";
5
6
  import type { Refreshable } from "../core/index.js";
6
7
  export { createProjectionNext as createProjection } from "./next/projection.js";
7
- export { registerPatch, registerRowOps, registerSlotPatchNext as registerSlotPatch, patchableRaw } from "./next/patch.js";
8
8
  export { storeIsShallow, storeHasFamily, storeHasOptimisticFamily } from "./next/store.js";
9
9
  export { createOptimisticStoreNext as createOptimisticStore } from "./next/optimistic.js";
10
- /** Public createStore: plain form `(init, options?)` and derived writable
10
+ /** Public createStore: plain form `(initialValue, options?)` and derived writable
11
11
  * form `(fn, seed, options?)`. */
12
- export declare function createStore<T extends object = {}>(store: NoFn<T> | Store<NoFn<T>>, options?: StoreOptions & {
13
- shallow?: boolean;
14
- }): [get: Store<T>, set: StoreSetter<T>];
15
- export declare function createStore<T extends object = {}>(fn: (store: T) => void | T | Promise<void | T> | AsyncIterable<void | T>, store: Partial<T> | Store<NoFn<T>>, options?: ProjectionOptions): [get: Refreshable<Store<T>>, set: StoreSetter<T>];
12
+ export declare function createStore<T extends object = {}>(initialValue: NoFn<T> | Store<NoFn<T>>, options?: StoreOptions): [get: Store<T>, set: StoreSetter<T>];
13
+ 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>];
16
14
  export declare function reconcile<T extends U, U>(value: T, key?: string | ((item: NonNullable<any>) => any) | null): (state: U) => T;
17
15
  export declare function snapshot<T>(value: T): T;
18
16
  export declare function deep<T>(value: T): T;
@@ -1,5 +1,6 @@
1
+ import { type Refreshable } from "../../core/index.js";
1
2
  import { type Transition } from "../../core/scheduler.js";
2
- import { type NoFn, type ProjectionOptions, type Store, type StoreSetter } from "../store.js";
3
+ import { type NoFn, type ProjectionOptions, type Store, type StoreOptions, type StoreSetter } from "../store.js";
3
4
  import type { StoreNextTarget } from "./target.js";
4
5
  /** #3164 fold: a stamped truth is HELD (masked from ordinary readers until
5
6
  * the reveal) only while its transition is live AND retaining optimism —
@@ -8,7 +9,8 @@ import type { StoreNextTarget } from "./target.js";
8
9
  * staged values to converge (normal speculation). Resolves merges first:
9
10
  * merge unions optimistic nodes/stores into the target. */
10
11
  export declare function transitionHoldsOptimism(transition: Transition): boolean;
11
- export declare function createOptimisticStoreNext<T extends object = {}>(first: T | ((store: T) => void | T | Promise<void | T> | AsyncIterable<void | T>), second?: NoFn<T> | Store<NoFn<T>>, options?: ProjectionOptions): [get: Store<T>, set: StoreSetter<T>];
12
+ export declare function createOptimisticStoreNext<T extends object = {}>(initialValue: NoFn<T> | Store<NoFn<T>>, options?: StoreOptions): [get: Store<T>, set: StoreSetter<T>];
13
+ export declare function createOptimisticStoreNext<T extends object = {}>(fn: (draft: T) => void | T | Promise<void | T> | AsyncIterable<void | T>, seed: Partial<T> | Store<NoFn<T>>, options?: ProjectionOptions): [get: Refreshable<Store<T>>, set: StoreSetter<T>];
12
14
  /** Diff the draft against the current OPTIMISTIC VIEW (committed + active
13
15
  * overrides — the same view the draft was seeded from) and emit engine writes
14
16
  * for exactly the changed keys. Visible-view diffing keeps no-op writes from
@@ -1,17 +1,10 @@
1
- import type { RowOps } from "./patch.js";
2
- import { type StoreNextTarget } from "./target.js";
3
1
  type KeyFn = (item: any) => any;
4
2
  export declare function reconcileNextState(value: any, state: any, key: string | KeyFn | null | undefined, replace?: boolean): void;
3
+ /** Setter-channel row ops (the fold site calls this for array targets with
4
+ * ops consumers): structural mutation through the setter — push/splice/index
5
5
  /** Key equality for EVERY key comparison in this module (re-audit 2, P1-5):
6
- * SameValueZero, matching the Map-based matchers (buildRowOps, the adoption
7
- * window) — NaN keys are equal to themselves, so aligned NaN rows stay
8
- * aligned in the prefix walk instead of forever misaligning. Adoption and
9
- * row ops MUST agree on key equality or retained DOM rows go stale. */
6
+ * SameValueZero, matching the adoption window's Map-based matcher NaN keys
7
+ * are equal to themselves, so aligned NaN rows stay aligned in the prefix
8
+ * walk instead of forever misaligning. */
10
9
  export declare function sameKey(a: any, b: any): boolean;
11
- export declare function emitSetterRowOps(t: StoreNextTarget, prevRows: any[], nextRows: any[]): void;
12
- /** Identity-keyed structural diff, returned rather than emitted: shared by
13
- * the setter channel (regular queue) and the OPTIMISTIC write channel (lane
14
- * queue) — same retention semantics, different dispatch timing. Returns
15
- * null when the lists are identity-aligned (no structure changed). */
16
- export declare function buildIdentityRowOps(prevRows: any[], nextRows: any[]): RowOps | null;
17
10
  export {};