You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs: sync reference to rc.13; internalized boundary primitives; public hydration API
Regenerate the reference against solidjs/solid 8950bb7b7 (rc.13).
Internalized (#3709, fb4e637): createErrorBoundary, createLoadingBoundary
and createRevealOrder are typed only through solid-js/internal now, so
their pages go and Boundaries' "Primitive forms" says so, composing
Errored + Loading for a custom boundary instead. sharedConfig and $DEVCOMP
stay hidden. The REACTIVITY_HALTED message points at <Errored> alone.
New public hydration API (#3718): isHydrating / isHydratable pages under
Manual hydration, a getHydrationWriter / takeHydrationValue page under
Rendering & SSR with HydrationWriter / HydrationValue folded in. Rendering
and SSR's "Controlling hydration" introduces the four; SSR-safe code uses
isHydrating() to seed a browser-measured value correctly on a client-side
navigation.
Observe tier (#3705, #3708, fe1eb68): the "request" record, the shared
CallLive, the bodies opt-in, OBSERVE.include, and the router's initial /
interaction declarations in the two observability guides and the debugging
guide; CallRequestEvent, CallRequestListener, RecordSubscribeOptions and
RenderRoute fold into the OBSERVE page. Server-component binding-slot
exports (SLOT_*, isSlotValue) are hidden as renderer ABI.
Extractor: member types go through cleanTypeText, so an interface member
no longer leaks SolidElement or an inline JSDoc blob; GlobalAbortSignal
renders as AbortSignal.
Router: defineFileRoute's config is optional (solid-router#622).
Co-authored-by: Cursor <cursoragent@cursor.com>
Copy file name to clipboardExpand all lines: src/routes/(2)concepts/(4)boundaries.mdx
+16-22Lines changed: 16 additions & 22 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -216,36 +216,30 @@ Wrapping a descendant in another loading boundary does not let it escape an oute
216
216
217
217
## Primitive forms
218
218
219
-
The components above are built from three primitives.
220
-
Application code does not need them; they exist for custom boundary components and renderer integrations.
221
-
222
-
- [`createLoadingBoundary(fn, fallback, options?)`](/reference/solid-js/advanced/jsx-component-primitives/create-loading-boundary) returns an accessor that switches between the tracked `fn` and the fallback.
223
-
Its `on` option takes an accessor, because the primitive does not receive JSX props.
224
-
- [`createErrorBoundary(fn, fallback)`](/reference/solid-js/advanced/jsx-component-primitives/create-error-boundary) returns an accessor and passes the fallback an error accessor and a reset function.
225
-
- [`createRevealOrder(fn, options?)`](/reference/solid-js/advanced/jsx-component-primitives/create-reveal-order) runs `fn` under a reveal controller; its `order` and `collapsed` options are accessors.
219
+
The components above are built from three primitives, `createLoadingBoundary`, `createErrorBoundary`, and `createRevealOrder`.
220
+
They stay runtime exports of `solid-js`, but their types live in `solid-js/internal`, which carries no semver guarantee: they exist for renderer integrations, not for application code.
221
+
A custom boundary component composes `Loading`, `Errored`, and `Reveal` instead:
226
222
227
223
```tsx
228
-
import {createErrorBoundary, createLoadingBoundary} from "solid-js";
Two functions answer questions about the hydration in progress.
293
+
[`isHydrating()`](/reference/solid-js/advanced/manual-hydration/is-hydrating) is `true` while the running code is claiming server-rendered DOM, during the root pass of `hydrate()` or while a streamed boundary resumes, and `false` on the server, in client-only renders, and afterwards; a component reads it to seed a browser-measured value with what the server rendered only when the server rendered anything, as [SSR-safe code](/guides/ssr-safe-code#browser-apis) shows.
294
+
[`isHydratable()`](/reference/solid-js/advanced/manual-hydration/is-hydratable) is `true` when the calling owner sits where hydration applies, so `false` under `NoHydration` and `true` again inside a nested `Hydration`.
295
+
296
+
Those two, with [`getHydrationWriter`](/reference/solid-web/rendering-ssr/get-hydration-writer) and [`takeHydrationValue`](/reference/solid-web/rendering-ssr/take-hydration-value) from `@solidjs/web`, are the surface a data library uses to carry its own values from the server render to the hydrating client: the server side writes a value under a namespaced key when `isHydratable()` allows it, and the client side takes it back by key, as a resolved value, a rejection, or a promise still streaming in.
297
+
Application code does not need them; Solid moves its own state this way already.
298
+
292
299
## Common problems
293
300
294
301
### `window is not defined` or `document is not defined`
Copy file name to clipboardExpand all lines: src/routes/(5)guides/(10)debugging-reactivity.mdx
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -285,7 +285,7 @@ Acknowledged holds under those thresholds still count in the feedback tables: `f
285
285
286
286
A router can name the holds its navigations cause by the route pattern that matched, `/products/:id` rather than `/products/mug`, so occurrences fold together in these tables.
287
287
It does so by wrapping its location write in `OBSERVE.attribution.withOrigin({ kind: "navigation", name, to, params }, write)`, which is router-agnostic; nothing else in attribution knows about routing.
288
-
The [attribution reference](/reference/solid-js/advanced/diagnostics-dev-hooks/attribution#navigationref) describes the `NavigationRef` fields, including how a router whose match is not final at write time fills them in later.
288
+
The [attribution reference](/reference/solid-js/advanced/diagnostics-dev-hooks/attribution#navigationref) describes the `NavigationRef` fields, including how a router whose match is not final at write time fills them in later, how it declares the route the document arrived on with `initial`, and how one that awaits before writing hands the click back as `interaction`.
289
289
:::
290
290
291
291
## The test sees the old DOM
@@ -345,7 +345,7 @@ An error thrown inside a computation that no boundary catches halts the reactive
345
345
346
346
```text
347
347
[REACTIVITY_HALTED] An uncaught error halted the reactive system. No further updates will be processed.
348
-
Handle errors with createErrorBoundary/<Errored> or treat this as a crash.
348
+
Handle errors with <Errored> or treat this as a crash.
349
349
```
350
350
351
351
Nothing on the page updates after this until a reload.
Copy file name to clipboardExpand all lines: src/routes/(5)guides/(15)observability.mdx
+6-1Lines changed: 6 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -180,6 +180,7 @@ The fields it returns replace the runtime's derivation; its `entries` merge by n
180
180
|`"render"`| server | A `renderToString` or `renderToStream` render: how long the shell took and how many boundaries it waited on. |
181
181
|`"boundary"`| server | A `Loading` boundary that waited during a render; one that rendered on its first pass emits nothing. |
182
182
|`"invocation"`| server | A server-function execution, from HTTP dispatch or an in-process call. |
183
+
|`"request"`| client | A server-function request the page sent, delivered at the send, so a call still in flight has a row. |
183
184
|`"call"`| client | A server-function call the page made, as the caller awaited it. |
184
185
|`"frame"`| both | A frame stream produced (server) or applied (client). |
185
186
|`"recovery"`| client | A `Loading` boundary the server gave up on, re-rendered as fresh DOM on the client; joins its `"boundary"` by id. |
@@ -204,6 +205,8 @@ Render `/orders` with a slow database and the line reads `<Loading> at <App> ›
204
205
A record is data: ids, names, an outcome, `at` on the `performance.now()` clock, durations, counts.
205
206
Anything live — the request, the response, the arguments, the error as thrown — travels in a second argument to the listener, never on the record, so a record can leave the process as it is.
206
207
A client `"call"` and the server `"invocation"` it caused share an `id`; the difference between their durations is the wire.
208
+
The `"request"` and `"call"` records of one call share their `live` object by identity, filled in as the call proceeds, so a listener holding it from the send reads the outcome off it at settle.
209
+
Request and response bodies are taken only for a listener that asked, `subscribe("call", fn, { bodies: true })`; a listener that reads ids, statuses, and timings never pays for them.
207
210
An invocation made during a boundary's render pass names that boundary, so a wait can be read as the calls it consisted of.
208
211
209
212
Listeners run synchronously inside the runtime, the moment the record is complete.
Click "Place order" and the line reads `click on button#place-order "Place order" took 840ms to settle: ["placeOrder held 812ms"]`.
236
239
An interaction record carries the handler's own time, the writes it made, the re-runs and creations they caused, when the last effect that traces back to it ran (`settledMs`), and the holds and navigations it performed, each settled before the interaction is.
237
240
A hold names what blocked the write, how long, and whether the screen acknowledged the wait with `isPending`, `latest`, or an optimistic value; `silent` is `true` on a hold nothing acknowledged, which is what the shopper experiences as a dead click, and `long` on one whose wait ran past the point a fallback should have taken over.
238
-
A router that wraps its location write in `OBSERVE.attribution.withOrigin` gives its navigations the matched route pattern as their name, so `/orders/:id` folds together across shoppers.
241
+
A router that wraps its location write in `OBSERVE.attribution.withOrigin` gives its navigations the matched route pattern as their name, so `/orders/:id` folds together across shoppers; the route the document arrived on is declared the same way, so the first navigation has a name too, and a server `"render"` record carries it as `route`.
239
242
240
243
`enable()` takes a hold on the engine and returns its release.
241
244
The engine is shared by every tool on the page — an adapter, the Performance panel tracks, a diagnostics capture — so each takes its own hold, options combine by the most demanding request per key, and the engine stays on until the last release; `attribution.disable()` tears everything down regardless.
@@ -279,6 +282,8 @@ createRoot(() => {
279
282
});
280
283
```
281
284
285
+
A tool that renders the app inside its own shell, `<DevToolbar><App /></DevToolbar>`, excludes the shell and re-admits the app with `OBSERVE.include(owner)` at the app's root; each owner answers by its nearest marked ancestor.
Copy file name to clipboardExpand all lines: src/routes/(5)guides/(16)observability-adapters.mdx
+5Lines changed: 5 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -60,6 +60,9 @@ The contract that shapes a span builder:
60
60
- Server records are delivered during the request, so a Node SDK whose active span is the request's parents them without anything passing a parent around.
61
61
- A client `"call"` and the server `"invocation"` it caused share `id`.
62
62
An invocation made during a boundary's render pass carries `boundary`, the `id` of that boundary's record.
63
+
- A `"request"` record leaves at the send, before the transport's `fetch`, for a call the `"call"` record cannot show yet: one still in flight, or one that never settles.
64
+
The two share one `live` object by identity.
65
+
- Bodies cost the call a copy, so they are taken only under `subscribe(type, fn, { bodies: true })`; without it `live.request` is absent and `live.response` is the transport's own, already consumed.
63
66
64
67
```ts
65
68
import { OBSERVE } from"solid-js";
@@ -117,6 +120,7 @@ Keep a `WeakMap` from origin to span and a call finds its parent without a clock
117
120
The stamp is read at dispatch: a call made synchronously in the handler carries it even when the response lands after the interaction settled, which is the usual shape of `onClick={async () => set(await call())}`; a call made after an `await` in the handler carries nothing, the same escape a write there has.
118
121
119
122
Routers declare their navigations to the engine with `OBSERVE.attribution.withOrigin`, so navigation records carry the matched route pattern as `name`; an adapter needs no router code.
123
+
The route the document arrived on is declared with the same call around the router's initial match, so the first `"navigation"` record names it with `initial: true`, timed from the document's navigation start, and the server `"render"` record carries the matched route as `route`; a router that resolves guards or loaders before it writes the location hands the interaction it captured back as `interaction`, and the write joins the click as if it had been synchronous.
120
124
121
125
## Trace context: answer once, the runtime carries it
122
126
@@ -168,6 +172,7 @@ createRoot(() => {
168
172
```
169
173
170
174
Under an excluded owner, diagnostics about the subtree are neither delivered nor reported, and the engine records no runs for its computations.
175
+
An adapter that renders the app inside its own shell excludes the shell and calls `OBSERVE.include(owner)` at the app's root to re-admit it; the verdict comes from the nearest marked ancestor, and a mark belongs at the owner's creation.
171
176
The signals and stores created under it stay excluded wherever their writes come from, so the writes need no `runWithOwner` and must not use one: a write under an owner is a write in an owned scope, which the dev build flags.
Copy file name to clipboardExpand all lines: src/routes/(5)guides/(8)ssr-safe-code.mdx
+17Lines changed: 17 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -122,6 +122,23 @@ In the `Prefer` version the server renders `class="drawer"`, the browser hydrate
122
122
Resizing the window updates it again through the listener, and the returned cleanup removes the listener when the drawer is disposed.
123
123
[Custom primitives](/guides/custom-primitives#clean-up-what-you-start) turns this into a reusable `createMediaQuery`.
124
124
125
+
The `false` seed is right while the browser is claiming server HTML, and wrong when the drawer is created later by a client-side navigation: there is no server markup to agree with, and the class still flips one frame after it appears.
126
+
[`isHydrating`](/reference/solid-js/advanced/manual-hydration/is-hydrating) tells the two apart, so the seed can ask the browser whenever the answer will not be checked against the server:
`isHydrating()` is `true` during the root pass of `hydrate()` and while a streamed boundary resumes, and `false` on the server, in client-only renders, and after hydration; it is not reactive, so read it where the signal is created.
140
+
The `onSettled` callback stays: it is still what updates the value after a hydrated first paint.
141
+
125
142
Some helpers are called from places that have no owner, such as a formatting function shared with server code.
126
143
For those, [`isServer`](/reference/solid-web/rendering-ssr/is-server) from `@solidjs/web` is a build-time constant, `true` in the server build and `false` in the browser build, so the bundler drops the branch that cannot run:
Copy file name to clipboardExpand all lines: src/routes/reference/(1)solid-js/(0)index.mdx
+3-2Lines changed: 3 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -69,12 +69,13 @@ Built-in components for conditions, lists, and boundaries.
69
69
70
70
## Advanced
71
71
72
-
Owner introspection, specialized effects, store internals, boundary primitives, manual hydration, interop, and development hooks.
72
+
Owner introspection, specialized effects, store internals, list primitives, manual hydration, interop, and development hooks.
73
73
These pages support libraries and tooling; application code rarely needs them.
74
74
75
75
-[`createRoot`](/reference/solid-js/advanced/owner-introspection/create-root), [`getOwner`](/reference/solid-js/advanced/owner-introspection/get-owner), and [`runWithOwner`](/reference/solid-js/advanced/owner-introspection/run-with-owner) manage reactive scopes by hand.
76
76
-[`createRenderEffect`](/reference/solid-js/advanced/specialized-reactivity/create-render-effect) and [`onCleanup`](/reference/solid-js/advanced/specialized-reactivity/on-cleanup) serve renderers and custom primitives.
77
-
-[`createLoadingBoundary`](/reference/solid-js/advanced/jsx-component-primitives/create-loading-boundary) and [`createErrorBoundary`](/reference/solid-js/advanced/jsx-component-primitives/create-error-boundary) back the flow components.
77
+
-[`mapArray`](/reference/solid-js/advanced/jsx-component-primitives/map-array) and [`repeat`](/reference/solid-js/advanced/jsx-component-primitives/repeat) are the list primitives behind `For` and `Repeat`.
78
+
-[`isHydrating`](/reference/solid-js/advanced/manual-hydration/is-hydrating) says whether the running code is claiming server-rendered DOM; [`isHydratable`](/reference/solid-js/advanced/manual-hydration/is-hydratable) whether the owner sits where hydration applies.
78
79
-[`DEV`](/reference/solid-js/advanced/diagnostics-dev-hooks/dev) exposes the development diagnostics that [Debugging reactivity](/guides/debugging-reactivity) reads.
0 commit comments