|
|
@ -210,6 +210,7 @@ class Parser { |
|
|
|
Expression* ParsePrimaryExpression(bool* ok); |
|
|
|
Expression* ParseArrayLiteral(bool* ok); |
|
|
|
Expression* ParseObjectLiteral(bool* ok); |
|
|
|
ObjectLiteral::Property* ParseObjectLiteralGetSet(bool is_getter, bool* ok); |
|
|
|
Expression* ParseRegExpLiteral(bool seen_equal, bool* ok); |
|
|
|
|
|
|
|
// Populate the constant properties fixed array for a materialized object
|
|
|
@ -3376,11 +3377,7 @@ Expression* Parser::ParsePrimaryExpression(bool* ok) { |
|
|
|
// default case.
|
|
|
|
|
|
|
|
default: { |
|
|
|
Token::Value tok = peek(); |
|
|
|
// Token::Peek returns the value of the next token but
|
|
|
|
// location() gives info about the current token.
|
|
|
|
// Therefore, we need to read ahead to the next token
|
|
|
|
Next(); |
|
|
|
Token::Value tok = Next(); |
|
|
|
ReportUnexpectedToken(tok); |
|
|
|
*ok = false; |
|
|
|
return NULL; |
|
|
@ -3584,6 +3581,35 @@ 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(); |
|
|
|
if (next == Token::IDENTIFIER || |
|
|
|
next == Token::STRING || |
|
|
|
next == Token::NUMBER || |
|
|
|
Token::IsKeyword(next)) { |
|
|
|
Handle<String> name = |
|
|
|
factory()->LookupSymbol(scanner_.literal_string(), |
|
|
|
scanner_.literal_length()); |
|
|
|
FunctionLiteral* value = |
|
|
|
ParseFunctionLiteral(name, |
|
|
|
RelocInfo::kNoPosition, |
|
|
|
DECLARATION, |
|
|
|
CHECK_OK); |
|
|
|
ObjectLiteral::Property* property = |
|
|
|
NEW(ObjectLiteral::Property(is_getter, value)); |
|
|
|
return property; |
|
|
|
} else { |
|
|
|
ReportUnexpectedToken(next); |
|
|
|
*ok = false; |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Expression* Parser::ParseObjectLiteral(bool* ok) { |
|
|
|
// ObjectLiteral ::
|
|
|
|
// '{' (
|
|
|
@ -3601,32 +3627,13 @@ Expression* Parser::ParseObjectLiteral(bool* ok) { |
|
|
|
Token::Value next = peek(); |
|
|
|
switch (next) { |
|
|
|
case Token::IDENTIFIER: { |
|
|
|
// Store identifier keys as literal symbols to avoid
|
|
|
|
// resolving them when compiling code for the object
|
|
|
|
// literal.
|
|
|
|
bool is_getter = false; |
|
|
|
bool is_setter = false; |
|
|
|
Handle<String> id = |
|
|
|
ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK); |
|
|
|
if (is_getter || is_setter) { |
|
|
|
// Special handling of getter and setter syntax.
|
|
|
|
Handle<String> name; |
|
|
|
next = peek(); |
|
|
|
if (next == Token::IDENTIFIER || |
|
|
|
next == Token::STRING || |
|
|
|
next == Token::NUMBER || |
|
|
|
Token::IsKeyword(next)) { |
|
|
|
Consume(next); |
|
|
|
Handle<String> name = |
|
|
|
factory()->LookupSymbol(scanner_.literal_string(), |
|
|
|
scanner_.literal_length()); |
|
|
|
FunctionLiteral* value = |
|
|
|
ParseFunctionLiteral(name, |
|
|
|
RelocInfo::kNoPosition, |
|
|
|
DECLARATION, |
|
|
|
CHECK_OK); |
|
|
|
if ((is_getter || is_setter) && peek() != Token::COLON) { |
|
|
|
ObjectLiteral::Property* property = |
|
|
|
NEW(ObjectLiteral::Property(is_getter, value)); |
|
|
|
ParseObjectLiteralGetSet(is_getter, CHECK_OK); |
|
|
|
if (IsBoilerplateProperty(property)) { |
|
|
|
number_of_boilerplate_properties++; |
|
|
|
} |
|
|
@ -3634,31 +3641,25 @@ Expression* Parser::ParseObjectLiteral(bool* ok) { |
|
|
|
if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK); |
|
|
|
continue; // restart the while
|
|
|
|
} |
|
|
|
} |
|
|
|
// Failed to parse as get/set property, so it's just a property
|
|
|
|
// called "get" or "set".
|
|
|
|
key = NEW(Literal(id)); |
|
|
|
break; |
|
|
|
} |
|
|
|
#define CASE_KEYWORD(name, ignore1, ignore2) \ |
|
|
|
case Token::name: |
|
|
|
TOKEN_LIST(IGNORE_TOKEN, CASE_KEYWORD, IGNORE_TOKEN) |
|
|
|
#undef CASE_KEYWORD |
|
|
|
// FALLTHROUGH - keyword tokens fall through to the same code as strings.
|
|
|
|
case Token::STRING: { |
|
|
|
Consume(next); |
|
|
|
Consume(Token::STRING); |
|
|
|
Handle<String> string = |
|
|
|
factory()->LookupSymbol(scanner_.literal_string(), |
|
|
|
scanner_.literal_length()); |
|
|
|
uint32_t index; |
|
|
|
if (next == Token::STRING && |
|
|
|
!string.is_null() && |
|
|
|
if (!string.is_null() && |
|
|
|
string->AsArrayIndex(&index)) { |
|
|
|
key = NewNumberLiteral(index); |
|
|
|
} else { |
|
|
|
key = NEW(Literal(string)); |
|
|
|
break; |
|
|
|
} |
|
|
|
key = NEW(Literal(string)); |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
case Token::NUMBER: { |
|
|
|
Consume(Token::NUMBER); |
|
|
|
double value = |
|
|
@ -3666,10 +3667,20 @@ Expression* Parser::ParseObjectLiteral(bool* ok) { |
|
|
|
key = NewNumberLiteral(value); |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
default: |
|
|
|
Expect(Token::RBRACE, CHECK_OK); |
|
|
|
break; |
|
|
|
if (Token::IsKeyword(next)) { |
|
|
|
Consume(next); |
|
|
|
Handle<String> string = |
|
|
|
factory()->LookupSymbol(scanner_.literal_string(), |
|
|
|
scanner_.literal_length()); |
|
|
|
key = NEW(Literal(string)); |
|
|
|
} else { |
|
|
|
// Unexpected token.
|
|
|
|
Token::Value next = Next(); |
|
|
|
ReportUnexpectedToken(next); |
|
|
|
*ok = false; |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
Expect(Token::COLON, CHECK_OK); |
|
|
|