Skip to content

docs: fix the from() migration snippet, add createDeferred to the cheatsheet, note SETTLED_CLEANUP_UNOWNED throws - #4183

Merged
ryansolid merged 4 commits into
solidjs:nextfrom
devagrawal09:docs/deferred-from-settled-cleanup
Oct 21, 2026
Merged

ryansolid merged 4 commits into
solidjs:nextfrom
devagrawal09:docs/deferred-from-settled-cleanup

Conversation

@devagrawal09

@devagrawal09 devagrawal09 commented Oct 21, 2026 •

Copy link
Copy Markdown

Three small docs fixes found while writing the "From React" additions in solidjs/solid-docs#1664.

MIGRATION.md: document that the from replacement doesn't clean up immediately (related to #4182)

  • The snippet is unchanged: async function* + for await. A note after it explains that when the owner is disposed, or a re-run replaces the stream, Solid calls the generator's return(), but a generator waiting at an await can't finish until that await settles. So the source stays subscribed until it produces another value or ends.
  • Tested on next @ b0ad1df: after dispose, the upstream return() is called 0 times, then 1 time once the upstream produces its next value.
  • A forwarding-only tip: createMemo(() => observable$) closes the source right away (return() called once, immediately on dispose).
  • Prompt cleanup for generators needs a cancellation hook from Solid, which is tracked in [2.0] The MIGRATION.md replacement for from() keeps the upstream subscription after dispose; add a subscription helper #4182. I tried the user-side options (onCleanup inside the compute or the generator, and wrapping the generator's return()), and none is clean enough for the migration guide.

CHEATSHEET.md: createDeferred added to the imports list and the Async section. It's exported from solid-js and is the closest counterpart to React's useDeferredValue, but the cheatsheet didn't mention it.

skills/reactivity-diagnostics/SKILL.md: SETTLED_CLEANUP_UNOWNED now says it throws in dev (signals.ts, throw new Error(message) after the diagnostic) and that the cleanup is dropped in production, matching 08-dev-diagnostics.md. Before, it sat under "leaks" with no mention of the throw.

Prettier passes on the lines this PR adds. Docs only, no code changes.

07-dom.md + CHEATSHEET.md: a ref runs before the element is attached. Inside a ref callback, el.isConnected is false and el.ownerDocument is the template's inert document, so defaultView is null. Code that reaches window through the element (listeners, getComputedStyle) silently breaks. The docs now say to use the global window/document, or onSettled for layout-dependent work. Tested on next (jsdom, native and Babel compilers):

Where defaultView ownerDocument === document isConnected
In the ref callback null false false
In onSettled window true true

04-stores.md: don't keep mutating an object after handing it to a store. Tested: after an in-place change to the object, the store still read the old value. Assigning the same object again, or reconciling it, changed nothing. A fresh copy updated it. This mostly affects test fixtures and caches that reuse one response object.

Both came from OpenClaw's Solid 2 migration notes (lessons.md L41 and L31 in openclaw/openclaw .agents/skills/solid/references/). 07-dom.md and 04-stores.md already fail prettier --check on next (an existing table and the setStore((s) => formatting); I left those lines alone.

…atsheet, note SETTLED_CLEANUP_UNOWNED throws
@changeset-bot

changeset-bot Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 80bb890

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@codspeed

codspeed Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Merging this PR will improve performance by 14.52%

⚠️ 2 benchmarks spent significant time in system calls

System calls cannot be consistently instrumented, so they are not included in the measure, which understates the real cost. Please switch to the Walltime instrument to accurately measure system calls.

Measurement and system calls

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 1 improved benchmark
✅ 195 untouched benchmarks
⏩ 5 skipped benchmarks1

Performance Changes

Benchmark BASE HEAD Efficiency
⚡ memo + sync render effect only (reference) 33.6 ms 29.4 ms +14.52%

Tip

Curious why performance improved? Comment @codspeedbot explain why performance improved on this PR, or directly use the CodSpeed MCP with your agent.


Comparing devagrawal09:docs/deferred-from-settled-cleanup (80bb890) with next (b0ad1df)

Open in CodSpeed

Footnotes

  1. 5 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩

@ryansolid
ryansolid merged commit 6bf1e55 into solidjs:next Oct 21, 2026
8 checks passed
ryansolid pushed a commit that referenced this pull request Oct 21, 2026
The drain costs about 35 B minified in every signals scenario, including
the simple-app floor, for a leak that only follows a cleanup that throws.
Held for a size decision.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018LY7F9czoRqdMEvk2QwPr1
ryansolid added a commit that referenced this pull request Oct 21, 2026
* fix(signals): release lazy nodes collected before a throwing cleanup

#4176 restores the release collector when a cleanup throws while an
unfinished pass's frame is dismantled, but the throw also skips the drain
at the end of the pass, so lazy nodes the frame's children released before
the throw were never released. Drain them before rethrowing.

Also adds the solid-js changeset for #4183's docs, which ship in the package.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018LY7F9czoRqdMEvk2QwPr1

* revert the lazy-release drain; keep only the #4183 changeset

The drain costs about 35 B minified in every signals scenario, including
the simple-app floor, for a leak that only follows a cleanup that throws.
Held for a size decision.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018LY7F9czoRqdMEvk2QwPr1

* chore(size): re-record the compiled CSR cap after #4188, #4207 and #4176

Each passed alone; together they put next 1 B past the 20 B minified
allowance (81,159 B against 81,138 recorded). Accepted by the maintainer.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018LY7F9czoRqdMEvk2QwPr1

---------

Co-authored-by: Claude <noreply@anthropic.com>
@devagrawal09
devagrawal09 deleted the docs/deferred-from-settled-cleanup branch October 22, 2026 09:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants