Skip to content

Commit c2388fc

Browse files
jbedardpetebacondarwin
authored andcommitted
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 angular#15234
1 parent 5706b7b commit c2388fc

File tree

2 files changed

+18
-3
lines changed

2 files changed

+18
-3
lines changed

src/ng/parse.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,10 @@ AST.prototype = {
436436
assignment: function() {
437437
var result = this.ternary();
438438
if (this.expect('=')) {
439+
if (!isAssignable(result)) {
440+
throw $parseMinErr('lval', 'Trying to assign a value to a non l-value');
441+
}
442+
439443
result = { type: AST.AssignmentExpression, left: result, right: this.assignment(), operator: '='};
440444
}
441445
return result;
@@ -1148,9 +1152,6 @@ ASTCompiler.prototype = {
11481152
case AST.AssignmentExpression:
11491153
right = this.nextId();
11501154
left = {};
1151-
if (!isAssignable(ast.left)) {
1152-
throw $parseMinErr('lval', 'Trying to assign a value to a non l-value');
1153-
}
11541155
this.recurse(ast.left, undefined, left, function() {
11551156
self.if_(self.notNull(left.context), function() {
11561157
self.recurse(ast.right, right);

test/ng/parseSpec.js

+14
Original file line numberDiff line numberDiff line change
@@ -2128,6 +2128,20 @@ describe('parser', function() {
21282128
expect(scope.b).toEqual(234);
21292129
});
21302130

2131+
it('should throw with invalid left-val in assignments', function() {
2132+
expect(function() { scope.$eval('1 = 1'); }).toThrowMinErr('$parse', 'lval');
2133+
expect(function() { scope.$eval('{} = 1'); }).toThrowMinErr('$parse', 'lval');
2134+
expect(function() { scope.$eval('[] = 1'); }).toThrowMinErr('$parse', 'lval');
2135+
expect(function() { scope.$eval('true = 1'); }).toThrowMinErr('$parse', 'lval');
2136+
expect(function() { scope.$eval('(a=b) = 1'); }).toThrowMinErr('$parse', 'lval');
2137+
expect(function() { scope.$eval('(1<2) = 1'); }).toThrowMinErr('$parse', 'lval');
2138+
expect(function() { scope.$eval('(1+2) = 1'); }).toThrowMinErr('$parse', 'lval');
2139+
expect(function() { scope.$eval('!v = 1'); }).toThrowMinErr('$parse', 'lval');
2140+
expect(function() { scope.$eval('this = 1'); }).toThrowMinErr('$parse', 'lval');
2141+
expect(function() { scope.$eval('+v = 1'); }).toThrowMinErr('$parse', 'lval');
2142+
expect(function() { scope.$eval('(1?v1:v2) = 1'); }).toThrowMinErr('$parse', 'lval');
2143+
});
2144+
21312145
it('should evaluate assignments in ternary operator', function() {
21322146
scope.$eval('a = 1 ? 2 : 3');
21332147
expect(scope.a).toBe(2);

0 commit comments

Comments
 (0)