Skip to content

Commit

Permalink
deconflict names. fixes #88
Browse files Browse the repository at this point in the history
  • Loading branch information
Rich-Harris committed Dec 6, 2016
1 parent 0e64f26 commit 659eb32
Show file tree
Hide file tree
Showing 14 changed files with 88 additions and 57 deletions.
16 changes: 7 additions & 9 deletions compiler/generate/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import getOutro from './utils/getOutro.js';
import visitors from './visitors/index.js';
import processCss from './css/process.js';

export default function generate ( parsed, source, options ) {
export default function generate ( parsed, source, options, names ) {
const format = options.format || 'es';
const renderers = [];

Expand Down Expand Up @@ -149,15 +149,13 @@ export default function generate ( parsed, source, options ) {
};
},

// TODO use getName instead of counters
counters: {
if: 0,
each: 0
},

events: {},

getName: counter(),
getUniqueName: counter( names ),

getUniqueNameMaker () {
return counter( names );
},

cssId: parsed.css ? `svelte-${parsed.hash}` : '',

Expand Down Expand Up @@ -278,7 +276,7 @@ export default function generate ( parsed, source, options ) {
indexNames: {},
listNames: {},

counter: counter()
getUniqueName: generator.getUniqueNameMaker()
});

parsed.html.children.forEach( generator.visit );
Expand Down
14 changes: 8 additions & 6 deletions compiler/generate/utils/counter.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
export default function counter () {
export default function counter ( used ) {
const counts = {};

return function ( label ) {
if ( label in counts ) {
return `${label}${counts[ label ]++}`;
used.forEach( name => counts[ name ] = 1 );

return function ( name ) {
if ( name in counts ) {
return `${name}${counts[ name ]++}`;
}

counts[ label ] = 1;
return label;
counts[ name ] = 1;
return name;
};
}
9 changes: 4 additions & 5 deletions compiler/generate/visitors/Component.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import deindent from '../utils/deindent.js';
import addComponentAttributes from './attributes/addComponentAttributes.js';
import counter from '../utils/counter.js';

export default {
enter ( generator, node ) {
const hasChildren = node.children.length > 0;
const name = generator.current.counter( `${node.name[0].toLowerCase()}${node.name.slice( 1 )}` );
const name = generator.current.getUniqueName( `${node.name[0].toLowerCase()}${node.name.slice( 1 )}` );

const local = {
name,
Expand Down Expand Up @@ -33,12 +32,12 @@ export default {
];
// Component has children
if ( hasChildren ) {
const yieldName = `render${name}YieldFragment`;
const yieldName = generator.current.getUniqueName( `render${name}YieldFragment` );

// {{YIELD STUFF}}
generator.push({
useAnchor: true,
name: generator.current.counter(yieldName),
name: yieldName,
target: 'target',
localElementDepth: 0,

Expand All @@ -48,7 +47,7 @@ export default {
detachStatements: [],
teardownStatements: [],

counter: counter()
getUniqueName: generator.getUniqueNameMaker()
});

node.children.forEach( generator.visit );
Expand Down
43 changes: 21 additions & 22 deletions compiler/generate/visitors/EachBlock.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import deindent from '../utils/deindent.js';
import counter from '../utils/counter.js';

export default {
enter ( generator, node ) {
const i = generator.counters.each++;
const name = `eachBlock_${i}`;
const name = generator.getUniqueName( `eachBlock` );
const renderer = generator.getUniqueName( `renderEachBlock` );
const elseName = `${name}_else`;
const iterations = `${name}_iterations`;
const renderer = `renderEachBlock_${i}`;
const renderElse = `${renderer}_else`;
const i = generator.current.getUniqueName( `i` );
const { params } = generator.current;

const listName = `${name}_value`;
Expand All @@ -26,9 +25,9 @@ export default {
var ${iterations} = [];
${node.else ? `var ${elseName} = null;` : ''}
for ( var i = 0; i < ${name}_value.length; i += 1 ) {
${iterations}[i] = ${renderer}( ${params}, ${listName}, ${listName}[i], i, component );
${!isToplevel ? `${iterations}[i].mount( ${anchor}.parentNode, ${anchor} );` : ''}
for ( var ${i} = 0; ${i} < ${name}_value.length; ${i} += 1 ) {
${iterations}[${i}] = ${renderer}( ${params}, ${listName}, ${listName}[${i}], ${i}, component );
${!isToplevel ? `${iterations}[${i}].mount( ${anchor}.parentNode, ${anchor} );` : ''}
}
` );
if ( node.else ) {
Expand All @@ -42,8 +41,8 @@ export default {

if ( isToplevel ) {
generator.current.mountStatements.push( deindent`
for ( var i = 0; i < ${iterations}.length; i += 1 ) {
${iterations}[i].mount( ${anchor}.parentNode, ${anchor} );
for ( var ${i} = 0; ${i} < ${iterations}.length; ${i} += 1 ) {
${iterations}[${i}].mount( ${anchor}.parentNode, ${anchor} );
}
` );
if ( node.else ) {
Expand All @@ -58,21 +57,22 @@ export default {
generator.current.updateStatements.push( deindent`
var ${name}_value = ${snippet};
for ( var i = 0; i < ${name}_value.length; i += 1 ) {
if ( !${iterations}[i] ) {
${iterations}[i] = ${renderer}( ${params}, ${listName}, ${listName}[i], i, component );
${iterations}[i].mount( ${anchor}.parentNode, ${anchor} );
for ( var ${i} = 0; ${i} < ${name}_value.length; ${i} += 1 ) {
if ( !${iterations}[${i}] ) {
${iterations}[${i}] = ${renderer}( ${params}, ${listName}, ${listName}[${i}], ${i}, component );
${iterations}[${i}].mount( ${anchor}.parentNode, ${anchor} );
} else {
${iterations}[i].update( changed, ${params}, ${listName}, ${listName}[i], i );
${iterations}[${i}].update( changed, ${params}, ${listName}, ${listName}[${i}], ${i} );
}
}
for ( var i = ${name}_value.length; i < ${iterations}.length; i += 1 ) {
${iterations}[i].teardown( true );
for ( var ${i} = ${name}_value.length; ${i} < ${iterations}.length; ${i} += 1 ) {
${iterations}[${i}].teardown( true );
}
${iterations}.length = ${listName}.length;
` );

if ( node.else ) {
generator.current.updateStatements.push( deindent`
if ( !${name}_value.length && ${elseName} ) {
Expand All @@ -87,10 +87,11 @@ export default {
}

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

if ( node.else ) {
generator.current.teardownStatements.push( deindent`
if ( ${elseName} ) {
Expand All @@ -112,7 +113,7 @@ export default {
detachStatements: [],
teardownStatements: [],

counter: counter()
getUniqueName: generator.getUniqueNameMaker()
});
node.else.children.forEach( generator.visit );
generator.addRenderer( generator.current );
Expand Down Expand Up @@ -163,9 +164,7 @@ export default {
detachStatements: [],
teardownStatements: [],

counter: counter(),

parent: generator.current
getUniqueName: generator.getUniqueNameMaker()
});
},

Expand Down
2 changes: 1 addition & 1 deletion compiler/generate/visitors/Element.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export default {
return Component.enter( generator, node );
}

const name = generator.current.counter( node.name );
const name = generator.current.getUniqueName( node.name );

const local = {
name,
Expand Down
13 changes: 5 additions & 8 deletions compiler/generate/visitors/IfBlock.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import deindent from '../utils/deindent.js';
import counter from '../utils/counter.js';

// collect all the conditions and blocks in the if/elseif/else chain
function generateBlock ( generator, node, name ) {
Expand All @@ -16,7 +15,7 @@ function generateBlock ( generator, node, name ) {
detachStatements: [],
teardownStatements: [],

counter: counter()
getUniqueName: generator.getUniqueNameMaker()
});
node.children.forEach( generator.visit );
generator.addRenderer( generator.current );
Expand Down Expand Up @@ -54,15 +53,13 @@ function getConditionsAndBlocks ( generator, node, _name, i = 0 ) {

export default {
enter ( generator, node ) {
const i = generator.counters.if++;

const { params } = generator.current;
const name = `ifBlock_${i}`;
const getBlock = `getBlock_${i}`;
const currentBlock = `currentBlock_${i}`;
const name = generator.getUniqueName( `ifBlock` );
const getBlock = generator.getUniqueName( `getBlock` );
const currentBlock = generator.getUniqueName( `currentBlock` );

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

const anchor = generator.createAnchor( name, `#if ${generator.source.slice( node.expression.start, node.expression.end )}` );

Expand Down
2 changes: 1 addition & 1 deletion compiler/generate/visitors/MustacheTag.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import deindent from '../utils/deindent.js';

export default {
enter ( generator, node ) {
const name = generator.current.counter( 'text' );
const name = generator.current.getUniqueName( 'text' );

generator.addSourcemapLocations( node.expression );
const { snippet } = generator.contextualise( node.expression );
Expand Down
4 changes: 2 additions & 2 deletions compiler/generate/visitors/RawMustacheTag.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import deindent from '../utils/deindent.js';

export default {
enter ( generator, node ) {
const name = generator.current.counter( 'raw' );
const name = generator.current.getUniqueName( 'raw' );

generator.addSourcemapLocations( node.expression );
const { snippet } = generator.contextualise( node.expression );
Expand All @@ -25,7 +25,7 @@ export default {
}
`;

if ( isToplevel ) {
if ( isToplevel ) {
generator.current.mountStatements.push(mountStatement);
} else {
generator.current.initStatements.push(mountStatement);
Expand Down
2 changes: 1 addition & 1 deletion compiler/generate/visitors/Text.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export default {
enter ( generator, node ) {
const name = generator.current.counter( `text` );
const name = generator.current.getUniqueName( `text` );
generator.addElement( name, `document.createTextNode( ${JSON.stringify( node.data )} )` );
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ export default function addElementAttributes ( generator, node, local ) {
return `var ${listName} = this.__svelte.${listName}, ${indexName} = this.__svelte.${indexName}, ${name} = ${listName}[${indexName}]`;
});

const handlerName = generator.current.counter( `${attribute.name}Handler` );
const handlerName = generator.current.getUniqueName( `${attribute.name}Handler` );
const handlerBody = ( declarations.length ? declarations.join( '\n' ) + '\n\n' : '' ) + `[✂${attribute.expression.start}-${attribute.expression.end}✂];`;

if ( attribute.name in generator.events ) {
Expand Down
2 changes: 1 addition & 1 deletion compiler/generate/visitors/attributes/binding/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export default function createBinding ( generator, node, attribute, current, loc
});
}

const handler = current.counter( `${local.name}ChangeHandler` );
const handler = current.getUniqueName( `${local.name}ChangeHandler` );
let setter;

let eventName = 'change';
Expand Down
1 change: 1 addition & 0 deletions test/compiler/names-deconflicted/Widget.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<p>{{index + 1}}: {{widget.name}}</p>
14 changes: 14 additions & 0 deletions test/compiler/names-deconflicted/_config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export default {
html: `<p>1: foo</p><p>2: bar</p><p>3: baz</p>`,

test ( assert, component, target ) {
component.set({
widgets: [
{ name: 'bish' },
{ name: 'bosh' }
]
});

assert.htmlEqual( target.innerHTML, `<p>1: bish</p><p>2: bosh</p>` );
}
};
21 changes: 21 additions & 0 deletions test/compiler/names-deconflicted/main.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{{#each widgets as widget, i}}
<Widget widget='{{widget}}' index='{{i}}'/>
{{/each}}

<script>
import Widget from './Widget.html';

export default {
data () {
return {
widgets: [
{ name: 'foo' },
{ name: 'bar' },
{ name: 'baz' }
]
};
},

components: { Widget }
};
</script>

0 comments on commit 659eb32

Please sign in to comment.