mirror of https://github.com/sveltejs/svelte
fix: disallow effect creation after `await` (#18299)
We incorrectly restore effect context after an`$derived(await ...)` if it occurs inside an async function, but only for those, no other `await` expressions. This is buggy and wrong. We only want to restore context _inside_ an async derived expression (including template expressions)` so that `await a + b` works correctly. It's possible that this will be a breaking change (albeit not semver-violating, because `experimental`) for some people if they are creating effects after an `await` (other than at the top level of a component). This is regrettable, but it should never have worked in the first place.pull/18311/head
parent
d4be4e2973
commit
0da9f9e2ab
@ -0,0 +1,12 @@
|
||||
import { tick } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
async test({ assert, logs }) {
|
||||
await tick();
|
||||
|
||||
assert.deepEqual(logs, [
|
||||
`effect_orphan\n\`$effect\` can only be used inside an effect (e.g. during component initialisation)\nhttps://svelte.dev/e/effect_orphan`
|
||||
]);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,14 @@
|
||||
<script>
|
||||
async function foo() {
|
||||
await 0;
|
||||
$effect(() => {
|
||||
console.log('this effect is orphaned');
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
await foo();
|
||||
} catch (e) {
|
||||
console.log(e.message)
|
||||
}
|
||||
</script>
|
||||
@ -1,14 +0,0 @@
|
||||
import { tick } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
async test({ assert, logs }) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 10));
|
||||
assert.deepEqual(logs, [1, 1]);
|
||||
const [button] = document.querySelectorAll('button');
|
||||
|
||||
button.click();
|
||||
await tick();
|
||||
assert.deepEqual(logs, [1, 1, 2]);
|
||||
}
|
||||
});
|
||||
@ -1,15 +0,0 @@
|
||||
<script>
|
||||
let increment;
|
||||
|
||||
async function fn() {
|
||||
let count = $state(1);
|
||||
increment = () => { count++; };
|
||||
const value = $derived(await count);
|
||||
$effect.pre(() => console.log(value))
|
||||
return { get value() { return value } };
|
||||
}
|
||||
fn().then(r => console.log(r.value));
|
||||
|
||||
</script>
|
||||
|
||||
<button onclick={() => increment()}>increment</button>
|
||||
Loading…
Reference in new issue