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 *is_generator = Check(Token::MUL); | |
1895 | |
1868 Token::Value token = peek(); | 1896 Token::Value token = peek(); |
1869 int pos = peek_position(); | 1897 int pos = peek_position(); |
1870 | 1898 |
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 | |
1871 // For non computed property names we normalize the name a bit: | 1949 // For non computed property names we normalize the name a bit: |
1872 // | 1950 // |
1873 // "12" -> 12 | 1951 // "12" -> 12 |
1874 // 12.3 -> "12.3" | 1952 // 12.3 -> "12.3" |
1875 // 12.30 -> "12.3" | 1953 // 12.30 -> "12.3" |
1876 // identifier -> "identifier" | 1954 // identifier -> "identifier" |
1877 // | 1955 // |
1878 // This is important because we use the property name as a key in a hash | 1956 // This is important because we use the property name as a key in a hash |
1879 // table when we compute constant properties. | 1957 // table when we compute constant properties. |
1958 ExpressionT expression; | |
1880 switch (token) { | 1959 switch (token) { |
1881 case Token::STRING: | 1960 case Token::STRING: |
1882 Consume(Token::STRING); | 1961 Consume(Token::STRING); |
1883 *name = impl()->GetSymbol(); | 1962 *name = impl()->GetSymbol(); |
1884 break; | 1963 break; |
1885 | 1964 |
1886 case Token::SMI: | 1965 case Token::SMI: |
1887 Consume(Token::SMI); | 1966 Consume(Token::SMI); |
1888 *name = impl()->GetNumberAsSymbol(); | 1967 *name = impl()->GetNumberAsSymbol(); |
1889 break; | 1968 break; |
1890 | 1969 |
1891 case Token::NUMBER: | 1970 case Token::NUMBER: |
1892 Consume(Token::NUMBER); | 1971 Consume(Token::NUMBER); |
1893 *name = impl()->GetNumberAsSymbol(); | 1972 *name = impl()->GetNumberAsSymbol(); |
1894 break; | 1973 break; |
1895 | 1974 |
1896 case Token::LBRACK: { | 1975 case Token::LBRACK: { |
1976 *name = impl()->EmptyIdentifier(); | |
1897 *is_computed_name = true; | 1977 *is_computed_name = true; |
1898 Consume(Token::LBRACK); | 1978 Consume(Token::LBRACK); |
1899 ExpressionClassifier computed_name_classifier(this); | 1979 ExpressionClassifier computed_name_classifier(this); |
1900 ExpressionT expression = | 1980 expression = |
1901 ParseAssignmentExpression(true, &computed_name_classifier, CHECK_OK); | 1981 ParseAssignmentExpression(true, &computed_name_classifier, CHECK_OK); |
1902 impl()->RewriteNonPattern(&computed_name_classifier, CHECK_OK); | 1982 impl()->RewriteNonPattern(&computed_name_classifier, CHECK_OK); |
1903 classifier->AccumulateFormalParameterContainmentErrors( | 1983 classifier->AccumulateFormalParameterContainmentErrors( |
1904 &computed_name_classifier); | 1984 &computed_name_classifier); |
1905 Expect(Token::RBRACK, CHECK_OK); | 1985 Expect(Token::RBRACK, CHECK_OK); |
1906 return expression; | 1986 break; |
1907 } | 1987 } |
1908 | 1988 |
1909 default: | 1989 default: |
1910 *name = ParseIdentifierName(CHECK_OK); | 1990 *name = ParseIdentifierName(CHECK_OK); |
1911 scanner()->IsGetOrSet(is_get, is_set); | |
1912 break; | 1991 break; |
1913 } | 1992 } |
1914 | 1993 |
1994 if (peek() != Token::COLON && *kind == PropertyKind::kValueProperty) { | |
marja
2016/08/29 08:07:46
This is still duplicate logic; can this call SetPr
bakkot
2016/08/29 19:54:50
Done. It's a little unpleasant, and strictly speak
| |
1995 switch (peek()) { | |
1996 case Token::COLON: | |
1997 UNREACHABLE(); | |
1998 break; | |
1999 case Token::COMMA: | |
2000 case Token::RBRACE: | |
2001 case Token::ASSIGN: | |
2002 if (!Token::IsIdentifier(token, language_mode(), this->is_generator(), | |
2003 parsing_module_ || is_async_function())) { | |
2004 Token::Value next = Next(); | |
2005 ReportUnexpectedToken(next); | |
2006 *ok = false; | |
2007 return impl()->EmptyExpression(); | |
2008 } | |
2009 *kind = PropertyKind::kShorthandProperty; | |
2010 break; | |
2011 case Token::LPAREN: | |
2012 *kind = PropertyKind::kMethodProperty; | |
2013 break; | |
2014 default: { | |
2015 Token::Value next = Next(); | |
2016 ReportUnexpectedToken(next); | |
2017 *ok = false; | |
2018 return impl()->EmptyExpression(); | |
2019 } | |
2020 } | |
2021 } | |
2022 | |
2023 if (*is_computed_name) { | |
2024 return expression; | |
2025 } | |
2026 | |
2027 if (fni_ != nullptr) { | |
2028 impl()->PushLiteralName(fni_, *name); | |
2029 } | |
2030 | |
1915 uint32_t index; | 2031 uint32_t index; |
1916 return impl()->IsArrayIndex(*name, &index) | 2032 return impl()->IsArrayIndex(*name, &index) |
1917 ? factory()->NewNumberLiteral(index, pos) | 2033 ? factory()->NewNumberLiteral(index, pos) |
1918 : factory()->NewStringLiteral(*name, pos); | 2034 : factory()->NewStringLiteral(*name, pos); |
1919 } | 2035 } |
1920 | 2036 |
1921 template <typename Impl> | 2037 template <typename Impl> |
1922 typename ParserBase<Impl>::ObjectLiteralPropertyT | 2038 typename ParserBase<Impl>::ObjectLiteralPropertyT |
1923 ParserBase<Impl>::ParsePropertyDefinition( | 2039 ParserBase<Impl>::ParsePropertyDefinition(ObjectLiteralCheckerBase* checker, |
1924 ObjectLiteralCheckerBase* checker, bool in_class, bool has_extends, | 2040 bool in_class, bool has_extends, |
1925 MethodKind method_kind, bool* is_computed_name, bool* has_seen_constructor, | 2041 bool* is_computed_name, |
1926 ExpressionClassifier* classifier, IdentifierT* name, bool* ok) { | 2042 bool* has_seen_constructor, |
1927 DCHECK(!in_class || IsStaticMethod(method_kind) || | 2043 ExpressionClassifier* classifier, |
1928 has_seen_constructor != nullptr); | 2044 IdentifierT* name, bool* ok) { |
2045 DCHECK(!in_class || has_seen_constructor != nullptr); | |
1929 bool is_get = false; | 2046 bool is_get = false; |
1930 bool is_set = false; | 2047 bool is_set = false; |
1931 bool is_generator = Check(Token::MUL); | 2048 bool is_generator = false; |
1932 bool is_async = false; | 2049 bool is_async = false; |
1933 const bool is_static = IsStaticMethod(method_kind); | 2050 bool is_static = false; |
2051 PropertyKind kind = PropertyKind::kValueProperty; | |
1934 | 2052 |
1935 Token::Value name_token = peek(); | 2053 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; | 2054 int next_beg_pos = scanner()->peek_location().beg_pos; |
1946 int next_end_pos = scanner()->peek_location().end_pos; | 2055 int next_end_pos = scanner()->peek_location().end_pos; |
2056 | |
1947 ExpressionT name_expression = | 2057 ExpressionT name_expression = |
1948 ParsePropertyName(name, &is_get, &is_set, is_computed_name, classifier, | 2058 ParsePropertyName(name, &kind, in_class, &is_generator, &is_get, &is_set, |
2059 &is_async, &is_static, is_computed_name, classifier, | |
1949 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 2060 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
1950 | 2061 |
1951 if (fni_ != nullptr && !*is_computed_name) { | 2062 switch (kind) { |
1952 impl()->PushLiteralName(fni_, *name); | 2063 case PropertyKind::kValueProperty: { |
1953 } | 2064 if (in_class) { |
2065 Token::Value next = Next(); | |
2066 ReportUnexpectedToken(next); | |
2067 *ok = false; | |
2068 return impl()->EmptyObjectLiteralProperty(); | |
2069 } | |
1954 | 2070 |
1955 if (!in_class && !is_generator) { | 2071 DCHECK(!is_get && !is_set && !is_generator && !is_async && !is_static); |
1956 DCHECK(!IsStaticMethod(method_kind)); | 2072 |
1957 if (peek() == Token::COLON) { | |
1958 // PropertyDefinition | |
1959 // PropertyName ':' AssignmentExpression | |
1960 if (!*is_computed_name) { | 2073 if (!*is_computed_name) { |
1961 checker->CheckProperty(name_token, kValueProperty, MethodKind::kNormal, | 2074 checker->CheckProperty(name_token, PropertyKind::kValueProperty, |
1962 classifier, | 2075 MethodKind::kNormal, classifier, |
1963 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 2076 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
1964 } | 2077 } |
1965 Consume(Token::COLON); | 2078 Consume(Token::COLON); |
1966 int beg_pos = peek_position(); | 2079 int beg_pos = peek_position(); |
1967 ExpressionT value = ParseAssignmentExpression( | 2080 ExpressionT value = ParseAssignmentExpression( |
1968 true, classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 2081 true, classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
1969 CheckDestructuringElement(value, classifier, beg_pos, | 2082 CheckDestructuringElement(value, classifier, beg_pos, |
1970 scanner()->location().end_pos); | 2083 scanner()->location().end_pos); |
1971 | 2084 |
1972 return factory()->NewObjectLiteralProperty(name_expression, value, | 2085 return factory()->NewObjectLiteralProperty(name_expression, value, |
1973 is_static, *is_computed_name); | 2086 is_static, *is_computed_name); |
1974 } | 2087 } |
1975 | 2088 |
1976 if (Token::IsIdentifier(name_token, language_mode(), this->is_generator(), | 2089 case PropertyKind::kShorthandProperty: { |
1977 parsing_module_ || is_async_function()) && | |
1978 (peek() == Token::COMMA || peek() == Token::RBRACE || | |
1979 peek() == Token::ASSIGN)) { | |
1980 // PropertyDefinition | 2090 // PropertyDefinition |
1981 // IdentifierReference | 2091 // IdentifierReference |
1982 // CoverInitializedName | 2092 // CoverInitializedName |
1983 // | 2093 // |
1984 // CoverInitializedName | 2094 // CoverInitializedName |
1985 // IdentifierReference Initializer? | 2095 // IdentifierReference Initializer? |
2096 if (in_class) { | |
2097 Token::Value next = Next(); | |
2098 ReportUnexpectedToken(next); | |
2099 *ok = false; | |
2100 return impl()->EmptyObjectLiteralProperty(); | |
2101 } | |
2102 | |
2103 DCHECK(!is_get && !is_set && !is_generator && !is_async && !is_static && | |
2104 !*is_computed_name); | |
2105 | |
1986 if (classifier->duplicate_finder() != nullptr && | 2106 if (classifier->duplicate_finder() != nullptr && |
1987 scanner()->FindSymbol(classifier->duplicate_finder(), 1) != 0) { | 2107 scanner()->FindSymbol(classifier->duplicate_finder(), 1) != 0) { |
1988 classifier->RecordDuplicateFormalParameterError(scanner()->location()); | 2108 classifier->RecordDuplicateFormalParameterError(scanner()->location()); |
1989 } | 2109 } |
1990 | 2110 |
1991 if (impl()->IsEvalOrArguments(*name) && is_strict(language_mode())) { | 2111 if (impl()->IsEvalOrArguments(*name) && is_strict(language_mode())) { |
1992 classifier->RecordBindingPatternError( | 2112 classifier->RecordBindingPatternError( |
1993 scanner()->location(), MessageTemplate::kStrictEvalArguments); | 2113 scanner()->location(), MessageTemplate::kStrictEvalArguments); |
1994 } | 2114 } |
1995 | 2115 |
(...skipping 28 matching lines...) Expand all Loading... | |
2024 | 2144 |
2025 impl()->SetFunctionNameFromIdentifierRef(rhs, lhs); | 2145 impl()->SetFunctionNameFromIdentifierRef(rhs, lhs); |
2026 } else { | 2146 } else { |
2027 value = lhs; | 2147 value = lhs; |
2028 } | 2148 } |
2029 | 2149 |
2030 return factory()->NewObjectLiteralProperty( | 2150 return factory()->NewObjectLiteralProperty( |
2031 name_expression, value, ObjectLiteralProperty::COMPUTED, is_static, | 2151 name_expression, value, ObjectLiteralProperty::COMPUTED, is_static, |
2032 false); | 2152 false); |
2033 } | 2153 } |
2034 } | |
2035 | 2154 |
2036 // Method definitions are never valid in patterns. | 2155 case PropertyKind::kMethodProperty: { |
2037 classifier->RecordPatternError( | 2156 DCHECK(!is_get && !is_set); |
2038 Scanner::Location(next_beg_pos, scanner()->location().end_pos), | |
2039 MessageTemplate::kInvalidDestructuringTarget); | |
2040 | 2157 |
2041 if (is_async && !IsSpecialMethod(method_kind)) { | 2158 MethodKind method_kind = MethodKind::kNormal; |
2042 DCHECK(!is_get); | 2159 if (is_generator) { |
2043 DCHECK(!is_set); | 2160 method_kind |= MethodKind::kGenerator; |
2044 bool dont_care; | 2161 } |
2045 name_expression = ParsePropertyName( | 2162 if (is_async) { |
2046 name, &dont_care, &dont_care, is_computed_name, classifier, | 2163 method_kind |= MethodKind::kAsync; |
2047 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 2164 } |
2048 method_kind |= MethodKind::kAsync; | 2165 if (is_static) { |
2049 } | 2166 method_kind |= MethodKind::kStatic; |
2167 } | |
2050 | 2168 |
2051 if (is_generator || peek() == Token::LPAREN) { | 2169 // MethodDefinition |
2052 // MethodDefinition | 2170 // PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}' |
2053 // PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}' | 2171 // '*' PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}' |
2054 // '*' PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}' | 2172 |
2055 if (!*is_computed_name) { | 2173 classifier->RecordPatternError( |
2056 checker->CheckProperty(name_token, kMethodProperty, method_kind, | 2174 Scanner::Location(next_beg_pos, scanner()->location().end_pos), |
2057 classifier, | 2175 MessageTemplate::kInvalidDestructuringTarget); |
2058 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 2176 |
2177 if (!*is_computed_name) { | |
2178 checker->CheckProperty(name_token, PropertyKind::kMethodProperty, | |
2179 method_kind, classifier, | |
2180 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
2181 } | |
2182 | |
2183 FunctionKind kind = is_generator | |
2184 ? FunctionKind::kConciseGeneratorMethod | |
2185 : is_async ? FunctionKind::kAsyncConciseMethod | |
2186 : FunctionKind::kConciseMethod; | |
2187 | |
2188 if (in_class && !is_static && impl()->IsConstructor(*name)) { | |
2189 *has_seen_constructor = true; | |
2190 kind = has_extends ? FunctionKind::kSubclassConstructor | |
2191 : FunctionKind::kBaseConstructor; | |
2192 } | |
2193 | |
2194 ExpressionT value = impl()->ParseFunctionLiteral( | |
2195 *name, scanner()->location(), kSkipFunctionNameCheck, kind, | |
2196 kNoSourcePosition, FunctionLiteral::kAccessorOrMethod, | |
2197 language_mode(), CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
2198 | |
2199 return factory()->NewObjectLiteralProperty( | |
2200 name_expression, value, ObjectLiteralProperty::COMPUTED, is_static, | |
2201 *is_computed_name); | |
2059 } | 2202 } |
2060 | 2203 |
2061 FunctionKind kind = is_generator | 2204 case PropertyKind::kAccessorProperty: { |
2062 ? FunctionKind::kConciseGeneratorMethod | 2205 DCHECK((is_get || is_set) && !is_generator && !is_async); |
2063 : is_async ? FunctionKind::kAsyncConciseMethod | |
2064 : FunctionKind::kConciseMethod; | |
2065 | 2206 |
2066 if (in_class && !IsStaticMethod(method_kind) && | 2207 MethodKind method_kind = MethodKind::kNormal; |
2067 impl()->IsConstructor(*name)) { | 2208 if (is_static) { |
2068 *has_seen_constructor = true; | 2209 DCHECK(in_class); |
2069 kind = has_extends ? FunctionKind::kSubclassConstructor | 2210 method_kind |= MethodKind::kStatic; |
2070 : FunctionKind::kBaseConstructor; | 2211 } |
2212 | |
2213 classifier->RecordPatternError( | |
2214 Scanner::Location(next_beg_pos, scanner()->location().end_pos), | |
2215 MessageTemplate::kInvalidDestructuringTarget); | |
2216 if (!*is_computed_name) { | |
2217 checker->CheckProperty(name_token, PropertyKind::kAccessorProperty, | |
2218 method_kind, classifier, | |
2219 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
2220 } | |
2221 | |
2222 typename Types::FunctionLiteral value = impl()->ParseFunctionLiteral( | |
2223 *name, scanner()->location(), kSkipFunctionNameCheck, | |
2224 is_get ? FunctionKind::kGetterFunction | |
2225 : FunctionKind::kSetterFunction, | |
2226 kNoSourcePosition, FunctionLiteral::kAccessorOrMethod, | |
2227 language_mode(), CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
2228 | |
2229 // Make sure the name expression is a string since we need a Name for | |
2230 // Runtime_DefineAccessorPropertyUnchecked and since we can determine this | |
2231 // statically we can skip the extra runtime check. | |
2232 if (!*is_computed_name) { | |
2233 name_expression = | |
2234 factory()->NewStringLiteral(*name, name_expression->position()); | |
2235 } | |
2236 | |
2237 return factory()->NewObjectLiteralProperty( | |
2238 name_expression, value, is_get ? ObjectLiteralProperty::GETTER | |
2239 : ObjectLiteralProperty::SETTER, | |
2240 is_static, *is_computed_name); | |
2071 } | 2241 } |
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 } | 2242 } |
2082 | 2243 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(); | 2244 return impl()->EmptyObjectLiteralProperty(); |
2136 } | 2245 } |
2137 | 2246 |
2138 template <typename Impl> | 2247 template <typename Impl> |
2139 typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseObjectLiteral( | 2248 typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseObjectLiteral( |
2140 ExpressionClassifier* classifier, bool* ok) { | 2249 ExpressionClassifier* classifier, bool* ok) { |
2141 // ObjectLiteral :: | 2250 // ObjectLiteral :: |
2142 // '{' (PropertyDefinition (',' PropertyDefinition)* ','? )? '}' | 2251 // '{' (PropertyDefinition (',' PropertyDefinition)* ','? )? '}' |
2143 | 2252 |
2144 int pos = peek_position(); | 2253 int pos = peek_position(); |
2145 typename Types::PropertyList properties = impl()->NewPropertyList(4); | 2254 typename Types::PropertyList properties = impl()->NewPropertyList(4); |
2146 int number_of_boilerplate_properties = 0; | 2255 int number_of_boilerplate_properties = 0; |
2147 bool has_computed_names = false; | 2256 bool has_computed_names = false; |
2148 ObjectLiteralChecker checker(this); | 2257 ObjectLiteralChecker checker(this); |
2149 | 2258 |
2150 Expect(Token::LBRACE, CHECK_OK); | 2259 Expect(Token::LBRACE, CHECK_OK); |
2151 | 2260 |
2152 while (peek() != Token::RBRACE) { | 2261 while (peek() != Token::RBRACE) { |
2153 FuncNameInferrer::State fni_state(fni_); | 2262 FuncNameInferrer::State fni_state(fni_); |
2154 | 2263 |
2155 const bool in_class = false; | 2264 const bool in_class = false; |
2156 const bool has_extends = false; | 2265 const bool has_extends = false; |
2157 bool is_computed_name = false; | 2266 bool is_computed_name = false; |
2158 IdentifierT name = impl()->EmptyIdentifier(); | 2267 IdentifierT name = impl()->EmptyIdentifier(); |
2159 ObjectLiteralPropertyT property = ParsePropertyDefinition( | 2268 ObjectLiteralPropertyT property = ParsePropertyDefinition( |
2160 &checker, in_class, has_extends, MethodKind::kNormal, &is_computed_name, | 2269 &checker, in_class, has_extends, &is_computed_name, nullptr, classifier, |
2161 NULL, classifier, &name, CHECK_OK); | 2270 &name, CHECK_OK); |
2162 | 2271 |
2163 if (is_computed_name) { | 2272 if (is_computed_name) { |
2164 has_computed_names = true; | 2273 has_computed_names = true; |
2165 } | 2274 } |
2166 | 2275 |
2167 // Count CONSTANT or COMPUTED properties to maintain the enumeration order. | 2276 // Count CONSTANT or COMPUTED properties to maintain the enumeration order. |
2168 if (!has_computed_names && impl()->IsBoilerplateProperty(property)) { | 2277 if (!has_computed_names && impl()->IsBoilerplateProperty(property)) { |
2169 number_of_boilerplate_properties++; | 2278 number_of_boilerplate_properties++; |
2170 } | 2279 } |
2171 properties->Add(property, zone()); | 2280 properties->Add(property, zone()); |
(...skipping 1462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3634 | 3743 |
3635 | 3744 |
3636 #undef CHECK_OK | 3745 #undef CHECK_OK |
3637 #undef CHECK_OK_CUSTOM | 3746 #undef CHECK_OK_CUSTOM |
3638 | 3747 |
3639 template <typename Impl> | 3748 template <typename Impl> |
3640 void ParserBase<Impl>::ObjectLiteralChecker::CheckProperty( | 3749 void ParserBase<Impl>::ObjectLiteralChecker::CheckProperty( |
3641 Token::Value property, PropertyKind type, MethodKind method_type, | 3750 Token::Value property, PropertyKind type, MethodKind method_type, |
3642 ExpressionClassifier* classifier, bool* ok) { | 3751 ExpressionClassifier* classifier, bool* ok) { |
3643 DCHECK(!IsStaticMethod(method_type)); | 3752 DCHECK(!IsStaticMethod(method_type)); |
3644 DCHECK(!IsSpecialMethod(method_type) || type == kMethodProperty); | 3753 DCHECK(!IsSpecialMethod(method_type) || |
3754 type == PropertyKind::kMethodProperty); | |
3645 | 3755 |
3646 if (property == Token::SMI || property == Token::NUMBER) return; | 3756 if (property == Token::SMI || property == Token::NUMBER) return; |
3647 | 3757 |
3648 if (type == kValueProperty && IsProto()) { | 3758 if (type == PropertyKind::kValueProperty && IsProto()) { |
3649 if (has_seen_proto_) { | 3759 if (has_seen_proto_) { |
3650 classifier->RecordExpressionError(this->scanner()->location(), | 3760 classifier->RecordExpressionError(this->scanner()->location(), |
3651 MessageTemplate::kDuplicateProto); | 3761 MessageTemplate::kDuplicateProto); |
3652 return; | 3762 return; |
3653 } | 3763 } |
3654 has_seen_proto_ = true; | 3764 has_seen_proto_ = true; |
3655 } | 3765 } |
3656 } | 3766 } |
3657 | 3767 |
3658 template <typename Impl> | 3768 template <typename Impl> |
3659 void ParserBase<Impl>::ClassLiteralChecker::CheckProperty( | 3769 void ParserBase<Impl>::ClassLiteralChecker::CheckProperty( |
3660 Token::Value property, PropertyKind type, MethodKind method_type, | 3770 Token::Value property, PropertyKind type, MethodKind method_type, |
3661 ExpressionClassifier* classifier, bool* ok) { | 3771 ExpressionClassifier* classifier, bool* ok) { |
3662 DCHECK(type == kMethodProperty || type == kAccessorProperty); | 3772 DCHECK(type == PropertyKind::kMethodProperty || |
3773 type == PropertyKind::kAccessorProperty); | |
3663 | 3774 |
3664 if (property == Token::SMI || property == Token::NUMBER) return; | 3775 if (property == Token::SMI || property == Token::NUMBER) return; |
3665 | 3776 |
3666 if (IsStaticMethod(method_type)) { | 3777 if (IsStaticMethod(method_type)) { |
3667 if (IsPrototype()) { | 3778 if (IsPrototype()) { |
3668 this->parser()->ReportMessage(MessageTemplate::kStaticPrototype); | 3779 this->parser()->ReportMessage(MessageTemplate::kStaticPrototype); |
3669 *ok = false; | 3780 *ok = false; |
3670 return; | 3781 return; |
3671 } | 3782 } |
3672 } else if (IsConstructor()) { | 3783 } else if (IsConstructor()) { |
3673 const bool is_generator = IsGeneratorMethod(method_type); | 3784 const bool is_generator = IsGeneratorMethod(method_type); |
3674 const bool is_async = IsAsyncMethod(method_type); | 3785 const bool is_async = IsAsyncMethod(method_type); |
3675 if (is_generator || is_async || type == kAccessorProperty) { | 3786 if (is_generator || is_async || type == PropertyKind::kAccessorProperty) { |
3676 MessageTemplate::Template msg = | 3787 MessageTemplate::Template msg = |
3677 is_generator ? MessageTemplate::kConstructorIsGenerator | 3788 is_generator ? MessageTemplate::kConstructorIsGenerator |
3678 : is_async ? MessageTemplate::kConstructorIsAsync | 3789 : is_async ? MessageTemplate::kConstructorIsAsync |
3679 : MessageTemplate::kConstructorIsAccessor; | 3790 : MessageTemplate::kConstructorIsAccessor; |
3680 this->parser()->ReportMessage(msg); | 3791 this->parser()->ReportMessage(msg); |
3681 *ok = false; | 3792 *ok = false; |
3682 return; | 3793 return; |
3683 } | 3794 } |
3684 if (has_seen_constructor_) { | 3795 if (has_seen_constructor_) { |
3685 this->parser()->ReportMessage(MessageTemplate::kDuplicateConstructor); | 3796 this->parser()->ReportMessage(MessageTemplate::kDuplicateConstructor); |
3686 *ok = false; | 3797 *ok = false; |
3687 return; | 3798 return; |
3688 } | 3799 } |
3689 has_seen_constructor_ = true; | 3800 has_seen_constructor_ = true; |
3690 return; | 3801 return; |
3691 } | 3802 } |
3692 } | 3803 } |
3693 | 3804 |
3694 | 3805 |
3695 } // namespace internal | 3806 } // namespace internal |
3696 } // namespace v8 | 3807 } // namespace v8 |
3697 | 3808 |
3698 #endif // V8_PARSING_PARSER_BASE_H | 3809 #endif // V8_PARSING_PARSER_BASE_H |
OLD | NEW |