chore: hoist IfBlock else if block cases

pull/9585/head
Dominic Gannaway 3 years ago
parent 46c572a14d
commit 21cab18f80

@ -0,0 +1,5 @@
---
'svelte': patch
---
chore: hoist else-if block closures

@ -93,7 +93,8 @@ export function client_component(source, analysis, options) {
preserve_whitespace: options.preserveWhitespace, preserve_whitespace: options.preserveWhitespace,
public_state: new Map(), public_state: new Map(),
private_state: new Map(), private_state: new Map(),
in_constructor: false in_constructor: false,
else_if_init: null
}; };
const module = /** @type {import('estree').Program} */ ( const module = /** @type {import('estree').Program} */ (
@ -466,7 +467,8 @@ export function client_module(analysis, options) {
legacy_reactive_statements: new Map(), legacy_reactive_statements: new Map(),
public_state: new Map(), public_state: new Map(),
private_state: new Map(), private_state: new Map(),
in_constructor: false in_constructor: false,
else_if_init: null
}; };
const module = /** @type {import('estree').Program} */ ( const module = /** @type {import('estree').Program} */ (

@ -19,6 +19,12 @@ export interface ClientTransformState extends TransformState {
*/ */
readonly in_constructor: boolean; readonly in_constructor: boolean;
/**
* `true` if the current lexical scope belongs to the alternate of an IfBlock. This
* allows us to hoist alternate if-blocks to the same scope as the original IfBlock.
*/
readonly else_if_init: null | Statement[];
/** The $: calls, which will be ordered in the end */ /** The $: calls, which will be ordered in the end */
readonly legacy_reactive_statements: Map<LabeledStatement, Statement>; readonly legacy_reactive_statements: Map<LabeledStatement, Statement>;
} }

@ -2298,6 +2298,28 @@ export const template_visitors = {
const consequent = /** @type {import('estree').BlockStatement} */ ( const consequent = /** @type {import('estree').BlockStatement} */ (
context.visit(node.consequent) context.visit(node.consequent)
); );
const in_else_if =
node.alternate !== null &&
node.alternate.nodes.length === 1 &&
node.alternate.nodes[0].type === 'IfBlock';
const else_if_init = in_else_if ? context.state.else_if_init || context.state.init : null;
const else_if_block_id = in_else_if ? context.state.scope.generate('else_if') : null;
const alternate = node.alternate
? b.arrow(
[b.id('$$anchor')],
/** @type {import('estree').BlockStatement} */ (
context.visit(node.alternate, {
...context.state,
else_if_init
})
)
)
: null;
if (else_if_block_id && else_if_init && alternate) {
else_if_init.push(b.var(else_if_block_id, alternate));
}
context.state.after_update.push( context.state.after_update.push(
b.stmt( b.stmt(
@ -2306,12 +2328,7 @@ export const template_visitors = {
context.state.node, context.state.node,
b.thunk(/** @type {import('estree').Expression} */ (context.visit(node.test))), b.thunk(/** @type {import('estree').Expression} */ (context.visit(node.test))),
b.arrow([b.id('$$anchor')], consequent), b.arrow([b.id('$$anchor')], consequent),
node.alternate alternate ? (else_if_block_id ? b.id(else_if_block_id) : alternate) : b.literal(null)
? b.arrow(
[b.id('$$anchor')],
/** @type {import('estree').BlockStatement} */ (context.visit(node.alternate))
)
: b.literal(null)
) )
) )
); );

Loading…
Cancel
Save