Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(54)

Side by Side Diff: src/parsing/parser-base.h

Issue 2278153004: Refactor object/class literal property name parsing (Closed)
Patch Set: make compilers happy Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/parsing/parser.cc ('k') | src/parsing/preparser.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/parsing/parser.cc ('k') | src/parsing/preparser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698