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

Unified Diff: src/preparser.h

Issue 491053002: Add back the duplicate property checker (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | test/cctest/test-parsing.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 5ca161d94925e885fe811d7fe565512a555593c4..13d33360b0252ceaba3dadb919ba8e82f5a38010 100644
--- a/src/preparser.h
+++ b/src/preparser.h
@@ -130,6 +130,7 @@ class ParserBase : public Traits {
};
class ParserCheckpoint;
+ class ObjectLiteralChecker;
// ---------------------------------------------------------------------------
// FunctionState and BlockState together implement the parser's scope stack.
@@ -476,7 +477,8 @@ class ParserBase : public Traits {
ExpressionT ParseExpression(bool accept_IN, bool* ok);
ExpressionT ParseArrayLiteral(bool* ok);
ExpressionT ParseObjectLiteral(bool* ok);
- ObjectLiteralPropertyT ParsePropertyDefinition(bool* ok);
+ ObjectLiteralPropertyT ParsePropertyDefinition(ObjectLiteralChecker* checker,
+ bool* ok);
typename Traits::Type::ExpressionList ParseArguments(bool* ok);
ExpressionT ParseAssignmentExpression(bool accept_IN, bool* ok);
ExpressionT ParseYieldExpression(bool* ok);
@@ -499,6 +501,60 @@ 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.
+ enum PropertyKind {
+ kNone = 0,
+ // Bit patterns representing different object literal property types.
+ kGetterProperty = 1,
+ kSetterProperty = 2,
+ kValueProperty = 7,
+ // Helper constants.
+ kValueFlag = 4
+ };
+
+ // Validation per ECMA 262 - 11.1.5 "Object Initializer".
+ class ObjectLiteralChecker {
+ public:
+ ObjectLiteralChecker(ParserBase* parser, StrictMode strict_mode)
+ : parser_(parser),
+ finder_(scanner()->unicode_cache()),
+ strict_mode_(strict_mode) {}
+
+ void CheckProperty(Token::Value property, PropertyKind type, bool* ok);
+
+ private:
+ 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;
+ }
+ bool IsAccessorAccessorConflict(PropertyKind type1, PropertyKind type2) {
+ return ((type1 | type2) & kValueFlag) == 0;
+ }
+
+ ParserBase* parser_;
+ DuplicateFinder finder_;
+ StrictMode strict_mode_;
+ };
+
// If true, the next (and immediately following) function literal is
// preceded by a parenthesis.
// Heuristically that means that the function will be called immediately,
@@ -1801,8 +1857,8 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseArrayLiteral(
template <class Traits>
-typename ParserBase<Traits>::ObjectLiteralPropertyT
-ParserBase<Traits>::ParsePropertyDefinition(bool* ok) {
+typename ParserBase<Traits>::ObjectLiteralPropertyT ParserBase<
+ Traits>::ParsePropertyDefinition(ObjectLiteralChecker* checker, bool* ok) {
LiteralT key = this->EmptyLiteral();
Token::Value next = peek();
int next_pos = peek_position();
@@ -1854,6 +1910,10 @@ ParserBase<Traits>::ParsePropertyDefinition(bool* ok) {
name = ParseIdentifierName(
CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
}
+ // Validate the property.
+ PropertyKind type = is_getter ? kGetterProperty : kSetterProperty;
+ checker->CheckProperty(next, type,
+ CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
typename Traits::Type::FunctionLiteral value =
this->ParseFunctionLiteral(
name, scanner()->location(),
@@ -1871,6 +1931,10 @@ ParserBase<Traits>::ParsePropertyDefinition(bool* ok) {
}
}
+ // Validate the property
+ checker->CheckProperty(next, kValueProperty,
+ CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+
Expect(Token::COLON, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
ExpressionT value = this->ParseAssignmentExpression(
true, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
@@ -1891,12 +1955,15 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral(
int number_of_boilerplate_properties = 0;
bool has_function = false;
+ ObjectLiteralChecker checker(this, strict_mode());
+
Expect(Token::LBRACE, CHECK_OK);
while (peek() != Token::RBRACE) {
if (fni_ != NULL) fni_->Enter();
- ObjectLiteralPropertyT property = this->ParsePropertyDefinition(CHECK_OK);
+ ObjectLiteralPropertyT property =
+ this->ParsePropertyDefinition(&checker, CHECK_OK);
// Mark top-level object literals that contain function literals and
// pretenure the literal so it can be added as a constant function
@@ -2580,6 +2647,32 @@ ParserBase<Traits>::CheckAndRewriteReferenceExpression(
#undef CHECK_OK_CUSTOM
+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");
+ }
+ *ok = false;
+ }
+}
} } // v8::internal
#endif // V8_PREPARSER_H
« no previous file with comments | « no previous file | test/cctest/test-parsing.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698