only create anchors for if blocks when necessary

pull/512/head
Rich-Harris 8 years ago
parent 162281ef4f
commit d274d08734

@ -223,7 +223,7 @@ const preprocessors = {
}
};
function preprocessChildren ( generator, block, state, node ) {
function preprocessChildren ( generator, block, state, node, isTopLevel ) {
// glue text nodes together
const cleaned = [];
let lastChild;
@ -238,16 +238,43 @@ function preprocessChildren ( generator, block, state, node ) {
cleaned.push( child );
}
if ( lastChild ) lastChild.next = 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 => {
const preprocess = preprocessors[ child.type ];
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 ) {
@ -268,21 +295,8 @@ export default function preprocess ( generator, state, node ) {
});
generator.blocks.push( block );
preprocessChildren( generator, block, state, node );
preprocessChildren( generator, block, state, node, true );
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;
}

@ -41,12 +41,16 @@ function visitChildren ( generator, block, state, node ) {
export default function visitIfBlock ( generator, block, state, node ) {
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 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 dynamic = branches.some( branch => branch.dynamic );
@ -70,11 +74,13 @@ function simple ( generator, block, state, node, branch, dynamic, { name, anchor
const isToplevel = !state.parentNode;
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 {
block.builders.create.addLine( `if ( ${name} ) ${name}.mount( ${state.parentNode}, null );` );
}
const parentNode = state.parentNode || `${anchor}.parentNode`;
if ( dynamic ) {
block.builders.update.addBlock( deindent`
if ( ${branch.condition} ) {
@ -82,7 +88,7 @@ function simple ( generator, block, state, node, branch, dynamic, { name, anchor
${name}.update( changed, ${params} );
} else {
${name} = ${branch.block}( ${params}, ${block.component} );
${name}.mount( ${anchor}.parentNode, ${anchor} );
${name}.mount( ${parentNode}, ${anchor} );
}
} else if ( ${name} ) {
${name}.destroy( true );
@ -94,7 +100,7 @@ function simple ( generator, block, state, node, branch, dynamic, { name, anchor
if ( ${branch.condition} ) {
if ( !${name} ) {
${name} = ${branch.block}( ${params}, ${block.component} );
${name}.mount( ${anchor}.parentNode, ${anchor} );
${name}.mount( ${parentNode}, ${anchor} );
}
} else if ( ${name} ) {
${name}.destroy( true );
@ -122,11 +128,13 @@ function compound ( generator, block, state, node, branches, dynamic, { name, an
const isToplevel = !state.parentNode;
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 {
block.builders.create.addLine( `if ( ${name} ) ${name}.mount( ${state.parentNode}, null );` );
}
const parentNode = state.parentNode || `${anchor}.parentNode`;
if ( dynamic ) {
block.builders.update.addBlock( deindent`
if ( ${current_block} === ( ${current_block} = ${getBlock}( ${params} ) ) && ${name} ) {
@ -134,7 +142,7 @@ function compound ( generator, block, state, node, branches, dynamic, { name, an
} else {
if ( ${name} ) ${name}.destroy( true );
${name} = ${current_block} && ${current_block}( ${params}, ${block.component} );
if ( ${name} ) ${name}.mount( ${anchor}.parentNode, ${anchor} );
if ( ${name} ) ${name}.mount( ${parentNode}, ${anchor} );
}
` );
} else {
@ -142,7 +150,7 @@ function compound ( generator, block, state, node, branches, dynamic, { name, an
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} );
if ( ${name} ) ${name}.mount( ${parentNode}, ${anchor} );
}
` );
}

@ -2,5 +2,5 @@
export default function visitText ( generator, block, state, node ) {
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 {
mount: function ( 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 ) {

@ -8,7 +8,7 @@ function create_main_fragment ( state, component ) {
return {
mount: function ( 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 ) {

@ -2,13 +2,12 @@ import { appendNode, assign, createComment, createElement, createText, detachNod
function create_main_fragment ( state, component ) {
var div = createElement( 'div' );
var if_block_anchor = createComment();
appendNode( if_block_anchor, div );
var if_block = state.a && create_if_block( state, component );
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' );
appendNode( p, div );
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 );
if ( if_block_1 ) if_block_1.mount( div, null );
var if_block_1_anchor = createComment();
appendNode( if_block_1_anchor, div );
appendNode( createText( "\n\n\t" ), div );
var text_3 = createText( "\n\n\t" );
appendNode( text_3, div );
var if_block_2 = state.c && create_if_block_2( state, component );
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' );
appendNode( p_1, div );
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 );
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 if_block_4_anchor = createComment();
@ -45,14 +44,14 @@ function create_main_fragment ( state, component ) {
insertNode( div, target, anchor );
insertNode( text_8, 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 ) {
if ( state.a ) {
if ( !if_block ) {
if_block = create_if_block( state, component );
if_block.mount( if_block_anchor.parentNode, p );
if_block.mount( div, text );
}
} else if ( if_block ) {
if_block.destroy( true );
@ -62,7 +61,7 @@ function create_main_fragment ( state, component ) {
if ( state.b ) {
if ( !if_block_1 ) {
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 ) {
if_block_1.destroy( true );
@ -72,7 +71,7 @@ function create_main_fragment ( state, component ) {
if ( state.c ) {
if ( !if_block_2 ) {
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 ) {
if_block_2.destroy( true );
@ -82,7 +81,7 @@ function create_main_fragment ( state, component ) {
if ( state.d ) {
if ( !if_block_3 ) {
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 ) {
if_block_3.destroy( true );

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