-
-
Notifications
You must be signed in to change notification settings - Fork 4.6k
fix: ensure derived effects are recreated when needed #16595
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
Potential fix for #16594 |
6d94df6
to
e2a1d9f
Compare
e2a1d9f
to
ee2e386
Compare
@@ -671,6 +672,10 @@ export function get(signal) { | |||
|
|||
if (is_dirty(derived)) { | |||
update_derived(derived); | |||
} else if ((derived.f & HAS_EFFECTS) !== 0 && (derived.effects === null || derived.effects.length === 0)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new test can be verified by adding && false
to the end of this if statement and running pnpm test
.
Adds HAS_EFFECTS flag to track when deriveds contain side effects and re-runs computation when effects are missing after reconnection.
ee2e386
to
d4cb4e4
Compare
|
Playground demonstrating fix: https://svelte.dev/playground/719a2a834fd34d02a204ac4b7c65973b?version=pr-16595 |
Problem
Effects created inside
$derived
statements are not re-executed when the derived is accessed after being disconnected and reconnected to the reactive dependency graph.Reproduction scenario:
const result = $derived(/* contains $effect */)
This happens because when a derived is disconnected from the graph (no more reactions), its effects are destroyed via
destroy_derived_effects()
. When the derived is later reconnected, the effects are not recreated since the derived appears "clean" and doesn't need re-execution.works here: https://svelte.dev/playground/719a2a834fd34d02a204ac4b7c65973b?version=5.19.4
does not work: https://svelte.dev/playground/719a2a834fd34d02a204ac4b7c65973b?version=5.19.5
Solution
Introduce a
HAS_EFFECTS
flag that tracks when a derived has contained effects, even after they've been destroyed. During reconnection, if a derived has theHAS_EFFECTS
flag but no current effects, we force re-execution to recreate them.Changes:
HAS_EFFECTS = 1 << 24
constanteffects.js
when effects are added to derivedsruntime.js
and trigger re-execution when neededImplementation
Testing
Added a comprehensive test that:
Without fix: 0 effect executions (effects lost forever)
With fix: 1 effect execution (effects recreated on reconnection)
Impact