fix: add top level snippets to instance scope (#9467)

fixes #9460
pull/9492/head
Simon H 11 months ago committed by GitHub
parent 1beb5e8dc9
commit 4418ba6535
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: add top level snippets to instance scope

@ -273,15 +273,6 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
next({ scope }); next({ scope });
}; };
/**
* @type {import('zimmerframe').Visitor<import('#compiler').SvelteNode, State, import('#compiler').SvelteNode>}
*/
const CreateBlock = (node, { state, next }) => {
const scope = state.scope.child();
scopes.set(node, scope);
next({ scope });
};
/** /**
* @param {import('#compiler').ElementLike} node * @param {import('#compiler').ElementLike} node
* @param {Scope} parent * @param {Scope} parent
@ -566,18 +557,24 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
}, },
SnippetBlock(node, context) { SnippetBlock(node, context) {
state.scope.declare(node.expression, 'normal', 'function', node.expression); // Special-case for root-level snippets: they become part of the instance scope
const is_top_level = !context.path.at(-2);
let scope = state.scope;
if (is_top_level) {
scope = /** @type {Scope} */ (parent);
}
scope.declare(node.expression, 'normal', 'function', node.expression);
const scope = state.scope.child(); const child_scope = state.scope.child();
scopes.set(node, scope); scopes.set(node, child_scope);
if (node.context) { if (node.context) {
for (const id of extract_identifiers(node.context)) { for (const id of extract_identifiers(node.context)) {
scope.declare(id, 'each', 'let'); child_scope.declare(id, 'each', 'let');
} }
} }
context.next({ scope }); context.next({ scope: child_scope });
}, },
Fragment: (node, context) => { Fragment: (node, context) => {
@ -586,9 +583,6 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
context.next({ scope }); context.next({ scope });
}, },
// TODO this will be unnecessary when we switch to fragments
IfBlock: CreateBlock,
BindDirective(node, context) { BindDirective(node, context) {
updates.push([ updates.push([
context.state.scope, context.state.scope,

@ -0,0 +1,9 @@
import { ok, test } from '../../test';
export default test({
test({ target }) {
const button = target.querySelector('button');
ok(button);
button.click();
}
});

@ -0,0 +1,13 @@
<script>
function log() {
// Test that the log function is not hoisted. If it was, this would make the test
// pass still, but Vitest would error because it sees that there are unhandled errors
snippet;
}
</script>
{#snippet snippet()}Hello{/snippet}
<button on:click={log}>
log snippet
</button>
Loading…
Cancel
Save