Merge branch 'master' into gh-371

pull/391/head
Rich Harris 8 years ago committed by GitHub
commit 8558b45337

@ -35,6 +35,12 @@ export default class Generator {
this.cssId = parsed.css ? `svelte-${parsed.hash}` : ''; this.cssId = parsed.css ? `svelte-${parsed.hash}` : '';
this.usesRefs = false; this.usesRefs = false;
// allow compiler to deconflict user's `import { get } from 'whatever'` and
// Svelte's builtin `import { get, ... } from 'svelte/shared.js'`;
this.importedNames = {};
this.aliases = {};
this._callbacks = {}; this._callbacks = {};
} }
@ -47,6 +53,20 @@ export default class Generator {
}); });
} }
alias ( name ) {
if ( !( name in this.aliases ) ) {
let alias = name;
let i = 1;
while ( alias in this.importedNames ) {
alias = `${name}$${i++}`;
}
this.aliases[ name ] = alias;
}
return this.aliases[ name ];
}
contextualise ( expression, isEventHandler ) { contextualise ( expression, isEventHandler ) {
this.addSourcemapLocations( expression ); this.addSourcemapLocations( expression );
@ -58,6 +78,8 @@ export default class Generator {
let scope = annotateWithScopes( expression ); let scope = annotateWithScopes( expression );
const self = this;
walk( expression, { walk( expression, {
enter ( node, parent, key ) { enter ( node, parent, key ) {
if ( node._scope ) { if ( node._scope ) {
@ -70,7 +92,7 @@ export default class Generator {
if ( scope.has( name ) ) return; if ( scope.has( name ) ) return;
if ( parent && parent.type === 'CallExpression' && node === parent.callee && helpers[ name ] ) { if ( parent && parent.type === 'CallExpression' && node === parent.callee && helpers[ name ] ) {
code.prependRight( node.start, `template.helpers.` ); code.prependRight( node.start, `${self.alias( 'template' )}.helpers.` );
} }
else if ( name === 'event' && isEventHandler ) { else if ( name === 'event' && isEventHandler ) {
@ -249,6 +271,9 @@ export default class Generator {
imports.push( node ); imports.push( node );
this.code.remove( a, b ); this.code.remove( a, b );
node.specifiers.forEach( specifier => {
this.importedNames[ specifier.local.name ] = true;
});
} }
} }
@ -260,21 +285,24 @@ export default class Generator {
// export is last property, we can just return it // export is last property, we can just return it
this.code.overwrite( defaultExport.start, defaultExport.declaration.start, `return ` ); this.code.overwrite( defaultExport.start, defaultExport.declaration.start, `return ` );
} else { } else {
// TODO ensure `template` isn't already declared const { declarations } = annotateWithScopes( js );
this.code.overwrite( defaultExport.start, defaultExport.declaration.start, `var template = ` ); let template = 'template';
for ( let i = 1; template in declarations; template = `template$${i++}` );
this.code.overwrite( defaultExport.start, defaultExport.declaration.start, `var ${template} = ` );
let i = defaultExport.start; let i = defaultExport.start;
while ( /\s/.test( source[ i - 1 ] ) ) i--; while ( /\s/.test( source[ i - 1 ] ) ) i--;
const indentation = source.slice( i, defaultExport.start ); const indentation = source.slice( i, defaultExport.start );
this.code.appendLeft( finalNode.end, `\n\n${indentation}return template;` ); this.code.appendLeft( finalNode.end, `\n\n${indentation}return ${template};` );
} }
defaultExport.declaration.properties.forEach( prop => { defaultExport.declaration.properties.forEach( prop => {
templateProperties[ prop.key.name ] = prop; templateProperties[ prop.key.name ] = prop;
}); });
this.code.prependRight( js.content.start, 'var template = (function () {' ); this.code.prependRight( js.content.start, `var ${this.alias( 'template' )} = (function () {` );
} else { } else {
this.code.prependRight( js.content.start, '(function () {' ); this.code.prependRight( js.content.start, '(function () {' );
} }

@ -28,7 +28,7 @@ export default function annotateWithScopes ( expression ) {
node._scope = scope = new Scope( scope, true ); node._scope = scope = new Scope( scope, true );
} }
else if ( /Declaration/.test( node.type ) ) { else if ( /(Function|Class|Variable)Declaration/.test( node.type ) ) {
scope.addDeclaration( node ); scope.addDeclaration( node );
} }
}, },
@ -54,7 +54,7 @@ class Scope {
if ( node.kind === 'var' && !this.block && this.parent ) { if ( node.kind === 'var' && !this.block && this.parent ) {
this.parent.addDeclaration( node ); this.parent.addDeclaration( node );
} else if ( node.type === 'VariableDeclaration' ) { } else if ( node.type === 'VariableDeclaration' ) {
node.declarators.forEach( declarator => { node.declarations.forEach( declarator => {
extractNames( declarator.id ).forEach( name => { extractNames( declarator.id ).forEach( name => {
this.declarations[ name ] = true; this.declarations[ name ] = true;
}); });
@ -100,4 +100,3 @@ const extractors = {
extractors[ param.left.type ]( names, param.left ); extractors[ param.left.type ]( names, param.left );
} }
}; };

@ -148,20 +148,6 @@ class DomGenerator extends Generator {
return this.alias( name ); return this.alias( name );
} }
alias ( name ) {
if ( !( name in this.aliases ) ) {
let alias = name;
let i = 1;
while ( alias in this.importedNames ) {
alias = `${name}$${i++}`;
}
this.aliases[ name ] = alias;
}
return this.aliases[ name ];
}
} }
export default function dom ( parsed, source, options, names ) { export default function dom ( parsed, source, options, names ) {
@ -185,12 +171,6 @@ export default function dom ( parsed, source, options, names ) {
templateProperties.ondestroy = templateProperties.onteardown; templateProperties.ondestroy = templateProperties.onteardown;
} }
generator.imports.forEach( node => {
node.specifiers.forEach( specifier => {
generator.importedNames[ specifier.local.name ] = true;
});
});
let namespace = null; let namespace = null;
if ( templateProperties.namespace ) { if ( templateProperties.namespace ) {
const ns = templateProperties.namespace.value.value; const ns = templateProperties.namespace.value.value;
@ -266,7 +246,7 @@ export default function dom ( parsed, source, options, names ) {
computations.forEach( ({ key, deps }) => { computations.forEach( ({ key, deps }) => {
builder.addBlock( deindent` builder.addBlock( deindent`
if ( isInitial || ${deps.map( dep => `( '${dep}' in newState && typeof state.${dep} === 'object' || state.${dep} !== oldState.${dep} )` ).join( ' || ' )} ) { if ( isInitial || ${deps.map( dep => `( '${dep}' in newState && typeof state.${dep} === 'object' || state.${dep} !== oldState.${dep} )` ).join( ' || ' )} ) {
state.${key} = newState.${key} = template.computed.${key}( ${deps.map( dep => `state.${dep}` ).join( ', ' )} ); state.${key} = newState.${key} = ${generator.alias( 'template' )}.computed.${key}( ${deps.map( dep => `state.${dep}` ).join( ', ' )} );
} }
` ); ` );
}); });
@ -343,9 +323,9 @@ export default function dom ( parsed, source, options, names ) {
if ( templateProperties.oncreate ) { if ( templateProperties.oncreate ) {
builders.init.addBlock( deindent` builders.init.addBlock( deindent`
if ( options._root ) { if ( options._root ) {
options._root._renderHooks.push({ fn: template.oncreate, context: this }); options._root._renderHooks.push({ fn: ${generator.alias( 'template' )}.oncreate, context: this });
} else { } else {
template.oncreate.call( this ); ${generator.alias( 'template' )}.oncreate.call( this );
} }
` ); ` );
} }
@ -356,7 +336,7 @@ export default function dom ( parsed, source, options, names ) {
if ( generator.usesRefs ) constructorBlock.addLine( `this.refs = {};` ); if ( generator.usesRefs ) constructorBlock.addLine( `this.refs = {};` );
constructorBlock.addLine( constructorBlock.addLine(
`this._state = ${templateProperties.data ? `Object.assign( template.data(), options.data )` : `options.data || {}`};` `this._state = ${templateProperties.data ? `Object.assign( ${generator.alias( 'template' )}.data(), options.data )` : `options.data || {}`};`
); );
if ( !generator.builders.metaBindings.isEmpty() ) { if ( !generator.builders.metaBindings.isEmpty() ) {
@ -408,11 +388,11 @@ export default function dom ( parsed, source, options, names ) {
const sharedPath = options.shared === true ? 'svelte/shared.js' : options.shared; const sharedPath = options.shared === true ? 'svelte/shared.js' : options.shared;
if ( sharedPath ) { if ( sharedPath ) {
const base = templateProperties.methods ? `{}, template.methods` : `{}`; const base = templateProperties.methods ? `{}, ${generator.alias( 'template' )}.methods` : `{}`;
builders.main.addBlock( `${name}.prototype = Object.assign( ${base}, ${generator.helper( 'proto' )} );` ); builders.main.addBlock( `${name}.prototype = Object.assign( ${base}, ${generator.helper( 'proto' )} );` );
} else { } else {
if ( templateProperties.methods ) { if ( templateProperties.methods ) {
builders.main.addBlock( `${name}.prototype = template.methods;` ); builders.main.addBlock( `${name}.prototype = ${generator.alias( 'template' )}.methods;` );
} }
[ 'get', 'fire', 'observe', 'on', 'set', '_flush' ].forEach( methodName => { [ 'get', 'fire', 'observe', 'on', 'set', '_flush' ].forEach( methodName => {
@ -427,7 +407,7 @@ export default function dom ( parsed, source, options, names ) {
}; };
${name}.prototype.teardown = ${name}.prototype.destroy = function destroy ( detach ) { ${name}.prototype.teardown = ${name}.prototype.destroy = function destroy ( detach ) {
this.fire( 'destroy' );${templateProperties.ondestroy ? `\ntemplate.ondestroy.call( this );` : ``} this.fire( 'destroy' );${templateProperties.ondestroy ? `\n${generator.alias( 'template' )}.ondestroy.call( this );` : ``}
this._fragment.teardown( detach !== false ); this._fragment.teardown( detach !== false );
this._fragment = null; this._fragment = null;

@ -106,7 +106,7 @@ export default {
componentInitProperties.push(`data: ${name}_initialData`); componentInitProperties.push(`data: ${name}_initialData`);
} }
const expression = node.name === ':Self' ? generator.name : generator.importedComponents[ node.name ] || `template.components.${node.name}`; const expression = node.name === ':Self' ? generator.name : generator.importedComponents[ node.name ] || `${generator.alias( 'template' )}.components.${node.name}`;
local.init.addBlockAtStart( deindent` local.init.addBlockAtStart( deindent`
${statements.join( '\n\n' )} ${statements.join( '\n\n' )}

@ -182,7 +182,7 @@ export default function addElementAttributes ( generator, node, local ) {
if ( name in generator.events ) { if ( name in generator.events ) {
local.init.addBlock( deindent` local.init.addBlock( deindent`
var ${handlerName} = template.events.${name}.call( component, ${local.name}, function ( event ) { var ${handlerName} = ${generator.alias( 'template' )}.events.${name}.call( component, ${local.name}, function ( event ) {
${handlerBody} ${handlerBody}
}); });
` ); ` );

@ -60,12 +60,12 @@ export default function ssr ( parsed, source, options, names ) {
parsed.html.children.forEach( node => generator.visit( node ) ); parsed.html.children.forEach( node => generator.visit( node ) );
builders.render.addLine( builders.render.addLine(
templateProperties.data ? `root = Object.assign( template.data(), root || {} );` : `root = root || {};` templateProperties.data ? `root = Object.assign( ${generator.alias( 'template' )}.data(), root || {} );` : `root = root || {};`
); );
computations.forEach( ({ key, deps }) => { computations.forEach( ({ key, deps }) => {
builders.render.addLine( builders.render.addLine(
`root.${key} = template.computed.${key}( ${deps.map( dep => `root.${dep}` ).join( ', ' )} );` `root.${key} = ${generator.alias( 'template' )}.computed.${key}( ${deps.map( dep => `root.${dep}` ).join( ', ' )} );`
); );
}); });
@ -118,7 +118,7 @@ export default function ssr ( parsed, source, options, names ) {
` ); ` );
templateProperties.components.value.properties.forEach( prop => { templateProperties.components.value.properties.forEach( prop => {
builders.renderCss.addLine( `addComponent( template.components.${prop.key.name} );` ); builders.renderCss.addLine( `addComponent( ${generator.alias( 'template' )}.components.${prop.key.name} );` );
}); });
} }
@ -140,7 +140,7 @@ export default function ssr ( parsed, source, options, names ) {
${name}.filename = ${JSON.stringify( options.filename )}; ${name}.filename = ${JSON.stringify( options.filename )};
${name}.data = function () { ${name}.data = function () {
return ${templateProperties.data ? `template.data()` : `{}`}; return ${templateProperties.data ? `${generator.alias( 'template' )}.data()` : `{}`};
}; };
${name}.render = function ( root, options ) { ${name}.render = function ( root, options ) {

@ -50,7 +50,7 @@ export default {
})) }))
.join( ', ' ); .join( ', ' );
const expression = node.name === ':Self' ? generator.name : `template.components.${node.name}`; const expression = node.name === ':Self' ? generator.name : `${generator.alias( 'template' )}.components.${node.name}`;
bindings.forEach( binding => { bindings.forEach( binding => {
generator.addBinding( binding, expression ); generator.addBinding( binding, expression );

@ -0,0 +1,3 @@
export default {
html: `template`
};

@ -0,0 +1,13 @@
{{value}}
<script>
import template from './module.js';
export default {
data() {
return {
value: template
};
}
};
</script>

@ -0,0 +1,3 @@
export default {
html: `template`
};

@ -0,0 +1,15 @@
{{value}}
<script>
export default {
data() {
return {
value: template()
};
}
};
function template() {
return 'template';
}
</script>
Loading…
Cancel
Save