| 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 12 matching lines...) Expand all Loading... |
| 23 kFunctionNameIsStrictReserved, | 23 kFunctionNameIsStrictReserved, |
| 24 kSkipFunctionNameCheck, | 24 kSkipFunctionNameCheck, |
| 25 kFunctionNameValidityUnknown | 25 kFunctionNameValidityUnknown |
| 26 }; | 26 }; |
| 27 | 27 |
| 28 enum AllowLabelledFunctionStatement { | 28 enum AllowLabelledFunctionStatement { |
| 29 kAllowLabelledFunctionStatement, | 29 kAllowLabelledFunctionStatement, |
| 30 kDisallowLabelledFunctionStatement, | 30 kDisallowLabelledFunctionStatement, |
| 31 }; | 31 }; |
| 32 | 32 |
| 33 enum class FunctionBody { Normal, SingleExpression }; | |
| 34 | |
| 35 enum class ParseFunctionFlags { | 33 enum class ParseFunctionFlags { |
| 36 kIsNormal = 0, | 34 kIsNormal = 0, |
| 37 kIsGenerator = 1, | 35 kIsGenerator = 1, |
| 38 kIsAsync = 2, | 36 kIsAsync = 2, |
| 39 kIsDefault = 4 | 37 kIsDefault = 4 |
| 40 }; | 38 }; |
| 41 | 39 |
| 42 static inline ParseFunctionFlags operator|(ParseFunctionFlags lhs, | 40 static inline ParseFunctionFlags operator|(ParseFunctionFlags lhs, |
| 43 ParseFunctionFlags rhs) { | 41 ParseFunctionFlags rhs) { |
| 44 typedef unsigned char T; | 42 typedef unsigned char T; |
| 45 return static_cast<ParseFunctionFlags>(static_cast<T>(lhs) | | 43 return static_cast<ParseFunctionFlags>(static_cast<T>(lhs) | |
| 46 static_cast<T>(rhs)); | 44 static_cast<T>(rhs)); |
| 47 } | 45 } |
| 48 | 46 |
| 49 static inline ParseFunctionFlags& operator|=(ParseFunctionFlags& lhs, | 47 static inline ParseFunctionFlags& operator|=(ParseFunctionFlags& lhs, |
| 50 const ParseFunctionFlags& rhs) { | 48 const ParseFunctionFlags& rhs) { |
| 51 lhs = lhs | rhs; | 49 lhs = lhs | rhs; |
| 52 return lhs; | 50 return lhs; |
| 53 } | 51 } |
| 54 | 52 |
| 55 static inline bool operator&(ParseFunctionFlags bitfield, | 53 static inline bool operator&(ParseFunctionFlags bitfield, |
| 56 ParseFunctionFlags mask) { | 54 ParseFunctionFlags mask) { |
| 57 typedef unsigned char T; | 55 typedef unsigned char T; |
| 58 return static_cast<T>(bitfield) & static_cast<T>(mask); | 56 return static_cast<T>(bitfield) & static_cast<T>(mask); |
| 59 } | 57 } |
| 60 | 58 |
| 61 enum class MethodKind { | 59 enum class MethodKind { |
| 62 Normal = 0, | 60 kNormal = 0, |
| 63 Static = 1 << 0, | 61 kStatic = 1 << 0, |
| 64 Generator = 1 << 1, | 62 kGenerator = 1 << 1, |
| 65 StaticGenerator = Static | Generator, | 63 kStaticGenerator = kStatic | kGenerator, |
| 66 Async = 1 << 2, | 64 kAsync = 1 << 2, |
| 67 StaticAsync = Static | Async, | 65 kStaticAsync = kStatic | kAsync, |
| 68 | 66 |
| 69 /* Any non-ordinary method kinds */ | 67 /* Any non-ordinary method kinds */ |
| 70 SpecialMask = Generator | Async | 68 kSpecialMask = kGenerator | kAsync |
| 71 }; | 69 }; |
| 72 | 70 |
| 73 inline bool IsValidMethodKind(MethodKind kind) { | 71 inline bool IsValidMethodKind(MethodKind kind) { |
| 74 return kind == MethodKind::Normal || kind == MethodKind::Static || | 72 return kind == MethodKind::kNormal || kind == MethodKind::kStatic || |
| 75 kind == MethodKind::Generator || kind == MethodKind::StaticGenerator || | 73 kind == MethodKind::kGenerator || |
| 76 kind == MethodKind::Async || kind == MethodKind::StaticAsync; | 74 kind == MethodKind::kStaticGenerator || kind == MethodKind::kAsync || |
| 75 kind == MethodKind::kStaticAsync; |
| 77 } | 76 } |
| 78 | 77 |
| 79 static inline MethodKind operator|(MethodKind lhs, MethodKind rhs) { | 78 static inline MethodKind operator|(MethodKind lhs, MethodKind rhs) { |
| 80 typedef unsigned char T; | 79 typedef unsigned char T; |
| 81 return static_cast<MethodKind>(static_cast<T>(lhs) | static_cast<T>(rhs)); | 80 return static_cast<MethodKind>(static_cast<T>(lhs) | static_cast<T>(rhs)); |
| 82 } | 81 } |
| 83 | 82 |
| 84 static inline MethodKind& operator|=(MethodKind& lhs, const MethodKind& rhs) { | 83 static inline MethodKind& operator|=(MethodKind& lhs, const MethodKind& rhs) { |
| 85 lhs = lhs | rhs; | 84 lhs = lhs | rhs; |
| 86 DCHECK(IsValidMethodKind(lhs)); | 85 DCHECK(IsValidMethodKind(lhs)); |
| 87 return lhs; | 86 return lhs; |
| 88 } | 87 } |
| 89 | 88 |
| 90 static inline bool operator&(MethodKind bitfield, MethodKind mask) { | 89 static inline bool operator&(MethodKind bitfield, MethodKind mask) { |
| 91 typedef unsigned char T; | 90 typedef unsigned char T; |
| 92 return static_cast<T>(bitfield) & static_cast<T>(mask); | 91 return static_cast<T>(bitfield) & static_cast<T>(mask); |
| 93 } | 92 } |
| 94 | 93 |
| 95 inline bool IsNormalMethod(MethodKind kind) { | 94 inline bool IsNormalMethod(MethodKind kind) { |
| 96 return kind == MethodKind::Normal; | 95 return kind == MethodKind::kNormal; |
| 97 } | 96 } |
| 98 | 97 |
| 99 inline bool IsSpecialMethod(MethodKind kind) { | 98 inline bool IsSpecialMethod(MethodKind kind) { |
| 100 return kind & MethodKind::SpecialMask; | 99 return kind & MethodKind::kSpecialMask; |
| 101 } | 100 } |
| 102 | 101 |
| 103 inline bool IsStaticMethod(MethodKind kind) { | 102 inline bool IsStaticMethod(MethodKind kind) { |
| 104 return kind & MethodKind::Static; | 103 return kind & MethodKind::kStatic; |
| 105 } | 104 } |
| 106 | 105 |
| 107 inline bool IsGeneratorMethod(MethodKind kind) { | 106 inline bool IsGeneratorMethod(MethodKind kind) { |
| 108 return kind & MethodKind::Generator; | 107 return kind & MethodKind::kGenerator; |
| 109 } | 108 } |
| 110 | 109 |
| 111 inline bool IsAsyncMethod(MethodKind kind) { return kind & MethodKind::Async; } | 110 inline bool IsAsyncMethod(MethodKind kind) { return kind & MethodKind::kAsync; } |
| 112 | 111 |
| 113 struct FormalParametersBase { | 112 struct FormalParametersBase { |
| 114 explicit FormalParametersBase(DeclarationScope* scope) : scope(scope) {} | 113 explicit FormalParametersBase(DeclarationScope* scope) : scope(scope) {} |
| 115 DeclarationScope* scope; | 114 DeclarationScope* scope; |
| 116 bool has_rest = false; | 115 bool has_rest = false; |
| 117 bool is_simple = true; | 116 bool is_simple = true; |
| 118 int materialized_literals_count = 0; | 117 int materialized_literals_count = 0; |
| 119 }; | 118 }; |
| 120 | 119 |
| 121 | 120 |
| (...skipping 1813 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1935 bool is_get = false; | 1934 bool is_get = false; |
| 1936 bool is_set = false; | 1935 bool is_set = false; |
| 1937 bool is_await = false; | 1936 bool is_await = false; |
| 1938 bool is_generator = Check(Token::MUL); | 1937 bool is_generator = Check(Token::MUL); |
| 1939 bool is_async = false; | 1938 bool is_async = false; |
| 1940 const bool is_static = IsStaticMethod(method_kind); | 1939 const bool is_static = IsStaticMethod(method_kind); |
| 1941 | 1940 |
| 1942 Token::Value name_token = peek(); | 1941 Token::Value name_token = peek(); |
| 1943 | 1942 |
| 1944 if (is_generator) { | 1943 if (is_generator) { |
| 1945 method_kind |= MethodKind::Generator; | 1944 method_kind |= MethodKind::kGenerator; |
| 1946 } else if (allow_harmony_async_await() && name_token == Token::ASYNC && | 1945 } else if (allow_harmony_async_await() && name_token == Token::ASYNC && |
| 1947 !scanner()->HasAnyLineTerminatorAfterNext() && | 1946 !scanner()->HasAnyLineTerminatorAfterNext() && |
| 1948 PeekAhead() != Token::LPAREN && PeekAhead()) { | 1947 PeekAhead() != Token::LPAREN && PeekAhead()) { |
| 1949 is_async = true; | 1948 is_async = true; |
| 1950 } | 1949 } |
| 1951 | 1950 |
| 1952 int next_beg_pos = scanner()->peek_location().beg_pos; | 1951 int next_beg_pos = scanner()->peek_location().beg_pos; |
| 1953 int next_end_pos = scanner()->peek_location().end_pos; | 1952 int next_end_pos = scanner()->peek_location().end_pos; |
| 1954 ExpressionT name_expression = ParsePropertyName( | 1953 ExpressionT name_expression = ParsePropertyName( |
| 1955 name, &is_get, &is_set, &is_await, is_computed_name, classifier, | 1954 name, &is_get, &is_set, &is_await, is_computed_name, classifier, |
| 1956 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 1955 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| 1957 | 1956 |
| 1958 if (fni_ != nullptr && !*is_computed_name) { | 1957 if (fni_ != nullptr && !*is_computed_name) { |
| 1959 this->PushLiteralName(fni_, *name); | 1958 this->PushLiteralName(fni_, *name); |
| 1960 } | 1959 } |
| 1961 | 1960 |
| 1962 if (!in_class && !is_generator) { | 1961 if (!in_class && !is_generator) { |
| 1963 DCHECK(!IsStaticMethod(method_kind)); | 1962 DCHECK(!IsStaticMethod(method_kind)); |
| 1964 | 1963 |
| 1965 if (peek() == Token::COLON) { | 1964 if (peek() == Token::COLON) { |
| 1966 // PropertyDefinition | 1965 // PropertyDefinition |
| 1967 // PropertyName ':' AssignmentExpression | 1966 // PropertyName ':' AssignmentExpression |
| 1968 if (!*is_computed_name) { | 1967 if (!*is_computed_name) { |
| 1969 checker->CheckProperty(name_token, kValueProperty, MethodKind::Normal, | 1968 checker->CheckProperty(name_token, kValueProperty, MethodKind::kNormal, |
| 1970 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 1969 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| 1971 } | 1970 } |
| 1972 Consume(Token::COLON); | 1971 Consume(Token::COLON); |
| 1973 int beg_pos = peek_position(); | 1972 int beg_pos = peek_position(); |
| 1974 ExpressionT value = this->ParseAssignmentExpression( | 1973 ExpressionT value = this->ParseAssignmentExpression( |
| 1975 true, classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 1974 true, classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| 1976 CheckDestructuringElement(value, classifier, beg_pos, | 1975 CheckDestructuringElement(value, classifier, beg_pos, |
| 1977 scanner()->location().end_pos); | 1976 scanner()->location().end_pos); |
| 1978 | 1977 |
| 1979 return factory()->NewObjectLiteralProperty(name_expression, value, | 1978 return factory()->NewObjectLiteralProperty(name_expression, value, |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2045 Scanner::Location(next_beg_pos, scanner()->location().end_pos), | 2044 Scanner::Location(next_beg_pos, scanner()->location().end_pos), |
| 2046 MessageTemplate::kInvalidDestructuringTarget); | 2045 MessageTemplate::kInvalidDestructuringTarget); |
| 2047 | 2046 |
| 2048 if (is_async && !IsSpecialMethod(method_kind)) { | 2047 if (is_async && !IsSpecialMethod(method_kind)) { |
| 2049 DCHECK(!is_get); | 2048 DCHECK(!is_get); |
| 2050 DCHECK(!is_set); | 2049 DCHECK(!is_set); |
| 2051 bool dont_care; | 2050 bool dont_care; |
| 2052 name_expression = ParsePropertyName( | 2051 name_expression = ParsePropertyName( |
| 2053 name, &dont_care, &dont_care, &dont_care, is_computed_name, classifier, | 2052 name, &dont_care, &dont_care, &dont_care, is_computed_name, classifier, |
| 2054 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 2053 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| 2055 method_kind |= MethodKind::Async; | 2054 method_kind |= MethodKind::kAsync; |
| 2056 } | 2055 } |
| 2057 | 2056 |
| 2058 if (is_generator || peek() == Token::LPAREN) { | 2057 if (is_generator || peek() == Token::LPAREN) { |
| 2059 // MethodDefinition | 2058 // MethodDefinition |
| 2060 // PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}' | 2059 // PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}' |
| 2061 // '*' PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}' | 2060 // '*' PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}' |
| 2062 if (!*is_computed_name) { | 2061 if (!*is_computed_name) { |
| 2063 checker->CheckProperty(name_token, kMethodProperty, method_kind, | 2062 checker->CheckProperty(name_token, kMethodProperty, method_kind, |
| 2064 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 2063 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| 2065 } | 2064 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 2084 return factory()->NewObjectLiteralProperty(name_expression, value, | 2083 return factory()->NewObjectLiteralProperty(name_expression, value, |
| 2085 ObjectLiteralProperty::COMPUTED, | 2084 ObjectLiteralProperty::COMPUTED, |
| 2086 is_static, *is_computed_name); | 2085 is_static, *is_computed_name); |
| 2087 } | 2086 } |
| 2088 | 2087 |
| 2089 if (in_class && name_token == Token::STATIC && IsNormalMethod(method_kind)) { | 2088 if (in_class && name_token == Token::STATIC && IsNormalMethod(method_kind)) { |
| 2090 // ClassElement (static) | 2089 // ClassElement (static) |
| 2091 // 'static' MethodDefinition | 2090 // 'static' MethodDefinition |
| 2092 *name = this->EmptyIdentifier(); | 2091 *name = this->EmptyIdentifier(); |
| 2093 ObjectLiteralPropertyT property = ParsePropertyDefinition( | 2092 ObjectLiteralPropertyT property = ParsePropertyDefinition( |
| 2094 checker, true, has_extends, MethodKind::Static, is_computed_name, | 2093 checker, true, has_extends, MethodKind::kStatic, is_computed_name, |
| 2095 nullptr, classifier, name, ok); | 2094 nullptr, classifier, name, ok); |
| 2096 Traits::RewriteNonPattern(classifier, ok); | 2095 Traits::RewriteNonPattern(classifier, ok); |
| 2097 return property; | 2096 return property; |
| 2098 } | 2097 } |
| 2099 | 2098 |
| 2100 if (is_get || is_set) { | 2099 if (is_get || is_set) { |
| 2101 // MethodDefinition (Accessors) | 2100 // MethodDefinition (Accessors) |
| 2102 // get PropertyName '(' ')' '{' FunctionBody '}' | 2101 // get PropertyName '(' ')' '{' FunctionBody '}' |
| 2103 // set PropertyName '(' PropertySetParameterList ')' '{' FunctionBody '}' | 2102 // set PropertyName '(' PropertySetParameterList ')' '{' FunctionBody '}' |
| 2104 *name = this->EmptyIdentifier(); | 2103 *name = this->EmptyIdentifier(); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2157 Expect(Token::LBRACE, CHECK_OK); | 2156 Expect(Token::LBRACE, CHECK_OK); |
| 2158 | 2157 |
| 2159 while (peek() != Token::RBRACE) { | 2158 while (peek() != Token::RBRACE) { |
| 2160 FuncNameInferrer::State fni_state(fni_); | 2159 FuncNameInferrer::State fni_state(fni_); |
| 2161 | 2160 |
| 2162 const bool in_class = false; | 2161 const bool in_class = false; |
| 2163 const bool has_extends = false; | 2162 const bool has_extends = false; |
| 2164 bool is_computed_name = false; | 2163 bool is_computed_name = false; |
| 2165 IdentifierT name = this->EmptyIdentifier(); | 2164 IdentifierT name = this->EmptyIdentifier(); |
| 2166 ObjectLiteralPropertyT property = this->ParsePropertyDefinition( | 2165 ObjectLiteralPropertyT property = this->ParsePropertyDefinition( |
| 2167 &checker, in_class, has_extends, MethodKind::Normal, &is_computed_name, | 2166 &checker, in_class, has_extends, MethodKind::kNormal, &is_computed_name, |
| 2168 NULL, classifier, &name, CHECK_OK); | 2167 NULL, classifier, &name, CHECK_OK); |
| 2169 | 2168 |
| 2170 if (is_computed_name) { | 2169 if (is_computed_name) { |
| 2171 has_computed_names = true; | 2170 has_computed_names = true; |
| 2172 } | 2171 } |
| 2173 | 2172 |
| 2174 // Count CONSTANT or COMPUTED properties to maintain the enumeration order. | 2173 // Count CONSTANT or COMPUTED properties to maintain the enumeration order. |
| 2175 if (!has_computed_names && this->IsBoilerplateProperty(property)) { | 2174 if (!has_computed_names && this->IsBoilerplateProperty(property)) { |
| 2176 number_of_boilerplate_properties++; | 2175 number_of_boilerplate_properties++; |
| 2177 } | 2176 } |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2323 expression = this->ParseConditionalExpression( | 2322 expression = this->ParseConditionalExpression( |
| 2324 accept_IN, &arrow_formals_classifier, CHECK_OK); | 2323 accept_IN, &arrow_formals_classifier, CHECK_OK); |
| 2325 } | 2324 } |
| 2326 | 2325 |
| 2327 if (is_async && this->IsIdentifier(expression) && peek_any_identifier() && | 2326 if (is_async && this->IsIdentifier(expression) && peek_any_identifier() && |
| 2328 PeekAhead() == Token::ARROW) { | 2327 PeekAhead() == Token::ARROW) { |
| 2329 // async Identifier => AsyncConciseBody | 2328 // async Identifier => AsyncConciseBody |
| 2330 IdentifierT name = | 2329 IdentifierT name = |
| 2331 ParseAndClassifyIdentifier(&arrow_formals_classifier, CHECK_OK); | 2330 ParseAndClassifyIdentifier(&arrow_formals_classifier, CHECK_OK); |
| 2332 expression = this->ExpressionFromIdentifier( | 2331 expression = this->ExpressionFromIdentifier( |
| 2333 name, position(), scanner()->location().end_pos, InferName::No); | 2332 name, position(), scanner()->location().end_pos, InferName::kNo); |
| 2334 if (fni_) { | 2333 if (fni_) { |
| 2335 // Remove `async` keyword from inferred name stack. | 2334 // Remove `async` keyword from inferred name stack. |
| 2336 fni_->RemoveAsyncKeywordFromEnd(); | 2335 fni_->RemoveAsyncKeywordFromEnd(); |
| 2337 } | 2336 } |
| 2338 } | 2337 } |
| 2339 | 2338 |
| 2340 if (peek() == Token::ARROW) { | 2339 if (peek() == Token::ARROW) { |
| 2341 Scanner::Location arrow_loc = scanner()->peek_location(); | 2340 Scanner::Location arrow_loc = scanner()->peek_location(); |
| 2342 ValidateArrowFormalParameters(&arrow_formals_classifier, expression, | 2341 ValidateArrowFormalParameters(&arrow_formals_classifier, expression, |
| 2343 parenthesized_formals, is_async, CHECK_OK); | 2342 parenthesized_formals, is_async, CHECK_OK); |
| (...skipping 1390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3734 has_seen_constructor_ = true; | 3733 has_seen_constructor_ = true; |
| 3735 return; | 3734 return; |
| 3736 } | 3735 } |
| 3737 } | 3736 } |
| 3738 | 3737 |
| 3739 | 3738 |
| 3740 } // namespace internal | 3739 } // namespace internal |
| 3741 } // namespace v8 | 3740 } // namespace v8 |
| 3742 | 3741 |
| 3743 #endif // V8_PARSING_PARSER_BASE_H | 3742 #endif // V8_PARSING_PARSER_BASE_H |
| OLD | NEW |