diff --git a/.changeset/big-moons-occur.md b/.changeset/big-moons-occur.md new file mode 100644 index 0000000000..42429d31f6 --- /dev/null +++ b/.changeset/big-moons-occur.md @@ -0,0 +1,5 @@ +--- +"svelte": patch +--- + +fix: improve unowned derived signal heuristics diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index d3d7e88412..28428c1fb7 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -171,6 +171,7 @@ export function check_dirtiness(reaction) { if ((flags & MAYBE_DIRTY) !== 0) { var dependencies = reaction.deps; + var is_unowned = (flags & UNOWNED) !== 0; if (dependencies !== null) { var length = dependencies.length; @@ -191,7 +192,6 @@ export function check_dirtiness(reaction) { // if our dependency write version is higher. If it is then we can assume // that state has changed to a newer version and thus this unowned signal // is also dirty. - var is_unowned = (flags & UNOWNED) !== 0; var version = dependency.version; if (is_unowned && version > /** @type {import('#client').Derived} */ (reaction).version) { @@ -201,7 +201,10 @@ export function check_dirtiness(reaction) { } } - set_signal_status(reaction, CLEAN); + // Unowned signals are always maybe dirty, as we instead check their dependency versions. + if (!is_unowned) { + set_signal_status(reaction, CLEAN); + } } return false; diff --git a/packages/svelte/tests/runtime-runes/samples/derived-unowned-4/_config.js b/packages/svelte/tests/runtime-runes/samples/derived-unowned-4/_config.js new file mode 100644 index 0000000000..4868a77076 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/derived-unowned-4/_config.js @@ -0,0 +1,17 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; + +export default test({ + async test({ assert, target }) { + let [btn1] = target.querySelectorAll('button'); + + flushSync(() => { + btn1.click(); + }); + + assert.htmlEqual( + target.innerHTML, + `