fix: improve internal signal dependency checking logic (#10111)

pull/10113/head
Dominic Gannaway 11 months ago committed by GitHub
parent 0c58524d23
commit ebbb5dd655
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: improve internal signal dependency checking logic

@ -349,15 +349,21 @@ function execute_signal_fn(signal) {
if (current_dependencies !== null) { if (current_dependencies !== null) {
let i; let i;
if (dependencies !== null) { 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 // 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? // 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++) { for (i = current_dependencies_index; i < dep_length; i++) {
const dependency = dependencies[i]; const dependency = full_dependencies[i];
if ( if (
(current_dependencies_set !== null && !current_dependencies_set.has(dependency)) || (current_dependencies_set !== null && !current_dependencies_set.has(dependency)) ||
!current_dependencies.includes(dependency) !full_dependencies.includes(dependency)
) { ) {
remove_consumer(signal, dependency, false); remove_consumer(signal, dependency, false);
} }

@ -33,7 +33,7 @@ export default test({
assert.htmlEqual( assert.htmlEqual(
target.innerHTML, target.innerHTML,
`<p>test costs $1</p><p>test 2 costs $2000</p><p>test costs $1</p><p>test 2 costs $2000</p><button>add</button><button>change</button><button>reload</button>` `<p>test costs $1</p><p>test 2 costs $2</p><p>test costs $1</p><p>test 2 costs $2</p><button>add</button><button>change</button><button>reload</button>`
); );
} }
}); });

@ -0,0 +1,22 @@
import { flushSync } from 'svelte';
import { test } from '../../test';
export default test({
html: `<p>0 - 0</p><button>+</button`,
async test({ assert, target }) {
const [btn1] = target.querySelectorAll('button');
flushSync(() => {
btn1.click();
});
assert.htmlEqual(target.innerHTML, `<p>1 - 1</p><button>+</button`);
flushSync(() => {
btn1.click();
});
assert.htmlEqual(target.innerHTML, `<p>2 - 2</p><button>+</button`);
}
});

@ -0,0 +1,12 @@
<script>
let x = $state({a: 0, b:0});
let count = 0;
</script>
<p>{x.a} - {x.b}</p>
<button onclick={() => {
const a = ++count;
x = {a, b: a};
}}>+</button>
Loading…
Cancel
Save