You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte/src/compile/nodes/Binding.ts

68 lines
2.1 KiB

import Node from './shared/Node';
import get_object from '../utils/get_object';
import Expression from './shared/Expression';
import Component from '../Component';
import TemplateScope from './shared/TemplateScope';
export default class Binding extends Node {
name: string;
expression: Expression;
is_contextual: boolean;
obj: string;
prop: string;
constructor(component: Component, parent, scope: TemplateScope, info) {
super(component, parent, scope, info);
if (info.expression.type !== 'Identifier' && info.expression.type !== 'MemberExpression') {
component.error(info, {
code: 'invalid-directive-value',
message: 'Can only bind to an identifier (e.g. `foo`) or a member expression (e.g. `foo.bar` or `foo[baz]`)'
});
}
this.name = info.name;
this.expression = new Expression(component, this, scope, info.expression);
let obj;
let prop;
const { name } = get_object(this.expression.node);
this.is_contextual = scope.names.has(name);
// make sure we track this as a mutable ref
if (scope.is_let(name)) {
component.error(this, {
code: 'invalid-binding',
message: 'Cannot bind to a variable declared with the let: directive'
});
} else if (this.is_contextual) {
scope.dependencies_for_name.get(name).forEach(name => {
const variable = component.var_lookup.get(name);
variable[this.expression.node.type === 'MemberExpression' ? 'mutated' : 'reassigned'] = true;
});
} else {
const variable = component.var_lookup.get(name);
if (!variable || variable.global) component.error(this.expression.node, {
code: 'binding-undeclared',
message: `${name} is not declared`
});
variable[this.expression.node.type === 'MemberExpression' ? 'mutated' : 'reassigned'] = true;
}
if (this.expression.node.type === 'MemberExpression') {
prop = `[✂${this.expression.node.property.start}-${this.expression.node.property.end}✂]`;
if (!this.expression.node.computed) prop = `'${prop}'`;
obj = `[✂${this.expression.node.object.start}-${this.expression.node.object.end}✂]`;
} else {
obj = 'ctx';
prop = `'${name}'`;
}
this.obj = obj;
this.prop = prop;
}
}