From 8f2dad716052d15a9bbbf7bf35370cdf29714290 Mon Sep 17 00:00:00 2001 From: Arpad Borsos Date: Thu, 1 Dec 2016 11:35:51 +0100 Subject: [PATCH] various optimizations * avoid teardown for nested textnodes * avoid detaching children of a nested each --- compiler/generate/index.js | 18 ++++++++++++++++++ compiler/generate/visitors/EachBlock.js | 15 +++++++-------- compiler/generate/visitors/IfBlock.js | 20 ++++++-------------- compiler/generate/visitors/MustacheTag.js | 14 ++------------ compiler/generate/visitors/Text.js | 18 ++---------------- 5 files changed, 35 insertions(+), 50 deletions(-) diff --git a/compiler/generate/index.js b/compiler/generate/index.js index fa2ba7816a..2e1aa684cf 100644 --- a/compiler/generate/index.js +++ b/compiler/generate/index.js @@ -14,6 +14,24 @@ export default function generate ( parsed, source, options ) { const renderers = []; const generator = { + addElement ( name, renderStatement, needsIdentifier = false ) { + const needsTeardown = generator.current.localElementDepth === 0; + if ( needsIdentifier || needsTeardown ) { + generator.current.initStatements.push( deindent` + var ${name} = ${renderStatement}; + ${generator.appendToTarget( name )}; + ` ); + } else { + generator.current.initStatements.push( deindent` + ${generator.current.target}.appendChild( ${renderStatement} ); + ` ); + } + if ( needsTeardown ) { + generator.current.teardownStatements.push( deindent` + if ( detach ) ${name}.parentNode.removeChild( ${name} ); + ` ); + } + }, appendToTarget ( name ) { if ( generator.current.useAnchor && generator.current.target === 'target' ) { return `anchor.parentNode.insertBefore( ${name}, anchor )`; diff --git a/compiler/generate/visitors/EachBlock.js b/compiler/generate/visitors/EachBlock.js index 474eabce64..cfa7edee39 100644 --- a/compiler/generate/visitors/EachBlock.js +++ b/compiler/generate/visitors/EachBlock.js @@ -5,6 +5,7 @@ export default { enter ( generator, node ) { const i = generator.counters.each++; const name = `eachBlock_${i}`; + const anchor = `${name}_anchor`; const renderer = `renderEachBlock_${i}`; const listName = `${name}_value`; @@ -13,10 +14,9 @@ export default { const { dependencies, snippet } = generator.contextualise( node.expression ); - generator.current.initStatements.push( deindent` - var ${name}_anchor = document.createComment( ${JSON.stringify( `#each ${generator.source.slice( node.expression.start, node.expression.end )}` )} ); - ${generator.appendToTarget( `${name}_anchor` )}; + generator.addElement( anchor, `document.createComment( ${JSON.stringify( `#each ${generator.source.slice( node.expression.start, node.expression.end )}` )} )`, true ); + generator.current.initStatements.push( deindent` var ${name}_value = ${snippet}; var ${name}_fragment = document.createDocumentFragment(); var ${name}_iterations = []; @@ -25,7 +25,7 @@ export default { ${name}_iterations[i] = ${renderer}( ${generator.current.params}, ${listName}, ${listName}[i], i, component, ${name}_fragment ); } - ${name}_anchor.parentNode.insertBefore( ${name}_fragment, ${name}_anchor ); + ${anchor}.parentNode.insertBefore( ${name}_fragment, ${anchor} ); ` ); generator.current.updateStatements.push( deindent` @@ -43,16 +43,15 @@ export default { ${name}_iterations[i].teardown( true ); } - ${name}_anchor.parentNode.insertBefore( ${name}_fragment, ${name}_anchor ); + ${anchor}.parentNode.insertBefore( ${name}_fragment, ${anchor} ); ${name}_iterations.length = ${listName}.length; ` ); + const needsTeardown = generator.current.localElementDepth === 0; generator.current.teardownStatements.push( deindent` for ( let i = 0; i < ${name}_iterations.length; i += 1 ) { - ${name}_iterations[i].teardown( detach ); + ${name}_iterations[i].teardown( ${needsTeardown ? 'detach' : 'false'} ); } - - if ( detach ) ${name}_anchor.parentNode.removeChild( ${name}_anchor ); ` ); const indexNames = Object.assign( {}, generator.current.indexNames ); diff --git a/compiler/generate/visitors/IfBlock.js b/compiler/generate/visitors/IfBlock.js index db6de77729..76ab5255e5 100644 --- a/compiler/generate/visitors/IfBlock.js +++ b/compiler/generate/visitors/IfBlock.js @@ -56,15 +56,15 @@ export default { const { params, target } = generator.current; const name = `ifBlock_${i}`; + const anchor = `${name}_anchor`; const getBlock = `getBlock_${i}`; const currentBlock = `currentBlock_${i}`; const conditionsAndBlocks = getConditionsAndBlocks( generator, node, `renderIfBlock_${i}` ); - generator.current.initStatements.push( deindent` - var ${name}_anchor = document.createComment( ${JSON.stringify( `#if ${generator.source.slice( node.expression.start, node.expression.end )}` )} ); - ${generator.appendToTarget( `${name}_anchor` )}; + generator.addElement( anchor, `document.createComment( ${JSON.stringify( `#if ${generator.source.slice( node.expression.start, node.expression.end )}` )} )`, true ); + generator.current.initStatements.push( deindent` function ${getBlock} ( ${params} ) { ${conditionsAndBlocks.map( ({ condition, block }) => { return `${condition ? `if ( ${condition} ) ` : ''}return ${block};`; @@ -72,7 +72,7 @@ export default { } var ${currentBlock} = ${getBlock}( ${params} ); - var ${name} = ${currentBlock} && ${currentBlock}( ${params}, component, ${target}, ${name}_anchor ); + var ${name} = ${currentBlock} && ${currentBlock}( ${params}, component, ${target}, ${anchor} ); ` ); generator.current.updateStatements.push( deindent` @@ -82,18 +82,10 @@ export default { ${name}.update( changed, ${params} ); } else { if ( ${name} ) ${name}.teardown( true ); - ${name} = ${currentBlock} && ${currentBlock}( ${params}, component, ${target}, ${name}_anchor ); + ${name} = ${currentBlock} && ${currentBlock}( ${params}, component, ${target}, ${anchor} ); } ` ); - const teardownStatements = [ - `if ( ${name} ) ${name}.teardown( detach );` - ]; - - if ( generator.current.localElementDepth === 0 ) { - teardownStatements.push( `if ( detach ) ${name}_anchor.parentNode.removeChild( ${name}_anchor );` ); - } - - generator.current.teardownStatements.push( teardownStatements.join( '\n' ) ); + generator.current.teardownStatements.push( `if ( ${name} ) ${name}.teardown( detach );` ); } }; diff --git a/compiler/generate/visitors/MustacheTag.js b/compiler/generate/visitors/MustacheTag.js index cc0c9dbf77..a7078e1e28 100644 --- a/compiler/generate/visitors/MustacheTag.js +++ b/compiler/generate/visitors/MustacheTag.js @@ -4,23 +4,13 @@ export default { enter ( generator, node ) { const name = generator.current.counter( 'text' ); + generator.addSourcemapLocations( node.expression ); const { snippet } = generator.contextualise( node.expression ); - generator.current.initStatements.push( deindent` - var ${name} = document.createTextNode( ${snippet} ); - ${generator.appendToTarget( name )}; - ` ); - - generator.addSourcemapLocations( node.expression ); + generator.addElement( name, `document.createTextNode( ${snippet} )`, true ); generator.current.updateStatements.push( deindent` ${name}.data = ${snippet}; ` ); - - if ( generator.current.localElementDepth === 0 ) { - generator.current.teardownStatements.push( deindent` - if ( detach ) ${name}.parentNode.removeChild( ${name} ); - ` ); - } } }; diff --git a/compiler/generate/visitors/Text.js b/compiler/generate/visitors/Text.js index efdb69ff1c..960d56b568 100644 --- a/compiler/generate/visitors/Text.js +++ b/compiler/generate/visitors/Text.js @@ -2,21 +2,7 @@ import deindent from '../utils/deindent.js'; export default { enter ( generator, node ) { - if ( generator.elementDepth > 1 ) { - generator.current.initStatements.push( deindent` - ${generator.current.target}.appendChild( document.createTextNode( ${JSON.stringify( node.data )} ) ); - ` ); - } else { - const name = generator.current.counter( `text` ); - - generator.current.initStatements.push( deindent` - var ${name} = document.createTextNode( ${JSON.stringify( node.data )} ); - ${generator.appendToTarget( name )}; - ` ); - - generator.current.teardownStatements.push( deindent` - if ( detach ) ${name}.parentNode.removeChild( ${name} ); - ` ); - } + const name = generator.current.counter( `text` ); + generator.addElement( name, `document.createTextNode( ${JSON.stringify( node.data )} )` ); } };