| Index: src/parser.cc
|
| diff --git a/src/parser.cc b/src/parser.cc
|
| index 6466ea29841973b11ff376f64d6f2a4abce59844..96b1aa84ff7cc61bab26f9d48dae91509ea9cfb6 100644
|
| --- a/src/parser.cc
|
| +++ b/src/parser.cc
|
| @@ -3771,84 +3771,6 @@ Handle<Object> Parser::GetBoilerplateValue(Expression* expression) {
|
| }
|
|
|
|
|
| -// Validation per 11.1.5 Object Initialiser
|
| -class ObjectLiteralPropertyChecker {
|
| - public:
|
| - ObjectLiteralPropertyChecker(Parser* parser, LanguageMode language_mode) :
|
| - props_(Literal::Match),
|
| - parser_(parser),
|
| - language_mode_(language_mode) {
|
| - }
|
| -
|
| - 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_;
|
| - Parser* parser_;
|
| - LanguageMode language_mode_;
|
| -};
|
| -
|
| -
|
| -void ObjectLiteralPropertyChecker::CheckProperty(
|
| - ObjectLiteral::Property* property,
|
| - Scanner::Location loc,
|
| - bool* ok) {
|
| - ASSERT(property != NULL);
|
| - Literal* literal = property->key();
|
| - HashMap::Entry* entry = props_.Lookup(literal, literal->Hash(), true);
|
| - intptr_t prev = reinterpret_cast<intptr_t> (entry->value);
|
| - intptr_t curr = GetPropertyKind(property);
|
| -
|
| - // Duplicate data properties are illegal in strict or extended mode.
|
| - if (language_mode_ != CLASSIC_MODE && (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,
|
| Handle<FixedArray> constant_properties,
|
| @@ -3921,39 +3843,9 @@ void Parser::BuildObjectLiteralConstantProperties(
|
| }
|
|
|
|
|
| -ObjectLiteral::Property* Parser::ParseObjectLiteralGetSet(bool is_getter,
|
| - bool* ok) {
|
| - // Special handling of getter and setter syntax:
|
| - // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... }
|
| - // We have already read the "get" or "set" keyword.
|
| - Token::Value next = Next();
|
| - bool is_keyword = Token::IsKeyword(next);
|
| - if (next == Token::IDENTIFIER || next == Token::NUMBER ||
|
| - next == Token::FUTURE_RESERVED_WORD ||
|
| - next == Token::FUTURE_STRICT_RESERVED_WORD ||
|
| - next == Token::STRING || is_keyword) {
|
| - Handle<String> name;
|
| - if (is_keyword) {
|
| - name = isolate_->factory()->InternalizeUtf8String(Token::String(next));
|
| - } else {
|
| - name = GetSymbol();
|
| - }
|
| - FunctionLiteral* value =
|
| - ParseFunctionLiteral(name,
|
| - false, // reserved words are allowed here
|
| - false, // not a generator
|
| - RelocInfo::kNoPosition,
|
| - FunctionLiteral::ANONYMOUS_EXPRESSION,
|
| - CHECK_OK);
|
| - // Allow any number of parameters for compatibilty with JSC.
|
| - // Specification only allows zero parameters for get and one for set.
|
| - return factory()->NewObjectLiteralProperty(is_getter, value);
|
| - } else {
|
| - ReportUnexpectedToken(next);
|
| - *ok = false;
|
| - return NULL;
|
| - }
|
| -}
|
| +// Force instantiation of template instances class.
|
| +template void ObjectLiteralChecker<Parser>::CheckProperty(
|
| + Token::Value property, PropertyKind type, bool* ok);
|
|
|
|
|
| Expression* Parser::ParseObjectLiteral(bool* ok) {
|
| @@ -3968,7 +3860,8 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
|
| int number_of_boilerplate_properties = 0;
|
| bool has_function = false;
|
|
|
| - ObjectLiteralPropertyChecker checker(this, top_scope_->language_mode());
|
| + ObjectLiteralChecker<Parser> checker(this, &scanner_,
|
| + top_scope_->language_mode());
|
|
|
| Expect(Token::LBRACE, CHECK_OK);
|
|
|
| @@ -3978,9 +3871,6 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
|
| Literal* key = NULL;
|
| Token::Value next = peek();
|
|
|
| - // Location of the property name token
|
| - Scanner::Location loc = scanner().peek_location();
|
| -
|
| switch (next) {
|
| case Token::FUTURE_RESERVED_WORD:
|
| case Token::FUTURE_STRICT_RESERVED_WORD:
|
| @@ -3992,23 +3882,50 @@ 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, zone());
|
| - if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
|
| -
|
| - if (fni_ != NULL) {
|
| - fni_->Infer();
|
| - fni_->Leave();
|
| - }
|
| - continue; // restart the while
|
| + // Special handling of getter and setter syntax:
|
| + // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... }
|
| + // We have already read the "get" or "set" keyword.
|
| + Token::Value next = Next();
|
| + bool is_keyword = Token::IsKeyword(next);
|
| + if (next != i::Token::IDENTIFIER &&
|
| + next != i::Token::FUTURE_RESERVED_WORD &&
|
| + next != i::Token::FUTURE_STRICT_RESERVED_WORD &&
|
| + next != i::Token::NUMBER &&
|
| + next != i::Token::STRING &&
|
| + !is_keyword) {
|
| + // Unexpected token.
|
| + ReportUnexpectedToken(next);
|
| + *ok = false;
|
| + return NULL;
|
| + }
|
| + // Validate the property.
|
| + PropertyKind type = is_getter ? kGetterProperty : kSetterProperty;
|
| + checker.CheckProperty(next, type, CHECK_OK);
|
| + Handle<String> name = is_keyword
|
| + ? isolate_->factory()->InternalizeUtf8String(Token::String(next))
|
| + : GetSymbol();
|
| + FunctionLiteral* value =
|
| + ParseFunctionLiteral(name,
|
| + false, // reserved words are allowed here
|
| + false, // not a generator
|
| + RelocInfo::kNoPosition,
|
| + FunctionLiteral::ANONYMOUS_EXPRESSION,
|
| + CHECK_OK);
|
| + // Allow any number of parameters for compatibilty with JSC.
|
| + // Specification only allows zero parameters for get and one for set.
|
| + ObjectLiteral::Property* property =
|
| + factory()->NewObjectLiteralProperty(is_getter, value);
|
| + if (IsBoilerplateProperty(property)) {
|
| + number_of_boilerplate_properties++;
|
| + }
|
| + properties->Add(property, zone());
|
| + if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
|
| +
|
| + if (fni_ != NULL) {
|
| + fni_->Infer();
|
| + fni_->Leave();
|
| + }
|
| + continue; // restart the while
|
| }
|
| // Failed to parse as get/set property, so it's just a property
|
| // called "get" or "set".
|
| @@ -4051,6 +3968,9 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
|
| }
|
| }
|
|
|
| + // Validate the property
|
| + checker.CheckProperty(next, kValueProperty, CHECK_OK);
|
| +
|
| Expect(Token::COLON, CHECK_OK);
|
| Expression* value = ParseAssignmentExpression(true, CHECK_OK);
|
|
|
| @@ -4068,8 +3988,6 @@ 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, zone());
|
|
|
| // TODO(1240767): Consider allowing trailing comma.
|
|
|