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
{{ message }}
Repository navigation
Commit 6f4fa94
Browse filesBrowse the repository at this point in the historyBrowse files
docs: sync diagnostics pages and the Vite plugin's test environment (#1665)
* docs: sync diagnostics pages and the Vite plugin's test environment
- Regenerate the diagnostics reference from solid next 6cca8b57: adds
STORE_WRITE_OUTSIDE_SETTER (#4194) and UNCOMMITTED_INPUT_OVERWRITTEN
(#4205), drops BINDING_SLOT_POSITION (binding slots were removed), and
picks up skill edits to EFFECT_RELAY_TEAR, LOWERCASE_EVENT_ATTRIBUTE,
REACTIVITY_HALTED, SSR_BOUNDARY_WATERFALL and SSR_LIVE_HOLE_LATCHED.
The generator's FIX_STARTS entry for SSR_BOUNDARY_WATERFALL follows the
skill's new capitalization, and the dead BINDING_SLOT_POSITION entry goes.
- The Vite plugin no longer defaults test.environment to jsdom
(vite-plugin-solid #459): the testing guide drops the "browser mode still
needs jsdom" note and troubleshooting entry, browser mode no longer
installs jsdom, and a new entry covers `document is not defined`. The
plugin options reference and the Solid 1 migration guide say to set the
environment.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R9d4iekBWmtH343gNAGJpd
* docs: regenerate diagnostics against solid-js@2.0.0-rc.17
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R9d4iekBWmtH343gNAGJpd
---------
Co-authored-by: Claude <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: src/routes/(5)guides/(14)testing.mdx
+5-10Lines changed: 5 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -146,15 +146,10 @@ The configuration above sets `globals: false`, so the explicit `afterEach(cleanu
146
146
Choose browser mode when jsdom cannot provide the behavior that the test needs.
147
147
The maintained browser-mode template uses the Playwright provider with headless Chromium.
148
148
149
-
:::note[Browser mode still needs jsdom installed]
150
-
When `test.environment` is unset, `@solidjs/vite-plugin` supplies a jsdom environment and Vitest resolves that dependency before it starts the browser pool.
151
-
Without jsdom, the Chromium test can pass while the Vitest command exits with a missing-dependency error.
152
-
:::
153
-
154
149
For a new test setup, install the complete dependency set:
@@ -380,11 +375,11 @@ The write is staged and the batch has not landed when the next line runs.
380
375
Call `flush()` after the event and before the assertion.
381
376
For an async source, `flush()` does not help; await `resolve(() => value())` or use an asynchronous query.
382
377
383
-
### The Chromium test passes but Vitest exits with a missing-dependency error
378
+
### A component test fails with `document is not defined`
384
379
385
-
jsdom is not installed.
386
-
`@solidjs/vite-plugin`supplies a jsdom environment when `test.environment` is unset, and Vitest resolves that dependency before starting the browser pool.
387
-
Keep `jsdom` in the development dependencies alongside the browser provider.
380
+
The `test` block does not set `environment`, so Vitest runs the file in Node.
381
+
`@solidjs/vite-plugin`does not choose a test environment.
382
+
Set `environment: "jsdom"` (or `"happy-dom"`) for component tests, or enable browser mode.
Copy file name to clipboardExpand all lines: src/routes/reference/(1)solid-js/(8)diagnostics/(0)index.mdx
+2-1Lines changed: 2 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -54,7 +54,6 @@ Naming your memos and effects (`{ name }`) turns the trailing `effect` in the `i
54
54
|[`ASYNC_OUTSIDE_LOADING_BOUNDARY`](/reference/solid-js/diagnostics/async-outside-loading-boundary)|`async`|`warn`| Async computation outside Loading boundary (non-halting; root mount is deferred) |
55
55
|[`ASYNC_STORE_SETTER`](/reference/solid-js/diagnostics/async-store-setter)|`write`|`error`| Store setter callback returned a Promise (setters are synchronous transactions) |
|[`BINDING_SLOT_POSITION`](/reference/solid-js/diagnostics/binding-slot-position)|`ssr`, `render`|`warn`, `error`| Binding-slot value where it cannot bind; `data.reason` names the position (spread is an error and throws), client reasons `orphan`/`fill-shape`|
|[`DYNAMIC_ASYNC_COMPONENT`](/reference/solid-js/diagnostics/dynamic-async-component)|`ssr`|`error`| An async `dynamic()` source landed on a client component function, which cannot serialize for adoption; the memo rejects (observe + dev; rejects in every tier) |
60
59
|[`EFFECT_RELAY_TEAR`](/reference/solid-js/diagnostics/effect-relay-tear)|`perf`|`info`, `warn`| Reader ran twice for one root change because an effect relayed it; `warn` when derivable or repeated (attribution enabled) |
@@ -105,8 +104,10 @@ Naming your memos and effects (`{ name }`) turns the trailing `effect` in the `i
105
104
|[`SSR_SUBTREE_ABANDONED`](/reference/solid-js/diagnostics/ssr-subtree-abandoned)|`ssr`|`warn`| A failed fragment's pending descendants were discarded (observe + dev) |
106
105
|[`SSR_UNDECLARED_LIVE_SOURCE`](/reference/solid-js/diagnostics/ssr-undeclared-live-source)|`ssr`|`warn`| A document render is still pumping an async iterable in server-component scope 5s in — declare the function `live(...)` or bound the source (dev) |
107
106
|[`STACKED_HOLDS`](/reference/solid-js/diagnostics/stacked-holds)|`responsiveness`|`warn`| 3+ interactions were waiting in one hold when it committed — repeats piled behind the same source (attribution enabled) |
107
+
|[`STORE_WRITE_OUTSIDE_SETTER`](/reference/solid-js/diagnostics/store-write-outside-setter)|`write`|`warn`| Store proxy written, deleted from, or defined on outside its setter; the write is ignored (once per store object and key) |
108
108
|[`STRICT_READ_UNTRACKED`](/reference/solid-js/diagnostics/strict-read-untracked)|`strict-read`|`warn`| Untracked reactive read in component/effect body |
109
109
|[`SYNC_NODE_RECEIVED_ASYNC`](/reference/solid-js/diagnostics/sync-node-received-async)|`lifecycle`|`error`|`sync: true` computation returned a Promise / AsyncIterable |
110
+
|[`UNCOMMITTED_INPUT_OVERWRITTEN`](/reference/solid-js/diagnostics/uncommitted-input-overwritten)|`render`|`warn`| A stateful property binding (`value`/`checked`/…) re-wrote an unchanged value over an edit the user never committed to the signal (dev; client) |
110
111
|[`UNRECOGNIZED_INSERT_VALUE`](/reference/solid-js/diagnostics/unrecognized-insert-value)|`render`|`warn`| Value at an insert position the renderer cannot render; skipped (dev; server and client) |
111
112
|[`UNSCOPED_HOLE_ALLOCATED_IDS`](/reference/solid-js/diagnostics/unscoped-hole-allocated-ids)|`render`|`warn`| Unscoped hole was handed a function whose content took ids at a position the other side does not share; keys permute (dev) |
112
113
|[`UNSTABLE_LIST_IDENTITY`](/reference/solid-js/diagnostics/unstable-list-identity)|`perf`|`warn`|`mapArray`/`For` recreated rows for equivalent items (attribution enabled) |
Copy file name to clipboardExpand all lines: src/routes/reference/(1)solid-js/(8)diagnostics/effect-relay-tear.mdx
+10-5Lines changed: 10 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -35,18 +35,23 @@ Derived state kept in sync by an effect: `createEffect(() => f(a()), v => setS(v
35
35
The message names a reader that ran twice for ONE write of `a` — once in the flush where `a` changed (against the stale `S`), once after the effect's write landed — so its first frame was inconsistent.
36
36
That double run is proven from the cause chain; the rest of the message is confidence:
37
37
38
+
- "The written value is the effect's compute output" — by Solid's contract the compute half is a pure function of its tracked reads, so the value is derivable. Repair: `const s = createMemo(() => f(a()))`, delete the effect and the signal. This form warns on its own once it has repeated (`data.copy: true`), even with no double-running reader — everything reading the copy paints a flush behind everything reading the source.
39
+
- "The written value is `a` itself" (`data.passthrough`) — the prop-to-state port. Repair: read `a` where `S` was read; a memo only if a stable derivation is genuinely needed.
40
+
- "Nothing else writes `S`" (`data.soleWriter`, `copy` false) — derived state if the value is computed from what the effect reads: same memo repair. If the effect measures (layout, `Date.now()`, a ref), the tear is the cost of measuring.
41
+
- "`S` has other writers — editable state reset from a source" (`copy` true, `soleWriter` false; `info` until it repeats) — the controlled-input shape. If resetting local editable state when the source changes is the intent, the tear is its cost; if `S` only ever mirrors the source, drop the copy.
42
+
- Neither — the written value is not the compute output and the signal has other writers. If the effect reads something outside the graph, the tear is the cost of measuring and the finding is a fact to accept; if the value is computed from what the effect reads, it is still a memo.
43
+
44
+
An effect whose apply half takes no argument (`createEffect(open, () => setFlipped(measure()))`) is reading something other than its compute output, so a matching write is never taken as a copy and its tears stay `info` however often they repeat: the cost of measuring.
45
+
One that takes the value (`v => setS(v)`, `v => setLabel(v ? "Close" : "Open")`) is judged as above and warns once it has repeated, a measurement included (`i => setLeft(offsets[i])` with stable layout): drop the parameter if the write does not use it.
46
+
38
47
:::note[Performance pathologies (from the attribution engine)]
39
48
These fire only while attribution is enabled and describe cost, not incorrect behavior.
40
49
The numbers in the message are measurements, not guesses.
41
50
:::
42
51
43
52
## How to fix it
44
53
45
-
- "The written value is the effect's compute output" — by Solid's contract the compute half is a pure function of its tracked reads, so the value is derivable. Repair: `const s = createMemo(() => f(a()))`, delete the effect and the signal. This form warns on its own once it has repeated (`data.copy: true`), even with no double-running reader — everything reading the copy paints a flush behind everything reading the source.
46
-
- "The written value is `a` itself" (`data.passthrough`) — the prop-to-state port. Repair: read `a` where `S` was read; a memo only if a stable derivation is genuinely needed.
47
-
- "Nothing else writes `S`" (`data.soleWriter`) — derived state without the identity proof; same memo repair.
48
-
- "`S` has other writers — editable state reset from a source" (`copy` true, `soleWriter` false; `info` until it repeats) — the controlled-input shape. If resetting local editable state when the source changes is the intent, the tear is its cost; if `S` only ever mirrors the source, drop the copy.
49
-
- Neither (`info` until it repeats) — the written value is not the compute output and the signal has other writers. If the effect reads something outside the graph (layout, `Date.now()`, a ref), the tear is the cost of measuring and the finding is a fact to accept; if the value is computed from what the effect reads, it is still a memo.
54
+
Do not defer the write to a microtask to quiet it; that only hides the cause chain.
Copy file name to clipboardExpand all lines: src/routes/reference/(1)solid-js/(8)diagnostics/lowercase-event-attribute.mdx
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -30,7 +30,7 @@ In a captured artifact the same finding is an event with `code: "LOWERCASE_EVENT
30
30
31
31
## Why it fires
32
32
33
-
A function was set on an attribute whose name starts with `on` but is not an event handler (`data.name`): a lowercase `onclick`, or a leftover 1.x `on:click`.
33
+
A function was set on an attribute whose name starts with `on` but is not an event handler (`data.name`): a lowercase `onclick`, or a leftover 1.x `on:click` passed through a spread (on a native element it is a compile error).
34
34
In 2.0 only `on` + an uppercase letter binds an event; anything else is a plain attribute, so the function was stringified into it and never runs.
Copy file name to clipboardExpand all lines: src/routes/reference/(1)solid-js/(8)diagnostics/reactivity-halted.mdx
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -35,6 +35,7 @@ An earlier uncaught error halted the reactive system; subsequent updates are ign
35
35
## How to fix it
36
36
37
37
Do not treat this code as the bug — find the original error above it (or add an error boundary with `<Errored>`) and fix that.
38
+
The `in <App> › …` line under the message (repeated on the "Update ignored" notice) is the owner path of the computation the error escaped from: start there.
0 commit comments