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