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

Side by Side Diff: src/preparser.cc

Issue 1416753009: [parser] early error when declaration Pattern missing Initializer (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: comments addressed Created 5 years, 1 month 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
« no previous file with comments | « src/preparser.h ('k') | test/cctest/test-parsing.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 514 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
OLDNEW
« no previous file with comments | « src/preparser.h ('k') | test/cctest/test-parsing.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698