Commit 9b15445e authored by caitpotter88's avatar caitpotter88 Committed by Commit bot

[parser] make kInvalidLhsInFor a SyntaxError

Second item in section 13.7.5.1 states that the error should be a
SyntaxError, when previously CheckAndRewriteReferenceExpression
would always emit a ReferenceError.

BUG=v8:4373
R=adamk, rossberg
LOG=N
CQ_INCLUDE_TRYBOTS=tryserver.chromium.linux:linux_chromium_rel_ng;tryserver.blink:linux_blink_rel

Review URL: https://codereview.chromium.org/1292393002

Cr-Commit-Position: refs/heads/master@{#30184}
parent 46d34252
......@@ -3693,7 +3693,7 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
if (!*ok) return nullptr;
expression = this->CheckAndRewriteReferenceExpression(
expression, lhs_beg_pos, lhs_end_pos,
MessageTemplate::kInvalidLhsInFor, CHECK_OK);
MessageTemplate::kInvalidLhsInFor, kSyntaxError, CHECK_OK);
ForEachStatement* loop =
factory()->NewForEachStatement(mode, labels, stmt_pos);
......
......@@ -922,7 +922,7 @@ PreParser::Statement PreParser::ParseForStatement(bool* ok) {
if (!*ok) return Statement::Default();
lhs = CheckAndRewriteReferenceExpression(
lhs, lhs_beg_pos, lhs_end_pos, MessageTemplate::kInvalidLhsInFor,
CHECK_OK);
kSyntaxError, CHECK_OK);
ParseExpression(true, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
ParseSubStatement(CHECK_OK);
......
......@@ -714,6 +714,9 @@ class ParserBase : public Traits {
ExpressionT CheckAndRewriteReferenceExpression(
ExpressionT expression, int beg_pos, int end_pos,
MessageTemplate::Template message, bool* ok);
ExpressionT CheckAndRewriteReferenceExpression(
ExpressionT expression, int beg_pos, int end_pos,
MessageTemplate::Template message, ParseErrorType type, bool* ok);
// Used to validate property names in object literals and class literals
enum PropertyKind {
......@@ -3937,6 +3940,16 @@ typename ParserBase<Traits>::ExpressionT
ParserBase<Traits>::CheckAndRewriteReferenceExpression(
ExpressionT expression, int beg_pos, int end_pos,
MessageTemplate::Template message, bool* ok) {
return this->CheckAndRewriteReferenceExpression(expression, beg_pos, end_pos,
message, kReferenceError, ok);
}
template <typename Traits>
typename ParserBase<Traits>::ExpressionT
ParserBase<Traits>::CheckAndRewriteReferenceExpression(
ExpressionT expression, int beg_pos, int end_pos,
MessageTemplate::Template message, ParseErrorType type, bool* ok) {
Scanner::Location location(beg_pos, end_pos);
if (this->IsIdentifier(expression)) {
if (is_strict(language_mode()) &&
......@@ -3963,7 +3976,7 @@ ParserBase<Traits>::CheckAndRewriteReferenceExpression(
ExpressionT error = this->NewThrowReferenceError(message, pos);
return factory()->NewProperty(expression, error, pos);
} else {
this->ReportMessageAt(location, message, kReferenceError);
this->ReportMessageAt(location, message, type);
*ok = false;
return this->EmptyExpression();
}
......
*%(basename)s:9: ReferenceError: Invalid left-hand side in for-loop
*%(basename)s:9: SyntaxError: Invalid left-hand side in for-loop
function f() { for ("unassignable" in {}); }
^^^^^^^^^^^^^^
ReferenceError: Invalid left-hand side in for-loop
SyntaxError: Invalid left-hand side in for-loop
*%(basename)s:7: ReferenceError: Invalid left-hand side in for-loop
*%(basename)s:7: SyntaxError: Invalid left-hand side in for-loop
function f() { for (new.target in {}); }
^^^^^^^^^^
ReferenceError: Invalid left-hand side in for-loop
SyntaxError: Invalid left-hand side in for-loop
......@@ -394,5 +394,5 @@
assertThrows(function() { Function("--new.target"); }, ReferenceError);
assertThrows(function() { Function("(new.target)++"); }, ReferenceError);
assertThrows(function() { Function("++(new.target)"); }, ReferenceError);
assertThrows(function() { Function("for (new.target of {});"); }, ReferenceError);
assertThrows(function() { Function("for (new.target of {});"); }, SyntaxError);
})();
......@@ -50,9 +50,9 @@ assertDoesNotThrow("if (false) ++(eval('12'))", ReferenceError);
assertDoesNotThrow("if (false) (eval('12'))++", ReferenceError);
// For in:
assertThrows("for (12 in [1]) print(12);", ReferenceError);
assertThrows("for (12 in [1]) print(12);", SyntaxError);
assertThrows("for (eval('var x') in [1]) print(12);", ReferenceError);
assertThrows("if (false) for (12 in [1]) print(12);", ReferenceError);
assertThrows("if (false) for (12 in [1]) print(12);", SyntaxError);
assertDoesNotThrow("if (false) for (eval('0') in [1]) print(12);", ReferenceError);
// For:
......@@ -64,7 +64,7 @@ assertDoesNotThrow("if (false) for (eval('var x') = 1;;) print(12);", ReferenceE
// Assignments to 'this'.
assertThrows("this = 42", ReferenceError);
assertThrows("function f() { this = 12; }", ReferenceError);
assertThrows("for (this in {x:3, y:4, z:5}) ;", ReferenceError);
assertThrows("for (this in {x:3, y:4, z:5}) ;", SyntaxError);
assertThrows("for (this = 0;;) ;", ReferenceError);
assertThrows("this++", ReferenceError);
assertThrows("++this", ReferenceError);
......
......@@ -422,36 +422,36 @@ PASS Valid: "for (a() in b) break"
PASS Valid: "function f() { for (a() in b) break }"
PASS Valid: "for (a().l[4] in b) break"
PASS Valid: "function f() { for (a().l[4] in b) break }"
PASS Valid: "for (new a in b in c in d) break"
PASS Valid: "function f() { for (new a in b in c in d) break }"
PASS Valid: "for (new new new a in b) break"
PASS Valid: "function f() { for (new new new a in b) break }"
FAIL Invalid: "for (delete new a() in b) break" should throw undefined
FAIL Invalid: "function f() { for (delete new a() in b) break }" should throw undefined
FAIL Invalid: "for (a * a in b) break" should throw undefined
FAIL Invalid: "function f() { for (a * a in b) break }" should throw undefined
PASS Valid: "for ((a * a) in b) break"
PASS Valid: "function f() { for ((a * a) in b) break }"
FAIL Invalid: "for (a++ in b) break" should throw undefined
FAIL Invalid: "function f() { for (a++ in b) break }" should throw undefined
PASS Valid: "for ((a++) in b) break"
PASS Valid: "function f() { for ((a++) in b) break }"
FAIL Invalid: "for (++a in b) break" should throw undefined
FAIL Invalid: "function f() { for (++a in b) break }" should throw undefined
PASS Valid: "for ((++a) in b) break"
PASS Valid: "function f() { for ((++a) in b) break }"
FAIL Invalid: "for (a, b in c) break" should throw undefined
FAIL Invalid: "function f() { for (a, b in c) break }" should throw undefined
FAIL Invalid: "for (a,b in c ;;) break" should throw undefined
FAIL Invalid: "function f() { for (a,b in c ;;) break }" should throw undefined
PASS Invalid: "for (new a in b in c in d) break"
PASS Invalid: "function f() { for (new a in b in c in d) break }"
PASS Invalid: "for (new new new a in b) break"
PASS Invalid: "function f() { for (new new new a in b) break }"
PASS Invalid: "for (delete new a() in b) break"
PASS Invalid: "function f() { for (delete new a() in b) break }"
PASS Invalid: "for (a * a in b) break"
PASS Invalid: "function f() { for (a * a in b) break }"
PASS Invalid: "for ((a * a) in b) break"
PASS Invalid: "function f() { for ((a * a) in b) break }"
PASS Invalid: "for (a++ in b) break"
PASS Invalid: "function f() { for (a++ in b) break }"
PASS Invalid: "for ((a++) in b) break"
PASS Invalid: "function f() { for ((a++) in b) break }"
PASS Invalid: "for (++a in b) break"
PASS Invalid: "function f() { for (++a in b) break }"
PASS Invalid: "for ((++a) in b) break"
PASS Invalid: "function f() { for ((++a) in b) break }"
PASS Invalid: "for (a, b in c) break"
PASS Invalid: "function f() { for (a, b in c) break }"
PASS Invalid: "for (a,b in c ;;) break"
PASS Invalid: "function f() { for (a,b in c ;;) break }"
PASS Valid: "for (a,(b in c) ;;) break"
PASS Valid: "function f() { for (a,(b in c) ;;) break }"
PASS Valid: "for ((a, b) in c) break"
PASS Valid: "function f() { for ((a, b) in c) break }"
FAIL Invalid: "for (a ? b : c in c) break" should throw undefined
FAIL Invalid: "function f() { for (a ? b : c in c) break }" should throw undefined
PASS Valid: "for ((a ? b : c) in c) break"
PASS Valid: "function f() { for ((a ? b : c) in c) break }"
PASS Invalid: "for ((a, b) in c) break"
PASS Invalid: "function f() { for ((a, b) in c) break }"
PASS Invalid: "for (a ? b : c in c) break"
PASS Invalid: "function f() { for (a ? b : c in c) break }"
PASS Invalid: "for ((a ? b : c) in c) break"
PASS Invalid: "function f() { for ((a ? b : c) in c) break }"
PASS Valid: "for (var a in b in c) break"
PASS Valid: "function f() { for (var a in b in c) break }"
PASS Valid: "for (var a = 5 += 6 in b) break"
......
......@@ -291,21 +291,21 @@ invalid("for ( %a ; ; ) { }");
valid ("for (a in b) break");
valid ("for (a() in b) break");
valid ("for (a().l[4] in b) break");
valid ("for (new a in b in c in d) break");
valid ("for (new new new a in b) break");
invalid("for (new a in b in c in d) break");
invalid("for (new new new a in b) break");
invalid("for (delete new a() in b) break");
invalid("for (a * a in b) break");
valid ("for ((a * a) in b) break");
invalid("for ((a * a) in b) break");
invalid("for (a++ in b) break");
valid ("for ((a++) in b) break");
invalid("for ((a++) in b) break");
invalid("for (++a in b) break");
valid ("for ((++a) in b) break");
invalid("for ((++a) in b) break");
invalid("for (a, b in c) break");
invalid("for (a,b in c ;;) break");
valid ("for (a,(b in c) ;;) break");
valid ("for ((a, b) in c) break");
invalid("for ((a, b) in c) break");
invalid("for (a ? b : c in c) break");
valid ("for ((a ? b : c) in c) break");
invalid("for ((a ? b : c) in c) break");
valid ("for (var a in b in c) break");
valid ("for (var a = 5 += 6 in b) break");
invalid("for (var a += 5 in b) break");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment