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