fix: hoist snippets above const in same block (#17516)

* fix: hoist snippets above const in same block

* fix: type error
pull/17518/head
Paolo Ricciuti 7 months ago committed by GitHub
parent c1fab8caae
commit d95887deb6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: hoist snippets above const in same block

@ -170,6 +170,7 @@ export function client_component(analysis, options) {
// these are set inside the `Fragment` visitor, and cannot be used until then
init: /** @type {any} */ (null),
consts: /** @type {any} */ (null),
snippets: /** @type {any} */ (null),
let_directives: /** @type {any} */ (null),
update: /** @type {any} */ (null),
after_update: /** @type {any} */ (null),

@ -49,6 +49,8 @@ export interface ComponentClientTransformState extends ClientTransformState {
readonly update: Statement[];
/** Stuff that happens after the render effect (control blocks, dynamic elements, bindings, actions, etc) */
readonly after_update: Statement[];
/** Transformed `{#snippets }` declarations */
readonly snippets: Statement[];
/** Transformed `{@const }` declarations */
readonly consts: Statement[];
/** Transformed async `{@const }` declarations (if any) and those coming after them */

@ -1,13 +1,13 @@
/** @import { Expression, Statement } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentClientTransformState, ComponentContext } from '../types' */
import { TEMPLATE_FRAGMENT, TEMPLATE_USE_IMPORT_NODE } from '../../../../../constants.js';
import * as b from '#compiler/builders';
import { TEMPLATE_FRAGMENT, TEMPLATE_USE_IMPORT_NODE } from '../../../../../constants.js';
import { clean_nodes, infer_namespace } from '../../utils.js';
import { transform_template } from '../transform-template/index.js';
import { Template } from '../transform-template/template.js';
import { process_children } from './shared/fragment.js';
import { build_render_statement, Memoizer } from './shared/utils.js';
import { Template } from '../transform-template/template.js';
/**
* @param {AST.Fragment} node
@ -60,6 +60,7 @@ export function Fragment(node, context) {
const state = {
...context.state,
init: [],
snippets: [],
consts: [],
let_directives: [],
update: [],
@ -150,7 +151,7 @@ export function Fragment(node, context) {
}
}
body.push(...state.let_directives, ...state.consts);
body.push(...state.snippets, ...state.let_directives, ...state.consts);
if (state.async_consts && state.async_consts.thunks.length > 0) {
body.push(b.var(state.async_consts.id, b.call('$.run', b.array(state.async_consts.thunks))));

@ -329,7 +329,7 @@ export function RegularElement(node, context) {
);
/** @type {typeof state} */
const child_state = { ...state, init: [], update: [], after_update: [] };
const child_state = { ...state, init: [], update: [], after_update: [], snippets: [] };
for (const node of hoisted) {
context.visit(node, child_state);
@ -441,6 +441,7 @@ export function RegularElement(node, context) {
// Wrap children in `{...}` to avoid declaration conflicts
context.state.init.push(
b.block([
...child_state.snippets,
...child_state.init,
...element_state.init,
child_state.update.length > 0 ? build_render_statement(child_state) : b.empty,

@ -89,6 +89,6 @@ export function SnippetBlock(node, context) {
context.state.instance_level_snippets.push(declaration);
}
} else {
context.state.init.push(declaration);
context.state.snippets.push(declaration);
}
}

@ -77,7 +77,7 @@ export function SvelteBoundary(node, context) {
/** @type {Statement[]} */
const statements = [];
context.visit(child, { ...context.state, init: statements });
context.visit(child, { ...context.state, snippets: statements });
const snippet = /** @type {VariableDeclaration} */ (statements[0]);

@ -333,7 +333,7 @@ export function build_component(node, component_name, loc, context) {
// can be used as props without creating conflicts
context.visit(child, {
...context.state,
init: snippet_declarations
snippets: snippet_declarations
});
push_prop(b.prop('init', child.expression, child.expression));

@ -0,0 +1,5 @@
import { test } from '../../test';
export default test({
test() {}
});

@ -0,0 +1,4 @@
{#if true}
{@const xx = test}
{#snippet test()}{/snippet}
{/if}
Loading…
Cancel
Save