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

Side by Side Diff: src/parsing/parser-base.h

Issue 2255353002: [parser] Allow duplicate __proto__ keys in patterns (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: review comments Created 4 years, 4 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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 #ifndef V8_PARSING_PARSER_BASE_H 5 #ifndef V8_PARSING_PARSER_BASE_H
6 #define V8_PARSING_PARSER_BASE_H 6 #define V8_PARSING_PARSER_BASE_H
7 7
8 #include "src/ast/scopes.h" 8 #include "src/ast/scopes.h"
9 #include "src/bailout-reason.h" 9 #include "src/bailout-reason.h"
10 #include "src/base/hashmap.h" 10 #include "src/base/hashmap.h"
(...skipping 891 matching lines...) Expand 10 before | Expand all | Expand 10 after
902 Scanner::Location location, Token::Value token, 902 Scanner::Location location, Token::Value token,
903 MessageTemplate::Template message = MessageTemplate::kUnexpectedToken); 903 MessageTemplate::Template message = MessageTemplate::kUnexpectedToken);
904 904
905 void ReportClassifierError( 905 void ReportClassifierError(
906 const typename ExpressionClassifier::Error& error) { 906 const typename ExpressionClassifier::Error& error) {
907 Traits::ReportMessageAt(error.location, error.message, error.arg, 907 Traits::ReportMessageAt(error.location, error.message, error.arg,
908 error.type); 908 error.type);
909 } 909 }
910 910
911 void ValidateExpression(const ExpressionClassifier* classifier, bool* ok) { 911 void ValidateExpression(const ExpressionClassifier* classifier, bool* ok) {
912 if (!classifier->is_valid_expression() || 912 if (!classifier->is_valid_expression()) {
913 classifier->has_cover_initialized_name()) {
914 const Scanner::Location& a = classifier->expression_error().location;
915 const Scanner::Location& b =
916 classifier->cover_initialized_name_error().location;
917 if (a.beg_pos < 0 || (b.beg_pos >= 0 && a.beg_pos > b.beg_pos)) {
adamk 2016/08/19 20:17:08 Ugh, I forgot about this logic, it's trying to det
caitp 2016/08/19 23:11:19 IIRC, the reason for this is related to how arrow
gsathya 2016/08/19 23:22:57 I combined CoverInitializedName with this for now.
918 ReportClassifierError(classifier->cover_initialized_name_error());
919 } else {
920 ReportClassifierError(classifier->expression_error()); 913 ReportClassifierError(classifier->expression_error());
921 } 914 *ok = false;
915 }
916
917 if (classifier->has_cover_initialized_name()) {
918 ReportClassifierError(classifier->cover_initialized_name_error());
919 *ok = false;
920 }
921
922 if (classifier->has_annexb_duplicate_proto()) {
923 ReportClassifierError(classifier->annexb_duplicate_proto_error());
922 *ok = false; 924 *ok = false;
923 } 925 }
924 } 926 }
925 927
926 void ValidateFormalParameterInitializer( 928 void ValidateFormalParameterInitializer(
927 const ExpressionClassifier* classifier, bool* ok) { 929 const ExpressionClassifier* classifier, bool* ok) {
928 if (!classifier->is_valid_formal_parameter_initializer()) { 930 if (!classifier->is_valid_formal_parameter_initializer()) {
929 ReportClassifierError(classifier->formal_parameter_initializer_error()); 931 ReportClassifierError(classifier->formal_parameter_initializer_error());
930 *ok = false; 932 *ok = false;
931 } 933 }
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
1195 kAccessorProperty, 1197 kAccessorProperty,
1196 kValueProperty, 1198 kValueProperty,
1197 kMethodProperty 1199 kMethodProperty
1198 }; 1200 };
1199 1201
1200 class ObjectLiteralCheckerBase { 1202 class ObjectLiteralCheckerBase {
1201 public: 1203 public:
1202 explicit ObjectLiteralCheckerBase(ParserBase* parser) : parser_(parser) {} 1204 explicit ObjectLiteralCheckerBase(ParserBase* parser) : parser_(parser) {}
1203 1205
1204 virtual void CheckProperty(Token::Value property, PropertyKind type, 1206 virtual void CheckProperty(Token::Value property, PropertyKind type,
1205 MethodKind method_type, bool* ok) = 0; 1207 MethodKind method_type,
1208 ExpressionClassifier* classifier, bool* ok) = 0;
1206 1209
1207 virtual ~ObjectLiteralCheckerBase() {} 1210 virtual ~ObjectLiteralCheckerBase() {}
1208 1211
1209 protected: 1212 protected:
1210 ParserBase* parser() const { return parser_; } 1213 ParserBase* parser() const { return parser_; }
1211 Scanner* scanner() const { return parser_->scanner(); } 1214 Scanner* scanner() const { return parser_->scanner(); }
1212 1215
1213 private: 1216 private:
1214 ParserBase* parser_; 1217 ParserBase* parser_;
1215 }; 1218 };
1216 1219
1217 // Validation per ES6 object literals. 1220 // Validation per ES6 object literals.
1218 class ObjectLiteralChecker : public ObjectLiteralCheckerBase { 1221 class ObjectLiteralChecker : public ObjectLiteralCheckerBase {
1219 public: 1222 public:
1220 explicit ObjectLiteralChecker(ParserBase* parser) 1223 explicit ObjectLiteralChecker(ParserBase* parser)
1221 : ObjectLiteralCheckerBase(parser), has_seen_proto_(false) {} 1224 : ObjectLiteralCheckerBase(parser), has_seen_proto_(false) {}
1222 1225
1223 void CheckProperty(Token::Value property, PropertyKind type, 1226 void CheckProperty(Token::Value property, PropertyKind type,
1224 MethodKind method_type, bool* ok) override; 1227 MethodKind method_type, ExpressionClassifier* classifier,
1228 bool* ok) override;
1225 1229
1226 private: 1230 private:
1227 bool IsProto() { return this->scanner()->LiteralMatches("__proto__", 9); } 1231 bool IsProto() { return this->scanner()->LiteralMatches("__proto__", 9); }
1228 1232
1229 bool has_seen_proto_; 1233 bool has_seen_proto_;
1230 }; 1234 };
1231 1235
1232 // Validation per ES6 class literals. 1236 // Validation per ES6 class literals.
1233 class ClassLiteralChecker : public ObjectLiteralCheckerBase { 1237 class ClassLiteralChecker : public ObjectLiteralCheckerBase {
1234 public: 1238 public:
1235 explicit ClassLiteralChecker(ParserBase* parser) 1239 explicit ClassLiteralChecker(ParserBase* parser)
1236 : ObjectLiteralCheckerBase(parser), has_seen_constructor_(false) {} 1240 : ObjectLiteralCheckerBase(parser), has_seen_constructor_(false) {}
1237 1241
1238 void CheckProperty(Token::Value property, PropertyKind type, 1242 void CheckProperty(Token::Value property, PropertyKind type,
1239 MethodKind method_type, bool* ok) override; 1243 MethodKind method_type, ExpressionClassifier* classifier,
1244 bool* ok) override;
1240 1245
1241 private: 1246 private:
1242 bool IsConstructor() { 1247 bool IsConstructor() {
1243 return this->scanner()->LiteralMatches("constructor", 11); 1248 return this->scanner()->LiteralMatches("constructor", 11);
1244 } 1249 }
1245 bool IsPrototype() { 1250 bool IsPrototype() {
1246 return this->scanner()->LiteralMatches("prototype", 9); 1251 return this->scanner()->LiteralMatches("prototype", 9);
1247 } 1252 }
1248 1253
1249 bool has_seen_constructor_; 1254 bool has_seen_constructor_;
(...skipping 723 matching lines...) Expand 10 before | Expand all | Expand 10 after
1973 this->PushLiteralName(fni_, *name); 1978 this->PushLiteralName(fni_, *name);
1974 } 1979 }
1975 1980
1976 if (!in_class && !is_generator) { 1981 if (!in_class && !is_generator) {
1977 DCHECK(!IsStaticMethod(method_kind)); 1982 DCHECK(!IsStaticMethod(method_kind));
1978 if (peek() == Token::COLON) { 1983 if (peek() == Token::COLON) {
1979 // PropertyDefinition 1984 // PropertyDefinition
1980 // PropertyName ':' AssignmentExpression 1985 // PropertyName ':' AssignmentExpression
1981 if (!*is_computed_name) { 1986 if (!*is_computed_name) {
1982 checker->CheckProperty(name_token, kValueProperty, MethodKind::kNormal, 1987 checker->CheckProperty(name_token, kValueProperty, MethodKind::kNormal,
1988 classifier,
1983 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); 1989 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
1984 } 1990 }
1985 Consume(Token::COLON); 1991 Consume(Token::COLON);
1986 int beg_pos = peek_position(); 1992 int beg_pos = peek_position();
1987 ExpressionT value = this->ParseAssignmentExpression( 1993 ExpressionT value = this->ParseAssignmentExpression(
1988 true, classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); 1994 true, classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
1989 CheckDestructuringElement(value, classifier, beg_pos, 1995 CheckDestructuringElement(value, classifier, beg_pos,
1990 scanner()->location().end_pos); 1996 scanner()->location().end_pos);
1991 1997
1992 return factory()->NewObjectLiteralProperty(name_expression, value, 1998 return factory()->NewObjectLiteralProperty(name_expression, value,
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
2073 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); 2079 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
2074 method_kind |= MethodKind::kAsync; 2080 method_kind |= MethodKind::kAsync;
2075 } 2081 }
2076 2082
2077 if (is_generator || peek() == Token::LPAREN) { 2083 if (is_generator || peek() == Token::LPAREN) {
2078 // MethodDefinition 2084 // MethodDefinition
2079 // PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}' 2085 // PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}'
2080 // '*' PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}' 2086 // '*' PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}'
2081 if (!*is_computed_name) { 2087 if (!*is_computed_name) {
2082 checker->CheckProperty(name_token, kMethodProperty, method_kind, 2088 checker->CheckProperty(name_token, kMethodProperty, method_kind,
2089 classifier,
2083 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); 2090 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
2084 } 2091 }
2085 2092
2086 FunctionKind kind = is_generator 2093 FunctionKind kind = is_generator
2087 ? FunctionKind::kConciseGeneratorMethod 2094 ? FunctionKind::kConciseGeneratorMethod
2088 : is_async ? FunctionKind::kAsyncConciseMethod 2095 : is_async ? FunctionKind::kAsyncConciseMethod
2089 : FunctionKind::kConciseMethod; 2096 : FunctionKind::kConciseMethod;
2090 2097
2091 if (in_class && !IsStaticMethod(method_kind) && 2098 if (in_class && !IsStaticMethod(method_kind) &&
2092 this->IsConstructor(*name)) { 2099 this->IsConstructor(*name)) {
(...skipping 30 matching lines...) Expand all
2123 *name = this->EmptyIdentifier(); 2130 *name = this->EmptyIdentifier();
2124 bool dont_care = false; 2131 bool dont_care = false;
2125 name_token = peek(); 2132 name_token = peek();
2126 2133
2127 name_expression = ParsePropertyName( 2134 name_expression = ParsePropertyName(
2128 name, &dont_care, &dont_care, &dont_care, is_computed_name, classifier, 2135 name, &dont_care, &dont_care, &dont_care, is_computed_name, classifier,
2129 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); 2136 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
2130 2137
2131 if (!*is_computed_name) { 2138 if (!*is_computed_name) {
2132 checker->CheckProperty(name_token, kAccessorProperty, method_kind, 2139 checker->CheckProperty(name_token, kAccessorProperty, method_kind,
2140 classifier,
2133 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); 2141 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
2134 } 2142 }
2135 2143
2136 typename Traits::Type::FunctionLiteral value = this->ParseFunctionLiteral( 2144 typename Traits::Type::FunctionLiteral value = this->ParseFunctionLiteral(
2137 *name, scanner()->location(), kSkipFunctionNameCheck, 2145 *name, scanner()->location(), kSkipFunctionNameCheck,
2138 is_get ? FunctionKind::kGetterFunction : FunctionKind::kSetterFunction, 2146 is_get ? FunctionKind::kGetterFunction : FunctionKind::kSetterFunction,
2139 kNoSourcePosition, FunctionLiteral::kAccessorOrMethod, language_mode(), 2147 kNoSourcePosition, FunctionLiteral::kAccessorOrMethod, language_mode(),
2140 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); 2148 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
2141 2149
2142 // Make sure the name expression is a string since we need a Name for 2150 // Make sure the name expression is a string since we need a Name for
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after
2410 2418
2411 // "expression" was not itself an arrow function parameter list, but it might 2419 // "expression" was not itself an arrow function parameter list, but it might
2412 // form part of one. Propagate speculative formal parameter error locations. 2420 // form part of one. Propagate speculative formal parameter error locations.
2413 // Do not merge pending non-pattern expressions yet! 2421 // Do not merge pending non-pattern expressions yet!
2414 classifier->Accumulate( 2422 classifier->Accumulate(
2415 &arrow_formals_classifier, 2423 &arrow_formals_classifier,
2416 ExpressionClassifier::ExpressionProductions | 2424 ExpressionClassifier::ExpressionProductions |
2417 ExpressionClassifier::PatternProductions | 2425 ExpressionClassifier::PatternProductions |
2418 ExpressionClassifier::FormalParametersProductions | 2426 ExpressionClassifier::FormalParametersProductions |
2419 ExpressionClassifier::CoverInitializedNameProduction | 2427 ExpressionClassifier::CoverInitializedNameProduction |
2428 ExpressionClassifier::AnnexBDuplicateProtoProduction |
2420 ExpressionClassifier::AsyncArrowFormalParametersProduction, 2429 ExpressionClassifier::AsyncArrowFormalParametersProduction,
2421 false); 2430 false);
2422 2431
2423 if (!Token::IsAssignmentOp(peek())) { 2432 if (!Token::IsAssignmentOp(peek())) {
2424 // Parsed conditional expression only (no assignment). 2433 // Parsed conditional expression only (no assignment).
2425 // Now pending non-pattern expressions must be merged. 2434 // Now pending non-pattern expressions must be merged.
2426 classifier->MergeNonPatterns(&arrow_formals_classifier); 2435 classifier->MergeNonPatterns(&arrow_formals_classifier);
2427 return expression; 2436 return expression;
2428 } 2437 }
2429 2438
2430 // Now pending non-pattern expressions must be discarded. 2439 // Now pending non-pattern expressions must be discarded.
2431 arrow_formals_classifier.Discard(); 2440 arrow_formals_classifier.Discard();
2432 2441
2433 CheckNoTailCallExpressions(classifier, CHECK_OK); 2442 CheckNoTailCallExpressions(classifier, CHECK_OK);
2434 2443
2435 if (IsValidPattern(expression) && peek() == Token::ASSIGN) { 2444 if (IsValidPattern(expression) && peek() == Token::ASSIGN) {
2436 classifier->ForgiveCoverInitializedNameError(); 2445 classifier->ForgiveCoverInitializedNameError();
2446 classifier->ForgiveAnnexBDuplicateProtoError();
2437 ValidateAssignmentPattern(classifier, CHECK_OK); 2447 ValidateAssignmentPattern(classifier, CHECK_OK);
2438 is_destructuring_assignment = true; 2448 is_destructuring_assignment = true;
2439 } else { 2449 } else {
2440 expression = this->CheckAndRewriteReferenceExpression( 2450 expression = this->CheckAndRewriteReferenceExpression(
2441 expression, lhs_beg_pos, scanner()->location().end_pos, 2451 expression, lhs_beg_pos, scanner()->location().end_pos,
2442 MessageTemplate::kInvalidLhsInAssignment, CHECK_OK); 2452 MessageTemplate::kInvalidLhsInAssignment, CHECK_OK);
2443 } 2453 }
2444 2454
2445 expression = this->MarkExpressionAsAssigned(expression); 2455 expression = this->MarkExpressionAsAssigned(expression);
2446 2456
2447 Token::Value op = Next(); // Get assignment operator. 2457 Token::Value op = Next(); // Get assignment operator.
2448 if (op != Token::ASSIGN) { 2458 if (op != Token::ASSIGN) {
2449 classifier->RecordPatternError(scanner()->location(), 2459 classifier->RecordPatternError(scanner()->location(),
2450 MessageTemplate::kUnexpectedToken, 2460 MessageTemplate::kUnexpectedToken,
2451 Token::String(op)); 2461 Token::String(op));
2452 } 2462 }
2453 int pos = position(); 2463 int pos = position();
2454 2464
2455 ExpressionClassifier rhs_classifier(this); 2465 ExpressionClassifier rhs_classifier(this);
2456 2466
2457 ExpressionT right = 2467 ExpressionT right =
2458 this->ParseAssignmentExpression(accept_IN, &rhs_classifier, CHECK_OK); 2468 this->ParseAssignmentExpression(accept_IN, &rhs_classifier, CHECK_OK);
2459 CheckNoTailCallExpressions(&rhs_classifier, CHECK_OK); 2469 CheckNoTailCallExpressions(&rhs_classifier, CHECK_OK);
2460 Traits::RewriteNonPattern(&rhs_classifier, CHECK_OK); 2470 Traits::RewriteNonPattern(&rhs_classifier, CHECK_OK);
2461 classifier->Accumulate( 2471 classifier->Accumulate(
2462 &rhs_classifier, 2472 &rhs_classifier,
2463 ExpressionClassifier::ExpressionProductions | 2473 ExpressionClassifier::ExpressionProductions |
2464 ExpressionClassifier::CoverInitializedNameProduction | 2474 ExpressionClassifier::CoverInitializedNameProduction |
2475 ExpressionClassifier::AnnexBDuplicateProtoProduction |
2465 ExpressionClassifier::AsyncArrowFormalParametersProduction); 2476 ExpressionClassifier::AsyncArrowFormalParametersProduction);
2466 2477
2467 // TODO(1231235): We try to estimate the set of properties set by 2478 // TODO(1231235): We try to estimate the set of properties set by
2468 // constructors. We define a new property whenever there is an 2479 // constructors. We define a new property whenever there is an
2469 // assignment to a property of 'this'. We should probably only add 2480 // assignment to a property of 'this'. We should probably only add
2470 // properties if we haven't seen them before. Otherwise we'll 2481 // properties if we haven't seen them before. Otherwise we'll
2471 // probably overestimate the number of properties. 2482 // probably overestimate the number of properties.
2472 if (op == Token::ASSIGN && this->IsThisProperty(expression)) { 2483 if (op == Token::ASSIGN && this->IsThisProperty(expression)) {
2473 function_state_->AddProperty(); 2484 function_state_->AddProperty();
2474 } 2485 }
(...skipping 1220 matching lines...) Expand 10 before | Expand all | Expand 10 after
3695 } 3706 }
3696 } 3707 }
3697 3708
3698 3709
3699 #undef CHECK_OK 3710 #undef CHECK_OK
3700 #undef CHECK_OK_CUSTOM 3711 #undef CHECK_OK_CUSTOM
3701 3712
3702 template <typename Traits> 3713 template <typename Traits>
3703 void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty( 3714 void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty(
3704 Token::Value property, PropertyKind type, MethodKind method_type, 3715 Token::Value property, PropertyKind type, MethodKind method_type,
3705 bool* ok) { 3716 ExpressionClassifier* classifier, bool* ok) {
3706 DCHECK(!IsStaticMethod(method_type)); 3717 DCHECK(!IsStaticMethod(method_type));
3707 DCHECK(!IsSpecialMethod(method_type) || type == kMethodProperty); 3718 DCHECK(!IsSpecialMethod(method_type) || type == kMethodProperty);
3708 3719
3709 if (property == Token::SMI || property == Token::NUMBER) return; 3720 if (property == Token::SMI || property == Token::NUMBER) return;
3710 3721
3711 if (type == kValueProperty && IsProto()) { 3722 if (type == kValueProperty && IsProto()) {
3712 if (has_seen_proto_) { 3723 if (has_seen_proto_) {
3713 this->parser()->ReportMessage(MessageTemplate::kDuplicateProto); 3724 classifier->RecordAnnexBDuplicateProtoError(
3714 *ok = false; 3725 this->scanner()->location(), MessageTemplate::kDuplicateProto);
3715 return; 3726 return;
3716 } 3727 }
3717 has_seen_proto_ = true; 3728 has_seen_proto_ = true;
3718 return;
3719 } 3729 }
3720 } 3730 }
3721 3731
3722 template <typename Traits> 3732 template <typename Traits>
3723 void ParserBase<Traits>::ClassLiteralChecker::CheckProperty( 3733 void ParserBase<Traits>::ClassLiteralChecker::CheckProperty(
3724 Token::Value property, PropertyKind type, MethodKind method_type, 3734 Token::Value property, PropertyKind type, MethodKind method_type,
3725 bool* ok) { 3735 ExpressionClassifier* classifier, bool* ok) {
3726 DCHECK(type == kMethodProperty || type == kAccessorProperty); 3736 DCHECK(type == kMethodProperty || type == kAccessorProperty);
3727 3737
3728 if (property == Token::SMI || property == Token::NUMBER) return; 3738 if (property == Token::SMI || property == Token::NUMBER) return;
3729 3739
3730 if (IsStaticMethod(method_type)) { 3740 if (IsStaticMethod(method_type)) {
3731 if (IsPrototype()) { 3741 if (IsPrototype()) {
3732 this->parser()->ReportMessage(MessageTemplate::kStaticPrototype); 3742 this->parser()->ReportMessage(MessageTemplate::kStaticPrototype);
3733 *ok = false; 3743 *ok = false;
3734 return; 3744 return;
3735 } 3745 }
(...skipping 17 matching lines...) Expand all
3753 has_seen_constructor_ = true; 3763 has_seen_constructor_ = true;
3754 return; 3764 return;
3755 } 3765 }
3756 } 3766 }
3757 3767
3758 3768
3759 } // namespace internal 3769 } // namespace internal
3760 } // namespace v8 3770 } // namespace v8
3761 3771
3762 #endif // V8_PARSING_PARSER_BASE_H 3772 #endif // V8_PARSING_PARSER_BASE_H
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698