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_PARSING_PARSER_BASE_H | 5 #ifndef V8_PARSING_PARSER_BASE_H |
6 #define V8_PARSING_PARSER_BASE_H | 6 #define V8_PARSING_PARSER_BASE_H |
7 | 7 |
8 #include "src/ast/scopes.h" | 8 #include "src/ast/scopes.h" |
9 #include "src/bailout-reason.h" | 9 #include "src/bailout-reason.h" |
10 #include "src/base/hashmap.h" | 10 #include "src/base/hashmap.h" |
(...skipping 1056 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1067 bool* is_async, bool* ok); | 1067 bool* is_async, bool* ok); |
1068 ExpressionT ParsePrimaryExpression(ExpressionClassifier* classifier, | 1068 ExpressionT ParsePrimaryExpression(ExpressionClassifier* classifier, |
1069 bool* ok) { | 1069 bool* ok) { |
1070 bool is_async; | 1070 bool is_async; |
1071 return ParsePrimaryExpression(classifier, &is_async, ok); | 1071 return ParsePrimaryExpression(classifier, &is_async, ok); |
1072 } | 1072 } |
1073 ExpressionT ParseExpression(bool accept_IN, bool* ok); | 1073 ExpressionT ParseExpression(bool accept_IN, bool* ok); |
1074 ExpressionT ParseExpression(bool accept_IN, ExpressionClassifier* classifier, | 1074 ExpressionT ParseExpression(bool accept_IN, ExpressionClassifier* classifier, |
1075 bool* ok); | 1075 bool* ok); |
1076 ExpressionT ParseArrayLiteral(ExpressionClassifier* classifier, bool* ok); | 1076 ExpressionT ParseArrayLiteral(ExpressionClassifier* classifier, bool* ok); |
1077 | 1077 ExpressionT ParsePropertyName(IdentifierT* name, bool* is_get, bool* is_set, |
1078 enum class PropertyKind { | |
1079 kAccessorProperty, | |
1080 kValueProperty, | |
1081 kShorthandProperty, | |
1082 kMethodProperty | |
1083 }; | |
1084 | |
1085 bool SetPropertyKindFromToken(Token::Value token, PropertyKind* kind); | |
1086 ExpressionT ParsePropertyName(IdentifierT* name, PropertyKind* kind, | |
1087 bool in_class, bool* is_generator, bool* is_get, | |
1088 bool* is_set, bool* is_async, bool* is_static, | |
1089 bool* is_computed_name, | 1078 bool* is_computed_name, |
1090 ExpressionClassifier* classifier, bool* ok); | 1079 ExpressionClassifier* classifier, bool* ok); |
1091 ExpressionT ParseObjectLiteral(ExpressionClassifier* classifier, bool* ok); | 1080 ExpressionT ParseObjectLiteral(ExpressionClassifier* classifier, bool* ok); |
1092 ObjectLiteralPropertyT ParsePropertyDefinition( | 1081 ObjectLiteralPropertyT ParsePropertyDefinition( |
1093 ObjectLiteralCheckerBase* checker, bool in_class, bool has_extends, | 1082 ObjectLiteralCheckerBase* checker, bool in_class, bool has_extends, |
1094 bool* is_computed_name, bool* has_seen_constructor, | 1083 MethodKind kind, bool* is_computed_name, bool* has_seen_constructor, |
1095 ExpressionClassifier* classifier, IdentifierT* name, bool* ok); | 1084 ExpressionClassifier* classifier, IdentifierT* name, bool* ok); |
1096 typename Types::ExpressionList ParseArguments( | 1085 typename Types::ExpressionList ParseArguments( |
1097 Scanner::Location* first_spread_pos, bool maybe_arrow, | 1086 Scanner::Location* first_spread_pos, bool maybe_arrow, |
1098 ExpressionClassifier* classifier, bool* ok); | 1087 ExpressionClassifier* classifier, bool* ok); |
1099 typename Types::ExpressionList ParseArguments( | 1088 typename Types::ExpressionList ParseArguments( |
1100 Scanner::Location* first_spread_pos, ExpressionClassifier* classifier, | 1089 Scanner::Location* first_spread_pos, ExpressionClassifier* classifier, |
1101 bool* ok) { | 1090 bool* ok) { |
1102 return ParseArguments(first_spread_pos, false, classifier, ok); | 1091 return ParseArguments(first_spread_pos, false, classifier, ok); |
1103 } | 1092 } |
1104 | 1093 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1183 if (is_sloppy(scope->language_mode())) { | 1172 if (is_sloppy(scope->language_mode())) { |
1184 // For sloppy scopes we also have to record the call at function level, | 1173 // For sloppy scopes we also have to record the call at function level, |
1185 // in case it includes declarations that will be hoisted. | 1174 // in case it includes declarations that will be hoisted. |
1186 scope->GetDeclarationScope()->RecordEvalCall(); | 1175 scope->GetDeclarationScope()->RecordEvalCall(); |
1187 } | 1176 } |
1188 return Call::IS_POSSIBLY_EVAL; | 1177 return Call::IS_POSSIBLY_EVAL; |
1189 } | 1178 } |
1190 return Call::NOT_EVAL; | 1179 return Call::NOT_EVAL; |
1191 } | 1180 } |
1192 | 1181 |
| 1182 // Used to validate property names in object literals and class literals |
| 1183 enum PropertyKind { |
| 1184 kAccessorProperty, |
| 1185 kValueProperty, |
| 1186 kMethodProperty |
| 1187 }; |
| 1188 |
1193 class ObjectLiteralCheckerBase { | 1189 class ObjectLiteralCheckerBase { |
1194 public: | 1190 public: |
1195 explicit ObjectLiteralCheckerBase(ParserBase* parser) : parser_(parser) {} | 1191 explicit ObjectLiteralCheckerBase(ParserBase* parser) : parser_(parser) {} |
1196 | 1192 |
1197 virtual void CheckProperty(Token::Value property, PropertyKind type, | 1193 virtual void CheckProperty(Token::Value property, PropertyKind type, |
1198 MethodKind method_type, | 1194 MethodKind method_type, |
1199 ExpressionClassifier* classifier, bool* ok) = 0; | 1195 ExpressionClassifier* classifier, bool* ok) = 0; |
1200 | 1196 |
1201 virtual ~ObjectLiteralCheckerBase() {} | 1197 virtual ~ObjectLiteralCheckerBase() {} |
1202 | 1198 |
(...skipping 656 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1859 // to change. Also, this error message will never appear while pre- | 1855 // to change. Also, this error message will never appear while pre- |
1860 // parsing (this is OK, as it is an implementation limitation). | 1856 // parsing (this is OK, as it is an implementation limitation). |
1861 ReportMessage(MessageTemplate::kTooManySpreads); | 1857 ReportMessage(MessageTemplate::kTooManySpreads); |
1862 return impl()->EmptyExpression(); | 1858 return impl()->EmptyExpression(); |
1863 } | 1859 } |
1864 } | 1860 } |
1865 return result; | 1861 return result; |
1866 } | 1862 } |
1867 | 1863 |
1868 template <class Impl> | 1864 template <class Impl> |
1869 bool ParserBase<Impl>::SetPropertyKindFromToken(Token::Value token, | |
1870 PropertyKind* kind) { | |
1871 switch (token) { | |
1872 case Token::COLON: | |
1873 *kind = PropertyKind::kValueProperty; | |
1874 return true; | |
1875 case Token::COMMA: | |
1876 case Token::RBRACE: | |
1877 case Token::ASSIGN: | |
1878 *kind = PropertyKind::kShorthandProperty; | |
1879 return true; | |
1880 case Token::LPAREN: | |
1881 *kind = PropertyKind::kMethodProperty; | |
1882 return true; | |
1883 default: | |
1884 break; | |
1885 } | |
1886 return false; | |
1887 } | |
1888 | |
1889 template <class Impl> | |
1890 typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePropertyName( | 1865 typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePropertyName( |
1891 IdentifierT* name, PropertyKind* kind, bool in_class, bool* is_generator, | 1866 IdentifierT* name, bool* is_get, bool* is_set, bool* is_computed_name, |
1892 bool* is_get, bool* is_set, bool* is_async, bool* is_static, | 1867 ExpressionClassifier* classifier, bool* ok) { |
1893 bool* is_computed_name, ExpressionClassifier* classifier, bool* ok) { | |
1894 *is_generator = Check(Token::MUL); | |
1895 | |
1896 Token::Value token = peek(); | 1868 Token::Value token = peek(); |
1897 int pos = peek_position(); | 1869 int pos = peek_position(); |
1898 | 1870 |
1899 if (in_class && !*is_generator && token == Token::STATIC) { | |
1900 Consume(Token::STATIC); | |
1901 *kind = PropertyKind::kMethodProperty; | |
1902 if (peek() == Token::LPAREN) { | |
1903 *name = impl()->GetSymbol(); // TODO(bakkot) specialize on 'static' | |
1904 return factory()->NewStringLiteral(*name, pos); | |
1905 } | |
1906 *is_generator = Check(Token::MUL); | |
1907 *is_static = true; | |
1908 token = peek(); | |
1909 pos = peek_position(); | |
1910 } | |
1911 | |
1912 if (allow_harmony_async_await() && !*is_generator && token == Token::ASYNC && | |
1913 !scanner()->HasAnyLineTerminatorAfterNext()) { | |
1914 Consume(Token::ASYNC); | |
1915 token = peek(); | |
1916 if (SetPropertyKindFromToken(token, kind)) { | |
1917 *name = impl()->GetSymbol(); // TODO(bakkot) specialize on 'async' | |
1918 if (fni_ != nullptr) { | |
1919 impl()->PushLiteralName(fni_, *name); | |
1920 } | |
1921 return factory()->NewStringLiteral(*name, pos); | |
1922 } | |
1923 *kind = PropertyKind::kMethodProperty; | |
1924 *is_async = true; | |
1925 pos = peek_position(); | |
1926 } | |
1927 | |
1928 if (token == Token::IDENTIFIER && !*is_generator && !*is_async) { | |
1929 Consume(Token::IDENTIFIER); | |
1930 token = peek(); | |
1931 if (SetPropertyKindFromToken(token, kind)) { | |
1932 *name = impl()->GetSymbol(); | |
1933 if (fni_ != nullptr) { | |
1934 impl()->PushLiteralName(fni_, *name); | |
1935 } | |
1936 return factory()->NewStringLiteral(*name, pos); | |
1937 } | |
1938 scanner()->IsGetOrSet(is_get, is_set); | |
1939 if (!*is_get && !*is_set) { // TODO(bakkot) have IsGetOrSet return a bool | |
1940 Token::Value next = Next(); | |
1941 ReportUnexpectedToken(next); | |
1942 *ok = false; | |
1943 return impl()->EmptyExpression(); | |
1944 } | |
1945 *kind = PropertyKind::kAccessorProperty; | |
1946 pos = peek_position(); | |
1947 } | |
1948 | |
1949 // For non computed property names we normalize the name a bit: | 1871 // For non computed property names we normalize the name a bit: |
1950 // | 1872 // |
1951 // "12" -> 12 | 1873 // "12" -> 12 |
1952 // 12.3 -> "12.3" | 1874 // 12.3 -> "12.3" |
1953 // 12.30 -> "12.3" | 1875 // 12.30 -> "12.3" |
1954 // identifier -> "identifier" | 1876 // identifier -> "identifier" |
1955 // | 1877 // |
1956 // This is important because we use the property name as a key in a hash | 1878 // This is important because we use the property name as a key in a hash |
1957 // table when we compute constant properties. | 1879 // table when we compute constant properties. |
1958 ExpressionT expression; | |
1959 switch (token) { | 1880 switch (token) { |
1960 case Token::STRING: | 1881 case Token::STRING: |
1961 Consume(Token::STRING); | 1882 Consume(Token::STRING); |
1962 *name = impl()->GetSymbol(); | 1883 *name = impl()->GetSymbol(); |
1963 break; | 1884 break; |
1964 | 1885 |
1965 case Token::SMI: | 1886 case Token::SMI: |
1966 Consume(Token::SMI); | 1887 Consume(Token::SMI); |
1967 *name = impl()->GetNumberAsSymbol(); | 1888 *name = impl()->GetNumberAsSymbol(); |
1968 break; | 1889 break; |
1969 | 1890 |
1970 case Token::NUMBER: | 1891 case Token::NUMBER: |
1971 Consume(Token::NUMBER); | 1892 Consume(Token::NUMBER); |
1972 *name = impl()->GetNumberAsSymbol(); | 1893 *name = impl()->GetNumberAsSymbol(); |
1973 break; | 1894 break; |
1974 | 1895 |
1975 case Token::LBRACK: { | 1896 case Token::LBRACK: { |
1976 *name = impl()->EmptyIdentifier(); | |
1977 *is_computed_name = true; | 1897 *is_computed_name = true; |
1978 Consume(Token::LBRACK); | 1898 Consume(Token::LBRACK); |
1979 ExpressionClassifier computed_name_classifier(this); | 1899 ExpressionClassifier computed_name_classifier(this); |
1980 expression = | 1900 ExpressionT expression = |
1981 ParseAssignmentExpression(true, &computed_name_classifier, CHECK_OK); | 1901 ParseAssignmentExpression(true, &computed_name_classifier, CHECK_OK); |
1982 impl()->RewriteNonPattern(&computed_name_classifier, CHECK_OK); | 1902 impl()->RewriteNonPattern(&computed_name_classifier, CHECK_OK); |
1983 classifier->AccumulateFormalParameterContainmentErrors( | 1903 classifier->AccumulateFormalParameterContainmentErrors( |
1984 &computed_name_classifier); | 1904 &computed_name_classifier); |
1985 Expect(Token::RBRACK, CHECK_OK); | 1905 Expect(Token::RBRACK, CHECK_OK); |
1986 break; | 1906 return expression; |
1987 } | 1907 } |
1988 | 1908 |
1989 default: | 1909 default: |
1990 *name = ParseIdentifierName(CHECK_OK); | 1910 *name = ParseIdentifierName(CHECK_OK); |
| 1911 scanner()->IsGetOrSet(is_get, is_set); |
1991 break; | 1912 break; |
1992 } | 1913 } |
1993 | 1914 |
1994 if (*kind == PropertyKind::kValueProperty) { | |
1995 if (!SetPropertyKindFromToken(peek(), kind) || | |
1996 (*kind == PropertyKind::kShorthandProperty && | |
1997 !Token::IsIdentifier(token, language_mode(), this->is_generator(), | |
1998 parsing_module_ || is_async_function()))) { | |
1999 Token::Value next = Next(); | |
2000 ReportUnexpectedToken(next); | |
2001 *ok = false; | |
2002 return impl()->EmptyExpression(); | |
2003 } | |
2004 } | |
2005 | |
2006 if (*is_computed_name) { | |
2007 return expression; | |
2008 } | |
2009 | |
2010 if (fni_ != nullptr) { | |
2011 impl()->PushLiteralName(fni_, *name); | |
2012 } | |
2013 | |
2014 uint32_t index; | 1915 uint32_t index; |
2015 return impl()->IsArrayIndex(*name, &index) | 1916 return impl()->IsArrayIndex(*name, &index) |
2016 ? factory()->NewNumberLiteral(index, pos) | 1917 ? factory()->NewNumberLiteral(index, pos) |
2017 : factory()->NewStringLiteral(*name, pos); | 1918 : factory()->NewStringLiteral(*name, pos); |
2018 } | 1919 } |
2019 | 1920 |
2020 template <typename Impl> | 1921 template <typename Impl> |
2021 typename ParserBase<Impl>::ObjectLiteralPropertyT | 1922 typename ParserBase<Impl>::ObjectLiteralPropertyT |
2022 ParserBase<Impl>::ParsePropertyDefinition(ObjectLiteralCheckerBase* checker, | 1923 ParserBase<Impl>::ParsePropertyDefinition( |
2023 bool in_class, bool has_extends, | 1924 ObjectLiteralCheckerBase* checker, bool in_class, bool has_extends, |
2024 bool* is_computed_name, | 1925 MethodKind method_kind, bool* is_computed_name, bool* has_seen_constructor, |
2025 bool* has_seen_constructor, | 1926 ExpressionClassifier* classifier, IdentifierT* name, bool* ok) { |
2026 ExpressionClassifier* classifier, | 1927 DCHECK(!in_class || IsStaticMethod(method_kind) || |
2027 IdentifierT* name, bool* ok) { | 1928 has_seen_constructor != nullptr); |
2028 DCHECK(!in_class || has_seen_constructor != nullptr); | |
2029 bool is_get = false; | 1929 bool is_get = false; |
2030 bool is_set = false; | 1930 bool is_set = false; |
2031 bool is_generator = false; | 1931 bool is_generator = Check(Token::MUL); |
2032 bool is_async = false; | 1932 bool is_async = false; |
2033 bool is_static = false; | 1933 const bool is_static = IsStaticMethod(method_kind); |
2034 PropertyKind kind = PropertyKind::kValueProperty; | |
2035 | 1934 |
2036 Token::Value name_token = peek(); | 1935 Token::Value name_token = peek(); |
| 1936 |
| 1937 if (is_generator) { |
| 1938 method_kind |= MethodKind::kGenerator; |
| 1939 } else if (allow_harmony_async_await() && name_token == Token::ASYNC && |
| 1940 !scanner()->HasAnyLineTerminatorAfterNext() && |
| 1941 PeekAhead() != Token::LPAREN && PeekAhead()) { |
| 1942 is_async = true; |
| 1943 } |
| 1944 |
2037 int next_beg_pos = scanner()->peek_location().beg_pos; | 1945 int next_beg_pos = scanner()->peek_location().beg_pos; |
2038 int next_end_pos = scanner()->peek_location().end_pos; | 1946 int next_end_pos = scanner()->peek_location().end_pos; |
2039 | |
2040 ExpressionT name_expression = | 1947 ExpressionT name_expression = |
2041 ParsePropertyName(name, &kind, in_class, &is_generator, &is_get, &is_set, | 1948 ParsePropertyName(name, &is_get, &is_set, is_computed_name, classifier, |
2042 &is_async, &is_static, is_computed_name, classifier, | |
2043 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 1949 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
2044 | 1950 |
2045 switch (kind) { | 1951 if (fni_ != nullptr && !*is_computed_name) { |
2046 case PropertyKind::kValueProperty: { | 1952 impl()->PushLiteralName(fni_, *name); |
2047 if (in_class) { | 1953 } |
2048 Token::Value next = Next(); | |
2049 ReportUnexpectedToken(next); | |
2050 *ok = false; | |
2051 return impl()->EmptyObjectLiteralProperty(); | |
2052 } | |
2053 | 1954 |
2054 DCHECK(!is_get && !is_set && !is_generator && !is_async && !is_static); | 1955 if (!in_class && !is_generator) { |
2055 | 1956 DCHECK(!IsStaticMethod(method_kind)); |
| 1957 if (peek() == Token::COLON) { |
| 1958 // PropertyDefinition |
| 1959 // PropertyName ':' AssignmentExpression |
2056 if (!*is_computed_name) { | 1960 if (!*is_computed_name) { |
2057 checker->CheckProperty(name_token, PropertyKind::kValueProperty, | 1961 checker->CheckProperty(name_token, kValueProperty, MethodKind::kNormal, |
2058 MethodKind::kNormal, classifier, | 1962 classifier, |
2059 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 1963 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
2060 } | 1964 } |
2061 Consume(Token::COLON); | 1965 Consume(Token::COLON); |
2062 int beg_pos = peek_position(); | 1966 int beg_pos = peek_position(); |
2063 ExpressionT value = ParseAssignmentExpression( | 1967 ExpressionT value = ParseAssignmentExpression( |
2064 true, classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 1968 true, classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
2065 CheckDestructuringElement(value, classifier, beg_pos, | 1969 CheckDestructuringElement(value, classifier, beg_pos, |
2066 scanner()->location().end_pos); | 1970 scanner()->location().end_pos); |
2067 | 1971 |
2068 return factory()->NewObjectLiteralProperty(name_expression, value, | 1972 return factory()->NewObjectLiteralProperty(name_expression, value, |
2069 is_static, *is_computed_name); | 1973 is_static, *is_computed_name); |
2070 } | 1974 } |
2071 | 1975 |
2072 case PropertyKind::kShorthandProperty: { | 1976 if (Token::IsIdentifier(name_token, language_mode(), this->is_generator(), |
| 1977 parsing_module_ || is_async_function()) && |
| 1978 (peek() == Token::COMMA || peek() == Token::RBRACE || |
| 1979 peek() == Token::ASSIGN)) { |
2073 // PropertyDefinition | 1980 // PropertyDefinition |
2074 // IdentifierReference | 1981 // IdentifierReference |
2075 // CoverInitializedName | 1982 // CoverInitializedName |
2076 // | 1983 // |
2077 // CoverInitializedName | 1984 // CoverInitializedName |
2078 // IdentifierReference Initializer? | 1985 // IdentifierReference Initializer? |
2079 if (in_class) { | |
2080 Token::Value next = Next(); | |
2081 ReportUnexpectedToken(next); | |
2082 *ok = false; | |
2083 return impl()->EmptyObjectLiteralProperty(); | |
2084 } | |
2085 | |
2086 DCHECK(!is_get && !is_set && !is_generator && !is_async && !is_static && | |
2087 !*is_computed_name); | |
2088 | |
2089 if (classifier->duplicate_finder() != nullptr && | 1986 if (classifier->duplicate_finder() != nullptr && |
2090 scanner()->FindSymbol(classifier->duplicate_finder(), 1) != 0) { | 1987 scanner()->FindSymbol(classifier->duplicate_finder(), 1) != 0) { |
2091 classifier->RecordDuplicateFormalParameterError(scanner()->location()); | 1988 classifier->RecordDuplicateFormalParameterError(scanner()->location()); |
2092 } | 1989 } |
2093 | 1990 |
2094 if (impl()->IsEvalOrArguments(*name) && is_strict(language_mode())) { | 1991 if (impl()->IsEvalOrArguments(*name) && is_strict(language_mode())) { |
2095 classifier->RecordBindingPatternError( | 1992 classifier->RecordBindingPatternError( |
2096 scanner()->location(), MessageTemplate::kStrictEvalArguments); | 1993 scanner()->location(), MessageTemplate::kStrictEvalArguments); |
2097 } | 1994 } |
2098 | 1995 |
(...skipping 28 matching lines...) Expand all Loading... |
2127 | 2024 |
2128 impl()->SetFunctionNameFromIdentifierRef(rhs, lhs); | 2025 impl()->SetFunctionNameFromIdentifierRef(rhs, lhs); |
2129 } else { | 2026 } else { |
2130 value = lhs; | 2027 value = lhs; |
2131 } | 2028 } |
2132 | 2029 |
2133 return factory()->NewObjectLiteralProperty( | 2030 return factory()->NewObjectLiteralProperty( |
2134 name_expression, value, ObjectLiteralProperty::COMPUTED, is_static, | 2031 name_expression, value, ObjectLiteralProperty::COMPUTED, is_static, |
2135 false); | 2032 false); |
2136 } | 2033 } |
| 2034 } |
2137 | 2035 |
2138 case PropertyKind::kMethodProperty: { | 2036 // Method definitions are never valid in patterns. |
2139 DCHECK(!is_get && !is_set); | 2037 classifier->RecordPatternError( |
| 2038 Scanner::Location(next_beg_pos, scanner()->location().end_pos), |
| 2039 MessageTemplate::kInvalidDestructuringTarget); |
2140 | 2040 |
2141 MethodKind method_kind = MethodKind::kNormal; | 2041 if (is_async && !IsSpecialMethod(method_kind)) { |
2142 if (is_generator) { | 2042 DCHECK(!is_get); |
2143 method_kind |= MethodKind::kGenerator; | 2043 DCHECK(!is_set); |
2144 } | 2044 bool dont_care; |
2145 if (is_async) { | 2045 name_expression = ParsePropertyName( |
2146 method_kind |= MethodKind::kAsync; | 2046 name, &dont_care, &dont_care, is_computed_name, classifier, |
2147 } | 2047 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
2148 if (is_static) { | 2048 method_kind |= MethodKind::kAsync; |
2149 method_kind |= MethodKind::kStatic; | 2049 } |
2150 } | |
2151 | 2050 |
2152 // MethodDefinition | 2051 if (is_generator || peek() == Token::LPAREN) { |
2153 // PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}' | 2052 // MethodDefinition |
2154 // '*' PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}' | 2053 // PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}' |
2155 | 2054 // '*' PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}' |
2156 classifier->RecordPatternError( | 2055 if (!*is_computed_name) { |
2157 Scanner::Location(next_beg_pos, scanner()->location().end_pos), | 2056 checker->CheckProperty(name_token, kMethodProperty, method_kind, |
2158 MessageTemplate::kInvalidDestructuringTarget); | 2057 classifier, |
2159 | 2058 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
2160 if (!*is_computed_name) { | |
2161 checker->CheckProperty(name_token, PropertyKind::kMethodProperty, | |
2162 method_kind, classifier, | |
2163 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
2164 } | |
2165 | |
2166 FunctionKind kind = is_generator | |
2167 ? FunctionKind::kConciseGeneratorMethod | |
2168 : is_async ? FunctionKind::kAsyncConciseMethod | |
2169 : FunctionKind::kConciseMethod; | |
2170 | |
2171 if (in_class && !is_static && impl()->IsConstructor(*name)) { | |
2172 *has_seen_constructor = true; | |
2173 kind = has_extends ? FunctionKind::kSubclassConstructor | |
2174 : FunctionKind::kBaseConstructor; | |
2175 } | |
2176 | |
2177 ExpressionT value = impl()->ParseFunctionLiteral( | |
2178 *name, scanner()->location(), kSkipFunctionNameCheck, kind, | |
2179 kNoSourcePosition, FunctionLiteral::kAccessorOrMethod, | |
2180 language_mode(), CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
2181 | |
2182 return factory()->NewObjectLiteralProperty( | |
2183 name_expression, value, ObjectLiteralProperty::COMPUTED, is_static, | |
2184 *is_computed_name); | |
2185 } | 2059 } |
2186 | 2060 |
2187 case PropertyKind::kAccessorProperty: { | 2061 FunctionKind kind = is_generator |
2188 DCHECK((is_get || is_set) && !is_generator && !is_async); | 2062 ? FunctionKind::kConciseGeneratorMethod |
| 2063 : is_async ? FunctionKind::kAsyncConciseMethod |
| 2064 : FunctionKind::kConciseMethod; |
2189 | 2065 |
2190 MethodKind method_kind = MethodKind::kNormal; | 2066 if (in_class && !IsStaticMethod(method_kind) && |
2191 if (is_static) { | 2067 impl()->IsConstructor(*name)) { |
2192 DCHECK(in_class); | 2068 *has_seen_constructor = true; |
2193 method_kind |= MethodKind::kStatic; | 2069 kind = has_extends ? FunctionKind::kSubclassConstructor |
2194 } | 2070 : FunctionKind::kBaseConstructor; |
| 2071 } |
2195 | 2072 |
2196 classifier->RecordPatternError( | 2073 ExpressionT value = impl()->ParseFunctionLiteral( |
2197 Scanner::Location(next_beg_pos, scanner()->location().end_pos), | 2074 *name, scanner()->location(), kSkipFunctionNameCheck, kind, |
2198 MessageTemplate::kInvalidDestructuringTarget); | 2075 kNoSourcePosition, FunctionLiteral::kAccessorOrMethod, language_mode(), |
2199 if (!*is_computed_name) { | 2076 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
2200 checker->CheckProperty(name_token, PropertyKind::kAccessorProperty, | |
2201 method_kind, classifier, | |
2202 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
2203 } | |
2204 | 2077 |
2205 typename Types::FunctionLiteral value = impl()->ParseFunctionLiteral( | 2078 return factory()->NewObjectLiteralProperty(name_expression, value, |
2206 *name, scanner()->location(), kSkipFunctionNameCheck, | 2079 ObjectLiteralProperty::COMPUTED, |
2207 is_get ? FunctionKind::kGetterFunction | 2080 is_static, *is_computed_name); |
2208 : FunctionKind::kSetterFunction, | 2081 } |
2209 kNoSourcePosition, FunctionLiteral::kAccessorOrMethod, | |
2210 language_mode(), CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
2211 | 2082 |
2212 // Make sure the name expression is a string since we need a Name for | 2083 if (in_class && name_token == Token::STATIC && IsNormalMethod(method_kind)) { |
2213 // Runtime_DefineAccessorPropertyUnchecked and since we can determine this | 2084 // ClassElement (static) |
2214 // statically we can skip the extra runtime check. | 2085 // 'static' MethodDefinition |
2215 if (!*is_computed_name) { | 2086 *name = impl()->EmptyIdentifier(); |
2216 name_expression = | 2087 ObjectLiteralPropertyT property = ParsePropertyDefinition( |
2217 factory()->NewStringLiteral(*name, name_expression->position()); | 2088 checker, true, has_extends, MethodKind::kStatic, is_computed_name, |
2218 } | 2089 nullptr, classifier, name, ok); |
| 2090 impl()->RewriteNonPattern(classifier, ok); |
| 2091 return property; |
| 2092 } |
2219 | 2093 |
2220 return factory()->NewObjectLiteralProperty( | 2094 if (is_get || is_set) { |
2221 name_expression, value, is_get ? ObjectLiteralProperty::GETTER | 2095 // MethodDefinition (Accessors) |
2222 : ObjectLiteralProperty::SETTER, | 2096 // get PropertyName '(' ')' '{' FunctionBody '}' |
2223 is_static, *is_computed_name); | 2097 // set PropertyName '(' PropertySetParameterList ')' '{' FunctionBody '}' |
| 2098 *name = impl()->EmptyIdentifier(); |
| 2099 bool dont_care = false; |
| 2100 name_token = peek(); |
| 2101 |
| 2102 name_expression = ParsePropertyName( |
| 2103 name, &dont_care, &dont_care, is_computed_name, classifier, |
| 2104 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| 2105 |
| 2106 if (!*is_computed_name) { |
| 2107 checker->CheckProperty(name_token, kAccessorProperty, method_kind, |
| 2108 classifier, |
| 2109 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
2224 } | 2110 } |
| 2111 |
| 2112 FunctionLiteralT value = impl()->ParseFunctionLiteral( |
| 2113 *name, scanner()->location(), kSkipFunctionNameCheck, |
| 2114 is_get ? FunctionKind::kGetterFunction : FunctionKind::kSetterFunction, |
| 2115 kNoSourcePosition, FunctionLiteral::kAccessorOrMethod, language_mode(), |
| 2116 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| 2117 |
| 2118 // Make sure the name expression is a string since we need a Name for |
| 2119 // Runtime_DefineAccessorPropertyUnchecked and since we can determine this |
| 2120 // statically we can skip the extra runtime check. |
| 2121 if (!*is_computed_name) { |
| 2122 name_expression = |
| 2123 factory()->NewStringLiteral(*name, name_expression->position()); |
| 2124 } |
| 2125 |
| 2126 return factory()->NewObjectLiteralProperty( |
| 2127 name_expression, value, |
| 2128 is_get ? ObjectLiteralProperty::GETTER : ObjectLiteralProperty::SETTER, |
| 2129 is_static, *is_computed_name); |
2225 } | 2130 } |
2226 UNREACHABLE(); | 2131 |
| 2132 Token::Value next = Next(); |
| 2133 ReportUnexpectedToken(next); |
| 2134 *ok = false; |
2227 return impl()->EmptyObjectLiteralProperty(); | 2135 return impl()->EmptyObjectLiteralProperty(); |
2228 } | 2136 } |
2229 | 2137 |
2230 template <typename Impl> | 2138 template <typename Impl> |
2231 typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseObjectLiteral( | 2139 typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseObjectLiteral( |
2232 ExpressionClassifier* classifier, bool* ok) { | 2140 ExpressionClassifier* classifier, bool* ok) { |
2233 // ObjectLiteral :: | 2141 // ObjectLiteral :: |
2234 // '{' (PropertyDefinition (',' PropertyDefinition)* ','? )? '}' | 2142 // '{' (PropertyDefinition (',' PropertyDefinition)* ','? )? '}' |
2235 | 2143 |
2236 int pos = peek_position(); | 2144 int pos = peek_position(); |
2237 typename Types::PropertyList properties = impl()->NewPropertyList(4); | 2145 typename Types::PropertyList properties = impl()->NewPropertyList(4); |
2238 int number_of_boilerplate_properties = 0; | 2146 int number_of_boilerplate_properties = 0; |
2239 bool has_computed_names = false; | 2147 bool has_computed_names = false; |
2240 ObjectLiteralChecker checker(this); | 2148 ObjectLiteralChecker checker(this); |
2241 | 2149 |
2242 Expect(Token::LBRACE, CHECK_OK); | 2150 Expect(Token::LBRACE, CHECK_OK); |
2243 | 2151 |
2244 while (peek() != Token::RBRACE) { | 2152 while (peek() != Token::RBRACE) { |
2245 FuncNameInferrer::State fni_state(fni_); | 2153 FuncNameInferrer::State fni_state(fni_); |
2246 | 2154 |
2247 const bool in_class = false; | 2155 const bool in_class = false; |
2248 const bool has_extends = false; | 2156 const bool has_extends = false; |
2249 bool is_computed_name = false; | 2157 bool is_computed_name = false; |
2250 IdentifierT name = impl()->EmptyIdentifier(); | 2158 IdentifierT name = impl()->EmptyIdentifier(); |
2251 ObjectLiteralPropertyT property = ParsePropertyDefinition( | 2159 ObjectLiteralPropertyT property = ParsePropertyDefinition( |
2252 &checker, in_class, has_extends, &is_computed_name, nullptr, classifier, | 2160 &checker, in_class, has_extends, MethodKind::kNormal, &is_computed_name, |
2253 &name, CHECK_OK); | 2161 NULL, classifier, &name, CHECK_OK); |
2254 | 2162 |
2255 if (is_computed_name) { | 2163 if (is_computed_name) { |
2256 has_computed_names = true; | 2164 has_computed_names = true; |
2257 } | 2165 } |
2258 | 2166 |
2259 // Count CONSTANT or COMPUTED properties to maintain the enumeration order. | 2167 // Count CONSTANT or COMPUTED properties to maintain the enumeration order. |
2260 if (!has_computed_names && impl()->IsBoilerplateProperty(property)) { | 2168 if (!has_computed_names && impl()->IsBoilerplateProperty(property)) { |
2261 number_of_boilerplate_properties++; | 2169 number_of_boilerplate_properties++; |
2262 } | 2170 } |
2263 properties->Add(property, zone()); | 2171 properties->Add(property, zone()); |
(...skipping 1469 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3733 | 3641 |
3734 | 3642 |
3735 #undef CHECK_OK | 3643 #undef CHECK_OK |
3736 #undef CHECK_OK_CUSTOM | 3644 #undef CHECK_OK_CUSTOM |
3737 | 3645 |
3738 template <typename Impl> | 3646 template <typename Impl> |
3739 void ParserBase<Impl>::ObjectLiteralChecker::CheckProperty( | 3647 void ParserBase<Impl>::ObjectLiteralChecker::CheckProperty( |
3740 Token::Value property, PropertyKind type, MethodKind method_type, | 3648 Token::Value property, PropertyKind type, MethodKind method_type, |
3741 ExpressionClassifier* classifier, bool* ok) { | 3649 ExpressionClassifier* classifier, bool* ok) { |
3742 DCHECK(!IsStaticMethod(method_type)); | 3650 DCHECK(!IsStaticMethod(method_type)); |
3743 DCHECK(!IsSpecialMethod(method_type) || | 3651 DCHECK(!IsSpecialMethod(method_type) || type == kMethodProperty); |
3744 type == PropertyKind::kMethodProperty); | |
3745 | 3652 |
3746 if (property == Token::SMI || property == Token::NUMBER) return; | 3653 if (property == Token::SMI || property == Token::NUMBER) return; |
3747 | 3654 |
3748 if (type == PropertyKind::kValueProperty && IsProto()) { | 3655 if (type == kValueProperty && IsProto()) { |
3749 if (has_seen_proto_) { | 3656 if (has_seen_proto_) { |
3750 classifier->RecordExpressionError(this->scanner()->location(), | 3657 classifier->RecordExpressionError(this->scanner()->location(), |
3751 MessageTemplate::kDuplicateProto); | 3658 MessageTemplate::kDuplicateProto); |
3752 return; | 3659 return; |
3753 } | 3660 } |
3754 has_seen_proto_ = true; | 3661 has_seen_proto_ = true; |
3755 } | 3662 } |
3756 } | 3663 } |
3757 | 3664 |
3758 template <typename Impl> | 3665 template <typename Impl> |
3759 void ParserBase<Impl>::ClassLiteralChecker::CheckProperty( | 3666 void ParserBase<Impl>::ClassLiteralChecker::CheckProperty( |
3760 Token::Value property, PropertyKind type, MethodKind method_type, | 3667 Token::Value property, PropertyKind type, MethodKind method_type, |
3761 ExpressionClassifier* classifier, bool* ok) { | 3668 ExpressionClassifier* classifier, bool* ok) { |
3762 DCHECK(type == PropertyKind::kMethodProperty || | 3669 DCHECK(type == kMethodProperty || type == kAccessorProperty); |
3763 type == PropertyKind::kAccessorProperty); | |
3764 | 3670 |
3765 if (property == Token::SMI || property == Token::NUMBER) return; | 3671 if (property == Token::SMI || property == Token::NUMBER) return; |
3766 | 3672 |
3767 if (IsStaticMethod(method_type)) { | 3673 if (IsStaticMethod(method_type)) { |
3768 if (IsPrototype()) { | 3674 if (IsPrototype()) { |
3769 this->parser()->ReportMessage(MessageTemplate::kStaticPrototype); | 3675 this->parser()->ReportMessage(MessageTemplate::kStaticPrototype); |
3770 *ok = false; | 3676 *ok = false; |
3771 return; | 3677 return; |
3772 } | 3678 } |
3773 } else if (IsConstructor()) { | 3679 } else if (IsConstructor()) { |
3774 const bool is_generator = IsGeneratorMethod(method_type); | 3680 const bool is_generator = IsGeneratorMethod(method_type); |
3775 const bool is_async = IsAsyncMethod(method_type); | 3681 const bool is_async = IsAsyncMethod(method_type); |
3776 if (is_generator || is_async || type == PropertyKind::kAccessorProperty) { | 3682 if (is_generator || is_async || type == kAccessorProperty) { |
3777 MessageTemplate::Template msg = | 3683 MessageTemplate::Template msg = |
3778 is_generator ? MessageTemplate::kConstructorIsGenerator | 3684 is_generator ? MessageTemplate::kConstructorIsGenerator |
3779 : is_async ? MessageTemplate::kConstructorIsAsync | 3685 : is_async ? MessageTemplate::kConstructorIsAsync |
3780 : MessageTemplate::kConstructorIsAccessor; | 3686 : MessageTemplate::kConstructorIsAccessor; |
3781 this->parser()->ReportMessage(msg); | 3687 this->parser()->ReportMessage(msg); |
3782 *ok = false; | 3688 *ok = false; |
3783 return; | 3689 return; |
3784 } | 3690 } |
3785 if (has_seen_constructor_) { | 3691 if (has_seen_constructor_) { |
3786 this->parser()->ReportMessage(MessageTemplate::kDuplicateConstructor); | 3692 this->parser()->ReportMessage(MessageTemplate::kDuplicateConstructor); |
3787 *ok = false; | 3693 *ok = false; |
3788 return; | 3694 return; |
3789 } | 3695 } |
3790 has_seen_constructor_ = true; | 3696 has_seen_constructor_ = true; |
3791 return; | 3697 return; |
3792 } | 3698 } |
3793 } | 3699 } |
3794 | 3700 |
3795 | 3701 |
3796 } // namespace internal | 3702 } // namespace internal |
3797 } // namespace v8 | 3703 } // namespace v8 |
3798 | 3704 |
3799 #endif // V8_PARSING_PARSER_BASE_H | 3705 #endif // V8_PARSING_PARSER_BASE_H |
OLD | NEW |