| OLD | NEW |
| 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 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 416 return final; | 416 return final; |
| 417 } | 417 } |
| 418 | 418 |
| 419 | 419 |
| 420 PreParser::Statement PreParser::ParseVariableStatement( | 420 PreParser::Statement PreParser::ParseVariableStatement( |
| 421 VariableDeclarationContext var_context, | 421 VariableDeclarationContext var_context, |
| 422 bool* ok) { | 422 bool* ok) { |
| 423 // VariableStatement :: | 423 // VariableStatement :: |
| 424 // VariableDeclarations ';' | 424 // VariableDeclarations ';' |
| 425 | 425 |
| 426 Statement result = ParseVariableDeclarations( | 426 Statement result = |
| 427 var_context, nullptr, nullptr, nullptr, nullptr, nullptr, CHECK_OK); | 427 ParseVariableDeclarations(var_context, nullptr, nullptr, CHECK_OK); |
| 428 ExpectSemicolon(CHECK_OK); | 428 ExpectSemicolon(CHECK_OK); |
| 429 return result; | 429 return result; |
| 430 } | 430 } |
| 431 | 431 |
| 432 | |
| 433 // If the variable declaration declares exactly one non-const | |
| 434 // variable, then *var is set to that variable. In all other cases, | |
| 435 // *var is untouched; in particular, it is the caller's responsibility | |
| 436 // to initialize it properly. This mechanism is also used for the parsing | |
| 437 // of 'for-in' loops. | |
| 438 PreParser::Statement PreParser::ParseVariableDeclarations( | |
| 439 VariableDeclarationContext var_context, int* num_decl, bool* is_lexical, | |
| 440 bool* is_binding_pattern, Scanner::Location* first_initializer_loc, | |
| 441 Scanner::Location* bindings_loc, bool* ok) { | |
| 442 // VariableDeclarations :: | |
| 443 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[','] | |
| 444 // | |
| 445 // The ES6 Draft Rev3 specifies the following grammar for const declarations | |
| 446 // | |
| 447 // ConstDeclaration :: | |
| 448 // const ConstBinding (',' ConstBinding)* ';' | |
| 449 // ConstBinding :: | |
| 450 // Identifier '=' AssignmentExpression | |
| 451 // | |
| 452 // TODO(ES6): | |
| 453 // ConstBinding :: | |
| 454 // BindingPattern '=' AssignmentExpression | |
| 455 bool require_initializer = false; | |
| 456 bool lexical = false; | |
| 457 bool is_pattern = false; | |
| 458 if (peek() == Token::VAR) { | |
| 459 Consume(Token::VAR); | |
| 460 } else if (peek() == Token::CONST) { | |
| 461 // TODO(ES6): The ES6 Draft Rev4 section 12.2.2 reads: | |
| 462 // | |
| 463 // ConstDeclaration : const ConstBinding (',' ConstBinding)* ';' | |
| 464 // | |
| 465 // * It is a Syntax Error if the code that matches this production is not | |
| 466 // contained in extended code. | |
| 467 // | |
| 468 // However disallowing const in sloppy mode will break compatibility with | |
| 469 // existing pages. Therefore we keep allowing const with the old | |
| 470 // non-harmony semantics in sloppy mode. | |
| 471 Consume(Token::CONST); | |
| 472 DCHECK(var_context != kStatement); | |
| 473 require_initializer = true; | |
| 474 lexical = true; | |
| 475 } else if (peek() == Token::LET) { | |
| 476 Consume(Token::LET); | |
| 477 DCHECK(var_context != kStatement); | |
| 478 lexical = true; | |
| 479 } else { | |
| 480 *ok = false; | |
| 481 return Statement::Default(); | |
| 482 } | |
| 483 | |
| 484 // The scope of a var/const declared variable anywhere inside a function | |
| 485 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope | |
| 486 // of a let declared variable is the scope of the immediately enclosing | |
| 487 // block. | |
| 488 int nvars = 0; // the number of variables declared | |
| 489 int bindings_start = peek_position(); | |
| 490 do { | |
| 491 // Parse binding pattern. | |
| 492 if (nvars > 0) Consume(Token::COMMA); | |
| 493 int decl_pos = peek_position(); | |
| 494 PreParserExpression pattern = PreParserExpression::Default(); | |
| 495 { | |
| 496 ExpressionClassifier pattern_classifier(this); | |
| 497 pattern = ParsePrimaryExpression(CHECK_OK); | |
| 498 | |
| 499 ValidateBindingPattern(CHECK_OK); | |
| 500 if (lexical) ValidateLetPattern(CHECK_OK); | |
| 501 } | |
| 502 | |
| 503 is_pattern = pattern.IsObjectLiteral() || pattern.IsArrayLiteral(); | |
| 504 | |
| 505 Scanner::Location variable_loc = scanner()->location(); | |
| 506 nvars++; | |
| 507 if (Check(Token::ASSIGN)) { | |
| 508 ExpressionClassifier classifier(this); | |
| 509 ParseAssignmentExpression(var_context != kForStatement, CHECK_OK); | |
| 510 ValidateExpression(CHECK_OK); | |
| 511 | |
| 512 variable_loc.end_pos = scanner()->location().end_pos; | |
| 513 if (first_initializer_loc && !first_initializer_loc->IsValid()) { | |
| 514 *first_initializer_loc = variable_loc; | |
| 515 } | |
| 516 } else if ((require_initializer || is_pattern) && | |
| 517 (var_context != kForStatement || !PeekInOrOf())) { | |
| 518 ReportMessageAt( | |
| 519 Scanner::Location(decl_pos, scanner()->location().end_pos), | |
| 520 MessageTemplate::kDeclarationMissingInitializer, | |
| 521 is_pattern ? "destructuring" : "const"); | |
| 522 *ok = false; | |
| 523 return Statement::Default(); | |
| 524 } | |
| 525 } while (peek() == Token::COMMA); | |
| 526 | |
| 527 if (bindings_loc) { | |
| 528 *bindings_loc = | |
| 529 Scanner::Location(bindings_start, scanner()->location().end_pos); | |
| 530 } | |
| 531 | |
| 532 if (num_decl != nullptr) *num_decl = nvars; | |
| 533 if (is_lexical != nullptr) *is_lexical = lexical; | |
| 534 if (is_binding_pattern != nullptr) *is_binding_pattern = is_pattern; | |
| 535 return Statement::Default(); | |
| 536 } | |
| 537 | |
| 538 PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) { | 432 PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) { |
| 539 Consume(Token::FUNCTION); | 433 Consume(Token::FUNCTION); |
| 540 int pos = position(); | 434 int pos = position(); |
| 541 ParseFunctionFlags flags = ParseFunctionFlags::kIsNormal; | 435 ParseFunctionFlags flags = ParseFunctionFlags::kIsNormal; |
| 542 if (Check(Token::MUL)) { | 436 if (Check(Token::MUL)) { |
| 543 flags |= ParseFunctionFlags::kIsGenerator; | 437 flags |= ParseFunctionFlags::kIsGenerator; |
| 544 if (allow_harmony_restrictive_declarations()) { | 438 if (allow_harmony_restrictive_declarations()) { |
| 545 ReportMessageAt(scanner()->location(), | 439 ReportMessageAt(scanner()->location(), |
| 546 MessageTemplate::kGeneratorInLegacyContext); | 440 MessageTemplate::kGeneratorInLegacyContext); |
| 547 *ok = false; | 441 *ok = false; |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 791 // Create an in-between scope for let-bound iteration variables. | 685 // Create an in-between scope for let-bound iteration variables. |
| 792 bool has_lexical = false; | 686 bool has_lexical = false; |
| 793 | 687 |
| 794 BlockState block_state(&scope_state_); | 688 BlockState block_state(&scope_state_); |
| 795 Expect(Token::FOR, CHECK_OK); | 689 Expect(Token::FOR, CHECK_OK); |
| 796 Expect(Token::LPAREN, CHECK_OK); | 690 Expect(Token::LPAREN, CHECK_OK); |
| 797 if (peek() != Token::SEMICOLON) { | 691 if (peek() != Token::SEMICOLON) { |
| 798 ForEachStatement::VisitMode mode; | 692 ForEachStatement::VisitMode mode; |
| 799 if (peek() == Token::VAR || peek() == Token::CONST || | 693 if (peek() == Token::VAR || peek() == Token::CONST || |
| 800 (peek() == Token::LET && IsNextLetKeyword())) { | 694 (peek() == Token::LET && IsNextLetKeyword())) { |
| 801 int decl_count; | 695 DeclarationParsingResult parsing_result; |
| 802 bool is_lexical; | 696 |
| 803 bool is_binding_pattern; | 697 ParseVariableDeclarations(kForStatement, &parsing_result, nullptr, |
| 804 Scanner::Location first_initializer_loc = Scanner::Location::invalid(); | 698 CHECK_OK); |
| 805 Scanner::Location bindings_loc = Scanner::Location::invalid(); | 699 if (parsing_result.descriptor.mode == CONST || |
| 806 ParseVariableDeclarations(kForStatement, &decl_count, &is_lexical, | 700 parsing_result.descriptor.mode == LET) { |
| 807 &is_binding_pattern, &first_initializer_loc, | 701 has_lexical = true; |
| 808 &bindings_loc, CHECK_OK); | 702 } |
| 809 if (is_lexical) has_lexical = true; | |
| 810 if (CheckInOrOf(&mode)) { | 703 if (CheckInOrOf(&mode)) { |
| 811 if (decl_count != 1) { | 704 if (!*ok) return Statement::Default(); |
| 812 ReportMessageAt(bindings_loc, | 705 if (parsing_result.declarations.length() != 1) { |
| 706 ReportMessageAt(parsing_result.bindings_loc, |
| 813 MessageTemplate::kForInOfLoopMultiBindings, | 707 MessageTemplate::kForInOfLoopMultiBindings, |
| 814 ForEachStatement::VisitModeString(mode)); | 708 ForEachStatement::VisitModeString(mode)); |
| 815 *ok = false; | 709 *ok = false; |
| 816 return Statement::Default(); | 710 return Statement::Default(); |
| 817 } | 711 } |
| 818 if (first_initializer_loc.IsValid() && | 712 bool is_binding_pattern = |
| 713 parsing_result.declarations[0].pattern.IsObjectLiteral() || |
| 714 parsing_result.declarations[0].pattern.IsArrayLiteral(); |
| 715 if (parsing_result.first_initializer_loc.IsValid() && |
| 819 (is_strict(language_mode()) || mode == ForEachStatement::ITERATE || | 716 (is_strict(language_mode()) || mode == ForEachStatement::ITERATE || |
| 820 is_lexical || is_binding_pattern || allow_harmony_for_in())) { | 717 has_lexical || is_binding_pattern || allow_harmony_for_in())) { |
| 821 // Only increment the use count if we would have let this through | 718 // Only increment the use count if we would have let this through |
| 822 // without the flag. | 719 // without the flag. |
| 823 if (use_counts_ != nullptr && allow_harmony_for_in()) { | 720 if (use_counts_ != nullptr && allow_harmony_for_in()) { |
| 824 ++use_counts_[v8::Isolate::kForInInitializer]; | 721 ++use_counts_[v8::Isolate::kForInInitializer]; |
| 825 } | 722 } |
| 826 ReportMessageAt(first_initializer_loc, | 723 ReportMessageAt(parsing_result.first_initializer_loc, |
| 827 MessageTemplate::kForInOfLoopInitializer, | 724 MessageTemplate::kForInOfLoopInitializer, |
| 828 ForEachStatement::VisitModeString(mode)); | 725 ForEachStatement::VisitModeString(mode)); |
| 829 *ok = false; | 726 *ok = false; |
| 830 return Statement::Default(); | 727 return Statement::Default(); |
| 831 } | 728 } |
| 832 | 729 |
| 833 if (mode == ForEachStatement::ITERATE) { | 730 if (mode == ForEachStatement::ITERATE) { |
| 834 ExpressionClassifier classifier(this); | 731 ExpressionClassifier classifier(this); |
| 835 ParseAssignmentExpression(true, CHECK_OK); | 732 ParseAssignmentExpression(true, CHECK_OK); |
| 836 RewriteNonPattern(CHECK_OK); | 733 RewriteNonPattern(CHECK_OK); |
| (...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1219 | 1116 |
| 1220 body->Add(PreParserStatement::ExpressionStatement(return_value), zone()); | 1117 body->Add(PreParserStatement::ExpressionStatement(return_value), zone()); |
| 1221 } | 1118 } |
| 1222 | 1119 |
| 1223 #undef CHECK_OK | 1120 #undef CHECK_OK |
| 1224 #undef CHECK_OK_CUSTOM | 1121 #undef CHECK_OK_CUSTOM |
| 1225 | 1122 |
| 1226 | 1123 |
| 1227 } // namespace internal | 1124 } // namespace internal |
| 1228 } // namespace v8 | 1125 } // namespace v8 |
| OLD | NEW |