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

Unified Diff: src/preparser.h

Issue 873823003: Move object literal checking into checker classes (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix assert Created 5 years, 11 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/ppc/full-codegen-ppc.cc ('k') | src/preparser.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/preparser.h
diff --git a/src/preparser.h b/src/preparser.h
index e2929b827d238d120528f2393a0160b1b3c4aaa0..3ba48826194bb5df1924fad039b03c4a4805997d 100644
--- a/src/preparser.h
+++ b/src/preparser.h
@@ -161,7 +161,7 @@ class ParserBase : public Traits {
};
class Checkpoint;
- class ObjectLiteralChecker;
+ class ObjectLiteralCheckerBase;
// ---------------------------------------------------------------------------
// FunctionState and BlockState together implement the parser's scope stack.
@@ -512,11 +512,9 @@ class ParserBase : public Traits {
bool* is_static, bool* is_computed_name,
bool* ok);
ExpressionT ParseObjectLiteral(bool* ok);
- ObjectLiteralPropertyT ParsePropertyDefinition(ObjectLiteralChecker* checker,
- bool in_class, bool is_static,
- bool* is_computed_name,
- bool* has_seen_constructor,
- bool* ok);
+ ObjectLiteralPropertyT ParsePropertyDefinition(
+ ObjectLiteralCheckerBase* checker, bool in_class, bool is_static,
+ bool* is_computed_name, bool* has_seen_constructor, bool* ok);
typename Traits::Type::ExpressionList ParseArguments(bool* ok);
ExpressionT ParseAssignmentExpression(bool accept_IN, bool* ok);
ExpressionT ParseYieldExpression(bool* ok);
@@ -541,58 +539,63 @@ class ParserBase : public Traits {
ExpressionT expression,
Scanner::Location location, const char* message, bool* ok);
- // Used to detect duplicates in object literals. Each of the values
- // kGetterProperty, kSetterProperty and kValueProperty represents
- // a type of object literal property. When parsing a property, its
- // type value is stored in the DuplicateFinder for the property name.
- // Values are chosen so that having intersection bits means the there is
- // an incompatibility.
- // I.e., you can add a getter to a property that already has a setter, since
- // kGetterProperty and kSetterProperty doesn't intersect, but not if it
- // already has a getter or a value. Adding the getter to an existing
- // setter will store the value (kGetterProperty | kSetterProperty), which
- // is incompatible with adding any further properties.
+ // Used to validate property names in object literals and class literals
enum PropertyKind {
- kNone = 0,
- // Bit patterns representing different object literal property types.
- kGetterProperty = 1,
- kSetterProperty = 2,
- kValueProperty = 7,
- // Helper constants.
- kValueFlag = 4
+ kAccessorProperty,
+ kValueProperty,
+ kMethodProperty
};
- // Validation per ECMA 262 - 11.1.5 "Object Initializer".
- class ObjectLiteralChecker {
+ class ObjectLiteralCheckerBase {
public:
- ObjectLiteralChecker(ParserBase* parser, StrictMode strict_mode)
- : parser_(parser),
- finder_(scanner()->unicode_cache()),
- strict_mode_(strict_mode) {}
+ explicit ObjectLiteralCheckerBase(ParserBase* parser) : parser_(parser) {}
- void CheckProperty(Token::Value property, PropertyKind type, bool* ok);
+ virtual void CheckProperty(Token::Value property, PropertyKind type,
+ bool is_static, bool is_generator, bool* ok) = 0;
- private:
+ virtual ~ObjectLiteralCheckerBase() {}
+
+ protected:
ParserBase* parser() const { return parser_; }
Scanner* scanner() const { return parser_->scanner(); }
- // Checks the type of conflict based on values coming from PropertyType.
- bool HasConflict(PropertyKind type1, PropertyKind type2) {
- return (type1 & type2) != 0;
- }
- bool IsDataDataConflict(PropertyKind type1, PropertyKind type2) {
- return ((type1 & type2) & kValueFlag) != 0;
- }
- bool IsDataAccessorConflict(PropertyKind type1, PropertyKind type2) {
- return ((type1 ^ type2) & kValueFlag) != 0;
+ private:
+ ParserBase* parser_;
+ };
+
+ // Validation per ES6 object literals.
+ class ObjectLiteralChecker : public ObjectLiteralCheckerBase {
+ public:
+ explicit ObjectLiteralChecker(ParserBase* parser)
+ : ObjectLiteralCheckerBase(parser), has_seen_proto_(false) {}
+
+ void CheckProperty(Token::Value property, PropertyKind type, bool is_static,
+ bool is_generator, bool* ok) OVERRIDE;
+
+ private:
+ bool IsProto() { return this->scanner()->LiteralMatches("__proto__", 9); }
+
+ bool has_seen_proto_;
+ };
+
+ // Validation per ES6 class literals.
+ class ClassLiteralChecker : public ObjectLiteralCheckerBase {
+ public:
+ explicit ClassLiteralChecker(ParserBase* parser)
+ : ObjectLiteralCheckerBase(parser), has_seen_constructor_(false) {}
+
+ void CheckProperty(Token::Value property, PropertyKind type, bool is_static,
+ bool is_generator, bool* ok) OVERRIDE;
+
+ private:
+ bool IsConstructor() {
+ return this->scanner()->LiteralMatches("constructor", 11);
}
- bool IsAccessorAccessorConflict(PropertyKind type1, PropertyKind type2) {
- return ((type1 | type2) & kValueFlag) == 0;
+ bool IsPrototype() {
+ return this->scanner()->LiteralMatches("prototype", 9);
}
- ParserBase* parser_;
- DuplicateFinder finder_;
- StrictMode strict_mode_;
+ bool has_seen_constructor_;
};
// If true, the next (and immediately following) function literal is
@@ -2070,12 +2073,12 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParsePropertyName(
template <class Traits>
typename ParserBase<Traits>::ObjectLiteralPropertyT
-ParserBase<Traits>::ParsePropertyDefinition(ObjectLiteralChecker* checker,
+ParserBase<Traits>::ParsePropertyDefinition(ObjectLiteralCheckerBase* checker,
bool in_class, bool is_static,
bool* is_computed_name,
bool* has_seen_constructor,
bool* ok) {
- DCHECK(!in_class || is_static || has_seen_constructor != NULL);
+ DCHECK(!in_class || is_static || has_seen_constructor != nullptr);
ExpressionT value = this->EmptyExpression();
IdentifierT name = this->EmptyIdentifier();
bool is_get = false;
@@ -2089,14 +2092,15 @@ ParserBase<Traits>::ParsePropertyDefinition(ObjectLiteralChecker* checker,
&name, &is_get, &is_set, &name_is_static, is_computed_name,
CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
- if (fni_ != NULL && !*is_computed_name) {
+ if (fni_ != nullptr && !*is_computed_name) {
this->PushLiteralName(fni_, name);
}
if (!in_class && !is_generator && peek() == Token::COLON) {
// PropertyDefinition : PropertyName ':' AssignmentExpression
- if (!*is_computed_name && checker != NULL) {
- checker->CheckProperty(name_token, kValueProperty,
+ if (!*is_computed_name) {
+ checker->CheckProperty(name_token, kValueProperty, is_static,
+ is_generator,
CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
}
Consume(Token::COLON);
@@ -2106,38 +2110,20 @@ ParserBase<Traits>::ParsePropertyDefinition(ObjectLiteralChecker* checker,
} else if (is_generator ||
(allow_harmony_object_literals_ && peek() == Token::LPAREN)) {
// Concise Method
-
- if (is_static && this->IsPrototype(name)) {
- ReportMessageAt(scanner()->location(), "static_prototype");
- *ok = false;
- return this->EmptyObjectLiteralProperty();
+ if (!*is_computed_name) {
+ checker->CheckProperty(name_token, kMethodProperty, is_static,
+ is_generator,
+ CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
}
FunctionKind kind = is_generator ? FunctionKind::kConciseGeneratorMethod
: FunctionKind::kConciseMethod;
if (in_class && !is_static && this->IsConstructor(name)) {
- if (is_generator) {
- ReportMessageAt(scanner()->location(), "constructor_special_method");
- *ok = false;
- return this->EmptyObjectLiteralProperty();
- }
-
- if (*has_seen_constructor) {
- ReportMessageAt(scanner()->location(), "duplicate_constructor");
- *ok = false;
- return this->EmptyObjectLiteralProperty();
- }
-
*has_seen_constructor = true;
kind = FunctionKind::kNormalFunction;
}
- if (!*is_computed_name && checker != NULL) {
- checker->CheckProperty(name_token, kValueProperty,
- CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
- }
-
value = this->ParseFunctionLiteral(
name, scanner()->location(),
false, // reserved words are allowed here
@@ -2151,8 +2137,8 @@ ParserBase<Traits>::ParsePropertyDefinition(ObjectLiteralChecker* checker,
} else if (in_class && name_is_static && !is_static) {
// static MethodDefinition
- return ParsePropertyDefinition(checker, true, true, is_computed_name, NULL,
- ok);
+ return ParsePropertyDefinition(checker, true, true, is_computed_name,
+ nullptr, ok);
} else if (is_get || is_set) {
// Accessor
@@ -2164,19 +2150,9 @@ ParserBase<Traits>::ParsePropertyDefinition(ObjectLiteralChecker* checker,
&name, &dont_care, &dont_care, &dont_care, is_computed_name,
CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
- // Validate the property.
- if (is_static && this->IsPrototype(name)) {
- ReportMessageAt(scanner()->location(), "static_prototype");
- *ok = false;
- return this->EmptyObjectLiteralProperty();
- } else if (in_class && !is_static && this->IsConstructor(name)) {
- ReportMessageAt(scanner()->location(), "constructor_special_method");
- *ok = false;
- return this->EmptyObjectLiteralProperty();
- }
- if (!*is_computed_name && checker != NULL) {
- checker->CheckProperty(name_token,
- is_get ? kGetterProperty : kSetterProperty,
+ if (!*is_computed_name) {
+ checker->CheckProperty(name_token, kAccessorProperty, is_static,
+ is_generator,
CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
}
@@ -2234,19 +2210,18 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral(
int number_of_boilerplate_properties = 0;
bool has_function = false;
bool has_computed_names = false;
-
- ObjectLiteralChecker checker(this, strict_mode());
+ ObjectLiteralChecker checker(this);
Expect(Token::LBRACE, CHECK_OK);
while (peek() != Token::RBRACE) {
- if (fni_ != NULL) fni_->Enter();
+ if (fni_ != nullptr) fni_->Enter();
const bool in_class = false;
const bool is_static = false;
bool is_computed_name = false;
ObjectLiteralPropertyT property = this->ParsePropertyDefinition(
- &checker, in_class, is_static, &is_computed_name, NULL, CHECK_OK);
+ &checker, in_class, is_static, &is_computed_name, nullptr, CHECK_OK);
if (is_computed_name) {
has_computed_names = true;
@@ -2269,7 +2244,7 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral(
Expect(Token::COMMA, CHECK_OK);
}
- if (fni_ != NULL) {
+ if (fni_ != nullptr) {
fni_->Infer();
fni_->Leave();
}
@@ -3041,28 +3016,52 @@ typename ParserBase<Traits>::ExpressionT ParserBase<
template <typename Traits>
void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty(
- Token::Value property, PropertyKind type, bool* ok) {
- int old;
- if (property == Token::NUMBER) {
- old = scanner()->FindNumber(&finder_, type);
- } else {
- old = scanner()->FindSymbol(&finder_, type);
- }
- PropertyKind old_type = static_cast<PropertyKind>(old);
- if (HasConflict(old_type, type)) {
- if (IsDataDataConflict(old_type, type)) {
- // Both are data properties.
- if (strict_mode_ == SLOPPY) return;
- parser()->ReportMessage("strict_duplicate_property");
- } else if (IsDataAccessorConflict(old_type, type)) {
- // Both a data and an accessor property with the same name.
- parser()->ReportMessage("accessor_data_property");
- } else {
- DCHECK(IsAccessorAccessorConflict(old_type, type));
- // Both accessors of the same type.
- parser()->ReportMessage("accessor_get_set");
+ Token::Value property, PropertyKind type, bool is_static, bool is_generator,
+ bool* ok) {
+ DCHECK(!is_static);
+ DCHECK(!is_generator || type == kMethodProperty);
+
+ if (property == Token::NUMBER) return;
+
+ if (type == kValueProperty && IsProto()) {
+ if (has_seen_proto_) {
+ this->parser()->ReportMessage("duplicate_proto");
+ *ok = false;
+ return;
}
- *ok = false;
+ has_seen_proto_ = true;
+ return;
+ }
+}
+
+
+template <typename Traits>
+void ParserBase<Traits>::ClassLiteralChecker::CheckProperty(
+ Token::Value property, PropertyKind type, bool is_static, bool is_generator,
+ bool* ok) {
+ DCHECK(type == kMethodProperty || type == kAccessorProperty);
+
+ if (property == Token::NUMBER) return;
+
+ if (is_static) {
+ if (IsPrototype()) {
+ this->parser()->ReportMessage("static_prototype");
+ *ok = false;
+ return;
+ }
+ } else if (IsConstructor()) {
+ if (is_generator || type == kAccessorProperty) {
+ this->parser()->ReportMessage("constructor_special_method");
+ *ok = false;
+ return;
+ }
+ if (has_seen_constructor_) {
+ this->parser()->ReportMessage("duplicate_constructor");
+ *ok = false;
+ return;
+ }
+ has_seen_constructor_ = true;
+ return;
}
}
} } // v8::internal
« no previous file with comments | « src/ppc/full-codegen-ppc.cc ('k') | src/preparser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698