deep bindings

pull/1367/head
Rich Harris 6 years ago
parent de9b3a56be
commit 6b3d7c2cf5

@ -215,108 +215,6 @@ export default class Generator {
return this.aliases.get(name);
}
// contextualise(
// contexts: Map<string, string>,
// indexes: Map<string, string>,
// expression: Node,
// context: string,
// isEventHandler: boolean
// ): {
// contexts: Set<string>,
// indexes: Set<string>
// } {
// // this.addSourcemapLocations(expression);
// const usedContexts: Set<string> = new Set();
// const usedIndexes: Set<string> = new Set();
// const { code, helpers } = this;
// let scope: Scope;
// let lexicalDepth = 0;
// const self = this;
// walk(expression, {
// enter(node: Node, parent: Node, key: string) {
// if (/^Function/.test(node.type)) lexicalDepth += 1;
// if (node._scope) {
// scope = node._scope;
// return;
// }
// if (node.type === 'ThisExpression') {
// if (lexicalDepth === 0 && context)
// code.overwrite(node.start, node.end, context, {
// storeName: true,
// contentOnly: false,
// });
// } else if (isReference(node, parent)) {
// const { name } = flattenReference(node);
// if (scope && scope.has(name)) return;
// if (name === 'event' && isEventHandler) {
// // noop
// } else if (contexts.has(name)) {
// const contextName = contexts.get(name);
// if (contextName !== name) {
// // this is true for 'reserved' names like `state` and `component`,
// // also destructured contexts
// code.overwrite(
// node.start,
// node.start + name.length,
// contextName,
// { storeName: true, contentOnly: false }
// );
// const destructuredName = contextName.replace(/\[\d+\]/, '');
// if (destructuredName !== contextName) {
// // so that hoisting the context works correctly
// usedContexts.add(destructuredName);
// }
// }
// usedContexts.add(name);
// } else if (helpers.has(name)) {
// let object = node;
// while (object.type === 'MemberExpression') object = object.object;
// const alias = self.templateVars.get(`helpers-${name}`);
// if (alias !== name) code.overwrite(object.start, object.end, alias);
// } else if (indexes.has(name)) {
// const context = indexes.get(name);
// usedContexts.add(context); // TODO is this right?
// usedIndexes.add(name);
// } else {
// // handle shorthand properties
// if (parent && parent.type === 'Property' && parent.shorthand) {
// if (key === 'key') {
// code.appendLeft(node.start, `${name}: `);
// return;
// }
// }
// code.prependRight(node.start, `state.`);
// usedContexts.add('state');
// }
// this.skip();
// }
// },
// leave(node: Node) {
// if (/^Function/.test(node.type)) lexicalDepth -= 1;
// if (node._scope) scope = scope.parent;
// },
// });
// return {
// contexts: usedContexts,
// indexes: usedIndexes
// };
// }
generate(result: string, options: CompileOptions, { banner = '', sharedPath, helpers, name, format }: GenerateOptions ) {
const pattern = /\[✂(\d+)-(\d+)$/;
@ -706,212 +604,4 @@ export default class Generator {
}
}
}
// walkTemplate() {
// const generator = this;
// const {
// code,
// expectedProperties,
// helpers
// } = this;
// const contextualise = (
// node: Node, contextDependencies: Map<string, string[]>,
// indexes: Set<string>,
// isEventHandler: boolean
// ) => {
// this.addSourcemapLocations(node); // TODO this involves an additional walk — can we roll it in somewhere else?
// let { scope } = annotateWithScopes(node);
// const dependencies: Set<string> = new Set();
// walk(node, {
// enter(node: Node, parent: Node) {
// code.addSourcemapLocation(node.start);
// code.addSourcemapLocation(node.end);
// if (node._scope) {
// scope = node._scope;
// return;
// }
// if (isReference(node, parent)) {
// const { name } = flattenReference(node);
// if (scope && scope.has(name) || helpers.has(name) || (name === 'event' && isEventHandler)) return;
// if (contextDependencies.has(name)) {
// contextDependencies.get(name).forEach(dependency => {
// dependencies.add(dependency);
// });
// } else if (!indexes.has(name)) {
// dependencies.add(name);
// }
// this.skip();
// }
// },
// leave(node: Node, parent: Node) {
// if (node._scope) scope = scope.parent;
// }
// });
// dependencies.forEach(dependency => {
// expectedProperties.add(dependency);
// });
// return {
// snippet: `[✂${node.start}-${node.end}✂]`,
// dependencies: Array.from(dependencies)
// };
// }
// const contextStack = [];
// const indexStack = [];
// const dependenciesStack = [];
// let contextDependencies = new Map();
// const contextDependenciesStack: Map<string, string[]>[] = [contextDependencies];
// let indexes = new Set();
// const indexesStack: Set<string>[] = [indexes];
// function parentIsHead(node) {
// if (!node) return false;
// if (node.type === 'Component' || node.type === 'Element') return false;
// if (node.type === 'Head') return true;
// return parentIsHead(node.parent);
// }
// walk(this.fragment, {
// enter(node: Node, parent: Node, key: string) {
// // TODO this is hacky as hell
// if (key === 'parent') return this.skip();
// node.parent = parent;
// node.generator = generator;
// if (node.type === 'Element' && (node.name === 'svelte:component' || node.name === 'svelte:self' || generator.components.has(node.name))) {
// node.type = 'Component';
// Object.setPrototypeOf(node, nodes.Component.prototype);
// } else if (node.type === 'Element' && node.name === 'title' && parentIsHead(parent)) { // TODO do this in parse?
// node.type = 'Title';
// Object.setPrototypeOf(node, nodes.Title.prototype);
// } else if (node.type === 'Element' && node.name === 'slot' && !generator.customElement) {
// node.type = 'Slot';
// Object.setPrototypeOf(node, nodes.Slot.prototype);
// } else if (node.type in nodes) {
// Object.setPrototypeOf(node, nodes[node.type].prototype);
// }
// if (node.type === 'Element') {
// generator.stylesheet.apply(node);
// }
// if (node.type === 'EachBlock') {
// node.metadata = contextualise(node.expression, contextDependencies, indexes, false);
// contextDependencies = new Map(contextDependencies);
// contextDependencies.set(node.context, node.metadata.dependencies);
// if (node.destructuredContexts) {
// node.destructuredContexts.forEach((name: string) => {
// contextDependencies.set(name, node.metadata.dependencies);
// });
// }
// contextDependenciesStack.push(contextDependencies);
// if (node.index) {
// indexes = new Set(indexes);
// indexes.add(node.index);
// indexesStack.push(indexes);
// }
// }
// if (node.type === 'AwaitBlock') {
// node.metadata = contextualise(node.expression, contextDependencies, indexes, false);
// contextDependencies = new Map(contextDependencies);
// contextDependencies.set(node.value, node.metadata.dependencies);
// contextDependencies.set(node.error, node.metadata.dependencies);
// contextDependenciesStack.push(contextDependencies);
// }
// if (node.type === 'IfBlock') {
// node.metadata = contextualise(node.expression, contextDependencies, indexes, false);
// }
// if (node.type === 'MustacheTag' || node.type === 'RawMustacheTag' || node.type === 'AttributeShorthand') {
// node.metadata = contextualise(node.expression, contextDependencies, indexes, false);
// this.skip();
// }
// if (node.type === 'Binding') {
// node.metadata = contextualise(node.value, contextDependencies, indexes, false);
// this.skip();
// }
// if (node.type === 'EventHandler' && node.expression) {
// node.expression.arguments.forEach((arg: Node) => {
// arg.metadata = contextualise(arg, contextDependencies, indexes, true);
// });
// this.skip();
// }
// if (node.type === 'Transition' && node.expression) {
// node.metadata = contextualise(node.expression, contextDependencies, indexes, false);
// this.skip();
// }
// if (node.type === 'Action' && node.expression) {
// node.metadata = contextualise(node.expression, contextDependencies, indexes, false);
// if (node.expression.type === 'CallExpression') {
// node.expression.arguments.forEach((arg: Node) => {
// arg.metadata = contextualise(arg, contextDependencies, indexes, true);
// });
// }
// this.skip();
// }
// if (node.type === 'Component' && node.name === 'svelte:component') {
// node.metadata = contextualise(node.expression, contextDependencies, indexes, false);
// }
// if (node.type === 'Spread') {
// node.metadata = contextualise(node.expression, contextDependencies, indexes, false);
// }
// },
// leave(node: Node, parent: Node) {
// if (node.type === 'EachBlock') {
// contextDependenciesStack.pop();
// contextDependencies = contextDependenciesStack[contextDependenciesStack.length - 1];
// if (node.index) {
// indexesStack.pop();
// indexes = indexesStack[indexesStack.length - 1];
// }
// }
// if (node.type === 'Element' && node.name === 'option') {
// // Special case — treat these the same way:
// // <option>{{foo}}</option>
// // <option value='{{foo}}'>{{foo}}</option>
// const valueAttribute = node.attributes.find((attribute: Node) => attribute.name === 'value');
// if (!valueAttribute) {
// node.attributes.push(new nodes.Attribute({
// generator,
// name: 'value',
// value: node.children,
// parent: node
// }));
// }
// }
// }
// });
// }
}

@ -85,7 +85,7 @@ export default class Binding extends Node {
// view to model
const valueFromDom = getValueFromDom(this.compiler, node, this);
const handler = getEventHandler(this.compiler, block, name, snippet, this, dependencies, valueFromDom);
const handler = getEventHandler(this, this.compiler, block, name, snippet, dependencies, valueFromDom);
// model to view
let updateDom = getDomUpdater(node, this, snippet);
@ -182,11 +182,11 @@ function getBindingGroup(compiler: DomGenerator, value: Node) {
}
function getEventHandler(
binding: Binding,
compiler: DomGenerator,
block: Block,
name: string,
snippet: string,
attribute: Node,
dependencies: string[],
value: string,
) {
@ -194,8 +194,8 @@ function getEventHandler(
dependencies = [...dependencies].filter(prop => prop[0] !== '$');
if (block.contexts.has(name)) {
const tail = attribute.value.type === 'MemberExpression'
? getTailSnippet(attribute.value)
const tail = binding.value.node.type === 'MemberExpression'
? getTailSnippet(binding.value.node)
: '';
const list = `context.${block.listNames.get(name)}`;
@ -211,7 +211,7 @@ function getEventHandler(
};
}
if (attribute.value.type === 'MemberExpression') {
if (binding.value.node.type === 'MemberExpression') {
// This is a little confusing, and should probably be tidied up
// at some point. It addresses a tricky bug (#893), wherein
// Svelte tries to `set()` a computed property, which throws an

Loading…
Cancel
Save