diff --git a/.changeset/shiny-melons-love.md b/.changeset/shiny-melons-love.md
new file mode 100644
index 0000000000..5633aff875
--- /dev/null
+++ b/.changeset/shiny-melons-love.md
@@ -0,0 +1,5 @@
+---
+"svelte": patch
+---
+
+fix: ensure derived is detected as dirty correctly
diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js
index 97f7c5c813..a9dee752e1 100644
--- a/packages/svelte/src/internal/client/runtime.js
+++ b/packages/svelte/src/internal/client/runtime.js
@@ -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;
}
}
}
diff --git a/packages/svelte/tests/runtime-runes/samples/derived-cascade/_config.js b/packages/svelte/tests/runtime-runes/samples/derived-cascade/_config.js
new file mode 100644
index 0000000000..ddadfb64f7
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/derived-cascade/_config.js
@@ -0,0 +1,12 @@
+import { test } from '../../test';
+
+export default test({
+ html: ``,
+
+ async test({ assert, target }) {
+ const btn = target.querySelector('button');
+ await btn?.click();
+
+ assert.htmlEqual(target.innerHTML, ``);
+ }
+});
diff --git a/packages/svelte/tests/runtime-runes/samples/derived-cascade/main.svelte b/packages/svelte/tests/runtime-runes/samples/derived-cascade/main.svelte
new file mode 100644
index 0000000000..c0d45c8532
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/derived-cascade/main.svelte
@@ -0,0 +1,12 @@
+
+
+