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 1073 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1084 bool* is_async, bool* ok); | 1084 bool* is_async, bool* ok); |
1085 ExpressionT ParsePrimaryExpression(ExpressionClassifier* classifier, | 1085 ExpressionT ParsePrimaryExpression(ExpressionClassifier* classifier, |
1086 bool* ok) { | 1086 bool* ok) { |
1087 bool is_async; | 1087 bool is_async; |
1088 return ParsePrimaryExpression(classifier, &is_async, ok); | 1088 return ParsePrimaryExpression(classifier, &is_async, ok); |
1089 } | 1089 } |
1090 ExpressionT ParseExpression(bool accept_IN, bool* ok); | 1090 ExpressionT ParseExpression(bool accept_IN, bool* ok); |
1091 ExpressionT ParseExpression(bool accept_IN, ExpressionClassifier* classifier, | 1091 ExpressionT ParseExpression(bool accept_IN, ExpressionClassifier* classifier, |
1092 bool* ok); | 1092 bool* ok); |
1093 ExpressionT ParseArrayLiteral(ExpressionClassifier* classifier, bool* ok); | 1093 ExpressionT ParseArrayLiteral(ExpressionClassifier* classifier, bool* ok); |
1094 ExpressionT ParsePropertyName(IdentifierT* name, bool* is_get, bool* is_set, | 1094 |
1095 enum PropertyKind { | |
Dan Ehrenberg
2016/08/27 00:09:00
Nit: While you're at it, what if you made this a c
bakkot
2016/08/27 01:51:54
Ah, good thought. Done.
| |
1096 kAccessorProperty, | |
1097 kValueProperty, | |
1098 kShorthandProperty, | |
1099 kMethodProperty | |
1100 }; | |
1101 | |
1102 ExpressionT ParsePropertyName(IdentifierT* name, PropertyKind* kind, | |
1103 bool in_class, bool* is_generator, bool* is_get, | |
1104 bool* is_set, bool* is_async, bool* is_static, | |
1095 bool* is_computed_name, | 1105 bool* is_computed_name, |
1096 ExpressionClassifier* classifier, bool* ok); | 1106 ExpressionClassifier* classifier, bool* ok); |
1097 ExpressionT ParseObjectLiteral(ExpressionClassifier* classifier, bool* ok); | 1107 ExpressionT ParseObjectLiteral(ExpressionClassifier* classifier, bool* ok); |
1098 ObjectLiteralPropertyT ParsePropertyDefinition( | 1108 ObjectLiteralPropertyT ParsePropertyDefinition( |
1099 ObjectLiteralCheckerBase* checker, bool in_class, bool has_extends, | 1109 ObjectLiteralCheckerBase* checker, bool in_class, bool has_extends, |
1100 MethodKind kind, bool* is_computed_name, bool* has_seen_constructor, | 1110 bool* is_computed_name, bool* has_seen_constructor, |
1101 ExpressionClassifier* classifier, IdentifierT* name, bool* ok); | 1111 ExpressionClassifier* classifier, IdentifierT* name, bool* ok); |
1102 typename Traits::Type::ExpressionList ParseArguments( | 1112 typename Traits::Type::ExpressionList ParseArguments( |
1103 Scanner::Location* first_spread_pos, bool maybe_arrow, | 1113 Scanner::Location* first_spread_pos, bool maybe_arrow, |
1104 ExpressionClassifier* classifier, bool* ok); | 1114 ExpressionClassifier* classifier, bool* ok); |
1105 typename Traits::Type::ExpressionList ParseArguments( | 1115 typename Traits::Type::ExpressionList ParseArguments( |
1106 Scanner::Location* first_spread_pos, ExpressionClassifier* classifier, | 1116 Scanner::Location* first_spread_pos, ExpressionClassifier* classifier, |
1107 bool* ok) { | 1117 bool* ok) { |
1108 return ParseArguments(first_spread_pos, false, classifier, ok); | 1118 return ParseArguments(first_spread_pos, false, classifier, ok); |
1109 } | 1119 } |
1110 | 1120 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1189 if (is_sloppy(scope->language_mode())) { | 1199 if (is_sloppy(scope->language_mode())) { |
1190 // For sloppy scopes we also have to record the call at function level, | 1200 // For sloppy scopes we also have to record the call at function level, |
1191 // in case it includes declarations that will be hoisted. | 1201 // in case it includes declarations that will be hoisted. |
1192 scope->GetDeclarationScope()->RecordEvalCall(); | 1202 scope->GetDeclarationScope()->RecordEvalCall(); |
1193 } | 1203 } |
1194 return Call::IS_POSSIBLY_EVAL; | 1204 return Call::IS_POSSIBLY_EVAL; |
1195 } | 1205 } |
1196 return Call::NOT_EVAL; | 1206 return Call::NOT_EVAL; |
1197 } | 1207 } |
1198 | 1208 |
1199 // Used to validate property names in object literals and class literals | |
1200 enum PropertyKind { | |
1201 kAccessorProperty, | |
1202 kValueProperty, | |
1203 kMethodProperty | |
1204 }; | |
1205 | |
1206 class ObjectLiteralCheckerBase { | 1209 class ObjectLiteralCheckerBase { |
1207 public: | 1210 public: |
1208 explicit ObjectLiteralCheckerBase(ParserBase* parser) : parser_(parser) {} | 1211 explicit ObjectLiteralCheckerBase(ParserBase* parser) : parser_(parser) {} |
1209 | 1212 |
1210 virtual void CheckProperty(Token::Value property, PropertyKind type, | 1213 virtual void CheckProperty(Token::Value property, PropertyKind type, |
1211 MethodKind method_type, | 1214 MethodKind method_type, |
1212 ExpressionClassifier* classifier, bool* ok) = 0; | 1215 ExpressionClassifier* classifier, bool* ok) = 0; |
1213 | 1216 |
1214 virtual ~ObjectLiteralCheckerBase() {} | 1217 virtual ~ObjectLiteralCheckerBase() {} |
1215 | 1218 |
(...skipping 657 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1873 // parsing (this is OK, as it is an implementation limitation). | 1876 // parsing (this is OK, as it is an implementation limitation). |
1874 ReportMessage(MessageTemplate::kTooManySpreads); | 1877 ReportMessage(MessageTemplate::kTooManySpreads); |
1875 return impl()->EmptyExpression(); | 1878 return impl()->EmptyExpression(); |
1876 } | 1879 } |
1877 } | 1880 } |
1878 return result; | 1881 return result; |
1879 } | 1882 } |
1880 | 1883 |
1881 template <class Impl> | 1884 template <class Impl> |
1882 typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePropertyName( | 1885 typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePropertyName( |
1883 IdentifierT* name, bool* is_get, bool* is_set, bool* is_computed_name, | 1886 IdentifierT* name, PropertyKind* kind, bool in_class, bool* is_generator, |
1884 ExpressionClassifier* classifier, bool* ok) { | 1887 bool* is_get, bool* is_set, bool* is_async, bool* is_static, |
1888 bool* is_computed_name, ExpressionClassifier* classifier, bool* ok) { | |
1889 *is_generator = Check(Token::MUL); | |
1890 | |
1885 Token::Value token = peek(); | 1891 Token::Value token = peek(); |
1886 int pos = peek_position(); | 1892 int pos = peek_position(); |
1887 | 1893 |
1894 if (in_class && !*is_generator && token == Token::STATIC) { | |
1895 Consume(Token::STATIC); | |
1896 *kind = PropertyKind::kMethodProperty; | |
1897 if (peek() == Token::LPAREN) { | |
1898 *name = impl()->GetSymbol(); // TODO(bakkot) specialize on 'static' | |
1899 return factory()->NewStringLiteral(*name, pos); | |
1900 } | |
1901 *is_generator = Check(Token::MUL); | |
1902 *is_static = true; | |
1903 token = peek(); | |
1904 pos = peek_position(); | |
1905 } | |
1906 | |
1907 if (allow_harmony_async_await() && !*is_generator && token == Token::ASYNC && | |
1908 !scanner()->HasAnyLineTerminatorAfterNext()) { | |
1909 Consume(Token::ASYNC); | |
1910 *name = impl()->GetSymbol(); // TODO(bakkot) specialize on 'async' | |
1911 token = peek(); | |
1912 switch (token) { | |
1913 case Token::COLON: | |
1914 *kind = PropertyKind::kValueProperty; | |
1915 return factory()->NewStringLiteral(*name, pos); | |
1916 case Token::COMMA: | |
1917 case Token::RBRACE: | |
1918 case Token::ASSIGN: | |
1919 *kind = PropertyKind::kShorthandProperty; | |
1920 return factory()->NewStringLiteral(*name, pos); | |
1921 case Token::LPAREN: | |
1922 *kind = PropertyKind::kMethodProperty; | |
1923 return factory()->NewStringLiteral(*name, pos); | |
1924 default: | |
1925 break; // This must be an async method. | |
1926 } | |
1927 *kind = PropertyKind::kMethodProperty; | |
1928 *is_async = true; | |
1929 pos = peek_position(); | |
1930 } | |
1931 | |
1932 if (token == Token::IDENTIFIER && !*is_generator && !*is_async) { | |
1933 Consume(Token::IDENTIFIER); | |
1934 *name = impl()->GetSymbol(); | |
1935 token = peek(); | |
1936 | |
1937 if (fni_ != nullptr) { | |
1938 // This isn't necessary in the case that we are in fact parsing a getter | |
1939 // or setter, but it doesn't hurt. | |
1940 impl()->PushLiteralName(fni_, *name); | |
1941 } | |
1942 | |
1943 switch (token) { | |
1944 case Token::COLON: | |
1945 *kind = PropertyKind::kValueProperty; | |
1946 return factory()->NewStringLiteral(*name, pos); | |
1947 case Token::COMMA: | |
1948 case Token::RBRACE: | |
1949 case Token::ASSIGN: | |
1950 *kind = PropertyKind::kShorthandProperty; | |
1951 return factory()->NewStringLiteral(*name, pos); | |
1952 case Token::LPAREN: | |
1953 *kind = PropertyKind::kMethodProperty; | |
1954 return factory()->NewStringLiteral(*name, pos); | |
1955 default: | |
1956 break; // This must be an accessor. | |
Dan Ehrenberg
2016/08/27 00:09:00
Any way you can avoid the duplication between this
bakkot
2016/08/27 01:51:54
I've factored it out into a method. It's not a hug
| |
1957 } | |
1958 scanner()->IsGetOrSet(is_get, is_set); | |
1959 if (!*is_get && !*is_set) { // TODO(bakkot) have IsGetOrSet return a bool | |
1960 Token::Value next = Next(); | |
1961 ReportUnexpectedToken(next); | |
1962 *ok = false; | |
1963 return impl()->EmptyExpression(); | |
1964 } | |
1965 *kind = PropertyKind::kAccessorProperty; | |
1966 pos = peek_position(); | |
1967 } | |
1968 | |
1888 // For non computed property names we normalize the name a bit: | 1969 // For non computed property names we normalize the name a bit: |
1889 // | 1970 // |
1890 // "12" -> 12 | 1971 // "12" -> 12 |
1891 // 12.3 -> "12.3" | 1972 // 12.3 -> "12.3" |
1892 // 12.30 -> "12.3" | 1973 // 12.30 -> "12.3" |
1893 // identifier -> "identifier" | 1974 // identifier -> "identifier" |
1894 // | 1975 // |
1895 // This is important because we use the property name as a key in a hash | 1976 // This is important because we use the property name as a key in a hash |
1896 // table when we compute constant properties. | 1977 // table when we compute constant properties. |
1978 ExpressionT expression; | |
1897 switch (token) { | 1979 switch (token) { |
1898 case Token::STRING: | 1980 case Token::STRING: |
1899 Consume(Token::STRING); | 1981 Consume(Token::STRING); |
1900 *name = impl()->GetSymbol(); | 1982 *name = impl()->GetSymbol(); |
1901 break; | 1983 break; |
1902 | 1984 |
1903 case Token::SMI: | 1985 case Token::SMI: |
1904 Consume(Token::SMI); | 1986 Consume(Token::SMI); |
1905 *name = impl()->GetNumberAsSymbol(); | 1987 *name = impl()->GetNumberAsSymbol(); |
1906 break; | 1988 break; |
1907 | 1989 |
1908 case Token::NUMBER: | 1990 case Token::NUMBER: |
1909 Consume(Token::NUMBER); | 1991 Consume(Token::NUMBER); |
1910 *name = impl()->GetNumberAsSymbol(); | 1992 *name = impl()->GetNumberAsSymbol(); |
1911 break; | 1993 break; |
1912 | 1994 |
1913 case Token::LBRACK: { | 1995 case Token::LBRACK: { |
1996 *name = impl()->EmptyIdentifier(); | |
1914 *is_computed_name = true; | 1997 *is_computed_name = true; |
1915 Consume(Token::LBRACK); | 1998 Consume(Token::LBRACK); |
1916 ExpressionClassifier computed_name_classifier(this); | 1999 ExpressionClassifier computed_name_classifier(this); |
1917 ExpressionT expression = | 2000 expression = |
1918 ParseAssignmentExpression(true, &computed_name_classifier, CHECK_OK); | 2001 ParseAssignmentExpression(true, &computed_name_classifier, CHECK_OK); |
1919 impl()->RewriteNonPattern(&computed_name_classifier, CHECK_OK); | 2002 impl()->RewriteNonPattern(&computed_name_classifier, CHECK_OK); |
1920 classifier->AccumulateFormalParameterContainmentErrors( | 2003 classifier->AccumulateFormalParameterContainmentErrors( |
1921 &computed_name_classifier); | 2004 &computed_name_classifier); |
1922 Expect(Token::RBRACK, CHECK_OK); | 2005 Expect(Token::RBRACK, CHECK_OK); |
1923 return expression; | 2006 break; |
1924 } | 2007 } |
1925 | 2008 |
1926 default: | 2009 default: |
1927 *name = ParseIdentifierName(CHECK_OK); | 2010 *name = ParseIdentifierName(CHECK_OK); |
1928 scanner()->IsGetOrSet(is_get, is_set); | |
1929 break; | 2011 break; |
1930 } | 2012 } |
1931 | 2013 |
2014 if (peek() != Token::COLON && *kind == PropertyKind::kValueProperty) { | |
2015 switch (peek()) { | |
2016 case Token::COLON: | |
2017 UNREACHABLE(); | |
2018 break; | |
2019 case Token::COMMA: | |
2020 case Token::RBRACE: | |
2021 case Token::ASSIGN: | |
2022 if (!Token::IsIdentifier(token, language_mode(), this->is_generator(), | |
2023 parsing_module_ || is_async_function())) { | |
2024 Token::Value next = Next(); | |
2025 ReportUnexpectedToken(next); | |
2026 *ok = false; | |
2027 return impl()->EmptyExpression(); | |
2028 } | |
2029 *kind = PropertyKind::kShorthandProperty; | |
2030 break; | |
2031 case Token::LPAREN: | |
2032 *kind = PropertyKind::kMethodProperty; | |
2033 break; | |
2034 default: { | |
2035 Token::Value next = Next(); | |
2036 ReportUnexpectedToken(next); | |
2037 *ok = false; | |
2038 return impl()->EmptyExpression(); | |
2039 } | |
2040 } | |
2041 } | |
2042 | |
2043 if (*is_computed_name) { | |
2044 return expression; | |
2045 } | |
2046 | |
2047 if (fni_ != nullptr) { | |
2048 impl()->PushLiteralName(fni_, *name); | |
2049 } | |
2050 | |
1932 uint32_t index; | 2051 uint32_t index; |
1933 return impl()->IsArrayIndex(*name, &index) | 2052 return impl()->IsArrayIndex(*name, &index) |
1934 ? factory()->NewNumberLiteral(index, pos) | 2053 ? factory()->NewNumberLiteral(index, pos) |
1935 : factory()->NewStringLiteral(*name, pos); | 2054 : factory()->NewStringLiteral(*name, pos); |
1936 } | 2055 } |
1937 | 2056 |
1938 template <typename Impl> | 2057 template <typename Impl> |
1939 typename ParserBase<Impl>::ObjectLiteralPropertyT | 2058 typename ParserBase<Impl>::ObjectLiteralPropertyT |
1940 ParserBase<Impl>::ParsePropertyDefinition( | 2059 ParserBase<Impl>::ParsePropertyDefinition(ObjectLiteralCheckerBase* checker, |
1941 ObjectLiteralCheckerBase* checker, bool in_class, bool has_extends, | 2060 bool in_class, bool has_extends, |
1942 MethodKind method_kind, bool* is_computed_name, bool* has_seen_constructor, | 2061 bool* is_computed_name, |
1943 ExpressionClassifier* classifier, IdentifierT* name, bool* ok) { | 2062 bool* has_seen_constructor, |
1944 DCHECK(!in_class || IsStaticMethod(method_kind) || | 2063 ExpressionClassifier* classifier, |
1945 has_seen_constructor != nullptr); | 2064 IdentifierT* name, bool* ok) { |
2065 DCHECK(!in_class || has_seen_constructor != nullptr); | |
1946 bool is_get = false; | 2066 bool is_get = false; |
1947 bool is_set = false; | 2067 bool is_set = false; |
1948 bool is_generator = Check(Token::MUL); | 2068 bool is_generator = false; |
1949 bool is_async = false; | 2069 bool is_async = false; |
1950 const bool is_static = IsStaticMethod(method_kind); | 2070 bool is_static = false; |
2071 PropertyKind kind = PropertyKind::kValueProperty; | |
1951 | 2072 |
1952 Token::Value name_token = peek(); | 2073 Token::Value name_token = peek(); |
1953 | |
1954 if (is_generator) { | |
1955 method_kind |= MethodKind::kGenerator; | |
1956 } else if (allow_harmony_async_await() && name_token == Token::ASYNC && | |
1957 !scanner()->HasAnyLineTerminatorAfterNext() && | |
1958 PeekAhead() != Token::LPAREN && PeekAhead()) { | |
1959 is_async = true; | |
1960 } | |
1961 | |
1962 int next_beg_pos = scanner()->peek_location().beg_pos; | 2074 int next_beg_pos = scanner()->peek_location().beg_pos; |
1963 int next_end_pos = scanner()->peek_location().end_pos; | 2075 int next_end_pos = scanner()->peek_location().end_pos; |
2076 | |
1964 ExpressionT name_expression = | 2077 ExpressionT name_expression = |
1965 ParsePropertyName(name, &is_get, &is_set, is_computed_name, classifier, | 2078 ParsePropertyName(name, &kind, in_class, &is_generator, &is_get, &is_set, |
2079 &is_async, &is_static, is_computed_name, classifier, | |
1966 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 2080 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
1967 | 2081 |
1968 if (fni_ != nullptr && !*is_computed_name) { | 2082 switch (kind) { |
1969 impl()->PushLiteralName(fni_, *name); | 2083 case kValueProperty: { |
1970 } | 2084 if (in_class) { |
2085 Token::Value next = Next(); | |
2086 ReportUnexpectedToken(next); | |
2087 *ok = false; | |
2088 return impl()->EmptyObjectLiteralProperty(); | |
2089 } | |
1971 | 2090 |
1972 if (!in_class && !is_generator) { | 2091 DCHECK(!is_get && !is_set && !is_generator && !is_async && !is_static); |
1973 DCHECK(!IsStaticMethod(method_kind)); | 2092 |
1974 if (peek() == Token::COLON) { | |
1975 // PropertyDefinition | |
1976 // PropertyName ':' AssignmentExpression | |
1977 if (!*is_computed_name) { | 2093 if (!*is_computed_name) { |
1978 checker->CheckProperty(name_token, kValueProperty, MethodKind::kNormal, | 2094 checker->CheckProperty(name_token, kValueProperty, MethodKind::kNormal, |
1979 classifier, | 2095 classifier, |
1980 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 2096 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
1981 } | 2097 } |
1982 Consume(Token::COLON); | 2098 Consume(Token::COLON); |
1983 int beg_pos = peek_position(); | 2099 int beg_pos = peek_position(); |
1984 ExpressionT value = ParseAssignmentExpression( | 2100 ExpressionT value = ParseAssignmentExpression( |
1985 true, classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 2101 true, classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
1986 CheckDestructuringElement(value, classifier, beg_pos, | 2102 CheckDestructuringElement(value, classifier, beg_pos, |
1987 scanner()->location().end_pos); | 2103 scanner()->location().end_pos); |
1988 | 2104 |
1989 return factory()->NewObjectLiteralProperty(name_expression, value, | 2105 return factory()->NewObjectLiteralProperty(name_expression, value, |
1990 is_static, *is_computed_name); | 2106 is_static, *is_computed_name); |
1991 } | 2107 } |
1992 | 2108 |
1993 if (Token::IsIdentifier(name_token, language_mode(), this->is_generator(), | 2109 case kShorthandProperty: { |
1994 parsing_module_ || is_async_function()) && | |
1995 (peek() == Token::COMMA || peek() == Token::RBRACE || | |
1996 peek() == Token::ASSIGN)) { | |
1997 // PropertyDefinition | 2110 // PropertyDefinition |
1998 // IdentifierReference | 2111 // IdentifierReference |
1999 // CoverInitializedName | 2112 // CoverInitializedName |
2000 // | 2113 // |
2001 // CoverInitializedName | 2114 // CoverInitializedName |
2002 // IdentifierReference Initializer? | 2115 // IdentifierReference Initializer? |
2116 if (in_class) { | |
2117 Token::Value next = Next(); | |
2118 ReportUnexpectedToken(next); | |
2119 *ok = false; | |
2120 return impl()->EmptyObjectLiteralProperty(); | |
2121 } | |
2122 | |
2123 DCHECK(!is_get && !is_set && !is_generator && !is_async && !is_static && | |
2124 !*is_computed_name); | |
2125 | |
2003 if (classifier->duplicate_finder() != nullptr && | 2126 if (classifier->duplicate_finder() != nullptr && |
2004 scanner()->FindSymbol(classifier->duplicate_finder(), 1) != 0) { | 2127 scanner()->FindSymbol(classifier->duplicate_finder(), 1) != 0) { |
2005 classifier->RecordDuplicateFormalParameterError(scanner()->location()); | 2128 classifier->RecordDuplicateFormalParameterError(scanner()->location()); |
2006 } | 2129 } |
2007 | 2130 |
2008 if (impl()->IsEvalOrArguments(*name) && is_strict(language_mode())) { | 2131 if (impl()->IsEvalOrArguments(*name) && is_strict(language_mode())) { |
2009 classifier->RecordBindingPatternError( | 2132 classifier->RecordBindingPatternError( |
2010 scanner()->location(), MessageTemplate::kStrictEvalArguments); | 2133 scanner()->location(), MessageTemplate::kStrictEvalArguments); |
2011 } | 2134 } |
2012 | 2135 |
(...skipping 28 matching lines...) Expand all Loading... | |
2041 | 2164 |
2042 impl()->SetFunctionNameFromIdentifierRef(rhs, lhs); | 2165 impl()->SetFunctionNameFromIdentifierRef(rhs, lhs); |
2043 } else { | 2166 } else { |
2044 value = lhs; | 2167 value = lhs; |
2045 } | 2168 } |
2046 | 2169 |
2047 return factory()->NewObjectLiteralProperty( | 2170 return factory()->NewObjectLiteralProperty( |
2048 name_expression, value, ObjectLiteralProperty::COMPUTED, is_static, | 2171 name_expression, value, ObjectLiteralProperty::COMPUTED, is_static, |
2049 false); | 2172 false); |
2050 } | 2173 } |
2051 } | |
2052 | 2174 |
2053 // Method definitions are never valid in patterns. | 2175 case kMethodProperty: { |
2054 classifier->RecordPatternError( | 2176 DCHECK(!is_get && !is_set); |
2055 Scanner::Location(next_beg_pos, scanner()->location().end_pos), | |
2056 MessageTemplate::kInvalidDestructuringTarget); | |
2057 | 2177 |
2058 if (is_async && !IsSpecialMethod(method_kind)) { | 2178 MethodKind method_kind = MethodKind::kNormal; |
2059 DCHECK(!is_get); | 2179 if (is_generator) { |
2060 DCHECK(!is_set); | 2180 method_kind |= MethodKind::kGenerator; |
2061 bool dont_care; | 2181 } |
2062 name_expression = ParsePropertyName( | 2182 if (is_async) { |
2063 name, &dont_care, &dont_care, is_computed_name, classifier, | 2183 method_kind |= MethodKind::kAsync; |
2064 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 2184 } |
2065 method_kind |= MethodKind::kAsync; | 2185 if (is_static) { |
2066 } | 2186 method_kind |= MethodKind::kStatic; |
2187 } | |
2067 | 2188 |
2068 if (is_generator || peek() == Token::LPAREN) { | 2189 // MethodDefinition |
2069 // MethodDefinition | 2190 // PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}' |
2070 // PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}' | 2191 // '*' PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}' |
2071 // '*' PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}' | 2192 |
2072 if (!*is_computed_name) { | 2193 classifier->RecordPatternError( |
2073 checker->CheckProperty(name_token, kMethodProperty, method_kind, | 2194 Scanner::Location(next_beg_pos, scanner()->location().end_pos), |
2074 classifier, | 2195 MessageTemplate::kInvalidDestructuringTarget); |
2075 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 2196 |
2197 if (!*is_computed_name) { | |
2198 checker->CheckProperty(name_token, kMethodProperty, method_kind, | |
2199 classifier, | |
2200 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
2201 } | |
2202 | |
2203 FunctionKind kind = is_generator | |
2204 ? FunctionKind::kConciseGeneratorMethod | |
2205 : is_async ? FunctionKind::kAsyncConciseMethod | |
2206 : FunctionKind::kConciseMethod; | |
2207 | |
2208 if (in_class && !is_static && impl()->IsConstructor(*name)) { | |
2209 *has_seen_constructor = true; | |
2210 kind = has_extends ? FunctionKind::kSubclassConstructor | |
2211 : FunctionKind::kBaseConstructor; | |
2212 } | |
2213 | |
2214 ExpressionT value = impl()->ParseFunctionLiteral( | |
2215 *name, scanner()->location(), kSkipFunctionNameCheck, kind, | |
2216 kNoSourcePosition, FunctionLiteral::kAccessorOrMethod, | |
2217 language_mode(), CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
2218 | |
2219 return factory()->NewObjectLiteralProperty( | |
2220 name_expression, value, ObjectLiteralProperty::COMPUTED, is_static, | |
2221 *is_computed_name); | |
2076 } | 2222 } |
2077 | 2223 |
2078 FunctionKind kind = is_generator | 2224 case kAccessorProperty: { |
2079 ? FunctionKind::kConciseGeneratorMethod | 2225 DCHECK((is_get || is_set) && !is_generator && !is_async); |
2080 : is_async ? FunctionKind::kAsyncConciseMethod | |
2081 : FunctionKind::kConciseMethod; | |
2082 | 2226 |
2083 if (in_class && !IsStaticMethod(method_kind) && | 2227 MethodKind method_kind = MethodKind::kNormal; |
2084 impl()->IsConstructor(*name)) { | 2228 if (is_static) { |
2085 *has_seen_constructor = true; | 2229 DCHECK(in_class); |
2086 kind = has_extends ? FunctionKind::kSubclassConstructor | 2230 method_kind |= MethodKind::kStatic; |
2087 : FunctionKind::kBaseConstructor; | 2231 } |
2232 | |
2233 classifier->RecordPatternError( | |
2234 Scanner::Location(next_beg_pos, scanner()->location().end_pos), | |
2235 MessageTemplate::kInvalidDestructuringTarget); | |
2236 if (!*is_computed_name) { | |
2237 checker->CheckProperty(name_token, kAccessorProperty, method_kind, | |
2238 classifier, | |
2239 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
2240 } | |
2241 | |
2242 typename Traits::Type::FunctionLiteral value = | |
2243 impl()->ParseFunctionLiteral( | |
2244 *name, scanner()->location(), kSkipFunctionNameCheck, | |
2245 is_get ? FunctionKind::kGetterFunction | |
2246 : FunctionKind::kSetterFunction, | |
2247 kNoSourcePosition, FunctionLiteral::kAccessorOrMethod, | |
2248 language_mode(), CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
2249 | |
2250 // Make sure the name expression is a string since we need a Name for | |
2251 // Runtime_DefineAccessorPropertyUnchecked and since we can determine this | |
2252 // statically we can skip the extra runtime check. | |
2253 if (!*is_computed_name) { | |
2254 name_expression = | |
2255 factory()->NewStringLiteral(*name, name_expression->position()); | |
2256 } | |
2257 | |
2258 return factory()->NewObjectLiteralProperty( | |
2259 name_expression, value, is_get ? ObjectLiteralProperty::GETTER | |
2260 : ObjectLiteralProperty::SETTER, | |
2261 is_static, *is_computed_name); | |
2088 } | 2262 } |
2089 | |
2090 ExpressionT value = impl()->ParseFunctionLiteral( | |
2091 *name, scanner()->location(), kSkipFunctionNameCheck, kind, | |
2092 kNoSourcePosition, FunctionLiteral::kAccessorOrMethod, language_mode(), | |
2093 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
2094 | |
2095 return factory()->NewObjectLiteralProperty(name_expression, value, | |
2096 ObjectLiteralProperty::COMPUTED, | |
2097 is_static, *is_computed_name); | |
2098 } | 2263 } |
2099 | 2264 UNREACHABLE(); |
2100 if (in_class && name_token == Token::STATIC && IsNormalMethod(method_kind)) { | |
2101 // ClassElement (static) | |
2102 // 'static' MethodDefinition | |
2103 *name = impl()->EmptyIdentifier(); | |
2104 ObjectLiteralPropertyT property = ParsePropertyDefinition( | |
2105 checker, true, has_extends, MethodKind::kStatic, is_computed_name, | |
2106 nullptr, classifier, name, ok); | |
2107 impl()->RewriteNonPattern(classifier, ok); | |
2108 return property; | |
2109 } | |
2110 | |
2111 if (is_get || is_set) { | |
2112 // MethodDefinition (Accessors) | |
2113 // get PropertyName '(' ')' '{' FunctionBody '}' | |
2114 // set PropertyName '(' PropertySetParameterList ')' '{' FunctionBody '}' | |
2115 *name = impl()->EmptyIdentifier(); | |
2116 bool dont_care = false; | |
2117 name_token = peek(); | |
2118 | |
2119 name_expression = ParsePropertyName( | |
2120 name, &dont_care, &dont_care, is_computed_name, classifier, | |
2121 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
2122 | |
2123 if (!*is_computed_name) { | |
2124 checker->CheckProperty(name_token, kAccessorProperty, method_kind, | |
2125 classifier, | |
2126 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
2127 } | |
2128 | |
2129 typename Traits::Type::FunctionLiteral value = impl()->ParseFunctionLiteral( | |
2130 *name, scanner()->location(), kSkipFunctionNameCheck, | |
2131 is_get ? FunctionKind::kGetterFunction : FunctionKind::kSetterFunction, | |
2132 kNoSourcePosition, FunctionLiteral::kAccessorOrMethod, language_mode(), | |
2133 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
2134 | |
2135 // Make sure the name expression is a string since we need a Name for | |
2136 // Runtime_DefineAccessorPropertyUnchecked and since we can determine this | |
2137 // statically we can skip the extra runtime check. | |
2138 if (!*is_computed_name) { | |
2139 name_expression = | |
2140 factory()->NewStringLiteral(*name, name_expression->position()); | |
2141 } | |
2142 | |
2143 return factory()->NewObjectLiteralProperty( | |
2144 name_expression, value, | |
2145 is_get ? ObjectLiteralProperty::GETTER : ObjectLiteralProperty::SETTER, | |
2146 is_static, *is_computed_name); | |
2147 } | |
2148 | |
2149 Token::Value next = Next(); | |
2150 ReportUnexpectedToken(next); | |
2151 *ok = false; | |
2152 return impl()->EmptyObjectLiteralProperty(); | 2265 return impl()->EmptyObjectLiteralProperty(); |
Dan Ehrenberg
2016/08/27 00:09:00
Does the compiler require you to keep this stateme
bakkot
2016/08/27 01:51:54
Unfortunately yes, at least on some platforms. I i
| |
2153 } | 2266 } |
2154 | 2267 |
2155 template <typename Impl> | 2268 template <typename Impl> |
2156 typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseObjectLiteral( | 2269 typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseObjectLiteral( |
2157 ExpressionClassifier* classifier, bool* ok) { | 2270 ExpressionClassifier* classifier, bool* ok) { |
2158 // ObjectLiteral :: | 2271 // ObjectLiteral :: |
2159 // '{' (PropertyDefinition (',' PropertyDefinition)* ','? )? '}' | 2272 // '{' (PropertyDefinition (',' PropertyDefinition)* ','? )? '}' |
2160 | 2273 |
2161 int pos = peek_position(); | 2274 int pos = peek_position(); |
2162 typename Traits::Type::PropertyList properties = impl()->NewPropertyList(4); | 2275 typename Traits::Type::PropertyList properties = impl()->NewPropertyList(4); |
2163 int number_of_boilerplate_properties = 0; | 2276 int number_of_boilerplate_properties = 0; |
2164 bool has_computed_names = false; | 2277 bool has_computed_names = false; |
2165 ObjectLiteralChecker checker(this); | 2278 ObjectLiteralChecker checker(this); |
2166 | 2279 |
2167 Expect(Token::LBRACE, CHECK_OK); | 2280 Expect(Token::LBRACE, CHECK_OK); |
2168 | 2281 |
2169 while (peek() != Token::RBRACE) { | 2282 while (peek() != Token::RBRACE) { |
2170 FuncNameInferrer::State fni_state(fni_); | 2283 FuncNameInferrer::State fni_state(fni_); |
2171 | 2284 |
2172 const bool in_class = false; | 2285 const bool in_class = false; |
2173 const bool has_extends = false; | 2286 const bool has_extends = false; |
2174 bool is_computed_name = false; | 2287 bool is_computed_name = false; |
2175 IdentifierT name = impl()->EmptyIdentifier(); | 2288 IdentifierT name = impl()->EmptyIdentifier(); |
2176 ObjectLiteralPropertyT property = ParsePropertyDefinition( | 2289 ObjectLiteralPropertyT property = ParsePropertyDefinition( |
2177 &checker, in_class, has_extends, MethodKind::kNormal, &is_computed_name, | 2290 &checker, in_class, has_extends, &is_computed_name, nullptr, classifier, |
2178 NULL, classifier, &name, CHECK_OK); | 2291 &name, CHECK_OK); |
2179 | 2292 |
2180 if (is_computed_name) { | 2293 if (is_computed_name) { |
2181 has_computed_names = true; | 2294 has_computed_names = true; |
2182 } | 2295 } |
2183 | 2296 |
2184 // Count CONSTANT or COMPUTED properties to maintain the enumeration order. | 2297 // Count CONSTANT or COMPUTED properties to maintain the enumeration order. |
2185 if (!has_computed_names && impl()->IsBoilerplateProperty(property)) { | 2298 if (!has_computed_names && impl()->IsBoilerplateProperty(property)) { |
2186 number_of_boilerplate_properties++; | 2299 number_of_boilerplate_properties++; |
2187 } | 2300 } |
2188 properties->Add(property, zone()); | 2301 properties->Add(property, zone()); |
(...skipping 1521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3710 has_seen_constructor_ = true; | 3823 has_seen_constructor_ = true; |
3711 return; | 3824 return; |
3712 } | 3825 } |
3713 } | 3826 } |
3714 | 3827 |
3715 | 3828 |
3716 } // namespace internal | 3829 } // namespace internal |
3717 } // namespace v8 | 3830 } // namespace v8 |
3718 | 3831 |
3719 #endif // V8_PARSING_PARSER_BASE_H | 3832 #endif // V8_PARSING_PARSER_BASE_H |
OLD | NEW |