|
|
@ -1,19 +1,28 @@
|
|
|
|
|
|
|
|
import Node from './Node';
|
|
|
|
|
|
|
|
import EachBlock from '../EachBlock';
|
|
|
|
|
|
|
|
import ThenBlock from '../ThenBlock';
|
|
|
|
|
|
|
|
import CatchBlock from '../CatchBlock';
|
|
|
|
|
|
|
|
import InlineComponent from '../InlineComponent';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
type NodeWithScope = EachBlock | ThenBlock | CatchBlock | InlineComponent | Element;
|
|
|
|
|
|
|
|
|
|
|
|
export default class TemplateScope {
|
|
|
|
export default class TemplateScope {
|
|
|
|
names: Set<string>;
|
|
|
|
names: Set<string>;
|
|
|
|
dependenciesForName: Map<string, Set<string>>;
|
|
|
|
dependenciesForName: Map<string, Set<string>>;
|
|
|
|
mutables: Set<string>;
|
|
|
|
mutables: Set<string> = new Set();
|
|
|
|
|
|
|
|
owners: Map<string, NodeWithScope> = new Map();
|
|
|
|
parent?: TemplateScope;
|
|
|
|
parent?: TemplateScope;
|
|
|
|
|
|
|
|
|
|
|
|
constructor(parent?: TemplateScope) {
|
|
|
|
constructor(parent?: TemplateScope) {
|
|
|
|
this.parent = parent;
|
|
|
|
this.parent = parent;
|
|
|
|
this.names = new Set(parent ? parent.names : []);
|
|
|
|
this.names = new Set(parent ? parent.names : []);
|
|
|
|
this.dependenciesForName = new Map(parent ? parent.dependenciesForName : []);
|
|
|
|
this.dependenciesForName = new Map(parent ? parent.dependenciesForName : []);
|
|
|
|
this.mutables = new Set();
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
add(name, dependencies: Set<string>) {
|
|
|
|
add(name, dependencies: Set<string>, owner) {
|
|
|
|
this.names.add(name);
|
|
|
|
this.names.add(name);
|
|
|
|
this.dependenciesForName.set(name, dependencies);
|
|
|
|
this.dependenciesForName.set(name, dependencies);
|
|
|
|
|
|
|
|
this.owners.set(name, owner);
|
|
|
|
return this;
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -32,6 +41,10 @@ export default class TemplateScope {
|
|
|
|
|
|
|
|
|
|
|
|
containsMutable(names: Iterable<string>) {
|
|
|
|
containsMutable(names: Iterable<string>) {
|
|
|
|
for (const name of names) {
|
|
|
|
for (const name of names) {
|
|
|
|
|
|
|
|
const owner = this.getOwner(name);
|
|
|
|
|
|
|
|
const is_let = owner && (owner.type === 'InlineComponent' || owner.type === 'Element');
|
|
|
|
|
|
|
|
if (is_let) return true;
|
|
|
|
|
|
|
|
|
|
|
|
if (name[0] === '$') return true;
|
|
|
|
if (name[0] === '$') return true;
|
|
|
|
if (this.mutables.has(name)) return true;
|
|
|
|
if (this.mutables.has(name)) return true;
|
|
|
|
else if (this.dependenciesForName.has(name) && this.containsMutable(this.dependenciesForName.get(name))) return true;
|
|
|
|
else if (this.dependenciesForName.has(name) && this.containsMutable(this.dependenciesForName.get(name))) return true;
|
|
|
@ -44,4 +57,8 @@ export default class TemplateScope {
|
|
|
|
isTopLevel(name: string) {
|
|
|
|
isTopLevel(name: string) {
|
|
|
|
return !this.parent || !this.names.has(name) && this.parent.isTopLevel(name);
|
|
|
|
return !this.parent || !this.names.has(name) && this.parent.isTopLevel(name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
getOwner(name: string): NodeWithScope {
|
|
|
|
|
|
|
|
return this.owners.get(name) || (this.parent && this.parent.getOwner(name));
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|