Reviewers: Michael Starzinger, rossberg,
Message:
This CL depends on the for-in crasher fix, FWIW.
Description:
For-of statements do not permit initializers.
[email protected], [email protected]
BUG=v8:2720
Please review this at https://codereview.chromium.org/16739008/
SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge
Affected files:
M src/parser.h
M src/parser.cc
M src/preparser.h
M src/preparser.cc
M test/mjsunit/harmony/iteration-syntax.js
Index: src/parser.cc
diff --git a/src/parser.cc b/src/parser.cc
index
fa24bf703bc6f62a039580db9731c0a6ae131c85..996d67745685131ab78e8d0b77d23028aa7e9e8e
100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -2624,11 +2624,13 @@ WhileStatement*
Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) {
}
-bool Parser::CheckInOrOf(ForEachStatement::VisitMode* visit_mode) {
+bool Parser::CheckInOrOf(bool accept_OF,
+ ForEachStatement::VisitMode* visit_mode) {
if (Check(Token::IN)) {
*visit_mode = ForEachStatement::ENUMERATE;
return true;
- } else if (allow_for_of() && CheckContextualKeyword(CStrVector("of"))) {
+ } else if (allow_for_of() && accept_OF &&
+ CheckContextualKeyword(CStrVector("of"))) {
*visit_mode = ForEachStatement::ITERATE;
return true;
}
@@ -2726,11 +2728,14 @@ Statement*
Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
if (peek() == Token::VAR || peek() == Token::CONST) {
bool is_const = peek() == Token::CONST;
Handle<String> name;
+ VariableDeclarationProperties decl_props = kHasNoInitializers;
Block* variable_statement =
- ParseVariableDeclarations(kForStatement, NULL, NULL, &name,
CHECK_OK);
+ ParseVariableDeclarations(kForStatement, &decl_props, NULL,
&name,
+ CHECK_OK);
+ bool accept_OF = decl_props == kHasNoInitializers;
ForEachStatement::VisitMode mode;
- if (!name.is_null() && CheckInOrOf(&mode)) {
+ if (!name.is_null() && CheckInOrOf(accept_OF, &mode)) {
Interface* interface =
is_const ? Interface::NewConst() : Interface::NewValue();
ForEachStatement* loop = factory()->NewForEachStatement(mode,
labels);
@@ -2762,9 +2767,10 @@ Statement* Parser::ParseForStatement(ZoneStringList*
labels, bool* ok) {
ParseVariableDeclarations(kForStatement, &decl_props, NULL, &name,
CHECK_OK);
bool accept_IN = !name.is_null() && decl_props != kHasInitializers;
+ bool accept_OF = decl_props == kHasNoInitializers;
ForEachStatement::VisitMode mode;
- if (accept_IN && CheckInOrOf(&mode)) {
+ if (accept_IN && CheckInOrOf(accept_OF, &mode)) {
// Rewrite a for-in statement of the form
//
// for (let x in e) b
@@ -2820,8 +2826,9 @@ Statement* Parser::ParseForStatement(ZoneStringList*
labels, bool* ok) {
} else {
Expression* expression = ParseExpression(false, CHECK_OK);
ForEachStatement::VisitMode mode;
+ bool accept_OF = expression->AsVariableProxy();
- if (CheckInOrOf(&mode)) {
+ if (CheckInOrOf(accept_OF, &mode)) {
// Signal a reference error if the expression is an invalid
// left-hand side expression. We could report this as a syntax
// error here but for compatibility with JSC we choose to report
Index: src/parser.h
diff --git a/src/parser.h b/src/parser.h
index
b7e0700009f6ff56cbe92ce48b9fb5788d5cd2e9..38633b0b42973e60632bae8b47455bc657162ff5
100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -729,7 +729,7 @@ class Parser BASE_EMBEDDED {
bool is_generator() const { return
current_function_state_->is_generator(); }
- bool CheckInOrOf(ForEachStatement::VisitMode* visit_mode);
+ bool CheckInOrOf(bool accept_OF, ForEachStatement::VisitMode*
visit_mode);
bool peek_any_identifier();
Index: src/preparser.cc
diff --git a/src/preparser.cc b/src/preparser.cc
index
828177aee0a696ddf51c75b2ca7867aacc163522..3268e3c508bc2fb6887564b5d03e5675c2f46d2a
100644
--- a/src/preparser.cc
+++ b/src/preparser.cc
@@ -659,10 +659,9 @@ PreParser::Statement
PreParser::ParseWhileStatement(bool* ok) {
}
-bool PreParser::CheckInOrOf() {
+bool PreParser::CheckInOrOf(bool accept_OF) {
if (peek() == i::Token::IN ||
- (allow_for_of() &&
- peek() == i::Token::IDENTIFIER &&
+ (allow_for_of() && accept_OF && peek() == i::Token::IDENTIFIER &&
scanner_->is_next_contextual_keyword(v8::internal::CStrVector("of")))) {
Next();
return true;
@@ -685,9 +684,10 @@ PreParser::Statement
PreParser::ParseForStatement(bool* ok) {
VariableDeclarationProperties decl_props = kHasNoInitializers;
ParseVariableDeclarations(
kForStatement, &decl_props, &decl_count, CHECK_OK);
- bool accept_IN = decl_count == 1 &&
- !(is_let && decl_props == kHasInitializers);
- if (accept_IN && CheckInOrOf()) {
+ bool has_initializers = decl_props == kHasInitializers;
+ bool accept_IN = decl_count == 1 && !(is_let && has_initializers);
+ bool accept_OF = !has_initializers;
+ if (accept_IN && CheckInOrOf(accept_OF)) {
ParseExpression(true, CHECK_OK);
Expect(i::Token::RPAREN, CHECK_OK);
@@ -695,8 +695,8 @@ PreParser::Statement PreParser::ParseForStatement(bool*
ok) {
return Statement::Default();
}
} else {
- ParseExpression(false, CHECK_OK);
- if (CheckInOrOf()) {
+ Expression lhs = ParseExpression(false, CHECK_OK);
+ if (CheckInOrOf(lhs.IsIdentifier())) {
ParseExpression(true, CHECK_OK);
Expect(i::Token::RPAREN, CHECK_OK);
Index: src/preparser.h
diff --git a/src/preparser.h b/src/preparser.h
index
786316ed5071465e44eb46ffee7d2210ca783a0b..41907d12eb18e24027590faebc4ecae412cabebd
100644
--- a/src/preparser.h
+++ b/src/preparser.h
@@ -658,7 +658,7 @@ class PreParser {
}
void ExpectSemicolon(bool* ok);
- bool CheckInOrOf();
+ bool CheckInOrOf(bool accept_OF);
static int Precedence(i::Token::Value tok, bool accept_IN);
Index: test/mjsunit/harmony/iteration-syntax.js
diff --git a/test/mjsunit/harmony/iteration-syntax.js
b/test/mjsunit/harmony/iteration-syntax.js
index
21149c04bc99108beb802fcfd65a253a558aae42..3bda78ed4e16d312d7f3351a9c60158659f99e1a
100644
--- a/test/mjsunit/harmony/iteration-syntax.js
+++ b/test/mjsunit/harmony/iteration-syntax.js
@@ -54,6 +54,11 @@ assertThrows("function f() { for (var of of) { } }",
SyntaxError);
assertThrows("function f() { for (let of y) { } }", SyntaxError);
assertThrows("function f() { for (let of of) { } }", SyntaxError);
+assertThrows("function f() { for (x = 3 of y) { } }", SyntaxError);
+assertThrows("function f() { for (var x = 3 of y) { } }", SyntaxError);
+assertThrows("function f() { for (let x = 3 of y) { } }", SyntaxError);
+
+
// Alack, this appears to be valid.
function f() { for (of of y) { } }
function f() { for (let of of y) { } }
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.