fix: ensure derived is detected as dirty correctly (#11496)

Deriveds where under certain conditions not detected as dirty correctly. The reason is that a transitive check_dirtiness call could update the flag of a derived, even if the condition doesn't ulimately result to true. That's why the check for "is now dirty" needs to be moved out of the inner if block.
Fixes #11481

This may also fix a yet undetected overfiring bug in the "is unowned" case because the previous inner "is now dirty?" check didn't take unowned into account.
pull/11474/head
Simon H 8 months ago committed by GitHub
parent d86b05279f
commit 6bd6f0971b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
"svelte": patch
---
fix: ensure derived is detected as dirty correctly

@ -197,11 +197,6 @@ export function check_dirtiness(reaction) {
if (!is_dirty && check_dirtiness(/** @type {import('#client').Derived} */ (dependency))) {
update_derived(/** @type {import('#client').Derived} **/ (dependency), true);
// `signal` might now be dirty, as a result of calling `update_derived`
if ((reaction.f & DIRTY) !== 0) {
return true;
}
}
if (is_unowned) {
@ -227,6 +222,9 @@ export function check_dirtiness(reaction) {
reactions.push(reaction);
}
}
} else if ((reaction.f & DIRTY) !== 0) {
// `signal` might now be dirty, as a result of calling `check_dirtiness` and/or `update_derived`
return true;
}
}
}

@ -0,0 +1,12 @@
import { test } from '../../test';
export default test({
html: `<button>00</button>`,
async test({ assert, target }) {
const btn = target.querySelector('button');
await btn?.click();
assert.htmlEqual(target.innerHTML, `<button>01</button>`);
}
});

@ -0,0 +1,12 @@
<script>
let shouldShow01 = $state(false);
let der1 = $derived(shouldShow01)
// der2 must depend on der1 and its output shouldn't change
let der2 = $derived(typeof der1 === "string");
let der3 = $derived(der2 ? "1" : "0");
// der3 must be read before der1
let der4 = $derived(der3 + (der1 ? "1" : "0"));
</script>
<button onclick={() => (shouldShow01 = true)}>{der4}</button>
Loading…
Cancel
Save