| 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 514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 525 // | 525 // |
| 526 // ConstDeclaration :: | 526 // ConstDeclaration :: |
| 527 // const ConstBinding (',' ConstBinding)* ';' | 527 // const ConstBinding (',' ConstBinding)* ';' |
| 528 // ConstBinding :: | 528 // ConstBinding :: |
| 529 // Identifier '=' AssignmentExpression | 529 // Identifier '=' AssignmentExpression |
| 530 // | 530 // |
| 531 // TODO(ES6): | 531 // TODO(ES6): |
| 532 // ConstBinding :: | 532 // ConstBinding :: |
| 533 // BindingPattern '=' AssignmentExpression | 533 // BindingPattern '=' AssignmentExpression |
| 534 bool require_initializer = false; | 534 bool require_initializer = false; |
| 535 bool is_strict_const = false; | |
| 536 bool lexical = false; | 535 bool lexical = false; |
| 537 if (peek() == Token::VAR) { | 536 if (peek() == Token::VAR) { |
| 538 if (is_strong(language_mode())) { | 537 if (is_strong(language_mode())) { |
| 539 Scanner::Location location = scanner()->peek_location(); | 538 Scanner::Location location = scanner()->peek_location(); |
| 540 ReportMessageAt(location, MessageTemplate::kStrongVar); | 539 ReportMessageAt(location, MessageTemplate::kStrongVar); |
| 541 *ok = false; | 540 *ok = false; |
| 542 return Statement::Default(); | 541 return Statement::Default(); |
| 543 } | 542 } |
| 544 Consume(Token::VAR); | 543 Consume(Token::VAR); |
| 545 } else if (peek() == Token::CONST && allow_const()) { | 544 } else if (peek() == Token::CONST && allow_const()) { |
| 546 // TODO(ES6): The ES6 Draft Rev4 section 12.2.2 reads: | 545 // TODO(ES6): The ES6 Draft Rev4 section 12.2.2 reads: |
| 547 // | 546 // |
| 548 // ConstDeclaration : const ConstBinding (',' ConstBinding)* ';' | 547 // ConstDeclaration : const ConstBinding (',' ConstBinding)* ';' |
| 549 // | 548 // |
| 550 // * It is a Syntax Error if the code that matches this production is not | 549 // * It is a Syntax Error if the code that matches this production is not |
| 551 // contained in extended code. | 550 // contained in extended code. |
| 552 // | 551 // |
| 553 // However disallowing const in sloppy mode will break compatibility with | 552 // However disallowing const in sloppy mode will break compatibility with |
| 554 // existing pages. Therefore we keep allowing const with the old | 553 // existing pages. Therefore we keep allowing const with the old |
| 555 // non-harmony semantics in sloppy mode. | 554 // non-harmony semantics in sloppy mode. |
| 556 Consume(Token::CONST); | 555 Consume(Token::CONST); |
| 557 if (is_strict(language_mode()) || | 556 if (is_strict(language_mode()) || |
| 558 (allow_harmony_sloppy() && !allow_legacy_const())) { | 557 (allow_harmony_sloppy() && !allow_legacy_const())) { |
| 559 DCHECK(var_context != kStatement); | 558 DCHECK(var_context != kStatement); |
| 560 is_strict_const = true; | 559 require_initializer = true; |
| 561 require_initializer = var_context != kForStatement; | |
| 562 lexical = true; | 560 lexical = true; |
| 563 } | 561 } |
| 564 } else if (peek() == Token::LET && allow_let()) { | 562 } else if (peek() == Token::LET && allow_let()) { |
| 565 Consume(Token::LET); | 563 Consume(Token::LET); |
| 566 DCHECK(var_context != kStatement); | 564 DCHECK(var_context != kStatement); |
| 567 lexical = true; | 565 lexical = true; |
| 568 } else { | 566 } else { |
| 569 *ok = false; | 567 *ok = false; |
| 570 return Statement::Default(); | 568 return Statement::Default(); |
| 571 } | 569 } |
| 572 | 570 |
| 573 // The scope of a var/const declared variable anywhere inside a function | 571 // The scope of a var/const declared variable anywhere inside a function |
| 574 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope | 572 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope |
| 575 // of a let declared variable is the scope of the immediately enclosing | 573 // of a let declared variable is the scope of the immediately enclosing |
| 576 // block. | 574 // block. |
| 577 int nvars = 0; // the number of variables declared | 575 int nvars = 0; // the number of variables declared |
| 578 int bindings_start = peek_position(); | 576 int bindings_start = peek_position(); |
| 579 do { | 577 do { |
| 580 // Parse binding pattern. | 578 // Parse binding pattern. |
| 581 if (nvars > 0) Consume(Token::COMMA); | 579 if (nvars > 0) Consume(Token::COMMA); |
| 580 int decl_pos = peek_position(); |
| 581 PreParserExpression pattern = PreParserExpression::Default(); |
| 582 { | 582 { |
| 583 ExpressionClassifier pattern_classifier; | 583 ExpressionClassifier pattern_classifier; |
| 584 Token::Value next = peek(); | 584 Token::Value next = peek(); |
| 585 PreParserExpression pattern = | 585 pattern = ParsePrimaryExpression(&pattern_classifier, CHECK_OK); |
| 586 ParsePrimaryExpression(&pattern_classifier, CHECK_OK); | 586 |
| 587 ValidateBindingPattern(&pattern_classifier, CHECK_OK); | 587 ValidateBindingPattern(&pattern_classifier, CHECK_OK); |
| 588 if (lexical) { | 588 if (lexical) { |
| 589 ValidateLetPattern(&pattern_classifier, CHECK_OK); | 589 ValidateLetPattern(&pattern_classifier, CHECK_OK); |
| 590 } | 590 } |
| 591 | 591 |
| 592 if (!allow_harmony_destructuring() && !pattern.IsIdentifier()) { | 592 if (!allow_harmony_destructuring() && !pattern.IsIdentifier()) { |
| 593 ReportUnexpectedToken(next); | 593 ReportUnexpectedToken(next); |
| 594 *ok = false; | 594 *ok = false; |
| 595 return Statement::Default(); | 595 return Statement::Default(); |
| 596 } | 596 } |
| 597 } | 597 } |
| 598 | 598 |
| 599 bool is_pattern = pattern.IsObjectLiteral() || pattern.IsArrayLiteral(); |
| 600 |
| 601 bool is_for_iteration_variable = |
| 602 var_context == kForStatement && |
| 603 (peek() == Token::IN || PeekContextualKeyword(CStrVector("of"))); |
| 604 |
| 599 Scanner::Location variable_loc = scanner()->location(); | 605 Scanner::Location variable_loc = scanner()->location(); |
| 600 nvars++; | 606 nvars++; |
| 601 if (peek() == Token::ASSIGN || require_initializer || | 607 if (Check(Token::ASSIGN)) { |
| 602 // require initializers for multiple consts. | |
| 603 (is_strict_const && peek() == Token::COMMA)) { | |
| 604 Expect(Token::ASSIGN, CHECK_OK); | |
| 605 ExpressionClassifier classifier; | 608 ExpressionClassifier classifier; |
| 606 ParseAssignmentExpression(var_context != kForStatement, &classifier, | 609 ParseAssignmentExpression(var_context != kForStatement, &classifier, |
| 607 CHECK_OK); | 610 CHECK_OK); |
| 608 ValidateExpression(&classifier, CHECK_OK); | 611 ValidateExpression(&classifier, CHECK_OK); |
| 609 | 612 |
| 610 variable_loc.end_pos = scanner()->location().end_pos; | 613 variable_loc.end_pos = scanner()->location().end_pos; |
| 611 if (first_initializer_loc && !first_initializer_loc->IsValid()) { | 614 if (first_initializer_loc && !first_initializer_loc->IsValid()) { |
| 612 *first_initializer_loc = variable_loc; | 615 *first_initializer_loc = variable_loc; |
| 613 } | 616 } |
| 617 } else if ((require_initializer || is_pattern) && |
| 618 !is_for_iteration_variable) { |
| 619 PreParserTraits::ReportMessageAt( |
| 620 Scanner::Location(decl_pos, scanner()->location().end_pos), |
| 621 MessageTemplate::kDeclarationMissingInitializer, |
| 622 is_pattern ? "destructuring" : "const"); |
| 623 *ok = false; |
| 624 return Statement::Default(); |
| 614 } | 625 } |
| 615 } while (peek() == Token::COMMA); | 626 } while (peek() == Token::COMMA); |
| 616 | 627 |
| 617 if (bindings_loc) { | 628 if (bindings_loc) { |
| 618 *bindings_loc = | 629 *bindings_loc = |
| 619 Scanner::Location(bindings_start, scanner()->location().end_pos); | 630 Scanner::Location(bindings_start, scanner()->location().end_pos); |
| 620 } | 631 } |
| 621 | 632 |
| 622 if (num_decl != NULL) *num_decl = nvars; | 633 if (num_decl != NULL) *num_decl = nvars; |
| 623 return Statement::Default(); | 634 return Statement::Default(); |
| (...skipping 630 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1254 Expect(Token::RBRACE, CHECK_OK); | 1265 Expect(Token::RBRACE, CHECK_OK); |
| 1255 return PreParserExpression::Default(); | 1266 return PreParserExpression::Default(); |
| 1256 } | 1267 } |
| 1257 } | 1268 } |
| 1258 | 1269 |
| 1259 #undef CHECK_OK | 1270 #undef CHECK_OK |
| 1260 | 1271 |
| 1261 | 1272 |
| 1262 } // namespace internal | 1273 } // namespace internal |
| 1263 } // namespace v8 | 1274 } // namespace v8 |
| OLD | NEW |