From 9480f349ec49c2411e74cedfb743068d50d860a8 Mon Sep 17 00:00:00 2001 From: Rich-Harris Date: Wed, 19 Apr 2017 14:05:34 -0400 Subject: [PATCH] anchor-less each blocks --- src/generators/dom/visitors/EachBlock.js | 35 ++++++++++++------- .../each-block-changed-check/expected.js | 10 ++---- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/src/generators/dom/visitors/EachBlock.js b/src/generators/dom/visitors/EachBlock.js index 7919cf1f3d..bf7e63b4d0 100644 --- a/src/generators/dom/visitors/EachBlock.js +++ b/src/generators/dom/visitors/EachBlock.js @@ -9,13 +9,12 @@ export default function visitEachBlock ( generator, block, state, node ) { const iterations = block.getUniqueName( `${each_block}_iterations` ); const i = block.alias( `i` ); const params = block.params.join( ', ' ); - const anchor = block.getUniqueName( `${each_block}_anchor` ); + const anchor = node.needsAnchor ? block.getUniqueName( `${each_block}_anchor` ) : ( node.next && node.next._state.name ) || 'null'; const vars = { each_block, create_each_block, each_block_value, iterations, i, params, anchor }; const { snippet } = block.contextualise( node.expression ); - block.createAnchor( anchor, state.parentNode ); block.builders.create.addLine( `var ${each_block_value} = ${snippet};` ); block.builders.create.addLine( `var ${iterations} = [];` ); @@ -30,11 +29,17 @@ export default function visitEachBlock ( generator, block, state, node ) { if ( isToplevel ) { block.builders.mount.addBlock( deindent` for ( var ${i} = 0; ${i} < ${iterations}.length; ${i} += 1 ) { - ${iterations}[${i}].mount( ${block.target}, ${anchor} ); + ${iterations}[${i}].mount( ${block.target}, null ); } ` ); } + if ( node.needsAnchor ) { + block.createAnchor( anchor, state.parentNode ); + } else if ( node.next ) { + node.next.usedAsAnchor = true; + } + block.builders.destroy.addBlock( `${generator.helper( 'destroyEach' )}( ${iterations}, ${isToplevel ? 'detach' : 'false'}, 0 );` ); @@ -47,23 +52,25 @@ export default function visitEachBlock ( generator, block, state, node ) { block.builders.create.addBlock( deindent` if ( !${each_block_value}.length ) { ${each_block_else} = ${node.else._block.name}( ${params}, ${block.component} ); - ${!isToplevel ? `${each_block_else}.mount( ${state.parentNode}, ${anchor} );` : ''} + ${!isToplevel ? `${each_block_else}.mount( ${state.parentNode}, null );` : ''} } ` ); block.builders.mount.addBlock( deindent` if ( ${each_block_else} ) { - ${each_block_else}.mount( ${state.parentNode || block.target}, ${anchor} ); + ${each_block_else}.mount( ${state.parentNode || block.target}, null ); } ` ); + const parentNode = state.parentNode || `${anchor}.parentNode`; + if ( node.else._block.hasUpdateMethod ) { block.builders.update.addBlock( deindent` if ( !${each_block_value}.length && ${each_block_else} ) { ${each_block_else}.update( changed, ${params} ); } else if ( !${each_block_value}.length ) { ${each_block_else} = ${node.else._block.name}( ${params}, ${block.component} ); - ${each_block_else}.mount( ${anchor}.parentNode, ${anchor} ); + ${each_block_else}.mount( ${parentNode}, ${anchor} ); } else if ( ${each_block_else} ) { ${each_block_else}.destroy( true ); } @@ -74,7 +81,7 @@ export default function visitEachBlock ( generator, block, state, node ) { if ( ${each_block_else} ) ${each_block_else}.destroy( true ); } else if ( !${each_block_else} ) { ${each_block_else} = ${node.else._block.name}( ${params}, ${block.component} ); - ${each_block_else}.mount( ${anchor}.parentNode, ${anchor} ); + ${each_block_else}.mount( ${parentNode}, ${anchor} ); } ` ); } @@ -118,7 +125,7 @@ function keyed ( generator, block, state, node, snippet, { each_block, create_ea if ( state.parentNode ) { create.addLine( - `${iterations}[${i}].mount( ${state.parentNode}, ${anchor} );` + `${iterations}[${i}].mount( ${state.parentNode}, null );` ); } @@ -135,6 +142,8 @@ function keyed ( generator, block, state, node, snippet, { each_block, create_ea ` : `${_iterations}[${i}] = ${_lookup}[ ${key} ] = ${lookup}[ ${key} ];`; + const parentNode = state.parentNode || `${anchor}.parentNode`; + block.builders.update.addBlock( deindent` var ${each_block_value} = ${snippet}; var ${_iterations} = []; @@ -164,7 +173,7 @@ function keyed ( generator, block, state, node, snippet, { each_block, create_ea } } - ${anchor}.parentNode.insertBefore( ${fragment}, ${anchor} ); + ${parentNode}.insertBefore( ${fragment}, ${anchor} ); ${iterations} = ${_iterations}; ${lookup} = ${_lookup}; @@ -180,7 +189,7 @@ function unkeyed ( generator, block, state, node, snippet, { create_each_block, if ( state.parentNode ) { create.addLine( - `${iterations}[${i}].mount( ${state.parentNode}, ${anchor} );` + `${iterations}[${i}].mount( ${state.parentNode}, null );` ); } @@ -200,6 +209,8 @@ function unkeyed ( generator, block, state, node, snippet, { create_each_block, .map( dependency => `'${dependency}' in changed` ) .join( ' || ' ); + const parentNode = state.parentNode || `${anchor}.parentNode`; + if ( condition !== '' ) { const forLoopBody = node._block.hasUpdateMethod ? deindent` @@ -207,12 +218,12 @@ function unkeyed ( generator, block, state, node, snippet, { create_each_block, ${iterations}[${i}].update( changed, ${params}, ${each_block_value}, ${each_block_value}[${i}], ${i} ); } else { ${iterations}[${i}] = ${create_each_block}( ${params}, ${each_block_value}, ${each_block_value}[${i}], ${i}, ${block.component} ); - ${iterations}[${i}].mount( ${anchor}.parentNode, ${anchor} ); + ${iterations}[${i}].mount( ${parentNode}, ${anchor} ); } ` : deindent` ${iterations}[${i}] = ${create_each_block}( ${params}, ${each_block_value}, ${each_block_value}[${i}], ${i}, ${block.component} ); - ${iterations}[${i}].mount( ${anchor}.parentNode, ${anchor} ); + ${iterations}[${i}].mount( ${parentNode}, ${anchor} ); `; const start = node._block.hasUpdateMethod ? '0' : `${iterations}.length`; diff --git a/test/js/samples/each-block-changed-check/expected.js b/test/js/samples/each-block-changed-check/expected.js index 7b0f01698f..40d2487c11 100644 --- a/test/js/samples/each-block-changed-check/expected.js +++ b/test/js/samples/each-block-changed-check/expected.js @@ -1,7 +1,6 @@ -import { appendNode, assign, createComment, createElement, createText, destroyEach, detachBetween, detachNode, dispatchObservers, insertNode, proto } from "svelte/shared.js"; +import { appendNode, assign, createElement, createText, destroyEach, detachBetween, detachNode, dispatchObservers, insertNode, proto } from "svelte/shared.js"; function create_main_fragment ( state, component ) { - var each_block_anchor = createComment(); var each_block_value = state.comments; var each_block_iterations = []; @@ -17,10 +16,8 @@ function create_main_fragment ( state, component ) { return { mount: function ( target, anchor ) { - insertNode( each_block_anchor, target, anchor ); - for ( var i = 0; i < each_block_iterations.length; i += 1 ) { - each_block_iterations[i].mount( target, each_block_anchor ); + each_block_iterations[i].mount( target, null ); } insertNode( text, target, anchor ); @@ -36,7 +33,7 @@ function create_main_fragment ( state, component ) { each_block_iterations[i].update( changed, state, each_block_value, each_block_value[i], i ); } else { each_block_iterations[i] = create_each_block( state, each_block_value, each_block_value[i], i, component ); - each_block_iterations[i].mount( each_block_anchor.parentNode, each_block_anchor ); + each_block_iterations[i].mount( text.parentNode, text ); } } @@ -54,7 +51,6 @@ function create_main_fragment ( state, component ) { destroyEach( each_block_iterations, detach, 0 ); if ( detach ) { - detachNode( each_block_anchor ); detachNode( text ); detachNode( p ); }