mirror of
https://github.com/sveltejs/svelte.git
synced 2024-12-01 17:30:59 +01:00
commit
5770048855
@ -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} );
|
||||
` );
|
||||
}
|
||||
@ -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' )}
|
||||
},
|
||||
@ -249,6 +253,7 @@ export default function generate ( parsed, source, options ) {
|
||||
localElementDepth: 0,
|
||||
|
||||
initStatements: [],
|
||||
mountStatements: [],
|
||||
updateStatements: [],
|
||||
teardownStatements: [],
|
||||
|
||||
@ -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 ) {
|
||||
@ -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;
|
||||
|
||||
|
@ -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 );
|
||||
@ -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'} );
|
||||
}
|
||||
` );
|
||||
|
||||
@ -87,6 +95,7 @@ export default {
|
||||
params,
|
||||
|
||||
initStatements: [],
|
||||
mountStatements: [],
|
||||
updateStatements: [ Object.keys( contexts ).map( contextName => {
|
||||
const listName = listNames[ contextName ];
|
||||
const indexName = indexNames[ contextName ];
|
||||
|
@ -15,6 +15,7 @@ export default {
|
||||
allUsedContexts: new Set(),
|
||||
|
||||
init: [],
|
||||
mount: [],
|
||||
update: [],
|
||||
teardown: []
|
||||
};
|
||||
@ -57,7 +58,7 @@ 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
|
||||
});
|
||||
@ -65,12 +66,16 @@ export default {
|
||||
} 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`
|
||||
@ -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({
|
||||
|
@ -11,6 +11,7 @@ function generateBlock ( generator, node, name ) {
|
||||
localElementDepth: 0,
|
||||
|
||||
initStatements: [],
|
||||
mountStatements: [],
|
||||
updateStatements: [],
|
||||
teardownStatements: [],
|
||||
|
||||
@ -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 )}` );
|
||||
@ -71,9 +73,16 @@ 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} );
|
||||
@ -81,11 +90,11 @@ export default {
|
||||
${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'} );
|
||||
` );
|
||||
|
33
test/compiler/each-block-random-permute/_config.js
Normal file
33
test/compiler/each-block-random-permute/_config.js
Normal file
@ -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
test/compiler/each-block-random-permute/main.html
Normal file
3
test/compiler/each-block-random-permute/main.html
Normal file
@ -0,0 +1,3 @@
|
||||
{{#each values as value}}
|
||||
({{value}})
|
||||
{{/each}}
|
Loading…
Reference in New Issue
Block a user