diff --git a/modules/change_detection/src/parser/ast.js b/modules/change_detection/src/parser/ast.js index 042630242c..bae81ea26d 100644 --- a/modules/change_detection/src/parser/ast.js +++ b/modules/change_detection/src/parser/ast.js @@ -335,8 +335,18 @@ export class MethodCall extends AST { } eval(context) { - var obj = this.receiver.eval(context); - return this.fn(obj, evalList(context, this.args)); + var evaluatedContext = this.receiver.eval(context); + var evaluatedArgs = evalList(context, this.args); + + while (evaluatedContext instanceof ContextWithVariableBindings) { + if (evaluatedContext.hasBinding(this.name)) { + var fn = evaluatedContext.get(this.name); + return FunctionWrapper.apply(fn, evaluatedArgs); + } + evaluatedContext = evaluatedContext.parent; + } + + return this.fn(evaluatedContext, evaluatedArgs); } visit(visitor, args) { diff --git a/modules/change_detection/test/parser/parser_spec.js b/modules/change_detection/test/parser/parser_spec.js index 0c32e5075b..1cc4c64f61 100644 --- a/modules/change_detection/test/parser/parser_spec.js +++ b/modules/change_detection/test/parser/parser_spec.js @@ -194,7 +194,7 @@ export function main() { }); it("should fall back to a regular field read when ContextWithVariableBindings "+ - "does not have the requested field", () => { + "does not have the requested field", () => { var locals = new ContextWithVariableBindings(td(999), MapWrapper.create()); expectEval("a", locals).toEqual(999); }); @@ -211,6 +211,23 @@ export function main() { it('should throw when no method', () => { expectEvalError("blah()").toThrowError(); }); + + it('should evaluate a method from ContextWithVariableBindings', () => { + var context = new ContextWithVariableBindings( + td(0, 0, 'parent'), + MapWrapper.createFromPairs([['fn', () => 'child']]) + ); + expectEval("fn()", context).toEqual('child'); + }); + + it('should fall back to the parent context when ContextWithVariableBindings does not ' + + 'have the requested method', () => { + var context = new ContextWithVariableBindings( + td(0, 0, 'parent'), + MapWrapper.create() + ); + expectEval("fn()", context).toEqual('parent'); + }); }); describe("functional calls", () => {