fix: avoid flushing sync with $inspect (#13239)

* fix: avoid flushing sync with $inspect

* add test
pull/13257/head
Dominic Gannaway 4 days ago committed by GitHub
parent 3d256727bb
commit 36a73fa794
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: avoid flushing sync with $inspect

@ -16,8 +16,9 @@ import {
update_effect, update_effect,
derived_sources, derived_sources,
set_derived_sources, set_derived_sources,
flush_sync, check_dirtiness,
check_dirtiness set_is_flushing_effect,
is_flushing_effect
} from '../runtime.js'; } from '../runtime.js';
import { equals, safe_equals } from './equality.js'; import { equals, safe_equals } from './equality.js';
import { import {
@ -170,23 +171,21 @@ export function set(source, value) {
if (DEV && inspect_effects.size > 0) { if (DEV && inspect_effects.size > 0) {
const inspects = Array.from(inspect_effects); const inspects = Array.from(inspect_effects);
if (current_effect === null) { var previously_flushing_effect = is_flushing_effect;
// Triggering an effect sync can tear the signal graph, so to avoid this we need set_is_flushing_effect(true);
// to ensure the graph has been flushed before triggering any inspect effects. try {
// Only needed when there's currently no effect, and flushing with one present for (const effect of inspects) {
// could have other unintended consequences, like effects running out of order. // Mark clean inspect-effects as maybe dirty and then check their dirtiness
// This is expensive, but given this is a DEV mode only feature, it should be fine // instead of just updating the effects - this way we avoid overfiring.
flush_sync(); if ((effect.f & CLEAN) !== 0) {
} set_signal_status(effect, MAYBE_DIRTY);
for (const effect of inspects) { }
// Mark clean inspect-effects as maybe dirty and then check their dirtiness if (check_dirtiness(effect)) {
// instead of just updating the effects - this way we avoid overfiring. update_effect(effect);
if ((effect.f & CLEAN) !== 0) { }
set_signal_status(effect, MAYBE_DIRTY);
}
if (check_dirtiness(effect)) {
update_effect(effect);
} }
} finally {
set_is_flushing_effect(previously_flushing_effect);
} }
inspect_effects.clear(); inspect_effects.clear();
} }

@ -0,0 +1,26 @@
import { test } from '../../test';
import { flushSync } from 'svelte';
export default test({
async test({ assert, target, logs }) {
const [b1] = target.querySelectorAll('button');
flushSync(() => {
b1.click();
});
flushSync(() => {
b1.click();
});
assert.deepEqual(logs, [
'effect',
0,
'in-increment',
1,
'effect',
1,
'in-increment',
2,
'effect',
2
]);
}
});

@ -0,0 +1,18 @@
<script>
let count = $state(0);
function increment() {
count += 1;
console.log("in-increment", count);
}
$effect(() => {
console.log("effect", count);
});
$inspect(count);
</script>
<button onclick={increment}>
clicks: {count}
</button>
Loading…
Cancel
Save