OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_PREPARSER_H | 5 #ifndef V8_PREPARSER_H |
6 #define V8_PREPARSER_H | 6 #define V8_PREPARSER_H |
7 | 7 |
8 #include "src/func-name-inferrer.h" | 8 #include "src/func-name-inferrer.h" |
9 #include "src/hashmap.h" | 9 #include "src/hashmap.h" |
10 #include "src/scopes.h" | 10 #include "src/scopes.h" |
(...skipping 751 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
762 int literal_index, | 762 int literal_index, |
763 int pos) { | 763 int pos) { |
764 return PreParserExpression::Default(); | 764 return PreParserExpression::Default(); |
765 } | 765 } |
766 PreParserExpression NewObjectLiteralProperty(bool is_getter, | 766 PreParserExpression NewObjectLiteralProperty(bool is_getter, |
767 PreParserExpression value, | 767 PreParserExpression value, |
768 int pos) { | 768 int pos) { |
769 return PreParserExpression::Default(); | 769 return PreParserExpression::Default(); |
770 } | 770 } |
771 PreParserExpression NewObjectLiteralProperty(PreParserExpression key, | 771 PreParserExpression NewObjectLiteralProperty(PreParserExpression key, |
772 PreParserExpression value) { | 772 PreParserExpression value, |
773 bool is_computed_name) { | |
773 return PreParserExpression::Default(); | 774 return PreParserExpression::Default(); |
774 } | 775 } |
775 PreParserExpression NewObjectLiteral(PreParserExpressionList properties, | 776 PreParserExpression NewObjectLiteral(PreParserExpressionList properties, |
776 int literal_index, | 777 int literal_index, |
777 int boilerplate_properties, | 778 int boilerplate_properties, |
778 bool has_function, | 779 bool has_function, |
779 int pos) { | 780 int pos) { |
780 return PreParserExpression::Default(); | 781 return PreParserExpression::Default(); |
781 } | 782 } |
782 PreParserExpression NewVariableProxy(void* generator_variable) { | 783 PreParserExpression NewVariableProxy(void* generator_variable) { |
(...skipping 706 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1489 return factory()->NewArrayLiteral(values, literal_index, pos); | 1490 return factory()->NewArrayLiteral(values, literal_index, pos); |
1490 } | 1491 } |
1491 | 1492 |
1492 | 1493 |
1493 template <class Traits> | 1494 template <class Traits> |
1494 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral( | 1495 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral( |
1495 bool* ok) { | 1496 bool* ok) { |
1496 // ObjectLiteral :: | 1497 // ObjectLiteral :: |
1497 // '{' (( | 1498 // '{' (( |
1498 // ((IdentifierName | String | Number) ':' AssignmentExpression) | | 1499 // ((IdentifierName | String | Number) ':' AssignmentExpression) | |
1499 // (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) | 1500 // (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)| |
1501 // ('[' AssignmentExpression ']' ':' AssignmentExpression) | |
1500 // ) ',')* '}' | 1502 // ) ',')* '}' |
1501 // (Except that trailing comma is not required and not allowed.) | 1503 // (Except that trailing comma is not required and not allowed.) |
1502 | 1504 |
1503 int pos = peek_position(); | 1505 int pos = peek_position(); |
1504 typename Traits::Type::PropertyList properties = | 1506 typename Traits::Type::PropertyList properties = |
1505 this->NewPropertyList(4, zone_); | 1507 this->NewPropertyList(4, zone_); |
1506 int number_of_boilerplate_properties = 0; | 1508 int number_of_boilerplate_properties = 0; |
1507 bool has_function = false; | 1509 bool has_function = false; |
1510 bool has_computed_names = false; | |
1508 | 1511 |
1509 ObjectLiteralChecker checker(this, strict_mode()); | 1512 ObjectLiteralChecker checker(this, strict_mode()); |
1510 | 1513 |
1511 Expect(Token::LBRACE, CHECK_OK); | 1514 Expect(Token::LBRACE, CHECK_OK); |
1512 | 1515 |
1513 while (peek() != Token::RBRACE) { | 1516 while (peek() != Token::RBRACE) { |
1514 if (fni_ != NULL) fni_->Enter(); | 1517 if (fni_ != NULL) fni_->Enter(); |
1515 | 1518 |
1516 typename Traits::Type::Literal key = this->EmptyLiteral(); | 1519 bool is_computed_name = false; |
1520 ExpressionT key = this->EmptyLiteral(); | |
1517 Token::Value next = peek(); | 1521 Token::Value next = peek(); |
1518 int next_pos = peek_position(); | 1522 int next_pos = peek_position(); |
1519 | 1523 |
1520 switch (next) { | 1524 switch (next) { |
1521 case Token::FUTURE_RESERVED_WORD: | 1525 case Token::FUTURE_RESERVED_WORD: |
1522 case Token::FUTURE_STRICT_RESERVED_WORD: | 1526 case Token::FUTURE_STRICT_RESERVED_WORD: |
1523 case Token::IDENTIFIER: { | 1527 case Token::IDENTIFIER: { |
1524 bool is_getter = false; | 1528 bool is_getter = false; |
1525 bool is_setter = false; | 1529 bool is_setter = false; |
1526 IdentifierT id = | 1530 IdentifierT id = |
1527 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK); | 1531 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK); |
1528 if (fni_ != NULL) this->PushLiteralName(fni_, id); | 1532 if (fni_ != NULL) this->PushLiteralName(fni_, id); |
1529 | 1533 |
1530 if ((is_getter || is_setter) && peek() != Token::COLON) { | 1534 if ((is_getter || is_setter) && peek() != Token::COLON) { |
1531 // Special handling of getter and setter syntax: | 1535 // Special handling of getter and setter syntax: |
1532 // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... } | 1536 // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... } |
1533 // We have already read the "get" or "set" keyword. | 1537 // We have already read the "get" or "set" keyword. |
1534 Token::Value next = Next(); | 1538 Token::Value next = Next(); |
1535 if (next != i::Token::IDENTIFIER && | 1539 if (next != i::Token::IDENTIFIER && |
1536 next != i::Token::FUTURE_RESERVED_WORD && | 1540 next != i::Token::FUTURE_RESERVED_WORD && |
1537 next != i::Token::FUTURE_STRICT_RESERVED_WORD && | 1541 next != i::Token::FUTURE_STRICT_RESERVED_WORD && |
1538 next != i::Token::NUMBER && | 1542 next != i::Token::NUMBER && |
1539 next != i::Token::STRING && | 1543 next != i::Token::STRING && |
1540 !Token::IsKeyword(next)) { | 1544 !Token::IsKeyword(next)) { |
1545 // FIXME(wingo): Add support for computed property names here, as in | |
1546 // get [AssignmentExpression]() { .. }. | |
1541 ReportUnexpectedToken(next); | 1547 ReportUnexpectedToken(next); |
1542 *ok = false; | 1548 *ok = false; |
1543 return this->EmptyLiteral(); | 1549 return this->EmptyLiteral(); |
1544 } | 1550 } |
1545 // Validate the property. | 1551 // Validate the property. |
1546 PropertyKind type = is_getter ? kGetterProperty : kSetterProperty; | 1552 PropertyKind type = is_getter ? kGetterProperty : kSetterProperty; |
1547 checker.CheckProperty(next, type, CHECK_OK); | 1553 checker.CheckProperty(next, type, CHECK_OK); |
1548 IdentifierT name = this->GetSymbol(scanner_); | 1554 IdentifierT name = this->GetSymbol(scanner_); |
1549 typename Traits::Type::FunctionLiteral value = | 1555 typename Traits::Type::FunctionLiteral value = |
1550 this->ParseFunctionLiteral( | 1556 this->ParseFunctionLiteral( |
1551 name, scanner()->location(), | 1557 name, scanner()->location(), |
1552 false, // reserved words are allowed here | 1558 false, // reserved words are allowed here |
1553 false, // not a generator | 1559 false, // not a generator |
1554 RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION, | 1560 RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION, |
1555 CHECK_OK); | 1561 CHECK_OK); |
1556 // Allow any number of parameters for compatibilty with JSC. | 1562 // Allow any number of parameters for compatibilty with JSC. |
1557 // Specification only allows zero parameters for get and one for set. | 1563 // Specification only allows zero parameters for get and one for set. |
1558 typename Traits::Type::ObjectLiteralProperty property = | 1564 typename Traits::Type::ObjectLiteralProperty property = |
1559 factory()->NewObjectLiteralProperty(is_getter, value, next_pos); | 1565 factory()->NewObjectLiteralProperty(is_getter, value, next_pos); |
1560 if (this->IsBoilerplateProperty(property)) { | 1566 if (!has_computed_names && this->IsBoilerplateProperty(property)) { |
1561 number_of_boilerplate_properties++; | 1567 number_of_boilerplate_properties++; |
1562 } | 1568 } |
1563 properties->Add(property, zone()); | 1569 properties->Add(property, zone()); |
1564 if (peek() != Token::RBRACE) { | 1570 if (peek() != Token::RBRACE) { |
1565 // Need {} because of the CHECK_OK macro. | 1571 // Need {} because of the CHECK_OK macro. |
1566 Expect(Token::COMMA, CHECK_OK); | 1572 Expect(Token::COMMA, CHECK_OK); |
1567 } | 1573 } |
1568 | 1574 |
1569 if (fni_ != NULL) { | 1575 if (fni_ != NULL) { |
1570 fni_->Infer(); | 1576 fni_->Infer(); |
(...skipping 17 matching lines...) Expand all Loading... | |
1588 } | 1594 } |
1589 key = factory()->NewLiteral(string, next_pos); | 1595 key = factory()->NewLiteral(string, next_pos); |
1590 break; | 1596 break; |
1591 } | 1597 } |
1592 case Token::NUMBER: { | 1598 case Token::NUMBER: { |
1593 Consume(Token::NUMBER); | 1599 Consume(Token::NUMBER); |
1594 key = this->ExpressionFromLiteral(Token::NUMBER, next_pos, scanner_, | 1600 key = this->ExpressionFromLiteral(Token::NUMBER, next_pos, scanner_, |
1595 factory()); | 1601 factory()); |
1596 break; | 1602 break; |
1597 } | 1603 } |
1604 case Token::LBRACK: { | |
1605 Consume(Token::LBRACK); | |
1606 has_computed_names = true; | |
1607 is_computed_name = true; | |
Michael Starzinger
2014/06/13 08:14:18
Shouldn't the detection of this syntax live behind
rossberg
2014/06/13 15:19:24
I agree, we should have --harmony-object-literals
wingo
2014/06/16 08:32:27
Done.
| |
1608 key = this->ParseAssignmentExpression(true, CHECK_OK); | |
1609 Expect(Token::RBRACK, CHECK_OK); | |
1610 break; | |
1611 } | |
1598 default: | 1612 default: |
1599 if (Token::IsKeyword(next)) { | 1613 if (Token::IsKeyword(next)) { |
1600 Consume(next); | 1614 Consume(next); |
1601 IdentifierT string = this->GetSymbol(scanner_); | 1615 IdentifierT string = this->GetSymbol(scanner_); |
1602 key = factory()->NewLiteral(string, next_pos); | 1616 key = factory()->NewLiteral(string, next_pos); |
1603 } else { | 1617 } else { |
1604 Token::Value next = Next(); | 1618 Token::Value next = Next(); |
1605 ReportUnexpectedToken(next); | 1619 ReportUnexpectedToken(next); |
1606 *ok = false; | 1620 *ok = false; |
1607 return this->EmptyLiteral(); | 1621 return this->EmptyLiteral(); |
1608 } | 1622 } |
1609 } | 1623 } |
1610 | 1624 |
1611 // Validate the property | 1625 // Validate the property |
1612 checker.CheckProperty(next, kValueProperty, CHECK_OK); | 1626 if (!is_computed_name) { |
1627 checker.CheckProperty(next, kValueProperty, CHECK_OK); | |
1628 } | |
1613 | 1629 |
1614 Expect(Token::COLON, CHECK_OK); | 1630 Expect(Token::COLON, CHECK_OK); |
1615 ExpressionT value = this->ParseAssignmentExpression(true, CHECK_OK); | 1631 ExpressionT value = this->ParseAssignmentExpression(true, CHECK_OK); |
1616 | 1632 |
1617 typename Traits::Type::ObjectLiteralProperty property = | 1633 typename Traits::Type::ObjectLiteralProperty property = |
1618 factory()->NewObjectLiteralProperty(key, value); | 1634 factory()->NewObjectLiteralProperty(key, value, is_computed_name); |
1619 | 1635 |
1620 // Mark top-level object literals that contain function literals and | 1636 // Mark top-level object literals that contain function literals and |
1621 // pretenure the literal so it can be added as a constant function | 1637 // pretenure the literal so it can be added as a constant function |
1622 // property. (Parser only.) | 1638 // property. (Parser only.) |
1623 this->CheckFunctionLiteralInsideTopLevelObjectLiteral(scope_, value, | 1639 this->CheckFunctionLiteralInsideTopLevelObjectLiteral(scope_, value, |
1624 &has_function); | 1640 &has_function); |
1625 | 1641 |
1626 // Count CONSTANT or COMPUTED properties to maintain the enumeration order. | 1642 // Count CONSTANT or COMPUTED properties to maintain the enumeration order. |
1627 if (this->IsBoilerplateProperty(property)) { | 1643 if (!has_computed_names && this->IsBoilerplateProperty(property)) { |
1628 number_of_boilerplate_properties++; | 1644 number_of_boilerplate_properties++; |
1629 } | 1645 } |
1630 properties->Add(property, zone()); | 1646 properties->Add(property, zone()); |
1631 | 1647 |
1632 // TODO(1240767): Consider allowing trailing comma. | 1648 // TODO(1240767): Consider allowing trailing comma. |
1633 if (peek() != Token::RBRACE) { | 1649 if (peek() != Token::RBRACE) { |
1634 // Need {} because of the CHECK_OK macro. | 1650 // Need {} because of the CHECK_OK macro. |
1635 Expect(Token::COMMA, CHECK_OK); | 1651 Expect(Token::COMMA, CHECK_OK); |
1636 } | 1652 } |
1637 | 1653 |
(...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2161 parser()->ReportMessage("accessor_get_set"); | 2177 parser()->ReportMessage("accessor_get_set"); |
2162 } | 2178 } |
2163 *ok = false; | 2179 *ok = false; |
2164 } | 2180 } |
2165 } | 2181 } |
2166 | 2182 |
2167 | 2183 |
2168 } } // v8::internal | 2184 } } // v8::internal |
2169 | 2185 |
2170 #endif // V8_PREPARSER_H | 2186 #endif // V8_PREPARSER_H |
OLD | NEW |