From 49403d4326bab9047c188052f5abfb76d249d9d1 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 19 Sep 2017 18:43:24 -0400 Subject: [PATCH] deconflict --- mocha.opts | 1 + src/generators/Generator.ts | 42 ++++++++++--------- src/generators/dom/index.ts | 13 +++--- .../dom/visitors/Element/EventHandler.ts | 2 +- .../dom/visitors/Element/addTransitions.ts | 6 +-- src/generators/server-side-rendering/index.ts | 12 +++--- 6 files changed, 43 insertions(+), 33 deletions(-) diff --git a/mocha.opts b/mocha.opts index 427b029758..af6b17a845 100644 --- a/mocha.opts +++ b/mocha.opts @@ -1 +1,2 @@ +--bail test/test.js \ No newline at end of file diff --git a/src/generators/Generator.ts b/src/generators/Generator.ts index 9827c09b0d..e7243bc6c5 100644 --- a/src/generators/Generator.ts +++ b/src/generators/Generator.ts @@ -63,6 +63,7 @@ export default class Generator { stylesheet: Stylesheet; userVars: Set; + templateVars: Map; aliases: Map; usedNames: Set; @@ -105,6 +106,7 @@ export default class Generator { // allow compiler to deconflict user's `import { get } from 'whatever'` and // Svelte's builtin `import { get, ... } from 'svelte/shared.ts'`; this.userVars = new Set(); + this.templateVars = new Map(); this.aliases = new Map(); this.usedNames = new Set(); @@ -204,8 +206,8 @@ export default class Generator { let object = node; while (object.type === 'MemberExpression') object = object.object; - const alias = self.alias(name); - if (alias !== name) code.overwrite(object.start, object.end, `${self.alias(name)}`); + const alias = self.templateVars.get(`helpers-${name}`); + if (alias !== name) code.overwrite(object.start, object.end, alias); } else if (indexes.has(name)) { const context = indexes.get(name); 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 paramString = params.length ? @@ -467,43 +469,45 @@ export default class Generator { if (body.type === 'BlockStatement') { componentDefinition.addBlock(deindent` - function @${key}(${paramString}) [✂${body.start}-${body.end}✂] + function ${name}(${paramString}) [✂${body.start}-${body.end}✂] `); } else { componentDefinition.addBlock(deindent` - function @${key}(${paramString}) { + function ${name}(${paramString}) { return [✂${body.start}-${body.end}✂]; } `); } }; - const addFunctionExpression = (key: string, node: Node) => { + const addFunctionExpression = (name: string, node: Node) => { let c = node.start; while (this.source[c] !== '(') c += 1; componentDefinition.addBlock(deindent` - function @${key}[✂${c}-${node.end}✂]; + function ${name}[✂${c}-${node.end}✂]; `); }; - const addValue = (key: string, node: Node) => { - const alias = this.alias(key); - if (node.type !== 'Identifier' || node.name !== alias) { + const addValue = (name: string, node: Node) => { + if (node.type !== 'Identifier' || node.name !== name) { 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 // no conflicts with existing aliases if (node.type === 'ArrowFunctionExpression') { - addArrowFunctionExpression(key, node); + addArrowFunctionExpression(name, node); } else if (node.type === 'FunctionExpression') { - addFunctionExpression(key, node); + addFunctionExpression(name, node); } else { - addValue(key, node); + addValue(name, node); } }; @@ -558,7 +562,7 @@ export default class Generator { computations.push({ key, deps }); 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) => @@ -572,13 +576,13 @@ export default class Generator { if (templateProperties.events) { templateProperties.events.value.properties.forEach((property: Node) => { - addDeclaration(property.key.name, property.value); + addDeclaration(property.key.name, property.value, 'events'); }); } if (templateProperties.helpers) { 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) { templateProperties.transitions.value.properties.forEach((property: Node) => { - addDeclaration(property.key.name, property.value); + addDeclaration(property.key.name, property.value, 'transitions'); }); } } diff --git a/src/generators/dom/index.ts b/src/generators/dom/index.ts index 7eac27be55..eee9c5669c 100644 --- a/src/generators/dom/index.ts +++ b/src/generators/dom/index.ts @@ -127,7 +127,7 @@ export default function dom( 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}`) .join(', ')})))) changed.${key} = true;`; @@ -173,7 +173,7 @@ export default function dom( const prototypeBase = `${name}.prototype` + - (templateProperties.methods ? `, @methods` : ''); + (templateProperties.methods ? `, %methods` : ''); const proto = sharedPath ? `@proto` : deindent` @@ -192,7 +192,7 @@ export default function dom( @init(this, options); ${generator.usesRefs && `this.refs = {};`} this._state = ${templateProperties.data - ? `@assign(@data(), options.data)` + ? `@assign(%data(), options.data)` : `options.data || {}`}; ${generator.metaBindings} ${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 && `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 || {};`} @@ -217,7 +217,7 @@ export default function dom( `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` if (!options._root) { @@ -345,6 +345,9 @@ export default function dom( let result = builder .toString() + .replace(/%(\w+(?:-\w+)?)/gm, (match: string, name: string) => { + return generator.templateVars.get(name); + }) .replace(/(@+)(\w*)/g, (match: string, sigil: string, name: string) => { if (sigil !== '@') return sigil.slice(1) + name; diff --git a/src/generators/dom/visitors/Element/EventHandler.ts b/src/generators/dom/visitors/Element/EventHandler.ts index f14c5e145f..0a887f63f7 100644 --- a/src/generators/dom/visitors/Element/EventHandler.ts +++ b/src/generators/dom/visitors/Element/EventHandler.ts @@ -79,7 +79,7 @@ export default function visitEventHandler( block.addVariable(handlerName); block.builders.hydrate.addBlock(deindent` - ${handlerName} = @${name}.call(#component, ${state.parentNode}, function(event) { + ${handlerName} = %events-${name}.call(#component, ${state.parentNode}, function(event) { ${handlerBody} }); `); diff --git a/src/generators/dom/visitors/Element/addTransitions.ts b/src/generators/dom/visitors/Element/addTransitions.ts index 739fe1b6bb..b10f404de2 100644 --- a/src/generators/dom/visitors/Element/addTransitions.ts +++ b/src/generators/dom/visitors/Element/addTransitions.ts @@ -20,7 +20,7 @@ export default function addTransitions( block.addVariable(name); - const fn = `@${intro.name}`; + const fn = `%transitions-${intro.name}`; block.builders.intro.addBlock(deindent` #component._root._aftercreate.push(function() { @@ -48,7 +48,7 @@ export default function addTransitions( ? 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) { block.builders.intro.addBlock(deindent` @@ -73,7 +73,7 @@ export default function addTransitions( ? 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 // group) prior to their removal from the DOM diff --git a/src/generators/server-side-rendering/index.ts b/src/generators/server-side-rendering/index.ts index 1ab3f68bc9..96f1b1fe40 100644 --- a/src/generators/server-side-rendering/index.ts +++ b/src/generators/server-side-rendering/index.ts @@ -108,17 +108,17 @@ export default function ssr( ${options.filename && `${name}.filename = ${stringify(options.filename)}`}; ${name}.data = function() { - return ${templateProperties.data ? `@data()` : `{}`}; + return ${templateProperties.data ? `%data()` : `{}`}; }; ${name}.render = function(state, options) { ${templateProperties.data - ? `state = Object.assign(@data(), state || {});` + ? `state = Object.assign(%data(), state || {});` : `state = state || {};`} ${computations.map( ({ key, deps }) => - `state.${key} = @${key}(${deps.map(dep => `state.${dep}`).join(', ')});` + `state.${key} = %computed-${key}(${deps.map(dep => `state.${dep}`).join(', ')});` )} ${generator.bindings.length && @@ -186,8 +186,10 @@ export default function ssr( function __escape(html) { return String(html).replace(/["'&<>]/g, match => escaped[match]); } - `.replace(/(@+|#+)(\w*)/g, (match: string, sigil: string, name: string) => { - return sigil === '@' ? generator.alias(name) : sigil.slice(1) + name; + `.replace(/(@+|#+|%+)(\w*(?:-\w*)?)/g, (match: string, sigil: string, name: string) => { + 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 });