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

Unified Diff: src/parser.cc

Issue 6335010: Strict mode object literal validation (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: CR feedback Created 9 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/messages.js ('k') | test/mjsunit/strict-mode.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/parser.cc
diff --git a/src/parser.cc b/src/parser.cc
index 2637281f080ed9f7f32fba93701c4da068a4f34e..c07d49768f0f14144f998cf3cf6a654456fe20fa 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -3012,6 +3012,126 @@ Handle<Object> Parser::GetBoilerplateValue(Expression* expression) {
return Factory::undefined_value();
}
+// Defined in ast.cc
+bool IsEqualString(void* first, void* second);
+bool IsEqualSmi(void* first, void* second);
+
+
+// Validation per 11.1.5 Object Initialiser
+class ObjectLiteralPropertyChecker {
+ public:
+ ObjectLiteralPropertyChecker(Parser* parser, bool strict) :
+ props(&IsEqualString),
+ elems(&IsEqualSmi),
+ parser_(parser),
+ strict_(strict) {
+ }
+
+ void CheckProperty(
+ ObjectLiteral::Property* property,
+ Scanner::Location loc,
+ bool* ok);
+
+ private:
+ enum PropertyKind {
+ kGetAccessor = 0x01,
+ kSetAccessor = 0x02,
+ kAccessor = kGetAccessor | kSetAccessor,
+ kData = 0x04
+ };
+
+ static intptr_t GetPropertyKind(ObjectLiteral::Property* property) {
+ switch (property->kind()) {
+ case ObjectLiteral::Property::GETTER:
+ return kGetAccessor;
+ case ObjectLiteral::Property::SETTER:
+ return kSetAccessor;
+ default:
+ return kData;
+ }
+ }
+
+ HashMap props;
+ HashMap elems;
+ Parser* parser_;
+ bool strict_;
+};
+
+
+void ObjectLiteralPropertyChecker::CheckProperty(
+ ObjectLiteral::Property* property,
+ Scanner::Location loc,
+ bool* ok) {
+
+ ASSERT(property != NULL);
+
+ Literal *lit = property->key();
+ Handle<Object> handle = lit->handle();
+
+ uint32_t hash;
+ HashMap* map;
+ void* key;
+ Smi* smi_key_location;
+
+ if (handle->IsSymbol()) {
+ Handle<String> name(String::cast(*handle));
+ if (name->AsArrayIndex(&hash)) {
+ smi_key_location = Smi::FromInt(hash);
+ key = &smi_key_location;
+ map = &elems;
+ } else {
+ key = handle.location();
+ hash = name->Hash();
+ map = &props;
+ }
+ } else if (handle->ToArrayIndex(&hash)) {
+ key = handle.location();
+ map = &elems;
+ } else {
+ ASSERT(handle->IsNumber());
+ double num = handle->Number();
+ char arr[100];
+ Vector<char> buffer(arr, ARRAY_SIZE(arr));
+ const char* str = DoubleToCString(num, buffer);
+ Handle<String> name = Factory::NewStringFromAscii(CStrVector(str));
+ key = name.location();
+ hash = name->Hash();
+ map = &props;
+ }
+
+ // Lookup property previously defined, if any.
+ HashMap::Entry* entry = map->Lookup(key, hash, true);
+ intptr_t prev = reinterpret_cast<intptr_t> (entry->value);
+ intptr_t curr = GetPropertyKind(property);
+
+ // Duplicate data properties are illegal in strict mode.
+ if (strict_ && (curr & prev & kData) != 0) {
+ parser_->ReportMessageAt(loc, "strict_duplicate_property",
+ Vector<const char*>::empty());
+ *ok = false;
+ return;
+ }
+ // Data property conflicting with an accessor.
+ if (((curr & kData) && (prev & kAccessor)) ||
+ ((prev & kData) && (curr & kAccessor))) {
+ parser_->ReportMessageAt(loc, "accessor_data_property",
+ Vector<const char*>::empty());
+ *ok = false;
+ return;
+ }
+ // Two accessors of the same type conflicting
+ if ((curr & prev & kAccessor) != 0) {
+ parser_->ReportMessageAt(loc, "accessor_get_set",
+ Vector<const char*>::empty());
+ *ok = false;
+ return;
+ }
+
+ // Update map
+ entry->value = reinterpret_cast<void*> (prev | curr);
+ *ok = true;
+}
+
void Parser::BuildObjectLiteralConstantProperties(
ZoneList<ObjectLiteral::Property*>* properties,
@@ -3117,12 +3237,20 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
new ZoneList<ObjectLiteral::Property*>(4);
int number_of_boilerplate_properties = 0;
+ ObjectLiteralPropertyChecker checker(this, temp_scope_->StrictMode());
+
Expect(Token::LBRACE, CHECK_OK);
+ Scanner::Location loc = scanner().location();
+
while (peek() != Token::RBRACE) {
if (fni_ != NULL) fni_->Enter();
Literal* key = NULL;
Token::Value next = peek();
+
+ // Location of the property name token
+ Scanner::Location loc = scanner().peek_location();
+
switch (next) {
case Token::IDENTIFIER: {
bool is_getter = false;
@@ -3132,11 +3260,15 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
if (fni_ != NULL) fni_->PushLiteralName(id);
if ((is_getter || is_setter) && peek() != Token::COLON) {
+ // Update loc to point to the identifier
+ loc = scanner().peek_location();
ObjectLiteral::Property* property =
ParseObjectLiteralGetSet(is_getter, CHECK_OK);
if (IsBoilerplateProperty(property)) {
number_of_boilerplate_properties++;
}
+ // Validate the property.
+ checker.CheckProperty(property, loc, CHECK_OK);
properties->Add(property);
if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
@@ -3193,6 +3325,8 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
// Count CONSTANT or COMPUTED properties to maintain the enumeration order.
if (IsBoilerplateProperty(property)) number_of_boilerplate_properties++;
+ // Validate the property
+ checker.CheckProperty(property, loc, CHECK_OK);
properties->Add(property);
// TODO(1240767): Consider allowing trailing comma.
@@ -3204,6 +3338,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
}
}
Expect(Token::RBRACE, CHECK_OK);
+
// Computation of literal_index must happen before pre parse bailout.
int literal_index = temp_scope_->NextMaterializedLiteralIndex();
« no previous file with comments | « src/messages.js ('k') | test/mjsunit/strict-mode.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698