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

* fix: avoid flushing sync with $inspect

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

@ -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