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 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
179 // // not related to pure parsing. | 179 // // not related to pure parsing. |
180 // typedef GeneratorVariable; | 180 // typedef GeneratorVariable; |
181 // // Return types for traversing functions. | 181 // // Return types for traversing functions. |
182 // typedef Identifier; | 182 // typedef Identifier; |
183 // typedef Expression; | 183 // typedef Expression; |
184 // typedef FunctionLiteral; | 184 // typedef FunctionLiteral; |
185 // typedef ObjectLiteralProperty; | 185 // typedef ObjectLiteralProperty; |
186 // typedef ExpressionList; | 186 // typedef ExpressionList; |
187 // typedef PropertyList; | 187 // typedef PropertyList; |
188 // typedef FormalParameters; | 188 // typedef FormalParameters; |
189 // typedef Statement; | |
189 // typedef StatementList; | 190 // typedef StatementList; |
190 // typedef Block; | 191 // typedef Block; |
191 // // For constructing objects returned by the traversing functions. | 192 // // For constructing objects returned by the traversing functions. |
192 // typedef Factory; | 193 // typedef Factory; |
194 // // For other implementation-specific tasks. | |
195 // typedef Target; | |
196 // typedef TargetScope; | |
193 // }; | 197 // }; |
194 | 198 |
195 template <typename Impl> | 199 template <typename Impl> |
196 struct ParserTypes; | 200 struct ParserTypes; |
197 | 201 |
198 template <typename Impl> | 202 template <typename Impl> |
199 class ParserBase { | 203 class ParserBase { |
200 public: | 204 public: |
201 // Shorten type names defined by ParserTypes<Impl>. | 205 // Shorten type names defined by ParserTypes<Impl>. |
202 typedef ParserTypes<Impl> Types; | 206 typedef ParserTypes<Impl> Types; |
203 typedef typename Types::Identifier IdentifierT; | 207 typedef typename Types::Identifier IdentifierT; |
204 typedef typename Types::Expression ExpressionT; | 208 typedef typename Types::Expression ExpressionT; |
205 typedef typename Types::FunctionLiteral FunctionLiteralT; | 209 typedef typename Types::FunctionLiteral FunctionLiteralT; |
206 typedef typename Types::ObjectLiteralProperty ObjectLiteralPropertyT; | 210 typedef typename Types::ObjectLiteralProperty ObjectLiteralPropertyT; |
207 typedef typename Types::ExpressionList ExpressionListT; | 211 typedef typename Types::ExpressionList ExpressionListT; |
208 typedef typename Types::PropertyList PropertyListT; | 212 typedef typename Types::PropertyList PropertyListT; |
209 typedef typename Types::FormalParameters FormalParametersT; | 213 typedef typename Types::FormalParameters FormalParametersT; |
214 typedef typename Types::Statement StatementT; | |
210 typedef typename Types::StatementList StatementListT; | 215 typedef typename Types::StatementList StatementListT; |
211 typedef typename Types::Block BlockT; | 216 typedef typename Types::Block BlockT; |
212 typedef typename v8::internal::ExpressionClassifier<Types> | 217 typedef typename v8::internal::ExpressionClassifier<Types> |
213 ExpressionClassifier; | 218 ExpressionClassifier; |
214 | 219 |
215 // All implementation-specific methods must be called through this. | 220 // All implementation-specific methods must be called through this. |
216 Impl* impl() { return static_cast<Impl*>(this); } | 221 Impl* impl() { return static_cast<Impl*>(this); } |
217 const Impl* impl() const { return static_cast<const Impl*>(this); } | 222 const Impl* impl() const { return static_cast<const Impl*>(this); } |
218 | 223 |
219 ParserBase(Zone* zone, Scanner* scanner, uintptr_t stack_limit, | 224 ParserBase(Zone* zone, Scanner* scanner, uintptr_t stack_limit, |
(...skipping 689 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
909 return 0; // 0 precedence will terminate binary expression parsing | 914 return 0; // 0 precedence will terminate binary expression parsing |
910 return Token::Precedence(token); | 915 return Token::Precedence(token); |
911 } | 916 } |
912 | 917 |
913 typename Types::Factory* factory() { return &ast_node_factory_; } | 918 typename Types::Factory* factory() { return &ast_node_factory_; } |
914 | 919 |
915 DeclarationScope* GetReceiverScope() const { | 920 DeclarationScope* GetReceiverScope() const { |
916 return scope()->GetReceiverScope(); | 921 return scope()->GetReceiverScope(); |
917 } | 922 } |
918 LanguageMode language_mode() { return scope()->language_mode(); } | 923 LanguageMode language_mode() { return scope()->language_mode(); } |
924 void RaiseLanguageMode(LanguageMode mode) { | |
925 LanguageMode old = scope()->language_mode(); | |
926 impl()->SetLanguageMode(scope(), old > mode ? old : mode); | |
927 } | |
919 bool is_generator() const { return function_state_->is_generator(); } | 928 bool is_generator() const { return function_state_->is_generator(); } |
920 bool is_async_function() const { | 929 bool is_async_function() const { |
921 return function_state_->is_async_function(); | 930 return function_state_->is_async_function(); |
922 } | 931 } |
923 bool is_resumable() const { return function_state_->is_resumable(); } | 932 bool is_resumable() const { return function_state_->is_resumable(); } |
924 | 933 |
925 // Report syntax errors. | 934 // Report syntax errors. |
926 void ReportMessage(MessageTemplate::Template message, const char* arg = NULL, | 935 void ReportMessage(MessageTemplate::Template message, const char* arg = NULL, |
927 ParseErrorType error_type = kSyntaxError) { | 936 ParseErrorType error_type = kSyntaxError) { |
928 Scanner::Location source_location = scanner()->location(); | 937 Scanner::Location source_location = scanner()->location(); |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1172 void ParseFormalParameterList(FormalParametersT* parameters, bool* ok); | 1181 void ParseFormalParameterList(FormalParametersT* parameters, bool* ok); |
1173 void CheckArityRestrictions(int param_count, FunctionKind function_type, | 1182 void CheckArityRestrictions(int param_count, FunctionKind function_type, |
1174 bool has_rest, int formals_start_pos, | 1183 bool has_rest, int formals_start_pos, |
1175 int formals_end_pos, bool* ok); | 1184 int formals_end_pos, bool* ok); |
1176 | 1185 |
1177 BlockT ParseVariableDeclarations(VariableDeclarationContext var_context, | 1186 BlockT ParseVariableDeclarations(VariableDeclarationContext var_context, |
1178 DeclarationParsingResult* parsing_result, | 1187 DeclarationParsingResult* parsing_result, |
1179 ZoneList<const AstRawString*>* names, | 1188 ZoneList<const AstRawString*>* names, |
1180 bool* ok); | 1189 bool* ok); |
1181 | 1190 |
1191 static const int kLazyParseTrialLimit = 200; | |
marja
2016/09/05 08:14:33
This const declaration could use a short comment h
nickie
2016/09/05 11:29:31
Done. It never had one, so I improvised.
| |
1192 V8_INLINE void ParseStatementList(StatementListT body, int end_token, | |
1193 bool* ok) { | |
1194 LazyParsingResult result = ParseStatementList(body, end_token, false, ok); | |
1195 USE(result); // The result is just used in debug modes. | |
marja
2016/09/05 08:14:33
... this comment, on the other hand, is not very u
nickie
2016/09/05 11:29:31
Done. Removed.
| |
1196 DCHECK_EQ(result, kLazyParsingComplete); | |
1197 } | |
1198 LazyParsingResult ParseStatementList(StatementListT body, int end_token, | |
1199 bool may_abort, bool* ok); | |
1200 StatementT ParseStatementListItem(bool* ok); | |
1201 StatementT ParseStatement(ZoneList<const AstRawString*>* labels, | |
1202 AllowLabelledFunctionStatement allow_function, | |
1203 bool* ok); | |
1204 StatementT ParseStatementAsUnlabelled(ZoneList<const AstRawString*>* labels, | |
1205 bool* ok); | |
1206 | |
1182 bool IsNextLetKeyword(); | 1207 bool IsNextLetKeyword(); |
1183 bool IsTrivialExpression(); | 1208 bool IsTrivialExpression(); |
1184 | 1209 |
1185 // Checks if the expression is a valid reference expression (e.g., on the | 1210 // Checks if the expression is a valid reference expression (e.g., on the |
1186 // left-hand side of assignments). Although ruled out by ECMA as early errors, | 1211 // left-hand side of assignments). Although ruled out by ECMA as early errors, |
1187 // we allow calls for web compatibility and rewrite them to a runtime throw. | 1212 // we allow calls for web compatibility and rewrite them to a runtime throw. |
1188 ExpressionT CheckAndRewriteReferenceExpression( | 1213 ExpressionT CheckAndRewriteReferenceExpression( |
1189 ExpressionT expression, int beg_pos, int end_pos, | 1214 ExpressionT expression, int beg_pos, int end_pos, |
1190 MessageTemplate::Template message, bool* ok); | 1215 MessageTemplate::Template message, bool* ok); |
1191 ExpressionT CheckAndRewriteReferenceExpression( | 1216 ExpressionT CheckAndRewriteReferenceExpression( |
(...skipping 2714 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3906 void ParserBase<Impl>::CheckDestructuringElement(ExpressionT expression, | 3931 void ParserBase<Impl>::CheckDestructuringElement(ExpressionT expression, |
3907 int begin, int end) { | 3932 int begin, int end) { |
3908 if (!IsValidPattern(expression) && !expression->IsAssignment() && | 3933 if (!IsValidPattern(expression) && !expression->IsAssignment() && |
3909 !IsValidReferenceExpression(expression)) { | 3934 !IsValidReferenceExpression(expression)) { |
3910 classifier()->RecordAssignmentPatternError( | 3935 classifier()->RecordAssignmentPatternError( |
3911 Scanner::Location(begin, end), | 3936 Scanner::Location(begin, end), |
3912 MessageTemplate::kInvalidDestructuringTarget); | 3937 MessageTemplate::kInvalidDestructuringTarget); |
3913 } | 3938 } |
3914 } | 3939 } |
3915 | 3940 |
3941 // Redefinition of CHECK_OK for parsing statements. | |
3942 #undef CHECK_OK | |
3943 #define CHECK_OK CHECK_OK_CUSTOM(NullStatement) | |
3944 | |
3945 template <typename Impl> | |
3946 typename ParserBase<Impl>::LazyParsingResult | |
3947 ParserBase<Impl>::ParseStatementList(StatementListT body, int end_token, | |
3948 bool may_abort, bool* ok) { | |
3949 // StatementList :: | |
3950 // (StatementListItem)* <end_token> | |
3951 | |
3952 // Allocate a target stack to use for this set of source | |
3953 // elements. This way, all scripts and functions get their own | |
3954 // target stack thus avoiding illegal breaks and continues across | |
3955 // functions. | |
3956 typename Types::TargetScope target_scope(this); | |
3957 int count_statements = 0; | |
3958 | |
3959 DCHECK(!impl()->IsNullStatementList(body)); | |
3960 bool directive_prologue = true; // Parsing directive prologue. | |
3961 | |
3962 while (peek() != end_token) { | |
3963 if (directive_prologue && peek() != Token::STRING) { | |
3964 directive_prologue = false; | |
3965 } | |
3966 | |
3967 bool starts_with_identifier = peek() == Token::IDENTIFIER; | |
3968 Scanner::Location token_loc = scanner()->peek_location(); | |
3969 StatementT stat = impl()->ParseStatementListItem( | |
3970 CHECK_OK_CUSTOM(Return, kLazyParsingComplete)); | |
3971 | |
3972 if (impl()->IsNullOrEmptyStatement(stat)) { | |
3973 directive_prologue = false; // End of directive prologue. | |
3974 continue; | |
3975 } | |
3976 | |
3977 if (directive_prologue) { | |
3978 // The length of the token is used to distinguish between strings literals | |
3979 // that evaluate equal to directives but contain either escape sequences | |
3980 // (e.g., "use \x73trict") or line continuations (e.g., "use \ | |
3981 // strict"). | |
3982 if (impl()->IsUseStrictDirective(stat) && | |
3983 token_loc.end_pos - token_loc.beg_pos == sizeof("use strict") + 1) { | |
3984 // Directive "use strict" (ES5 14.1). | |
3985 RaiseLanguageMode(STRICT); | |
3986 if (!scope()->HasSimpleParameters()) { | |
3987 // TC39 deemed "use strict" directives to be an error when occurring | |
3988 // in the body of a function with non-simple parameter list, on | |
3989 // 29/7/2015. https://goo.gl/ueA7Ln | |
3990 impl()->ReportMessageAt( | |
3991 token_loc, MessageTemplate::kIllegalLanguageModeDirective, | |
3992 "use strict"); | |
3993 *ok = false; | |
3994 return kLazyParsingComplete; | |
3995 } | |
3996 // Because declarations in strict eval code don't leak into the scope | |
3997 // of the eval call, it is likely that functions declared in strict | |
3998 // eval code will be used within the eval code, so lazy parsing is | |
3999 // probably not a win. | |
4000 if (scope()->is_eval_scope()) mode_ = PARSE_EAGERLY; | |
4001 } else if (impl()->IsUseAsmDirective(stat) && | |
4002 token_loc.end_pos - token_loc.beg_pos == | |
4003 sizeof("use asm") + 1) { | |
4004 // Directive "use asm". | |
4005 impl()->SetAsmModule(); | |
4006 } else if (impl()->IsStringLiteral(stat)) { | |
4007 // Possibly an unknown directive. | |
4008 // TODO(nikolaos): Check if the following is really what we want! | |
4009 // """Should not change mode, but will increment UseCounter | |
4010 // if appropriate. Ditto usages below.""" ??? | |
4011 RaiseLanguageMode(SLOPPY); | |
4012 } else { | |
nickie
2016/09/05 11:29:31
These were copied from here [1] and history takes
| |
4013 // End of the directive prologue. | |
4014 directive_prologue = false; | |
4015 // TODO(nikolaos): Check if the following is really what we want! | |
4016 RaiseLanguageMode(SLOPPY); | |
4017 } | |
4018 } else { | |
4019 // TODO(nikolaos): Check if the following is really what we want! | |
4020 RaiseLanguageMode(SLOPPY); | |
4021 } | |
4022 | |
4023 // If we're allowed to reset to a bookmark, we will do so when we see a long | |
4024 // and trivial function. | |
4025 // Our current definition of 'long and trivial' is: | |
4026 // - over 200 statements | |
4027 // - all starting with an identifier (i.e., no if, for, while, etc.) | |
4028 if (may_abort) { | |
4029 if (!starts_with_identifier) { | |
4030 may_abort = false; | |
4031 } else if (++count_statements > kLazyParseTrialLimit) { | |
4032 return kLazyParsingAborted; | |
4033 } | |
4034 } | |
4035 | |
4036 body->Add(stat, zone()); | |
4037 } | |
4038 return kLazyParsingComplete; | |
4039 } | |
4040 | |
4041 template <typename Impl> | |
4042 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseStatementListItem( | |
4043 bool* ok) { | |
4044 // ECMA 262 6th Edition | |
4045 // StatementListItem[Yield, Return] : | |
4046 // Statement[?Yield, ?Return] | |
4047 // Declaration[?Yield] | |
4048 // | |
4049 // Declaration[Yield] : | |
4050 // HoistableDeclaration[?Yield] | |
4051 // ClassDeclaration[?Yield] | |
4052 // LexicalDeclaration[In, ?Yield] | |
4053 // | |
4054 // HoistableDeclaration[Yield, Default] : | |
4055 // FunctionDeclaration[?Yield, ?Default] | |
4056 // GeneratorDeclaration[?Yield, ?Default] | |
4057 // | |
4058 // LexicalDeclaration[In, Yield] : | |
4059 // LetOrConst BindingList[?In, ?Yield] ; | |
4060 | |
4061 switch (peek()) { | |
4062 case Token::FUNCTION: | |
4063 return impl()->ParseHoistableDeclaration(NULL, false, ok); | |
marja
2016/09/05 08:14:33
Nit: NULL -> nullptr in several places
nickie
2016/09/05 11:29:31
Done.
| |
4064 case Token::CLASS: | |
4065 Consume(Token::CLASS); | |
4066 return impl()->ParseClassDeclaration(NULL, false, ok); | |
4067 case Token::VAR: | |
4068 case Token::CONST: | |
4069 return impl()->ParseVariableStatement(kStatementListItem, NULL, ok); | |
4070 case Token::LET: | |
4071 if (IsNextLetKeyword()) { | |
4072 return impl()->ParseVariableStatement(kStatementListItem, NULL, ok); | |
4073 } | |
4074 break; | |
4075 case Token::ASYNC: | |
4076 if (allow_harmony_async_await() && PeekAhead() == Token::FUNCTION && | |
4077 !scanner()->HasAnyLineTerminatorAfterNext()) { | |
4078 Consume(Token::ASYNC); | |
4079 return impl()->ParseAsyncFunctionDeclaration(NULL, false, ok); | |
4080 } | |
4081 /* falls through */ | |
4082 default: | |
4083 break; | |
4084 } | |
4085 return impl()->ParseStatement(NULL, kAllowLabelledFunctionStatement, ok); | |
4086 } | |
4087 | |
4088 template <typename Impl> | |
4089 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseStatement( | |
4090 ZoneList<const AstRawString*>* labels, | |
4091 AllowLabelledFunctionStatement allow_function, bool* ok) { | |
4092 // Statement :: | |
4093 // Block | |
4094 // VariableStatement | |
4095 // EmptyStatement | |
4096 // ExpressionStatement | |
4097 // IfStatement | |
4098 // IterationStatement | |
4099 // ContinueStatement | |
4100 // BreakStatement | |
4101 // ReturnStatement | |
4102 // WithStatement | |
4103 // LabelledStatement | |
4104 // SwitchStatement | |
4105 // ThrowStatement | |
4106 // TryStatement | |
4107 // DebuggerStatement | |
4108 | |
4109 // Note: Since labels can only be used by 'break' and 'continue' | |
4110 // statements, which themselves are only valid within blocks, | |
4111 // iterations or 'switch' statements (i.e., BreakableStatements), | |
4112 // labels can be simply ignored in all other cases; except for | |
4113 // trivial labeled break statements 'label: break label' which is | |
4114 // parsed into an empty statement. | |
4115 switch (peek()) { | |
4116 case Token::LBRACE: | |
4117 return impl()->ParseBlock(labels, ok); | |
4118 case Token::SEMICOLON: | |
4119 Next(); | |
4120 return factory()->NewEmptyStatement(kNoSourcePosition); | |
4121 case Token::IF: | |
4122 return impl()->ParseIfStatement(labels, ok); | |
4123 case Token::DO: | |
4124 return impl()->ParseDoWhileStatement(labels, ok); | |
4125 case Token::WHILE: | |
4126 return impl()->ParseWhileStatement(labels, ok); | |
4127 case Token::FOR: | |
4128 return impl()->ParseForStatement(labels, ok); | |
4129 case Token::CONTINUE: | |
4130 case Token::BREAK: | |
4131 case Token::RETURN: | |
4132 case Token::THROW: | |
4133 case Token::TRY: { | |
4134 // These statements must have their labels preserved in an enclosing | |
4135 // block | |
4136 if (labels == nullptr) { | |
4137 return ParseStatementAsUnlabelled(labels, ok); | |
4138 } else { | |
4139 BlockT result = | |
4140 factory()->NewBlock(labels, 1, false, kNoSourcePosition); | |
4141 typename Types::Target target(this, result); | |
4142 StatementT statement = ParseStatementAsUnlabelled(labels, CHECK_OK); | |
marja
2016/09/05 08:14:33
What does "ParseStatementAsUnlabelled" mean? You'r
nickie
2016/09/05 11:29:31
I don't know what it means... :-)
(Offline discuss
| |
4143 result->statements()->Add(statement, zone()); | |
4144 return result; | |
4145 } | |
4146 } | |
4147 case Token::WITH: | |
4148 return impl()->ParseWithStatement(labels, ok); | |
4149 case Token::SWITCH: | |
4150 return impl()->ParseSwitchStatement(labels, ok); | |
4151 case Token::FUNCTION: | |
4152 // FunctionDeclaration only allowed as a StatementListItem, not in | |
4153 // an arbitrary Statement position. Exceptions such as | |
4154 // ES#sec-functiondeclarations-in-ifstatement-statement-clauses | |
4155 // are handled by calling ParseScopedStatement rather than | |
4156 // ParseStatement directly. | |
4157 impl()->ReportMessageAt(scanner()->peek_location(), | |
4158 is_strict(language_mode()) | |
4159 ? MessageTemplate::kStrictFunction | |
4160 : MessageTemplate::kSloppyFunction); | |
4161 *ok = false; | |
4162 return impl()->NullStatement(); | |
4163 case Token::DEBUGGER: | |
4164 return impl()->ParseDebuggerStatement(ok); | |
4165 case Token::VAR: | |
4166 return impl()->ParseVariableStatement(kStatement, nullptr, ok); | |
4167 default: | |
4168 return impl()->ParseExpressionOrLabelledStatement(labels, allow_function, | |
4169 ok); | |
4170 } | |
4171 } | |
4172 | |
4173 template <typename Impl> | |
4174 typename ParserBase<Impl>::StatementT | |
4175 ParserBase<Impl>::ParseStatementAsUnlabelled( | |
4176 ZoneList<const AstRawString*>* labels, bool* ok) { | |
4177 switch (peek()) { | |
4178 case Token::CONTINUE: | |
4179 return impl()->ParseContinueStatement(ok); | |
4180 case Token::BREAK: | |
4181 return impl()->ParseBreakStatement(labels, ok); | |
4182 case Token::RETURN: | |
4183 return impl()->ParseReturnStatement(ok); | |
4184 case Token::THROW: | |
4185 return impl()->ParseThrowStatement(ok); | |
4186 case Token::TRY: | |
4187 return impl()->ParseTryStatement(ok); | |
4188 default: | |
4189 UNREACHABLE(); | |
4190 return impl()->NullStatement(); | |
4191 } | |
4192 } | |
4193 | |
3916 #undef CHECK_OK | 4194 #undef CHECK_OK |
3917 #undef CHECK_OK_CUSTOM | 4195 #undef CHECK_OK_CUSTOM |
3918 | 4196 |
3919 template <typename Impl> | 4197 template <typename Impl> |
3920 void ParserBase<Impl>::ObjectLiteralChecker::CheckProperty( | 4198 void ParserBase<Impl>::ObjectLiteralChecker::CheckProperty( |
3921 Token::Value property, PropertyKind type, MethodKind method_type, | 4199 Token::Value property, PropertyKind type, MethodKind method_type, |
3922 bool* ok) { | 4200 bool* ok) { |
3923 DCHECK(!IsStaticMethod(method_type)); | 4201 DCHECK(!IsStaticMethod(method_type)); |
3924 DCHECK(!IsSpecialMethod(method_type) || | 4202 DCHECK(!IsSpecialMethod(method_type) || |
3925 type == PropertyKind::kMethodProperty); | 4203 type == PropertyKind::kMethodProperty); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3971 has_seen_constructor_ = true; | 4249 has_seen_constructor_ = true; |
3972 return; | 4250 return; |
3973 } | 4251 } |
3974 } | 4252 } |
3975 | 4253 |
3976 | 4254 |
3977 } // namespace internal | 4255 } // namespace internal |
3978 } // namespace v8 | 4256 } // namespace v8 |
3979 | 4257 |
3980 #endif // V8_PARSING_PARSER_BASE_H | 4258 #endif // V8_PARSING_PARSER_BASE_H |
OLD | NEW |