Skip to content
Permalink
Browse files

fix($parse): validate assignment lval in parser phase

The parser always threw an error in the case of an invalid left-value
assignment but it was an unhelpful:

```
Cannot set property 'undefined' of undefined
```

This commit provides a more meaningful error message, so it is not a
breaking change.

Closes #15234
  • Loading branch information
jbedard authored and petebacondarwin committed Oct 9, 2016
1 parent fcffa0d commit a16a827fdcc4181cd6d5451b7a4c3c6f846f33ec
Showing with 18 additions and 3 deletions.
  1. +4 −3 src/ng/parse.js
  2. +14 −0 test/ng/parseSpec.js
@@ -436,6 +436,10 @@ AST.prototype = {
assignment: function() {
var result = this.ternary();
if (this.expect('=')) {
if (!isAssignable(result)) {
throw $parseMinErr('lval', 'Trying to assign a value to a non l-value');
}

result = { type: AST.AssignmentExpression, left: result, right: this.assignment(), operator: '='};
}
return result;
@@ -1148,9 +1152,6 @@ ASTCompiler.prototype = {
case AST.AssignmentExpression:
right = this.nextId();
left = {};
if (!isAssignable(ast.left)) {
throw $parseMinErr('lval', 'Trying to assign a value to a non l-value');
}
this.recurse(ast.left, undefined, left, function() {
self.if_(self.notNull(left.context), function() {
self.recurse(ast.right, right);
@@ -2128,6 +2128,20 @@ describe('parser', function() {
expect(scope.b).toEqual(234);
});

it('should throw with invalid left-val in assignments', function() {
expect(function() { scope.$eval('1 = 1'); }).toThrowMinErr('$parse', 'lval');
expect(function() { scope.$eval('{} = 1'); }).toThrowMinErr('$parse', 'lval');
expect(function() { scope.$eval('[] = 1'); }).toThrowMinErr('$parse', 'lval');
expect(function() { scope.$eval('true = 1'); }).toThrowMinErr('$parse', 'lval');
expect(function() { scope.$eval('(a=b) = 1'); }).toThrowMinErr('$parse', 'lval');
expect(function() { scope.$eval('(1<2) = 1'); }).toThrowMinErr('$parse', 'lval');
expect(function() { scope.$eval('(1+2) = 1'); }).toThrowMinErr('$parse', 'lval');
expect(function() { scope.$eval('!v = 1'); }).toThrowMinErr('$parse', 'lval');
expect(function() { scope.$eval('this = 1'); }).toThrowMinErr('$parse', 'lval');
expect(function() { scope.$eval('+v = 1'); }).toThrowMinErr('$parse', 'lval');
expect(function() { scope.$eval('(1?v1:v2) = 1'); }).toThrowMinErr('$parse', 'lval');
});

it('should evaluate assignments in ternary operator', function() {
scope.$eval('a = 1 ? 2 : 3');
expect(scope.a).toBe(2);

0 comments on commit a16a827

Please sign in to comment.
You can’t perform that action at this time.