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 #include "src/parsing/parser.h" | 5 #include "src/parsing/parser.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 | 8 |
9 #include "src/api.h" | 9 #include "src/api.h" |
10 #include "src/ast/ast-expression-rewriter.h" | 10 #include "src/ast/ast-expression-rewriter.h" |
(...skipping 1602 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1613 !is_async && !(allow_harmony_restrictive_generators() && is_generator)) { | 1613 !is_async && !(allow_harmony_restrictive_generators() && is_generator)) { |
1614 SloppyBlockFunctionStatement* delegate = | 1614 SloppyBlockFunctionStatement* delegate = |
1615 factory()->NewSloppyBlockFunctionStatement(scope()); | 1615 factory()->NewSloppyBlockFunctionStatement(scope()); |
1616 DeclarationScope* target_scope = GetDeclarationScope(); | 1616 DeclarationScope* target_scope = GetDeclarationScope(); |
1617 target_scope->DeclareSloppyBlockFunction(variable_name, delegate); | 1617 target_scope->DeclareSloppyBlockFunction(variable_name, delegate); |
1618 return delegate; | 1618 return delegate; |
1619 } | 1619 } |
1620 return factory()->NewEmptyStatement(kNoSourcePosition); | 1620 return factory()->NewEmptyStatement(kNoSourcePosition); |
1621 } | 1621 } |
1622 | 1622 |
1623 static bool ContainsLabel(ZoneList<const AstRawString*>* labels, | 1623 ZoneList<const AstRawString*>* Parser::DeclareLabel( |
1624 const AstRawString* label) { | 1624 ZoneList<const AstRawString*>* labels, VariableProxy* var, bool* ok) { |
1625 DCHECK(label != NULL); | 1625 const AstRawString* label = var->raw_name(); |
1626 if (labels != NULL) { | 1626 // TODO(1240780): We don't check for redeclaration of labels |
1627 for (int i = labels->length(); i-- > 0; ) { | 1627 // during preparsing since keeping track of the set of active |
1628 if (labels->at(i) == label) { | 1628 // labels requires nontrivial changes to the way scopes are |
1629 return true; | 1629 // structured. However, these are probably changes we want to |
1630 } | 1630 // make later anyway so we should go back and fix this then. |
| 1631 if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) { |
| 1632 ReportMessage(MessageTemplate::kLabelRedeclaration, label); |
| 1633 *ok = false; |
| 1634 return nullptr; |
| 1635 } |
| 1636 if (labels == nullptr) { |
| 1637 labels = new (zone()) ZoneList<const AstRawString*>(1, zone()); |
| 1638 } |
| 1639 labels->Add(label, zone()); |
| 1640 // Remove the "ghost" variable that turned out to be a label |
| 1641 // from the top scope. This way, we don't try to resolve it |
| 1642 // during the scope processing. |
| 1643 scope()->RemoveUnresolved(var); |
| 1644 return labels; |
| 1645 } |
| 1646 |
| 1647 bool Parser::ContainsLabel(ZoneList<const AstRawString*>* labels, |
| 1648 const AstRawString* label) { |
| 1649 DCHECK_NOT_NULL(label); |
| 1650 if (labels != nullptr) { |
| 1651 for (int i = labels->length(); i-- > 0;) { |
| 1652 if (labels->at(i) == label) return true; |
1631 } | 1653 } |
1632 } | 1654 } |
1633 return false; | 1655 return false; |
1634 } | 1656 } |
1635 | 1657 |
| 1658 Expression* Parser::RewriteReturn(Expression* return_value, int pos) { |
| 1659 if (IsSubclassConstructor(function_state_->kind())) { |
| 1660 // For subclass constructors we need to return this in case of undefined |
| 1661 // return a Smi (transformed into an exception in the ConstructStub) |
| 1662 // for a non object. |
| 1663 // |
| 1664 // return expr; |
| 1665 // |
| 1666 // Is rewritten as: |
| 1667 // |
| 1668 // return (temp = expr) === undefined ? this : |
| 1669 // %_IsJSReceiver(temp) ? temp : 1; |
| 1670 |
| 1671 // temp = expr |
| 1672 Variable* temp = NewTemporary(ast_value_factory()->empty_string()); |
| 1673 Assignment* assign = factory()->NewAssignment( |
| 1674 Token::ASSIGN, factory()->NewVariableProxy(temp), return_value, pos); |
| 1675 |
| 1676 // %_IsJSReceiver(temp) |
| 1677 ZoneList<Expression*>* is_spec_object_args = |
| 1678 new (zone()) ZoneList<Expression*>(1, zone()); |
| 1679 is_spec_object_args->Add(factory()->NewVariableProxy(temp), zone()); |
| 1680 Expression* is_spec_object_call = factory()->NewCallRuntime( |
| 1681 Runtime::kInlineIsJSReceiver, is_spec_object_args, pos); |
| 1682 |
| 1683 // %_IsJSReceiver(temp) ? temp : 1; |
| 1684 Expression* is_object_conditional = factory()->NewConditional( |
| 1685 is_spec_object_call, factory()->NewVariableProxy(temp), |
| 1686 factory()->NewSmiLiteral(1, pos), pos); |
| 1687 |
| 1688 // temp === undefined |
| 1689 Expression* is_undefined = factory()->NewCompareOperation( |
| 1690 Token::EQ_STRICT, assign, |
| 1691 factory()->NewUndefinedLiteral(kNoSourcePosition), pos); |
| 1692 |
| 1693 // is_undefined ? this : is_object_conditional |
| 1694 return_value = factory()->NewConditional(is_undefined, ThisExpression(pos), |
| 1695 is_object_conditional, pos); |
| 1696 } |
| 1697 if (is_generator()) { |
| 1698 return_value = BuildIteratorResult(return_value, true); |
| 1699 } else if (is_async_function()) { |
| 1700 return_value = BuildResolvePromise(return_value, return_value->position()); |
| 1701 } |
| 1702 return return_value; |
| 1703 } |
| 1704 |
1636 Statement* Parser::ParseFunctionDeclaration(bool* ok) { | 1705 Statement* Parser::ParseFunctionDeclaration(bool* ok) { |
1637 Consume(Token::FUNCTION); | 1706 Consume(Token::FUNCTION); |
1638 int pos = position(); | 1707 int pos = position(); |
1639 ParseFunctionFlags flags = ParseFunctionFlags::kIsNormal; | 1708 ParseFunctionFlags flags = ParseFunctionFlags::kIsNormal; |
1640 if (Check(Token::MUL)) { | 1709 if (Check(Token::MUL)) { |
1641 flags |= ParseFunctionFlags::kIsGenerator; | 1710 flags |= ParseFunctionFlags::kIsGenerator; |
1642 if (allow_harmony_restrictive_declarations()) { | 1711 if (allow_harmony_restrictive_declarations()) { |
1643 ReportMessageAt(scanner()->location(), | 1712 ReportMessageAt(scanner()->location(), |
1644 MessageTemplate::kGeneratorInLegacyContext); | 1713 MessageTemplate::kGeneratorInLegacyContext); |
1645 *ok = false; | 1714 *ok = false; |
1646 return nullptr; | 1715 return nullptr; |
1647 } | 1716 } |
1648 } | 1717 } |
1649 | 1718 |
1650 return ParseHoistableDeclaration(pos, flags, nullptr, false, CHECK_OK); | 1719 return ParseHoistableDeclaration(pos, flags, nullptr, false, CHECK_OK); |
1651 } | 1720 } |
1652 | 1721 |
1653 Statement* Parser::ParseExpressionOrLabelledStatement( | |
1654 ZoneList<const AstRawString*>* labels, | |
1655 AllowLabelledFunctionStatement allow_function, bool* ok) { | |
1656 // ExpressionStatement | LabelledStatement :: | |
1657 // Expression ';' | |
1658 // Identifier ':' Statement | |
1659 // | |
1660 // ExpressionStatement[Yield] : | |
1661 // [lookahead ∉ {{, function, class, let [}] Expression[In, ?Yield] ; | |
1662 | |
1663 int pos = peek_position(); | |
1664 | |
1665 switch (peek()) { | |
1666 case Token::FUNCTION: | |
1667 case Token::LBRACE: | |
1668 UNREACHABLE(); // Always handled by the callers. | |
1669 case Token::CLASS: | |
1670 ReportUnexpectedToken(Next()); | |
1671 *ok = false; | |
1672 return nullptr; | |
1673 default: | |
1674 break; | |
1675 } | |
1676 | |
1677 bool starts_with_idenfifier = peek_any_identifier(); | |
1678 Expression* expr = ParseExpression(true, CHECK_OK); | |
1679 if (peek() == Token::COLON && starts_with_idenfifier && expr != NULL && | |
1680 expr->AsVariableProxy() != NULL && | |
1681 !expr->AsVariableProxy()->is_this()) { | |
1682 // Expression is a single identifier, and not, e.g., a parenthesized | |
1683 // identifier. | |
1684 VariableProxy* var = expr->AsVariableProxy(); | |
1685 const AstRawString* label = var->raw_name(); | |
1686 // TODO(1240780): We don't check for redeclaration of labels | |
1687 // during preparsing since keeping track of the set of active | |
1688 // labels requires nontrivial changes to the way scopes are | |
1689 // structured. However, these are probably changes we want to | |
1690 // make later anyway so we should go back and fix this then. | |
1691 if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) { | |
1692 ReportMessage(MessageTemplate::kLabelRedeclaration, label); | |
1693 *ok = false; | |
1694 return NULL; | |
1695 } | |
1696 if (labels == NULL) { | |
1697 labels = new(zone()) ZoneList<const AstRawString*>(4, zone()); | |
1698 } | |
1699 labels->Add(label, zone()); | |
1700 // Remove the "ghost" variable that turned out to be a label | |
1701 // from the top scope. This way, we don't try to resolve it | |
1702 // during the scope processing. | |
1703 scope()->RemoveUnresolved(var); | |
1704 Expect(Token::COLON, CHECK_OK); | |
1705 // ES#sec-labelled-function-declarations Labelled Function Declarations | |
1706 if (peek() == Token::FUNCTION && is_sloppy(language_mode())) { | |
1707 if (allow_function == kAllowLabelledFunctionStatement) { | |
1708 return ParseFunctionDeclaration(ok); | |
1709 } else { | |
1710 return ParseScopedStatement(labels, true, ok); | |
1711 } | |
1712 } | |
1713 return ParseStatement(labels, kDisallowLabelledFunctionStatement, ok); | |
1714 } | |
1715 | |
1716 // If we have an extension, we allow a native function declaration. | |
1717 // A native function declaration starts with "native function" with | |
1718 // no line-terminator between the two words. | |
1719 if (extension_ != NULL && peek() == Token::FUNCTION && | |
1720 !scanner()->HasAnyLineTerminatorBeforeNext() && expr != NULL && | |
1721 expr->AsVariableProxy() != NULL && | |
1722 expr->AsVariableProxy()->raw_name() == | |
1723 ast_value_factory()->native_string() && | |
1724 !scanner()->literal_contains_escapes()) { | |
1725 return ParseNativeDeclaration(ok); | |
1726 } | |
1727 | |
1728 // Parsed expression statement, followed by semicolon. | |
1729 ExpectSemicolon(CHECK_OK); | |
1730 return factory()->NewExpressionStatement(expr, pos); | |
1731 } | |
1732 | |
1733 | |
1734 IfStatement* Parser::ParseIfStatement(ZoneList<const AstRawString*>* labels, | |
1735 bool* ok) { | |
1736 // IfStatement :: | |
1737 // 'if' '(' Expression ')' Statement ('else' Statement)? | |
1738 | |
1739 int pos = peek_position(); | |
1740 Expect(Token::IF, CHECK_OK); | |
1741 Expect(Token::LPAREN, CHECK_OK); | |
1742 Expression* condition = ParseExpression(true, CHECK_OK); | |
1743 Expect(Token::RPAREN, CHECK_OK); | |
1744 Statement* then_statement = ParseScopedStatement(labels, false, CHECK_OK); | |
1745 Statement* else_statement = NULL; | |
1746 if (peek() == Token::ELSE) { | |
1747 Next(); | |
1748 else_statement = ParseScopedStatement(labels, false, CHECK_OK); | |
1749 } else { | |
1750 else_statement = factory()->NewEmptyStatement(kNoSourcePosition); | |
1751 } | |
1752 return factory()->NewIfStatement( | |
1753 condition, then_statement, else_statement, pos); | |
1754 } | |
1755 | |
1756 | |
1757 Statement* Parser::ParseContinueStatement(bool* ok) { | |
1758 // ContinueStatement :: | |
1759 // 'continue' Identifier? ';' | |
1760 | |
1761 int pos = peek_position(); | |
1762 Expect(Token::CONTINUE, CHECK_OK); | |
1763 const AstRawString* label = NULL; | |
1764 Token::Value tok = peek(); | |
1765 if (!scanner()->HasAnyLineTerminatorBeforeNext() && | |
1766 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) { | |
1767 // ECMA allows "eval" or "arguments" as labels even in strict mode. | |
1768 label = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); | |
1769 } | |
1770 IterationStatement* target = LookupContinueTarget(label, CHECK_OK); | |
1771 if (target == NULL) { | |
1772 // Illegal continue statement. | |
1773 MessageTemplate::Template message = MessageTemplate::kIllegalContinue; | |
1774 if (label != NULL) { | |
1775 message = MessageTemplate::kUnknownLabel; | |
1776 } | |
1777 ReportMessage(message, label); | |
1778 *ok = false; | |
1779 return NULL; | |
1780 } | |
1781 ExpectSemicolon(CHECK_OK); | |
1782 return factory()->NewContinueStatement(target, pos); | |
1783 } | |
1784 | |
1785 | |
1786 Statement* Parser::ParseBreakStatement(ZoneList<const AstRawString*>* labels, | |
1787 bool* ok) { | |
1788 // BreakStatement :: | |
1789 // 'break' Identifier? ';' | |
1790 | |
1791 int pos = peek_position(); | |
1792 Expect(Token::BREAK, CHECK_OK); | |
1793 const AstRawString* label = NULL; | |
1794 Token::Value tok = peek(); | |
1795 if (!scanner()->HasAnyLineTerminatorBeforeNext() && | |
1796 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) { | |
1797 // ECMA allows "eval" or "arguments" as labels even in strict mode. | |
1798 label = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); | |
1799 } | |
1800 // Parse labeled break statements that target themselves into | |
1801 // empty statements, e.g. 'l1: l2: l3: break l2;' | |
1802 if (label != NULL && ContainsLabel(labels, label)) { | |
1803 ExpectSemicolon(CHECK_OK); | |
1804 return factory()->NewEmptyStatement(pos); | |
1805 } | |
1806 BreakableStatement* target = NULL; | |
1807 target = LookupBreakTarget(label, CHECK_OK); | |
1808 if (target == NULL) { | |
1809 // Illegal break statement. | |
1810 MessageTemplate::Template message = MessageTemplate::kIllegalBreak; | |
1811 if (label != NULL) { | |
1812 message = MessageTemplate::kUnknownLabel; | |
1813 } | |
1814 ReportMessage(message, label); | |
1815 *ok = false; | |
1816 return NULL; | |
1817 } | |
1818 ExpectSemicolon(CHECK_OK); | |
1819 return factory()->NewBreakStatement(target, pos); | |
1820 } | |
1821 | |
1822 | |
1823 Statement* Parser::ParseReturnStatement(bool* ok) { | |
1824 // ReturnStatement :: | |
1825 // 'return' Expression? ';' | |
1826 | |
1827 // Consume the return token. It is necessary to do that before | |
1828 // reporting any errors on it, because of the way errors are | |
1829 // reported (underlining). | |
1830 Expect(Token::RETURN, CHECK_OK); | |
1831 Scanner::Location loc = scanner()->location(); | |
1832 | |
1833 Token::Value tok = peek(); | |
1834 Statement* result; | |
1835 Expression* return_value; | |
1836 if (scanner()->HasAnyLineTerminatorBeforeNext() || | |
1837 tok == Token::SEMICOLON || | |
1838 tok == Token::RBRACE || | |
1839 tok == Token::EOS) { | |
1840 if (IsSubclassConstructor(function_state_->kind())) { | |
1841 return_value = ThisExpression(loc.beg_pos); | |
1842 } else { | |
1843 return_value = GetLiteralUndefined(position()); | |
1844 } | |
1845 } else { | |
1846 int pos = peek_position(); | |
1847 | |
1848 if (IsSubclassConstructor(function_state_->kind())) { | |
1849 // Because of the return code rewriting that happens in case of a subclass | |
1850 // constructor we don't want to accept tail calls, therefore we don't set | |
1851 // ReturnExprScope to kInsideValidReturnStatement here. | |
1852 return_value = ParseExpression(true, CHECK_OK); | |
1853 | |
1854 // For subclass constructors we need to return this in case of undefined | |
1855 // return a Smi (transformed into an exception in the ConstructStub) | |
1856 // for a non object. | |
1857 // | |
1858 // return expr; | |
1859 // | |
1860 // Is rewritten as: | |
1861 // | |
1862 // return (temp = expr) === undefined ? this : | |
1863 // %_IsJSReceiver(temp) ? temp : 1; | |
1864 | |
1865 // temp = expr | |
1866 Variable* temp = NewTemporary(ast_value_factory()->empty_string()); | |
1867 Assignment* assign = factory()->NewAssignment( | |
1868 Token::ASSIGN, factory()->NewVariableProxy(temp), return_value, pos); | |
1869 | |
1870 // %_IsJSReceiver(temp) | |
1871 ZoneList<Expression*>* is_spec_object_args = | |
1872 new (zone()) ZoneList<Expression*>(1, zone()); | |
1873 is_spec_object_args->Add(factory()->NewVariableProxy(temp), zone()); | |
1874 Expression* is_spec_object_call = factory()->NewCallRuntime( | |
1875 Runtime::kInlineIsJSReceiver, is_spec_object_args, pos); | |
1876 | |
1877 // %_IsJSReceiver(temp) ? temp : 1; | |
1878 Expression* is_object_conditional = factory()->NewConditional( | |
1879 is_spec_object_call, factory()->NewVariableProxy(temp), | |
1880 factory()->NewSmiLiteral(1, pos), pos); | |
1881 | |
1882 // temp === undefined | |
1883 Expression* is_undefined = factory()->NewCompareOperation( | |
1884 Token::EQ_STRICT, assign, | |
1885 factory()->NewUndefinedLiteral(kNoSourcePosition), pos); | |
1886 | |
1887 // is_undefined ? this : is_object_conditional | |
1888 return_value = factory()->NewConditional( | |
1889 is_undefined, ThisExpression(pos), is_object_conditional, pos); | |
1890 } else { | |
1891 ReturnExprScope maybe_allow_tail_calls( | |
1892 function_state_, ReturnExprContext::kInsideValidReturnStatement); | |
1893 return_value = ParseExpression(true, CHECK_OK); | |
1894 | |
1895 if (allow_tailcalls() && !is_sloppy(language_mode()) && !is_resumable()) { | |
1896 // ES6 14.6.1 Static Semantics: IsInTailPosition | |
1897 function_state_->AddImplicitTailCallExpression(return_value); | |
1898 } | |
1899 } | |
1900 } | |
1901 ExpectSemicolon(CHECK_OK); | |
1902 | |
1903 if (is_generator()) { | |
1904 return_value = BuildIteratorResult(return_value, true); | |
1905 } else if (is_async_function()) { | |
1906 return_value = BuildResolvePromise(return_value, return_value->position()); | |
1907 } | |
1908 | |
1909 result = factory()->NewReturnStatement(return_value, loc.beg_pos); | |
1910 | |
1911 DeclarationScope* decl_scope = GetDeclarationScope(); | |
1912 if (decl_scope->is_script_scope() || decl_scope->is_eval_scope()) { | |
1913 ReportMessageAt(loc, MessageTemplate::kIllegalReturn); | |
1914 *ok = false; | |
1915 return NULL; | |
1916 } | |
1917 return result; | |
1918 } | |
1919 | |
1920 | |
1921 Statement* Parser::ParseWithStatement(ZoneList<const AstRawString*>* labels, | |
1922 bool* ok) { | |
1923 // WithStatement :: | |
1924 // 'with' '(' Expression ')' Statement | |
1925 | |
1926 Expect(Token::WITH, CHECK_OK); | |
1927 int pos = position(); | |
1928 | |
1929 if (is_strict(language_mode())) { | |
1930 ReportMessage(MessageTemplate::kStrictWith); | |
1931 *ok = false; | |
1932 return NULL; | |
1933 } | |
1934 | |
1935 Expect(Token::LPAREN, CHECK_OK); | |
1936 Expression* expr = ParseExpression(true, CHECK_OK); | |
1937 Expect(Token::RPAREN, CHECK_OK); | |
1938 | |
1939 Scope* with_scope = NewScope(WITH_SCOPE); | |
1940 Statement* body; | |
1941 { | |
1942 BlockState block_state(&scope_state_, with_scope); | |
1943 with_scope->set_start_position(scanner()->peek_location().beg_pos); | |
1944 body = ParseScopedStatement(labels, true, CHECK_OK); | |
1945 with_scope->set_end_position(scanner()->location().end_pos); | |
1946 } | |
1947 return factory()->NewWithStatement(with_scope, expr, body, pos); | |
1948 } | |
1949 | |
1950 | |
1951 CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) { | 1722 CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) { |
1952 // CaseClause :: | 1723 // CaseClause :: |
1953 // 'case' Expression ':' StatementList | 1724 // 'case' Expression ':' StatementList |
1954 // 'default' ':' StatementList | 1725 // 'default' ':' StatementList |
1955 | 1726 |
1956 Expression* label = NULL; // NULL expression indicates default case | 1727 Expression* label = NULL; // NULL expression indicates default case |
1957 if (peek() == Token::CASE) { | 1728 if (peek() == Token::CASE) { |
1958 Expect(Token::CASE, CHECK_OK); | 1729 Expect(Token::CASE, CHECK_OK); |
1959 label = ParseExpression(true, CHECK_OK); | 1730 label = ParseExpression(true, CHECK_OK); |
1960 } else { | 1731 } else { |
(...skipping 4017 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5978 node->Print(Isolate::Current()); | 5749 node->Print(Isolate::Current()); |
5979 } | 5750 } |
5980 #endif // DEBUG | 5751 #endif // DEBUG |
5981 | 5752 |
5982 #undef CHECK_OK | 5753 #undef CHECK_OK |
5983 #undef CHECK_OK_VOID | 5754 #undef CHECK_OK_VOID |
5984 #undef CHECK_FAILED | 5755 #undef CHECK_FAILED |
5985 | 5756 |
5986 } // namespace internal | 5757 } // namespace internal |
5987 } // namespace v8 | 5758 } // namespace v8 |
OLD | NEW |