Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef V8_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 |