From 27c90dfa8322c9f225e22a730a776c4f4cbd2c5e Mon Sep 17 00:00:00 2001 From: Simon H <5968653+dummdidumm@users.noreply.github.com> Date: Sat, 19 Jul 2025 08:23:27 +0200 Subject: [PATCH] fix: don't reexecute derived with no dependencies on teardown (#16438) The prior logic was wrong because it reexecuted when something was clean, but we want to when it's not. The remaining fix was to also check the reactions: If an effect is destroyed and it was the last reaction of a derived then the derived is set to `MAYBE_DIRTY`. We therefore also need to check if the derived still has anyone listening to it, and only then reexecute it. Fixes #16363 --- .changeset/clever-toys-decide.md | 5 ++++ .../svelte/src/internal/client/runtime.js | 8 +++-- .../props-derived-teardown/Teardown.svelte | 11 +++++++ .../samples/props-derived-teardown/_config.js | 30 +++++++++++++++++++ .../props-derived-teardown/main.svelte | 25 ++++++++++++++++ 5 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 .changeset/clever-toys-decide.md create mode 100644 packages/svelte/tests/runtime-runes/samples/props-derived-teardown/Teardown.svelte create mode 100644 packages/svelte/tests/runtime-runes/samples/props-derived-teardown/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/props-derived-teardown/main.svelte diff --git a/.changeset/clever-toys-decide.md b/.changeset/clever-toys-decide.md new file mode 100644 index 0000000000..57eb2b0058 --- /dev/null +++ b/.changeset/clever-toys-decide.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: don't reexecute derived with no dependencies on teardown diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index 306b9b9dd9..3d3c89975c 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -653,8 +653,12 @@ export function get(signal) { var value = derived.v; - // if the derived is dirty, or depends on the values that just changed, re-execute - if ((derived.f & CLEAN) !== 0 || depends_on_old_values(derived)) { + // if the derived is dirty and has reactions, or depends on the values that just changed, re-execute + // (a derived can be maybe_dirty due to the effect destroy removing its last reaction) + if ( + ((derived.f & CLEAN) === 0 && derived.reactions !== null) || + depends_on_old_values(derived) + ) { value = execute_derived(derived); } diff --git a/packages/svelte/tests/runtime-runes/samples/props-derived-teardown/Teardown.svelte b/packages/svelte/tests/runtime-runes/samples/props-derived-teardown/Teardown.svelte new file mode 100644 index 0000000000..f71890d31e --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/props-derived-teardown/Teardown.svelte @@ -0,0 +1,11 @@ + + +