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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 return PreParserIdentifier::Static(); | 46 return PreParserIdentifier::Static(); |
47 } else if (scanner->current_token() == Token::YIELD) { | 47 } else if (scanner->current_token() == Token::YIELD) { |
48 return PreParserIdentifier::Yield(); | 48 return PreParserIdentifier::Yield(); |
49 } | 49 } |
50 if (scanner->UnescapedLiteralMatches("eval", 4)) { | 50 if (scanner->UnescapedLiteralMatches("eval", 4)) { |
51 return PreParserIdentifier::Eval(); | 51 return PreParserIdentifier::Eval(); |
52 } | 52 } |
53 if (scanner->UnescapedLiteralMatches("arguments", 9)) { | 53 if (scanner->UnescapedLiteralMatches("arguments", 9)) { |
54 return PreParserIdentifier::Arguments(); | 54 return PreParserIdentifier::Arguments(); |
55 } | 55 } |
| 56 if (scanner->UnescapedLiteralMatches("undefined", 9)) { |
| 57 return PreParserIdentifier::Undefined(); |
| 58 } |
56 if (scanner->LiteralMatches("prototype", 9)) { | 59 if (scanner->LiteralMatches("prototype", 9)) { |
57 return PreParserIdentifier::Prototype(); | 60 return PreParserIdentifier::Prototype(); |
58 } | 61 } |
59 if (scanner->LiteralMatches("constructor", 11)) { | 62 if (scanner->LiteralMatches("constructor", 11)) { |
60 return PreParserIdentifier::Constructor(); | 63 return PreParserIdentifier::Constructor(); |
61 } | 64 } |
62 return PreParserIdentifier::Default(); | 65 return PreParserIdentifier::Default(); |
63 } | 66 } |
64 | 67 |
65 | 68 |
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
474 } | 477 } |
475 | 478 |
476 // The scope of a var/const declared variable anywhere inside a function | 479 // The scope of a var/const declared variable anywhere inside a function |
477 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope | 480 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope |
478 // of a let declared variable is the scope of the immediately enclosing | 481 // of a let declared variable is the scope of the immediately enclosing |
479 // block. | 482 // block. |
480 int nvars = 0; // the number of variables declared | 483 int nvars = 0; // the number of variables declared |
481 do { | 484 do { |
482 // Parse variable name. | 485 // Parse variable name. |
483 if (nvars > 0) Consume(Token::COMMA); | 486 if (nvars > 0) Consume(Token::COMMA); |
484 ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); | 487 ParseIdentifier(kDontAllowRestrictedIdentifiers, CHECK_OK); |
485 Scanner::Location variable_loc = scanner()->location(); | 488 Scanner::Location variable_loc = scanner()->location(); |
486 nvars++; | 489 nvars++; |
487 if (peek() == Token::ASSIGN || require_initializer || | 490 if (peek() == Token::ASSIGN || require_initializer || |
488 // require initializers for multiple consts. | 491 // require initializers for multiple consts. |
489 (is_strict_const && peek() == Token::COMMA)) { | 492 (is_strict_const && peek() == Token::COMMA)) { |
490 Expect(Token::ASSIGN, CHECK_OK); | 493 Expect(Token::ASSIGN, CHECK_OK); |
491 ParseAssignmentExpression(var_context != kForStatement, CHECK_OK); | 494 ParseAssignmentExpression(var_context != kForStatement, CHECK_OK); |
492 | 495 |
493 variable_loc.end_pos = scanner()->location().end_pos; | 496 variable_loc.end_pos = scanner()->location().end_pos; |
494 if (first_initializer_loc && !first_initializer_loc->IsValid()) { | 497 if (first_initializer_loc && !first_initializer_loc->IsValid()) { |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
574 // ContinueStatement :: | 577 // ContinueStatement :: |
575 // 'continue' [no line terminator] Identifier? ';' | 578 // 'continue' [no line terminator] Identifier? ';' |
576 | 579 |
577 Expect(Token::CONTINUE, CHECK_OK); | 580 Expect(Token::CONTINUE, CHECK_OK); |
578 Token::Value tok = peek(); | 581 Token::Value tok = peek(); |
579 if (!scanner()->HasAnyLineTerminatorBeforeNext() && | 582 if (!scanner()->HasAnyLineTerminatorBeforeNext() && |
580 tok != Token::SEMICOLON && | 583 tok != Token::SEMICOLON && |
581 tok != Token::RBRACE && | 584 tok != Token::RBRACE && |
582 tok != Token::EOS) { | 585 tok != Token::EOS) { |
583 // ECMA allows "eval" or "arguments" as labels even in strict mode. | 586 // ECMA allows "eval" or "arguments" as labels even in strict mode. |
584 ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); | 587 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); |
585 } | 588 } |
586 ExpectSemicolon(CHECK_OK); | 589 ExpectSemicolon(CHECK_OK); |
587 return Statement::Default(); | 590 return Statement::Default(); |
588 } | 591 } |
589 | 592 |
590 | 593 |
591 PreParser::Statement PreParser::ParseBreakStatement(bool* ok) { | 594 PreParser::Statement PreParser::ParseBreakStatement(bool* ok) { |
592 // BreakStatement :: | 595 // BreakStatement :: |
593 // 'break' [no line terminator] Identifier? ';' | 596 // 'break' [no line terminator] Identifier? ';' |
594 | 597 |
595 Expect(Token::BREAK, CHECK_OK); | 598 Expect(Token::BREAK, CHECK_OK); |
596 Token::Value tok = peek(); | 599 Token::Value tok = peek(); |
597 if (!scanner()->HasAnyLineTerminatorBeforeNext() && | 600 if (!scanner()->HasAnyLineTerminatorBeforeNext() && |
598 tok != Token::SEMICOLON && | 601 tok != Token::SEMICOLON && |
599 tok != Token::RBRACE && | 602 tok != Token::RBRACE && |
600 tok != Token::EOS) { | 603 tok != Token::EOS) { |
601 // ECMA allows "eval" or "arguments" as labels even in strict mode. | 604 // ECMA allows "eval" or "arguments" as labels even in strict mode. |
602 ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); | 605 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); |
603 } | 606 } |
604 ExpectSemicolon(CHECK_OK); | 607 ExpectSemicolon(CHECK_OK); |
605 return Statement::Default(); | 608 return Statement::Default(); |
606 } | 609 } |
607 | 610 |
608 | 611 |
609 PreParser::Statement PreParser::ParseReturnStatement(bool* ok) { | 612 PreParser::Statement PreParser::ParseReturnStatement(bool* ok) { |
610 // ReturnStatement :: | 613 // ReturnStatement :: |
611 // 'return' [no line terminator] Expression? ';' | 614 // 'return' [no line terminator] Expression? ';' |
612 | 615 |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
832 | 835 |
833 Token::Value tok = peek(); | 836 Token::Value tok = peek(); |
834 if (tok != Token::CATCH && tok != Token::FINALLY) { | 837 if (tok != Token::CATCH && tok != Token::FINALLY) { |
835 ReportMessageAt(scanner()->location(), "no_catch_or_finally"); | 838 ReportMessageAt(scanner()->location(), "no_catch_or_finally"); |
836 *ok = false; | 839 *ok = false; |
837 return Statement::Default(); | 840 return Statement::Default(); |
838 } | 841 } |
839 if (tok == Token::CATCH) { | 842 if (tok == Token::CATCH) { |
840 Consume(Token::CATCH); | 843 Consume(Token::CATCH); |
841 Expect(Token::LPAREN, CHECK_OK); | 844 Expect(Token::LPAREN, CHECK_OK); |
842 ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); | 845 ParseIdentifier(kDontAllowRestrictedIdentifiers, CHECK_OK); |
843 Expect(Token::RPAREN, CHECK_OK); | 846 Expect(Token::RPAREN, CHECK_OK); |
844 { | 847 { |
845 Scope* with_scope = NewScope(scope_, WITH_SCOPE); | 848 Scope* with_scope = NewScope(scope_, WITH_SCOPE); |
846 BlockState block_state(&scope_, with_scope); | 849 BlockState block_state(&scope_, with_scope); |
847 ParseBlock(CHECK_OK); | 850 ParseBlock(CHECK_OK); |
848 } | 851 } |
849 tok = peek(); | 852 tok = peek(); |
850 } | 853 } |
851 if (tok == Token::FINALLY) { | 854 if (tok == Token::FINALLY) { |
852 Consume(Token::FINALLY); | 855 Consume(Token::FINALLY); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
896 Expect(Token::LPAREN, CHECK_OK); | 899 Expect(Token::LPAREN, CHECK_OK); |
897 int start_position = position(); | 900 int start_position = position(); |
898 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); | 901 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); |
899 // We don't yet know if the function will be strict, so we cannot yet produce | 902 // We don't yet know if the function will be strict, so we cannot yet produce |
900 // errors for parameter names or duplicates. However, we remember the | 903 // errors for parameter names or duplicates. However, we remember the |
901 // locations of these errors if they occur and produce the errors later. | 904 // locations of these errors if they occur and produce the errors later. |
902 Scanner::Location eval_args_error_loc = Scanner::Location::invalid(); | 905 Scanner::Location eval_args_error_loc = Scanner::Location::invalid(); |
903 Scanner::Location dupe_error_loc = Scanner::Location::invalid(); | 906 Scanner::Location dupe_error_loc = Scanner::Location::invalid(); |
904 Scanner::Location reserved_error_loc = Scanner::Location::invalid(); | 907 Scanner::Location reserved_error_loc = Scanner::Location::invalid(); |
905 | 908 |
| 909 // Similarly for strong mode. |
| 910 Scanner::Location undefined_error_loc = Scanner::Location::invalid(); |
| 911 |
906 bool is_rest = false; | 912 bool is_rest = false; |
907 bool done = arity_restriction == FunctionLiteral::GETTER_ARITY || | 913 bool done = arity_restriction == FunctionLiteral::GETTER_ARITY || |
908 (peek() == Token::RPAREN && | 914 (peek() == Token::RPAREN && |
909 arity_restriction != FunctionLiteral::SETTER_ARITY); | 915 arity_restriction != FunctionLiteral::SETTER_ARITY); |
910 while (!done) { | 916 while (!done) { |
911 bool is_strict_reserved = false; | 917 bool is_strict_reserved = false; |
912 is_rest = peek() == Token::ELLIPSIS && allow_harmony_rest_params(); | 918 is_rest = peek() == Token::ELLIPSIS && allow_harmony_rest_params(); |
913 if (is_rest) { | 919 if (is_rest) { |
914 Consume(Token::ELLIPSIS); | 920 Consume(Token::ELLIPSIS); |
915 } | 921 } |
916 | 922 |
917 Identifier param_name = | 923 Identifier param_name = |
918 ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); | 924 ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); |
919 if (!eval_args_error_loc.IsValid() && param_name.IsEvalOrArguments()) { | 925 if (!eval_args_error_loc.IsValid() && param_name.IsEvalOrArguments()) { |
920 eval_args_error_loc = scanner()->location(); | 926 eval_args_error_loc = scanner()->location(); |
921 } | 927 } |
| 928 if (!undefined_error_loc.IsValid() && param_name.IsUndefined()) { |
| 929 undefined_error_loc = scanner()->location(); |
| 930 } |
922 if (!reserved_error_loc.IsValid() && is_strict_reserved) { | 931 if (!reserved_error_loc.IsValid() && is_strict_reserved) { |
923 reserved_error_loc = scanner()->location(); | 932 reserved_error_loc = scanner()->location(); |
924 } | 933 } |
925 | 934 |
926 int prev_value = scanner()->FindSymbol(&duplicate_finder, 1); | 935 int prev_value = scanner()->FindSymbol(&duplicate_finder, 1); |
927 | 936 |
928 if (!dupe_error_loc.IsValid() && prev_value != 0) { | 937 if (!dupe_error_loc.IsValid() && prev_value != 0) { |
929 dupe_error_loc = scanner()->location(); | 938 dupe_error_loc = scanner()->location(); |
930 } | 939 } |
931 | 940 |
(...skipping 23 matching lines...) Expand all Loading... |
955 ParseStatementList(Token::RBRACE, CHECK_OK); | 964 ParseStatementList(Token::RBRACE, CHECK_OK); |
956 } | 965 } |
957 Expect(Token::RBRACE, CHECK_OK); | 966 Expect(Token::RBRACE, CHECK_OK); |
958 | 967 |
959 // Validate name and parameter names. We can do this only after parsing the | 968 // Validate name and parameter names. We can do this only after parsing the |
960 // function, since the function can declare itself strict. | 969 // function, since the function can declare itself strict. |
961 CheckFunctionName(language_mode(), kind, function_name, | 970 CheckFunctionName(language_mode(), kind, function_name, |
962 name_is_strict_reserved, function_name_location, CHECK_OK); | 971 name_is_strict_reserved, function_name_location, CHECK_OK); |
963 const bool use_strict_params = is_rest || IsConciseMethod(kind); | 972 const bool use_strict_params = is_rest || IsConciseMethod(kind); |
964 CheckFunctionParameterNames(language_mode(), use_strict_params, | 973 CheckFunctionParameterNames(language_mode(), use_strict_params, |
965 eval_args_error_loc, dupe_error_loc, | 974 eval_args_error_loc, undefined_error_loc, |
966 reserved_error_loc, CHECK_OK); | 975 dupe_error_loc, reserved_error_loc, CHECK_OK); |
967 | 976 |
968 if (is_strict(language_mode())) { | 977 if (is_strict(language_mode())) { |
969 int end_position = scanner()->location().end_pos; | 978 int end_position = scanner()->location().end_pos; |
970 CheckStrictOctalLiteral(start_position, end_position, CHECK_OK); | 979 CheckStrictOctalLiteral(start_position, end_position, CHECK_OK); |
971 } | 980 } |
972 | 981 |
973 if (is_strong(language_mode()) && IsSubclassConstructor(kind)) { | 982 if (is_strong(language_mode()) && IsSubclassConstructor(kind)) { |
974 if (!function_state.super_call_location().IsValid()) { | 983 if (!function_state.super_call_location().IsValid()) { |
975 ReportMessageAt(function_name_location, "strong_super_call_missing", | 984 ReportMessageAt(function_name_location, "strong_super_call_missing", |
976 kReferenceError); | 985 kReferenceError); |
(...skipping 28 matching lines...) Expand all Loading... |
1005 if (name_is_strict_reserved) { | 1014 if (name_is_strict_reserved) { |
1006 ReportMessageAt(class_name_location, "unexpected_strict_reserved"); | 1015 ReportMessageAt(class_name_location, "unexpected_strict_reserved"); |
1007 *ok = false; | 1016 *ok = false; |
1008 return EmptyExpression(); | 1017 return EmptyExpression(); |
1009 } | 1018 } |
1010 if (IsEvalOrArguments(name)) { | 1019 if (IsEvalOrArguments(name)) { |
1011 ReportMessageAt(class_name_location, "strict_eval_arguments"); | 1020 ReportMessageAt(class_name_location, "strict_eval_arguments"); |
1012 *ok = false; | 1021 *ok = false; |
1013 return EmptyExpression(); | 1022 return EmptyExpression(); |
1014 } | 1023 } |
| 1024 LanguageMode class_language_mode = language_mode(); |
| 1025 if (is_strong(class_language_mode) && IsUndefined(name)) { |
| 1026 ReportMessageAt(class_name_location, "strong_undefined"); |
| 1027 *ok = false; |
| 1028 return EmptyExpression(); |
| 1029 } |
1015 | 1030 |
1016 Scope* scope = NewScope(scope_, BLOCK_SCOPE); | 1031 Scope* scope = NewScope(scope_, BLOCK_SCOPE); |
1017 BlockState block_state(&scope_, scope); | 1032 BlockState block_state(&scope_, scope); |
1018 scope_->SetLanguageMode( | 1033 scope_->SetLanguageMode( |
1019 static_cast<LanguageMode>(scope_->language_mode() | STRICT_BIT)); | 1034 static_cast<LanguageMode>(class_language_mode | STRICT_BIT)); |
1020 // TODO(marja): Make PreParser use scope names too. | 1035 // TODO(marja): Make PreParser use scope names too. |
1021 // scope_->SetScopeName(name); | 1036 // scope_->SetScopeName(name); |
1022 | 1037 |
1023 bool has_extends = Check(Token::EXTENDS); | 1038 bool has_extends = Check(Token::EXTENDS); |
1024 if (has_extends) { | 1039 if (has_extends) { |
1025 ParseLeftHandSideExpression(CHECK_OK); | 1040 ParseLeftHandSideExpression(CHECK_OK); |
1026 } | 1041 } |
1027 | 1042 |
1028 ClassLiteralChecker checker(this); | 1043 ClassLiteralChecker checker(this); |
1029 bool has_seen_constructor = false; | 1044 bool has_seen_constructor = false; |
(...skipping 17 matching lines...) Expand all Loading... |
1047 | 1062 |
1048 PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) { | 1063 PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) { |
1049 // CallRuntime :: | 1064 // CallRuntime :: |
1050 // '%' Identifier Arguments | 1065 // '%' Identifier Arguments |
1051 Expect(Token::MOD, CHECK_OK); | 1066 Expect(Token::MOD, CHECK_OK); |
1052 if (!allow_natives()) { | 1067 if (!allow_natives()) { |
1053 *ok = false; | 1068 *ok = false; |
1054 return Expression::Default(); | 1069 return Expression::Default(); |
1055 } | 1070 } |
1056 // Allow "eval" or "arguments" for backward compatibility. | 1071 // Allow "eval" or "arguments" for backward compatibility. |
1057 ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); | 1072 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); |
1058 ParseArguments(ok); | 1073 ParseArguments(ok); |
1059 | 1074 |
1060 return Expression::Default(); | 1075 return Expression::Default(); |
1061 } | 1076 } |
1062 | 1077 |
1063 #undef CHECK_OK | 1078 #undef CHECK_OK |
1064 | 1079 |
1065 | 1080 |
1066 } } // v8::internal | 1081 } } // v8::internal |
OLD | NEW |