fix(change_detection): handle locals when invoking a method

Closes #660
This commit is contained in:
vsavkin 2015-02-20 15:50:12 -08:00
parent 7f31036427
commit 0dfd287ec3
3 changed files with 34 additions and 3 deletions

View File

@ -203,6 +203,17 @@ if (${TEMP_LOCAL} instanceof ContextWithVariableBindings) {
`; `;
} }
function invokeMethodTemplate(name:string, args:string, context:string, newValue:string) {
return `
${TEMP_LOCAL} = ${UTIL}.findContext("${name}", ${context});
if (${TEMP_LOCAL} instanceof ContextWithVariableBindings) {
${newValue} = ${TEMP_LOCAL}.get('${name}').apply(null, [${args}]);
} else {
${newValue} = ${context}.${name}(${args});
}
`;
}
function localDefinitionsTemplate(names:List):string { function localDefinitionsTemplate(names:List):string {
return names.map((n) => `var ${n};`).join("\n"); return names.map((n) => `var ${n};`).join("\n");
} }
@ -366,7 +377,11 @@ export class ChangeDetectorJITGenerator {
} }
case RECORD_TYPE_INVOKE_METHOD: case RECORD_TYPE_INVOKE_METHOD:
return assignmentTemplate(newValue, `${context}.${r.name}(${args})`); if (r.contextIndex == 0) { // only the first property read can be a local
return invokeMethodTemplate(r.name, args, context, newValue);
} else {
return assignmentTemplate(newValue, `${context}.${r.name}(${args})`);
}
case RECORD_TYPE_INVOKE_CLOSURE: case RECORD_TYPE_INVOKE_CLOSURE:
return assignmentTemplate(newValue, `${context}(${args})`); return assignmentTemplate(newValue, `${context}(${args})`);

View File

@ -132,8 +132,16 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
break; break;
case RECORD_TYPE_INVOKE_METHOD: case RECORD_TYPE_INVOKE_METHOD:
var methodInvoker:Function = proto.funcOrValue; var context = this._readContext(proto);
return methodInvoker(this._readContext(proto), this._readArgs(proto)); var args = this._readArgs(proto);
var c = ChangeDetectionUtil.findContext(proto.name, context);
if (c instanceof ContextWithVariableBindings) {
return FunctionWrapper.apply(c.get(proto.name), args);
} else {
var methodInvoker:Function = proto.funcOrValue;
return methodInvoker(c, args);
}
break;
case RECORD_TYPE_KEYED_ACCESS: case RECORD_TYPE_KEYED_ACCESS:
var arg = this._readArgs(proto)[0]; var arg = this._readArgs(proto)[0];

View File

@ -318,6 +318,14 @@ export function main() {
.toEqual(['key=value']); .toEqual(['key=value']);
}); });
it('should invoke a function from ContextWithVariableBindings', () => {
var locals = new ContextWithVariableBindings(null,
MapWrapper.createFromPairs([["key", () => "value"]]));
expect(executeWatch('key', 'key()', locals))
.toEqual(['key=value']);
});
it('should handle nested ContextWithVariableBindings', () => { it('should handle nested ContextWithVariableBindings', () => {
var nested = new ContextWithVariableBindings(null, var nested = new ContextWithVariableBindings(null,
MapWrapper.createFromPairs([["key", "value"]])); MapWrapper.createFromPairs([["key", "value"]]));