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

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: rebase 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
« 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 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 410 matching lines...) Expand 10 before | Expand all | Expand 10 after
476 479
477 // The scope of a var/const declared variable anywhere inside a function 480 // The scope of a var/const declared variable anywhere inside a function
478 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope 481 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope
479 // of a let declared variable is the scope of the immediately enclosing 482 // of a let declared variable is the scope of the immediately enclosing
480 // block. 483 // block.
481 int nvars = 0; // the number of variables declared 484 int nvars = 0; // the number of variables declared
482 int bindings_start = peek_position(); 485 int bindings_start = peek_position();
483 do { 486 do {
484 // Parse variable name. 487 // Parse variable name.
485 if (nvars > 0) Consume(Token::COMMA); 488 if (nvars > 0) Consume(Token::COMMA);
486 ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); 489 ParseIdentifier(kDontAllowRestrictedIdentifiers, CHECK_OK);
487 Scanner::Location variable_loc = scanner()->location(); 490 Scanner::Location variable_loc = scanner()->location();
488 nvars++; 491 nvars++;
489 if (peek() == Token::ASSIGN || require_initializer || 492 if (peek() == Token::ASSIGN || require_initializer ||
490 // require initializers for multiple consts. 493 // require initializers for multiple consts.
491 (is_strict_const && peek() == Token::COMMA)) { 494 (is_strict_const && peek() == Token::COMMA)) {
492 Expect(Token::ASSIGN, CHECK_OK); 495 Expect(Token::ASSIGN, CHECK_OK);
493 ParseAssignmentExpression(var_context != kForStatement, CHECK_OK); 496 ParseAssignmentExpression(var_context != kForStatement, CHECK_OK);
494 497
495 variable_loc.end_pos = scanner()->location().end_pos; 498 variable_loc.end_pos = scanner()->location().end_pos;
496 if (first_initializer_loc && !first_initializer_loc->IsValid()) { 499 if (first_initializer_loc && !first_initializer_loc->IsValid()) {
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
581 // ContinueStatement :: 584 // ContinueStatement ::
582 // 'continue' [no line terminator] Identifier? ';' 585 // 'continue' [no line terminator] Identifier? ';'
583 586
584 Expect(Token::CONTINUE, CHECK_OK); 587 Expect(Token::CONTINUE, CHECK_OK);
585 Token::Value tok = peek(); 588 Token::Value tok = peek();
586 if (!scanner()->HasAnyLineTerminatorBeforeNext() && 589 if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
587 tok != Token::SEMICOLON && 590 tok != Token::SEMICOLON &&
588 tok != Token::RBRACE && 591 tok != Token::RBRACE &&
589 tok != Token::EOS) { 592 tok != Token::EOS) {
590 // ECMA allows "eval" or "arguments" as labels even in strict mode. 593 // ECMA allows "eval" or "arguments" as labels even in strict mode.
591 ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); 594 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
592 } 595 }
593 ExpectSemicolon(CHECK_OK); 596 ExpectSemicolon(CHECK_OK);
594 return Statement::Default(); 597 return Statement::Default();
595 } 598 }
596 599
597 600
598 PreParser::Statement PreParser::ParseBreakStatement(bool* ok) { 601 PreParser::Statement PreParser::ParseBreakStatement(bool* ok) {
599 // BreakStatement :: 602 // BreakStatement ::
600 // 'break' [no line terminator] Identifier? ';' 603 // 'break' [no line terminator] Identifier? ';'
601 604
602 Expect(Token::BREAK, CHECK_OK); 605 Expect(Token::BREAK, CHECK_OK);
603 Token::Value tok = peek(); 606 Token::Value tok = peek();
604 if (!scanner()->HasAnyLineTerminatorBeforeNext() && 607 if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
605 tok != Token::SEMICOLON && 608 tok != Token::SEMICOLON &&
606 tok != Token::RBRACE && 609 tok != Token::RBRACE &&
607 tok != Token::EOS) { 610 tok != Token::EOS) {
608 // ECMA allows "eval" or "arguments" as labels even in strict mode. 611 // ECMA allows "eval" or "arguments" as labels even in strict mode.
609 ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); 612 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
610 } 613 }
611 ExpectSemicolon(CHECK_OK); 614 ExpectSemicolon(CHECK_OK);
612 return Statement::Default(); 615 return Statement::Default();
613 } 616 }
614 617
615 618
616 PreParser::Statement PreParser::ParseReturnStatement(bool* ok) { 619 PreParser::Statement PreParser::ParseReturnStatement(bool* ok) {
617 // ReturnStatement :: 620 // ReturnStatement ::
618 // 'return' [no line terminator] Expression? ';' 621 // 'return' [no line terminator] Expression? ';'
619 622
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
846 849
847 Token::Value tok = peek(); 850 Token::Value tok = peek();
848 if (tok != Token::CATCH && tok != Token::FINALLY) { 851 if (tok != Token::CATCH && tok != Token::FINALLY) {
849 ReportMessageAt(scanner()->location(), "no_catch_or_finally"); 852 ReportMessageAt(scanner()->location(), "no_catch_or_finally");
850 *ok = false; 853 *ok = false;
851 return Statement::Default(); 854 return Statement::Default();
852 } 855 }
853 if (tok == Token::CATCH) { 856 if (tok == Token::CATCH) {
854 Consume(Token::CATCH); 857 Consume(Token::CATCH);
855 Expect(Token::LPAREN, CHECK_OK); 858 Expect(Token::LPAREN, CHECK_OK);
856 ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); 859 ParseIdentifier(kDontAllowRestrictedIdentifiers, CHECK_OK);
857 Expect(Token::RPAREN, CHECK_OK); 860 Expect(Token::RPAREN, CHECK_OK);
858 { 861 {
859 Scope* with_scope = NewScope(scope_, WITH_SCOPE); 862 Scope* with_scope = NewScope(scope_, WITH_SCOPE);
860 BlockState block_state(&scope_, with_scope); 863 BlockState block_state(&scope_, with_scope);
861 ParseBlock(CHECK_OK); 864 ParseBlock(CHECK_OK);
862 } 865 }
863 tok = peek(); 866 tok = peek();
864 } 867 }
865 if (tok == Token::FINALLY) { 868 if (tok == Token::FINALLY) {
866 Consume(Token::FINALLY); 869 Consume(Token::FINALLY);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
910 Expect(Token::LPAREN, CHECK_OK); 913 Expect(Token::LPAREN, CHECK_OK);
911 int start_position = position(); 914 int start_position = position();
912 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); 915 DuplicateFinder duplicate_finder(scanner()->unicode_cache());
913 // We don't yet know if the function will be strict, so we cannot yet produce 916 // We don't yet know if the function will be strict, so we cannot yet produce
914 // errors for parameter names or duplicates. However, we remember the 917 // errors for parameter names or duplicates. However, we remember the
915 // locations of these errors if they occur and produce the errors later. 918 // locations of these errors if they occur and produce the errors later.
916 Scanner::Location eval_args_error_loc = Scanner::Location::invalid(); 919 Scanner::Location eval_args_error_loc = Scanner::Location::invalid();
917 Scanner::Location dupe_error_loc = Scanner::Location::invalid(); 920 Scanner::Location dupe_error_loc = Scanner::Location::invalid();
918 Scanner::Location reserved_error_loc = Scanner::Location::invalid(); 921 Scanner::Location reserved_error_loc = Scanner::Location::invalid();
919 922
923 // Similarly for strong mode.
924 Scanner::Location undefined_error_loc = Scanner::Location::invalid();
925
920 bool is_rest = false; 926 bool is_rest = false;
921 bool done = arity_restriction == FunctionLiteral::GETTER_ARITY || 927 bool done = arity_restriction == FunctionLiteral::GETTER_ARITY ||
922 (peek() == Token::RPAREN && 928 (peek() == Token::RPAREN &&
923 arity_restriction != FunctionLiteral::SETTER_ARITY); 929 arity_restriction != FunctionLiteral::SETTER_ARITY);
924 while (!done) { 930 while (!done) {
925 bool is_strict_reserved = false; 931 bool is_strict_reserved = false;
926 is_rest = peek() == Token::ELLIPSIS && allow_harmony_rest_params(); 932 is_rest = peek() == Token::ELLIPSIS && allow_harmony_rest_params();
927 if (is_rest) { 933 if (is_rest) {
928 Consume(Token::ELLIPSIS); 934 Consume(Token::ELLIPSIS);
929 } 935 }
930 936
931 Identifier param_name = 937 Identifier param_name =
932 ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); 938 ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
933 if (!eval_args_error_loc.IsValid() && param_name.IsEvalOrArguments()) { 939 if (!eval_args_error_loc.IsValid() && param_name.IsEvalOrArguments()) {
934 eval_args_error_loc = scanner()->location(); 940 eval_args_error_loc = scanner()->location();
935 } 941 }
942 if (!undefined_error_loc.IsValid() && param_name.IsUndefined()) {
943 undefined_error_loc = scanner()->location();
944 }
936 if (!reserved_error_loc.IsValid() && is_strict_reserved) { 945 if (!reserved_error_loc.IsValid() && is_strict_reserved) {
937 reserved_error_loc = scanner()->location(); 946 reserved_error_loc = scanner()->location();
938 } 947 }
939 948
940 int prev_value = scanner()->FindSymbol(&duplicate_finder, 1); 949 int prev_value = scanner()->FindSymbol(&duplicate_finder, 1);
941 950
942 if (!dupe_error_loc.IsValid() && prev_value != 0) { 951 if (!dupe_error_loc.IsValid() && prev_value != 0) {
943 dupe_error_loc = scanner()->location(); 952 dupe_error_loc = scanner()->location();
944 } 953 }
945 954
(...skipping 23 matching lines...) Expand all
969 ParseStatementList(Token::RBRACE, CHECK_OK); 978 ParseStatementList(Token::RBRACE, CHECK_OK);
970 } 979 }
971 Expect(Token::RBRACE, CHECK_OK); 980 Expect(Token::RBRACE, CHECK_OK);
972 981
973 // Validate name and parameter names. We can do this only after parsing the 982 // Validate name and parameter names. We can do this only after parsing the
974 // function, since the function can declare itself strict. 983 // function, since the function can declare itself strict.
975 CheckFunctionName(language_mode(), kind, function_name, 984 CheckFunctionName(language_mode(), kind, function_name,
976 name_is_strict_reserved, function_name_location, CHECK_OK); 985 name_is_strict_reserved, function_name_location, CHECK_OK);
977 const bool use_strict_params = is_rest || IsConciseMethod(kind); 986 const bool use_strict_params = is_rest || IsConciseMethod(kind);
978 CheckFunctionParameterNames(language_mode(), use_strict_params, 987 CheckFunctionParameterNames(language_mode(), use_strict_params,
979 eval_args_error_loc, dupe_error_loc, 988 eval_args_error_loc, undefined_error_loc,
980 reserved_error_loc, CHECK_OK); 989 dupe_error_loc, reserved_error_loc, CHECK_OK);
981 990
982 if (is_strict(language_mode())) { 991 if (is_strict(language_mode())) {
983 int end_position = scanner()->location().end_pos; 992 int end_position = scanner()->location().end_pos;
984 CheckStrictOctalLiteral(start_position, end_position, CHECK_OK); 993 CheckStrictOctalLiteral(start_position, end_position, CHECK_OK);
985 } 994 }
986 995
987 if (is_strong(language_mode()) && IsSubclassConstructor(kind)) { 996 if (is_strong(language_mode()) && IsSubclassConstructor(kind)) {
988 if (!function_state.super_call_location().IsValid()) { 997 if (!function_state.super_call_location().IsValid()) {
989 ReportMessageAt(function_name_location, "strong_super_call_missing", 998 ReportMessageAt(function_name_location, "strong_super_call_missing",
990 kReferenceError); 999 kReferenceError);
(...skipping 28 matching lines...) Expand all
1019 if (name_is_strict_reserved) { 1028 if (name_is_strict_reserved) {
1020 ReportMessageAt(class_name_location, "unexpected_strict_reserved"); 1029 ReportMessageAt(class_name_location, "unexpected_strict_reserved");
1021 *ok = false; 1030 *ok = false;
1022 return EmptyExpression(); 1031 return EmptyExpression();
1023 } 1032 }
1024 if (IsEvalOrArguments(name)) { 1033 if (IsEvalOrArguments(name)) {
1025 ReportMessageAt(class_name_location, "strict_eval_arguments"); 1034 ReportMessageAt(class_name_location, "strict_eval_arguments");
1026 *ok = false; 1035 *ok = false;
1027 return EmptyExpression(); 1036 return EmptyExpression();
1028 } 1037 }
1038 LanguageMode class_language_mode = language_mode();
1039 if (is_strong(class_language_mode) && IsUndefined(name)) {
1040 ReportMessageAt(class_name_location, "strong_undefined");
1041 *ok = false;
1042 return EmptyExpression();
1043 }
1029 1044
1030 Scope* scope = NewScope(scope_, BLOCK_SCOPE); 1045 Scope* scope = NewScope(scope_, BLOCK_SCOPE);
1031 BlockState block_state(&scope_, scope); 1046 BlockState block_state(&scope_, scope);
1032 scope_->SetLanguageMode( 1047 scope_->SetLanguageMode(
1033 static_cast<LanguageMode>(scope_->language_mode() | STRICT_BIT)); 1048 static_cast<LanguageMode>(class_language_mode | STRICT_BIT));
1034 // TODO(marja): Make PreParser use scope names too. 1049 // TODO(marja): Make PreParser use scope names too.
1035 // scope_->SetScopeName(name); 1050 // scope_->SetScopeName(name);
1036 1051
1037 bool has_extends = Check(Token::EXTENDS); 1052 bool has_extends = Check(Token::EXTENDS);
1038 if (has_extends) { 1053 if (has_extends) {
1039 ParseLeftHandSideExpression(CHECK_OK); 1054 ParseLeftHandSideExpression(CHECK_OK);
1040 } 1055 }
1041 1056
1042 ClassLiteralChecker checker(this); 1057 ClassLiteralChecker checker(this);
1043 bool has_seen_constructor = false; 1058 bool has_seen_constructor = false;
(...skipping 17 matching lines...) Expand all
1061 1076
1062 PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) { 1077 PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) {
1063 // CallRuntime :: 1078 // CallRuntime ::
1064 // '%' Identifier Arguments 1079 // '%' Identifier Arguments
1065 Expect(Token::MOD, CHECK_OK); 1080 Expect(Token::MOD, CHECK_OK);
1066 if (!allow_natives()) { 1081 if (!allow_natives()) {
1067 *ok = false; 1082 *ok = false;
1068 return Expression::Default(); 1083 return Expression::Default();
1069 } 1084 }
1070 // Allow "eval" or "arguments" for backward compatibility. 1085 // Allow "eval" or "arguments" for backward compatibility.
1071 ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); 1086 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
1072 Scanner::Location spread_pos; 1087 Scanner::Location spread_pos;
1073 ParseArguments(&spread_pos, ok); 1088 ParseArguments(&spread_pos, ok);
1074 1089
1075 DCHECK(!spread_pos.IsValid()); 1090 DCHECK(!spread_pos.IsValid());
1076 1091
1077 return Expression::Default(); 1092 return Expression::Default();
1078 } 1093 }
1079 1094
1080 #undef CHECK_OK 1095 #undef CHECK_OK
1081 1096
1082 1097
1083 } } // v8::internal 1098 } } // v8::internal
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