@solidjs/signals 2.0.0-rc.1 → 2.0.0-rc.11

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 (150) hide show
  1. package/dist/dev-shared.js +7155 -0
  2. package/dist/dev.attribution.js +3307 -0
  3. package/dist/dev.js +5765 -4496
  4. package/dist/observe/affects.js +129 -0
  5. package/dist/observe/attribution.js +7 -0
  6. package/dist/observe/boundaries.js +793 -0
  7. package/dist/observe/core/action.js +177 -0
  8. package/dist/observe/core/async.js +849 -0
  9. package/dist/observe/core/attribution-costs.js +66 -0
  10. package/dist/observe/core/attribution-feedback.js +280 -0
  11. package/dist/observe/core/attribution-hooks.js +83 -0
  12. package/dist/observe/core/attribution-queries.js +43 -0
  13. package/dist/observe/core/attribution.js +2904 -0
  14. package/dist/observe/core/constants.js +283 -0
  15. package/dist/{types-cjs/core/context.d.cts → observe/core/context.js} +37 -12
  16. package/dist/observe/core/core.js +1999 -0
  17. package/dist/observe/core/dev.js +343 -0
  18. package/dist/observe/core/effect.js +200 -0
  19. package/dist/observe/core/error-hooks.js +71 -0
  20. package/dist/observe/core/error.js +80 -0
  21. package/dist/observe/core/external.js +98 -0
  22. package/dist/observe/core/graph.js +155 -0
  23. package/dist/observe/core/heap.js +147 -0
  24. package/dist/observe/core/invariants.js +45 -0
  25. package/dist/observe/core/lanes.js +205 -0
  26. package/dist/observe/core/optimistic.js +669 -0
  27. package/dist/observe/core/owner.js +353 -0
  28. package/dist/observe/core/scheduler.js +1561 -0
  29. package/dist/observe/core/verdict.js +674 -0
  30. package/dist/observe/index.js +59 -0
  31. package/dist/observe/map.js +507 -0
  32. package/dist/observe/signals.js +731 -0
  33. package/dist/observe/store/index.js +44 -0
  34. package/dist/observe/store/next/optimistic.js +717 -0
  35. package/dist/observe/store/next/projection.js +266 -0
  36. package/dist/observe/store/next/reconcile.js +375 -0
  37. package/dist/observe/store/next/store.js +2480 -0
  38. package/dist/observe/store/next/target.js +51 -0
  39. package/dist/observe/store/store.js +331 -0
  40. package/dist/observe/store/storePath.js +103 -0
  41. package/dist/observe/store/utils.js +1070 -0
  42. package/dist/prod/affects.js +10 -9
  43. package/dist/prod/attribution.js +45 -0
  44. package/dist/prod/boundaries.js +388 -178
  45. package/dist/prod/core/action.js +65 -37
  46. package/dist/prod/core/async.js +378 -163
  47. package/dist/prod/core/attribution-hooks.js +3 -0
  48. package/dist/prod/core/constants.js +186 -1
  49. package/dist/prod/core/context.js +10 -16
  50. package/dist/prod/core/core.js +1546 -416
  51. package/dist/prod/core/dev.js +18 -1
  52. package/dist/prod/core/effect.js +119 -79
  53. package/dist/prod/core/error-hooks.js +71 -0
  54. package/dist/prod/core/error.js +13 -1
  55. package/dist/prod/core/external.js +4 -4
  56. package/dist/prod/core/graph.js +105 -54
  57. package/dist/prod/core/heap.js +72 -65
  58. package/dist/prod/core/invariants.js +3 -2
  59. package/dist/prod/core/lanes.js +117 -52
  60. package/dist/prod/core/optimistic.js +500 -104
  61. package/dist/prod/core/owner.js +131 -84
  62. package/dist/prod/core/scheduler.js +1012 -241
  63. package/dist/prod/core/verdict.js +417 -112
  64. package/dist/prod/index.js +20 -8
  65. package/dist/prod/map.js +355 -171
  66. package/dist/prod/signals.js +363 -32
  67. package/dist/prod/store/index.js +2 -0
  68. package/dist/prod/store/next/optimistic.js +530 -197
  69. package/dist/prod/store/next/projection.js +142 -57
  70. package/dist/prod/store/next/reconcile.js +149 -103
  71. package/dist/prod/store/next/store.js +1470 -346
  72. package/dist/prod/store/next/target.js +40 -9
  73. package/dist/prod/store/store.js +23 -19
  74. package/dist/prod/store/utils.js +997 -130
  75. package/dist/types/attribution.d.ts +19 -0
  76. package/dist/types/attribution.prod.d.ts +22 -0
  77. package/dist/types/boundaries.d.ts +78 -5
  78. package/dist/types/core/action.d.ts +12 -5
  79. package/dist/types/core/async.d.ts +3 -1
  80. package/dist/types/core/attribution-costs.d.ts +35 -0
  81. package/dist/types/core/attribution-feedback.d.ts +133 -0
  82. package/dist/types/core/attribution-hooks.d.ts +304 -0
  83. package/dist/types/core/attribution-queries.d.ts +24 -0
  84. package/dist/types/core/attribution.d.ts +892 -0
  85. package/dist/types/core/constants.d.ts +179 -0
  86. package/dist/types/core/core.d.ts +299 -25
  87. package/dist/types/core/dev.d.ts +421 -8
  88. package/dist/types/core/effect.d.ts +8 -1
  89. package/dist/types/core/error-hooks.d.ts +71 -0
  90. package/dist/types/core/error.d.ts +9 -0
  91. package/dist/types/core/graph.d.ts +23 -0
  92. package/dist/types/core/heap.d.ts +5 -3
  93. package/dist/types/core/index.d.ts +6 -3
  94. package/dist/types/core/invariants.d.ts +5 -1
  95. package/dist/types/core/lanes.d.ts +51 -19
  96. package/dist/types/core/owner.d.ts +15 -3
  97. package/dist/types/core/scheduler.d.ts +252 -1
  98. package/dist/types/core/types.d.ts +124 -41
  99. package/dist/types/index.d.ts +18 -5
  100. package/dist/types/map.d.ts +2 -0
  101. package/dist/types/signals.d.ts +145 -13
  102. package/dist/types/store/index.d.ts +7 -6
  103. package/dist/types/store/next/optimistic.d.ts +18 -13
  104. package/dist/types/store/next/projection.d.ts +5 -2
  105. package/dist/types/store/next/reconcile.d.ts +7 -0
  106. package/dist/types/store/next/store.d.ts +83 -11
  107. package/dist/types/store/next/target.d.ts +108 -11
  108. package/dist/types/store/store.d.ts +20 -11
  109. package/dist/types/store/utils.d.ts +188 -0
  110. package/package.json +31 -26
  111. package/dist/node.cjs +0 -8137
  112. package/dist/types/store/optimistic.d.ts +0 -45
  113. package/dist/types/store/projection.d.ts +0 -70
  114. package/dist/types/store/reconcile.d.ts +0 -46
  115. package/dist/types-cjs/affects.d.cts +0 -47
  116. package/dist/types-cjs/boundaries.d.cts +0 -175
  117. package/dist/types-cjs/core/action.d.cts +0 -64
  118. package/dist/types-cjs/core/async.d.cts +0 -21
  119. package/dist/types-cjs/core/constants.d.cts +0 -71
  120. package/dist/types-cjs/core/core.d.cts +0 -156
  121. package/dist/types-cjs/core/dev.d.cts +0 -64
  122. package/dist/types-cjs/core/effect.d.cts +0 -30
  123. package/dist/types-cjs/core/error.d.cts +0 -47
  124. package/dist/types-cjs/core/external.d.cts +0 -15
  125. package/dist/types-cjs/core/graph.d.cts +0 -5
  126. package/dist/types-cjs/core/heap.d.cts +0 -22
  127. package/dist/types-cjs/core/index.d.cts +0 -13
  128. package/dist/types-cjs/core/invariants.d.cts +0 -59
  129. package/dist/types-cjs/core/lanes.d.cts +0 -56
  130. package/dist/types-cjs/core/optimistic.d.cts +0 -6
  131. package/dist/types-cjs/core/owner.d.cts +0 -124
  132. package/dist/types-cjs/core/scheduler.d.cts +0 -172
  133. package/dist/types-cjs/core/types.d.cts +0 -148
  134. package/dist/types-cjs/core/verdict.d.cts +0 -2
  135. package/dist/types-cjs/index.d.cts +0 -10
  136. package/dist/types-cjs/map.d.cts +0 -69
  137. package/dist/types-cjs/package.json +0 -3
  138. package/dist/types-cjs/signals.d.cts +0 -624
  139. package/dist/types-cjs/store/index.d.cts +0 -19
  140. package/dist/types-cjs/store/next/optimistic.d.cts +0 -20
  141. package/dist/types-cjs/store/next/projection.d.cts +0 -24
  142. package/dist/types-cjs/store/next/reconcile.d.cts +0 -3
  143. package/dist/types-cjs/store/next/store.d.cts +0 -71
  144. package/dist/types-cjs/store/next/target.d.cts +0 -99
  145. package/dist/types-cjs/store/optimistic.d.cts +0 -45
  146. package/dist/types-cjs/store/projection.d.cts +0 -70
  147. package/dist/types-cjs/store/reconcile.d.cts +0 -46
  148. package/dist/types-cjs/store/store.d.cts +0 -138
  149. package/dist/types-cjs/store/storePath.d.cts +0 -58
  150. package/dist/types-cjs/store/utils.d.cts +0 -74
@@ -1,3 +1,5 @@
1
+ import { type InteractionRef, type NavigationRef } from "./attribution-hooks.js";
2
+ import type { ChangeOrigin, CreateEvent, EffectRunEvent, FallbackEvent, FlightEvent, FlushEvent, GraphEvent, HoldEvent, InteractionEvent, NavigationEvent, RerunEvent } from "./attribution.js";
1
3
  import type { Computed, Owner, Signal } from "./types.js";
2
4
  export interface DevHooks {
3
5
  onOwner?: (owner: Owner) => void;
@@ -5,9 +7,27 @@ export interface DevHooks {
5
7
  onUpdate?: () => void;
6
8
  onStoreNodeUpdate?: (state: any, property: PropertyKey, value: any, prev: any) => void;
7
9
  }
8
- export type DiagnosticSeverity = "warn" | "error";
9
- 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" | "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";
10
- export type DiagnosticKind = "strict-read" | "async" | "write" | "lifecycle" | "owner" | "error";
10
+ /**
11
+ * `info` is the advisory tier: a structural fact worth surfacing that is not
12
+ * presumptively a bug (e.g. a 2-deep sequential fetch chain, which may be an
13
+ * intrinsic data dependency). Budget/assertion consumers should treat only
14
+ * `warn`/`error` as failures unless they opt in to `info`.
15
+ */
16
+ export type DiagnosticSeverity = "info" | "warn" | "error";
17
+ export type DiagnosticCode = "STRICT_READ_UNTRACKED" | "PENDING_ASYNC_UNTRACKED_READ" | "PENDING_ASYNC_FORBIDDEN_SCOPE" | "REACTIVE_WRITE_IN_OWNED_SCOPE" | "ASYNC_STORE_SETTER" | "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" | "LOADING_ON_OUTSIDE_HOLD" | "INVALID_REFRESH_TARGET" | "INVALID_AFFECTS_TARGET" | "MISSING_EFFECT_FN" | "SYNC_NODE_RECEIVED_ASYNC" | "UNTRACKED_READ_AFTER_AWAIT" | "REACTIVITY_HALTED" | "INVARIANT_VIOLATION" | "HUGE_FAN_OUT" | "HUGE_FAN_IN" | "GRAPH_GROWTH" | "HOT_SCOPE_RERUNS" | "HOT_SCOPE_TIME" | "WIDE_SCOPE_DEPS" | "UNSTABLE_MEMO_OUTPUT" | "WASTED_RECOMPUTE" | "ASYNC_WATERFALL" | "HOT_SCOPE_FANOUT" | "SILENT_HOLD" | "LONG_HOLD" | "UNTRACKED_ASYNC_HANDLER" | "ABANDONED_FLIGHTS" | "FALLBACK_FLASH" | "STACKED_HOLDS" | "OPTIMISTIC_REVERTED" | "EFFECT_WRITES_OWN_SOURCE" | "EFFECT_RELAY_TEAR" | "IMMUTABLE_UPDATE_IN_STORE" | "UNSTABLE_LIST_IDENTITY" | "SSR_RENDER_ERROR_CONTAINED" | "SSR_SUBTREE_ABANDONED" | "SSR_STREAM_ABANDONED" | "SSR_CLIENT_CONTENT_MASKED" | "LATE_HEADER_WRITE" | "SERVER_ERROR_SANITIZED" | "SSR_BOUNDARY_WATERFALL" | "SSR_UNDECLARED_LIVE_SOURCE" | "SERVER_WRITE" | "REVEAL_IN_RENDER_TO_STRING" | "LAZY_ASSET_UNMAPPED" | "PRELOAD_DESCRIPTOR_INVALID" | "HEAD_TAG_INVALID" | "UNRECOGNIZED_INSERT_VALUE" | "UNSCOPED_HOLE_ALLOCATED_IDS" | "BEHAVIOR_CLAIM_DROPPED" | "FRAME_MARKER_CORRUPTED" | "DYNAMIC_ASYNC_COMPONENT";
18
+ export type DiagnosticKind = "strict-read" | "async" | "write" | "lifecycle" | "owner" | "error" | "perf" | "graph"
19
+ /** Perceived responsiveness: the runtime behaved correctly but the user saw no feedback. */
20
+ | "responsiveness"
21
+ /** Server rendering: boundaries, fragments, the stream, the server-function wire. */
22
+ | "ssr"
23
+ /** The response head: `<head>` tags, preload descriptors, HTTP headers. */
24
+ | "head"
25
+ /** The renderer's insert positions, on either platform: a value it has no rendering for. */
26
+ | "render";
27
+ /** First warning when a change reaches (or a pass tracks) this many edges. */
28
+ export declare const GRAPH_SIZE_WARN_AT = 2000;
29
+ /** Re-warn once the count has grown by this much since the last warning. */
30
+ export declare const GRAPH_SIZE_WARN_EVERY = 500;
11
31
  export interface DiagnosticEvent {
12
32
  sequence: number;
13
33
  code: DiagnosticCode;
@@ -17,9 +37,26 @@ export interface DiagnosticEvent {
17
37
  ownerId?: string;
18
38
  ownerName?: string;
19
39
  nodeName?: string;
40
+ /**
41
+ * Root-first chain of named owners enclosing the subject of the event —
42
+ * component roots as `<Name>`, computations by their `name` option (or
43
+ * the `effect`/`computed` default) — e.g. `["<App>", "<TodoRow>", "effect"]`.
44
+ * Unnamed owners (plain roots) are skipped. Absent when the subject has no
45
+ * named owner at all (a top-level scope, or an unowned primitive — which
46
+ * is usually the finding itself).
47
+ */
48
+ ownerPath?: string[];
20
49
  data?: Record<string, unknown>;
21
50
  }
22
- export type DiagnosticListener = (event: DiagnosticEvent) => void;
51
+ /**
52
+ * A findings listener. `subject` is the live node the event is about, when
53
+ * the emitter located one — passed BESIDE the serializable event, the way
54
+ * the records channel passes `live` — for an in-process consumer that goes
55
+ * from a finding to the scope (devtools, a console task lookup);
56
+ * `undefined` for an event with no location, or a host event whose owners
57
+ * are not signals' owners.
58
+ */
59
+ export type DiagnosticListener = (event: DiagnosticEvent, subject: DiagnosticSubject | undefined) => void;
23
60
  export interface DiagnosticCapture {
24
61
  readonly events: readonly DiagnosticEvent[];
25
62
  clear(): void;
@@ -28,16 +65,302 @@ export interface DiagnosticCapture {
28
65
  export interface Diagnostics {
29
66
  subscribe(listener: DiagnosticListener): () => void;
30
67
  capture(): DiagnosticCapture;
68
+ /**
69
+ * Records an event on the channel from outside the reactive core — a host
70
+ * runtime reporting its own findings (hydration mismatches, server render
71
+ * faults) so consumers see one stream. `subject` locates it like the
72
+ * internal sites do; a host whose owners are not signals' owners passes
73
+ * `ownerPath` on the event instead and it is used as-is.
74
+ */
75
+ emit(event: Omit<DiagnosticEvent, "sequence">, subject?: DiagnosticSubject | null): DiagnosticEvent;
76
+ }
77
+ /**
78
+ * The core's side of attribution: the slot the engine installs into, and
79
+ * the interaction frame the rendering runtime opens around event dispatch.
80
+ * The engine itself — "why did this run", costs, holds, feedback — is
81
+ * `@solidjs/signals/attribution`, a separate entry so an observe build pays
82
+ * for it only when something imports it; enabling it is what installs.
83
+ */
84
+ export interface AttributionSlot {
85
+ /**
86
+ * The installed engine, or `null` when none is enabled — the one fact a
87
+ * runtime reads off the slot (`solid-js` opens a `console.createTask` per
88
+ * component only while an engine is there to attribute to it). The
89
+ * object is the engine's hook table, opaque here: the hook contract is
90
+ * between the core and its engine, not public surface.
91
+ */
92
+ readonly installed: object | null;
93
+ /**
94
+ * Run `fn` as a user interaction's handler: root writes inside stamp it as
95
+ * their origin, and actions/effects/flights it causes carry it. The web
96
+ * runtime wraps every event dispatch in this; custom renderers and test
97
+ * harnesses call it themselves. `fn()` when no engine is installed.
98
+ */
99
+ withInteraction<T>(ref: InteractionRef, fn: () => T): T;
100
+ /**
101
+ * Run `fn` as a declared unit of work — a router's navigation, described
102
+ * by the parametrized route it matched: root writes inside are attributed
103
+ * to it (under the enclosing interaction, if any), so the hold behind the
104
+ * route's data, the re-runs and the verdicts carry the route's name. Any
105
+ * router calls this around its location write; nothing else is
106
+ * router-specific. `fn()` when no engine is installed.
107
+ */
108
+ withOrigin<T>(ref: NavigationRef, fn: () => T): T;
109
+ /**
110
+ * The provenance a root write performed now would be stamped with — the
111
+ * interaction whose handler is running, the navigation or effect or action
112
+ * frame open, or inside a recompute the origin of the change that caused
113
+ * it — as the installed engine sees it; `undefined` with no engine, or when
114
+ * nothing is in effect (external). For a runtime recording a fact of its
115
+ * own beside the engine's records: `@solidjs/web` stamps its `"call"`
116
+ * record with this, so a server-function call joins the interaction or
117
+ * navigation it ran for by the identity of the object, not by time.
118
+ */
119
+ currentOrigin(): ChangeOrigin | undefined;
120
+ }
121
+ /**
122
+ * The records delivered on `OBSERVE.records`, by type — each entry
123
+ * `{ event, live }`: the serializable record and the live handle (the node
124
+ * that ran, a thrown error, a request) an in-process consumer may want
125
+ * beside it. This package declares the attribution engine's records here —
126
+ * the engine ships in this package, behind its own entry, and emits on the
127
+ * same channel as every runtime — and the runtimes that emit declare theirs
128
+ * by augmentation, so the union of record types is whatever loaded.
129
+ * `solid-js` augments THIS interface (its `"boundary"` and `"recovery"`
130
+ * records); the runtimes above it — `@solidjs/web`'s `"invocation"`,
131
+ * `"frame"` and `"call"`, a router's — augment `HostRecordTypes`, reached
132
+ * through the `solid-js` re-export, which this interface extends so the
133
+ * channel sees one catalogue.
134
+ *
135
+ * Two interfaces, one augmenter each, by design: TypeScript merges an
136
+ * augmentation into a re-exported interface by following the alias, and
137
+ * two augmentations reaching the same interface through DIFFERENT aliases
138
+ * (`"@solidjs/signals"` from solid-js, `"solid-js"` from web) merge
139
+ * order-dependently — one set is lost. So each layer augments an interface
140
+ * of its own, through one module name.
141
+ *
142
+ * The engine's records (`@solidjs/signals/attribution`; none is emitted
143
+ * until `attribution.enable()`): `live` is the computation the record is
144
+ * about where there is one — the node that ran for `rerun`, `create` and
145
+ * `effect`, the async node for `flight`, the boundary's subtree for
146
+ * `fallback` (when the boundary reported one), the first held root signal
147
+ * for `hold` (the subject the SILENT_HOLD finding names) — and `undefined`
148
+ * for the records with no single subject (`flush`, `interaction`,
149
+ * `navigation`, `graph`). The records are the same objects the engine's
150
+ * ring buffers hold (`attribution.history(type)`), delivered synchronously
151
+ * the moment each is complete — a re-run at recompute end, a hold, a
152
+ * navigation, an interaction when it settles, bottom-up — so a listener
153
+ * runs inside the engine and must not write signals. The timeline records
154
+ * (`create`, `effect`, `flush`, `flight`, `fallback`) and `graph` enter no
155
+ * ring buffer and are built only while `observed(type)`: subscribing is
156
+ * what turns them on. `rerun` is built while something wants it — a
157
+ * listener, an imported fold (`costs`/`feedback`) or the console log; the
158
+ * engine's own checks read the facts, not the record.
159
+ */
160
+ export interface RecordTypes extends HostRecordTypes {
161
+ rerun: {
162
+ event: RerunEvent;
163
+ live: Computed<any>;
164
+ };
165
+ create: {
166
+ event: CreateEvent;
167
+ live: Computed<any>;
168
+ };
169
+ effect: {
170
+ event: EffectRunEvent;
171
+ live: Computed<any>;
172
+ };
173
+ flush: {
174
+ event: FlushEvent;
175
+ live: undefined;
176
+ };
177
+ flight: {
178
+ event: FlightEvent;
179
+ live: Computed<any>;
180
+ };
181
+ fallback: {
182
+ event: FallbackEvent;
183
+ live: Computed<any> | undefined;
184
+ };
185
+ interaction: {
186
+ event: InteractionEvent;
187
+ live: undefined;
188
+ };
189
+ hold: {
190
+ event: HoldEvent;
191
+ live: Signal<any>;
192
+ };
193
+ navigation: {
194
+ event: NavigationEvent;
195
+ live: undefined;
196
+ };
197
+ graph: {
198
+ event: GraphEvent;
199
+ live: undefined;
200
+ };
201
+ }
202
+ /** The record types host runtimes declare — see `RecordTypes`. */
203
+ export interface HostRecordTypes {
31
204
  }
205
+ export type RecordType = keyof RecordTypes & string;
206
+ export type RecordEvent<K extends RecordType> = RecordTypes[K] extends {
207
+ event: infer E;
208
+ } ? E : never;
209
+ export type RecordLive<K extends RecordType> = RecordTypes[K] extends {
210
+ live: infer L;
211
+ } ? L : never;
212
+ export type RecordListener<K extends RecordType> = (event: RecordEvent<K>, live: RecordLive<K>) => void;
213
+ /**
214
+ * The records channel — `OBSERVE.records`, on either platform: one place a
215
+ * consumer (an APM adapter's `init()`, devtools, the diagnostics harness)
216
+ * subscribes to the completed, serializable summaries of the things the
217
+ * runtimes did — a `<Loading>` boundary that waited on the server, a
218
+ * server-function execution or call, a frame stream produced or applied,
219
+ * and the attribution engine's: a re-run, a hold, an interaction — each
220
+ * delivered synchronously the moment it is complete, with its live handle
221
+ * passed BESIDE it. Any number of listeners; none can alter what it
222
+ * observes; one that throws is reported and the rest run. The engine's
223
+ * records are declared here and emitted only while the engine
224
+ * (`@solidjs/signals/attribution`, a separate entry the observe build pays
225
+ * for only when imported) is enabled; `observed(type)` is the one gate an
226
+ * emitter of either kind checks before building a record.
227
+ *
228
+ * The object is created once per PROCESS under a registered symbol, so a
229
+ * subscription made before the emitting runtime has loaded, or from a
230
+ * second bundled copy of the core, reaches the same listener set. Absent in
231
+ * prod with the rest of `OBSERVE`.
232
+ */
233
+ export interface Records {
234
+ /**
235
+ * Deliver `type` records as they complete; returns the unsubscribe. The
236
+ * subscription is the channel's, not any emitter's: it outlives the
237
+ * attribution engine's `enable()`/`disable()` cycles and is dropped only
238
+ * by its own unsubscribe.
239
+ */
240
+ subscribe<K extends RecordType>(type: K, listener: RecordListener<K>): () => void;
241
+ /**
242
+ * Whether anything is subscribed to `type` — an emitter's pre-check, so
243
+ * a record nobody will hear costs nothing to not build (no clock read).
244
+ */
245
+ observed(type: RecordType): boolean;
246
+ /**
247
+ * Delivers a completed record to `type`'s listeners, synchronously: how a
248
+ * runtime publishes. Snapshot semantics without a snapshot — the listener
249
+ * list is replaced, never mutated, on subscribe/unsubscribe — so a
250
+ * listener unsubscribing mid-delivery neither skips nor double-calls
251
+ * anyone this round, and delivery allocates nothing.
252
+ */
253
+ emit<K extends RecordType>(type: K, event: RecordEvent<K>, live: RecordLive<K>): void;
254
+ }
255
+ /**
256
+ * The server runtime's observe surface — where a server-side consumer
257
+ * installs what only the server has: the trace-context provider slot.
258
+ * Declared EMPTY here and typed by the runtime that owns the surface:
259
+ * `solid-js`'s server entry augments this interface with `trace:
260
+ * ServerTrace`, an interface of its own that `@solidjs/web`'s server
261
+ * entries fill in (`provide`) — so the core never learns that shape and
262
+ * the consumer still finds it on the one `OBSERVE`. One augmenter per
263
+ * interface: see `RecordTypes` for why.
264
+ *
265
+ * The OBJECT behind it is not the core's either: the core has one artifact
266
+ * per tier for both platforms, and the client would carry it for nothing.
267
+ * `solid-js`'s server entry replaces this empty literal with the
268
+ * process-wide slot the moment it evaluates (see `serverSlots` in
269
+ * solid-js/src/server/observe.ts), so a consumer that imports only
270
+ * `solid-js` can provide before the web runtime that reads it has loaded,
271
+ * and from a second copy when a host bundles one. On the client this stays
272
+ * `{}`.
273
+ */
274
+ export interface ServerObserve {
275
+ }
276
+ /**
277
+ * The observe tier: the structured channel and the attribution wiring —
278
+ * everything a production observability consumer needs, and nothing that
279
+ * assumes a developer at a console. Present in dev and observe builds
280
+ * (`__OBSERVE__`); `undefined` in prod.
281
+ */
282
+ export interface Observe {
283
+ diagnostics: Diagnostics;
284
+ /** Completed records from the runtimes, by type — see `Records`. */
285
+ records: Records;
286
+ /** The attribution hook slot and interaction frame — see `AttributionSlot`. */
287
+ attribution: AttributionSlot;
288
+ /** The server runtime's surface — see `ServerObserve`. */
289
+ server: ServerObserve;
290
+ /**
291
+ * Marks `owner`'s subtree as the observer's own. A consumer that renders
292
+ * inside the app it watches — an APM adapter's panel, devtools — would
293
+ * otherwise see its own effects, stores and holds reported as findings about
294
+ * the app. Under an excluded owner: diagnostics whose subject sits in the
295
+ * subtree are neither delivered nor reported (the entry is still built, so
296
+ * a site that throws its message still throws), and the attribution engine
297
+ * records no runs for its computations. Mark the root as it is created
298
+ * (`createRoot(() => { OBSERVE.exclude(getOwner()!); … })`); the signals
299
+ * and stores created under it are excluded subjects wherever their writes
300
+ * come from (a click handler, an adapter callback), so writes need no
301
+ * `runWithOwner` — and must not use one: a write under an owner is a write
302
+ * in an owned scope (REACTIVE_WRITE_IN_OWNED_SCOPE). Irrevocable for the
303
+ * owner's lifetime.
304
+ */
305
+ exclude(owner: Owner): void;
306
+ /** Whether `subject` sits under an excluded owner (itself included). */
307
+ isExcluded(subject: DiagnosticSubject | null | undefined): boolean;
308
+ /**
309
+ * Root-first names of the owners enclosing `subject` (inclusive when the
310
+ * subject is itself a named owner) — component roots as `<Name>`,
311
+ * computations by their `name` option — the labels every finding and
312
+ * record carries as `ownerPath` (`["<App>", "<TodoRow>", "label"]`), from
313
+ * the one walk that stamps them, so a consumer locating a live node it
314
+ * was handed (`live`, a diagnostic's `subject`) reads the same path.
315
+ * Signals hop to their registering owner; unnamed owners are skipped;
316
+ * `undefined` when nothing on the chain is named. Names exist only in the
317
+ * observing tiers, which is why the walk lives here and not on the prod
318
+ * surface.
319
+ */
320
+ ownerPath(subject: DiagnosticSubject | null | undefined): string[] | undefined;
321
+ }
322
+ /**
323
+ * The dev tier: devtools hooks, graph traversal, and the console face of the
324
+ * diagnostics channel. Present only in dev builds (`__DEV__`).
325
+ */
32
326
  export interface Dev {
33
327
  hooks: DevHooks;
34
- diagnostics: Diagnostics;
35
328
  getChildren: typeof getChildren;
36
329
  getSignals: typeof getSignals;
37
330
  getParent: typeof getParent;
38
331
  getSources: typeof getSources;
39
332
  getObservers: typeof getObservers;
333
+ /** Console face of an emitted event — see `reportDiagnostic`. */
334
+ report(entry: DiagnosticEvent): void;
335
+ /**
336
+ * The stable URL of `code`'s section in the repair guide — the
337
+ * `reactivity-diagnostics` skill shipped with `solid-js`, one section per
338
+ * code. The one place the URL is built: the console footer prints it and
339
+ * the performance tracks' Insights link (`learnMoreUrl`) reads it, so both
340
+ * name the same section. Dev-tier: it is guidance for a developer, and a
341
+ * URL string on a retained object is a cost every observe build would pay.
342
+ */
343
+ guideUrl(code: DiagnosticCode): string;
40
344
  }
345
+ /**
346
+ * Registers the console footer appended to the first console report of
347
+ * each diagnostic code — a discovery pointer to deeper guidance. Reported
348
+ * events carry it as trailing lines of the same console entry; events that
349
+ * surface as a thrown error instead get it as a follow-up line. Returning
350
+ * undefined for an event suppresses the footer. Passing undefined
351
+ * unregisters and resets the once-per-code memory.
352
+ *
353
+ * @internal A seam for `solid-js`, which owns the repair skill the footer
354
+ * names and installs it from both of its entries; not part of `DEV`. No-op
355
+ * outside dev builds, where nothing reports to the console.
356
+ */
357
+ export declare function setConsoleFooter(footer: ((event: DiagnosticEvent) => string | undefined) | undefined): void;
358
+ export declare const OBSERVE: Observe;
359
+ export declare function isExcluded(subject: DiagnosticSubject | null | undefined): boolean;
360
+ /** For engines that cache the verdict per node: is anything excluded at all? */
361
+ export declare function anyExcluded(): boolean;
362
+ /** Was `entry` built for an excluded subject? Once-per-key reporters must not spend their slot on it. */
363
+ export declare function isSuppressed(entry: DiagnosticEvent): boolean;
41
364
  export declare const DEV: Dev;
42
365
  /**
43
366
  * Dev-mode internal consistency check. A failure means the reactive system
@@ -47,18 +370,108 @@ export declare const DEV: Dev;
47
370
  * dev builds so user apps degrade instead of crashing.
48
371
  */
49
372
  export declare function assertInvariant(condition: boolean, name: string, message: string): void;
50
- export declare function emitDiagnostic(event: Omit<DiagnosticEvent, "sequence">): DiagnosticEvent;
373
+ /** Anything a diagnostic can be about: an owner (root, computed, effect) or a signal. */
374
+ export type DiagnosticSubject = Owner | Signal<any> | Computed<any>;
375
+ /**
376
+ * Root-first names of the owners enclosing `subject` (inclusive when the
377
+ * subject is itself a named owner). Signals hop to their registering owner
378
+ * (`_owner`, set by registerGraph). Unnamed owners are skipped so the path
379
+ * reads as the component tree plus the scope: `<App> › <TodoRow> › effect`.
380
+ * Public as `OBSERVE.ownerPath`; the core's own sites import it directly.
381
+ */
382
+ export declare function ownerPath(subject: DiagnosticSubject | null | undefined): string[] | undefined;
383
+ /**
384
+ * Records a diagnostic on the structured channel (listeners, captures) and
385
+ * returns the entry. `subject` locates it: the current reactive `context` by
386
+ * default (right for the synchronous rule checks — they fire inside the
387
+ * scope that misbehaved); pass the node for scheduler-time findings whose
388
+ * ambient context is the flush, or `null` for events that have no location
389
+ * by nature. An `ownerPath` already on the event wins over the subject walk
390
+ * (hosts whose owners are not signals' owners compute their own). Console
391
+ * output is a separate, dev-tier step — see `reportDiagnostic`.
392
+ */
393
+ export declare function emitDiagnostic(event: Omit<DiagnosticEvent, "sequence">, subject?: DiagnosticSubject | null | undefined): DiagnosticEvent;
394
+ /**
395
+ * The console face of a diagnostic — ONE entry per finding: the message, the
396
+ * owner path (`in <App> › <TodoRow> › effect`) so a human can locate it, the
397
+ * once-per-code footer as trailing lines, and — when the subject is a
398
+ * binding effect the rendering runtime tagged — the element it writes, as a
399
+ * second console argument (hover highlights it, click jumps to Elements).
400
+ * Severity picks the console method. Call sites report the entry
401
+ * `emitDiagnostic` returned so the structured and console channels never
402
+ * disagree. Dev-tier: in an observe build this is a no-op, so wiring paths
403
+ * that both emit and report (graph-size warnings) reach the channel only —
404
+ * production observability never writes to the console.
405
+ */
406
+ export declare function reportDiagnostic(entry: DiagnosticEvent): void;
51
407
  /**
52
408
  * Shared strict-read diagnostics for core read() and the store proxy traps.
53
409
  * Single source for the message text — the #2897 safeguard parity between
54
410
  * memos and stores is exactly these firing identically from both paths.
55
411
  */
56
- export declare function throwPendingUntrackedRead(strictReadLabel: string, fields?: Partial<Omit<DiagnosticEvent, "sequence" | "data">>): never;
57
- export declare function warnStrictReadUntracked(strictReadLabel: string, fields?: Partial<Omit<DiagnosticEvent, "sequence">>): void;
412
+ export declare function throwPendingUntrackedRead(strictReadLabel: string, fields?: Partial<Omit<DiagnosticEvent, "sequence" | "data" | "ownerPath">>): never;
413
+ export declare function warnStrictReadUntracked(strictReadLabel: string, fields?: Partial<Omit<DiagnosticEvent, "sequence" | "ownerPath">>): void;
414
+ /**
415
+ * Observe-tier: stamp a signal with its creating owner so `ownerPath` can
416
+ * locate signal subjects. The per-owner `_signals` list and the devtools
417
+ * `onGraph` hook are dev-tier — the observe build pays one property write.
418
+ */
58
419
  export declare function registerGraph(value: any, owner: Owner | null): void;
59
420
  export declare function clearSignals(node: Owner): void;
421
+ export declare function registerRoot(owner: Owner): void;
422
+ export declare function unregisterRoot(owner: Owner): void;
423
+ /**
424
+ * The live top-level roots, for a walk of the owner tree (the engine's
425
+ * `graphSize`): dead refs are dropped as they are met. Empty in prod.
426
+ */
427
+ export declare function liveRootOwners(): Owner[];
60
428
  export declare function getChildren(owner: Owner): Owner[];
61
429
  export declare function getSignals(owner: Owner): any[];
62
430
  export declare function getParent(owner: Owner): Owner | null;
63
431
  export declare function getSources(computation: Computed<any>): (Signal<any> | Computed<any>)[];
64
432
  export declare function getObservers(node: Signal<any> | Computed<any>): Computed<any>[];
433
+ /**
434
+ * The root invalidation a HUGE_FAN_OUT finding was priced on, when the
435
+ * attribution engine is the one reporting it: a signal/store write, a
436
+ * `refresh()`, or an async landing. The always-on core check counts the
437
+ * notify walk of any change and cannot tell — it reports no `write`.
438
+ */
439
+ export type FanOutWrite = "write" | "refresh" | "async";
440
+ /**
441
+ * Observe-tier: a committed change on `node` is about to re-run `count`
442
+ * subscribers. Two reporters, one finding, one dedupe: the core counts the
443
+ * notify walk in `insertSubs` as it goes (fan-out costs exactly one local
444
+ * increment in a loop that already visits every edge, and nothing at link
445
+ * time) and fires from GRAPH_SIZE_WARN_AT up, always-on wherever the
446
+ * channel exists — a graph-size pathology should surface without asking.
447
+ * The attribution engine, while enabled, reports the same code from its
448
+ * lower `fanOut` threshold (default 250) on the root writes it stamps, with
449
+ * the write kind it knows, and hands over to the core at
450
+ * GRAPH_SIZE_WARN_AT so one change never carries two findings. Both fire on
451
+ * the write rather than the link: a fan-out that is never written costs
452
+ * nothing, and one that is re-runs every subscriber this flush. Once per
453
+ * node, re-warning only once the count has grown by GRAPH_SIZE_WARN_EVERY.
454
+ */
455
+ export declare function noteFanOut(node: Signal<any> | Computed<any>, count: number, write?: FanOutWrite): void;
456
+ /**
457
+ * Observe-tier: a recompute pass of `node` tracked `count` distinct sources
458
+ * (its trimmed dep list, walked once at the end of the pass — see recompute;
459
+ * no per-link work, no pass bracket). Fires from GRAPH_SIZE_WARN_AT up.
460
+ */
461
+ export declare function noteFanIn(node: Computed<any>, count: number): void;
462
+ /**
463
+ * Dev-only: attribute reads that run after an `await` inside an async compute.
464
+ * JS has no async context, so a native-promise flight is consumed by a uniquely
465
+ * named async function instead of `.then`; V8's async stack traces then carry a
466
+ * `__solidAsyncCompute_<id>` frame on every read in the compute's continuation.
467
+ * `await` on a native promise settles on the same tick as `.then`, so dev and
468
+ * prod timing match. Other thenables, and engines without async frames
469
+ * (Firefox, Safari), are left alone and never warn.
470
+ */
471
+ export declare let asyncTailFlights: number;
472
+ export declare function watchAsyncTail<T>(el: Computed<T>, flight: PromiseLike<T>): PromiseLike<T>;
473
+ /**
474
+ * `dep` is the node a tracked read would have linked (undefined when a store key
475
+ * was never tracked); `holder`/`key` identify the read for once-only reporting.
476
+ */
477
+ export declare function checkPostAwaitRead(dep: object | undefined, holder: object, key: PropertyKey | undefined, nodeName: string | undefined, throwsPending: boolean): 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
@@ -0,0 +1,71 @@
1
+ import type { Owner } from "./types.js";
2
+ /**
3
+ * The client error hook — the prod-tier seam through which an app or an
4
+ * error monitor hears the one failure nothing else can see: an error
5
+ * boundary (`createErrorBoundary`, `<Errored>`) collected it and is rendering
6
+ * its fallback. The browser's global handlers hear what reaches
7
+ * `window.onerror`; a rendered fallback never does. An UNCAUGHT error is not
8
+ * this hook's: the halt (`REACTIVITY_HALTED`) hands its cause to the
9
+ * platform's `reportError`, the channel every monitor already listens on —
10
+ * one event, not two.
11
+ *
12
+ * Called once per error object: a boundary's `reset()` recomputing the same
13
+ * failing node re-collects the same error and does not report it again.
14
+ * Two tiers: ambient (`configureClientErrors`) and per root
15
+ * (`render`/`hydrate`'s `onError` in `@solidjs/web`), the nearest root's
16
+ * winning. Fires in every tier; no return — the client has no wire to map
17
+ * for. `ownerPath` carries the component labels where the runtime keeps
18
+ * owner names (the observe and dev artifacts).
19
+ *
20
+ * Pay-for-use: this module is retained by `createErrorBoundary` (which
21
+ * reports here) or the app's own `configureClientErrors` import. A root's
22
+ * hook is parked ON the root owner under a registered symbol
23
+ * (`ROOT_ERROR_HOOK`, defined in the scheduler), so `render` writes it
24
+ * without importing anything: an app that configures no hook and renders no
25
+ * boundary carries none of this.
26
+ */
27
+ export interface ClientErrorContext {
28
+ /**
29
+ * Where the error was THROWN: labels root-first up the owner chain of the
30
+ * computation that threw — component labels and named primitives — when
31
+ * the runtime keeps owner names (the observe and dev artifacts). The
32
+ * boundary's own chain when the thrower is unknown (a value thrown
33
+ * outside any computation).
34
+ */
35
+ ownerPath?: string[];
36
+ /**
37
+ * Where the error was MET: the same labels up the chain of the `<Errored>`
38
+ * that rendered its fallback for it — what the user saw, as against
39
+ * `ownerPath`, which is what broke.
40
+ */
41
+ boundaryPath?: string[];
42
+ }
43
+ export type ClientErrorHook = (error: unknown, context: ClientErrorContext) => void;
44
+ export interface ClientErrorsConfig {
45
+ /** The hook, or `undefined` to clear it. */
46
+ onError?: ClientErrorHook;
47
+ }
48
+ /**
49
+ * Registers the ambient client error hook — the one call a browser `init()`
50
+ * makes to see every failure a boundary renders a fallback for, in
51
+ * production. (Uncaught errors reach `reportError` / `window.onerror`.)
52
+ *
53
+ * ```ts
54
+ * configureClientErrors({
55
+ * onError: (error, { ownerPath }) =>
56
+ * Sentry.captureException(error, {
57
+ * mechanism: { type: "solid.error_boundary", handled: true }
58
+ * })
59
+ * });
60
+ * ```
61
+ */
62
+ export declare function configureClientErrors(config: ClientErrorsConfig): void;
63
+ /**
64
+ * Tells the client error hook about `error`, caught by the boundary whose
65
+ * owner is `owner`, thrown by `thrower` (the computation the engine's status
66
+ * wrapper named; unknown for a value that never crossed one) — once per
67
+ * error object. A throwing hook is reported on the console and otherwise
68
+ * ignored — a monitor must never take the app down.
69
+ * @internal
70
+ */
71
+ export declare function reportClientError(error: unknown, owner: Owner | null | undefined, thrower?: Owner | null): void;
@@ -39,6 +39,15 @@ export declare class StatusError extends Error {
39
39
  }
40
40
  /** Return the user's error from an internal status wrapper. */
41
41
  export declare function unwrapStatusError(error: unknown): unknown;
42
+ /**
43
+ * Rejection value of `until(fn, { timeout })` when the predicate does not turn
44
+ * truthy within the window. Inside an `action()`, the rejection is thrown back
45
+ * in at the `yield` point — catchable there, or the action fails and its
46
+ * optimistic state reverts.
47
+ */
48
+ export declare class TimeoutError extends Error {
49
+ constructor(message?: string);
50
+ }
42
51
  export declare class NoOwnerError extends Error {
43
52
  constructor();
44
53
  }
@@ -1,5 +1,28 @@
1
1
  import type { Computed, Link, Signal } from "./types.js";
2
2
  export declare function unlinkSubs(link: Link): Link | null;
3
3
  export declare function trimStaleDeps(el: Computed<any>): void;
4
+ export declare function clearDeps(el: Computed<unknown>): void;
4
5
  export declare function unobserved(el: Computed<unknown>): void;
6
+ /**
7
+ * Deferred dormancy for never-observed auto-dispose computeds (#3078).
8
+ *
9
+ * An untracked top-level read of a subscriber-less observation-lifecycle memo
10
+ * used to call unobserved() inline at the end of read(). That kept the leak
11
+ * closed (the compute links the memo into its deps' sub lists — without a
12
+ * teardown point a never-observed memo is retained by its sources forever;
13
+ * upstream alien-signals has exactly this retention), but it made reads
14
+ * destructive: each read disposed the node, the next read revived it with a
15
+ * full recompute in whatever ambient transition/lane context happened to be
16
+ * current, so consecutive reads could return different answers with no write
17
+ * in between.
18
+ *
19
+ * Instead, reads queue the node here and the scheduler sweeps at the top of
20
+ * the next flush (before runHeap, so a same-tick dirtying is reclaimed
21
+ * instead of recomputed). Reads become idempotent within a tick (the node
22
+ * stays alive and serves its cache, uniform with observed memos) while
23
+ * reclamation still happens within one microtask — the enqueue site arms
24
+ * schedule(), so a flush is guaranteed even when no other work is queued.
25
+ */
26
+ export declare const dormantNodes: Set<Computed<unknown>>;
27
+ export declare function sweepDormant(): void;
5
28
  export declare function link(dep: Signal<any> | Computed<any>, sub: Computed<any>, pendingObserver?: boolean): void;
@@ -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 {
@@ -1,5 +1,5 @@
1
- export { ContextNotFoundError, NoOwnerError, NotReadyError } from "./error.js";
2
- export { isEqual, untrack, runWithOwner, computed, signal, read, setSignal, setMemo, suppressComputedRecompute, optimisticSignal, optimisticComputed, refresh, staleValues, setSnapshotCapture, markSnapshotScope, releaseSnapshotScope, clearSnapshots } from "./core.js";
1
+ export { ContextNotFoundError, NoOwnerError, NotReadyError, TimeoutError } from "./error.js";
2
+ export { isEqual, untrack, runWithOwner, computed, signal, read, setSignal, setMemo, optimisticSignal, optimisticComputed, installAuthoritativeRead, markRefresh, staleValues, setSnapshotCapture, markSnapshotScope, releaseSnapshotScope, clearSnapshots } from "./core.js";
3
3
  export { enableExternalSource, _resetExternalSourceConfig, type ExternalSourceFactory, type ExternalSource, type ExternalSourceConfig } from "./external.js";
4
4
  export { createOwner, createRoot, dispose, getNextChildId, getObserver, getOwner, isDisposed, cleanup, peekNextChildId } from "./owner.js";
5
5
  export { createContext, getContext, setContext, type Context, type ContextRecord } from "./context.js";
@@ -9,5 +9,8 @@ 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 { InteractionRef, NavigationRef } from "./attribution-hooks.js";
13
+ export { ROOT_ERROR_HOOK } from "./scheduler.js";
14
+ export { configureClientErrors, type ClientErrorContext, type ClientErrorHook, type ClientErrorsConfig } from "./error-hooks.js";
15
+ export { DEV, OBSERVE, setConsoleFooter, type AttributionSlot, type Dev, type Observe, type ServerObserve, type Records, type RecordTypes, type HostRecordTypes, type RecordType, type RecordEvent, type RecordLive, type RecordListener, type DevHooks, type DiagnosticCapture, type DiagnosticCode, type DiagnosticEvent, type DiagnosticKind, type DiagnosticListener, type Diagnostics, type DiagnosticSeverity, type DiagnosticSubject } from "./dev.js";
13
16
  export * from "./constants.js";