mirror of https://github.com/sveltejs/svelte
fix: unset context synchronously in `run` (#18236)
Our `run` function which executes top level awaits (and synchronous statements in-between/after) did not unset the context in time in case the function returns an async value. In that case the context was still around until the that promise resolves, which can be too late because unrelated things can be intertwined with the batch. The test shows this: Without the fix, the unrelated count incrementation would not update the view until the top level awaits in the child are done. In the test this just shows as a delayed visual update, but it also can result in stale roots as shown in https://github.com/sveltejs/svelte/issues/18221#issuecomment-4470921077pull/18239/head
parent
4d8f99a270
commit
eb10a70cf1
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
fix: unset context synchronously in `run`
|
||||
@ -0,0 +1,7 @@
|
||||
<script>
|
||||
import { push } from "./main.svelte";
|
||||
const x = await push(1);
|
||||
const y = await push(2);
|
||||
</script>
|
||||
|
||||
{x} {y}
|
||||
@ -0,0 +1,26 @@
|
||||
import { tick } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
async test({ assert, target }) {
|
||||
const [show, resolve, count] = target.querySelectorAll('button');
|
||||
|
||||
show.click();
|
||||
await tick();
|
||||
resolve.click();
|
||||
await tick();
|
||||
count.click();
|
||||
await tick();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
'<button>show</button> <button>resolve</button> <button>1</button>'
|
||||
);
|
||||
|
||||
resolve.click();
|
||||
await tick();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
'1 2 <button>show</button> <button>resolve</button> <button>1</button>'
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,23 @@
|
||||
<script module>
|
||||
const queued = [];
|
||||
export function push(v) {
|
||||
return new Promise((fulfil) => {
|
||||
queued.push(() => fulfil(v));
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
import Child from "./Child.svelte";
|
||||
|
||||
let show = $state(false);
|
||||
let count = $state(0);
|
||||
</script>
|
||||
|
||||
{#if show}
|
||||
<Child />
|
||||
{/if}
|
||||
|
||||
<button onclick={() => show = true}>show</button>
|
||||
<button onclick={() => queued.shift()?.()}>resolve</button>
|
||||
<button onclick={() => count++}>{count}</button>
|
||||
Loading…
Reference in new issue