import Binding from '../../../nodes/Binding'; import ElementWrapper from '../Element'; import { dimensions } from '../../../../utils/patterns'; import get_object from '../../../utils/get_object'; import Block from '../../Block'; import Node from '../../../nodes/shared/Node'; import Renderer from '../../Renderer'; import flatten_reference from '../../../utils/flatten_reference'; import EachBlock from '../../../nodes/EachBlock'; import { Node as INode } from '../../../../interfaces'; function get_tail(node: INode) { const end = node.end; while (node.type === 'MemberExpression') node = node.object; return { start: node.end, end }; } export default class BindingWrapper { node: Binding; parent: ElementWrapper; object: string; handler: { uses_context: boolean; mutation: string; contextual_dependencies: Set, snippet?: string }; snippet: string; is_readonly: boolean; needs_lock: boolean; constructor(block: Block, node: Binding, parent: ElementWrapper) { this.node = node; this.parent = parent; const { dependencies } = this.node.expression; block.add_dependencies(dependencies); // TODO does this also apply to e.g. ``? if (parent.node.name === 'select') { parent.select_binding_dependencies = dependencies; dependencies.forEach((prop: string) => { parent.renderer.component.indirect_dependencies.set(prop, new Set()); }); } if (node.is_contextual) { // we need to ensure that the each block creates a context including // the list and the index, if they're not otherwise referenced const { name } = get_object(this.node.expression.node); const each_block = this.parent.node.scope.get_owner(name); (each_block as EachBlock).has_binding = true; } this.object = get_object(this.node.expression.node).name; // TODO unfortunate code is necessary because we need to use `ctx` // inside the fragment, but not inside the