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

Side by Side Diff: src/preparser.cc

Issue 1033823002: [es6] emit error when for-in loop declarations are initialized in strict mode (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Add TODO 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 unified diff | Download patch
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <cmath> 5 #include <cmath>
6 6
7 #include "src/allocation.h" 7 #include "src/allocation.h"
8 #include "src/base/logging.h" 8 #include "src/base/logging.h"
9 #include "src/conversions-inl.h" 9 #include "src/conversions-inl.h"
10 #include "src/conversions.h" 10 #include "src/conversions.h"
(...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after
403 return Statement::Default(); 403 return Statement::Default();
404 } 404 }
405 405
406 406
407 PreParser::Statement PreParser::ParseVariableStatement( 407 PreParser::Statement PreParser::ParseVariableStatement(
408 VariableDeclarationContext var_context, 408 VariableDeclarationContext var_context,
409 bool* ok) { 409 bool* ok) {
410 // VariableStatement :: 410 // VariableStatement ::
411 // VariableDeclarations ';' 411 // VariableDeclarations ';'
412 412
413 Statement result = ParseVariableDeclarations(var_context, 413 Statement result = ParseVariableDeclarations(var_context, nullptr, nullptr,
414 NULL, 414 nullptr, CHECK_OK);
415 NULL,
416 CHECK_OK);
417 ExpectSemicolon(CHECK_OK); 415 ExpectSemicolon(CHECK_OK);
418 return result; 416 return result;
419 } 417 }
420 418
421 419
422 // If the variable declaration declares exactly one non-const 420 // If the variable declaration declares exactly one non-const
423 // variable, then *var is set to that variable. In all other cases, 421 // variable, then *var is set to that variable. In all other cases,
424 // *var is untouched; in particular, it is the caller's responsibility 422 // *var is untouched; in particular, it is the caller's responsibility
425 // to initialize it properly. This mechanism is also used for the parsing 423 // to initialize it properly. This mechanism is also used for the parsing
426 // of 'for-in' loops. 424 // of 'for-in' loops.
427 PreParser::Statement PreParser::ParseVariableDeclarations( 425 PreParser::Statement PreParser::ParseVariableDeclarations(
428 VariableDeclarationContext var_context, 426 VariableDeclarationContext var_context,
429 VariableDeclarationProperties* decl_props, 427 VariableDeclarationProperties* decl_props, int* num_decl,
marja 2015/04/07 08:30:34 Ditto
430 int* num_decl, 428 Scanner::Location* first_initializer_loc, bool* ok) {
431 bool* ok) {
432 // VariableDeclarations :: 429 // VariableDeclarations ::
433 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[','] 430 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
434 // 431 //
435 // The ES6 Draft Rev3 specifies the following grammar for const declarations 432 // The ES6 Draft Rev3 specifies the following grammar for const declarations
436 // 433 //
437 // ConstDeclaration :: 434 // ConstDeclaration ::
438 // const ConstBinding (',' ConstBinding)* ';' 435 // const ConstBinding (',' ConstBinding)* ';'
439 // ConstBinding :: 436 // ConstBinding ::
440 // Identifier '=' AssignmentExpression 437 // Identifier '=' AssignmentExpression
441 // 438 //
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
479 476
480 // The scope of a var/const declared variable anywhere inside a function 477 // The scope of a var/const declared variable anywhere inside a function
481 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope 478 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope
482 // of a let declared variable is the scope of the immediately enclosing 479 // of a let declared variable is the scope of the immediately enclosing
483 // block. 480 // block.
484 int nvars = 0; // the number of variables declared 481 int nvars = 0; // the number of variables declared
485 do { 482 do {
486 // Parse variable name. 483 // Parse variable name.
487 if (nvars > 0) Consume(Token::COMMA); 484 if (nvars > 0) Consume(Token::COMMA);
488 ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); 485 ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
486 Scanner::Location variable_loc = scanner()->location();
489 nvars++; 487 nvars++;
490 if (peek() == Token::ASSIGN || require_initializer || 488 if (peek() == Token::ASSIGN || require_initializer ||
491 // require initializers for multiple consts. 489 // require initializers for multiple consts.
492 (is_strict_const && peek() == Token::COMMA)) { 490 (is_strict_const && peek() == Token::COMMA)) {
493 Expect(Token::ASSIGN, CHECK_OK); 491 Expect(Token::ASSIGN, CHECK_OK);
494 ParseAssignmentExpression(var_context != kForStatement, CHECK_OK); 492 ParseAssignmentExpression(var_context != kForStatement, CHECK_OK);
493
494 variable_loc.end_pos = scanner()->location().end_pos;
495 if (first_initializer_loc && !first_initializer_loc->IsValid()) {
496 *first_initializer_loc = variable_loc;
497 }
498
495 if (decl_props != NULL) *decl_props = kHasInitializers; 499 if (decl_props != NULL) *decl_props = kHasInitializers;
496 } 500 }
497 } while (peek() == Token::COMMA); 501 } while (peek() == Token::COMMA);
498 502
499 if (num_decl != NULL) *num_decl = nvars; 503 if (num_decl != NULL) *num_decl = nvars;
500 return Statement::Default(); 504 return Statement::Default();
501 } 505 }
502 506
503 507
504 PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) { 508 PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) {
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
721 725
722 726
723 PreParser::Statement PreParser::ParseForStatement(bool* ok) { 727 PreParser::Statement PreParser::ParseForStatement(bool* ok) {
724 // ForStatement :: 728 // ForStatement ::
725 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement 729 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
726 730
727 Expect(Token::FOR, CHECK_OK); 731 Expect(Token::FOR, CHECK_OK);
728 Expect(Token::LPAREN, CHECK_OK); 732 Expect(Token::LPAREN, CHECK_OK);
729 bool is_let_identifier_expression = false; 733 bool is_let_identifier_expression = false;
730 if (peek() != Token::SEMICOLON) { 734 if (peek() != Token::SEMICOLON) {
731 ForEachStatement::VisitMode visit_mode; 735 ForEachStatement::VisitMode mode;
marja 2015/04/07 08:30:34 Why this change?
caitp (gmail) 2015/04/07 11:56:20 It matches the version of this code in parser.cc,
732 if (peek() == Token::VAR || peek() == Token::CONST || 736 if (peek() == Token::VAR || peek() == Token::CONST ||
733 (peek() == Token::LET && is_strict(language_mode()))) { 737 (peek() == Token::LET && is_strict(language_mode()))) {
734 bool is_lexical = peek() == Token::LET || 738 bool is_lexical = peek() == Token::LET ||
735 (peek() == Token::CONST && is_strict(language_mode())); 739 (peek() == Token::CONST && is_strict(language_mode()));
736 int decl_count; 740 int decl_count;
737 VariableDeclarationProperties decl_props = kHasNoInitializers; 741 VariableDeclarationProperties decl_props = kHasNoInitializers;
738 ParseVariableDeclarations( 742 Scanner::Location first_initializer_loc = Scanner::Location::invalid();
739 kForStatement, &decl_props, &decl_count, CHECK_OK); 743 ParseVariableDeclarations(kForStatement, &decl_props, &decl_count,
744 &first_initializer_loc, CHECK_OK);
740 bool has_initializers = decl_props == kHasInitializers; 745 bool has_initializers = decl_props == kHasInitializers;
741 bool accept_IN = decl_count == 1 && !(is_lexical && has_initializers); 746 bool accept_IN = decl_count == 1 && !(is_lexical && has_initializers);
742 bool accept_OF = !has_initializers; 747 bool accept_OF = true;
743 if (accept_IN && CheckInOrOf(accept_OF, &visit_mode, ok)) { 748 if (accept_IN && CheckInOrOf(accept_OF, &mode, ok)) {
744 if (!*ok) return Statement::Default(); 749 if (!*ok) return Statement::Default();
750 if (first_initializer_loc.IsValid() &&
751 (is_strict(language_mode()) || mode == ForEachStatement::ITERATE)) {
752 if (mode == ForEachStatement::ITERATE) {
753 ReportMessageAt(first_initializer_loc, "for_of_loop_initializer");
754 } else {
755 // TODO(caitp): This should be an error in sloppy mode, too.
756 ReportMessageAt(first_initializer_loc, "for_in_loop_initializer");
757 }
758 *ok = false;
759 return Statement::Default();
760 }
745 ParseExpression(true, CHECK_OK); 761 ParseExpression(true, CHECK_OK);
746 Expect(Token::RPAREN, CHECK_OK); 762 Expect(Token::RPAREN, CHECK_OK);
747 ParseSubStatement(CHECK_OK); 763 ParseSubStatement(CHECK_OK);
748 return Statement::Default(); 764 return Statement::Default();
749 } 765 }
750 } else { 766 } else {
751 Expression lhs = ParseExpression(false, CHECK_OK); 767 Expression lhs = ParseExpression(false, CHECK_OK);
752 is_let_identifier_expression = 768 is_let_identifier_expression =
753 lhs.IsIdentifier() && lhs.AsIdentifier().IsLet(); 769 lhs.IsIdentifier() && lhs.AsIdentifier().IsLet();
754 if (CheckInOrOf(lhs.IsIdentifier(), &visit_mode, ok)) { 770 if (CheckInOrOf(lhs.IsIdentifier(), &mode, ok)) {
755 if (!*ok) return Statement::Default(); 771 if (!*ok) return Statement::Default();
756 ParseExpression(true, CHECK_OK); 772 ParseExpression(true, CHECK_OK);
757 Expect(Token::RPAREN, CHECK_OK); 773 Expect(Token::RPAREN, CHECK_OK);
758 ParseSubStatement(CHECK_OK); 774 ParseSubStatement(CHECK_OK);
759 return Statement::Default(); 775 return Statement::Default();
760 } 776 }
761 } 777 }
762 } 778 }
763 779
764 // Parsed initializer at this point. 780 // Parsed initializer at this point.
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after
1045 ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); 1061 ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
1046 ParseArguments(ok); 1062 ParseArguments(ok);
1047 1063
1048 return Expression::Default(); 1064 return Expression::Default();
1049 } 1065 }
1050 1066
1051 #undef CHECK_OK 1067 #undef CHECK_OK
1052 1068
1053 1069
1054 } } // v8::internal 1070 } } // v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698