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 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
175 // | 175 // |
176 // LexicalDeclaration[In, Yield] : | 176 // LexicalDeclaration[In, Yield] : |
177 // LetOrConst BindingList[?In, ?Yield] ; | 177 // LetOrConst BindingList[?In, ?Yield] ; |
178 | 178 |
179 switch (peek()) { | 179 switch (peek()) { |
180 case Token::FUNCTION: | 180 case Token::FUNCTION: |
181 return ParseFunctionDeclaration(ok); | 181 return ParseFunctionDeclaration(ok); |
182 case Token::CLASS: | 182 case Token::CLASS: |
183 return ParseClassDeclaration(ok); | 183 return ParseClassDeclaration(ok); |
184 case Token::CONST: | 184 case Token::CONST: |
185 if (allow_const()) { | 185 return ParseVariableStatement(kStatementListItem, ok); |
186 return ParseVariableStatement(kStatementListItem, ok); | |
187 } | |
188 break; | |
189 case Token::LET: | 186 case Token::LET: |
190 if (IsNextLetKeyword()) { | 187 if (IsNextLetKeyword()) { |
191 return ParseVariableStatement(kStatementListItem, ok); | 188 return ParseVariableStatement(kStatementListItem, ok); |
192 } | 189 } |
193 break; | 190 break; |
194 default: | 191 default: |
195 break; | 192 break; |
196 } | 193 } |
197 return ParseStatement(kAllowLabelledFunctionStatement, ok); | 194 return ParseStatement(kAllowLabelledFunctionStatement, ok); |
198 } | 195 } |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
396 is_generator ? FunctionKind::kGeneratorFunction | 393 is_generator ? FunctionKind::kGeneratorFunction |
397 : FunctionKind::kNormalFunction, | 394 : FunctionKind::kNormalFunction, |
398 pos, FunctionLiteral::kDeclaration, language_mode(), | 395 pos, FunctionLiteral::kDeclaration, language_mode(), |
399 CHECK_OK); | 396 CHECK_OK); |
400 return Statement::FunctionDeclaration(); | 397 return Statement::FunctionDeclaration(); |
401 } | 398 } |
402 | 399 |
403 | 400 |
404 PreParser::Statement PreParser::ParseClassDeclaration(bool* ok) { | 401 PreParser::Statement PreParser::ParseClassDeclaration(bool* ok) { |
405 Expect(Token::CLASS, CHECK_OK); | 402 Expect(Token::CLASS, CHECK_OK); |
406 if (!allow_harmony_sloppy() && is_sloppy(language_mode())) { | |
407 ReportMessage(MessageTemplate::kSloppyLexical); | |
408 *ok = false; | |
409 return Statement::Default(); | |
410 } | |
411 | 403 |
412 int pos = position(); | 404 int pos = position(); |
413 bool is_strict_reserved = false; | 405 bool is_strict_reserved = false; |
414 Identifier name = | 406 Identifier name = |
415 ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); | 407 ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); |
416 ParseClassLiteral(name, scanner()->location(), is_strict_reserved, pos, | 408 ParseClassLiteral(name, scanner()->location(), is_strict_reserved, pos, |
417 CHECK_OK); | 409 CHECK_OK); |
418 return Statement::Default(); | 410 return Statement::Default(); |
419 } | 411 } |
420 | 412 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
466 // Identifier '=' AssignmentExpression | 458 // Identifier '=' AssignmentExpression |
467 // | 459 // |
468 // TODO(ES6): | 460 // TODO(ES6): |
469 // ConstBinding :: | 461 // ConstBinding :: |
470 // BindingPattern '=' AssignmentExpression | 462 // BindingPattern '=' AssignmentExpression |
471 bool require_initializer = false; | 463 bool require_initializer = false; |
472 bool lexical = false; | 464 bool lexical = false; |
473 bool is_pattern = false; | 465 bool is_pattern = false; |
474 if (peek() == Token::VAR) { | 466 if (peek() == Token::VAR) { |
475 Consume(Token::VAR); | 467 Consume(Token::VAR); |
476 } else if (peek() == Token::CONST && allow_const()) { | 468 } else if (peek() == Token::CONST) { |
477 // TODO(ES6): The ES6 Draft Rev4 section 12.2.2 reads: | 469 // TODO(ES6): The ES6 Draft Rev4 section 12.2.2 reads: |
478 // | 470 // |
479 // ConstDeclaration : const ConstBinding (',' ConstBinding)* ';' | 471 // ConstDeclaration : const ConstBinding (',' ConstBinding)* ';' |
480 // | 472 // |
481 // * It is a Syntax Error if the code that matches this production is not | 473 // * It is a Syntax Error if the code that matches this production is not |
482 // contained in extended code. | 474 // contained in extended code. |
483 // | 475 // |
484 // However disallowing const in sloppy mode will break compatibility with | 476 // However disallowing const in sloppy mode will break compatibility with |
485 // existing pages. Therefore we keep allowing const with the old | 477 // existing pages. Therefore we keep allowing const with the old |
486 // non-harmony semantics in sloppy mode. | 478 // non-harmony semantics in sloppy mode. |
487 Consume(Token::CONST); | 479 Consume(Token::CONST); |
488 if (is_strict(language_mode()) || allow_harmony_sloppy()) { | 480 DCHECK(var_context != kStatement); |
489 DCHECK(var_context != kStatement); | 481 require_initializer = true; |
490 require_initializer = true; | 482 lexical = true; |
491 lexical = true; | 483 } else if (peek() == Token::LET) { |
492 } | |
493 } else if (peek() == Token::LET && allow_let()) { | |
494 Consume(Token::LET); | 484 Consume(Token::LET); |
495 DCHECK(var_context != kStatement); | 485 DCHECK(var_context != kStatement); |
496 lexical = true; | 486 lexical = true; |
497 } else { | 487 } else { |
498 *ok = false; | 488 *ok = false; |
499 return Statement::Default(); | 489 return Statement::Default(); |
500 } | 490 } |
501 | 491 |
502 // The scope of a var/const declared variable anywhere inside a function | 492 // The scope of a var/const declared variable anywhere inside a function |
503 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope | 493 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
599 } | 589 } |
600 } | 590 } |
601 Statement statement = | 591 Statement statement = |
602 ParseStatement(kDisallowLabelledFunctionStatement, ok); | 592 ParseStatement(kDisallowLabelledFunctionStatement, ok); |
603 return statement.IsJumpStatement() ? Statement::Default() : statement; | 593 return statement.IsJumpStatement() ? Statement::Default() : statement; |
604 // Preparsing is disabled for extensions (because the extension details | 594 // Preparsing is disabled for extensions (because the extension details |
605 // aren't passed to lazily compiled functions), so we don't | 595 // aren't passed to lazily compiled functions), so we don't |
606 // accept "native function" in the preparser. | 596 // accept "native function" in the preparser. |
607 } | 597 } |
608 // Parsed expression statement. | 598 // Parsed expression statement. |
609 // Detect attempts at 'let' declarations in sloppy mode. | |
610 if (!allow_harmony_sloppy_let() && peek() == Token::IDENTIFIER && | |
611 is_sloppy(language_mode()) && expr.IsIdentifier() && | |
612 expr.AsIdentifier().IsLet()) { | |
613 ReportMessage(MessageTemplate::kSloppyLexical, NULL); | |
614 *ok = false; | |
615 return Statement::Default(); | |
616 } | |
617 ExpectSemicolon(CHECK_OK); | 599 ExpectSemicolon(CHECK_OK); |
618 return Statement::ExpressionStatement(expr); | 600 return Statement::ExpressionStatement(expr); |
619 } | 601 } |
620 | 602 |
621 | 603 |
622 PreParser::Statement PreParser::ParseIfStatement(bool* ok) { | 604 PreParser::Statement PreParser::ParseIfStatement(bool* ok) { |
623 // IfStatement :: | 605 // IfStatement :: |
624 // 'if' '(' Expression ')' Statement ('else' Statement)? | 606 // 'if' '(' Expression ')' Statement ('else' Statement)? |
625 | 607 |
626 Expect(Token::IF, CHECK_OK); | 608 Expect(Token::IF, CHECK_OK); |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
783 return Statement::Default(); | 765 return Statement::Default(); |
784 } | 766 } |
785 | 767 |
786 | 768 |
787 PreParser::Statement PreParser::ParseForStatement(bool* ok) { | 769 PreParser::Statement PreParser::ParseForStatement(bool* ok) { |
788 // ForStatement :: | 770 // ForStatement :: |
789 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement | 771 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement |
790 | 772 |
791 Expect(Token::FOR, CHECK_OK); | 773 Expect(Token::FOR, CHECK_OK); |
792 Expect(Token::LPAREN, CHECK_OK); | 774 Expect(Token::LPAREN, CHECK_OK); |
793 bool is_let_identifier_expression = false; | |
794 if (peek() != Token::SEMICOLON) { | 775 if (peek() != Token::SEMICOLON) { |
795 ForEachStatement::VisitMode mode; | 776 ForEachStatement::VisitMode mode; |
796 if (peek() == Token::VAR || (peek() == Token::CONST && allow_const()) || | 777 if (peek() == Token::VAR || peek() == Token::CONST || |
797 (peek() == Token::LET && IsNextLetKeyword())) { | 778 (peek() == Token::LET && IsNextLetKeyword())) { |
798 int decl_count; | 779 int decl_count; |
799 bool is_lexical; | 780 bool is_lexical; |
800 bool is_binding_pattern; | 781 bool is_binding_pattern; |
801 Scanner::Location first_initializer_loc = Scanner::Location::invalid(); | 782 Scanner::Location first_initializer_loc = Scanner::Location::invalid(); |
802 Scanner::Location bindings_loc = Scanner::Location::invalid(); | 783 Scanner::Location bindings_loc = Scanner::Location::invalid(); |
803 ParseVariableDeclarations(kForStatement, &decl_count, &is_lexical, | 784 ParseVariableDeclarations(kForStatement, &decl_count, &is_lexical, |
804 &is_binding_pattern, &first_initializer_loc, | 785 &is_binding_pattern, &first_initializer_loc, |
805 &bindings_loc, CHECK_OK); | 786 &bindings_loc, CHECK_OK); |
806 if (CheckInOrOf(&mode, ok)) { | 787 if (CheckInOrOf(&mode, ok)) { |
(...skipping 25 matching lines...) Expand all Loading... |
832 | 813 |
833 Expect(Token::RPAREN, CHECK_OK); | 814 Expect(Token::RPAREN, CHECK_OK); |
834 ParseScopedStatement(true, CHECK_OK); | 815 ParseScopedStatement(true, CHECK_OK); |
835 return Statement::Default(); | 816 return Statement::Default(); |
836 } | 817 } |
837 } else { | 818 } else { |
838 int lhs_beg_pos = peek_position(); | 819 int lhs_beg_pos = peek_position(); |
839 ExpressionClassifier classifier(this); | 820 ExpressionClassifier classifier(this); |
840 Expression lhs = ParseExpression(false, &classifier, CHECK_OK); | 821 Expression lhs = ParseExpression(false, &classifier, CHECK_OK); |
841 int lhs_end_pos = scanner()->location().end_pos; | 822 int lhs_end_pos = scanner()->location().end_pos; |
842 is_let_identifier_expression = | |
843 lhs.IsIdentifier() && lhs.AsIdentifier().IsLet(); | |
844 bool is_for_each = CheckInOrOf(&mode, ok); | 823 bool is_for_each = CheckInOrOf(&mode, ok); |
845 if (!*ok) return Statement::Default(); | 824 if (!*ok) return Statement::Default(); |
846 bool is_destructuring = is_for_each && | 825 bool is_destructuring = is_for_each && |
847 (lhs->IsArrayLiteral() || lhs->IsObjectLiteral()); | 826 (lhs->IsArrayLiteral() || lhs->IsObjectLiteral()); |
848 | 827 |
849 if (is_destructuring) { | 828 if (is_destructuring) { |
850 ValidateAssignmentPattern(&classifier, CHECK_OK); | 829 ValidateAssignmentPattern(&classifier, CHECK_OK); |
851 } else { | 830 } else { |
852 ValidateExpression(&classifier, CHECK_OK); | 831 ValidateExpression(&classifier, CHECK_OK); |
853 } | 832 } |
(...skipping 14 matching lines...) Expand all Loading... |
868 } | 847 } |
869 | 848 |
870 Expect(Token::RPAREN, CHECK_OK); | 849 Expect(Token::RPAREN, CHECK_OK); |
871 ParseScopedStatement(true, CHECK_OK); | 850 ParseScopedStatement(true, CHECK_OK); |
872 return Statement::Default(); | 851 return Statement::Default(); |
873 } | 852 } |
874 } | 853 } |
875 } | 854 } |
876 | 855 |
877 // Parsed initializer at this point. | 856 // Parsed initializer at this point. |
878 // Detect attempts at 'let' declarations in sloppy mode. | |
879 if (!allow_harmony_sloppy_let() && peek() == Token::IDENTIFIER && | |
880 is_sloppy(language_mode()) && is_let_identifier_expression) { | |
881 ReportMessage(MessageTemplate::kSloppyLexical, NULL); | |
882 *ok = false; | |
883 return Statement::Default(); | |
884 } | |
885 Expect(Token::SEMICOLON, CHECK_OK); | 857 Expect(Token::SEMICOLON, CHECK_OK); |
886 | 858 |
887 if (peek() != Token::SEMICOLON) { | 859 if (peek() != Token::SEMICOLON) { |
888 ParseExpression(true, CHECK_OK); | 860 ParseExpression(true, CHECK_OK); |
889 } | 861 } |
890 Expect(Token::SEMICOLON, CHECK_OK); | 862 Expect(Token::SEMICOLON, CHECK_OK); |
891 | 863 |
892 if (peek() != Token::RPAREN) { | 864 if (peek() != Token::RPAREN) { |
893 ParseExpression(true, CHECK_OK); | 865 ParseExpression(true, CHECK_OK); |
894 } | 866 } |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1152 Expect(Token::RBRACE, CHECK_OK); | 1124 Expect(Token::RBRACE, CHECK_OK); |
1153 return PreParserExpression::Default(); | 1125 return PreParserExpression::Default(); |
1154 } | 1126 } |
1155 } | 1127 } |
1156 | 1128 |
1157 #undef CHECK_OK | 1129 #undef CHECK_OK |
1158 | 1130 |
1159 | 1131 |
1160 } // namespace internal | 1132 } // namespace internal |
1161 } // namespace v8 | 1133 } // namespace v8 |
OLD | NEW |