Skip to content

Commit

Permalink
Merge pull request #107 from sveltejs/Swatinem-separatemount
Browse files Browse the repository at this point in the history
#91 again
  • Loading branch information
Rich-Harris committed Dec 4, 2016
2 parents 9d6e947 + 9463f5f commit 5770048
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 28 deletions.
27 changes: 20 additions & 7 deletions compiler/generate/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ export default function generate ( parsed, source, options ) {
},

createMountStatement ( name ) {
if ( generator.current.useAnchor && generator.current.target === 'target' ) {
generator.current.initStatements.push( deindent `
anchor.parentNode.insertBefore( ${name}, anchor );
if ( generator.current.target === 'target' ) {
generator.current.mountStatements.push( deindent`
target.insertBefore( ${name}, anchor );
` );
} else {
generator.current.initStatements.push( deindent `
generator.current.initStatements.push( deindent`
${generator.current.target}.appendChild( ${name} );
` );
}
Expand All @@ -58,10 +58,14 @@ export default function generate ( parsed, source, options ) {
}

renderers.push( deindent`
function ${fragment.name} ( ${fragment.params}, component, target${fragment.useAnchor ? ', anchor' : ''} ) {
function ${fragment.name} ( ${fragment.params}, component ) {
${fragment.initStatements.join( '\n\n' )}
return {
mount: function ( target, anchor ) {
${fragment.mountStatements.join( '\n\n' )}
},
update: function ( changed, ${fragment.params} ) {
${fragment.updateStatements.join( '\n\n' )}
},
Expand Down Expand Up @@ -249,6 +253,7 @@ export default function generate ( parsed, source, options ) {
localElementDepth: 0,

initStatements: [],
mountStatements: [],
updateStatements: [],
teardownStatements: [],

Expand Down Expand Up @@ -377,13 +382,17 @@ export default function generate ( parsed, source, options ) {
if ( generator.hasComplexBindings ) {
initStatements.push( deindent`
this.__bindings = [];
var mainFragment = renderMainFragment( state, this, options.target );
var mainFragment = renderMainFragment( state, this );
if ( options.target ) this.mount( options.target );
while ( this.__bindings.length ) this.__bindings.pop()();
` );

setStatements.push( `while ( this.__bindings.length ) this.__bindings.pop()();` );
} else {
initStatements.push( `var mainFragment = renderMainFragment( state, this, options.target );` );
initStatements.push( deindent`
var mainFragment = renderMainFragment( state, this );
if ( options.target ) this.mount( options.target );
` );
}

if ( generator.hasComponents ) {
Expand Down Expand Up @@ -462,6 +471,10 @@ export default function generate ( parsed, source, options ) {
${setStatements.join( '\n\n' )}
};
this.mount = function mount ( target, anchor ) {
mainFragment.mount( target, anchor );
}
this.observe = function ( key, callback, options ) {
var group = ( options && options.defer ) ? observers.deferred : observers.immediate;
Expand Down
39 changes: 24 additions & 15 deletions compiler/generate/visitors/EachBlock.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@ export default {
enter ( generator, node ) {
const i = generator.counters.each++;
const name = `eachBlock_${i}`;
const iterations = `${name}_iterations`;
const renderer = `renderEachBlock_${i}`;

const listName = `${name}_value`;

const isToplevel = generator.current.localElementDepth === 0;

generator.addSourcemapLocations( node.expression );

const { dependencies, snippet } = generator.contextualise( node.expression );
Expand All @@ -17,39 +20,44 @@ export default {

generator.current.initStatements.push( deindent`
var ${name}_value = ${snippet};
var ${name}_fragment = document.createDocumentFragment();
var ${name}_iterations = [];
var ${iterations} = [];
for ( var i = 0; i < ${name}_value.length; i += 1 ) {
${name}_iterations[i] = ${renderer}( ${generator.current.params}, ${listName}, ${listName}[i], i, component, ${name}_fragment );
${iterations}[i] = ${renderer}( ${generator.current.params}, ${listName}, ${listName}[i], i, component );
${!isToplevel ? `${iterations}[i].mount( ${anchor}.parentNode, ${anchor} );` : ''}
}
${anchor}.parentNode.insertBefore( ${name}_fragment, ${anchor} );
` );

if ( isToplevel ) {
generator.current.mountStatements.push( deindent`
for ( var i = 0; i < ${iterations}.length; i += 1 ) {
${iterations}[i].mount( ${anchor}.parentNode, ${anchor} );
}
` );
}

generator.current.updateStatements.push( deindent`
var ${name}_value = ${snippet};
for ( var i = 0; i < ${name}_value.length; i += 1 ) {
if ( !${name}_iterations[i] ) {
${name}_iterations[i] = ${renderer}( ${generator.current.params}, ${listName}, ${listName}[i], i, component, ${name}_fragment );
if ( !${iterations}[i] ) {
${iterations}[i] = ${renderer}( ${generator.current.params}, ${listName}, ${listName}[i], i, component );
${iterations}[i].mount( ${anchor}.parentNode, ${anchor} );
} else {
${name}_iterations[i].update( changed, ${generator.current.params}, ${listName}, ${listName}[i], i );
${iterations}[i].update( changed, ${generator.current.params}, ${listName}, ${listName}[i], i );
}
}
for ( var i = ${name}_value.length; i < ${name}_iterations.length; i += 1 ) {
${name}_iterations[i].teardown( true );
for ( var i = ${name}_value.length; i < ${iterations}.length; i += 1 ) {
${iterations}[i].teardown( true );
}
${anchor}.parentNode.insertBefore( ${name}_fragment, ${anchor} );
${name}_iterations.length = ${listName}.length;
${iterations}.length = ${listName}.length;
` );

const isToplevel = generator.current.localElementDepth === 0;
generator.current.teardownStatements.push( deindent`
for ( var i = 0; i < ${name}_iterations.length; i += 1 ) {
${name}_iterations[i].teardown( ${isToplevel ? 'detach' : 'false'} );
for ( var i = 0; i < ${iterations}.length; i += 1 ) {
${iterations}[i].teardown( ${isToplevel ? 'detach' : 'false'} );
}
` );

Expand Down Expand Up @@ -87,6 +95,7 @@ export default {
params,

initStatements: [],
mountStatements: [],
updateStatements: [ Object.keys( contexts ).map( contextName => {
const listName = listNames[ contextName ];
const indexName = indexNames[ contextName ];
Expand Down
10 changes: 8 additions & 2 deletions compiler/generate/visitors/Element.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export default {
allUsedContexts: new Set(),

init: [],
mount: [],
update: [],
teardown: []
};
Expand Down Expand Up @@ -57,20 +58,24 @@ export default {
${statements.join( '\n\n' )}
var ${name} = new template.components.${node.name}({
target: ${generator.current.target},
target: ${!isToplevel ? generator.current.target: 'null'},
root: component.root || component,
data: ${name}_initialData
});
` );
} else {
local.init.unshift( deindent`
var ${name} = new template.components.${node.name}({
target: ${generator.current.target},
target: ${!isToplevel ? generator.current.target: 'null'},
root: component.root || component
});
` );
}

if ( isToplevel ) {
local.mount.unshift( `${name}.mount( target, anchor );` );
}

if ( local.dynamicAttributes.length ) {
const updates = local.dynamicAttributes.map( attribute => {
return deindent`
Expand Down Expand Up @@ -146,6 +151,7 @@ export default {

generator.current.initStatements.push( local.init.join( '\n' ) );
if ( local.update.length ) generator.current.updateStatements.push( local.update.join( '\n' ) );
if ( local.mount.length ) generator.current.mountStatements.push( local.mount.join( '\n' ) );
generator.current.teardownStatements.push( local.teardown.join( '\n' ) );

generator.push({
Expand Down
17 changes: 13 additions & 4 deletions compiler/generate/visitors/IfBlock.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ function generateBlock ( generator, node, name ) {
localElementDepth: 0,

initStatements: [],
mountStatements: [],
updateStatements: [],
teardownStatements: [],

Expand Down Expand Up @@ -54,11 +55,12 @@ export default {
enter ( generator, node ) {
const i = generator.counters.if++;

const { params, target } = generator.current;
const { params } = generator.current;
const name = `ifBlock_${i}`;
const getBlock = `getBlock_${i}`;
const currentBlock = `currentBlock_${i}`;

const isToplevel = generator.current.localElementDepth === 0;
const conditionsAndBlocks = getConditionsAndBlocks( generator, node, `renderIfBlock_${i}` );

const anchor = generator.createAnchor( name, `#if ${generator.source.slice( node.expression.start, node.expression.end )}` );
Expand All @@ -71,21 +73,28 @@ export default {
}
var ${currentBlock} = ${getBlock}( ${params} );
var ${name} = ${currentBlock} && ${currentBlock}( ${params}, component, ${target}, ${anchor} );
var ${name} = ${currentBlock} && ${currentBlock}( ${params}, component );
` );

const mountStatement = `if ( ${name} ) ${name}.mount( ${anchor}.parentNode, ${anchor} );`;
if ( isToplevel ) {
generator.current.mountStatements.push( mountStatement );
} else {
generator.current.initStatements.push( mountStatement );
}

generator.current.updateStatements.push( deindent`
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}, ${anchor} );
${name} = ${currentBlock} && ${currentBlock}( ${params}, component );
if ( ${name} ) ${name}.mount( ${anchor}.parentNode, ${anchor} );
}
` );

const isToplevel = generator.current.localElementDepth === 0;
generator.current.teardownStatements.push( deindent`
if ( ${name} ) ${name}.teardown( ${isToplevel ? 'detach' : 'false'} );
` );
Expand Down
33 changes: 33 additions & 0 deletions test/compiler/each-block-random-permute/_config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
const VALUES = Array.from( 'abcdefghijklmnopqrstuvwxyz' );

function permute () {
const values = VALUES.slice();
const number = Math.floor(Math.random() * VALUES.length);
const permuted = [];
for (let i = 0; i < number; i++) {
permuted.push( ...values.splice( Math.floor( Math.random() * ( number - i ) ), 1 ) );
}

return {
data: permuted,
expected: permuted.length ? `(${permuted.join(')(')})` : ''
};
}

let step = permute();

export default {
data: {
values: step.data
},

html: step.expected,

test ( assert, component, target ) {
for (let i = 0; i < 100; i++) {
step = permute();
component.set({ values: step.data });
assert.htmlEqual( target.innerHTML, step.expected );
}
}
};
3 changes: 3 additions & 0 deletions test/compiler/each-block-random-permute/main.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{{#each values as value}}
({{value}})
{{/each}}

0 comments on commit 5770048

Please sign in to comment.