only create anchors for if blocks when necessary

pull/7738/head
Rich-Harris 9 years ago
parent 12f211c6a8
commit e903ff69fc

@ -223,7 +223,7 @@ const preprocessors = {
} }
}; };
function preprocessChildren ( generator, block, state, node ) { function preprocessChildren ( generator, block, state, node, isTopLevel ) {
// glue text nodes together // glue text nodes together
const cleaned = []; const cleaned = [];
let lastChild; let lastChild;
@ -238,16 +238,43 @@ function preprocessChildren ( generator, block, state, node ) {
cleaned.push( child ); cleaned.push( child );
} }
if ( lastChild ) lastChild.next = child;
lastChild = child; lastChild = child;
}); });
node.children = cleaned; if ( isTopLevel ) {
// trim leading and trailing whitespace from the top level
const firstChild = cleaned[0];
if ( firstChild && firstChild.type === 'Text' ) {
firstChild.data = trimStart( firstChild.data );
if ( !firstChild.data ) cleaned.shift();
}
const lastChild = cleaned[ cleaned.length - 1 ];
if ( lastChild && lastChild.type === 'Text' ) {
lastChild.data = trimEnd( lastChild.data );
if ( !lastChild.data ) cleaned.pop();
}
}
lastChild = null;
cleaned.forEach( child => { cleaned.forEach( child => {
const preprocess = preprocessors[ child.type ]; const preprocess = preprocessors[ child.type ];
if ( preprocess ) preprocess( generator, block, state, child ); if ( preprocess ) preprocess( generator, block, state, child );
if ( lastChild ) {
lastChild.next = child;
lastChild.needsAnchor = !child._state.name;
}
lastChild = child;
}); });
if ( lastChild ) {
lastChild.needsAnchor = !state.parentNode;
}
node.children = cleaned;
} }
export default function preprocess ( generator, state, node ) { export default function preprocess ( generator, state, node ) {
@ -268,21 +295,8 @@ export default function preprocess ( generator, state, node ) {
}); });
generator.blocks.push( block ); generator.blocks.push( block );
preprocessChildren( generator, block, state, node ); preprocessChildren( generator, block, state, node, true );
block.hasUpdateMethod = block.dependencies.size > 0; block.hasUpdateMethod = block.dependencies.size > 0;
// trim leading and trailing whitespace from the top level
const firstChild = node.children[0];
if ( firstChild && firstChild.type === 'Text' ) {
firstChild.data = trimStart( firstChild.data );
if ( !firstChild.data ) node.children.shift();
}
const lastChild = node.children[ node.children.length - 1 ];
if ( lastChild && lastChild.type === 'Text' ) {
lastChild.data = trimEnd( lastChild.data );
if ( !lastChild.data ) node.children.pop();
}
return block; return block;
} }

@ -41,12 +41,16 @@ function visitChildren ( generator, block, state, node ) {
export default function visitIfBlock ( generator, block, state, node ) { export default function visitIfBlock ( generator, block, state, node ) {
const name = generator.getUniqueName( `if_block` ); const name = generator.getUniqueName( `if_block` );
const anchor = generator.getUniqueName( `${name}_anchor` ); const anchor = node.needsAnchor ? block.getUniqueName( `${name}_anchor` ) : ( node.next && node.next._state.name ) || 'null';
const params = block.params.join( ', ' ); const params = block.params.join( ', ' );
const vars = { name, anchor, params }; const vars = { name, anchor, params };
block.createAnchor( anchor, state.parentNode ); if ( node.needsAnchor ) {
block.createAnchor( anchor, state.parentNode );
} else if ( node.next ) {
node.next.usedAsAnchor = true;
}
const branches = getBranches( generator, block, state, node, generator.getUniqueName( `create_if_block` ) ); const branches = getBranches( generator, block, state, node, generator.getUniqueName( `create_if_block` ) );
const dynamic = branches.some( branch => branch.dynamic ); const dynamic = branches.some( branch => branch.dynamic );
@ -70,11 +74,13 @@ function simple ( generator, block, state, node, branch, dynamic, { name, anchor
const isToplevel = !state.parentNode; const isToplevel = !state.parentNode;
if ( isToplevel ) { if ( isToplevel ) {
block.builders.mount.addLine( `if ( ${name} ) ${name}.mount( ${block.target}, ${anchor} );` ); block.builders.mount.addLine( `if ( ${name} ) ${name}.mount( ${block.target}, null );` );
} else { } else {
block.builders.create.addLine( `if ( ${name} ) ${name}.mount( ${state.parentNode}, null );` ); block.builders.create.addLine( `if ( ${name} ) ${name}.mount( ${state.parentNode}, null );` );
} }
const parentNode = state.parentNode || `${anchor}.parentNode`;
if ( dynamic ) { if ( dynamic ) {
block.builders.update.addBlock( deindent` block.builders.update.addBlock( deindent`
if ( ${branch.condition} ) { if ( ${branch.condition} ) {
@ -82,7 +88,7 @@ function simple ( generator, block, state, node, branch, dynamic, { name, anchor
${name}.update( changed, ${params} ); ${name}.update( changed, ${params} );
} else { } else {
${name} = ${branch.block}( ${params}, ${block.component} ); ${name} = ${branch.block}( ${params}, ${block.component} );
${name}.mount( ${anchor}.parentNode, ${anchor} ); ${name}.mount( ${parentNode}, ${anchor} );
} }
} else if ( ${name} ) { } else if ( ${name} ) {
${name}.destroy( true ); ${name}.destroy( true );
@ -94,7 +100,7 @@ function simple ( generator, block, state, node, branch, dynamic, { name, anchor
if ( ${branch.condition} ) { if ( ${branch.condition} ) {
if ( !${name} ) { if ( !${name} ) {
${name} = ${branch.block}( ${params}, ${block.component} ); ${name} = ${branch.block}( ${params}, ${block.component} );
${name}.mount( ${anchor}.parentNode, ${anchor} ); ${name}.mount( ${parentNode}, ${anchor} );
} }
} else if ( ${name} ) { } else if ( ${name} ) {
${name}.destroy( true ); ${name}.destroy( true );
@ -122,11 +128,13 @@ function compound ( generator, block, state, node, branches, dynamic, { name, an
const isToplevel = !state.parentNode; const isToplevel = !state.parentNode;
if ( isToplevel ) { if ( isToplevel ) {
block.builders.mount.addLine( `if ( ${name} ) ${name}.mount( ${block.target}, ${anchor} );` ); block.builders.mount.addLine( `if ( ${name} ) ${name}.mount( ${block.target}, null );` );
} else { } else {
block.builders.create.addLine( `if ( ${name} ) ${name}.mount( ${state.parentNode}, null );` ); block.builders.create.addLine( `if ( ${name} ) ${name}.mount( ${state.parentNode}, null );` );
} }
const parentNode = state.parentNode || `${anchor}.parentNode`;
if ( dynamic ) { if ( dynamic ) {
block.builders.update.addBlock( deindent` block.builders.update.addBlock( deindent`
if ( ${current_block} === ( ${current_block} = ${getBlock}( ${params} ) ) && ${name} ) { if ( ${current_block} === ( ${current_block} = ${getBlock}( ${params} ) ) && ${name} ) {
@ -134,7 +142,7 @@ function compound ( generator, block, state, node, branches, dynamic, { name, an
} else { } else {
if ( ${name} ) ${name}.destroy( true ); if ( ${name} ) ${name}.destroy( true );
${name} = ${current_block} && ${current_block}( ${params}, ${block.component} ); ${name} = ${current_block} && ${current_block}( ${params}, ${block.component} );
if ( ${name} ) ${name}.mount( ${anchor}.parentNode, ${anchor} ); if ( ${name} ) ${name}.mount( ${parentNode}, ${anchor} );
} }
` ); ` );
} else { } else {
@ -142,7 +150,7 @@ function compound ( generator, block, state, node, branches, dynamic, { name, an
if ( ${current_block} !== ( ${current_block} = ${getBlock}( ${params} ) ) ) { if ( ${current_block} !== ( ${current_block} = ${getBlock}( ${params} ) ) ) {
if ( ${name} ) ${name}.destroy( true ); if ( ${name} ) ${name}.destroy( true );
${name} = ${current_block} && ${current_block}( ${params}, ${block.component} ); ${name} = ${current_block} && ${current_block}( ${params}, ${block.component} );
if ( ${name} ) ${name}.mount( ${anchor}.parentNode, ${anchor} ); if ( ${name} ) ${name}.mount( ${parentNode}, ${anchor} );
} }
` ); ` );
} }

@ -2,5 +2,5 @@
export default function visitText ( generator, block, state, node ) { export default function visitText ( generator, block, state, node ) {
if ( !node._state.shouldCreate ) return; if ( !node._state.shouldCreate ) return;
block.addElement( node._state.name, `${generator.helper( 'createText' )}( ${JSON.stringify( node.data )} )`, state.parentNode, false ); block.addElement( node._state.name, `${generator.helper( 'createText' )}( ${JSON.stringify( node.data )} )`, state.parentNode, node.usedAsAnchor );
} }

@ -14,7 +14,7 @@ function create_main_fragment ( state, component ) {
return { return {
mount: function ( target, anchor ) { mount: function ( target, anchor ) {
insertNode( if_block_anchor, target, anchor ); insertNode( if_block_anchor, target, anchor );
if ( if_block ) if_block.mount( target, if_block_anchor ); if ( if_block ) if_block.mount( target, null );
}, },
update: function ( changed, state ) { update: function ( changed, state ) {

@ -8,7 +8,7 @@ function create_main_fragment ( state, component ) {
return { return {
mount: function ( target, anchor ) { mount: function ( target, anchor ) {
insertNode( if_block_anchor, target, anchor ); insertNode( if_block_anchor, target, anchor );
if ( if_block ) if_block.mount( target, if_block_anchor ); if ( if_block ) if_block.mount( target, null );
}, },
update: function ( changed, state ) { update: function ( changed, state ) {

@ -2,13 +2,12 @@ import { appendNode, assign, createComment, createElement, createText, detachNod
function create_main_fragment ( state, component ) { function create_main_fragment ( state, component ) {
var div = createElement( 'div' ); var div = createElement( 'div' );
var if_block_anchor = createComment();
appendNode( if_block_anchor, div );
var if_block = state.a && create_if_block( state, component ); var if_block = state.a && create_if_block( state, component );
if ( if_block ) if_block.mount( div, null ); if ( if_block ) if_block.mount( div, null );
appendNode( createText( "\n\n\t" ), div ); var text = createText( "\n\n\t" );
appendNode( text, div );
var p = createElement( 'p' ); var p = createElement( 'p' );
appendNode( p, div ); appendNode( p, div );
appendNode( createText( "this can be used as an anchor" ), p ); appendNode( createText( "this can be used as an anchor" ), p );
@ -17,15 +16,14 @@ function create_main_fragment ( state, component ) {
var if_block_1 = state.b && create_if_block_1( state, component ); var if_block_1 = state.b && create_if_block_1( state, component );
if ( if_block_1 ) if_block_1.mount( div, null ); if ( if_block_1 ) if_block_1.mount( div, null );
var if_block_1_anchor = createComment(); var text_3 = createText( "\n\n\t" );
appendNode( if_block_1_anchor, div ); appendNode( text_3, div );
appendNode( createText( "\n\n\t" ), div );
var if_block_2 = state.c && create_if_block_2( state, component ); var if_block_2 = state.c && create_if_block_2( state, component );
if ( if_block_2 ) if_block_2.mount( div, null ); if ( if_block_2 ) if_block_2.mount( div, null );
appendNode( createText( "\n\n\t" ), div ); var text_4 = createText( "\n\n\t" );
appendNode( text_4, div );
var p_1 = createElement( 'p' ); var p_1 = createElement( 'p' );
appendNode( p_1, div ); appendNode( p_1, div );
appendNode( createText( "so can this" ), p_1 ); appendNode( createText( "so can this" ), p_1 );
@ -34,7 +32,8 @@ function create_main_fragment ( state, component ) {
var if_block_3 = state.d && create_if_block_3( state, component ); var if_block_3 = state.d && create_if_block_3( state, component );
if ( if_block_3 ) if_block_3.mount( div, null ); if ( if_block_3 ) if_block_3.mount( div, null );
appendNode( createText( "\n\n\t" ), div ); var text_7 = createText( "\n\n\t" );
appendNode( text_7, div );
var text_8 = createText( "\n\n" ); var text_8 = createText( "\n\n" );
var if_block_4_anchor = createComment(); var if_block_4_anchor = createComment();
@ -45,14 +44,14 @@ function create_main_fragment ( state, component ) {
insertNode( div, target, anchor ); insertNode( div, target, anchor );
insertNode( text_8, target, anchor ); insertNode( text_8, target, anchor );
insertNode( if_block_4_anchor, target, anchor ); insertNode( if_block_4_anchor, target, anchor );
if ( if_block_4 ) if_block_4.mount( target, if_block_4_anchor ); if ( if_block_4 ) if_block_4.mount( target, null );
}, },
update: function ( changed, state ) { update: function ( changed, state ) {
if ( state.a ) { if ( state.a ) {
if ( !if_block ) { if ( !if_block ) {
if_block = create_if_block( state, component ); if_block = create_if_block( state, component );
if_block.mount( if_block_anchor.parentNode, p ); if_block.mount( div, text );
} }
} else if ( if_block ) { } else if ( if_block ) {
if_block.destroy( true ); if_block.destroy( true );
@ -62,7 +61,7 @@ function create_main_fragment ( state, component ) {
if ( state.b ) { if ( state.b ) {
if ( !if_block_1 ) { if ( !if_block_1 ) {
if_block_1 = create_if_block_1( state, component ); if_block_1 = create_if_block_1( state, component );
if_block_1.mount( if_block_1_anchor.parentNode, if_block_1_anchor ); if_block_1.mount( div, text_3 );
} }
} else if ( if_block_1 ) { } else if ( if_block_1 ) {
if_block_1.destroy( true ); if_block_1.destroy( true );
@ -72,7 +71,7 @@ function create_main_fragment ( state, component ) {
if ( state.c ) { if ( state.c ) {
if ( !if_block_2 ) { if ( !if_block_2 ) {
if_block_2 = create_if_block_2( state, component ); if_block_2 = create_if_block_2( state, component );
if_block_2.mount( if_block_2_anchor.parentNode, p_2 ); if_block_2.mount( div, text_4 );
} }
} else if ( if_block_2 ) { } else if ( if_block_2 ) {
if_block_2.destroy( true ); if_block_2.destroy( true );
@ -82,7 +81,7 @@ function create_main_fragment ( state, component ) {
if ( state.d ) { if ( state.d ) {
if ( !if_block_3 ) { if ( !if_block_3 ) {
if_block_3 = create_if_block_3( state, component ); if_block_3 = create_if_block_3( state, component );
if_block_3.mount( if_block_3_anchor.parentNode, null ); if_block_3.mount( div, text_7 );
} }
} else if ( if_block_3 ) { } else if ( if_block_3 ) {
if_block_3.destroy( true ); if_block_3.destroy( true );

@ -2,11 +2,26 @@ export default {
data: { data: {
visible: true visible: true
}, },
html: 'before\n<p>Widget</p><!---->\nafter',
html: `
before
<p>Widget</p>
after
`,
test ( assert, component, target ) { test ( assert, component, target ) {
component.set({ visible: false }); component.set({ visible: false });
assert.equal( target.innerHTML, 'before\n<!---->\nafter' ); assert.htmlEqual( target.innerHTML, `
before
after
` );
component.set({ visible: true }); component.set({ visible: true });
assert.equal( target.innerHTML, 'before\n<p>Widget</p><!---->\nafter' ); assert.htmlEqual( target.innerHTML, `
before
<p>Widget</p>
after
` );
} }
}; };

Loading…
Cancel
Save