fix(signals): defer onSettled fallback cleanup to owner disposal (closes #2766)#2782
Open
tsushanth wants to merge 2 commits into
Open
fix(signals): defer onSettled fallback cleanup to owner disposal (closes #2766)#2782tsushanth wants to merge 2 commits into
tsushanth wants to merge 2 commits into
Conversation
solidjs#2766) When `onSettled` is called from a children-forbidden scope (most commonly from inside another `onSettled` callback, which runs as a tracked effect), the implementation fell back to enqueueing a one-shot callback on the global queue and invoked the returned cleanup eagerly inside the same flush: globalQueue.enqueue(EFFECT_USER, () => { const cleanup = callback(); … cleanup?.(); }); That immediately tore down helpers whose intent was "install on settle, tear down on dispose" — composable helpers using `onSettled` internally saw their subscription set up and ripped down in the same tick (solidjs#2766). Capture the calling owner and, when the callback returns a function, attach it via `cleanup()` under that owner with `runWithOwner`. The cleanup now fires when the captured owner is disposed, matching the contract of the non-forbidden path. Orphaned helpers (no owner at all) drop the cleanup rather than run it immediately — there is no point at which firing it would be correct. Add a regression test in `tests/onSettled.test.ts` that wraps the reporter's pattern (a nested `onSettled` inside an outer `onSettled`) and asserts the subscription stays alive until `dispose()`.
|
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.
Summary
Closes #2766.
onSettledfalls back to the global queue when the current owner is null or hasCONFIG_CHILDREN_FORBIDDEN. The most common trigger for that fallback isonSettled()called from inside anotheronSettled()callback (the outer callback runs as a tracked effect, which setsCONFIG_CHILDREN_FORBIDDEN). The previous fallback shape:invoked the returned cleanup eagerly inside the same flush, immediately tearing down helpers whose intent was "install on settle, tear down on dispose." Composable helpers using
onSettledinternally — subscription setup, listener install, focus management — set up and ripped themselves down in the same tick.Capture the calling owner and, when the callback returns a function, register it via
cleanup()under that owner withrunWithOwner. Cleanup now fires when the captured owner is disposed, matching the contract of the non-forbidden path. Orphaned helpers (no owner at all) drop the cleanup rather than run it immediately — there is no point at which firing it would be correct.Test plan
Added
defers cleanup from nested onSettled to owner disposal (#2766)totests/onSettled.test.tsmirroring the reporter's scenario:Result: 13/13 pass with the fix; reverting
signals.tsto upstream and re-running shows the new case fails (expected ["subscribed","unsubscribed"] to equal ["subscribed"]) — confirming the test isolates the regression.