mirror of https://github.com/sveltejs/svelte
Merge pull request #28 from Swatinem/optimize_if
optimize generated code for if statementspull/72/head
commit
5a2e5c2510
@ -1,23 +0,0 @@
|
|||||||
import counter from '../utils/counter.js';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
enter ( generator ) {
|
|
||||||
const name = generator.current.name.replace( 'If', 'Else' );
|
|
||||||
|
|
||||||
generator.push({
|
|
||||||
name,
|
|
||||||
localElementDepth: 0,
|
|
||||||
|
|
||||||
initStatements: [],
|
|
||||||
updateStatements: [],
|
|
||||||
teardownStatements: [],
|
|
||||||
|
|
||||||
counter: counter()
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
leave ( generator ) {
|
|
||||||
generator.addRenderer( generator.current );
|
|
||||||
generator.pop();
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,125 +1,99 @@
|
|||||||
import deindent from '../utils/deindent.js';
|
import deindent from '../utils/deindent.js';
|
||||||
import counter from '../utils/counter.js';
|
import counter from '../utils/counter.js';
|
||||||
|
|
||||||
|
// collect all the conditions and blocks in the if/elseif/else chain
|
||||||
|
function generateBlock ( generator, node, name ) {
|
||||||
|
// walk the children here
|
||||||
|
generator.push({
|
||||||
|
useAnchor: true,
|
||||||
|
name,
|
||||||
|
target: 'target',
|
||||||
|
localElementDepth: 0,
|
||||||
|
|
||||||
|
initStatements: [],
|
||||||
|
updateStatements: [],
|
||||||
|
teardownStatements: [],
|
||||||
|
|
||||||
|
counter: counter()
|
||||||
|
});
|
||||||
|
node.children.forEach( generator.visit );
|
||||||
|
//generator.visit( node.children );
|
||||||
|
generator.addRenderer( generator.current );
|
||||||
|
generator.pop();
|
||||||
|
// unset the children, to avoid them being visited again
|
||||||
|
node.children = [];
|
||||||
|
}
|
||||||
|
function getConditionsAndBlocks ( generator, node, _name, i = 0 ) {
|
||||||
|
generator.addSourcemapLocations( node.expression );
|
||||||
|
const name = `${_name}_${i}`;
|
||||||
|
|
||||||
|
const conditionsAndBlocks = [{
|
||||||
|
condition: generator.contextualise( node.expression ).snippet,
|
||||||
|
block: name
|
||||||
|
}];
|
||||||
|
generateBlock( generator, node, name );
|
||||||
|
|
||||||
|
if ( node.else && node.else.children.length === 1 &&
|
||||||
|
node.else.children[0].type === 'IfBlock' ) {
|
||||||
|
conditionsAndBlocks.push(
|
||||||
|
...getConditionsAndBlocks( generator, node.else.children[0], _name, i + 1 ) );
|
||||||
|
} else {
|
||||||
|
const name = `${_name}_${i + 1}`;
|
||||||
|
conditionsAndBlocks.push({
|
||||||
|
condition: null,
|
||||||
|
block: node.else ? name : null,
|
||||||
|
});
|
||||||
|
if (node.else) {
|
||||||
|
generateBlock( generator, node.else, name );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return conditionsAndBlocks;
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
enter ( generator, node ) {
|
enter ( generator, node ) {
|
||||||
const i = generator.counters.if++;
|
const i = generator.counters.if++;
|
||||||
const name = `ifBlock_${i}`;
|
|
||||||
const renderer = `renderIfBlock_${i}`;
|
|
||||||
|
|
||||||
const elseName = `elseBlock_${i}`;
|
const { params, target } = generator.current;
|
||||||
const elseRenderer = `renderElseBlock_${i}`;
|
const name = `ifBlock_${i}`;
|
||||||
|
const getBlock = `getBlock_${i}`;
|
||||||
|
const currentBlock = `currentBlock_${i}`;
|
||||||
|
|
||||||
generator.addSourcemapLocations( node.expression );
|
const conditionsAndBlocks = getConditionsAndBlocks( generator, node, `renderIfBlock_${i}` );
|
||||||
const { snippet } = generator.contextualise( node.expression );
|
|
||||||
|
|
||||||
generator.current.initStatements.push( deindent`
|
generator.current.initStatements.push( deindent`
|
||||||
var ${name}_anchor = document.createComment( ${JSON.stringify( `#if ${generator.source.slice( node.expression.start, node.expression.end )}` )} );
|
var ${name}_anchor = document.createComment( ${JSON.stringify( `#if ${generator.source.slice( node.expression.start, node.expression.end )}` )} );
|
||||||
${generator.appendToTarget( `${name}_anchor` )};
|
${generator.appendToTarget( `${name}_anchor` )};
|
||||||
` );
|
|
||||||
|
|
||||||
if ( node.else ) {
|
function ${getBlock} ( ${params} ) {
|
||||||
generator.current.initStatements.push( deindent`
|
${conditionsAndBlocks.map( ({ condition, block }) => {
|
||||||
var ${name} = null;
|
return `${condition ? `if ( ${condition} ) ` : ''}return ${block};`;
|
||||||
var ${elseName} = null;
|
} ).join( '\n' )}
|
||||||
|
|
||||||
if ( ${snippet} ) {
|
|
||||||
${name} = ${renderer}( ${generator.current.params}, component, ${generator.current.target}, ${name}_anchor );
|
|
||||||
} else {
|
|
||||||
${elseName} = ${elseRenderer}( ${generator.current.params}, component, ${generator.current.target}, ${name}_anchor );
|
|
||||||
}
|
|
||||||
` );
|
|
||||||
} else {
|
|
||||||
generator.current.initStatements.push( deindent`
|
|
||||||
var ${name} = ${snippet} ? ${renderer}( ${generator.current.params}, component, ${generator.current.target}, ${name}_anchor ) : null;
|
|
||||||
` );
|
|
||||||
}
|
|
||||||
|
|
||||||
const ifTrue = [ deindent`
|
|
||||||
if ( !${name } ) {
|
|
||||||
${name} = ${renderer}( ${generator.current.params}, component, ${generator.current.target}, ${name}_anchor );
|
|
||||||
} else {
|
|
||||||
${name}.update( changed, ${generator.current.params} );
|
|
||||||
}
|
|
||||||
` ];
|
|
||||||
|
|
||||||
if ( node.else ) {
|
|
||||||
ifTrue.push( deindent`
|
|
||||||
if ( ${elseName } ) {
|
|
||||||
${elseName}.teardown( true );
|
|
||||||
${elseName} = null;
|
|
||||||
}
|
|
||||||
` );
|
|
||||||
}
|
|
||||||
|
|
||||||
const ifFalse = [ deindent`
|
|
||||||
if ( ${name} ) {
|
|
||||||
${name}.teardown( true );
|
|
||||||
${name} = null;
|
|
||||||
}
|
}
|
||||||
` ];
|
|
||||||
|
|
||||||
if ( node.else ) {
|
|
||||||
ifFalse.push( deindent`
|
|
||||||
if ( !${elseName } ) {
|
|
||||||
${elseName} = ${elseRenderer}( ${generator.current.params}, component, ${generator.current.target}, ${name}_anchor );
|
|
||||||
} else {
|
|
||||||
${elseName}.update( changed, ${generator.current.params} );
|
|
||||||
}
|
|
||||||
` );
|
|
||||||
}
|
|
||||||
|
|
||||||
let update = deindent`
|
var ${currentBlock} = ${getBlock}( ${params} );
|
||||||
if ( ${snippet} ) {
|
var ${name} = ${currentBlock} && ${currentBlock}( ${params}, component, ${target}, ${name}_anchor );
|
||||||
${ifTrue.join( '\n\n' )}
|
` );
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
generator.current.updateStatements.push( deindent`
|
||||||
${ifFalse.join( '\n\n' )}
|
var _${currentBlock} = ${currentBlock};
|
||||||
|
${currentBlock} = ${getBlock}( ${params} );
|
||||||
|
if ( _${currentBlock} === ${currentBlock} && ${name}) {
|
||||||
|
${name}.update( changed, ${params} );
|
||||||
|
} else {
|
||||||
|
if ( ${name} ) ${name}.teardown( true );
|
||||||
|
${name} = ${currentBlock} && ${currentBlock}( ${params}, component, ${target}, ${name}_anchor );
|
||||||
}
|
}
|
||||||
`;
|
` );
|
||||||
|
|
||||||
if ( node.else ) {
|
|
||||||
update += `\nif ( ${elseName} ) ${elseName}.update( changed, ${generator.current.params} );`;
|
|
||||||
}
|
|
||||||
|
|
||||||
generator.current.updateStatements.push( update );
|
|
||||||
|
|
||||||
const teardownStatements = [
|
const teardownStatements = [
|
||||||
`if ( ${name} ) ${name}.teardown( detach );`
|
`if ( ${name} ) ${name}.teardown( detach );`
|
||||||
];
|
];
|
||||||
|
|
||||||
if ( node.else ) {
|
|
||||||
teardownStatements.push( `if ( ${elseName} ) ${elseName}.teardown( detach );` );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( generator.current.localElementDepth === 0 ) {
|
if ( generator.current.localElementDepth === 0 ) {
|
||||||
teardownStatements.push( `if ( detach ) ${name}_anchor.parentNode.removeChild( ${name}_anchor );` );
|
teardownStatements.push( `if ( detach ) ${name}_anchor.parentNode.removeChild( ${name}_anchor );` );
|
||||||
}
|
}
|
||||||
|
|
||||||
generator.current.teardownStatements.push( teardownStatements.join( '\n' ) );
|
generator.current.teardownStatements.push( teardownStatements.join( '\n' ) );
|
||||||
|
|
||||||
generator.push({
|
|
||||||
useAnchor: true,
|
|
||||||
name: renderer,
|
|
||||||
target: 'target',
|
|
||||||
localElementDepth: 0,
|
|
||||||
|
|
||||||
initStatements: [],
|
|
||||||
updateStatements: [],
|
|
||||||
teardownStatements: [],
|
|
||||||
|
|
||||||
counter: counter()
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
leave ( generator, node ) {
|
|
||||||
generator.addRenderer( generator.current );
|
|
||||||
|
|
||||||
if ( node.else ) {
|
|
||||||
generator.visit( node.else );
|
|
||||||
}
|
|
||||||
|
|
||||||
generator.pop();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in new issue