Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/flat-points-kick.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte': patch
---

fix: reset `is_flushing` if `flushSync` is called and there's no scheduled effect
7 changes: 7 additions & 0 deletions packages/svelte/src/internal/client/runtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,13 @@ export function flushSync(fn) {
flush_tasks();

if (queued_root_effects.length === 0) {
// this would be reset in `flush_queued_root_effects` but since we are early returning here,
// we need to reset it here as well
is_flushing = false;
last_scheduled_effect = null;
if (DEV) {
dev_effect_stack = [];
}
return /** @type {T} */ (result);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { ok, test } from '../../test';

export default test({
async test({ assert, target }) {
const btn = target.querySelector('button');
const main = target.querySelector('main');
ok(main);
console.log(main.innerHTML);
assert.htmlEqual(main.innerHTML, `<div>true</div>`);
// we don't want to use flush sync (or tick that use it inside) since we are testing that calling `flushSync` once
// when there are no scheduled effects does not cause reactivity to break
btn?.click();
await Promise.resolve();
assert.htmlEqual(main.innerHTML, `<div>false</div> <div>false</div>`);
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<script>
import { flushSync } from 'svelte'

let flag = $state(true)
let test = $state(true);
</script>

<button onclick={()=>{
flushSync(() => {
test = !test
})

flag = !flag;
}}>switch</button>

<main>
<div>{flag}</div>

{#if !flag}
<div>{test} </div>
{/if}
</main>