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