diff --git a/.changeset/olive-kangaroos-brake.md b/.changeset/olive-kangaroos-brake.md new file mode 100644 index 000000000000..68f3d407048b --- /dev/null +++ b/.changeset/olive-kangaroos-brake.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: improve internal signal dependency checking logic diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index 946a6c3196fd..1e5301a97004 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -349,15 +349,21 @@ function execute_signal_fn(signal) { if (current_dependencies !== null) { let i; if (dependencies !== null) { - const dep_length = dependencies.length; + // Include any dependencies up until the current_dependencies_index. + const full_dependencies = + current_dependencies_index === 0 + ? dependencies + : dependencies.slice(0, current_dependencies_index).concat(current_dependencies); + const dep_length = full_dependencies.length; // If we have more than 16 elements in the array then use a Set for faster performance // TODO: evaluate if we should always just use a Set or not here? - const current_dependencies_set = dep_length > 16 ? new Set(current_dependencies) : null; + const current_dependencies_set = dep_length > 16 ? new Set(full_dependencies) : null; + for (i = current_dependencies_index; i < dep_length; i++) { - const dependency = dependencies[i]; + const dependency = full_dependencies[i]; if ( (current_dependencies_set !== null && !current_dependencies_set.has(dependency)) || - !current_dependencies.includes(dependency) + !full_dependencies.includes(dependency) ) { remove_consumer(signal, dependency, false); } diff --git a/packages/svelte/tests/runtime-runes/samples/each-updates/_config.js b/packages/svelte/tests/runtime-runes/samples/each-updates/_config.js index a6cdafd20f4e..13b0b4aed769 100644 --- a/packages/svelte/tests/runtime-runes/samples/each-updates/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/each-updates/_config.js @@ -33,7 +33,7 @@ export default test({ assert.htmlEqual( target.innerHTML, - `
test costs $1
test 2 costs $2000
test costs $1
test 2 costs $2000
` + `test costs $1
test 2 costs $2
test costs $1
test 2 costs $2
` ); } }); diff --git a/packages/svelte/tests/runtime-runes/samples/text-effect-multi-deps/_config.js b/packages/svelte/tests/runtime-runes/samples/text-effect-multi-deps/_config.js new file mode 100644 index 000000000000..7dba287f5a89 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/text-effect-multi-deps/_config.js @@ -0,0 +1,22 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; + +export default test({ + html: `0 - 0
{ + btn1.click(); + }); + + assert.htmlEqual(target.innerHTML, `1 - 1
{ + btn1.click(); + }); + + assert.htmlEqual(target.innerHTML, `2 - 2
+ let x = $state({a: 0, b:0}); + let count = 0; + + +{x.a} - {x.b}
+ + +