import Binding from '../../../nodes/Binding'; import ElementWrapper from '.'; import { dimensions } from '../../../../utils/patterns'; import getObject from '../../../../utils/getObject'; import Block from '../../Block'; import Node from '../../../nodes/shared/Node'; import Renderer from '../../Renderer'; import flattenReference from '../../../../utils/flattenReference'; import getTailSnippet from '../../../../utils/getTailSnippet'; // TODO this should live in a specific binding const readOnlyMediaAttributes = new Set([ 'duration', 'buffered', 'seekable', 'played' ]); export default class BindingWrapper { node: Binding; parent: ElementWrapper; object: string; handler: any; // TODO updateDom: string; initialUpdate: string; needsLock: boolean; updateCondition: string; constructor(block: Block, node: Binding, parent: ElementWrapper) { this.node = node; this.parent = parent; const { dependencies } = this.node.value; block.addDependencies(dependencies); // TODO does this also apply to e.g. ``? if (parent.node.name === 'select') { parent.selectBindingDependencies = dependencies; dependencies.forEach((prop: string) => { parent.renderer.component.indirectDependencies.set(prop, new Set()); }); } } isReadOnlyMediaAttribute() { return readOnlyMediaAttributes.has(this.node.name); } munge(block: Block) { const { parent } = this; const { renderer } = parent; const needsLock = ( parent.node.name !== 'input' || !/radio|checkbox|range|color/.test(parent.node.getStaticAttributeValue('type')) ); const isReadOnly = ( (parent.node.isMediaNode() && readOnlyMediaAttributes.has(this.node.name)) || dimensions.test(this.node.name) ); let updateConditions: string[] = []; const { name } = getObject(this.node.value.node); const { snippet } = this.node.value; // special case: if you have e.g. `` // and `selected` is an object chosen with a if (name === 'group') { const bindingGroup = getBindingGroup(renderer, binding.node.value.node); if (type === 'checkbox') { return `@getBindingGroupValue(#component._bindingGroups[${bindingGroup}])`; } return `${element.var}.__value`; } // if (type === 'range' || type === 'number') { return `@toNumber(${element.var}.${name})`; } if ((name === 'buffered' || name === 'seekable' || name === 'played')) { return `@timeRangesToArray(${element.var}.${name})` } // everything else return `${element.var}.${name}`; } function isComputed(node: Node) { while (node.type === 'MemberExpression') { if (node.computed) return true; node = node.object; } return false; }