|
|
@ -265,6 +265,7 @@ class Parser { |
|
|
|
Literal* GetLiteralNumber(double value); |
|
|
|
|
|
|
|
Handle<String> ParseIdentifier(bool* ok); |
|
|
|
Handle<String> ParseIdentifierName(bool* ok); |
|
|
|
Handle<String> ParseIdentifierOrGetOrSet(bool* is_get, |
|
|
|
bool* is_set, |
|
|
|
bool* ok); |
|
|
@ -3121,7 +3122,7 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) { |
|
|
|
case Token::PERIOD: { |
|
|
|
Consume(Token::PERIOD); |
|
|
|
int pos = scanner().location().beg_pos; |
|
|
|
Handle<String> name = ParseIdentifier(CHECK_OK); |
|
|
|
Handle<String> name = ParseIdentifierName(CHECK_OK); |
|
|
|
result = factory()->NewProperty(result, NEW(Literal(name)), pos); |
|
|
|
break; |
|
|
|
} |
|
|
@ -3207,7 +3208,7 @@ Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack, |
|
|
|
case Token::PERIOD: { |
|
|
|
Consume(Token::PERIOD); |
|
|
|
int pos = scanner().location().beg_pos; |
|
|
|
Handle<String> name = ParseIdentifier(CHECK_OK); |
|
|
|
Handle<String> name = ParseIdentifierName(CHECK_OK); |
|
|
|
result = factory()->NewProperty(result, NEW(Literal(name)), pos); |
|
|
|
break; |
|
|
|
} |
|
|
@ -3586,8 +3587,8 @@ void Parser::BuildObjectLiteralConstantProperties( |
|
|
|
Expression* Parser::ParseObjectLiteral(bool* ok) { |
|
|
|
// ObjectLiteral ::
|
|
|
|
// '{' (
|
|
|
|
// ((Identifier | String | Number) ':' AssignmentExpression)
|
|
|
|
// | (('get' | 'set') FunctionLiteral)
|
|
|
|
// ((IdentifierName | String | Number) ':' AssignmentExpression)
|
|
|
|
// | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
|
|
|
|
// )*[','] '}'
|
|
|
|
|
|
|
|
ZoneListWrapper<ObjectLiteral::Property> properties = |
|
|
@ -3597,7 +3598,8 @@ Expression* Parser::ParseObjectLiteral(bool* ok) { |
|
|
|
Expect(Token::LBRACE, CHECK_OK); |
|
|
|
while (peek() != Token::RBRACE) { |
|
|
|
Literal* key = NULL; |
|
|
|
switch (peek()) { |
|
|
|
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
|
|
|
@ -3608,15 +3610,26 @@ Expression* Parser::ParseObjectLiteral(bool* ok) { |
|
|
|
ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK); |
|
|
|
if (is_getter || is_setter) { |
|
|
|
// Special handling of getter and setter syntax.
|
|
|
|
if (peek() == Token::IDENTIFIER) { |
|
|
|
Handle<String> name = ParseIdentifier(CHECK_OK); |
|
|
|
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); |
|
|
|
ParseFunctionLiteral(name, |
|
|
|
RelocInfo::kNoPosition, |
|
|
|
DECLARATION, |
|
|
|
CHECK_OK); |
|
|
|
ObjectLiteral::Property* property = |
|
|
|
NEW(ObjectLiteral::Property(is_getter, value)); |
|
|
|
if (IsBoilerplateProperty(property)) |
|
|
|
if (IsBoilerplateProperty(property)) { |
|
|
|
number_of_boilerplate_properties++; |
|
|
|
} |
|
|
|
properties.Add(property); |
|
|
|
if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK); |
|
|
|
continue; // restart the while
|
|
|
@ -3625,14 +3638,20 @@ Expression* Parser::ParseObjectLiteral(bool* ok) { |
|
|
|
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(Token::STRING); |
|
|
|
Consume(next); |
|
|
|
Handle<String> string = |
|
|
|
factory()->LookupSymbol(scanner_.literal_string(), |
|
|
|
scanner_.literal_length()); |
|
|
|
uint32_t index; |
|
|
|
if (!string.is_null() && string->AsArrayIndex(&index)) { |
|
|
|
if (next == Token::STRING && |
|
|
|
!string.is_null() && |
|
|
|
string->AsArrayIndex(&index)) { |
|
|
|
key = NewNumberLiteral(index); |
|
|
|
} else { |
|
|
|
key = NEW(Literal(string)); |
|
|
@ -4008,6 +4027,19 @@ Handle<String> Parser::ParseIdentifier(bool* ok) { |
|
|
|
scanner_.literal_length()); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Handle<String> Parser::ParseIdentifierName(bool* ok) { |
|
|
|
Token::Value next = Next(); |
|
|
|
if (next != Token::IDENTIFIER && !Token::IsKeyword(next)) { |
|
|
|
ReportUnexpectedToken(next); |
|
|
|
*ok = false; |
|
|
|
return Handle<String>(); |
|
|
|
} |
|
|
|
return factory()->LookupSymbol(scanner_.literal_string(), |
|
|
|
scanner_.literal_length()); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// This function reads an identifier and determines whether or not it
|
|
|
|
// is 'get' or 'set'. The reason for not using ParseIdentifier and
|
|
|
|
// checking on the output is that this involves heap allocation which
|
|
|
|