fix: correctly compile $effect.root in svelte modules (#12315)

Fixes #12222
pull/12307/head
Dominic Gannaway 4 months ago committed by GitHub
parent b2448dcc5c
commit b3c002a703
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: correctly compile $effect.root in svelte modules

@ -411,6 +411,14 @@ const global_visitors = {
return b.literal(false);
}
if (rune === '$effect.root') {
const args = /** @type {import('estree').Expression[]} */ (
node.arguments.map((arg) => context.visit(arg))
);
// Just call the function directly
return b.call(args[0]);
}
if (rune === '$state.snapshot') {
return /** @type {import('estree').Expression} */ (context.visit(node.arguments[0]));
}
@ -571,7 +579,7 @@ const javascript_visitors_runes = {
for (const declarator of node.declarations) {
const init = declarator.init;
const rune = get_rune(init, state.scope);
if (!rune || rune === '$effect.tracking' || rune === '$inspect') {
if (!rune || rune === '$effect.tracking' || rune === '$inspect' || rune === '$effect.root') {
declarations.push(/** @type {import('estree').VariableDeclarator} */ (visit(declarator)));
continue;
}

@ -0,0 +1,30 @@
import { flushSync } from 'svelte';
import { test } from '../../test';
export default test({
html: '<button>0</button><button>0</button><button>cleanup</button>',
async test({ assert, target, logs }) {
const [b1, b2, b3] = target.querySelectorAll('button');
flushSync(() => {
b1.click();
b2.click();
});
assert.deepEqual(logs, [0, 1]);
flushSync(() => {
b3.click();
});
assert.deepEqual(logs, [0, 1, 'cleanup 1', 'cleanup 2']);
flushSync(() => {
b1.click();
b2.click();
});
assert.deepEqual(logs, [0, 1, 'cleanup 1', 'cleanup 2']);
}
});

@ -0,0 +1,11 @@
<script>
import { with_root } from './root.svelte.js';
let x = $state(0);
let y = $state(0);
const cleanup = with_root(() => x)
</script>
<button onclick={() => x++}>{x}</button>
<button onclick={() => y++}>{y}</button>
<button onclick={cleanup}>cleanup</button>

@ -0,0 +1,20 @@
export function with_root(get_x) {
const cleanup = $effect.root(() => {
$effect(() => {
console.log(get_x());
});
const nested_cleanup = $effect.root(() => {
return () => {
console.log('cleanup 2');
};
});
return () => {
console.log('cleanup 1');
nested_cleanup();
};
});
return cleanup;
}
Loading…
Cancel
Save