Use the effect primitives Solid 2 actually kept - #247
Merged
Conversation
added 2 commits
August 16, 2026 20:46
Every effect in the library was written against Solid 1, where `createEffect(fn)` tracked whatever the body read. Solid 2 gives that signature a second parameter and splits the work: the first function tracks and returns a value, the second receives it and runs untracked. A lone function is now rejected outright with MISSING_EFFECT_FN, which halts the reactive system, so any component reaching one of these took its whole page down. `createTrackedEffect` is the primitive that kept the old behaviour, so this is a rename across the 65 call sites rather than a rewrite. The two forms are not interchangeable, and choosing between them per site is a judgement about which reads are dependencies; splitting them is worth doing, but not while the library does not run. Cleanup had to move with it. A tracked effect owns its teardown through the function it returns, and calling `onCleanup` inside one is refused with CLEANUP_IN_FORBIDDEN_SCOPE, so the 16 effects that registered teardown that way now return it instead. Two of them registered cleanup from inside a conditional, which a return cannot express, so those invert the guard first. Fixes the blank home page seen on promptsyntax.org, where Tabs was the component that reached one of these first.
Same rule as the tracked effects in the previous commit: `onSettled` owns its teardown through the function it returns, and calling `onCleanup` inside one is refused with CLEANUP_IN_FORBIDDEN_SCOPE. Eight callbacks still registered cleanup that way. Six were a trailing `onCleanup` and became a return. The other two registered it partway through a callback that then goes on to bail out early, so those name the teardown and return it from each exit rather than reordering the work around it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
@pathscale/ui@2.6.1requiressolid-js >=2.0.0-rc.0, but its components are still written against Solid 1's effect API. Solid 2 changed two rules, and the library breaks on both:createEffectgained a second parameter. The first function tracks and returns a value; the second receives it and runs untracked. A lone function is rejected withMISSING_EFFECT_FN.onCleanupis no longer allowed inside a tracked effect or a settled callback. They own teardown through the function they return, and calling it is refused withCLEANUP_IN_FORBIDDEN_SCOPE.Either error halts the reactive system, so any page reaching one renders blank.
Tabswas where promptsyntax.org hit it: the home page came up empty withMISSING_EFFECT_FN.What changed
createEffect(fn)call sites becomecreateTrackedEffect(fn), the primitive that kept Solid 1's semantics: one function, whole body tracked. This is deliberately a rename, not a rewrite. The two forms are not interchangeable, and choosing between them per site is a judgement about which reads are dependencies. Splitting them into the two-argument form is worth doing, but not in the change that makes the library run again.onCleanup. Most were a trailingonCleanupthat became areturn. Four registered cleanup from inside a conditional or partway through a callback that then bails out early: two invert the guard, and two name the teardown and return it from each exit rather than reordering the work around it.createTrackedEffectreplacescreateEffect, andonCleanupis dropped where it is no longer called.36 files, 152 insertions, 152 deletions. No public API or prop changes.
Verification
bun run buildsucceeds. Onmasterwith the same clean tree it also succeeds, so this is a like-for-like comparison.bun run lintreports the same 148 errors asmaster. The warning count differs by three, all inchatbubbleandcardgenerated files that this branch does not touch./,/spec,/syntax,/vignette. Tabs switch panels, the theme toggle flips light and dark, and client-side navigation works. Before this change the home page was blank withMISSING_EFFECT_FN, and after the first commit alone it still threwCLEANUP_IN_FORBIDDEN_SCOPE.Follow-up worth tracking separately
Moving these 65 sites onto the two-argument
createEffectwould make dependencies explicit and is the shape Solid 2 is steering toward. It needs a per-site decision about which reads are dependencies, so it belongs in its own change with its own review.