OLD | NEW |
---|---|
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 1164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1175 kAccessorProperty, | 1175 kAccessorProperty, |
1176 kValueProperty, | 1176 kValueProperty, |
1177 kMethodProperty | 1177 kMethodProperty |
1178 }; | 1178 }; |
1179 | 1179 |
1180 class ObjectLiteralCheckerBase { | 1180 class ObjectLiteralCheckerBase { |
1181 public: | 1181 public: |
1182 explicit ObjectLiteralCheckerBase(ParserBase* parser) : parser_(parser) {} | 1182 explicit ObjectLiteralCheckerBase(ParserBase* parser) : parser_(parser) {} |
1183 | 1183 |
1184 virtual void CheckProperty(Token::Value property, PropertyKind type, | 1184 virtual void CheckProperty(Token::Value property, PropertyKind type, |
1185 MethodKind method_type, bool* ok) = 0; | 1185 MethodKind method_type, |
1186 ExpressionClassifier* classifier, bool* ok) = 0; | |
1186 | 1187 |
1187 virtual ~ObjectLiteralCheckerBase() {} | 1188 virtual ~ObjectLiteralCheckerBase() {} |
1188 | 1189 |
1189 protected: | 1190 protected: |
1190 ParserBase* parser() const { return parser_; } | 1191 ParserBase* parser() const { return parser_; } |
1191 Scanner* scanner() const { return parser_->scanner(); } | 1192 Scanner* scanner() const { return parser_->scanner(); } |
1192 | 1193 |
1193 private: | 1194 private: |
1194 ParserBase* parser_; | 1195 ParserBase* parser_; |
1195 }; | 1196 }; |
1196 | 1197 |
1197 // Validation per ES6 object literals. | 1198 // Validation per ES6 object literals. |
1198 class ObjectLiteralChecker : public ObjectLiteralCheckerBase { | 1199 class ObjectLiteralChecker : public ObjectLiteralCheckerBase { |
1199 public: | 1200 public: |
1200 explicit ObjectLiteralChecker(ParserBase* parser) | 1201 explicit ObjectLiteralChecker(ParserBase* parser) |
1201 : ObjectLiteralCheckerBase(parser), has_seen_proto_(false) {} | 1202 : ObjectLiteralCheckerBase(parser), has_seen_proto_(false) {} |
1202 | 1203 |
1203 void CheckProperty(Token::Value property, PropertyKind type, | 1204 void CheckProperty(Token::Value property, PropertyKind type, |
1204 MethodKind method_type, bool* ok) override; | 1205 MethodKind method_type, ExpressionClassifier* classifier, |
1206 bool* ok) override; | |
1205 | 1207 |
1206 private: | 1208 private: |
1207 bool IsProto() { return this->scanner()->LiteralMatches("__proto__", 9); } | 1209 bool IsProto() { return this->scanner()->LiteralMatches("__proto__", 9); } |
1208 | 1210 |
1209 bool has_seen_proto_; | 1211 bool has_seen_proto_; |
1210 }; | 1212 }; |
1211 | 1213 |
1212 // Validation per ES6 class literals. | 1214 // Validation per ES6 class literals. |
1213 class ClassLiteralChecker : public ObjectLiteralCheckerBase { | 1215 class ClassLiteralChecker : public ObjectLiteralCheckerBase { |
1214 public: | 1216 public: |
1215 explicit ClassLiteralChecker(ParserBase* parser) | 1217 explicit ClassLiteralChecker(ParserBase* parser) |
1216 : ObjectLiteralCheckerBase(parser), has_seen_constructor_(false) {} | 1218 : ObjectLiteralCheckerBase(parser), has_seen_constructor_(false) {} |
1217 | 1219 |
1218 void CheckProperty(Token::Value property, PropertyKind type, | 1220 void CheckProperty(Token::Value property, PropertyKind type, |
1219 MethodKind method_type, bool* ok) override; | 1221 MethodKind method_type, ExpressionClassifier* classifier, |
1222 bool* ok) override; | |
1220 | 1223 |
1221 private: | 1224 private: |
1222 bool IsConstructor() { | 1225 bool IsConstructor() { |
1223 return this->scanner()->LiteralMatches("constructor", 11); | 1226 return this->scanner()->LiteralMatches("constructor", 11); |
1224 } | 1227 } |
1225 bool IsPrototype() { | 1228 bool IsPrototype() { |
1226 return this->scanner()->LiteralMatches("prototype", 9); | 1229 return this->scanner()->LiteralMatches("prototype", 9); |
1227 } | 1230 } |
1228 | 1231 |
1229 bool has_seen_constructor_; | 1232 bool has_seen_constructor_; |
(...skipping 724 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1954 } | 1957 } |
1955 | 1958 |
1956 if (!in_class && !is_generator) { | 1959 if (!in_class && !is_generator) { |
1957 DCHECK(!IsStaticMethod(method_kind)); | 1960 DCHECK(!IsStaticMethod(method_kind)); |
1958 | 1961 |
1959 if (peek() == Token::COLON) { | 1962 if (peek() == Token::COLON) { |
1960 // PropertyDefinition | 1963 // PropertyDefinition |
1961 // PropertyName ':' AssignmentExpression | 1964 // PropertyName ':' AssignmentExpression |
1962 if (!*is_computed_name) { | 1965 if (!*is_computed_name) { |
1963 checker->CheckProperty(name_token, kValueProperty, MethodKind::kNormal, | 1966 checker->CheckProperty(name_token, kValueProperty, MethodKind::kNormal, |
1967 classifier, | |
1964 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 1968 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
1965 } | 1969 } |
1966 Consume(Token::COLON); | 1970 Consume(Token::COLON); |
1967 int beg_pos = peek_position(); | 1971 int beg_pos = peek_position(); |
1968 ExpressionT value = this->ParseAssignmentExpression( | 1972 ExpressionT value = this->ParseAssignmentExpression( |
1969 true, classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 1973 true, classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
1970 CheckDestructuringElement(value, classifier, beg_pos, | 1974 CheckDestructuringElement(value, classifier, beg_pos, |
1971 scanner()->location().end_pos); | 1975 scanner()->location().end_pos); |
1972 | 1976 |
1973 return factory()->NewObjectLiteralProperty(name_expression, value, | 1977 return factory()->NewObjectLiteralProperty(name_expression, value, |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2048 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 2052 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
2049 method_kind |= MethodKind::kAsync; | 2053 method_kind |= MethodKind::kAsync; |
2050 } | 2054 } |
2051 | 2055 |
2052 if (is_generator || peek() == Token::LPAREN) { | 2056 if (is_generator || peek() == Token::LPAREN) { |
2053 // MethodDefinition | 2057 // MethodDefinition |
2054 // PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}' | 2058 // PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}' |
2055 // '*' PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}' | 2059 // '*' PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}' |
2056 if (!*is_computed_name) { | 2060 if (!*is_computed_name) { |
2057 checker->CheckProperty(name_token, kMethodProperty, method_kind, | 2061 checker->CheckProperty(name_token, kMethodProperty, method_kind, |
2062 classifier, | |
2058 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 2063 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
2059 } | 2064 } |
2060 | 2065 |
2061 FunctionKind kind = is_generator | 2066 FunctionKind kind = is_generator |
2062 ? FunctionKind::kConciseGeneratorMethod | 2067 ? FunctionKind::kConciseGeneratorMethod |
2063 : is_async ? FunctionKind::kAsyncConciseMethod | 2068 : is_async ? FunctionKind::kAsyncConciseMethod |
2064 : FunctionKind::kConciseMethod; | 2069 : FunctionKind::kConciseMethod; |
2065 | 2070 |
2066 if (in_class && !IsStaticMethod(method_kind) && | 2071 if (in_class && !IsStaticMethod(method_kind) && |
2067 this->IsConstructor(*name)) { | 2072 this->IsConstructor(*name)) { |
(...skipping 30 matching lines...) Expand all Loading... | |
2098 *name = this->EmptyIdentifier(); | 2103 *name = this->EmptyIdentifier(); |
2099 bool dont_care = false; | 2104 bool dont_care = false; |
2100 name_token = peek(); | 2105 name_token = peek(); |
2101 | 2106 |
2102 name_expression = ParsePropertyName( | 2107 name_expression = ParsePropertyName( |
2103 name, &dont_care, &dont_care, &dont_care, is_computed_name, classifier, | 2108 name, &dont_care, &dont_care, &dont_care, is_computed_name, classifier, |
2104 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 2109 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
2105 | 2110 |
2106 if (!*is_computed_name) { | 2111 if (!*is_computed_name) { |
2107 checker->CheckProperty(name_token, kAccessorProperty, method_kind, | 2112 checker->CheckProperty(name_token, kAccessorProperty, method_kind, |
2113 classifier, | |
2108 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 2114 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
2109 } | 2115 } |
2110 | 2116 |
2111 typename Traits::Type::FunctionLiteral value = this->ParseFunctionLiteral( | 2117 typename Traits::Type::FunctionLiteral value = this->ParseFunctionLiteral( |
2112 *name, scanner()->location(), kSkipFunctionNameCheck, | 2118 *name, scanner()->location(), kSkipFunctionNameCheck, |
2113 is_get ? FunctionKind::kGetterFunction : FunctionKind::kSetterFunction, | 2119 is_get ? FunctionKind::kGetterFunction : FunctionKind::kSetterFunction, |
2114 kNoSourcePosition, FunctionLiteral::kAccessorOrMethod, language_mode(), | 2120 kNoSourcePosition, FunctionLiteral::kAccessorOrMethod, language_mode(), |
2115 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 2121 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
2116 | 2122 |
2117 // Make sure the name expression is a string since we need a Name for | 2123 // Make sure the name expression is a string since we need a Name for |
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2402 return expression; | 2408 return expression; |
2403 } | 2409 } |
2404 | 2410 |
2405 // Now pending non-pattern expressions must be discarded. | 2411 // Now pending non-pattern expressions must be discarded. |
2406 arrow_formals_classifier.Discard(); | 2412 arrow_formals_classifier.Discard(); |
2407 | 2413 |
2408 CheckNoTailCallExpressions(classifier, CHECK_OK); | 2414 CheckNoTailCallExpressions(classifier, CHECK_OK); |
2409 | 2415 |
2410 if (IsValidPattern(expression) && peek() == Token::ASSIGN) { | 2416 if (IsValidPattern(expression) && peek() == Token::ASSIGN) { |
2411 classifier->ForgiveCoverInitializedNameError(); | 2417 classifier->ForgiveCoverInitializedNameError(); |
2418 classifier->ForgiveExpressionError(); | |
adamk
2016/08/18 20:35:22
Is this necessary? What fails if you don't "forgiv
gsathya
2016/08/19 20:11:18
As discussed offline -- leaving this here.
| |
2412 ValidateAssignmentPattern(classifier, CHECK_OK); | 2419 ValidateAssignmentPattern(classifier, CHECK_OK); |
2413 is_destructuring_assignment = true; | 2420 is_destructuring_assignment = true; |
2414 } else { | 2421 } else { |
2415 expression = this->CheckAndRewriteReferenceExpression( | 2422 expression = this->CheckAndRewriteReferenceExpression( |
2416 expression, lhs_beg_pos, scanner()->location().end_pos, | 2423 expression, lhs_beg_pos, scanner()->location().end_pos, |
2417 MessageTemplate::kInvalidLhsInAssignment, CHECK_OK); | 2424 MessageTemplate::kInvalidLhsInAssignment, CHECK_OK); |
2418 } | 2425 } |
2419 | 2426 |
2420 expression = this->MarkExpressionAsAssigned(expression); | 2427 expression = this->MarkExpressionAsAssigned(expression); |
2421 | 2428 |
(...skipping 10 matching lines...) Expand all Loading... | |
2432 ExpressionT right = | 2439 ExpressionT right = |
2433 this->ParseAssignmentExpression(accept_IN, &rhs_classifier, CHECK_OK); | 2440 this->ParseAssignmentExpression(accept_IN, &rhs_classifier, CHECK_OK); |
2434 CheckNoTailCallExpressions(&rhs_classifier, CHECK_OK); | 2441 CheckNoTailCallExpressions(&rhs_classifier, CHECK_OK); |
2435 Traits::RewriteNonPattern(&rhs_classifier, CHECK_OK); | 2442 Traits::RewriteNonPattern(&rhs_classifier, CHECK_OK); |
2436 classifier->Accumulate( | 2443 classifier->Accumulate( |
2437 &rhs_classifier, | 2444 &rhs_classifier, |
2438 ExpressionClassifier::ExpressionProductions | | 2445 ExpressionClassifier::ExpressionProductions | |
2439 ExpressionClassifier::CoverInitializedNameProduction | | 2446 ExpressionClassifier::CoverInitializedNameProduction | |
2440 ExpressionClassifier::AsyncArrowFormalParametersProduction); | 2447 ExpressionClassifier::AsyncArrowFormalParametersProduction); |
2441 | 2448 |
2449 if (!classifier->is_valid_expression()) | |
adamk
2016/08/18 20:35:22
Was this necessary? I wouldn't think you'd need to
gsathya
2016/08/19 20:11:18
Removed.
| |
2450 ReportClassifierError(classifier->expression_error()); | |
2451 | |
2442 // TODO(1231235): We try to estimate the set of properties set by | 2452 // TODO(1231235): We try to estimate the set of properties set by |
2443 // constructors. We define a new property whenever there is an | 2453 // constructors. We define a new property whenever there is an |
2444 // assignment to a property of 'this'. We should probably only add | 2454 // assignment to a property of 'this'. We should probably only add |
2445 // properties if we haven't seen them before. Otherwise we'll | 2455 // properties if we haven't seen them before. Otherwise we'll |
2446 // probably overestimate the number of properties. | 2456 // probably overestimate the number of properties. |
2447 if (op == Token::ASSIGN && this->IsThisProperty(expression)) { | 2457 if (op == Token::ASSIGN && this->IsThisProperty(expression)) { |
2448 function_state_->AddProperty(); | 2458 function_state_->AddProperty(); |
2449 } | 2459 } |
2450 | 2460 |
2451 this->CheckAssigningFunctionLiteralToProperty(expression, right); | 2461 this->CheckAssigningFunctionLiteralToProperty(expression, right); |
(...skipping 1218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3670 } | 3680 } |
3671 } | 3681 } |
3672 | 3682 |
3673 | 3683 |
3674 #undef CHECK_OK | 3684 #undef CHECK_OK |
3675 #undef CHECK_OK_CUSTOM | 3685 #undef CHECK_OK_CUSTOM |
3676 | 3686 |
3677 template <typename Traits> | 3687 template <typename Traits> |
3678 void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty( | 3688 void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty( |
3679 Token::Value property, PropertyKind type, MethodKind method_type, | 3689 Token::Value property, PropertyKind type, MethodKind method_type, |
3680 bool* ok) { | 3690 ExpressionClassifier* classifier, bool* ok) { |
adamk
2016/08/18 20:35:22
Hmm, it's a little strange that this takes "ok" no
gsathya
2016/08/19 20:11:18
Yeah :/ It's the same with classifier being added
| |
3681 DCHECK(!IsStaticMethod(method_type)); | 3691 DCHECK(!IsStaticMethod(method_type)); |
3682 DCHECK(!IsSpecialMethod(method_type) || type == kMethodProperty); | 3692 DCHECK(!IsSpecialMethod(method_type) || type == kMethodProperty); |
3683 | 3693 |
3684 if (property == Token::SMI || property == Token::NUMBER) return; | 3694 if (property == Token::SMI || property == Token::NUMBER) return; |
3685 | 3695 |
3686 if (type == kValueProperty && IsProto()) { | 3696 if (type == kValueProperty && IsProto()) { |
3687 if (has_seen_proto_) { | 3697 if (has_seen_proto_) { |
3688 this->parser()->ReportMessage(MessageTemplate::kDuplicateProto); | 3698 classifier->RecordExpressionError(this->scanner()->location(), |
3689 *ok = false; | 3699 MessageTemplate::kDuplicateProto, |
3700 kSyntaxError); | |
3690 return; | 3701 return; |
3691 } | 3702 } |
3692 has_seen_proto_ = true; | 3703 has_seen_proto_ = true; |
3693 return; | |
3694 } | 3704 } |
3695 } | 3705 } |
3696 | 3706 |
3697 template <typename Traits> | 3707 template <typename Traits> |
3698 void ParserBase<Traits>::ClassLiteralChecker::CheckProperty( | 3708 void ParserBase<Traits>::ClassLiteralChecker::CheckProperty( |
3699 Token::Value property, PropertyKind type, MethodKind method_type, | 3709 Token::Value property, PropertyKind type, MethodKind method_type, |
3700 bool* ok) { | 3710 ExpressionClassifier* classifier, bool* ok) { |
3701 DCHECK(type == kMethodProperty || type == kAccessorProperty); | 3711 DCHECK(type == kMethodProperty || type == kAccessorProperty); |
3702 | 3712 |
3703 if (property == Token::SMI || property == Token::NUMBER) return; | 3713 if (property == Token::SMI || property == Token::NUMBER) return; |
3704 | 3714 |
3705 if (IsStaticMethod(method_type)) { | 3715 if (IsStaticMethod(method_type)) { |
3706 if (IsPrototype()) { | 3716 if (IsPrototype()) { |
3707 this->parser()->ReportMessage(MessageTemplate::kStaticPrototype); | 3717 this->parser()->ReportMessage(MessageTemplate::kStaticPrototype); |
3708 *ok = false; | 3718 *ok = false; |
3709 return; | 3719 return; |
3710 } | 3720 } |
(...skipping 17 matching lines...) Expand all Loading... | |
3728 has_seen_constructor_ = true; | 3738 has_seen_constructor_ = true; |
3729 return; | 3739 return; |
3730 } | 3740 } |
3731 } | 3741 } |
3732 | 3742 |
3733 | 3743 |
3734 } // namespace internal | 3744 } // namespace internal |
3735 } // namespace v8 | 3745 } // namespace v8 |
3736 | 3746 |
3737 #endif // V8_PARSING_PARSER_BASE_H | 3747 #endif // V8_PARSING_PARSER_BASE_H |
OLD | NEW |