mirror of https://github.com/sveltejs/svelte
149 lines
4.6 KiB
149 lines
4.6 KiB
import deindent from '../../../utils/deindent.js';
|
|
import visit from '../visit.js';
|
|
|
|
function isElseIf ( node ) {
|
|
return node && node.children.length === 1 && node.children[0].type === 'IfBlock';
|
|
}
|
|
|
|
function getBranches ( generator, block, state, node ) {
|
|
const branches = [{
|
|
condition: block.contextualise( node.expression ).snippet,
|
|
block: node._block.name,
|
|
dynamic: node._block.dependencies.size > 0
|
|
}];
|
|
|
|
visitChildren( generator, block, state, node );
|
|
|
|
if ( isElseIf( node.else ) ) {
|
|
branches.push(
|
|
...getBranches( generator, block, state, node.else.children[0] )
|
|
);
|
|
} else {
|
|
branches.push({
|
|
condition: null,
|
|
block: node.else ? node.else._block.name : null,
|
|
dynamic: node.else ? node.else._block.dependencies.size > 0 : false
|
|
});
|
|
|
|
if ( node.else ) {
|
|
visitChildren( generator, block, state, node.else );
|
|
}
|
|
}
|
|
|
|
return branches;
|
|
}
|
|
|
|
function visitChildren ( generator, block, state, node ) {
|
|
node.children.forEach( child => {
|
|
visit( generator, node._block, node._state, child );
|
|
});
|
|
}
|
|
|
|
export default function visitIfBlock ( generator, block, state, node ) {
|
|
const name = generator.getUniqueName( `if_block` );
|
|
const anchor = generator.getUniqueName( `${name}_anchor` );
|
|
const params = block.params.join( ', ' );
|
|
|
|
const vars = { name, anchor, params };
|
|
|
|
block.createAnchor( anchor, state.parentNode );
|
|
|
|
const branches = getBranches( generator, block, state, node, generator.getUniqueName( `create_if_block` ) );
|
|
const dynamic = branches.some( branch => branch.dynamic );
|
|
|
|
if ( node.else ) {
|
|
compound( generator, block, state, node, branches, dynamic, vars );
|
|
} else {
|
|
simple( generator, block, state, node, branches[0], dynamic, vars );
|
|
}
|
|
|
|
block.builders.destroy.addLine(
|
|
`if ( ${name} ) ${name}.destroy( ${state.parentNode ? 'false' : 'detach'} );`
|
|
);
|
|
}
|
|
|
|
function simple ( generator, block, state, node, branch, dynamic, { name, anchor, params } ) {
|
|
block.builders.create.addBlock( deindent`
|
|
var ${name} = ${branch.condition} && ${branch.block}( ${params}, ${block.component} );
|
|
` );
|
|
|
|
const isToplevel = !state.parentNode;
|
|
|
|
if ( isToplevel ) {
|
|
block.builders.mount.addLine( `if ( ${name} ) ${name}.mount( ${block.target}, ${anchor} );` );
|
|
} else {
|
|
block.builders.create.addLine( `if ( ${name} ) ${name}.mount( ${state.parentNode}, null );` );
|
|
}
|
|
|
|
if ( dynamic ) {
|
|
block.builders.update.addBlock( deindent`
|
|
if ( ${branch.condition} ) {
|
|
if ( ${name} ) {
|
|
${name}.update( changed, ${params} );
|
|
} else {
|
|
${name} = ${branch.block}( ${params}, ${block.component} );
|
|
${name}.mount( ${anchor}.parentNode, ${anchor} );
|
|
}
|
|
} else if ( ${name} ) {
|
|
${name}.destroy( true );
|
|
${name} = null;
|
|
}
|
|
` );
|
|
} else {
|
|
block.builders.update.addBlock( deindent`
|
|
if ( ${branch.condition} ) {
|
|
if ( !${name} ) {
|
|
${name} = ${branch.block}( ${params}, ${block.component} );
|
|
${name}.mount( ${anchor}.parentNode, ${anchor} );
|
|
}
|
|
} else if ( ${name} ) {
|
|
${name}.destroy( true );
|
|
${name} = null;
|
|
}
|
|
` );
|
|
}
|
|
}
|
|
|
|
function compound ( generator, block, state, node, branches, dynamic, { name, anchor, params } ) {
|
|
const getBlock = block.getUniqueName( `get_block` );
|
|
const current_block = block.getUniqueName( `current_block` );
|
|
|
|
block.builders.create.addBlock( deindent`
|
|
function ${getBlock} ( ${params} ) {
|
|
${branches.map( ({ condition, block }) => {
|
|
return `${condition ? `if ( ${condition} ) ` : ''}return ${block};`;
|
|
} ).join( '\n' )}
|
|
}
|
|
|
|
var ${current_block} = ${getBlock}( ${params} );
|
|
var ${name} = ${current_block} && ${current_block}( ${params}, ${block.component} );
|
|
` );
|
|
|
|
const isToplevel = !state.parentNode;
|
|
|
|
if ( isToplevel ) {
|
|
block.builders.mount.addLine( `if ( ${name} ) ${name}.mount( ${block.target}, ${anchor} );` );
|
|
} else {
|
|
block.builders.create.addLine( `if ( ${name} ) ${name}.mount( ${state.parentNode}, null );` );
|
|
}
|
|
|
|
if ( dynamic ) {
|
|
block.builders.update.addBlock( deindent`
|
|
if ( ${current_block} === ( ${current_block} = ${getBlock}( ${params} ) ) && ${name} ) {
|
|
${name}.update( changed, ${params} );
|
|
} else {
|
|
if ( ${name} ) ${name}.destroy( true );
|
|
${name} = ${current_block} && ${current_block}( ${params}, ${block.component} );
|
|
if ( ${name} ) ${name}.mount( ${anchor}.parentNode, ${anchor} );
|
|
}
|
|
` );
|
|
} else {
|
|
block.builders.update.addBlock( deindent`
|
|
if ( ${current_block} !== ( ${current_block} = ${getBlock}( ${params} ) ) ) {
|
|
if ( ${name} ) ${name}.destroy( true );
|
|
${name} = ${current_block} && ${current_block}( ${params}, ${block.component} );
|
|
if ( ${name} ) ${name}.mount( ${anchor}.parentNode, ${anchor} );
|
|
}
|
|
` );
|
|
}
|
|
} |