diff --git a/modules/change_detection/src/parser/ast.js b/modules/change_detection/src/parser/ast.js index be9ec58c42..78c7660019 100644 --- a/modules/change_detection/src/parser/ast.js +++ b/modules/change_detection/src/parser/ast.js @@ -6,6 +6,10 @@ export class AST { throw new BaseException("Not supported"); } + get isAssignable() { + return false; + } + assign(context, value) { throw new BaseException("Not supported"); } @@ -75,6 +79,10 @@ export class FieldRead extends AST { return this.getter(this.receiver.eval(context)); } + get isAssignable() { + return true; + } + assign(context, value) { return this.setter(this.receiver.eval(context), value); } @@ -101,6 +109,11 @@ export class KeyedAccess extends AST { throw new BaseException(`Cannot access ${key} on ${obj}`); } } + + get isAssignable() { + return true; + } + assign(context, value) { var obj = this.obj.eval(context); var key = this.key.eval(context); diff --git a/modules/change_detection/src/parser/parser.js b/modules/change_detection/src/parser/parser.js index 7c5a8235be..9d30a34899 100644 --- a/modules/change_detection/src/parser/parser.js +++ b/modules/change_detection/src/parser/parser.js @@ -150,9 +150,16 @@ class _ParseAST { } parseExpression() { + var start = this.inputIndex; var result = this.parseConditional(); while (this.next.isOperator('=')) { + if (!result.isAssignable) { + var end = this.inputIndex; + var expression = this.input.substring(start, end); + this.error(`Expression ${expression} is not assignable`); + } + this.expectOperator('='); result = new Assignment(result, this.parseConditional()); } diff --git a/modules/change_detection/test/parser/parser_spec.js b/modules/change_detection/test/parser/parser_spec.js index 2ea396af84..b03c9b87d9 100644 --- a/modules/change_detection/test/parser/parser_spec.js +++ b/modules/change_detection/test/parser/parser_spec.js @@ -179,6 +179,10 @@ export function main() { expect(MapWrapper.get(context.a[0], "key")).toEqual(200); }); + it('should throw on bad assignment', () => { + expectEvalError("5=4").toThrowError(new RegExp("Expression 5 is not assignable")); + }); + it('should evaluate array', () => { expectEval("[1][0]").toEqual(1); expectEval("[[1]][0][0]").toEqual(1); @@ -188,7 +192,7 @@ export function main() { }); it("should error when unfinished exception", () => { - expectEvalError('a[0 = 200').toThrowError(new RegExp("Missing expected ]")); + expectEvalError('a[0').toThrowError(new RegExp("Missing expected ]")); }); it('should evaluate map', () => { @@ -201,8 +205,6 @@ export function main() { }); describe("parseBinding", () => { - //throw on assignment - it("should parse formatters", function () { var exp = parseBinding("'Foo'|uppercase"); expect(exp).toBeAnInstanceOf(Formatter);