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 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 |