diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index 3a31c175f1..5f59b7aeac 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -664,15 +664,18 @@ function reconnect(derived) { /** * Removes the WAS_MARKED flag from the derived and its dependencies - * @param {Derived} derived + * @param {Value} derived */ function remove_marked_flag(derived) { - if ((derived.f & WAS_MARKED) === 0) return; - derived.f ^= WAS_MARKED; + // We cannot stop at the first non-marked derived because batch_values can + // cause "holes" of unmarked deriveds in an otherwise marked graph + if ((derived.f & DERIVED) === 0) return; + + derived.f &= ~WAS_MARKED; // Only deriveds with dependencies can be marked - for (const dep of /** @type {Value[]} */ (derived.deps)) { - remove_marked_flag(/** @type {Derived} */ (dep)); + for (const dep of /** @type {Value[]} */ (/** @type {Derived} */ (derived).deps)) { + remove_marked_flag(dep); } } diff --git a/packages/svelte/tests/runtime-runes/samples/async-derived-in-multiple-effects/Component.svelte b/packages/svelte/tests/runtime-runes/samples/async-derived-in-multiple-effects/Component.svelte new file mode 100644 index 0000000000..200778dc5b --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/async-derived-in-multiple-effects/Component.svelte @@ -0,0 +1,27 @@ + diff --git a/packages/svelte/tests/runtime-runes/samples/async-derived-in-multiple-effects/_config.js b/packages/svelte/tests/runtime-runes/samples/async-derived-in-multiple-effects/_config.js new file mode 100644 index 0000000000..600e7f096b --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/async-derived-in-multiple-effects/_config.js @@ -0,0 +1,18 @@ +import { tick } from 'svelte'; +import { test } from '../../test'; + +export default test({ + async test({ assert, target, logs }) { + const button = target.querySelector('button'); + + button?.click(); + await tick(); + // TODO this is wrong: it should be [5] + assert.deepEqual(logs, [4]); + + button?.click(); + await tick(); + // TODO this is wrong: it should be [5, 7] + assert.deepEqual(logs, [4, 7]); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/async-derived-in-multiple-effects/main.svelte b/packages/svelte/tests/runtime-runes/samples/async-derived-in-multiple-effects/main.svelte new file mode 100644 index 0000000000..bd82e35a3b --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/async-derived-in-multiple-effects/main.svelte @@ -0,0 +1,19 @@ + + + + {await new Promise((r) => { + // long enough for the test to do all its other stuff while this is pending + setTimeout(r, 10); + })} + {#snippet pending()}{/snippet} + + + + +{#if count > 0} + +{/if}