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

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

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

Powered by Google App Engine
This is Rietveld 408576698