Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(73)

Unified Diff: src/parser.cc

Issue 1062263002: [parser] report better errors for multiple ForBindings in ForIn/Of loops (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: add tests for zero declarations Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/parser.h ('k') | src/preparser.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/parser.cc
diff --git a/src/parser.cc b/src/parser.cc
index 608a6bdaf0435aebb24edeac1bd9a21160a120f7..4412b8a98cdca5618ec0b7caf1a77caf246718b3 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -2217,8 +2217,8 @@ Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context,
// VariableDeclarations ';'
const AstRawString* ignore;
- Block* result =
- ParseVariableDeclarations(var_context, names, &ignore, nullptr, CHECK_OK);
+ Block* result = ParseVariableDeclarations(
+ var_context, nullptr, names, &ignore, nullptr, nullptr, CHECK_OK);
ExpectSemicolon(CHECK_OK);
return result;
}
@@ -2230,9 +2230,10 @@ Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context,
// to initialize it properly. This mechanism is used for the parsing
// of 'for-in' loops.
Block* Parser::ParseVariableDeclarations(
- VariableDeclarationContext var_context,
+ VariableDeclarationContext var_context, int* num_decl,
ZoneList<const AstRawString*>* names, const AstRawString** out,
- Scanner::Location* first_initializer_loc, bool* ok) {
+ Scanner::Location* first_initializer_loc, Scanner::Location* bindings_loc,
+ bool* ok) {
// VariableDeclarations ::
// ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[',']
//
@@ -2304,7 +2305,9 @@ Block* Parser::ParseVariableDeclarations(
// Create new block with one expected declaration.
Block* block = factory()->NewBlock(NULL, 1, true, pos);
int nvars = 0; // the number of variables declared
+ int bindings_start = peek_position();
const AstRawString* name = NULL;
+ const AstRawString* first_name = NULL;
bool is_for_iteration_variable;
do {
if (fni_ != NULL) fni_->Enter();
@@ -2312,6 +2315,7 @@ Block* Parser::ParseVariableDeclarations(
// Parse variable name.
if (nvars > 0) Consume(Token::COMMA);
name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
+ if (!first_name) first_name = name;
Scanner::Location variable_loc = scanner()->location();
if (fni_ != NULL) fni_->PushVariableName(name);
@@ -2519,12 +2523,14 @@ Block* Parser::ParseVariableDeclarations(
if (fni_ != NULL) fni_->Leave();
} while (peek() == Token::COMMA);
- // If there was a single non-const declaration, return it in the output
- // parameter for possible use by for/in.
- if (nvars == 1 && (!is_const || is_for_iteration_variable)) {
- *out = name;
+ if (bindings_loc) {
+ *bindings_loc =
+ Scanner::Location(bindings_start, scanner()->location().end_pos);
}
+ if (num_decl) *num_decl = nvars;
+ *out = first_name;
+
return block;
}
@@ -3368,15 +3374,27 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
(peek() == Token::CONST && is_sloppy(language_mode()))) {
const AstRawString* name = NULL;
Scanner::Location first_initializer_loc = Scanner::Location::invalid();
+ Scanner::Location bindings_loc = Scanner::Location::invalid();
+ int num_decl;
Block* variable_statement = ParseVariableDeclarations(
- kForStatement, nullptr, &name, &first_initializer_loc, CHECK_OK);
+ kForStatement, &num_decl, nullptr, &name, &first_initializer_loc,
+ &bindings_loc, CHECK_OK);
+ bool accept_IN = num_decl >= 1;
marja 2015/04/08 15:11:05 I was reading this code for a while and it's sligh
bool accept_OF = true;
ForEachStatement::VisitMode mode;
int each_beg_pos = scanner()->location().beg_pos;
int each_end_pos = scanner()->location().end_pos;
- if (name != NULL && CheckInOrOf(accept_OF, &mode, ok)) {
+ if (accept_IN && CheckInOrOf(accept_OF, &mode, ok)) {
if (!*ok) return nullptr;
+ if (num_decl != 1) {
+ const char* loop_type =
+ mode == ForEachStatement::ITERATE ? "for-of" : "for-in";
+ ParserTraits::ReportMessageAt(
+ bindings_loc, "for_inof_loop_multi_bindings", loop_type);
+ *ok = false;
+ return nullptr;
+ }
if (first_initializer_loc.IsValid() &&
(is_strict(language_mode()) || mode == ForEachStatement::ITERATE)) {
if (mode == ForEachStatement::ITERATE) {
@@ -3417,10 +3435,12 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
is_const = peek() == Token::CONST;
const AstRawString* name = NULL;
Scanner::Location first_initializer_loc = Scanner::Location::invalid();
- Block* variable_statement =
- ParseVariableDeclarations(kForStatement, &lexical_bindings, &name,
- &first_initializer_loc, CHECK_OK);
- bool accept_IN = name != NULL;
+ Scanner::Location bindings_loc = Scanner::Location::invalid();
+ int num_decl;
+ Block* variable_statement = ParseVariableDeclarations(
+ kForStatement, &num_decl, &lexical_bindings, &name,
+ &first_initializer_loc, &bindings_loc, CHECK_OK);
+ bool accept_IN = num_decl >= 1;
bool accept_OF = true;
ForEachStatement::VisitMode mode;
int each_beg_pos = scanner()->location().beg_pos;
@@ -3428,6 +3448,14 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
if (accept_IN && CheckInOrOf(accept_OF, &mode, ok)) {
if (!*ok) return nullptr;
+ if (num_decl != 1) {
+ const char* loop_type =
+ mode == ForEachStatement::ITERATE ? "for-of" : "for-in";
+ ParserTraits::ReportMessageAt(
+ bindings_loc, "for_inof_loop_multi_bindings", loop_type);
+ *ok = false;
+ return nullptr;
+ }
if (first_initializer_loc.IsValid() &&
(is_strict(language_mode()) || mode == ForEachStatement::ITERATE)) {
if (mode == ForEachStatement::ITERATE) {
« no previous file with comments | « src/parser.h ('k') | src/preparser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698