Repository navigation
Conversation
`queueMicrotask(o.dispose)` on an owner from `createOwner()` threw "Cannot read properties of undefined (reading '_flags')". Root cause: since e16371f every owner's `dispose` is the shared `disposeRootSelf`, which reads its owner from `this`; a detached call leaves `this` undefined and `disposeChildren(undefined)` reads `._flags`. The `createRenderEffect(..., { schedule: true })` in the report is incidental: a bare owner throws the same way, with or without effects, synchronously or from any task. Called as a method (`o.dispose()`), disposal before, during and after a scheduled first run already worked. The exported `createOwner` now binds `dispose` to its owner (as `createRoot`'s dispose is, #4097). Internal owners (mapArray rows, boundaries, reveal) keep the shared method and pay no allocation; no per-pass or flush code is touched. No F-/D- rule governs the call shape of a disposer; the disposal it performs is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015hPxMkC3jg3Uivh65gvaf2
🦋 Changeset detectedLatest commit: 691f109 The changes in this PR will be included in the next version bump. This PR includes changesets to release 15 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Size (brotli, eager entry chunk)
Bundled with Rolldown (what Vite ships), brotli q11, decimal KB. A scenario fails only when it is over its brotli cap and its minified size is more than 20 B over the minified recorded with the cap; over the cap within that allowance is brotli layout noise and passes with a warning. Caps and their recorded minified in |
|
Size gate ( This PR's own growth is on the pages that import the public Generated by Claude Code |
Coverage Report for CI Build 41140873806Warning Build has drifted: This PR's base is out of sync with its target branch, so coverage data may include unrelated changes. Coverage remained the same at 78.1%Details
Uncovered ChangesNo uncovered changes found. Coverage RegressionsNo coverage regressions found. Coverage Stats
💛 - Coveralls |
Merging this PR will improve performance by 11.03%2 warnings
Performance Changes
Tip Curious why performance improved? Comment Comparing Footnotes
|
…ound dispose (#4444) NoHydration, Portal and a frame's fill called the exported createOwner, so every page carried the bind wrapper (+51 to +63 B minified) for a dispose they only ever call as o.dispose() or through the parent. They now take the unbound owner from an @internal signals export (createScopeOwner), re-exported through solid-js/internal. Apps that never call createOwner are back to 0 B; the router pages still pay it, since @solidjs/router calls the public createOwner. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015hPxMkC3jg3Uivh65gvaf2
|
CodSpeed flags Generated by Claude Code |
…ts, scope the changeset Review nits on #4508, comment-only: the public `createOwner` shows a user-facing doc comment instead of the maintainer note, the `solid-js/internal` header lists `createScopeOwner`, and the changeset no longer says "again" (a detached `getOwner().dispose` on other owner kinds still throws; out of #4444's scope). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015hPxMkC3jg3Uivh65gvaf2
|
The
This PR stays red until that cap moves. I'm keeping it watched. Generated by Claude Code |
#4508 (#4444) binds `dispose` on the public `createOwner`, which @solidjs/router calls, so the router pages pay the bind. The maintainer accepted the growth on 2026-10-30, with a router follow-up to win it back. Recorded from #4508's CI head a4ab913 (matches local): - page: live + router: 48.65 -> 48.67 KB, minified 143,454 -> 143,527 - page: base + router: recorded minified 125,539 -> 125,596 (cap unchanged at 41.25 KB) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015hPxMkC3jg3Uivh65gvaf2
|
The CodSpeed run on 0753ed9 flags two store-setter benches, including This PR doesn't touch the store setter path. Its runtime change is limited to Generated by Claude Code |
…4512, #4506, #4509, #4508) (#4514) * chore(size): re-record the ledger after the third 2026-10-30 batch (#4512, #4506, #4509) next @ 71a6a75 fails the size gate on server: renderToString after #4512 (low-priority modulepreload hints): 22,854 B brotli against the frozen 22.80 KB cap, +266 B minified over its record. Re-records, measured over next @ 71a6a75 (linux): - server: renderToString (frozen floor): 22.80 -> 22.87 KB, minified 77,473 -> 77,739 - app: render + one signal (frozen floor): 9.78 -> 9.80 KB, minified 26,739 -> 26,754 (it measured 9,781 B, 1 B over its cap, with 5 B of minified allowance left) - page: compiled live server components: 43.01 -> 43.02 KB, minified 126,181 -> 126,196 and the recorded minified only (caps unchanged) where #4509 moved it +15 B: signals core floor (frozen, 19,908 -> 19,923), isPending/latest (31,245 -> 31,260), live server components (frozen, 118,033 -> 118,048), live + router (143,439 -> 143,454). Hello world is 9,971 B (cap 9.98 KB). The build leaves the pinned mangle-props.json unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015hPxMkC3jg3Uivh65gvaf2 * chore(size): record #4508's router growth in the batch ledger #4508 (#4444) binds `dispose` on the public `createOwner`, which @solidjs/router calls, so the router pages pay the bind. The maintainer accepted the growth on 2026-10-30, with a router follow-up to win it back. Recorded from #4508's CI head a4ab913 (matches local): - page: live + router: 48.65 -> 48.67 KB, minified 143,454 -> 143,527 - page: base + router: recorded minified 125,539 -> 125,596 (cap unchanged at 41.25 KB) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015hPxMkC3jg3Uivh65gvaf2 --------- Co-authored-by: Claude <noreply@anthropic.com>
|
#4515 supersedes this PR. The maintainer decided Generated by Claude Code |
Ryan's call on #4444 (2026-10-30): `createOwner` isn't intended as application API, and 1.x had none. Like the boundary primitives in #3709, it stays a runtime export of both solid-js entries but is `@internal` (stripped from the declarations) and typed for renderers in `solid-js/internal`. Apps host a scope with `createRoot()` and re-enter it with `runWithOwner()`. @solidjs/web keeps importing it from solid-js at runtime, with a `@ts-expect-error` on the two typed imports (`Portal`, the frames client), so the bundle holds one binding: 0 B on every size scenario. Importing it through solid-js/internal instead cost +6 to +29 B minified. The web specs that create owners import it from solid-js/internal. Supersedes #4508. Claude-Session: https://claude.ai/code/session_015hPxMkC3jg3Uivh65gvaf2 Co-authored-by: Claude <noreply@anthropic.com>
Before:
const o = createOwner(); queueMicrotask(o.dispose)threwTypeError: Cannot read properties of undefined (reading '_flags'). Effects aren't involved: a bare owner throws the same, and so doesconst d = o.dispose; d()called synchronously.After: the owner
createOwnerreturns has adisposebound to it, so it can be handed around as a plain function, ascreateRoot's dispose already can (#4097).dispose(false)still works.Cause: since e16371f ("reduce effect overhead"), every owner's
disposeis one shared method,disposeRootSelf(this)inpackages/signals/src/core/owner.ts. It finds its owner throughthis, so a detached call passedundefinedtodisposeChildren. Before that commit,disposeclosed over its owner.How:
createPublicOwnercalls the existingcreateOwnerand bindsdispose. The package's publiccreateOwnerexport is now that function, so the public name is unchanged.createRoot) keep the shared method, so there is no allocation per row.NoHydration,Portaland a frame's fill only ever dispose aso.dispose()or through their parent. They take it from an@internalsignals export,createScopeOwner, re-exported throughsolid-js/internal(no public surface;solid-jsstrips@internalfrom its declarations). Without this, every server-components page carried the bind wrapper (+51 to +63 B minified) without ever callingcreateOwner.disposeis supported; this restores the behaviour from before e16371f.Tests:
packages/signals/tests/owner-detached-dispose-4444.test.tshas 15 tests, all failing onnext. It covers the issue's shape, detacheddispose()anddispose(false), and render and plain effects with and withoutschedule, disposed sync, in a microtask and in a macrotask, three under one owner. A dispose before the first flush means the effects never run. A dispose after it cleans them up after their first run. Signals: 6121 passed / 15 expected fail. Web: 1581 passed / 7 expected fail. solid-js: 917 passed.test-typespasses.Size (client, vs next d8ca095, brotli / minified, measured locally; no ledger edits): only the router pages pay the bind, because
@solidjs/routercalls the publiccreateOwner. Hello world and every other scenario are +0, except the frames consumer below.All three stay under their caps.
Closes #4444
🤖 Generated with Claude Code
https://claude.ai/code/session_015hPxMkC3jg3Uivh65gvaf2