rename Compiler to Component

pull/1721/head
Rich Harris 7 years ago
parent 8f854b4b49
commit d08051b35c

@ -1,5 +1,5 @@
import { Node, Warning } from './interfaces';
import Compiler from './compile/Compiler';
import Component from './compile/Component';
const now = (typeof process !== 'undefined' && process.hrtime)
? () => {
@ -73,14 +73,14 @@ export default class Stats {
this.currentChildren = this.currentTiming ? this.currentTiming.children : this.timings;
}
render(compiler: Compiler) {
render(component: Component) {
const timings = Object.assign({
total: now() - this.startTime
}, collapseTimings(this.timings));
// TODO would be good to have this info even
// if options.generate is false
const imports = compiler && compiler.imports.map(node => {
const imports = component && component.imports.map(node => {
return {
source: node.source.value,
specifiers: node.specifiers.map(specifier => {
@ -96,11 +96,11 @@ export default class Stats {
}
});
const hooks: Record<string, boolean> = compiler && {
oncreate: !!compiler.templateProperties.oncreate,
ondestroy: !!compiler.templateProperties.ondestroy,
onstate: !!compiler.templateProperties.onstate,
onupdate: !!compiler.templateProperties.onupdate
const hooks: Record<string, boolean> = component && {
oncreate: !!component.templateProperties.oncreate,
ondestroy: !!component.templateProperties.ondestroy,
onstate: !!component.templateProperties.onstate,
onupdate: !!component.templateProperties.onupdate
};
return {

@ -6,20 +6,19 @@ import { getLocator } from 'locate-character';
import Stats from '../Stats';
import deindent from '../utils/deindent';
import CodeBuilder from '../utils/CodeBuilder';
import flattenReference from '../utils/flattenReference';
import reservedNames from '../utils/reservedNames';
import namespaces from '../utils/namespaces';
import { removeNode, removeObjectKey } from '../utils/removeNode';
import { removeNode } from '../utils/removeNode';
import nodeToString from '../utils/nodeToString';
import wrapModule from './wrapModule';
import annotateWithScopes, { Scope } from '../utils/annotateWithScopes';
import annotateWithScopes from '../utils/annotateWithScopes';
import getName from '../utils/getName';
import Stylesheet from '../css/Stylesheet';
import { test } from '../config';
import Fragment from './nodes/Fragment';
import shared from './shared';
import { DomTarget } from './dom/index';
import { SsrTarget } from './ssr/index';
import { DomTarget } from './dom';
import { SsrTarget } from './ssr';
import { Node, GenerateOptions, ShorthandImport, Ast, CompileOptions, CustomElementOptions } from '../interfaces';
interface Computation {
@ -79,7 +78,7 @@ function removeIndentation(
childKeys.EachBlock = childKeys.IfBlock = ['children', 'else'];
childKeys.Attribute = ['value'];
export default class Compiler {
export default class Component {
stats: Stats;
ast: Ast;
@ -136,7 +135,6 @@ export default class Compiler {
stylesheet: Stylesheet,
options: CompileOptions,
stats: Stats,
dom: boolean,
target: DomTarget | SsrTarget
) {
stats.start('compile');
@ -189,7 +187,7 @@ export default class Compiler {
this.computations = [];
this.templateProperties = {};
this.walkJs(dom);
this.walkJs();
this.name = this.alias(name);
if (options.customElement === true) {
@ -266,7 +264,7 @@ export default class Compiler {
} else {
let inlineHelpers = '';
const compiler = this;
const component = this;
importedHelpers = [];
@ -291,7 +289,7 @@ export default class Compiler {
const dependency = node.name;
helpers.add(dependency);
const alias = compiler.alias(dependency);
const alias = component.alias(dependency);
if (alias !== node.name) {
code.overwrite(node.start, node.end, alias);
}
@ -432,7 +430,7 @@ export default class Compiler {
};
}
walkJs(dom: boolean) {
walkJs() {
const {
code,
source,
@ -532,7 +530,13 @@ export default class Compiler {
`);
};
const addDeclaration = (key: string, node: Node, allowShorthandImport?: boolean, disambiguator?: string, conflicts?: Record<string, boolean>) => {
const addDeclaration = (
key: string,
node: Node,
allowShorthandImport?: boolean,
disambiguator?: string,
conflicts?: Record<string, boolean>
) => {
const qualified = disambiguator ? `${disambiguator}-${key}` : key;
if (node.type === 'Identifier' && node.name === key) {
@ -634,7 +638,7 @@ export default class Compiler {
addDeclaration('data', templateProperties.data.value);
}
if (templateProperties.events && dom) {
if (templateProperties.events) {
templateProperties.events.value.properties.forEach((property: Node) => {
addDeclaration(getName(property.key), property.value, false, 'events');
});
@ -646,7 +650,7 @@ export default class Compiler {
});
}
if (templateProperties.methods && dom) {
if (templateProperties.methods) {
addDeclaration('methods', templateProperties.methods.value);
templateProperties.methods.value.properties.forEach(prop => {
@ -659,19 +663,19 @@ export default class Compiler {
this.namespace = namespaces[ns] || ns;
}
if (templateProperties.oncreate && dom) {
if (templateProperties.oncreate) {
addDeclaration('oncreate', templateProperties.oncreate.value);
}
if (templateProperties.ondestroy && dom) {
if (templateProperties.ondestroy) {
addDeclaration('ondestroy', templateProperties.ondestroy.value);
}
if (templateProperties.onstate && dom) {
if (templateProperties.onstate) {
addDeclaration('onstate', templateProperties.onstate.value);
}
if (templateProperties.onupdate && dom) {
if (templateProperties.onupdate) {
addDeclaration('onupdate', templateProperties.onupdate.value);
}

@ -1,12 +1,12 @@
import CodeBuilder from '../../utils/CodeBuilder';
import deindent from '../../utils/deindent';
import { escape } from '../../utils/stringify';
import Compiler from '../Compiler';
import Component from '../Component';
export interface BlockOptions {
parent?: Block;
name: string;
compiler?: Compiler;
component?: Component;
comment?: string;
key?: string;
bindings?: Map<string, string>;
@ -15,7 +15,7 @@ export interface BlockOptions {
export default class Block {
parent?: Block;
compiler: Compiler;
component: Component;
name: string;
comment?: string;
@ -58,7 +58,7 @@ export default class Block {
constructor(options: BlockOptions) {
this.parent = options.parent;
this.compiler = options.compiler;
this.component = options.component;
this.name = options.name;
this.comment = options.comment;
@ -90,7 +90,7 @@ export default class Block {
this.hasOutroMethod = false;
this.outros = 0;
this.getUniqueName = this.compiler.getUniqueNameMaker();
this.getUniqueName = this.component.getUniqueNameMaker();
this.variables = new Map();
this.aliases = new Map()
@ -128,11 +128,11 @@ export default class Block {
}
addIntro() {
this.hasIntros = this.hasIntroMethod = this.compiler.target.hasIntroTransitions = true;
this.hasIntros = this.hasIntroMethod = this.component.target.hasIntroTransitions = true;
}
addOutro() {
this.hasOutros = this.hasOutroMethod = this.compiler.target.hasOutroTransitions = true;
this.hasOutros = this.hasOutroMethod = this.component.target.hasOutroTransitions = true;
this.outros += 1;
}
@ -167,7 +167,7 @@ export default class Block {
}
toString() {
const { dev } = this.compiler.options;
const { dev } = this.component.options;
if (this.hasIntroMethod || this.hasOutroMethod) {
this.addVariable('#current');
@ -202,7 +202,7 @@ export default class Block {
properties.addBlock(`c: @noop,`);
} else {
const hydrate = !this.builders.hydrate.isEmpty() && (
this.compiler.options.hydratable
this.component.options.hydratable
? `this.h()`
: this.builders.hydrate
);
@ -215,7 +215,7 @@ export default class Block {
`);
}
if (this.compiler.options.hydratable) {
if (this.component.options.hydratable) {
if (this.builders.claim.isEmpty() && this.builders.hydrate.isEmpty()) {
properties.addBlock(`l: @noop,`);
} else {
@ -228,7 +228,7 @@ export default class Block {
}
}
if (this.compiler.options.hydratable && !this.builders.hydrate.isEmpty()) {
if (this.component.options.hydratable && !this.builders.hydrate.isEmpty()) {
properties.addBlock(deindent`
${dev ? 'h: function hydrate' : 'h'}() {
${this.builders.hydrate}

@ -2,7 +2,7 @@ import deindent from '../../utils/deindent';
import { stringify, escape } from '../../utils/stringify';
import CodeBuilder from '../../utils/CodeBuilder';
import globalWhitelist from '../../utils/globalWhitelist';
import Compiler from '../Compiler';
import Component from '../Component';
import Stylesheet from '../../css/Stylesheet';
import Stats from '../../Stats';
import Block from './Block';
@ -36,19 +36,19 @@ export default function dom(
const format = options.format || 'es';
const target = new DomTarget();
const compiler = new Compiler(ast, source, options.name || 'SvelteComponent', stylesheet, options, stats, true, target);
const component = new Component(ast, source, options.name || 'SvelteComponent', stylesheet, options, stats, target);
const {
computations,
name,
templateProperties,
namespace,
} = compiler;
} = component;
compiler.fragment.build();
const { block } = compiler.fragment;
component.fragment.build();
const { block } = component.fragment;
if (compiler.options.nestedTransitions) {
if (component.options.nestedTransitions) {
block.hasOutroMethod = true;
}
@ -89,24 +89,24 @@ export default function dom(
});
}
if (compiler.javascript) {
builder.addBlock(compiler.javascript);
if (component.javascript) {
builder.addBlock(component.javascript);
}
if (compiler.options.dev) {
builder.addLine(`const ${compiler.fileVar} = ${JSON.stringify(compiler.file)};`);
if (component.options.dev) {
builder.addLine(`const ${component.fileVar} = ${JSON.stringify(component.file)};`);
}
const css = compiler.stylesheet.render(options.filename, !compiler.customElement);
const styles = compiler.stylesheet.hasStyles && stringify(options.dev ?
const css = component.stylesheet.render(options.filename, !component.customElement);
const styles = component.stylesheet.hasStyles && stringify(options.dev ?
`${css.code}\n/*# sourceMappingURL=${css.map.toUrl()} */` :
css.code, { onlyEscapeAtSymbol: true });
if (styles && compiler.options.css !== false && !compiler.customElement) {
if (styles && component.options.css !== false && !component.customElement) {
builder.addBlock(deindent`
function @add_css() {
var style = @createElement("style");
style.id = '${compiler.stylesheet.id}-style';
style.id = '${component.stylesheet.id}-style';
style.textContent = ${styles};
@append(document.head, style);
}
@ -130,10 +130,10 @@ export default function dom(
.join(',\n')}
}`;
const debugName = `<${compiler.customElement ? compiler.tag : name}>`;
const debugName = `<${component.customElement ? component.tag : name}>`;
// generate initial state object
const expectedProperties = Array.from(compiler.expectedProperties);
const expectedProperties = Array.from(component.expectedProperties);
const globals = expectedProperties.filter(prop => globalWhitelist.has(prop));
const storeProps = expectedProperties.filter(prop => prop[0] === '$');
const initialState = [];
@ -158,32 +158,32 @@ export default function dom(
const constructorBody = deindent`
${options.dev && `this._debugName = '${debugName}';`}
${options.dev && !compiler.customElement &&
${options.dev && !component.customElement &&
`if (!options || (!options.target && !options.root)) throw new Error("'target' is a required option");`}
@init(this, options);
${templateProperties.store && `this.store = %store();`}
${compiler.usesRefs && `this.refs = {};`}
${component.usesRefs && `this.refs = {};`}
this._state = ${initialState.reduce((state, piece) => `@assign(${state}, ${piece})`)};
${storeProps.length > 0 && `this.store._add(this, [${storeProps.map(prop => `"${prop.slice(1)}"`)}]);`}
${target.metaBindings}
${computations.length && `this._recompute({ ${Array.from(computationDeps).map(dep => `${dep}: 1`).join(', ')} }, this._state);`}
${options.dev &&
Array.from(compiler.expectedProperties).map(prop => {
Array.from(component.expectedProperties).map(prop => {
if (globalWhitelist.has(prop)) return;
if (computations.find(c => c.key === prop)) return;
const message = compiler.components.has(prop) ?
const message = component.components.has(prop) ?
`${debugName} expected to find '${prop}' in \`data\`, but found it in \`components\` instead` :
`${debugName} was created without expected data property '${prop}'`;
const conditions = [`!('${prop}' in this._state)`];
if (compiler.customElement) conditions.push(`!('${prop}' in this.attributes)`);
if (component.customElement) conditions.push(`!('${prop}' in this.attributes)`);
return `if (${conditions.join(' && ')}) console.warn("${message}");`
})}
${compiler.bindingGroups.length &&
`this._bindingGroups = [${Array(compiler.bindingGroups.length).fill('[]').join(', ')}];`}
this._intro = ${compiler.options.skipIntroByDefault ? '!!options.intro' : 'true'};
${component.bindingGroups.length &&
`this._bindingGroups = [${Array(component.bindingGroups.length).fill('[]').join(', ')}];`}
this._intro = ${component.options.skipIntroByDefault ? '!!options.intro' : 'true'};
${templateProperties.onstate && `this._handlers.state = [%onstate];`}
${templateProperties.onupdate && `this._handlers.update = [%onupdate];`}
@ -194,15 +194,15 @@ export default function dom(
}];`
)}
${compiler.slots.size && `this._slotted = options.slots || {};`}
${component.slots.size && `this._slotted = options.slots || {};`}
${compiler.customElement ?
${component.customElement ?
deindent`
this.attachShadow({ mode: 'open' });
${css.code && `this.shadowRoot.innerHTML = \`<style>${escape(css.code, { onlyEscapeAtSymbol: true }).replace(/\\/g, '\\\\')}${options.dev ? `\n/*# sourceMappingURL=${css.map.toUrl()} */` : ''}</style>\`;`}
` :
(compiler.stylesheet.hasStyles && options.css !== false &&
`if (!document.getElementById("${compiler.stylesheet.id}-style")) @add_css();`)
(component.stylesheet.hasStyles && options.css !== false &&
`if (!document.getElementById("${component.stylesheet.id}-style")) @add_css();`)
}
${templateProperties.onstate && `%onstate.call(this, { changed: @assignTrue({}, this._state), current: this._state });`}
@ -216,14 +216,14 @@ export default function dom(
});
`}
${compiler.customElement ? deindent`
${component.customElement ? deindent`
this._fragment.c();
this._fragment.${block.hasIntroMethod ? 'i' : 'm'}(this.shadowRoot, null);
if (options.target) this._mount(options.target, options.anchor);
` : deindent`
if (options.target) {
${compiler.options.hydratable
${component.options.hydratable
? deindent`
var nodes = @children(options.target);
options.hydrate ? this._fragment.l(nodes) : this._fragment.c();
@ -234,16 +234,16 @@ export default function dom(
this._fragment.c();`}
this._mount(options.target, options.anchor);
${(compiler.hasComponents || target.hasComplexBindings || hasInitHooks || target.hasIntroTransitions) &&
${(component.hasComponents || target.hasComplexBindings || hasInitHooks || target.hasIntroTransitions) &&
`@flush(this);`}
}
`}
${compiler.options.skipIntroByDefault && `this._intro = true;`}
${component.options.skipIntroByDefault && `this._intro = true;`}
`;
if (compiler.customElement) {
const props = compiler.props || Array.from(compiler.expectedProperties);
if (component.customElement) {
const props = component.props || Array.from(component.expectedProperties);
builder.addBlock(deindent`
class ${name} extends HTMLElement {
@ -266,7 +266,7 @@ export default function dom(
}
`).join('\n\n')}
${compiler.slots.size && deindent`
${component.slots.size && deindent`
connectedCallback() {
Object.keys(this._slotted).forEach(key => {
this.appendChild(this._slotted[key]);
@ -277,7 +277,7 @@ export default function dom(
this.set({ [attr]: newValue });
}
${(compiler.hasComponents || target.hasComplexBindings || templateProperties.oncreate || target.hasIntroTransitions) && deindent`
${(component.hasComponents || target.hasComplexBindings || templateProperties.oncreate || target.hasIntroTransitions) && deindent`
connectedCallback() {
@flush(this);
}
@ -292,7 +292,7 @@ export default function dom(
}
});
customElements.define("${compiler.tag}", ${name});
customElements.define("${component.tag}", ${name});
`);
} else {
builder.addBlock(deindent`
@ -332,8 +332,8 @@ export default function dom(
let result = builder.toString();
return compiler.generate(result, options, {
banner: `/* ${compiler.file ? `${compiler.file} ` : ``}generated by Svelte v${"__VERSION__"} */`,
return component.generate(result, options, {
banner: `/* ${component.file ? `${component.file} ` : ``}generated by Svelte v${"__VERSION__"} */`,
sharedPath,
name,
format,

@ -6,13 +6,13 @@ export default class Action extends Node {
name: string;
expression: Expression;
constructor(compiler, parent, scope, info) {
super(compiler, parent, scope, info);
constructor(component, parent, scope, info) {
super(component, parent, scope, info);
this.name = info.name;
this.expression = info.expression
? new Expression(compiler, this, scope, info.expression)
? new Expression(component, this, scope, info.expression)
: null;
}
}

@ -7,13 +7,13 @@ export default class Animation extends Node {
name: string;
expression: Expression;
constructor(compiler, parent, scope, info) {
super(compiler, parent, scope, info);
constructor(component, parent, scope, info) {
super(component, parent, scope, info);
this.name = info.name;
this.expression = info.expression
? new Expression(compiler, this, scope, info.expression)
? new Expression(component, this, scope, info.expression)
: null;
}

@ -2,7 +2,7 @@ import deindent from '../../utils/deindent';
import { escape, escapeTemplate, stringify } from '../../utils/stringify';
import fixAttributeCasing from '../../utils/fixAttributeCasing';
import addToSet from '../../utils/addToSet';
import Compiler from '../Compiler';
import Component from '../Component';
import Node from './shared/Node';
import Element from './Element';
import Text from './Text';
@ -19,7 +19,7 @@ export default class Attribute extends Node {
start: number;
end: number;
compiler: Compiler;
component: Component;
parent: Element;
name: string;
isSpread: boolean;
@ -31,8 +31,8 @@ export default class Attribute extends Node {
chunks: (Text | Expression)[];
dependencies: Set<string>;
constructor(compiler, parent, scope, info) {
super(compiler, parent, scope, info);
constructor(component, parent, scope, info) {
super(component, parent, scope, info);
if (info.type === 'Spread') {
this.name = null;
@ -40,7 +40,7 @@ export default class Attribute extends Node {
this.isTrue = false;
this.isSynthetic = false;
this.expression = new Expression(compiler, this, scope, info.expression);
this.expression = new Expression(component, this, scope, info.expression);
this.dependencies = this.expression.dependencies;
this.chunks = null;
@ -60,7 +60,7 @@ export default class Attribute extends Node {
: info.value.map(node => {
if (node.type === 'Text') return node;
const expression = new Expression(compiler, this, scope, node.expression);
const expression = new Expression(component, this, scope, node.expression);
addToSet(this.dependencies, expression.dependencies);
return expression;
@ -136,9 +136,9 @@ export default class Attribute extends Node {
? '@setXlinkAttribute'
: '@setAttribute';
const isLegacyInputType = this.compiler.options.legacy && name === 'type' && this.parent.name === 'input';
const isLegacyInputType = this.component.options.legacy && name === 'type' && this.parent.name === 'input';
const isDataSet = /^data-/.test(name) && !this.compiler.options.legacy && !node.namespace;
const isDataSet = /^data-/.test(name) && !this.component.options.legacy && !node.namespace;
const camelCaseName = isDataSet ? name.replace('data-', '').replace(/(-\w)/g, function (m) {
return m[1].toUpperCase();
}) : name;

@ -17,18 +17,18 @@ export default class AwaitBlock extends Node {
then: ThenBlock;
catch: CatchBlock;
constructor(compiler, parent, scope, info) {
super(compiler, parent, scope, info);
constructor(component, parent, scope, info) {
super(component, parent, scope, info);
this.expression = new Expression(compiler, this, scope, info.expression);
this.expression = new Expression(component, this, scope, info.expression);
const deps = this.expression.dependencies;
this.value = info.value;
this.error = info.error;
this.pending = new PendingBlock(compiler, this, scope, info.pending);
this.then = new ThenBlock(compiler, this, scope.add(this.value, deps), info.then);
this.catch = new CatchBlock(compiler, this, scope.add(this.error, deps), info.catch);
this.pending = new PendingBlock(component, this, scope, info.pending);
this.then = new ThenBlock(component, this, scope.add(this.value, deps), info.then);
this.catch = new CatchBlock(component, this, scope.add(this.error, deps), info.catch);
}
init(
@ -49,12 +49,12 @@ export default class AwaitBlock extends Node {
const child = this[status];
child.block = block.child({
comment: createDebuggingComment(child, this.compiler),
name: this.compiler.getUniqueName(`create_${status}_block`)
comment: createDebuggingComment(child, this.component),
name: this.component.getUniqueName(`create_${status}_block`)
});
child.initChildren(child.block, stripWhitespace, nextSibling);
this.compiler.target.blocks.push(child.block);
this.component.target.blocks.push(child.block);
if (child.block.dependencies.size > 0) {
isDynamic = true;
@ -77,7 +77,7 @@ export default class AwaitBlock extends Node {
this.then.block.hasOutroMethod = hasOutros;
this.catch.block.hasOutroMethod = hasOutros;
if (hasOutros && this.compiler.options.nestedTransitions) block.addOutro();
if (hasOutros && this.component.options.nestedTransitions) block.addOutro();
}
build(
@ -171,7 +171,7 @@ export default class AwaitBlock extends Node {
`);
}
if (this.pending.block.hasOutroMethod && this.compiler.options.nestedTransitions) {
if (this.pending.block.hasOutroMethod && this.component.options.nestedTransitions) {
const countdown = block.getUniqueName('countdown');
block.builders.outro.addBlock(deindent`
const ${countdown} = @callAfter(#outrocallback, 3);
@ -196,7 +196,7 @@ export default class AwaitBlock extends Node {
}
ssr() {
const target: SsrTarget = <SsrTarget>this.compiler.target;
const target: SsrTarget = <SsrTarget>this.component.target;
const { snippet } = this.expression;
target.append('${(function(__value) { if(@isPromise(__value)) return `');

@ -3,7 +3,7 @@ import Element from './Element';
import getObject from '../../utils/getObject';
import getTailSnippet from '../../utils/getTailSnippet';
import flattenReference from '../../utils/flattenReference';
import Compiler from '../Compiler';
import Component from '../Component';
import Block from '../dom/Block';
import Expression from './shared/Expression';
import { dimensions } from '../../utils/patterns';
@ -26,11 +26,11 @@ export default class Binding extends Node {
obj: string;
prop: string;
constructor(compiler, parent, scope, info) {
super(compiler, parent, scope, info);
constructor(component, parent, scope, info) {
super(component, parent, scope, info);
this.name = info.name;
this.value = new Expression(compiler, this, scope, info.value);
this.value = new Expression(component, this, scope, info.value);
let obj;
let prop;
@ -78,7 +78,7 @@ export default class Binding extends Node {
// TODO should this happen in preprocess?
const dependencies = new Set(this.value.dependencies);
this.value.dependencies.forEach((prop: string) => {
const indirectDependencies = this.compiler.indirectDependencies.get(prop);
const indirectDependencies = this.component.indirectDependencies.get(prop);
if (indirectDependencies) {
indirectDependencies.forEach(indirectDependency => {
dependencies.add(indirectDependency);
@ -87,8 +87,8 @@ export default class Binding extends Node {
});
// view to model
const valueFromDom = getValueFromDom(this.compiler, node, this);
const handler = getEventHandler(this, this.compiler, block, name, snippet, dependencies, valueFromDom);
const valueFromDom = getValueFromDom(this.component, node, this);
const handler = getEventHandler(this, this.component, block, name, snippet, dependencies, valueFromDom);
// model to view
let updateDom = getDomUpdater(node, this, snippet);
@ -96,7 +96,7 @@ export default class Binding extends Node {
// special cases
if (this.name === 'group') {
const bindingGroup = getBindingGroup(this.compiler, this.value.node);
const bindingGroup = getBindingGroup(this.component, this.value.node);
block.builders.hydrate.addLine(
`#component._bindingGroups[${bindingGroup}].push(${node.var});`
@ -184,16 +184,16 @@ function getDomUpdater(
return `${node.var}.${binding.name} = ${snippet};`;
}
function getBindingGroup(compiler: Compiler, value: Node) {
function getBindingGroup(component: Component, value: Node) {
const { parts } = flattenReference(value); // TODO handle cases involving computed member expressions
const keypath = parts.join('.');
// TODO handle contextual bindings — `keypath` should include unique ID of
// each block that provides context
let index = compiler.bindingGroups.indexOf(keypath);
let index = component.bindingGroups.indexOf(keypath);
if (index === -1) {
index = compiler.bindingGroups.length;
compiler.bindingGroups.push(keypath);
index = component.bindingGroups.length;
component.bindingGroups.push(keypath);
}
return index;
@ -201,7 +201,7 @@ function getBindingGroup(compiler: Compiler, value: Node) {
function getEventHandler(
binding: Binding,
compiler: Compiler,
component: Component,
block: Block,
name: string,
snippet: string,
@ -235,9 +235,9 @@ function getEventHandler(
// Svelte tries to `set()` a computed property, which throws an
// error in dev mode. a) it's possible that we should be
// replacing computations with *their* dependencies, and b)
// we should probably populate `compiler.target.readonly` sooner so
// we should probably populate `component.target.readonly` sooner so
// that we don't have to do the `.some()` here
dependencies = dependencies.filter(prop => !compiler.computations.some(computation => computation.key === prop));
dependencies = dependencies.filter(prop => !component.computations.some(computation => computation.key === prop));
return {
usesContext: false,
@ -271,7 +271,7 @@ function getEventHandler(
}
function getValueFromDom(
compiler: Compiler,
component: Component,
node: Element,
binding: Node
) {
@ -286,7 +286,7 @@ function getValueFromDom(
// <input type='checkbox' bind:group='foo'>
if (binding.name === 'group') {
const bindingGroup = getBindingGroup(compiler, binding.value.node);
const bindingGroup = getBindingGroup(component, binding.value.node);
if (type === 'checkbox') {
return `@getBindingGroupValue(#component._bindingGroups[${bindingGroup}])`;
}

@ -6,8 +6,8 @@ export default class CatchBlock extends Node {
block: Block;
children: Node[];
constructor(compiler, parent, scope, info) {
super(compiler, parent, scope, info);
this.children = mapChildren(compiler, parent, scope, info.children);
constructor(component, parent, scope, info) {
super(component, parent, scope, info);
this.children = mapChildren(component, parent, scope, info.children);
}
}

@ -6,13 +6,13 @@ export default class Class extends Node {
name: string;
expression: Expression;
constructor(compiler, parent, scope, info) {
super(compiler, parent, scope, info);
constructor(component, parent, scope, info) {
super(component, parent, scope, info);
this.name = info.name;
this.expression = info.expression
? new Expression(compiler, this, scope, info.expression)
? new Expression(component, this, scope, info.expression)
: null;
}
}

@ -4,15 +4,15 @@ export default class Comment extends Node {
type: 'Comment';
data: string;
constructor(compiler, parent, scope, info) {
super(compiler, parent, scope, info);
constructor(component, parent, scope, info) {
super(component, parent, scope, info);
this.data = info.data;
}
ssr() {
// Allow option to preserve comments, otherwise ignore
if (this.compiler.options.preserveComments) {
this.compiler.target.append(`<!--${this.data}-->`);
if (this.component.options.preserveComments) {
this.component.target.append(`<!--${this.data}-->`);
}
}
}

@ -9,11 +9,11 @@ import { stringify } from '../../utils/stringify';
export default class DebugTag extends Node {
expressions: Expression[];
constructor(compiler, parent, scope, info) {
super(compiler, parent, scope, info);
constructor(component, parent, scope, info) {
super(component, parent, scope, info);
this.expressions = info.identifiers.map(node => {
return new Expression(compiler, parent, scope, node);
return new Expression(component, parent, scope, node);
});
}
@ -22,9 +22,9 @@ export default class DebugTag extends Node {
parentNode: string,
parentNodes: string,
) {
if (!this.compiler.options.dev) return;
if (!this.component.options.dev) return;
const { code } = this.compiler;
const { code } = this.component;
if (this.expressions.length === 0) {
// Debug all
@ -36,7 +36,7 @@ export default class DebugTag extends Node {
block.builders.create.addLine(statement);
block.builders.update.addLine(statement);
} else {
const { code } = this.compiler;
const { code } = this.component;
code.overwrite(this.start + 1, this.start + 7, 'log', {
storeName: true
});
@ -70,10 +70,10 @@ export default class DebugTag extends Node {
}
ssr() {
if (!this.compiler.options.dev) return;
if (!this.component.options.dev) return;
const filename = this.compiler.file || null;
const { line, column } = this.compiler.locate(this.start + 1);
const filename = this.component.file || null;
const { line, column } = this.component.locate(this.start + 1);
const obj = this.expressions.length === 0
? `ctx`
@ -84,6 +84,6 @@ export default class DebugTag extends Node {
const str = '${@debug(' + `${filename && stringify(filename)}, ${line}, ${column}, ${obj})}`;
this.compiler.target.append(str);
this.component.target.append(str);
}
}

@ -24,10 +24,10 @@ export default class EachBlock extends Node {
children: Node[];
else?: ElseBlock;
constructor(compiler, parent, scope, info) {
super(compiler, parent, scope, info);
constructor(component, parent, scope, info) {
super(component, parent, scope, info);
this.expression = new Expression(compiler, this, scope, info.expression);
this.expression = new Expression(component, this, scope, info.expression);
this.context = info.context.name || 'each'; // TODO this is used to facilitate binding; currently fails with destructuring
this.index = info.index;
@ -41,7 +41,7 @@ export default class EachBlock extends Node {
});
this.key = info.key
? new Expression(compiler, this, this.scope, info.key)
? new Expression(component, this, this.scope, info.key)
: null;
if (this.index) {
@ -50,10 +50,10 @@ export default class EachBlock extends Node {
this.scope.add(this.index, dependencies);
}
this.children = mapChildren(compiler, this, this.scope, info.children);
this.children = mapChildren(component, this, this.scope, info.children);
this.else = info.else
? new ElseBlock(compiler, this, this.scope, info.else)
? new ElseBlock(component, this, this.scope, info.else)
: null;
}
@ -66,22 +66,22 @@ export default class EachBlock extends Node {
this.var = block.getUniqueName(`each`);
this.iterations = block.getUniqueName(`${this.var}_blocks`);
this.get_each_context = this.compiler.getUniqueName(`get_${this.var}_context`);
this.get_each_context = this.component.getUniqueName(`get_${this.var}_context`);
const { dependencies } = this.expression;
block.addDependencies(dependencies);
this.block = block.child({
comment: createDebuggingComment(this, this.compiler),
name: this.compiler.getUniqueName('create_each_block'),
comment: createDebuggingComment(this, this.component),
name: this.component.getUniqueName('create_each_block'),
key: this.key,
bindings: new Map(block.bindings)
});
this.each_block_value = this.compiler.getUniqueName('each_value');
this.each_block_value = this.component.getUniqueName('each_value');
const indexName = this.index || this.compiler.getUniqueName(`${this.context}_index`);
const indexName = this.index || this.component.getUniqueName(`${this.context}_index`);
this.contexts.forEach(prop => {
this.block.bindings.set(prop.key.name, `ctx.${this.each_block_value}[ctx.${indexName}]${prop.tail}`);
@ -99,18 +99,18 @@ export default class EachBlock extends Node {
`child_ctx.${indexName} = i;`
);
this.compiler.target.blocks.push(this.block);
this.component.target.blocks.push(this.block);
this.initChildren(this.block, stripWhitespace, nextSibling);
block.addDependencies(this.block.dependencies);
this.block.hasUpdateMethod = this.block.dependencies.size > 0;
if (this.else) {
this.else.block = block.child({
comment: createDebuggingComment(this.else, this.compiler),
name: this.compiler.getUniqueName(`${this.block.name}_else`),
comment: createDebuggingComment(this.else, this.component),
name: this.component.getUniqueName(`${this.block.name}_else`),
});
this.compiler.target.blocks.push(this.else.block);
this.component.target.blocks.push(this.else.block);
this.else.initChildren(
this.else.block,
stripWhitespace,
@ -131,7 +131,7 @@ export default class EachBlock extends Node {
) {
if (this.children.length === 0) return;
const { compiler } = this;
const { component } = this;
const each = this.var;
@ -146,8 +146,8 @@ export default class EachBlock extends Node {
// hack the sourcemap, so that if data is missing the bug
// is easy to find
let c = this.start + 2;
while (compiler.source[c] !== 'e') c += 1;
compiler.code.overwrite(c, c + 4, 'length');
while (component.source[c] !== 'e') c += 1;
component.code.overwrite(c, c + 4, 'length');
const length = `[✂${c}-${c+4}✂]`;
const mountOrIntro = (this.block.hasIntroMethod || this.block.hasOutroMethod) ? 'i' : 'm';
@ -164,7 +164,7 @@ export default class EachBlock extends Node {
block.builders.init.addLine(`var ${this.each_block_value} = ${snippet};`);
this.compiler.target.blocks.push(deindent`
this.component.target.blocks.push(deindent`
function ${this.get_each_context}(ctx, list, i) {
const child_ctx = Object.create(ctx);
${this.contextProps}
@ -188,7 +188,7 @@ export default class EachBlock extends Node {
}
if (this.else) {
const each_block_else = compiler.getUniqueName(`${each}_else`);
const each_block_else = component.getUniqueName(`${each}_else`);
const mountOrIntro = (this.else.block.hasIntroMethod || this.else.block.hasOutroMethod) ? 'i' : 'm';
block.builders.init.addLine(`var ${each_block_else} = null;`);
@ -331,7 +331,7 @@ export default class EachBlock extends Node {
${this.block.hasAnimation && `for (let #i = 0; #i < ${blocks}.length; #i += 1) ${blocks}[#i].a();`}
`);
if (this.block.hasOutros && this.compiler.options.nestedTransitions) {
if (this.block.hasOutros && this.component.options.nestedTransitions) {
const countdown = block.getUniqueName('countdown');
block.builders.outro.addBlock(deindent`
const ${countdown} = @callAfter(#outrocallback, ${blocks}.length);
@ -477,7 +477,7 @@ export default class EachBlock extends Node {
`);
}
if (outroBlock && this.compiler.options.nestedTransitions) {
if (outroBlock && this.component.options.nestedTransitions) {
const countdown = block.getUniqueName('countdown');
block.builders.outro.addBlock(deindent`
${iterations} = ${iterations}.filter(Boolean);
@ -495,7 +495,7 @@ export default class EachBlock extends Node {
}
ssr() {
const { compiler } = this;
const { component } = this;
const { snippet } = this.expression;
const props = this.contexts.map(prop => `${prop.key.name}: item${prop.tail}`);
@ -505,23 +505,23 @@ export default class EachBlock extends Node {
: `item => Object.assign({}, ctx, { ${props.join(', ')} })`;
const open = `\${ ${this.else ? `${snippet}.length ? ` : ''}@each(${snippet}, ${getContext}, ctx => \``;
compiler.target.append(open);
component.target.append(open);
this.children.forEach((child: Node) => {
child.ssr();
});
const close = `\`)`;
compiler.target.append(close);
component.target.append(close);
if (this.else) {
compiler.target.append(` : \``);
component.target.append(` : \``);
this.else.children.forEach((child: Node) => {
child.ssr();
});
compiler.target.append(`\``);
component.target.append(`\``);
}
compiler.target.append('}');
component.target.append('}');
}
}

@ -6,7 +6,7 @@ import validCalleeObjects from '../../utils/validCalleeObjects';
import reservedNames from '../../utils/reservedNames';
import fixAttributeCasing from '../../utils/fixAttributeCasing';
import { quoteNameIfNecessary, quotePropIfNecessary } from '../../utils/quoteIfNecessary';
import Compiler from '../Compiler';
import Component from '../Component';
import Node from './shared/Node';
import Block from '../dom/Block';
import Attribute from './Attribute';
@ -80,15 +80,15 @@ export default class Element extends Node {
ref: string;
namespace: string;
constructor(compiler, parent, scope, info: any) {
super(compiler, parent, scope, info);
constructor(component, parent, scope, info: any) {
super(component, parent, scope, info);
this.name = info.name;
this.scope = scope;
const parentElement = parent.findNearest(/^Element/);
this.namespace = this.name === 'svg' ?
namespaces.svg :
parentElement ? parentElement.namespace : this.compiler.namespace;
parentElement ? parentElement.namespace : this.component.namespace;
this.attributes = [];
this.actions = [];
@ -134,7 +134,7 @@ export default class Element extends Node {
info.attributes.forEach(node => {
switch (node.type) {
case 'Action':
this.actions.push(new Action(compiler, this, scope, node));
this.actions.push(new Action(component, this, scope, node));
break;
case 'Attribute':
@ -142,36 +142,36 @@ export default class Element extends Node {
// special case
if (node.name === 'xmlns') this.namespace = node.value[0].data;
this.attributes.push(new Attribute(compiler, this, scope, node));
this.attributes.push(new Attribute(component, this, scope, node));
break;
case 'Binding':
this.bindings.push(new Binding(compiler, this, scope, node));
this.bindings.push(new Binding(component, this, scope, node));
break;
case 'Class':
this.classes.push(new Class(compiler, this, scope, node));
this.classes.push(new Class(component, this, scope, node));
break;
case 'EventHandler':
this.handlers.push(new EventHandler(compiler, this, scope, node));
this.handlers.push(new EventHandler(component, this, scope, node));
break;
case 'Transition':
const transition = new Transition(compiler, this, scope, node);
const transition = new Transition(component, this, scope, node);
if (node.intro) this.intro = transition;
if (node.outro) this.outro = transition;
break;
case 'Animation':
this.animation = new Animation(compiler, this, scope, node);
this.animation = new Animation(component, this, scope, node);
break;
case 'Ref':
// TODO catch this in validation
if (this.ref) throw new Error(`Duplicate refs`);
compiler.usesRefs = true
component.usesRefs = true
this.ref = node.name;
break;
@ -180,9 +180,9 @@ export default class Element extends Node {
}
});
this.children = mapChildren(compiler, this, scope, info.children);
this.children = mapChildren(component, this, scope, info.children);
compiler.stylesheet.apply(this);
component.stylesheet.apply(this);
}
init(
@ -190,7 +190,7 @@ export default class Element extends Node {
stripWhitespace: boolean,
nextSibling: Node
) {
if (this.name === 'slot' || this.name === 'option' || this.compiler.options.dev) {
if (this.name === 'slot' || this.name === 'option' || this.component.options.dev) {
this.cannotUseInnerHTML();
}
@ -217,7 +217,7 @@ export default class Element extends Node {
if (select && select.selectBindingDependencies) {
select.selectBindingDependencies.forEach(prop => {
attr.dependencies.forEach((dependency: string) => {
this.compiler.indirectDependencies.get(prop).add(dependency);
this.component.indirectDependencies.get(prop).add(dependency);
});
});
}
@ -276,7 +276,7 @@ export default class Element extends Node {
const dependencies = binding.value.dependencies;
this.selectBindingDependencies = dependencies;
dependencies.forEach((prop: string) => {
this.compiler.indirectDependencies.set(prop, new Set());
this.component.indirectDependencies.set(prop, new Set());
});
} else {
this.selectBindingDependencies = null;
@ -303,11 +303,11 @@ export default class Element extends Node {
parentNode: string,
parentNodes: string
) {
const { compiler } = this;
const { component } = this;
if (this.name === 'slot') {
const slotName = this.getStaticAttributeValue('name') || 'default';
this.compiler.slots.add(slotName);
this.component.slots.add(slotName);
}
if (this.name === 'noscript') return;
@ -327,10 +327,10 @@ export default class Element extends Node {
`${node} = ${renderStatement};`
);
if (this.compiler.options.hydratable) {
if (this.component.options.hydratable) {
if (parentNodes) {
block.builders.claim.addBlock(deindent`
${node} = ${getClaimStatement(compiler, this.namespace, parentNodes, this)};
${node} = ${getClaimStatement(component, this.namespace, parentNodes, this)};
var ${nodes} = @children(${this.name === 'template' ? `${node}.content` : node});
`);
} else {
@ -453,10 +453,10 @@ export default class Element extends Node {
return `${open}>${node.children.map(toHTML).join('')}</${node.name}>`;
}
if (this.compiler.options.dev) {
const loc = this.compiler.locate(this.start);
if (this.component.options.dev) {
const loc = this.component.locate(this.start);
block.builders.hydrate.addLine(
`@addLoc(${this.var}, ${this.compiler.fileVar}, ${loc.line}, ${loc.column}, ${this.start});`
`@addLoc(${this.var}, ${this.component.fileVar}, ${loc.line}, ${loc.column}, ${this.start});`
);
}
}
@ -466,7 +466,7 @@ export default class Element extends Node {
) {
if (this.bindings.length === 0) return;
if (this.name === 'select' || this.isMediaNode()) this.compiler.target.hasComplexBindings = true;
if (this.name === 'select' || this.isMediaNode()) this.component.target.hasComplexBindings = true;
const needsLock = this.name !== 'input' || !/radio|checkbox|range|color/.test(this.getStaticAttributeValue('type'));
@ -575,7 +575,7 @@ export default class Element extends Node {
.join(' && ');
if (this.name === 'select' || group.bindings.find(binding => binding.name === 'indeterminate' || binding.isReadOnlyMediaAttribute)) {
this.compiler.target.hasComplexBindings = true;
this.component.target.hasComplexBindings = true;
block.builders.hydrate.addLine(
`if (!(${allInitialStateIsDefined})) #component.root._beforecreate.push(${handler});`
@ -583,7 +583,7 @@ export default class Element extends Node {
}
if (group.events[0] === 'resize') {
this.compiler.target.hasComplexBindings = true;
this.component.target.hasComplexBindings = true;
block.builders.hydrate.addLine(
`#component.root._beforecreate.push(${handler});`
@ -659,24 +659,24 @@ export default class Element extends Node {
}
addEventHandlers(block: Block) {
const { compiler } = this;
const { component } = this;
this.handlers.forEach(handler => {
const isCustomEvent = compiler.events.has(handler.name);
const isCustomEvent = component.events.has(handler.name);
if (handler.callee) {
handler.render(this.compiler, block, handler.shouldHoist);
handler.render(this.component, block, handler.shouldHoist);
}
const target = handler.shouldHoist ? 'this' : this.var;
// get a name for the event handler that is globally unique
// if hoisted, locally unique otherwise
const handlerName = (handler.shouldHoist ? compiler : block).getUniqueName(
const handlerName = (handler.shouldHoist ? component : block).getUniqueName(
`${handler.name.replace(/[^a-zA-Z0-9_$]/g, '_')}_handler`
);
const component = block.alias('component'); // can't use #component, might be hoisted
const component_name = block.alias('component'); // can't use #component, might be hoisted
// create the handler body
const handlerBody = deindent`
@ -688,14 +688,14 @@ export default class Element extends Node {
${handler.snippet ?
handler.snippet :
`${component}.fire("${handler.name}", event);`}
`${component_name}.fire("${handler.name}", event);`}
`;
if (isCustomEvent) {
block.addVariable(handlerName);
block.builders.hydrate.addBlock(deindent`
${handlerName} = %events-${handler.name}.call(${component}, ${this.var}, function(event) {
${handlerName} = %events-${handler.name}.call(${component_name}, ${this.var}, function(event) {
${handlerBody}
});
`);
@ -711,7 +711,7 @@ export default class Element extends Node {
`;
if (handler.shouldHoist) {
compiler.target.blocks.push(handlerFunction);
component.target.blocks.push(handlerFunction);
} else {
block.builders.init.addBlock(handlerFunction);
}
@ -946,14 +946,14 @@ export default class Element extends Node {
return `@append(${name}._slotted.default, ${this.var});`;
}
addCssClass(className = this.compiler.stylesheet.id) {
addCssClass(className = this.component.stylesheet.id) {
const classAttribute = this.attributes.find(a => a.name === 'class');
if (classAttribute && !classAttribute.isTrue) {
if (classAttribute.chunks.length === 1 && classAttribute.chunks[0].type === 'Text') {
(<Text>classAttribute.chunks[0]).data += ` ${className}`;
} else {
(<Node[]>classAttribute.chunks).push(
new Text(this.compiler, this, this.scope, {
new Text(this.component, this, this.scope, {
type: 'Text',
data: ` ${className}`
})
@ -961,7 +961,7 @@ export default class Element extends Node {
}
} else {
this.attributes.push(
new Attribute(this.compiler, this, this.scope, {
new Attribute(this.component, this, this.scope, {
type: 'Attribute',
name: 'class',
value: [{ type: 'Text', data: className }]
@ -971,7 +971,7 @@ export default class Element extends Node {
}
ssr() {
const { compiler } = this;
const { component } = this;
let openingTag = `<${this.name}`;
let textareaContents; // awkward special case
@ -980,7 +980,7 @@ export default class Element extends Node {
if (slot && this.hasAncestor('InlineComponent')) {
const slot = this.attributes.find((attribute: Node) => attribute.name === 'slot');
const slotName = slot.chunks[0].data;
const appendTarget = compiler.target.appendTargets[compiler.target.appendTargets.length - 1];
const appendTarget = component.target.appendTargets[component.target.appendTargets.length - 1];
appendTarget.slotStack.push(slotName);
appendTarget.slots[slotName] = '';
}
@ -1048,10 +1048,10 @@ export default class Element extends Node {
openingTag += '>';
compiler.target.append(openingTag);
component.target.append(openingTag);
if (this.name === 'textarea' && textareaContents !== undefined) {
compiler.target.append(textareaContents);
component.target.append(textareaContents);
} else {
this.children.forEach((child: Node) => {
child.ssr();
@ -1059,7 +1059,7 @@ export default class Element extends Node {
}
if (!isVoidElementName(this.name)) {
compiler.target.append(`</${this.name}>`);
component.target.append(`</${this.name}>`);
}
}
}
@ -1080,7 +1080,7 @@ function getRenderStatement(
}
function getClaimStatement(
compiler: Compiler,
component: Component,
namespace: string,
nodes: string,
node: Node

@ -7,8 +7,8 @@ export default class ElseBlock extends Node {
children: Node[];
block: Block;
constructor(compiler, parent, scope, info) {
super(compiler, parent, scope, info);
this.children = mapChildren(compiler, this, scope, info.children);
constructor(component, parent, scope, info) {
super(component, parent, scope, info);
this.children = mapChildren(component, this, scope, info.children);
}
}

@ -19,8 +19,8 @@ export default class EventHandler extends Node {
args: Expression[];
snippet: string;
constructor(compiler, parent, scope, info) {
super(compiler, parent, scope, info);
constructor(component, parent, scope, info) {
super(component, parent, scope, info);
this.name = info.name;
this.dependencies = new Set();
@ -33,7 +33,7 @@ export default class EventHandler extends Node {
this.usesContext = false;
this.args = info.expression.arguments.map(param => {
const expression = new Expression(compiler, this, scope, param);
const expression = new Expression(component, this, scope, param);
addToSet(this.dependencies, expression.dependencies);
if (expression.usesContext) this.usesContext = true;
return expression;
@ -51,28 +51,28 @@ export default class EventHandler extends Node {
this.snippet = null; // TODO handle shorthand events here?
}
this.isCustomEvent = compiler.events.has(this.name);
this.isCustomEvent = component.events.has(this.name);
this.shouldHoist = !this.isCustomEvent && parent.hasAncestor('EachBlock');
}
render(compiler, block, hoisted) { // TODO hoist more event handlers
render(component, block, hoisted) { // TODO hoist more event handlers
if (this.insertionPoint === null) return; // TODO handle shorthand events here?
if (!validCalleeObjects.has(this.callee.name)) {
const component = hoisted ? `component` : block.alias(`component`);
const component_name = hoisted ? `component` : block.alias(`component`);
// allow event.stopPropagation(), this.select() etc
// TODO verify that it's a valid callee (i.e. built-in or declared method)
if (this.callee.name[0] === '$' && !compiler.methods.has(this.callee.name)) {
compiler.code.overwrite(
if (this.callee.name[0] === '$' && !component.methods.has(this.callee.name)) {
component.code.overwrite(
this.insertionPoint,
this.insertionPoint + 1,
`${component}.store.`
`${component_name}.store.`
);
} else {
compiler.code.prependRight(
component.code.prependRight(
this.insertionPoint,
`${component}.`
`${component_name}.`
);
}
}
@ -84,7 +84,7 @@ export default class EventHandler extends Node {
if (this.callee && this.callee.name === 'this') {
const node = this.callee.nodes[0];
compiler.code.overwrite(node.start, node.end, this.parent.var, {
component.code.overwrite(node.start, node.end, this.parent.var, {
storeName: true,
contentOnly: true
});

@ -1,5 +1,5 @@
import Node from './shared/Node';
import Compiler from '../Compiler';
import Component from '../Component';
import mapChildren from './shared/mapChildren';
import Block from '../dom/Block';
import TemplateScope from './shared/TemplateScope';
@ -9,17 +9,17 @@ export default class Fragment extends Node {
children: Node[];
scope: TemplateScope;
constructor(compiler: Compiler, info: any) {
constructor(component: Component, info: any) {
const scope = new TemplateScope();
super(compiler, null, scope, info);
super(component, null, scope, info);
this.scope = scope;
this.children = mapChildren(compiler, this, scope, info.children);
this.children = mapChildren(component, this, scope, info.children);
}
init() {
this.block = new Block({
compiler: this.compiler,
component: this.component,
name: '@create_main_fragment',
key: null,
@ -28,7 +28,7 @@ export default class Fragment extends Node {
dependencies: new Set(),
});
this.compiler.target.blocks.push(this.block);
this.component.target.blocks.push(this.block);
this.initChildren(this.block, true, null);
this.block.hasUpdateMethod = true;

@ -9,9 +9,9 @@ export default class Head extends Node {
type: 'Head';
children: any[]; // TODO
constructor(compiler, parent, scope, info) {
super(compiler, parent, scope, info);
this.children = mapChildren(compiler, parent, scope, info.children.filter(child => {
constructor(component, parent, scope, info) {
super(component, parent, scope, info);
this.children = mapChildren(component, parent, scope, info.children.filter(child => {
return (child.type !== 'Text' || /\S/.test(child.data));
}));
}
@ -37,12 +37,12 @@ export default class Head extends Node {
}
ssr() {
this.compiler.target.append('${(__result.head += `');
this.component.target.append('${(__result.head += `');
this.children.forEach((child: Node) => {
child.ssr();
});
this.compiler.target.append('`, "")}');
this.component.target.append('`, "")}');
}
}

@ -1,7 +1,7 @@
import deindent from '../../utils/deindent';
import Node from './shared/Node';
import ElseBlock from './ElseBlock';
import Compiler from '../Compiler';
import Component from '../Component';
import Block from '../dom/Block';
import createDebuggingComment from '../../utils/createDebuggingComment';
import Expression from './shared/Expression';
@ -25,14 +25,14 @@ export default class IfBlock extends Node {
block: Block;
constructor(compiler, parent, scope, info) {
super(compiler, parent, scope, info);
constructor(component, parent, scope, info) {
super(component, parent, scope, info);
this.expression = new Expression(compiler, this, scope, info.expression);
this.children = mapChildren(compiler, this, scope, info.children);
this.expression = new Expression(component, this, scope, info.expression);
this.children = mapChildren(component, this, scope, info.children);
this.else = info.else
? new ElseBlock(compiler, this, scope, info.else)
? new ElseBlock(component, this, scope, info.else)
: null;
}
@ -41,7 +41,7 @@ export default class IfBlock extends Node {
stripWhitespace: boolean,
nextSibling: Node
) {
const { compiler } = this;
const { component } = this;
this.cannotUseInnerHTML();
@ -56,8 +56,8 @@ export default class IfBlock extends Node {
block.addDependencies(node.expression.dependencies);
node.block = block.child({
comment: createDebuggingComment(node, compiler),
name: compiler.getUniqueName(`create_if_block`),
comment: createDebuggingComment(node, component),
name: component.getUniqueName(`create_if_block`),
});
blocks.push(node.block);
@ -75,8 +75,8 @@ export default class IfBlock extends Node {
attachBlocks(node.else.children[0]);
} else if (node.else) {
node.else.block = block.child({
comment: createDebuggingComment(node.else, compiler),
name: compiler.getUniqueName(`create_if_block`),
comment: createDebuggingComment(node.else, component),
name: component.getUniqueName(`create_if_block`),
});
blocks.push(node.else.block);
@ -98,7 +98,7 @@ export default class IfBlock extends Node {
attachBlocks(this);
if (compiler.options.nestedTransitions) {
if (component.options.nestedTransitions) {
if (hasIntros) block.addIntro();
if (hasOutros) block.addOutro();
}
@ -109,7 +109,7 @@ export default class IfBlock extends Node {
block.hasOutroMethod = hasOutros;
});
compiler.target.blocks.push(...blocks);
component.target.blocks.push(...blocks);
}
build(
@ -138,7 +138,7 @@ export default class IfBlock extends Node {
if (hasOutros) {
this.buildCompoundWithOutros(block, parentNode, parentNodes, branches, dynamic, vars);
if (this.compiler.options.nestedTransitions) {
if (this.component.options.nestedTransitions) {
block.builders.outro.addBlock(deindent`
if (${name}) ${name}.o(#outrocallback);
else #outrocallback();
@ -150,7 +150,7 @@ export default class IfBlock extends Node {
} else {
this.buildSimple(block, parentNode, parentNodes, branches[0], dynamic, vars);
if (hasOutros && this.compiler.options.nestedTransitions) {
if (hasOutros && this.component.options.nestedTransitions) {
block.builders.outro.addBlock(deindent`
if (${name}) ${name}.o(#outrocallback);
else #outrocallback();
@ -184,7 +184,7 @@ export default class IfBlock extends Node {
dynamic,
{ name, anchor, hasElse, if_name }
) {
const select_block_type = this.compiler.getUniqueName(`select_block_type`);
const select_block_type = this.component.getUniqueName(`select_block_type`);
const current_block_type = block.getUniqueName(`current_block_type`);
const current_block_type_and = hasElse ? '' : `${current_block_type} && `;
@ -247,7 +247,7 @@ export default class IfBlock extends Node {
dynamic,
{ name, anchor, hasElse }
) {
const select_block_type = this.compiler.getUniqueName(`select_block_type`);
const select_block_type = this.component.getUniqueName(`select_block_type`);
const current_block_type_index = block.getUniqueName(`current_block_type_index`);
const previous_block_index = block.getUniqueName(`previous_block_index`);
const if_block_creators = block.getUniqueName(`if_block_creators`);
@ -482,16 +482,16 @@ export default class IfBlock extends Node {
}
ssr() {
const { compiler } = this;
const { component } = this;
const { snippet } = this.expression;
compiler.target.append('${ ' + snippet + ' ? `');
component.target.append('${ ' + snippet + ' ? `');
this.children.forEach((child: Node) => {
child.ssr();
});
compiler.target.append('` : `');
component.target.append('` : `');
if (this.else) {
this.else.children.forEach((child: Node) => {
@ -499,7 +499,7 @@ export default class IfBlock extends Node {
});
}
compiler.target.append('` }');
component.target.append('` }');
}
visitChildren(block: Block, node: Node) {

@ -25,15 +25,15 @@ export default class InlineComponent extends Node {
children: Node[];
ref: string;
constructor(compiler, parent, scope, info) {
super(compiler, parent, scope, info);
constructor(component, parent, scope, info) {
super(component, parent, scope, info);
compiler.hasComponents = true;
component.hasComponents = true;
this.name = info.name;
this.expression = this.name === 'svelte:component'
? new Expression(compiler, this, scope, info.expression)
? new Expression(component, this, scope, info.expression)
: null;
this.attributes = [];
@ -44,22 +44,22 @@ export default class InlineComponent extends Node {
switch (node.type) {
case 'Attribute':
case 'Spread':
this.attributes.push(new Attribute(compiler, this, scope, node));
this.attributes.push(new Attribute(component, this, scope, node));
break;
case 'Binding':
this.bindings.push(new Binding(compiler, this, scope, node));
this.bindings.push(new Binding(component, this, scope, node));
break;
case 'EventHandler':
this.handlers.push(new EventHandler(compiler, this, scope, node));
this.handlers.push(new EventHandler(component, this, scope, node));
break;
case 'Ref':
// TODO catch this in validation
if (this.ref) throw new Error(`Duplicate refs`);
compiler.usesRefs = true
component.usesRefs = true
this.ref = node.name;
break;
@ -68,7 +68,7 @@ export default class InlineComponent extends Node {
}
});
this.children = mapChildren(compiler, this, scope, info.children);
this.children = mapChildren(component, this, scope, info.children);
}
init(
@ -96,7 +96,7 @@ export default class InlineComponent extends Node {
this.var = block.getUniqueName(
(
this.name === 'svelte:self' ? this.compiler.name :
this.name === 'svelte:self' ? this.component.name :
this.name === 'svelte:component' ? 'switch_instance' :
this.name
).toLowerCase()
@ -110,7 +110,7 @@ export default class InlineComponent extends Node {
});
}
if (this.compiler.options.nestedTransitions) {
if (this.component.options.nestedTransitions) {
block.addOutro();
}
}
@ -120,7 +120,7 @@ export default class InlineComponent extends Node {
parentNode: string,
parentNodes: string
) {
const { compiler } = this;
const { component } = this;
const name = this.var;
@ -228,7 +228,7 @@ export default class InlineComponent extends Node {
}
if (this.bindings.length) {
compiler.target.hasComplexBindings = true;
component.target.hasComplexBindings = true;
name_updating = block.alias(`${name}_updating`);
block.addVariable(name_updating, '{}');
@ -337,7 +337,7 @@ export default class InlineComponent extends Node {
this.handlers.forEach(handler => {
handler.var = block.getUniqueName(`${this.var}_${handler.name}`); // TODO this is hacky
handler.render(compiler, block, false); // TODO hoist when possible
handler.render(component, block, false); // TODO hoist when possible
if (handler.usesContext) block.maintainContext = true; // TODO is there a better place to put this?
});
@ -403,7 +403,7 @@ export default class InlineComponent extends Node {
block.builders.update.addBlock(deindent`
if (${switch_value} !== (${switch_value} = ${snippet})) {
if (${name}) {
${this.compiler.options.nestedTransitions
${this.component.options.nestedTransitions
? deindent`
@groupOutros();
const old_component = ${name};
@ -455,7 +455,7 @@ export default class InlineComponent extends Node {
block.builders.destroy.addLine(`if (${name}) ${name}.destroy(${parentNode ? '' : 'detach'});`);
} else {
const expression = this.name === 'svelte:self'
? compiler.name
? component.name
: `%components-${this.name}`;
block.builders.init.addBlock(deindent`
@ -503,7 +503,7 @@ export default class InlineComponent extends Node {
`);
}
if (this.compiler.options.nestedTransitions) {
if (this.component.options.nestedTransitions) {
block.builders.outro.addLine(
`if (${name}) ${name}._fragment.o(#outrocallback);`
);
@ -570,7 +570,7 @@ export default class InlineComponent extends Node {
const expression = (
this.name === 'svelte:self'
? this.compiler.name
? this.component.name
: this.name === 'svelte:component'
? `((${this.expression.snippet}) || @missingComponent)`
: `%components-${this.name}`
@ -594,7 +594,7 @@ export default class InlineComponent extends Node {
const { name } = getObject(binding.value.node);
this.compiler.target.bindings.push(deindent`
this.component.target.bindings.push(deindent`
if (${conditions.reverse().join('&&')}) {
tmp = ${expression}.data();
if ('${name}' in tmp) {
@ -616,7 +616,7 @@ export default class InlineComponent extends Node {
slotStack: ['default']
};
this.compiler.target.appendTargets.push(appendTarget);
this.component.target.appendTargets.push(appendTarget);
this.children.forEach((child: Node) => {
child.ssr();
@ -628,15 +628,15 @@ export default class InlineComponent extends Node {
options.push(`slotted: { ${slotted} }`);
this.compiler.target.appendTargets.pop();
this.component.target.appendTargets.pop();
}
if (options.length) {
open += `, { ${options.join(', ')} }`;
}
this.compiler.target.append(open);
this.compiler.target.append(')}');
this.component.target.append(open);
this.component.target.append(')}');
}
}

@ -26,7 +26,7 @@ export default class MustacheTag extends Tag {
}
ssr() {
this.compiler.target.append(
this.component.target.append(
this.parent &&
this.parent.type === 'Element' &&
this.parent.name === 'style'

@ -6,8 +6,8 @@ export default class PendingBlock extends Node {
block: Block;
children: Node[];
constructor(compiler, parent, scope, info) {
super(compiler, parent, scope, info);
this.children = mapChildren(compiler, parent, scope, info.children);
constructor(component, parent, scope, info) {
super(component, parent, scope, info);
this.children = mapChildren(component, parent, scope, info.children);
}
}

@ -95,6 +95,6 @@ export default class RawMustacheTag extends Tag {
}
ssr() {
this.compiler.target.append('${' + this.expression.snippet + '}');
this.component.target.append('${' + this.expression.snippet + '}');
}
}

@ -36,10 +36,10 @@ export default class Slot extends Element {
parentNode: string,
parentNodes: string
) {
const { compiler } = this;
const { component } = this;
const slotName = this.getStaticAttributeValue('name') || 'default';
compiler.slots.add(slotName);
component.slots.add(slotName);
const content_name = block.getUniqueName(`slot_content_${sanitize(slotName)}`);
const prop = quotePropIfNecessary(slotName);
@ -160,12 +160,12 @@ export default class Slot extends Element {
const slotName = name && name.chunks[0].data || 'default';
const prop = quotePropIfNecessary(slotName);
this.compiler.target.append(`\${options && options.slotted && options.slotted${prop} ? options.slotted${prop}() : \``);
this.component.target.append(`\${options && options.slotted && options.slotted${prop} ? options.slotted${prop}() : \``);
this.children.forEach((child: Node) => {
child.ssr();
});
this.compiler.target.append(`\`}`);
this.component.target.append(`\`}`);
}
}

@ -31,8 +31,8 @@ export default class Text extends Node {
data: string;
shouldSkip: boolean;
constructor(compiler, parent, scope, info) {
super(compiler, parent, scope, info);
constructor(component, parent, scope, info) {
super(component, parent, scope, info);
this.data = info.data;
}
@ -74,6 +74,6 @@ export default class Text extends Node {
// unless this Text node is inside a <script> or <style> element, escape &,<,>
text = escapeHTML(text);
}
this.compiler.target.append(escape(escapeTemplate(text)));
this.component.target.append(escape(escapeTemplate(text)));
}
}

@ -6,8 +6,8 @@ export default class ThenBlock extends Node {
block: Block;
children: Node[];
constructor(compiler, parent, scope, info) {
super(compiler, parent, scope, info);
this.children = mapChildren(compiler, parent, scope, info.children);
constructor(component, parent, scope, info) {
super(component, parent, scope, info);
this.children = mapChildren(component, parent, scope, info.children);
}
}

@ -8,9 +8,9 @@ export default class Title extends Node {
children: any[]; // TODO
shouldCache: boolean;
constructor(compiler, parent, scope, info) {
super(compiler, parent, scope, info);
this.children = mapChildren(compiler, parent, scope, info.children);
constructor(component, parent, scope, info) {
super(component, parent, scope, info);
this.children = mapChildren(component, parent, scope, info.children);
this.shouldCache = info.children.length === 1
? (
@ -103,12 +103,12 @@ export default class Title extends Node {
}
ssr() {
this.compiler.target.append(`<title>`);
this.component.target.append(`<title>`);
this.children.forEach((child: Node) => {
child.ssr();
});
this.compiler.target.append(`</title>`);
this.component.target.append(`</title>`);
}
}

@ -6,13 +6,13 @@ export default class Transition extends Node {
name: string;
expression: Expression;
constructor(compiler, parent, scope, info) {
super(compiler, parent, scope, info);
constructor(component, parent, scope, info) {
super(component, parent, scope, info);
this.name = info.name;
this.expression = info.expression
? new Expression(compiler, this, scope, info.expression)
? new Expression(component, this, scope, info.expression)
: null;
}
}

@ -38,17 +38,17 @@ export default class Window extends Node {
handlers: EventHandler[];
bindings: Binding[];
constructor(compiler, parent, scope, info) {
super(compiler, parent, scope, info);
constructor(component, parent, scope, info) {
super(component, parent, scope, info);
this.handlers = [];
this.bindings = [];
info.attributes.forEach(node => {
if (node.type === 'EventHandler') {
this.handlers.push(new EventHandler(compiler, this, scope, node));
this.handlers.push(new EventHandler(component, this, scope, node));
} else if (node.type === 'Binding') {
this.bindings.push(new Binding(compiler, this, scope, node));
this.bindings.push(new Binding(component, this, scope, node));
}
});
}
@ -58,20 +58,20 @@ export default class Window extends Node {
parentNode: string,
parentNodes: string
) {
const { compiler } = this;
const { component } = this;
const events = {};
const bindings: Record<string, string> = {};
this.handlers.forEach(handler => {
// TODO verify that it's a valid callee (i.e. built-in or declared method)
compiler.addSourcemapLocations(handler.expression);
component.addSourcemapLocations(handler.expression);
const isCustomEvent = compiler.events.has(handler.name);
const isCustomEvent = component.events.has(handler.name);
let usesState = handler.dependencies.size > 0;
handler.render(compiler, block, false); // TODO hoist?
handler.render(component, block, false); // TODO hoist?
const handlerName = block.getUniqueName(`onwindow${handler.name}`);
const handlerBody = deindent`
@ -109,7 +109,7 @@ export default class Window extends Node {
this.bindings.forEach(binding => {
// in dev mode, throw if read-only values are written to
if (readonly.has(binding.name)) {
compiler.target.readonly.add(binding.value.node.name);
component.target.readonly.add(binding.value.node.name);
}
bindings[binding.name] = binding.value.node.name;
@ -126,7 +126,7 @@ export default class Window extends Node {
);
// add initial value
compiler.target.metaBindings.push(
component.target.metaBindings.push(
`this._state.${binding.value.node.name} = window.${property};`
);
});
@ -151,13 +151,13 @@ export default class Window extends Node {
if (${lock}) return;
${lock} = true;
`}
${compiler.options.dev && `component._updatingReadonlyProperty = true;`}
${component.options.dev && `component._updatingReadonlyProperty = true;`}
#component.set({
${props}
});
${compiler.options.dev && `component._updatingReadonlyProperty = false;`}
${component.options.dev && `component._updatingReadonlyProperty = false;`}
${event === 'scroll' && `${lock} = false;`}
`;
@ -200,16 +200,16 @@ export default class Window extends Node {
const handlerName = block.getUniqueName(`onlinestatuschanged`);
block.builders.init.addBlock(deindent`
function ${handlerName}(event) {
${compiler.options.dev && `component._updatingReadonlyProperty = true;`}
${component.options.dev && `component._updatingReadonlyProperty = true;`}
#component.set({ ${bindings.online}: navigator.onLine });
${compiler.options.dev && `component._updatingReadonlyProperty = false;`}
${component.options.dev && `component._updatingReadonlyProperty = false;`}
}
window.addEventListener("online", ${handlerName});
window.addEventListener("offline", ${handlerName});
`);
// add initial value
compiler.target.metaBindings.push(
component.target.metaBindings.push(
`this._state.${bindings.online} = navigator.onLine;`
);

@ -1,4 +1,4 @@
import Compiler from '../../Compiler';
import Component from '../../Component';
import { walk } from 'estree-walker';
import isReference from 'is-reference';
import flattenReference from '../../../utils/flattenReference';
@ -54,7 +54,7 @@ const precedence: Record<string, (node?: Node) => number> = {
};
export default class Expression {
compiler: Compiler;
component: Component;
node: any;
snippet: string;
@ -64,11 +64,11 @@ export default class Expression {
thisReferences: Array<{ start: number, end: number }>;
constructor(compiler, parent, scope, info) {
constructor(component, parent, scope, info) {
// TODO revert to direct property access in prod?
Object.defineProperties(this, {
compiler: {
value: compiler
component: {
value: component
}
});
@ -81,7 +81,7 @@ export default class Expression {
const dependencies = new Set();
const { code, helpers } = compiler;
const { code, helpers } = component;
let { map, scope: currentScope } = createScopes(info);
@ -111,11 +111,11 @@ export default class Expression {
if (currentScope.has(name) || (name === 'event' && isEventHandler)) return;
if (compiler.helpers.has(name)) {
if (component.helpers.has(name)) {
let object = node;
while (object.type === 'MemberExpression') object = object.object;
const alias = compiler.templateVars.get(`helpers-${name}`);
const alias = component.templateVars.get(`helpers-${name}`);
if (alias !== name) code.overwrite(object.start, object.end, alias);
return;
}
@ -135,7 +135,7 @@ export default class Expression {
});
} else {
dependencies.add(name);
compiler.expectedProperties.add(name);
component.expectedProperties.add(name);
}
if (node.type === 'MemberExpression') {
@ -163,7 +163,7 @@ export default class Expression {
overwriteThis(name) {
this.thisReferences.forEach(ref => {
this.compiler.code.overwrite(ref.start, ref.end, name, {
this.component.code.overwrite(ref.start, ref.end, name, {
storeName: true
});
});

@ -1,11 +1,11 @@
import Compiler from './../../Compiler';
import Component from './../../Component';
import Block from '../../dom/Block';
import { trimStart, trimEnd } from '../../../utils/trim';
export default class Node {
readonly start: number;
readonly end: number;
readonly compiler: Compiler;
readonly component: Component;
readonly parent: Node;
readonly type: string;
@ -15,7 +15,7 @@ export default class Node {
canUseInnerHTML: boolean;
var: string;
constructor(compiler: Compiler, parent, scope, info: any) {
constructor(component: Component, parent, scope, info: any) {
this.start = info.start;
this.end = info.end;
this.type = info.type;
@ -23,8 +23,8 @@ export default class Node {
// this makes properties non-enumerable, which makes logging
// bearable. might have a performance cost. TODO remove in prod?
Object.defineProperties(this, {
compiler: {
value: compiler
component: {
value: component
},
parent: {
value: parent
@ -86,7 +86,7 @@ export default class Node {
lastChild = null;
cleaned.forEach((child: Node, i: number) => {
child.canUseInnerHTML = !this.compiler.options.hydratable;
child.canUseInnerHTML = !this.component.options.hydratable;
child.init(block, stripWhitespace, cleaned[i + 1] || nextSibling);

@ -6,9 +6,9 @@ export default class Tag extends Node {
expression: Expression;
shouldCache: boolean;
constructor(compiler, parent, scope, info) {
super(compiler, parent, scope, info);
this.expression = new Expression(compiler, this, scope, info.expression);
constructor(component, parent, scope, info) {
super(component, parent, scope, info);
this.expression = new Expression(component, this, scope, info.expression);
this.shouldCache = (
info.expression.type !== 'Identifier' ||

@ -34,11 +34,11 @@ function getConstructor(type): typeof Node {
}
}
export default function mapChildren(compiler, parent, scope, children: any[]) {
export default function mapChildren(component, parent, scope, children: any[]) {
let last = null;
return children.map(child => {
const constructor = getConstructor(child.type);
const node = new constructor(compiler, parent, scope, child);
const node = new constructor(component, parent, scope, child);
if (last) last.next = node;
node.prev = last;

@ -1,5 +1,5 @@
import deindent from '../../utils/deindent';
import Compiler from '../Compiler';
import Component from '../Component';
import Stats from '../../Stats';
import Stylesheet from '../../css/Stylesheet';
import { removeNode, removeObjectKey } from '../../utils/removeNode';
@ -41,21 +41,21 @@ export default function ssr(
const format = options.format || 'cjs';
const target = new SsrTarget();
const compiler = new Compiler(ast, source, options.name || 'SvelteComponent', stylesheet, options, stats, false, target);
const component = new Component(ast, source, options.name || 'SvelteComponent', stylesheet, options, stats, target);
const { computations, name, templateProperties } = compiler;
const { computations, name, templateProperties } = component;
// create main render() function
trim(compiler.fragment.children).forEach((node: Node) => {
trim(component.fragment.children).forEach((node: Node) => {
node.ssr();
});
const css = compiler.customElement ?
const css = component.customElement ?
{ code: null, map: null } :
compiler.stylesheet.render(options.filename, true);
component.stylesheet.render(options.filename, true);
// generate initial state object
const expectedProperties = Array.from(compiler.expectedProperties);
const expectedProperties = Array.from(component.expectedProperties);
const globals = expectedProperties.filter(prop => globalWhitelist.has(prop));
const storeProps = expectedProperties.filter(prop => prop[0] === '$');
@ -81,7 +81,7 @@ export default function ssr(
// TODO concatenate CSS maps
const result = deindent`
${compiler.javascript}
${component.javascript}
var ${name} = {};
@ -148,7 +148,7 @@ export default function ssr(
${templateProperties.preload && `${name}.preload = %preload;`}
`;
return compiler.generate(result, options, { name, format });
return component.generate(result, options, { name, format });
}
function trim(nodes) {

@ -1,8 +1,11 @@
import Compiler from '../compile/Compiler';
import Component from '../compile/Component';
import { Node } from '../interfaces';
export default function createDebuggingComment(node: Node, compiler: Compiler) {
const { locate, source } = compiler;
export default function createDebuggingComment(
node: Node,
component: Component
) {
const { locate, source } = component;
let c = node.start;
if (node.type === 'ElseBlock') {

Loading…
Cancel
Save