pull/864/head
Rich Harris 8 years ago
parent 2865a98e57
commit 49403d4326

@ -1 +1,2 @@
--bail
test/test.js test/test.js

@ -63,6 +63,7 @@ export default class Generator {
stylesheet: Stylesheet; stylesheet: Stylesheet;
userVars: Set<string>; userVars: Set<string>;
templateVars: Map<string, string>;
aliases: Map<string, string>; aliases: Map<string, string>;
usedNames: Set<string>; usedNames: Set<string>;
@ -105,6 +106,7 @@ export default class Generator {
// allow compiler to deconflict user's `import { get } from 'whatever'` and // allow compiler to deconflict user's `import { get } from 'whatever'` and
// Svelte's builtin `import { get, ... } from 'svelte/shared.ts'`; // Svelte's builtin `import { get, ... } from 'svelte/shared.ts'`;
this.userVars = new Set(); this.userVars = new Set();
this.templateVars = new Map();
this.aliases = new Map(); this.aliases = new Map();
this.usedNames = new Set(); this.usedNames = new Set();
@ -204,8 +206,8 @@ export default class Generator {
let object = node; let object = node;
while (object.type === 'MemberExpression') object = object.object; while (object.type === 'MemberExpression') object = object.object;
const alias = self.alias(name); const alias = self.templateVars.get(`helpers-${name}`);
if (alias !== name) code.overwrite(object.start, object.end, `${self.alias(name)}`); if (alias !== name) code.overwrite(object.start, object.end, alias);
} else if (indexes.has(name)) { } else if (indexes.has(name)) {
const context = indexes.get(name); const context = indexes.get(name);
usedContexts.add(context); // TODO is this right? usedContexts.add(context); // TODO is this right?
@ -458,7 +460,7 @@ export default class Generator {
} }
}); });
const addArrowFunctionExpression = (key: string, node: Node) => { const addArrowFunctionExpression = (name: string, node: Node) => {
const { body, params } = node; const { body, params } = node;
const paramString = params.length ? const paramString = params.length ?
@ -467,43 +469,45 @@ export default class Generator {
if (body.type === 'BlockStatement') { if (body.type === 'BlockStatement') {
componentDefinition.addBlock(deindent` componentDefinition.addBlock(deindent`
function @${key}(${paramString}) [${body.start}-${body.end}] function ${name}(${paramString}) [${body.start}-${body.end}]
`); `);
} else { } else {
componentDefinition.addBlock(deindent` componentDefinition.addBlock(deindent`
function @${key}(${paramString}) { function ${name}(${paramString}) {
return [${body.start}-${body.end}]; return [${body.start}-${body.end}];
} }
`); `);
} }
}; };
const addFunctionExpression = (key: string, node: Node) => { const addFunctionExpression = (name: string, node: Node) => {
let c = node.start; let c = node.start;
while (this.source[c] !== '(') c += 1; while (this.source[c] !== '(') c += 1;
componentDefinition.addBlock(deindent` componentDefinition.addBlock(deindent`
function @${key}[${c}-${node.end}]; function ${name}[${c}-${node.end}];
`); `);
}; };
const addValue = (key: string, node: Node) => { const addValue = (name: string, node: Node) => {
const alias = this.alias(key); if (node.type !== 'Identifier' || node.name !== name) {
if (node.type !== 'Identifier' || node.name !== alias) {
componentDefinition.addBlock(deindent` componentDefinition.addBlock(deindent`
var ${alias} = [${node.start}-${node.end}]; var ${name} = [${node.start}-${node.end}];
`); `);
} }
}; };
const addDeclaration = (key: string, node: Node) => { const addDeclaration = (key: string, node: Node, disambiguator?: string) => {
let name = this.getUniqueName(key);
this.templateVars.set(disambiguator ? `${disambiguator}-${key}` : key, name);
// TODO disambiguate between different categories, and ensure // TODO disambiguate between different categories, and ensure
// no conflicts with existing aliases // no conflicts with existing aliases
if (node.type === 'ArrowFunctionExpression') { if (node.type === 'ArrowFunctionExpression') {
addArrowFunctionExpression(key, node); addArrowFunctionExpression(name, node);
} else if (node.type === 'FunctionExpression') { } else if (node.type === 'FunctionExpression') {
addFunctionExpression(key, node); addFunctionExpression(name, node);
} else { } else {
addValue(key, node); addValue(name, node);
} }
}; };
@ -558,7 +562,7 @@ export default class Generator {
computations.push({ key, deps }); computations.push({ key, deps });
const prop = templateProperties.computed.value.properties.find((prop: Node) => prop.key.name === key); const prop = templateProperties.computed.value.properties.find((prop: Node) => prop.key.name === key);
addDeclaration(key, prop.value); addDeclaration(key, prop.value, 'computed');
}; };
templateProperties.computed.value.properties.forEach((prop: Node) => templateProperties.computed.value.properties.forEach((prop: Node) =>
@ -572,13 +576,13 @@ export default class Generator {
if (templateProperties.events) { if (templateProperties.events) {
templateProperties.events.value.properties.forEach((property: Node) => { templateProperties.events.value.properties.forEach((property: Node) => {
addDeclaration(property.key.name, property.value); addDeclaration(property.key.name, property.value, 'events');
}); });
} }
if (templateProperties.helpers) { if (templateProperties.helpers) {
templateProperties.helpers.value.properties.forEach((property: Node) => { templateProperties.helpers.value.properties.forEach((property: Node) => {
addDeclaration(property.key.name, property.value); addDeclaration(property.key.name, property.value, 'helpers');
}); });
} }
@ -615,7 +619,7 @@ export default class Generator {
if (templateProperties.transitions) { if (templateProperties.transitions) {
templateProperties.transitions.value.properties.forEach((property: Node) => { templateProperties.transitions.value.properties.forEach((property: Node) => {
addDeclaration(property.key.name, property.value); addDeclaration(property.key.name, property.value, 'transitions');
}); });
} }
} }

@ -127,7 +127,7 @@ export default function dom(
const condition = `${deps.map(dep => `changed.${dep}`).join(' || ')}`; const condition = `${deps.map(dep => `changed.${dep}`).join(' || ')}`;
const statement = `if (@differs(state.${key}, (state.${key} = @${key}(${deps const statement = `if (@differs(state.${key}, (state.${key} = %computed-${key}(${deps
.map(dep => `state.${dep}`) .map(dep => `state.${dep}`)
.join(', ')})))) changed.${key} = true;`; .join(', ')})))) changed.${key} = true;`;
@ -173,7 +173,7 @@ export default function dom(
const prototypeBase = const prototypeBase =
`${name}.prototype` + `${name}.prototype` +
(templateProperties.methods ? `, @methods` : ''); (templateProperties.methods ? `, %methods` : '');
const proto = sharedPath const proto = sharedPath
? `@proto` ? `@proto`
: deindent` : deindent`
@ -192,7 +192,7 @@ export default function dom(
@init(this, options); @init(this, options);
${generator.usesRefs && `this.refs = {};`} ${generator.usesRefs && `this.refs = {};`}
this._state = ${templateProperties.data this._state = ${templateProperties.data
? `@assign(@data(), options.data)` ? `@assign(%data(), options.data)`
: `options.data || {}`}; : `options.data || {}`};
${generator.metaBindings} ${generator.metaBindings}
${computations.length && `this._recompute({ ${Array.from(computationDeps).map(dep => `${dep}: 1`).join(', ')} }, this._state);`} ${computations.length && `this._recompute({ ${Array.from(computationDeps).map(dep => `${dep}: 1`).join(', ')} }, this._state);`}
@ -204,7 +204,7 @@ export default function dom(
${generator.bindingGroups.length && ${generator.bindingGroups.length &&
`this._bindingGroups = [${Array(generator.bindingGroups.length).fill('[]').join(', ')}];`} `this._bindingGroups = [${Array(generator.bindingGroups.length).fill('[]').join(', ')}];`}
${templateProperties.ondestroy && `this._handlers.destroy = [@ondestroy]`} ${templateProperties.ondestroy && `this._handlers.destroy = [%ondestroy]`}
${generator.slots.size && `this._slotted = options.slots || {};`} ${generator.slots.size && `this._slotted = options.slots || {};`}
@ -217,7 +217,7 @@ export default function dom(
`if (!document.getElementById("${generator.stylesheet.id}-style")) @add_css();`) `if (!document.getElementById("${generator.stylesheet.id}-style")) @add_css();`)
} }
${templateProperties.oncreate && `var _oncreate = @oncreate.bind(this);`} ${templateProperties.oncreate && `var _oncreate = %oncreate.bind(this);`}
${(templateProperties.oncreate || generator.hasComponents || generator.hasComplexBindings || generator.hasIntroTransitions) && deindent` ${(templateProperties.oncreate || generator.hasComponents || generator.hasComplexBindings || generator.hasIntroTransitions) && deindent`
if (!options._root) { if (!options._root) {
@ -345,6 +345,9 @@ export default function dom(
let result = builder let result = builder
.toString() .toString()
.replace(/%(\w+(?:-\w+)?)/gm, (match: string, name: string) => {
return generator.templateVars.get(name);
})
.replace(/(@+)(\w*)/g, (match: string, sigil: string, name: string) => { .replace(/(@+)(\w*)/g, (match: string, sigil: string, name: string) => {
if (sigil !== '@') return sigil.slice(1) + name; if (sigil !== '@') return sigil.slice(1) + name;

@ -79,7 +79,7 @@ export default function visitEventHandler(
block.addVariable(handlerName); block.addVariable(handlerName);
block.builders.hydrate.addBlock(deindent` block.builders.hydrate.addBlock(deindent`
${handlerName} = @${name}.call(#component, ${state.parentNode}, function(event) { ${handlerName} = %events-${name}.call(#component, ${state.parentNode}, function(event) {
${handlerBody} ${handlerBody}
}); });
`); `);

@ -20,7 +20,7 @@ export default function addTransitions(
block.addVariable(name); block.addVariable(name);
const fn = `@${intro.name}`; const fn = `%transitions-${intro.name}`;
block.builders.intro.addBlock(deindent` block.builders.intro.addBlock(deindent`
#component._root._aftercreate.push(function() { #component._root._aftercreate.push(function() {
@ -48,7 +48,7 @@ export default function addTransitions(
? block.contextualise(intro.expression).snippet ? block.contextualise(intro.expression).snippet
: '{}'; : '{}';
const fn = `@${intro.name}`; // TODO add built-in transitions? const fn = `%transitions-${intro.name}`; // TODO add built-in transitions?
if (outro) { if (outro) {
block.builders.intro.addBlock(deindent` block.builders.intro.addBlock(deindent`
@ -73,7 +73,7 @@ export default function addTransitions(
? block.contextualise(outro.expression).snippet ? block.contextualise(outro.expression).snippet
: '{}'; : '{}';
const fn = `@${outro.name}`; const fn = `%transitions-${outro.name}`;
// TODO hide elements that have outro'd (unless they belong to a still-outroing // TODO hide elements that have outro'd (unless they belong to a still-outroing
// group) prior to their removal from the DOM // group) prior to their removal from the DOM

@ -108,17 +108,17 @@ export default function ssr(
${options.filename && `${name}.filename = ${stringify(options.filename)}`}; ${options.filename && `${name}.filename = ${stringify(options.filename)}`};
${name}.data = function() { ${name}.data = function() {
return ${templateProperties.data ? `@data()` : `{}`}; return ${templateProperties.data ? `%data()` : `{}`};
}; };
${name}.render = function(state, options) { ${name}.render = function(state, options) {
${templateProperties.data ${templateProperties.data
? `state = Object.assign(@data(), state || {});` ? `state = Object.assign(%data(), state || {});`
: `state = state || {};`} : `state = state || {};`}
${computations.map( ${computations.map(
({ key, deps }) => ({ key, deps }) =>
`state.${key} = @${key}(${deps.map(dep => `state.${dep}`).join(', ')});` `state.${key} = %computed-${key}(${deps.map(dep => `state.${dep}`).join(', ')});`
)} )}
${generator.bindings.length && ${generator.bindings.length &&
@ -186,8 +186,10 @@ export default function ssr(
function __escape(html) { function __escape(html) {
return String(html).replace(/["'&<>]/g, match => escaped[match]); return String(html).replace(/["'&<>]/g, match => escaped[match]);
} }
`.replace(/(@+|#+)(\w*)/g, (match: string, sigil: string, name: string) => { `.replace(/(@+|#+|%+)(\w*(?:-\w*)?)/g, (match: string, sigil: string, name: string) => {
return sigil === '@' ? generator.alias(name) : sigil.slice(1) + name; if (sigil === '@') return generator.alias(name);
if (sigil === '%') return generator.templateVars.get(name);
return sigil.slice(1) + name;
}); });
return generator.generate(result, options, { name, format }); return generator.generate(result, options, { name, format });

Loading…
Cancel
Save