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

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: Add a bunch of message tests + refactor a bit 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
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 539 matching lines...) Expand 10 before | Expand all | Expand 10 after
550 // * It is a Syntax Error if the code that matches this production is not 550 // * It is a Syntax Error if the code that matches this production is not
551 // contained in extended code. 551 // contained in extended code.
552 // 552 //
553 // However disallowing const in sloppy mode will break compatibility with 553 // However disallowing const in sloppy mode will break compatibility with
554 // existing pages. Therefore we keep allowing const with the old 554 // existing pages. Therefore we keep allowing const with the old
555 // non-harmony semantics in sloppy mode. 555 // non-harmony semantics in sloppy mode.
556 Consume(Token::CONST); 556 Consume(Token::CONST);
557 if (is_strict(language_mode()) || 557 if (is_strict(language_mode()) ||
558 (allow_harmony_sloppy() && !allow_legacy_const())) { 558 (allow_harmony_sloppy() && !allow_legacy_const())) {
559 DCHECK(var_context != kStatement); 559 DCHECK(var_context != kStatement);
560 is_strict_const = true; 560 is_strict_const = true;
adamk 2015/11/04 00:37:54 This means "is not legacy const".
561 require_initializer = var_context != kForStatement; 561 require_initializer = true;
adamk 2015/11/04 00:37:54 Seems like "is_const" would be a better name for t
562 lexical = true; 562 lexical = true;
563 } 563 }
564 } else if (peek() == Token::LET && allow_let()) { 564 } else if (peek() == Token::LET && allow_let()) {
565 Consume(Token::LET); 565 Consume(Token::LET);
566 DCHECK(var_context != kStatement); 566 DCHECK(var_context != kStatement);
567 lexical = true; 567 lexical = true;
568 } else { 568 } else {
569 *ok = false; 569 *ok = false;
570 return Statement::Default(); 570 return Statement::Default();
571 } 571 }
572 572
573 // The scope of a var/const declared variable anywhere inside a function 573 // 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 574 // 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 575 // of a let declared variable is the scope of the immediately enclosing
576 // block. 576 // block.
577 int nvars = 0; // the number of variables declared 577 int nvars = 0; // the number of variables declared
578 int bindings_start = peek_position(); 578 int bindings_start = peek_position();
579 do { 579 do {
580 // Parse binding pattern. 580 // Parse binding pattern.
581 if (nvars > 0) Consume(Token::COMMA); 581 if (nvars > 0) Consume(Token::COMMA);
582 int decl_pos = peek_position();
583 bool is_pattern = false;
582 { 584 {
583 ExpressionClassifier pattern_classifier; 585 ExpressionClassifier pattern_classifier;
584 Token::Value next = peek(); 586 Token::Value next = peek();
585 PreParserExpression pattern = 587 PreParserExpression pattern =
586 ParsePrimaryExpression(&pattern_classifier, CHECK_OK); 588 ParsePrimaryExpression(&pattern_classifier, CHECK_OK);
589 is_pattern = pattern.IsObjectLiteral(); // (or pattern.IsArrayLiteral());
adamk 2015/11/04 00:37:54 I'd rather you just add the bit for ArrayLiteral t
caitp (gmail) 2015/11/04 15:07:28 Done, although I think it will mean adding an extr
590
587 ValidateBindingPattern(&pattern_classifier, CHECK_OK); 591 ValidateBindingPattern(&pattern_classifier, CHECK_OK);
588 if (lexical) { 592 if (lexical) {
589 ValidateLetPattern(&pattern_classifier, CHECK_OK); 593 ValidateLetPattern(&pattern_classifier, CHECK_OK);
590 } 594 }
591 595
592 if (!allow_harmony_destructuring() && !pattern.IsIdentifier()) { 596 if (!allow_harmony_destructuring() && !pattern.IsIdentifier()) {
593 ReportUnexpectedToken(next); 597 ReportUnexpectedToken(next);
594 *ok = false; 598 *ok = false;
595 return Statement::Default(); 599 return Statement::Default();
596 } 600 }
597 } 601 }
598 602
603 bool is_for_iteration_variable =
604 var_context == kForStatement &&
605 (peek() == Token::IN || PeekContextualKeyword(CStrVector("of")));
606
599 Scanner::Location variable_loc = scanner()->location(); 607 Scanner::Location variable_loc = scanner()->location();
600 nvars++; 608 nvars++;
601 if (peek() == Token::ASSIGN || require_initializer || 609 if (peek() == Token::ASSIGN ||
610 (!is_for_iteration_variable && (require_initializer || is_pattern)) ||
adamk 2015/11/04 00:37:54 Maybe put this in the same order as in the parser
rossberg 2015/11/04 10:52:36 Same comment as in the parser: move this to else b
602 // require initializers for multiple consts. 611 // require initializers for multiple consts.
603 (is_strict_const && peek() == Token::COMMA)) { 612 (is_strict_const && peek() == Token::COMMA)) {
adamk 2015/11/04 00:37:54 I think this bit is now redundant with your is_for
caitp (gmail) 2015/11/04 15:07:28 Well, this was the only place the variable was use
604 Expect(Token::ASSIGN, CHECK_OK); 613 if (peek() != Token::ASSIGN) {
adamk 2015/11/04 00:37:54 Same note here as in the parser, you can use if (!
614 PreParserTraits::ReportMessageAt(
615 Scanner::Location(decl_pos, scanner()->location().end_pos),
616 MessageTemplate::kDeclarationMissingInitializer,
617 is_pattern ? "destructuring" : "const");
618 *ok = false;
619 return Statement::Default();
620 }
621 Consume(Token::ASSIGN);
605 ExpressionClassifier classifier; 622 ExpressionClassifier classifier;
606 ParseAssignmentExpression(var_context != kForStatement, &classifier, 623 ParseAssignmentExpression(var_context != kForStatement, &classifier,
607 CHECK_OK); 624 CHECK_OK);
608 ValidateExpression(&classifier, CHECK_OK); 625 ValidateExpression(&classifier, CHECK_OK);
609 626
610 variable_loc.end_pos = scanner()->location().end_pos; 627 variable_loc.end_pos = scanner()->location().end_pos;
611 if (first_initializer_loc && !first_initializer_loc->IsValid()) { 628 if (first_initializer_loc && !first_initializer_loc->IsValid()) {
612 *first_initializer_loc = variable_loc; 629 *first_initializer_loc = variable_loc;
613 } 630 }
614 } 631 }
(...skipping 639 matching lines...) Expand 10 before | Expand all | Expand 10 after
1254 Expect(Token::RBRACE, CHECK_OK); 1271 Expect(Token::RBRACE, CHECK_OK);
1255 return PreParserExpression::Default(); 1272 return PreParserExpression::Default();
1256 } 1273 }
1257 } 1274 }
1258 1275
1259 #undef CHECK_OK 1276 #undef CHECK_OK
1260 1277
1261 1278
1262 } // namespace internal 1279 } // namespace internal
1263 } // namespace v8 1280 } // namespace v8
OLDNEW
« src/parser.cc ('K') | « src/preparser.h ('k') | test/cctest/test-parsing.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698