import Node from './shared/Node'; import Attribute from './Attribute'; import map_children from './shared/map_children'; import Binding from './Binding'; import EventHandler from './EventHandler'; import Expression from './shared/Expression'; import Component from '../Component'; import Let from './Let'; import TemplateScope from './shared/TemplateScope'; import { INode } from './interfaces'; export default class InlineComponent extends Node { type: 'InlineComponent'; name: string; expression: Expression; attributes: Attribute[] = []; bindings: Binding[] = []; handlers: EventHandler[] = []; lets: Let[] = []; children: INode[]; scope: TemplateScope; constructor(component: Component, parent, scope, info) { super(component, parent, scope, info); if (info.name !== 'svelte:component' && info.name !== 'svelte:self') { const name = info.name.split('.')[0]; // accommodate namespaces component.warn_if_undefined(name, info, scope); component.add_reference(name); } this.name = info.name; this.expression = this.name === 'svelte:component' ? new Expression(component, this, scope, info.expression) : null; info.attributes.forEach(node => { switch (node.type) { case 'Action': component.error(node, { code: `invalid-action`, message: `Actions can only be applied to DOM elements, not components` }); case 'Attribute': if (node.name === 'slot') { component.error(node, { code: `invalid-prop`, message: `'slot' is reserved for future use in named slots` }); } // fallthrough case 'Spread': this.attributes.push(new Attribute(component, this, scope, node)); break; case 'Binding': this.bindings.push(new Binding(component, this, scope, node)); break; case 'Class': component.error(node, { code: `invalid-class`, message: `Classes can only be applied to DOM elements, not components` }); case 'EventHandler': this.handlers.push(new EventHandler(component, this, scope, node)); break; case 'Let': this.lets.push(new Let(component, this, scope, node)); break; case 'Transition': component.error(node, { code: `invalid-transition`, message: `Transitions can only be applied to DOM elements, not components` }); default: throw new Error(`Not implemented: ${node.type}`); } }); if (this.lets.length > 0) { this.scope = scope.child(); this.lets.forEach(l => { const dependencies = new Set([l.name]); l.names.forEach(name => { this.scope.add(name, dependencies, this); }); }); } else { this.scope = scope; } this.children = map_children(component, this, this.scope, info.children); } }