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

Side by Side Diff: src/preparser.cc

Issue 1070633002: [strong] Implement static restrictions on binding/assignment to 'undefined' identifier. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 8 months 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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698