Chromium Code Reviews| 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/v8.h" | 8 #include "src/v8.h" |
| 9 | 9 |
| 10 #include "src/bailout-reason.h" | 10 #include "src/bailout-reason.h" |
| (...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 329 if (scanner()->HasAnyLineTerminatorBeforeNext() || | 329 if (scanner()->HasAnyLineTerminatorBeforeNext() || |
| 330 tok == Token::RBRACE || | 330 tok == Token::RBRACE || |
| 331 tok == Token::EOS) { | 331 tok == Token::EOS) { |
| 332 return; | 332 return; |
| 333 } | 333 } |
| 334 Expect(Token::SEMICOLON, ok); | 334 Expect(Token::SEMICOLON, ok); |
| 335 } | 335 } |
| 336 | 336 |
| 337 bool peek_any_identifier() { | 337 bool peek_any_identifier() { |
| 338 Token::Value next = peek(); | 338 Token::Value next = peek(); |
| 339 return next == Token::IDENTIFIER || | 339 return next == Token::IDENTIFIER || next == Token::FUTURE_RESERVED_WORD || |
| 340 next == Token::FUTURE_RESERVED_WORD || | 340 next == Token::FUTURE_STRICT_RESERVED_WORD || next == Token::LET || |
| 341 next == Token::FUTURE_STRICT_RESERVED_WORD || | 341 next == Token::STATIC || next == Token::YIELD; |
| 342 next == Token::LET || | |
| 343 next == Token::YIELD; | |
| 344 } | 342 } |
| 345 | 343 |
| 346 bool CheckContextualKeyword(Vector<const char> keyword) { | 344 bool CheckContextualKeyword(Vector<const char> keyword) { |
| 347 if (PeekContextualKeyword(keyword)) { | 345 if (PeekContextualKeyword(keyword)) { |
| 348 Consume(Token::IDENTIFIER); | 346 Consume(Token::IDENTIFIER); |
| 349 return true; | 347 return true; |
| 350 } | 348 } |
| 351 return false; | 349 return false; |
| 352 } | 350 } |
| 353 | 351 |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 599 } | 597 } |
| 600 static PreParserIdentifier FutureReserved() { | 598 static PreParserIdentifier FutureReserved() { |
| 601 return PreParserIdentifier(kFutureReservedIdentifier); | 599 return PreParserIdentifier(kFutureReservedIdentifier); |
| 602 } | 600 } |
| 603 static PreParserIdentifier FutureStrictReserved() { | 601 static PreParserIdentifier FutureStrictReserved() { |
| 604 return PreParserIdentifier(kFutureStrictReservedIdentifier); | 602 return PreParserIdentifier(kFutureStrictReservedIdentifier); |
| 605 } | 603 } |
| 606 static PreParserIdentifier Let() { | 604 static PreParserIdentifier Let() { |
| 607 return PreParserIdentifier(kLetIdentifier); | 605 return PreParserIdentifier(kLetIdentifier); |
| 608 } | 606 } |
| 607 static PreParserIdentifier Static() { | |
| 608 return PreParserIdentifier(kStaticIdentifier); | |
| 609 } | |
| 609 static PreParserIdentifier Yield() { | 610 static PreParserIdentifier Yield() { |
| 610 return PreParserIdentifier(kYieldIdentifier); | 611 return PreParserIdentifier(kYieldIdentifier); |
| 611 } | 612 } |
| 612 static PreParserIdentifier Prototype() { | 613 static PreParserIdentifier Prototype() { |
| 613 return PreParserIdentifier(kPrototypeIdentifier); | 614 return PreParserIdentifier(kPrototypeIdentifier); |
| 614 } | 615 } |
| 615 static PreParserIdentifier Constructor() { | 616 static PreParserIdentifier Constructor() { |
| 616 return PreParserIdentifier(kConstructorIdentifier); | 617 return PreParserIdentifier(kConstructorIdentifier); |
| 617 } | 618 } |
| 618 bool IsEval() const { return type_ == kEvalIdentifier; } | 619 bool IsEval() const { return type_ == kEvalIdentifier; } |
| 619 bool IsArguments(const AstValueFactory* = NULL) const { | 620 bool IsArguments(const AstValueFactory* = NULL) const { |
| 620 return type_ == kArgumentsIdentifier; | 621 return type_ == kArgumentsIdentifier; |
| 621 } | 622 } |
| 623 bool IsLet() const { return type_ == kLetIdentifier; } | |
| 624 bool IsStatic() const { return type_ == kStaticIdentifier; } | |
| 622 bool IsYield() const { return type_ == kYieldIdentifier; } | 625 bool IsYield() const { return type_ == kYieldIdentifier; } |
| 623 bool IsPrototype() const { return type_ == kPrototypeIdentifier; } | 626 bool IsPrototype() const { return type_ == kPrototypeIdentifier; } |
| 624 bool IsConstructor() const { return type_ == kConstructorIdentifier; } | 627 bool IsConstructor() const { return type_ == kConstructorIdentifier; } |
| 625 bool IsEvalOrArguments() const { | 628 bool IsEvalOrArguments() const { |
| 626 return type_ == kEvalIdentifier || type_ == kArgumentsIdentifier; | 629 return type_ == kEvalIdentifier || type_ == kArgumentsIdentifier; |
| 627 } | 630 } |
| 628 bool IsFutureReserved() const { return type_ == kFutureReservedIdentifier; } | 631 bool IsFutureReserved() const { return type_ == kFutureReservedIdentifier; } |
| 629 bool IsFutureStrictReserved() const { | 632 bool IsFutureStrictReserved() const { |
| 630 return type_ == kFutureStrictReservedIdentifier; | 633 return type_ == kFutureStrictReservedIdentifier || |
| 634 type_ == kLetIdentifier || type_ == kStaticIdentifier || | |
|
arv (Not doing code reviews)
2014/10/31 12:11:54
This is where the bug was. I had kEvalIdentifier i
| |
| 635 type_ == kYieldIdentifier; | |
| 631 } | 636 } |
| 632 bool IsValidStrictVariable() const { return type_ == kUnknownIdentifier; } | 637 bool IsValidStrictVariable() const { return type_ == kUnknownIdentifier; } |
| 633 V8_INLINE bool IsValidArrowParam() const { | 638 V8_INLINE bool IsValidArrowParam() const { |
| 634 // A valid identifier can be an arrow function parameter | 639 // A valid identifier can be an arrow function parameter |
| 635 // except for eval, arguments, yield, and reserved keywords. | 640 // except for eval, arguments, yield, and reserved keywords. |
| 636 return !(IsEval() || IsArguments() || IsYield() || | 641 return !(IsEval() || IsArguments() || IsFutureStrictReserved()); |
| 637 IsFutureStrictReserved()); | |
| 638 } | 642 } |
| 639 | 643 |
| 640 // Allow identifier->name()[->length()] to work. The preparser | 644 // Allow identifier->name()[->length()] to work. The preparser |
| 641 // does not need the actual positions/lengths of the identifiers. | 645 // does not need the actual positions/lengths of the identifiers. |
| 642 const PreParserIdentifier* operator->() const { return this; } | 646 const PreParserIdentifier* operator->() const { return this; } |
| 643 const PreParserIdentifier raw_name() const { return *this; } | 647 const PreParserIdentifier raw_name() const { return *this; } |
| 644 | 648 |
| 645 int position() const { return 0; } | 649 int position() const { return 0; } |
| 646 int length() const { return 0; } | 650 int length() const { return 0; } |
| 647 | 651 |
| 648 private: | 652 private: |
| 649 enum Type { | 653 enum Type { |
| 650 kUnknownIdentifier, | 654 kUnknownIdentifier, |
| 651 kFutureReservedIdentifier, | 655 kFutureReservedIdentifier, |
| 652 kFutureStrictReservedIdentifier, | 656 kFutureStrictReservedIdentifier, |
| 653 kLetIdentifier, | 657 kLetIdentifier, |
| 658 kStaticIdentifier, | |
| 654 kYieldIdentifier, | 659 kYieldIdentifier, |
| 655 kEvalIdentifier, | 660 kEvalIdentifier, |
| 656 kArgumentsIdentifier, | 661 kArgumentsIdentifier, |
| 657 kPrototypeIdentifier, | 662 kPrototypeIdentifier, |
| 658 kConstructorIdentifier | 663 kConstructorIdentifier |
| 659 }; | 664 }; |
| 660 explicit PreParserIdentifier(Type type) : type_(type) {} | 665 explicit PreParserIdentifier(Type type) : type_(type) {} |
| 661 Type type_; | 666 Type type_; |
| 662 | 667 |
| 663 friend class PreParserExpression; | 668 friend class PreParserExpression; |
| (...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1165 | 1170 |
| 1166 static bool IsIdentifier(PreParserExpression expression) { | 1171 static bool IsIdentifier(PreParserExpression expression) { |
| 1167 return expression.IsIdentifier(); | 1172 return expression.IsIdentifier(); |
| 1168 } | 1173 } |
| 1169 | 1174 |
| 1170 static PreParserIdentifier AsIdentifier(PreParserExpression expression) { | 1175 static PreParserIdentifier AsIdentifier(PreParserExpression expression) { |
| 1171 return expression.AsIdentifier(); | 1176 return expression.AsIdentifier(); |
| 1172 } | 1177 } |
| 1173 | 1178 |
| 1174 static bool IsFutureStrictReserved(PreParserIdentifier identifier) { | 1179 static bool IsFutureStrictReserved(PreParserIdentifier identifier) { |
| 1175 return identifier.IsYield() || identifier.IsFutureStrictReserved(); | 1180 return identifier.IsFutureStrictReserved(); |
| 1176 } | 1181 } |
| 1177 | 1182 |
| 1178 static bool IsBoilerplateProperty(PreParserExpression property) { | 1183 static bool IsBoilerplateProperty(PreParserExpression property) { |
| 1179 // PreParser doesn't count boilerplate properties. | 1184 // PreParser doesn't count boilerplate properties. |
| 1180 return false; | 1185 return false; |
| 1181 } | 1186 } |
| 1182 | 1187 |
| 1183 static bool IsArrayIndex(PreParserIdentifier string, uint32_t* index) { | 1188 static bool IsArrayIndex(PreParserIdentifier string, uint32_t* index) { |
| 1184 return false; | 1189 return false; |
| 1185 } | 1190 } |
| (...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1586 return ReportMessageAt(source_location, "unexpected_eos"); | 1591 return ReportMessageAt(source_location, "unexpected_eos"); |
| 1587 case Token::NUMBER: | 1592 case Token::NUMBER: |
| 1588 return ReportMessageAt(source_location, "unexpected_token_number"); | 1593 return ReportMessageAt(source_location, "unexpected_token_number"); |
| 1589 case Token::STRING: | 1594 case Token::STRING: |
| 1590 return ReportMessageAt(source_location, "unexpected_token_string"); | 1595 return ReportMessageAt(source_location, "unexpected_token_string"); |
| 1591 case Token::IDENTIFIER: | 1596 case Token::IDENTIFIER: |
| 1592 return ReportMessageAt(source_location, "unexpected_token_identifier"); | 1597 return ReportMessageAt(source_location, "unexpected_token_identifier"); |
| 1593 case Token::FUTURE_RESERVED_WORD: | 1598 case Token::FUTURE_RESERVED_WORD: |
| 1594 return ReportMessageAt(source_location, "unexpected_reserved"); | 1599 return ReportMessageAt(source_location, "unexpected_reserved"); |
| 1595 case Token::LET: | 1600 case Token::LET: |
| 1601 case Token::STATIC: | |
| 1596 case Token::YIELD: | 1602 case Token::YIELD: |
| 1597 case Token::FUTURE_STRICT_RESERVED_WORD: | 1603 case Token::FUTURE_STRICT_RESERVED_WORD: |
| 1598 return ReportMessageAt(source_location, strict_mode() == SLOPPY | 1604 return ReportMessageAt(source_location, strict_mode() == SLOPPY |
| 1599 ? "unexpected_token_identifier" : "unexpected_strict_reserved"); | 1605 ? "unexpected_token_identifier" : "unexpected_strict_reserved"); |
| 1600 default: | 1606 default: |
| 1601 const char* name = Token::String(token); | 1607 const char* name = Token::String(token); |
| 1602 DCHECK(name != NULL); | 1608 DCHECK(name != NULL); |
| 1603 Traits::ReportMessageAt(source_location, "unexpected_token", name); | 1609 Traits::ReportMessageAt(source_location, "unexpected_token", name); |
| 1604 } | 1610 } |
| 1605 } | 1611 } |
| 1606 | 1612 |
| 1607 | 1613 |
| 1608 template<class Traits> | 1614 template<class Traits> |
| 1609 typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParseIdentifier( | 1615 typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParseIdentifier( |
| 1610 AllowEvalOrArgumentsAsIdentifier allow_eval_or_arguments, | 1616 AllowEvalOrArgumentsAsIdentifier allow_eval_or_arguments, |
| 1611 bool* ok) { | 1617 bool* ok) { |
| 1612 Token::Value next = Next(); | 1618 Token::Value next = Next(); |
| 1613 if (next == Token::IDENTIFIER) { | 1619 if (next == Token::IDENTIFIER) { |
| 1614 IdentifierT name = this->GetSymbol(scanner()); | 1620 IdentifierT name = this->GetSymbol(scanner()); |
| 1615 if (allow_eval_or_arguments == kDontAllowEvalOrArguments && | 1621 if (allow_eval_or_arguments == kDontAllowEvalOrArguments && |
| 1616 strict_mode() == STRICT && this->IsEvalOrArguments(name)) { | 1622 strict_mode() == STRICT && this->IsEvalOrArguments(name)) { |
| 1617 ReportMessage("strict_eval_arguments"); | 1623 ReportMessage("strict_eval_arguments"); |
| 1618 *ok = false; | 1624 *ok = false; |
| 1619 } | 1625 } |
| 1620 if (name->IsArguments(this->ast_value_factory())) | 1626 if (name->IsArguments(this->ast_value_factory())) |
| 1621 scope_->RecordArgumentsUsage(); | 1627 scope_->RecordArgumentsUsage(); |
| 1622 return name; | 1628 return name; |
| 1623 } else if (strict_mode() == SLOPPY && | 1629 } else if (strict_mode() == SLOPPY && |
| 1624 (next == Token::FUTURE_STRICT_RESERVED_WORD || | 1630 (next == Token::FUTURE_STRICT_RESERVED_WORD || |
| 1625 (next == Token::LET) || | 1631 next == Token::LET || next == Token::STATIC || |
| 1626 (next == Token::YIELD && !is_generator()))) { | 1632 (next == Token::YIELD && !is_generator()))) { |
| 1627 return this->GetSymbol(scanner()); | 1633 return this->GetSymbol(scanner()); |
| 1628 } else { | 1634 } else { |
| 1629 this->ReportUnexpectedToken(next); | 1635 this->ReportUnexpectedToken(next); |
| 1630 *ok = false; | 1636 *ok = false; |
| 1631 return Traits::EmptyIdentifier(); | 1637 return Traits::EmptyIdentifier(); |
| 1632 } | 1638 } |
| 1633 } | 1639 } |
| 1634 | 1640 |
| 1635 | 1641 |
| 1636 template <class Traits> | 1642 template <class Traits> |
| 1637 typename ParserBase<Traits>::IdentifierT ParserBase< | 1643 typename ParserBase<Traits>::IdentifierT ParserBase< |
| 1638 Traits>::ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved, | 1644 Traits>::ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved, |
| 1639 bool* ok) { | 1645 bool* ok) { |
| 1640 Token::Value next = Next(); | 1646 Token::Value next = Next(); |
| 1641 if (next == Token::IDENTIFIER) { | 1647 if (next == Token::IDENTIFIER) { |
| 1642 *is_strict_reserved = false; | 1648 *is_strict_reserved = false; |
| 1643 } else if (next == Token::FUTURE_STRICT_RESERVED_WORD || | 1649 } else if (next == Token::FUTURE_STRICT_RESERVED_WORD || next == Token::LET || |
| 1644 next == Token::LET || | 1650 next == Token::STATIC || |
| 1645 (next == Token::YIELD && !this->is_generator())) { | 1651 (next == Token::YIELD && !this->is_generator())) { |
| 1646 *is_strict_reserved = true; | 1652 *is_strict_reserved = true; |
| 1647 } else { | 1653 } else { |
| 1648 ReportUnexpectedToken(next); | 1654 ReportUnexpectedToken(next); |
| 1649 *ok = false; | 1655 *ok = false; |
| 1650 return Traits::EmptyIdentifier(); | 1656 return Traits::EmptyIdentifier(); |
| 1651 } | 1657 } |
| 1652 | 1658 |
| 1653 IdentifierT name = this->GetSymbol(scanner()); | 1659 IdentifierT name = this->GetSymbol(scanner()); |
| 1654 if (name->IsArguments(this->ast_value_factory())) | 1660 if (name->IsArguments(this->ast_value_factory())) |
| 1655 scope_->RecordArgumentsUsage(); | 1661 scope_->RecordArgumentsUsage(); |
| 1656 return name; | 1662 return name; |
| 1657 } | 1663 } |
| 1658 | 1664 |
| 1659 | 1665 |
| 1660 template <class Traits> | 1666 template <class Traits> |
| 1661 typename ParserBase<Traits>::IdentifierT | 1667 typename ParserBase<Traits>::IdentifierT |
| 1662 ParserBase<Traits>::ParseIdentifierName(bool* ok) { | 1668 ParserBase<Traits>::ParseIdentifierName(bool* ok) { |
| 1663 Token::Value next = Next(); | 1669 Token::Value next = Next(); |
| 1664 if (next != Token::IDENTIFIER && next != Token::FUTURE_RESERVED_WORD && | 1670 if (next != Token::IDENTIFIER && next != Token::FUTURE_RESERVED_WORD && |
| 1665 next != Token::LET && next != Token::YIELD && | 1671 next != Token::LET && next != Token::STATIC && next != Token::YIELD && |
| 1666 next != Token::FUTURE_STRICT_RESERVED_WORD && !Token::IsKeyword(next)) { | 1672 next != Token::FUTURE_STRICT_RESERVED_WORD && !Token::IsKeyword(next)) { |
| 1667 this->ReportUnexpectedToken(next); | 1673 this->ReportUnexpectedToken(next); |
| 1668 *ok = false; | 1674 *ok = false; |
| 1669 return Traits::EmptyIdentifier(); | 1675 return Traits::EmptyIdentifier(); |
| 1670 } | 1676 } |
| 1671 | 1677 |
| 1672 IdentifierT name = this->GetSymbol(scanner()); | 1678 IdentifierT name = this->GetSymbol(scanner()); |
| 1673 if (name->IsArguments(this->ast_value_factory())) | 1679 if (name->IsArguments(this->ast_value_factory())) |
| 1674 scope_->RecordArgumentsUsage(); | 1680 scope_->RecordArgumentsUsage(); |
| 1675 return name; | 1681 return name; |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1758 case Token::NULL_LITERAL: | 1764 case Token::NULL_LITERAL: |
| 1759 case Token::TRUE_LITERAL: | 1765 case Token::TRUE_LITERAL: |
| 1760 case Token::FALSE_LITERAL: | 1766 case Token::FALSE_LITERAL: |
| 1761 case Token::NUMBER: | 1767 case Token::NUMBER: |
| 1762 Next(); | 1768 Next(); |
| 1763 result = this->ExpressionFromLiteral(token, pos, scanner(), factory()); | 1769 result = this->ExpressionFromLiteral(token, pos, scanner(), factory()); |
| 1764 break; | 1770 break; |
| 1765 | 1771 |
| 1766 case Token::IDENTIFIER: | 1772 case Token::IDENTIFIER: |
| 1767 case Token::LET: | 1773 case Token::LET: |
| 1774 case Token::STATIC: | |
| 1768 case Token::YIELD: | 1775 case Token::YIELD: |
| 1769 case Token::FUTURE_STRICT_RESERVED_WORD: { | 1776 case Token::FUTURE_STRICT_RESERVED_WORD: { |
| 1770 // Using eval or arguments in this context is OK even in strict mode. | 1777 // Using eval or arguments in this context is OK even in strict mode. |
| 1771 IdentifierT name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); | 1778 IdentifierT name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); |
| 1772 result = this->ExpressionFromIdentifier(name, pos, scope_, factory()); | 1779 result = this->ExpressionFromIdentifier(name, pos, scope_, factory()); |
| 1773 break; | 1780 break; |
| 1774 } | 1781 } |
| 1775 | 1782 |
| 1776 case Token::STRING: { | 1783 case Token::STRING: { |
| 1777 Consume(Token::STRING); | 1784 Consume(Token::STRING); |
| (...skipping 1063 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2841 DCHECK(IsAccessorAccessorConflict(old_type, type)); | 2848 DCHECK(IsAccessorAccessorConflict(old_type, type)); |
| 2842 // Both accessors of the same type. | 2849 // Both accessors of the same type. |
| 2843 parser()->ReportMessage("accessor_get_set"); | 2850 parser()->ReportMessage("accessor_get_set"); |
| 2844 } | 2851 } |
| 2845 *ok = false; | 2852 *ok = false; |
| 2846 } | 2853 } |
| 2847 } | 2854 } |
| 2848 } } // v8::internal | 2855 } } // v8::internal |
| 2849 | 2856 |
| 2850 #endif // V8_PREPARSER_H | 2857 #endif // V8_PREPARSER_H |
| OLD | NEW |