v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
parser-base.h
Go to the documentation of this file.
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
3// found in the LICENSE file.
4
5#ifndef V8_PARSING_PARSER_BASE_H_
6#define V8_PARSING_PARSER_BASE_H_
7
8#include <stdint.h>
9
10#include <optional>
11#include <utility>
12#include <vector>
13
15#include "src/ast/ast.h"
16#include "src/ast/scopes.h"
17#include "src/base/flags.h"
18#include "src/base/hashmap.h"
21#include "src/common/globals.h"
23#include "src/logging/log.h"
29#include "src/parsing/scanner.h"
30#include "src/parsing/token.h"
31#include "src/regexp/regexp.h"
33
34namespace v8::internal {
35
36class PreParserIdentifier;
37
43
48
50
51enum class ParseFunctionFlag : uint8_t {
52 kIsNormal = 0,
53 kIsGenerator = 1 << 0,
54 kIsAsync = 1 << 1
55};
56
58
61
62 int num_parameters() const {
63 // Don't include the rest parameter into the function's formal parameter
64 // count (esp. the SharedFunctionInfo::internal_formal_parameter_count,
65 // which says whether we need to create an inlined arguments frame).
66 return arity - has_rest;
67 }
68
69 void UpdateArityAndFunctionLength(bool is_optional, bool is_rest) {
70 if (!is_optional && !is_rest && function_length == arity) {
72 }
73 ++arity;
74 }
75
77 bool has_rest = false;
78 bool is_simple = true;
80 int arity = 0;
81};
82
83// Stack-allocated scope to collect source ranges from the parser.
85 public:
86 SourceRangeScope(const Scanner* scanner, SourceRange* range)
87 : scanner_(scanner), range_(range) {
88 range_->start = scanner->peek_location().beg_pos;
89 DCHECK_NE(range_->start, kNoSourcePosition);
90 DCHECK_EQ(range_->end, kNoSourcePosition);
91 }
92
94 DCHECK_EQ(kNoSourcePosition, range_->end);
95 range_->end = scanner_->location().end_pos;
96 DCHECK_NE(range_->end, kNoSourcePosition);
97 }
98
99 private:
102
104};
105
106// ----------------------------------------------------------------------------
107// The RETURN_IF_PARSE_ERROR macro is a convenient macro to enforce error
108// handling for functions that may fail (by returning if there was an parser
109// error).
110//
111// Usage:
112// foo = ParseFoo(); // may fail
113// RETURN_IF_PARSE_ERROR
114//
115// SAFE_USE(foo);
116
117#define RETURN_IF_PARSE_ERROR \
118 if (has_error()) return impl()->NullStatement();
119
120// Common base class template shared between parser and pre-parser.
121// The Impl parameter is the actual class of the parser/pre-parser,
122// following the Curiously Recurring Template Pattern (CRTP).
123// The structure of the parser objects is roughly the following:
124//
125// // A structure template containing type definitions, needed to
126// // avoid a cyclic dependency.
127// template <typename Impl>
128// struct ParserTypes;
129//
130// // The parser base object, which should just implement pure
131// // parser behavior. The Impl parameter is the actual derived
132// // class (according to CRTP), which implements impure parser
133// // behavior.
134// template <typename Impl>
135// class ParserBase { ... };
136//
137// // And then, for each parser variant (e.g., parser, preparser, etc):
138// class Parser;
139//
140// template <>
141// class ParserTypes<Parser> { ... };
142//
143// class Parser : public ParserBase<Parser> { ... };
144//
145// The parser base object implements pure parsing, according to the
146// language grammar. Different parser implementations may exhibit
147// different parser-driven behavior that is not considered as pure
148// parsing, e.g., early error detection and reporting, AST generation, etc.
149
150// The ParserTypes structure encapsulates the differences in the
151// types used in parsing methods. E.g., Parser methods use Expression*
152// and PreParser methods use PreParserExpression. For any given parser
153// implementation class Impl, it is expected to contain the following typedefs:
154//
155// template <>
156// struct ParserTypes<Impl> {
157// // Synonyms for ParserBase<Impl> and Impl, respectively.
158// typedef Base;
159// typedef Impl;
160// // Return types for traversing functions.
161// typedef Identifier;
162// typedef Expression;
163// typedef FunctionLiteral;
164// typedef ObjectLiteralProperty;
165// typedef ClassLiteralProperty;
166// typedef ExpressionList;
167// typedef ObjectPropertyList;
168// typedef ClassPropertyList;
169// typedef FormalParameters;
170// typedef Statement;
171// typedef StatementList;
172// typedef Block;
173// typedef BreakableStatement;
174// typedef ForStatement;
175// typedef IterationStatement;
176// // For constructing objects returned by the traversing functions.
177// typedef Factory;
178// // For other implementation-specific tasks.
179// typedef Target;
180// typedef TargetScope;
181// };
182
183template <typename Impl>
185
199
200template <typename Impl>
202 public:
203 // Shorten type names defined by ParserTypes<Impl>.
215
216 // Return types for traversing functions.
217 using BlockT = typename Types::Block;
218 using BreakableStatementT = typename Types::BreakableStatement;
219 using ClassLiteralPropertyT = typename Types::ClassLiteralProperty;
220 using ClassPropertyListT = typename Types::ClassPropertyList;
221 using ClassStaticElementListT = typename Types::ClassStaticElementList;
222 using ExpressionT = typename Types::Expression;
223 using ExpressionListT = typename Types::ExpressionList;
224 using FormalParametersT = typename Types::FormalParameters;
225 using ForStatementT = typename Types::ForStatement;
226 using FunctionLiteralT = typename Types::FunctionLiteral;
227 using IdentifierT = typename Types::Identifier;
228 using IterationStatementT = typename Types::IterationStatement;
229 using ObjectLiteralPropertyT = typename Types::ObjectLiteralProperty;
230 using ObjectPropertyListT = typename Types::ObjectPropertyList;
231 using StatementT = typename Types::Statement;
232 using StatementListT = typename Types::StatementList;
233 using SuspendExpressionT = typename Types::Suspend;
234 // For constructing objects returned by the traversing functions.
235 using FactoryT = typename Types::Factory;
236 // Other implementation-specific tasks.
237 using FuncNameInferrer = typename Types::FuncNameInferrer;
238 using FuncNameInferrerState = typename Types::FuncNameInferrer::State;
239 using SourceRange = typename Types::SourceRange;
240 using SourceRangeScope = typename Types::SourceRangeScope;
241
242 // All implementation-specific methods must be called through this.
243 Impl* impl() { return static_cast<Impl*>(this); }
244 const Impl* impl() const { return static_cast<const Impl*>(this); }
245
249 RuntimeCallStats* runtime_call_stats, V8FileLogger* v8_file_logger,
250 UnoptimizedCompileFlags flags, bool parsing_on_main_thread,
251 bool compile_hints_magic_enabled,
252 bool compile_hints_per_function_magic_enabled)
253 : scope_(nullptr),
254 original_scope_(nullptr),
255 function_state_(nullptr),
259 runtime_call_stats_(runtime_call_stats),
260 v8_file_logger_(v8_file_logger),
261 parsing_on_main_thread_(parsing_on_main_thread),
264 zone_(zone),
265 expression_scope_(nullptr),
267 flags_(flags),
268 info_id_(0),
270 default_eager_compile_hint_(FunctionLiteral::kShouldLazyCompile),
271 compile_hints_magic_enabled_(compile_hints_magic_enabled),
273 compile_hints_per_function_magic_enabled) {
274 pointer_buffer_.reserve(32);
275 variable_buffer_.reserve(32);
276 }
277
278 const UnoptimizedCompileFlags& flags() const { return flags_; }
280
281 // DebugEvaluate code
283 return flags().parsing_while_debugging() == ParsingWhileDebugging::kYes;
284 }
285
286 bool allow_eval_cache() const { return allow_eval_cache_; }
287 void set_allow_eval_cache(bool allow) { allow_eval_cache_ = allow; }
288
289 V8_INLINE bool has_error() const { return scanner()->has_parser_error(); }
290
291 uintptr_t stack_limit() const { return stack_limit_; }
292
294
296 FunctionLiteral::EagerCompileHint eager_compile_hint) {
297 default_eager_compile_hint_ = eager_compile_hint;
298 }
299
303
304 int loop_nesting_depth() const {
306 }
307 int PeekNextInfoId() { return info_id_ + 1; }
308 int GetNextInfoId() { return ++info_id_; }
309 int GetLastInfoId() const { return info_id_; }
310
311 void SkipInfos(int delta) { info_id_ += delta; }
312
313 void ResetInfoId() { info_id_ = 0; }
314
315 // The Zone where the parsing outputs are stored.
317
318 // The current Zone, which might be the main zone or a temporary Zone.
319 Zone* zone() const { return zone_; }
320
322
323 protected:
324 friend class v8::internal::ExpressionScope<ParserTypes<Impl>>;
327
333
334 class ClassLiteralChecker;
335
336 // ---------------------------------------------------------------------------
337 // BlockState and FunctionState implement the parser's scope stack.
338 // The parser's current scope is in scope_. BlockState and FunctionState
339 // constructors push on the scope stack and the destructors pop. They are also
340 // used to hold the parser's per-funcion state.
342 public:
343 BlockState(Scope** scope_stack, Scope* scope)
344 : scope_stack_(scope_stack), outer_scope_(*scope_stack) {
346 }
347
348 BlockState(Zone* zone, Scope** scope_stack)
349 : BlockState(scope_stack,
350 zone->New<Scope>(zone, *scope_stack, BLOCK_SCOPE)) {}
351
353
354 private:
357 };
358
359 // ---------------------------------------------------------------------------
360 // Target is a support class to facilitate manipulation of the
361 // Parser's target_stack_ (the stack of potential 'break' and
362 // 'continue' statement targets). Upon construction, a new target is
363 // added; it is removed upon destruction.
364
365 // |labels| is a list of all labels that can be used as a target for break.
366 // |own_labels| is a list of all labels that an iteration statement is
367 // directly prefixed with, i.e. all the labels that a continue statement in
368 // the body can use to continue this iteration statement. This is always a
369 // subset of |labels|.
370 //
371 // Example: "l1: { l2: if (b) l3: l4: for (;;) s }"
372 // labels() of the Block will be l1.
373 // labels() of the ForStatement will be l2, l3, l4.
374 // own_labels() of the ForStatement will be l3, l4.
375 class Target {
376 public:
378
382 : stack_(parser->function_state_->target_stack_address()),
386 target_type_(target_type),
387 previous_(*stack_) {
388 DCHECK_IMPLIES(Impl::IsIterationStatement(statement_),
389 target_type == Target::TARGET_FOR_ANONYMOUS);
390 DCHECK_IMPLIES(!Impl::IsIterationStatement(statement_),
391 own_labels == nullptr);
392 *stack_ = this;
393 }
394
396
397 const Target* previous() const { return previous_; }
398 const BreakableStatementT statement() const { return statement_; }
401 return own_labels_;
402 }
403 bool is_iteration() const { return Impl::IsIterationStatement(statement_); }
406 }
407
408 private:
409 Target** const stack_;
415 };
416
418
420 bool anonymous = impl()->IsNull(label);
421 for (const Target* t = target_stack(); t != nullptr; t = t->previous()) {
422 if ((anonymous && t->is_target_for_anonymous()) ||
423 (!anonymous &&
424 ContainsLabel(t->labels(),
425 impl()->GetRawNameFromIdentifier(label)))) {
426 return t->statement();
427 }
428 }
429 return impl()->NullStatement();
430 }
431
433 bool anonymous = impl()->IsNull(label);
434 for (const Target* t = target_stack(); t != nullptr; t = t->previous()) {
435 if (!t->is_iteration()) continue;
436
437 DCHECK(t->is_target_for_anonymous());
438 if (anonymous || ContainsLabel(t->own_labels(),
439 impl()->GetRawNameFromIdentifier(label))) {
440 return impl()->AsIterationStatement(t->statement());
441 }
442 }
443 return impl()->NullStatement();
444 }
445
446 class FunctionState final : public BlockState {
447 public:
448 FunctionState(FunctionState** function_state_stack, Scope** scope_stack,
451
453
456
458 dont_optimize_reason_ = reason;
459 }
461
463 int suspend_count() const { return suspend_count_; }
464 bool CanSuspend() const { return suspend_count_ > 0; }
465
466 FunctionKind kind() const { return scope()->function_kind(); }
467
471
475
479
484
486 public:
488 : state_and_prev_value_(state, state->contains_function_or_eval_) {
489 state->contains_function_or_eval_ = false;
490 }
492 bool found = state_and_prev_value_->contains_function_or_eval_;
493 if (!found) {
494 state_and_prev_value_->contains_function_or_eval_ =
495 state_and_prev_value_.GetPayload();
496 }
497 }
498
499 private:
501 };
502
504 public:
505 explicit LoopScope(FunctionState* function_state)
506 : function_state_(function_state) {
507 function_state_->loop_nesting_depth_++;
508 }
509
510 ~LoopScope() { function_state_->loop_nesting_depth_--; }
511
512 private:
514 };
515
517
519
520 private:
521 // Properties count estimation.
523
524 // How many suspends are needed for this function.
526
527 // How deeply nested we currently are in this function.
529
533 Target* target_stack_ = nullptr; // for break, continue statements
534
535 // A reason, if any, why this function should not be optimized.
537
538 // Record whether the next (=== immediately following) function literal is
539 // preceded by a parenthesis / exclamation mark. Also record the previous
540 // state.
541 // These are managed by the FunctionState constructor; the caller may only
542 // call set_next_function_is_likely_called.
545
546 // Track if a function or eval occurs within this FunctionState
548
549 friend Impl;
550 };
551
558
580
581 struct CatchInfo {
582 public:
583 explicit CatchInfo(ParserBase* parser)
584 : pattern(parser->impl()->NullExpression()),
585 variable(nullptr),
586 scope(nullptr) {}
590 };
591
604
605 struct ClassInfo {
606 public:
607 explicit ClassInfo(ParserBase* parser)
608 : extends(parser->impl()->NullExpression()),
609 public_members(parser->impl()->NewClassPropertyList(4)),
610 private_members(parser->impl()->NewClassPropertyList(4)),
611 static_elements(parser->impl()->NewClassStaticElementList(4)),
612 instance_fields(parser->impl()->NewClassPropertyList(4)),
613 constructor(parser->impl()->NullExpression()) {}
620
621 bool has_static_elements() const {
622 return static_elements_scope != nullptr;
623 }
624 bool has_instance_members() const {
625 return instance_members_scope != nullptr;
626 }
627
629 int info_id) {
630 if (!has_static_elements()) {
636 // Actually consume the id. The id that was passed in might be an
637 // earlier id in case of computed property names.
638 parser->GetNextInfoId();
639 }
641 }
642
644 int beg_pos, int info_id) {
645 if (!has_instance_members()) {
651 // Actually consume the id. The id that was passed in might be an
652 // earlier id in case of computed property names.
653 parser->GetNextInfoId();
654 }
656 }
657
669 bool has_static_blocks : 1 = false;
670 bool requires_brand : 1 = false;
671 bool is_anonymous : 1 = false;
672 };
673
676 public:
680 name(parser->impl()->NullIdentifier()),
684 is_computed_name(false),
685 is_private(false),
686 is_static(false),
687 is_rest(false) {}
688
690 // This returns true, setting the property kind, iff the given token is
691 // one which must occur after a property name, indicating that the
692 // previous token was in fact a name and not a modifier (like the "get" in
693 // "get x").
694 switch (token) {
695 case Token::kColon:
697 return true;
698 case Token::kComma:
700 return true;
701 case Token::kRightBrace:
703 return true;
704 case Token::kAssign:
706 return true;
707 case Token::kLeftParen:
709 return true;
710 case Token::kMul:
711 case Token::kSemicolon:
713 return true;
714 default:
715 break;
716 }
717 return false;
718 }
719
729 };
730
733 const AstRawString* label) {
735 ReportMessage(MessageTemplate::kLabelRedeclaration, label);
736 return;
737 }
738
739 // Add {label} to both {labels} and {own_labels}.
740 if (*labels == nullptr) {
741 DCHECK_NULL(*own_labels);
742 *labels =
743 zone()->template New<ZonePtrList<const AstRawString>>(1, zone());
744 *own_labels =
745 zone()->template New<ZonePtrList<const AstRawString>>(1, zone());
746 } else {
747 if (*own_labels == nullptr) {
748 *own_labels =
749 zone()->template New<ZonePtrList<const AstRawString>>(1, zone());
750 }
751 }
752 (*labels)->Add(label, zone());
753 (*own_labels)->Add(label, zone());
754 }
755
757 const AstRawString* label) {
759 if (labels != nullptr) {
760 for (int i = labels->length(); i-- > 0;) {
761 if (labels->at(i) == label) return true;
762 }
763 }
764 return false;
765 }
766
768 for (const Target* t = target_stack(); t != nullptr; t = t->previous()) {
769 if (ContainsLabel(t->labels(), label)) return true;
770 }
771 return false;
772 }
773
791
806
808 int index) {
809 std::string name = ".class-field-" + std::to_string(index);
810 return ast_value_factory->GetOneByteString(name.c_str());
811 }
812
815 std::string name = ".accessor-storage-" + std::to_string(index);
816 return ast_value_factory->GetOneByteString(name.c_str());
817 }
818
820 return zone()->template New<DeclarationScope>(zone(), ast_value_factory(),
821 repl_mode);
822 }
823
825 return zone()->template New<DeclarationScope>(zone(), scope(), BLOCK_SCOPE);
826 }
827
829 return zone()->template New<ModuleScope>(parent, ast_value_factory());
830 }
831
833 return zone()->template New<DeclarationScope>(zone(), parent, EVAL_SCOPE);
834 }
835
836 ClassScope* NewClassScope(Scope* parent, bool is_anonymous) const {
837 return zone()->template New<ClassScope>(zone(), parent, is_anonymous);
838 }
839
845
846 Scope* NewScope(ScopeType scope_type) const {
847 return NewScopeWithParent(scope(), scope_type);
848 }
849
850 // This constructor should only be used when absolutely necessary. Most scopes
851 // should automatically use scope() as parent, and be fine with
852 // NewScope(ScopeType) above.
853 Scope* NewScopeWithParent(Scope* parent, ScopeType scope_type) const {
854 // Must always use the specific constructors for the blocklisted scope
855 // types.
856 DCHECK_NE(FUNCTION_SCOPE, scope_type);
857 DCHECK_NE(SCRIPT_SCOPE, scope_type);
858 DCHECK_NE(REPL_MODE_SCOPE, scope_type);
859 DCHECK_NE(MODULE_SCOPE, scope_type);
860 DCHECK_NOT_NULL(parent);
861 return zone()->template New<Scope>(zone(), parent, scope_type);
862 }
863
864 // Creates a function scope that always allocates in zone(). The function
865 // scope itself is either allocated in zone() or in target_zone if one is
866 // passed in.
868 Zone* parse_zone = nullptr) const {
870 if (parse_zone == nullptr) parse_zone = zone();
871 DeclarationScope* result = zone()->template New<DeclarationScope>(
872 parse_zone, scope(), FUNCTION_SCOPE, kind);
873
874 // Record presence of an inner function scope
876
877 // TODO(verwaest): Move into the DeclarationScope constructor.
878 if (!IsArrowFunction(kind)) {
879 result->DeclareDefaultFunctionVariables(ast_value_factory());
880 }
881 return result;
882 }
883
890
892 return factory()->ast_node_factory()->NewVariableProxy(
893 name, NORMAL_VARIABLE, pos);
894 }
895
897 return scope()->NewUnresolved(factory()->ast_node_factory(), name,
898 scanner()->location().beg_pos);
899 }
900
901 VariableProxy* NewUnresolved(const AstRawString* name, int begin_pos,
903 return scope()->NewUnresolved(factory()->ast_node_factory(), name,
904 begin_pos, kind);
905 }
906
907 Scanner* scanner() const { return scanner_; }
909 int position() const { return scanner_->location().beg_pos; }
910 int peek_position() const { return scanner_->peek_location().beg_pos; }
911 int end_position() const { return scanner_->location().end_pos; }
912 int peek_end_position() const { return scanner_->peek_location().end_pos; }
913 bool stack_overflow() const {
914 return pending_error_handler()->stack_overflow();
915 }
918 pending_error_handler()->set_stack_overflow();
919 }
921 // Any further calls to Next or peek will return the illegal token.
923 }
924
926
927 // Returns the position past the following semicolon (if it exists), and the
928 // position past the end of the current token otherwise.
930 return (peek() == Token::kSemicolon) ? peek_end_position() : end_position();
931 }
932
936
938
940
942 Token::Value next = scanner()->Next();
943 USE(next);
944 USE(token);
945 DCHECK_IMPLIES(!has_error(), next == token);
946 }
947
949 Token::Value next = scanner()->peek();
950 if (next == token) {
951 Consume(next);
952 return true;
953 }
954 return false;
955 }
956
957 void Expect(Token::Value token) {
958 Token::Value next = Next();
959 if (V8_UNLIKELY(next != token)) {
961 }
962 }
963
965 // Check for automatic semicolon insertion according to
966 // the rules given in ECMA-262, section 7.9, page 21.
967 Token::Value tok = peek();
968 if (V8_LIKELY(tok == Token::kSemicolon)) {
969 Next();
970 return;
971 }
972 if (V8_LIKELY(scanner()->HasLineTerminatorBeforeNext() ||
974 return;
975 }
976
977 if (scanner()->current_token() == Token::kAwait && !is_async_function()) {
978 if (flags().parsing_while_debugging() == ParsingWhileDebugging::kYes) {
979 ReportMessageAt(scanner()->location(),
980 MessageTemplate::kAwaitNotInDebugEvaluate);
981 } else {
982 ReportMessageAt(scanner()->location(),
983 MessageTemplate::kAwaitNotInAsyncContext);
984 }
985 return;
986 }
987
989 }
990
992
994 return peek() == Token::kIdentifier &&
997 }
998
1000 return peek() == token && !scanner()->next_literal_contains_escapes();
1001 }
1002
1004 if (PeekContextualKeyword(name)) {
1005 Consume(Token::kIdentifier);
1006 return true;
1007 }
1008 return false;
1009 }
1010
1012 if (PeekContextualKeyword(token)) {
1013 Consume(token);
1014 return true;
1015 }
1016 return false;
1017 }
1018
1020 const char* fullname = nullptr, int pos = -1) {
1021 Expect(Token::kIdentifier);
1022 if (V8_UNLIKELY(scanner()->CurrentSymbol(ast_value_factory()) != name)) {
1023 ReportUnexpectedToken(scanner()->current_token());
1024 }
1025 if (V8_UNLIKELY(scanner()->literal_contains_escapes())) {
1026 const char* full = fullname == nullptr
1027 ? reinterpret_cast<const char*>(name->raw_data())
1028 : fullname;
1029 int start = pos == -1 ? position() : pos;
1030 impl()->ReportMessageAt(Scanner::Location(start, end_position()),
1031 MessageTemplate::kInvalidEscapedMetaProperty,
1032 full);
1033 }
1034 }
1035
1037 // Token Should be in range of Token::kIdentifier + 1 to Token::kAsync
1038 DCHECK(base::IsInRange(token, Token::kGet, Token::kAsync));
1039 Token::Value next = Next();
1040 if (V8_UNLIKELY(next != token)) {
1042 }
1043 if (V8_UNLIKELY(scanner()->literal_contains_escapes())) {
1044 impl()->ReportUnexpectedToken(Token::kEscapedKeyword);
1045 }
1046 }
1047
1049 if (Check(Token::kIn)) {
1050 *visit_mode = ForEachStatement::ENUMERATE;
1051 return true;
1052 } else if (CheckContextualKeyword(Token::kOf)) {
1053 *visit_mode = ForEachStatement::ITERATE;
1054 return true;
1055 }
1056 return false;
1057 }
1058
1059 bool PeekInOrOf() {
1060 return peek() == Token::kIn || PeekContextualKeyword(Token::kOf);
1061 }
1062
1063 // Checks whether an octal literal was last seen between beg_pos and end_pos.
1064 // Only called for strict mode strings.
1065 void CheckStrictOctalLiteral(int beg_pos, int end_pos) {
1067 if (octal.IsValid() && beg_pos <= octal.beg_pos &&
1068 octal.end_pos <= end_pos) {
1069 MessageTemplate message = scanner()->octal_message();
1070 DCHECK_NE(message, MessageTemplate::kNone);
1071 impl()->ReportMessageAt(octal, message);
1073 if (message == MessageTemplate::kStrictDecimalWithLeadingZero) {
1075 }
1076 }
1077 }
1078
1079 // Checks if an octal literal or an invalid hex or unicode escape sequence
1080 // appears in the current template literal token. In the presence of such,
1081 // either returns false or reports an error, depending on should_throw.
1082 // Otherwise returns true.
1083 inline bool CheckTemplateEscapes(bool should_throw) {
1084 DCHECK(Token::IsTemplate(scanner()->current_token()));
1085 if (!scanner()->has_invalid_template_escape()) return true;
1086
1087 // Handle error case(s)
1088 if (should_throw) {
1089 impl()->ReportMessageAt(scanner()->invalid_template_escape_location(),
1090 scanner()->invalid_template_escape_message());
1091 }
1093 return should_throw;
1094 }
1095
1097 void ClassifyParameter(IdentifierT parameter, int beg_pos, int end_pos);
1099 int position, ExpressionT parameter);
1100
1101 // Checking the name of a function literal. This has to be done after parsing
1102 // the function, since the function can declare itself strict.
1104 FunctionNameValidity function_name_validity,
1105 const Scanner::Location& function_name_loc) {
1106 if (impl()->IsNull(function_name)) return;
1107 if (function_name_validity == kSkipFunctionNameCheck) return;
1108 // The function name needs to be checked in strict mode.
1109 if (is_sloppy(language_mode)) return;
1110
1111 if (impl()->IsEvalOrArguments(function_name)) {
1112 impl()->ReportMessageAt(function_name_loc,
1113 MessageTemplate::kStrictEvalArguments);
1114 return;
1115 }
1116 if (function_name_validity == kFunctionNameIsStrictReserved) {
1117 impl()->ReportMessageAt(function_name_loc,
1118 MessageTemplate::kUnexpectedStrictReserved);
1119 return;
1120 }
1121 }
1122
1123 typename Types::Factory* factory() { return &ast_node_factory_; }
1124
1126 return scope()->GetReceiverScope();
1127 }
1130 LanguageMode old = scope()->language_mode();
1131 impl()->SetLanguageMode(scope(), old > mode ? old : mode);
1132 }
1133 bool is_generator() const {
1135 }
1136 bool is_async_function() const {
1138 }
1139 bool is_async_generator() const {
1141 }
1142 bool is_resumable() const {
1144 }
1145 bool is_await_allowed() const {
1147 }
1149 return flags().is_module() ||
1151 }
1153 // 'await' is always disallowed as an identifier in module contexts. Callers
1154 // should short-circuit the module case instead of calling this.
1155 //
1156 // There is one special case: direct eval inside a module. In that case,
1157 // even though the eval script itself is parsed as a Script (not a Module,
1158 // i.e. flags().is_module() is false), thus allowing await as an identifier
1159 // by default, the immediate outer scope is a module scope.
1160 DCHECK(!IsModule(kind) ||
1161 (flags().is_eval() && function_state_->scope() == original_scope_ &&
1163 return IsAsyncFunction(kind) ||
1165 }
1166 bool is_using_allowed() const {
1167 // UsingDeclaration and AwaitUsingDeclaration are Syntax Errors if the goal
1168 // symbol is Script. UsingDeclaration and AwaitUsingDeclaration are not
1169 // contained, either directly or indirectly, within a Block, CaseBlock,
1170 // ForStatement, ForInOfStatement, FunctionBody, GeneratorBody,
1171 // AsyncGeneratorBody, AsyncFunctionBody, ClassStaticBlockBody, or
1172 // ClassBody. Unless the current scope's ScopeType is ScriptScope, the
1173 // current position is directly or indirectly within one of the productions
1174 // listed above since they open a new scope.
1175 return ((scope()->scope_type() != SCRIPT_SCOPE &&
1176 scope()->scope_type() != EVAL_SCOPE) ||
1177 scope()->scope_type() == REPL_MODE_SCOPE);
1178 }
1179 bool IsNextUsingKeyword(Token::Value token_after_using, bool is_await_using) {
1180 // using and await using declarations in for-of statements must be followed
1181 // by a non-pattern ForBinding. In the case of synchronous `using`, `of` is
1182 // disallowed as well with a negative lookahead.
1183 //
1184 // `of`: for ( [lookahead ≠ using of] ForDeclaration[?Yield, ?Await, +Using]
1185 // of AssignmentExpression[+In, ?Yield, ?Await] )
1186 //
1187 // If `using` is not considered a keyword, it is parsed as an identifier.
1188 if (v8_flags.js_explicit_resource_management) {
1189 switch (token_after_using) {
1190 case Token::kIdentifier:
1191 case Token::kStatic:
1192 case Token::kLet:
1193 case Token::kYield:
1194 case Token::kAwait:
1195 case Token::kGet:
1196 case Token::kSet:
1197 case Token::kUsing:
1198 case Token::kAccessor:
1199 case Token::kAsync:
1200 return true;
1201 case Token::kOf:
1202 return is_await_using;
1203 case Token::kFutureStrictReservedWord:
1204 case Token::kEscapedStrictReservedWord:
1205 return is_sloppy(language_mode());
1206 default:
1207 return false;
1208 }
1209 } else {
1210 return false;
1211 }
1212 }
1214 // ForDeclaration[Yield, Await, Using] : ...
1215 // [+Using] using [no LineTerminator here] ForBinding[?Yield, ?Await,
1216 // ~Pattern]
1217 // [+Using, +Await] await [no LineTerminator here] using [no
1218 // LineTerminator here] ForBinding[?Yield, +Await, ~Pattern]
1219 return ((peek() == Token::kUsing &&
1220 !scanner()->HasLineTerminatorAfterNext() &&
1221 IsNextUsingKeyword(PeekAhead(), /* is_await_using */ false)) ||
1222 (is_await_allowed() && peek() == Token::kAwait &&
1223 !scanner()->HasLineTerminatorAfterNext() &&
1224 PeekAhead() == Token::kUsing &&
1225 !scanner()->HasLineTerminatorAfterNextNext() &&
1226 IsNextUsingKeyword(PeekAheadAhead(), /* is_await_using */ true)));
1227 }
1234
1235 // Report syntax errors.
1236 template <typename... Ts>
1237 V8_NOINLINE void ReportMessage(MessageTemplate message, const Ts&... args) {
1238 ReportMessageAt(scanner()->location(), message, args...);
1239 }
1240
1241 template <typename... Ts>
1243 MessageTemplate message, const Ts&... args) {
1244 impl()->pending_error_handler()->ReportMessageAt(
1245 source_location.beg_pos, source_location.end_pos, message, args...);
1247 }
1248
1250 MessageTemplate message,
1251 const PreParserIdentifier& arg0) {
1252 ReportMessageAt(source_location, message,
1253 impl()->PreParserIdentifierToAstRawString(arg0));
1254 }
1255
1257
1259 const FormalParametersT& parameters,
1260 bool allow_duplicates) {
1261 if (!allow_duplicates) parameters.ValidateDuplicate(impl());
1262 if (is_strict(language_mode)) parameters.ValidateStrictMode(impl());
1263 }
1264
1265 // Needs to be called if the reference needs to be available from the current
1266 // point. It causes the receiver to be context allocated if necessary.
1267 // Returns the receiver variable that we're referencing.
1269 Scope* scope = this->scope();
1270 DeclarationScope* closure_scope = scope->GetClosureScope();
1271 if (closure_scope->is_reparsed()) return;
1272 DeclarationScope* receiver_scope = closure_scope->GetReceiverScope();
1273 Variable* var = receiver_scope->receiver();
1274 var->set_is_used();
1275 if (closure_scope == receiver_scope) {
1276 // It's possible that we're parsing the head of an arrow function, in
1277 // which case we haven't realized yet that closure_scope !=
1278 // receiver_scope. Mark through the ExpressionScope for now.
1279 expression_scope()->RecordThisUse();
1280 } else {
1281 closure_scope->set_has_this_reference();
1283 }
1284 }
1285
1287
1288 // Similar logic to ParseAndClassifyIdentifier but the identifier is
1289 // already parsed in prop_info. Returns false if this is an invalid
1290 // identifier or an invalid use of the "arguments" keyword.
1292 ParsePropertyInfo* prop_info);
1293 // Parses an identifier or a strict mode future reserved word. Allows passing
1294 // in function_kind for the case of parsing the identifier in a function
1295 // expression, where the relevant "function_kind" bit is of the function being
1296 // parsed, not the containing function.
1301 // Same as above but additionally disallows 'eval' and 'arguments' in strict
1302 // mode.
1304
1305 // This method should be used to ambiguously parse property names that can
1306 // become destructuring identifiers.
1308
1310
1316 RegExpError* regexp_error);
1318
1321
1322 // Use when parsing an expression that is known to not be a pattern or part of
1323 // a pattern.
1327
1328 // These methods do not wrap the parsing of the expression inside a new
1329 // expression_scope; they use the outer expression_scope instead. They should
1330 // be used whenever we're parsing something with the "cover" grammar that
1331 // recognizes both patterns and non-patterns (which roughly corresponds to
1332 // what's inside the parentheses generated by the symbol
1333 // "CoverParenthesizedExpressionAndArrowParameterList" in the ES 2017
1334 // specification).
1338 int lhs_beg_pos, ExpressionT expression);
1340
1343 int seen_variables);
1344
1346
1351
1352 ExpressionT ParseProperty(ParsePropertyInfo* prop_info);
1354 V8_INLINE bool VerifyCanHaveAutoAccessorOrThrow(ParsePropertyInfo* prop_info,
1355 ExpressionT name_expression,
1356 int name_token_position);
1358 ParsePropertyInfo* prop_info, ExpressionT* name_expression);
1360 ParsePropertyInfo* prop_info, ExpressionT* name_expression,
1361 int* name_token_position);
1363 ClassInfo* class_info, ParsePropertyInfo* prop_info, bool has_extends);
1364 void CheckClassFieldName(IdentifierT name, bool is_static);
1366 ParseFunctionFlags flags, bool is_static,
1367 bool* has_seen_constructor);
1368 ExpressionT ParseMemberInitializer(ClassInfo* class_info, int beg_pos,
1369 int info_id, bool is_static);
1370 BlockT ParseClassStaticBlock(ClassInfo* class_info);
1372 ParsePropertyInfo* prop_info, bool* has_seen_proto);
1374 ExpressionListT* args, bool* has_spread,
1376
1380 int condition_pos);
1391 int lhs_beg_pos);
1403
1405 int function_literal_id,
1406 bool could_be_immediately_invoked);
1410 Scanner::Location class_name_location,
1411 bool name_is_strict_reserved,
1412 int class_token_pos);
1413 void ParseClassLiteralBody(ClassInfo& class_info, IdentifierT name,
1414 int class_token_pos, Token::Value end_token);
1415
1420
1423 void CheckArityRestrictions(int param_count, FunctionKind function_type,
1424 bool has_rest, int formals_start_pos,
1425 int formals_end_pos);
1426
1428 DeclarationParsingResult* parsing_result,
1431 ZonePtrList<const AstRawString>* names, bool default_export);
1434 bool default_export);
1437 bool default_export);
1439 bool default_export);
1441
1442 // Whether we're parsing a single-expression arrow function or something else.
1444 // Consumes the ending }.
1446 int pos, const FormalParametersT& parameters,
1448 FunctionSyntaxKind function_syntax_kind,
1449 FunctionBodyType body_type);
1450
1451 // Check if the scope has conflicting var/let declarations from different
1452 // scopes. This covers for example
1453 //
1454 // function f() { { { var x; } let x; } }
1455 // function g() { { var x; let x; } }
1456 //
1457 // The var declarations are hoisted to the function scope, but originate from
1458 // a scope where the name has also been let bound or the var declaration is
1459 // hoisted over such a scope.
1461 bool allowed_catch_binding_var_redeclaration = false;
1462 Declaration* decl = scope->CheckConflictingVarDeclarations(
1463 &allowed_catch_binding_var_redeclaration);
1464 if (allowed_catch_binding_var_redeclaration) {
1466 }
1467 if (decl != nullptr) {
1468 // In ES6, conflicting variable bindings are early errors.
1469 const AstRawString* name = decl->var()->raw_name();
1470 int position = decl->position();
1471 Scanner::Location location =
1475 impl()->ReportMessageAt(location, MessageTemplate::kVarRedeclaration,
1476 name);
1477 }
1478 }
1479
1480 // TODO(nikolaos, marja): The first argument should not really be passed
1481 // by value. The method is expected to add the parsed statements to the
1482 // list. This works because in the case of the parser, StatementListT is
1483 // a pointer whereas the preparser does not really modify the body.
1485 Token::Value end_token);
1487
1495 AllowLabelledFunctionStatement allow_function);
1497 Scope* block_scope);
1499
1500 // Parse a SubStatement in strict mode, or with an extra block scope in
1501 // sloppy mode to handle
1502 // ES#sec-functiondeclarations-in-ifstatement-statement-clauses
1504
1507
1508 // Magical syntax support.
1510
1512
1516 AllowLabelledFunctionStatement allow_function);
1532 int stmt_pos, ForInfo* for_info, ZonePtrList<const AstRawString>* labels,
1533 ZonePtrList<const AstRawString>* own_labels, Scope* inner_block_scope);
1535 int stmt_pos, ExpressionT expression, int lhs_beg_pos, int lhs_end_pos,
1536 ForInfo* for_info, ZonePtrList<const AstRawString>* labels,
1538
1539 // Parse a C-style for loop: 'for (<init>; <cond>; <next>) { ... }'
1540 // "for (<init>;" is assumed to have been parser already.
1542 int stmt_pos, ZonePtrList<const AstRawString>* labels,
1544 StatementT* next, StatementT* body);
1545 // Same as the above, but handles those cases where <init> is a
1546 // lexical variable declaration.
1548 int stmt_pos, StatementT init, ForInfo* for_info,
1554
1556 return identifier == ast_value_factory()->let_string();
1557 }
1558
1560
1561 // Checks if the expression is a valid reference expression (e.g., on the
1562 // left-hand side of assignments). Although ruled out by ECMA as early errors,
1563 // we allow calls for web compatibility and rewrite them to a runtime throw.
1564 // Modern language features can be exempted from this hack by passing
1565 // early_error = true.
1567 int beg_pos, int end_pos,
1568 MessageTemplate message,
1569 bool early_error);
1570
1572
1574 if (!impl()->IsIdentifier(expression)) return false;
1575 if (is_strict(language_mode()) &&
1576 impl()->IsEvalOrArguments(impl()->AsIdentifier(expression))) {
1577 return false;
1578 }
1579 return true;
1580 }
1581
1583
1585 ParseFunctionFlags flags) {
1586 static const FunctionKind kFunctionKinds[][2][2] = {
1587 {
1588 // SubFunctionKind::kNormalFunction
1589 {// is_generator=false
1591 {// is_generator=true
1594 },
1595 {
1596 // SubFunctionKind::kNonStaticMethod
1597 {// is_generator=false
1599 {// is_generator=true
1602 },
1603 {
1604 // SubFunctionKind::kStaticMethod
1605 {// is_generator=false
1608 {// is_generator=true
1611 }};
1612 return kFunctionKinds[sub_function_kind]
1613 [(flags & ParseFunctionFlag::kIsGenerator) != 0]
1614 [(flags & ParseFunctionFlag::kIsAsync) != 0];
1615 }
1616
1620
1621 inline FunctionKind MethodKindFor(bool is_static, ParseFunctionFlags flags) {
1624 flags);
1625 }
1626
1627 // Keep track of eval() calls since they disable all local variable
1628 // optimizations. This checks if expression is an eval call, and if yes,
1629 // forwards the information to scope.
1630 bool CheckPossibleEvalCall(ExpressionT expression, bool is_optional_call,
1631 Scope* scope) {
1632 if (impl()->IsIdentifier(expression) &&
1633 impl()->IsEval(impl()->AsIdentifier(expression)) && !is_optional_call) {
1636 return true;
1637 }
1638 return false;
1639 }
1640
1641 // Convenience method which determines the type of return statement to emit
1642 // depending on the current function type.
1644 ExpressionT expr, int pos,
1646 if (impl()->IsNull(expr)) {
1647 expr = factory()->NewUndefinedLiteral(kNoSourcePosition);
1648 } else if (is_async_generator()) {
1649 // In async generators, if there is an explicit operand to the return
1650 // statement, await the operand.
1651 expr = factory()->NewAwait(expr, kNoSourcePosition);
1653 }
1654 if (is_async_function()) {
1655 return factory()->NewAsyncReturnStatement(expr, pos, end_pos);
1656 }
1657 return factory()->NewReturnStatement(expr, pos, end_pos);
1658 }
1659
1661 return scope()->AsModuleScope()->module();
1662 }
1663 Scope* scope() const { return scope_; }
1664
1665 // Stack of expression expression_scopes.
1666 // The top of the stack is always pointed to by expression_scope().
1671
1673 return expression_scope_ != nullptr &&
1674 expression_scope_->has_possible_arrow_parameter_in_scope_chain();
1675 }
1676
1678 public:
1679 AcceptINScope(ParserBase* parser, bool accept_IN)
1680 : parser_(parser), previous_accept_IN_(parser->accept_IN_) {
1681 parser_->accept_IN_ = accept_IN;
1682 }
1683
1684 ~AcceptINScope() { parser_->accept_IN_ = previous_accept_IN_; }
1685
1686 private:
1689 };
1690
1692 public:
1693 ParameterParsingScope(Impl* parser, FormalParametersT* parameters)
1694 : parser_(parser), parent_parameters_(parser_->parameters_) {
1695 parser_->parameters_ = parameters;
1696 }
1697
1698 ~ParameterParsingScope() { parser_->parameters_ = parent_parameters_; }
1699
1700 private:
1701 Impl* parser_;
1703 };
1704
1706 public:
1707 explicit FunctionParsingScope(Impl* parser)
1708 : parser_(parser), expression_scope_(parser_->expression_scope_) {
1709 parser_->expression_scope_ = nullptr;
1710 }
1711
1712 ~FunctionParsingScope() { parser_->expression_scope_ = expression_scope_; }
1713
1714 private:
1715 Impl* parser_;
1717 };
1718
1719 std::vector<void*>* pointer_buffer() { return &pointer_buffer_; }
1720 std::vector<std::pair<VariableProxy*, int>>* variable_buffer() {
1721 return &variable_buffer_;
1722 }
1723
1724 // Parser base's protected field members.
1725
1726 Scope* scope_; // Scope stack.
1727 // Stack of scopes for object literals we're currently parsing.
1729 Scope* original_scope_; // The top scope for the current parsing item.
1730 FunctionState* function_state_; // Function state stack.
1733 typename Types::Factory ast_node_factory_;
1737 uintptr_t stack_limit_;
1739
1740 // Parser base's private field members.
1742
1743 private:
1746
1747 std::vector<void*> pointer_buffer_;
1748 std::vector<std::pair<VariableProxy*, int>> variable_buffer_;
1749
1751
1754
1756
1760
1761 // This struct is used to move information about the next arrow function from
1762 // the place where the arrow head was parsed to where the body will be parsed.
1763 // Nothing can be parsed between the head and the body, so it will be consumed
1764 // immediately after it's produced.
1765 // Preallocating the struct as part of the parser minimizes the cost of
1766 // supporting arrow functions on non-arrow expressions.
1774
1775 bool HasInitialState() const { return scope == nullptr; }
1776
1777 void Reset() {
1778 scope = nullptr;
1783 }
1784
1785 // Tracks strict-mode parameter violations of sloppy-mode arrow heads in
1786 // case the function ends up becoming strict mode. Only one global place to
1787 // track this is necessary since arrow functions with none-simple parameters
1788 // cannot become strict-mode later on.
1793 };
1794
1797
1798 // The position of the token following the start parenthesis in the production
1799 // PrimaryExpression :: '(' Expression ')'
1801
1802 bool accept_IN_ = true;
1804};
1805
1806template <typename Impl>
1808 FunctionState** function_state_stack, Scope** scope_stack,
1809 DeclarationScope* scope)
1810 : BlockState(scope_stack, scope),
1811 expected_property_count_(0),
1812 suspend_count_(0),
1813 function_state_stack_(function_state_stack),
1814 outer_function_state_(*function_state_stack),
1815 scope_(scope),
1816 dont_optimize_reason_(BailoutReason::kNoReason),
1817 next_function_is_likely_called_(false),
1818 previous_function_was_likely_called_(false),
1819 contains_function_or_eval_(false) {
1820 *function_state_stack = this;
1825 }
1826}
1827
1828template <typename Impl>
1830 *function_state_stack_ = outer_function_state_;
1831}
1832
1833template <typename Impl>
1835 return impl()->ReportUnexpectedTokenAt(scanner_->location(), token);
1836}
1837
1838template <typename Impl>
1840 Token::Value next, ParsePropertyInfo* prop_info) {
1841 // Updates made here must be reflected on ParseAndClassifyIdentifier.
1842 if (V8_LIKELY(base::IsInRange(next, Token::kIdentifier, Token::kAsync))) {
1843 if (V8_UNLIKELY(impl()->IsArguments(prop_info->name) &&
1844 scope()->ShouldBanArguments())) {
1846 MessageTemplate::kArgumentsDisallowedInInitializerAndStaticBlock);
1847 return false;
1848 }
1849 return true;
1850 }
1851
1855 return false;
1856 }
1857
1858 DCHECK(!prop_info->is_computed_name);
1859
1860 if (next == Token::kAwait) {
1862 expression_scope()->RecordAsyncArrowParametersError(
1863 scanner()->peek_location(), MessageTemplate::kAwaitBindingIdentifier);
1864 }
1865 return true;
1866}
1867
1868template <typename Impl>
1871 // Updates made here must be reflected on ClassifyPropertyIdentifier.
1872 DCHECK_EQ(scanner()->current_token(), next);
1873 if (V8_LIKELY(base::IsInRange(next, Token::kIdentifier, Token::kAsync))) {
1874 IdentifierT name = impl()->GetIdentifier();
1875 if (V8_UNLIKELY(impl()->IsArguments(name) &&
1876 scope()->ShouldBanArguments())) {
1878 MessageTemplate::kArgumentsDisallowedInInitializerAndStaticBlock);
1879 return impl()->EmptyIdentifierString();
1880 }
1881 return name;
1882 }
1883
1887 return impl()->EmptyIdentifierString();
1888 }
1889
1890 if (next == Token::kAwait) {
1891 expression_scope()->RecordAsyncArrowParametersError(
1892 scanner()->location(), MessageTemplate::kAwaitBindingIdentifier);
1893 return impl()->GetIdentifier();
1894 }
1895
1897 expression_scope()->RecordStrictModeParameterError(
1898 scanner()->location(), MessageTemplate::kUnexpectedStrictReserved);
1899 return impl()->GetIdentifier();
1900}
1901
1902template <class Impl>
1904 FunctionKind function_kind) {
1905 Token::Value next = Next();
1906
1908 next, language_mode(), IsGeneratorFunction(function_kind),
1909 flags().is_module() ||
1910 IsAwaitAsIdentifierDisallowed(function_kind))) {
1912 return impl()->EmptyIdentifierString();
1913 }
1914
1915 return impl()->GetIdentifier();
1916}
1917
1918template <typename Impl>
1922
1923 if (is_strict(language_mode()) &&
1924 V8_UNLIKELY(impl()->IsEvalOrArguments(result))) {
1925 impl()->ReportMessageAt(scanner()->location(),
1926 MessageTemplate::kStrictEvalArguments);
1927 }
1928
1929 return result;
1930}
1931
1932template <typename Impl>
1934 Token::Value next = Next();
1935 if (V8_LIKELY(Token::IsPropertyName(next))) {
1936 if (peek() == Token::kColon) return impl()->GetSymbol();
1937 return impl()->GetIdentifier();
1938 }
1939
1941 return impl()->EmptyIdentifierString();
1942}
1943
1944template <typename Impl>
1946 if (flags().parsing_while_debugging() != ParsingWhileDebugging::kYes &&
1947 !flags().is_repl_mode()) {
1948 return false;
1949 }
1950 Scope* current_scope = scope();
1951 while (current_scope != nullptr) {
1952 switch (current_scope->scope_type()) {
1953 case CLASS_SCOPE:
1954 case CATCH_SCOPE:
1955 case BLOCK_SCOPE:
1956 case WITH_SCOPE:
1957 case SHADOW_REALM_SCOPE:
1958 return false;
1959 // Top-level scopes.
1960 case REPL_MODE_SCOPE:
1961 case SCRIPT_SCOPE:
1962 case MODULE_SCOPE:
1963 return true;
1964 // Top-level wrapper function scopes.
1965 case FUNCTION_SCOPE:
1967 // Used by debug-evaluate. If the outer scope is top-level,
1968 // extraordinary private name access is allowed.
1969 case EVAL_SCOPE:
1970 current_scope = current_scope->outer_scope();
1971 DCHECK_NOT_NULL(current_scope);
1972 break;
1973 }
1974 }
1975 UNREACHABLE();
1976}
1977
1978template <typename Impl>
1981 int pos = position();
1984 Token::Value next = Next();
1985 if (V8_LIKELY(Token::IsPropertyName(next))) {
1986 name = impl()->GetSymbol();
1987 key = factory()->NewStringLiteral(name, pos);
1988 } else if (next == Token::kPrivateName) {
1989 // In the case of a top level function, we completely skip
1990 // analysing it's scope, meaning, we don't have a chance to
1991 // resolve private names and find that they are not enclosed in a
1992 // class body.
1993 //
1994 // Here, we check if this is a new private name reference in a top
1995 // level function and throw an error if so.
1996 PrivateNameScopeIterator private_name_scope_iter(scope());
1997 // Parse the identifier so that we can display it in the error message
1998 name = impl()->GetIdentifier();
1999 // In debug-evaluate, we relax the private name resolution to enable
2000 // evaluation of obj.#member outside the class bodies in top-level scopes.
2001 if (private_name_scope_iter.Done() &&
2003 impl()->ReportMessageAt(Scanner::Location(pos, pos + 1),
2004 MessageTemplate::kInvalidPrivateFieldResolution,
2005 impl()->GetRawNameFromIdentifier(name));
2006 return impl()->FailureExpression();
2007 }
2008 key =
2009 impl()->ExpressionFromPrivateName(&private_name_scope_iter, name, pos);
2010 } else {
2012 return impl()->FailureExpression();
2013 }
2014 impl()->PushLiteralName(name);
2015 return key;
2016}
2017
2018template <typename Impl>
2022
2023template <typename Impl>
2025 RegExpFlags flags,
2026 RegExpError* regexp_error) {
2027 // TODO(jgruber): If already validated in the preparser, skip validation in
2028 // the parser.
2030 ZoneScope zone_scope(zone()); // Free regexp parser memory after use.
2031 const unsigned char* d = pattern->raw_data();
2032 if (pattern->is_one_byte()) {
2034 static_cast<const uint8_t*>(d),
2035 pattern->length(), flags, regexp_error, no_gc);
2036 } else {
2038 reinterpret_cast<const uint16_t*>(d),
2039 pattern->length(), flags, regexp_error, no_gc);
2040 }
2041}
2042
2043template <typename Impl>
2045 int pos = peek_position();
2046 if (!scanner()->ScanRegExpPattern()) {
2047 Next();
2048 ReportMessage(MessageTemplate::kUnterminatedRegExp);
2049 return impl()->FailureExpression();
2050 }
2051
2053 std::optional<RegExpFlags> flags = scanner()->ScanRegExpFlags();
2054 const AstRawString* flags_as_ast_raw_string = GetNextSymbolForRegExpLiteral();
2055 if (!flags.has_value() || !ValidateRegExpFlags(flags.value())) {
2056 Next();
2057 ReportMessage(MessageTemplate::kMalformedRegExpFlags);
2058 return impl()->FailureExpression();
2059 }
2060 Next();
2061 RegExpError regexp_error;
2062 if (!ValidateRegExpLiteral(pattern, flags.value(), &regexp_error)) {
2064 ReportMessage(MessageTemplate::kMalformedRegExp, pattern,
2065 flags_as_ast_raw_string, RegExpErrorString(regexp_error));
2066 return impl()->FailureExpression();
2067 }
2068 return factory()->NewRegExpLiteral(pattern, flags.value(), pos);
2069}
2070
2071template <typename Impl>
2073 // Pattern ::
2074 // Identifier
2075 // ArrayLiteral
2076 // ObjectLiteral
2077
2078 int beg_pos = peek_position();
2079 Token::Value token = peek();
2081
2082 if (Token::IsAnyIdentifier(token)) {
2085 impl()->IsEvalOrArguments(name))) {
2086 impl()->ReportMessageAt(scanner()->location(),
2087 MessageTemplate::kStrictEvalArguments);
2088 return impl()->FailureExpression();
2089 }
2090 return impl()->ExpressionFromIdentifier(name, beg_pos);
2091 }
2092
2094
2095 if (token == Token::kLeftBracket) {
2097 } else if (token == Token::kLeftBrace) {
2099 } else {
2101 return impl()->FailureExpression();
2102 }
2103
2104 return result;
2105}
2106
2107template <typename Impl>
2111
2112 // PrimaryExpression ::
2113 // 'this'
2114 // 'null'
2115 // 'true'
2116 // 'false'
2117 // Identifier
2118 // Number
2119 // String
2120 // ArrayLiteral
2121 // ObjectLiteral
2122 // RegExpLiteral
2123 // ClassLiteral
2124 // '(' Expression ')'
2125 // TemplateLiteral
2126 // do Block
2127 // AsyncFunctionLiteral
2128
2129 int beg_pos = peek_position();
2130 Token::Value token = peek();
2131
2132 if (Token::IsAnyIdentifier(token)) {
2133 Consume(token);
2134
2136
2137 if (V8_UNLIKELY(token == Token::kAsync &&
2138 !scanner()->HasLineTerminatorBeforeNext() &&
2139 !scanner()->literal_contains_escapes())) {
2140 // async function ...
2141 if (peek() == Token::kFunction) return ParseAsyncFunctionLiteral();
2142
2143 // async Identifier => ...
2144 if (peek_any_identifier() && PeekAhead() == Token::kArrow) {
2145 token = Next();
2146 beg_pos = position();
2148 }
2149 }
2150
2151 if (V8_UNLIKELY(peek() == Token::kArrow)) {
2152 ArrowHeadParsingScope parsing_scope(impl(), kind, PeekNextInfoId());
2154 ClassifyParameter(name, beg_pos, end_position());
2156 impl()->ExpressionFromIdentifier(name, beg_pos, InferName::kNo);
2157 parsing_scope.SetInitializers(0, peek_position());
2158 next_arrow_function_info_.scope = parsing_scope.ValidateAndCreateScope();
2160 parsing_scope.function_literal_id();
2163 return result;
2164 }
2165
2167 return impl()->ExpressionFromIdentifier(name, beg_pos);
2168 }
2169
2170 if (Token::IsLiteral(token)) {
2171 return impl()->ExpressionFromLiteral(Next(), beg_pos);
2172 }
2173
2174 switch (token) {
2175 case Token::kNew:
2177
2178 case Token::kThis: {
2179 Consume(Token::kThis);
2180 // Not necessary for this.x, this.x(), this?.x and this?.x() to
2181 // store the source position for ThisExpression.
2182 if (peek() == Token::kPeriod || peek() == Token::kQuestionPeriod) {
2183 return impl()->ThisExpression();
2184 }
2185 return impl()->NewThisExpression(beg_pos);
2186 }
2187
2188 case Token::kAssignDiv:
2189 case Token::kDiv:
2190 return ParseRegExpLiteral();
2191
2192 case Token::kFunction:
2193 return ParseFunctionExpression();
2194
2195 case Token::kSuper: {
2196 return ParseSuperExpression();
2197 }
2198 case Token::kImport:
2199 return ParseImportExpressions();
2200
2201 case Token::kLeftBracket:
2202 return ParseArrayLiteral();
2203
2204 case Token::kLeftBrace:
2205 return ParseObjectLiteral();
2206
2207 case Token::kLeftParen: {
2208 Consume(Token::kLeftParen);
2209
2210 if (Check(Token::kRightParen)) {
2211 // clear last next_arrow_function_info tracked strict parameters error.
2213
2214 // ()=>x. The continuation that consumes the => is in
2215 // ParseAssignmentExpressionCoverGrammar.
2216 if (peek() != Token::kArrow) ReportUnexpectedToken(Token::kRightParen);
2222 return factory()->NewEmptyParentheses(beg_pos);
2223 }
2224 Scope::Snapshot scope_snapshot(scope());
2225 bool could_be_immediately_invoked_arrow_function =
2228 PeekNextInfoId());
2230 peek_position();
2231 // Heuristically try to detect immediately called functions before
2232 // seeing the call parentheses.
2233 if (peek() == Token::kFunction ||
2234 (peek() == Token::kAsync && PeekAhead() == Token::kFunction)) {
2236 }
2237 AcceptINScope scope(this, true);
2239 expr->mark_parenthesized();
2240 Expect(Token::kRightParen);
2241
2242 if (peek() == Token::kArrow) {
2243 next_arrow_function_info_.scope = maybe_arrow.ValidateAndCreateScope();
2245 maybe_arrow.function_literal_id();
2247 could_be_immediately_invoked_arrow_function;
2249 } else {
2250 maybe_arrow.ValidateExpression();
2251 }
2252
2253 return expr;
2254 }
2255
2256 case Token::kClass: {
2257 return ParseClassExpression(scope());
2258 }
2259
2260 case Token::kTemplateSpan:
2261 case Token::kTemplateTail:
2262 return ParseTemplateLiteral(impl()->NullExpression(), beg_pos, false);
2263
2264 case Token::kMod:
2265 if (flags().allow_natives_syntax() || impl()->ParsingExtension()) {
2266 return ParseV8Intrinsic();
2267 }
2268 break;
2269
2270 default:
2271 break;
2272 }
2273
2275 return impl()->FailureExpression();
2276}
2277
2278template <typename Impl>
2286
2287template <typename Impl>
2295
2296template <typename Impl>
2304
2305template <typename Impl>
2308 // Expression ::
2309 // AssignmentExpression
2310 // Expression ',' AssignmentExpression
2311
2314 AccumulationScope accumulation_scope(expression_scope());
2315 int variable_index = 0;
2316 while (true) {
2317 if (V8_UNLIKELY(peek() == Token::kEllipsis)) {
2318 return ParseArrowParametersWithRest(&list, &accumulation_scope,
2319 variable_index);
2320 }
2321
2322 int expr_pos = peek_position();
2324
2325 ClassifyArrowParameter(&accumulation_scope, expr_pos, expression);
2326 list.Add(expression);
2327
2328 variable_index =
2329 expression_scope()->SetInitializers(variable_index, peek_position());
2330
2331 if (!Check(Token::kComma)) break;
2332
2333 if (peek() == Token::kRightParen && PeekAhead() == Token::kArrow) {
2334 // a trailing comma is allowed at the end of an arrow parameter list
2335 break;
2336 }
2337
2338 // Pass on the 'set_next_function_is_likely_called' flag if we have
2339 // several function literals separated by comma.
2340 if (peek() == Token::kFunction &&
2343 }
2344 }
2345
2346 // Return the single element if the list is empty. We need to do this because
2347 // callers of this function care about the type of the result if there was
2348 // only a single assignment expression. The preparser would lose this
2349 // information otherwise.
2350 if (list.length() == 1) return expression;
2351 return impl()->ExpressionListToExpression(list);
2352}
2353
2354template <typename Impl>
2357 typename ParserBase<Impl>::ExpressionListT* list,
2358 AccumulationScope* accumulation_scope, int seen_variables) {
2359 Consume(Token::kEllipsis);
2360
2361 Scanner::Location ellipsis = scanner()->location();
2362 int pattern_pos = peek_position();
2364 ClassifyArrowParameter(accumulation_scope, pattern_pos, pattern);
2365
2366 expression_scope()->RecordNonSimpleParameter();
2367
2368 if (V8_UNLIKELY(peek() == Token::kAssign)) {
2369 ReportMessage(MessageTemplate::kRestDefaultInitializer);
2370 return impl()->FailureExpression();
2371 }
2372
2373 ExpressionT spread =
2374 factory()->NewSpread(pattern, ellipsis.beg_pos, pattern_pos);
2375 if (V8_UNLIKELY(peek() == Token::kComma)) {
2376 ReportMessage(MessageTemplate::kParamAfterRest);
2377 return impl()->FailureExpression();
2378 }
2379
2380 expression_scope()->SetInitializers(seen_variables, peek_position());
2381
2382 // 'x, y, ...z' in CoverParenthesizedExpressionAndArrowParameterList only
2383 // as the formal parameters of'(x, y, ...z) => foo', and is not itself a
2384 // valid expression.
2385 if (peek() != Token::kRightParen || PeekAhead() != Token::kArrow) {
2386 impl()->ReportUnexpectedTokenAt(ellipsis, Token::kEllipsis);
2387 return impl()->FailureExpression();
2388 }
2389
2390 list->Add(spread);
2391 return impl()->ExpressionListToExpression(*list);
2392}
2393
2394template <typename Impl>
2396 // ArrayLiteral ::
2397 // '[' Expression? (',' Expression?)* ']'
2398
2399 int pos = peek_position();
2401 int first_spread_index = -1;
2402 Consume(Token::kLeftBracket);
2403
2404 AccumulationScope accumulation_scope(expression_scope());
2405
2406 while (!Check(Token::kRightBracket)) {
2407 ExpressionT elem;
2408 if (peek() == Token::kComma) {
2409 elem = factory()->NewTheHoleLiteral();
2410 } else if (Check(Token::kEllipsis)) {
2411 int start_pos = position();
2412 int expr_pos = peek_position();
2413 AcceptINScope scope(this, true);
2414 ExpressionT argument =
2415 ParsePossibleDestructuringSubPattern(&accumulation_scope);
2416 elem = factory()->NewSpread(argument, start_pos, expr_pos);
2417
2418 if (first_spread_index < 0) {
2419 first_spread_index = values.length();
2420 }
2421
2422 if (argument->IsAssignment()) {
2423 expression_scope()->RecordPatternError(
2424 Scanner::Location(start_pos, end_position()),
2425 MessageTemplate::kInvalidDestructuringTarget);
2426 }
2427
2428 if (peek() == Token::kComma) {
2429 expression_scope()->RecordPatternError(
2430 Scanner::Location(start_pos, end_position()),
2431 MessageTemplate::kElementAfterRest);
2432 }
2433 } else {
2434 AcceptINScope scope(this, true);
2435 elem = ParsePossibleDestructuringSubPattern(&accumulation_scope);
2436 }
2437 values.Add(elem);
2438 if (peek() != Token::kRightBracket) {
2439 Expect(Token::kComma);
2440 if (elem->IsFailureExpression()) return elem;
2441 }
2442 }
2443
2444 return factory()->NewArrayLiteral(values, first_spread_index, pos);
2445}
2446
2447template <class Impl>
2449 ParsePropertyInfo* prop_info) {
2452 DCHECK(!prop_info->is_computed_name);
2453
2454 if (Check(Token::kAsync)) {
2455 Token::Value token = peek();
2456 if ((token != Token::kMul &&
2457 prop_info->ParsePropertyKindFromToken(token)) ||
2458 scanner()->HasLineTerminatorBeforeNext()) {
2459 prop_info->name = impl()->GetIdentifier();
2460 impl()->PushLiteralName(prop_info->name);
2461 return factory()->NewStringLiteral(prop_info->name, position());
2462 }
2463 if (V8_UNLIKELY(scanner()->literal_contains_escapes())) {
2464 impl()->ReportUnexpectedToken(Token::kEscapedKeyword);
2465 }
2467 prop_info->kind = ParsePropertyKind::kMethod;
2468 }
2469
2470 if (Check(Token::kMul)) {
2472 prop_info->kind = ParsePropertyKind::kMethod;
2473 }
2474
2475 if (prop_info->kind == ParsePropertyKind::kNotSet &&
2476 base::IsInRange(peek(), Token::kGet, Token::kSet)) {
2477 Token::Value token = Next();
2478 if (prop_info->ParsePropertyKindFromToken(peek())) {
2479 prop_info->name = impl()->GetIdentifier();
2480 impl()->PushLiteralName(prop_info->name);
2481 return factory()->NewStringLiteral(prop_info->name, position());
2482 }
2483 if (V8_UNLIKELY(scanner()->literal_contains_escapes())) {
2484 impl()->ReportUnexpectedToken(Token::kEscapedKeyword);
2485 }
2486 if (token == Token::kGet) {
2488 } else if (token == Token::kSet) {
2490 }
2491 }
2492
2493 int pos = peek_position();
2494
2495 // For non computed property names we normalize the name a bit:
2496 //
2497 // "12" -> 12
2498 // 12.3 -> "12.3"
2499 // 12.30 -> "12.3"
2500 // identifier -> "identifier"
2501 //
2502 // This is important because we use the property name as a key in a hash
2503 // table when we compute constant properties.
2504 bool is_array_index;
2505 uint32_t index;
2506 switch (peek()) {
2507 case Token::kPrivateName:
2508 prop_info->is_private = true;
2509 is_array_index = false;
2510 Consume(Token::kPrivateName);
2511 if (prop_info->kind == ParsePropertyKind::kNotSet) {
2512 prop_info->ParsePropertyKindFromToken(peek());
2513 }
2514 prop_info->name = impl()->GetIdentifier();
2515 if (V8_UNLIKELY(prop_info->position ==
2517 ReportUnexpectedToken(Token::kPrivateName);
2518 prop_info->kind = ParsePropertyKind::kNotSet;
2519 return impl()->FailureExpression();
2520 }
2521 break;
2522
2523 case Token::kString:
2524 Consume(Token::kString);
2525 prop_info->name = peek() == Token::kColon ? impl()->GetSymbol()
2526 : impl()->GetIdentifier();
2527 is_array_index = impl()->IsArrayIndex(prop_info->name, &index);
2528 break;
2529
2530 case Token::kSmi:
2531 Consume(Token::kSmi);
2532 index = scanner()->smi_value();
2533 is_array_index = true;
2534 // Token::kSmi were scanned from their canonical representation.
2535 prop_info->name = impl()->GetSymbol();
2536 break;
2537
2538 case Token::kNumber: {
2539 Consume(Token::kNumber);
2540 prop_info->name = impl()->GetNumberAsSymbol();
2541 is_array_index = impl()->IsArrayIndex(prop_info->name, &index);
2542 break;
2543 }
2544
2545 case Token::kBigInt: {
2546 Consume(Token::kBigInt);
2547 prop_info->name = impl()->GetBigIntAsSymbol();
2548 is_array_index = impl()->IsArrayIndex(prop_info->name, &index);
2549 break;
2550 }
2551
2552 case Token::kLeftBracket: {
2553 prop_info->name = impl()->NullIdentifier();
2554 prop_info->is_computed_name = true;
2555 Consume(Token::kLeftBracket);
2556 AcceptINScope scope(this, true);
2558 Expect(Token::kRightBracket);
2559 if (prop_info->kind == ParsePropertyKind::kNotSet) {
2560 prop_info->ParsePropertyKindFromToken(peek());
2561 }
2562 return expression;
2563 }
2564
2565 case Token::kEllipsis:
2566 if (prop_info->kind == ParsePropertyKind::kNotSet) {
2567 prop_info->name = impl()->NullIdentifier();
2568 Consume(Token::kEllipsis);
2569 AcceptINScope scope(this, true);
2570 int start_pos = peek_position();
2571 ExpressionT expression =
2573 prop_info->kind = ParsePropertyKind::kSpread;
2574
2575 if (!IsValidReferenceExpression(expression)) {
2576 expression_scope()->RecordDeclarationError(
2577 Scanner::Location(start_pos, end_position()),
2578 MessageTemplate::kInvalidRestBindingPattern);
2579 expression_scope()->RecordPatternError(
2580 Scanner::Location(start_pos, end_position()),
2581 MessageTemplate::kInvalidRestAssignmentPattern);
2582 }
2583
2584 if (peek() != Token::kRightBrace) {
2585 expression_scope()->RecordPatternError(
2586 scanner()->location(), MessageTemplate::kElementAfterRest);
2587 }
2588 return expression;
2589 }
2590 [[fallthrough]];
2591
2592 default:
2593 prop_info->name = ParsePropertyName();
2594 is_array_index = false;
2595 break;
2596 }
2597
2598 if (prop_info->kind == ParsePropertyKind::kNotSet) {
2599 prop_info->ParsePropertyKindFromToken(peek());
2600 }
2601 impl()->PushLiteralName(prop_info->name);
2602 return is_array_index ? factory()->NewNumberLiteral(index, pos)
2603 : factory()->NewStringLiteral(prop_info->name, pos);
2604}
2605
2606template <typename Impl>
2608 ParsePropertyInfo* prop_info, ExpressionT name_expression,
2609 int name_token_position) {
2610 switch (prop_info->kind) {
2616 return true;
2617 default:
2618 impl()->ReportUnexpectedTokenAt(
2619 Scanner::Location(name_token_position, name_expression->position()),
2620 Token::kAccessor);
2621 return false;
2622 }
2623}
2624
2625template <typename Impl>
2627 ParsePropertyInfo* prop_info, ExpressionT* name_expression) {
2628 if (peek() == Token::kLeftParen) {
2629 prop_info->kind = ParsePropertyKind::kMethod;
2630 prop_info->name = impl()->GetIdentifier();
2631 *name_expression = factory()->NewStringLiteral(prop_info->name, position());
2632 return true;
2633 }
2634 if (peek() == Token::kAssign || peek() == Token::kSemicolon ||
2635 peek() == Token::kRightBrace) {
2636 prop_info->name = impl()->GetIdentifier();
2637 *name_expression = factory()->NewStringLiteral(prop_info->name, position());
2638 return true;
2639 }
2640 return false;
2641}
2642
2643template <typename Impl>
2645 ParsePropertyInfo* prop_info, ExpressionT* name_expression,
2646 int* name_token_position) {
2647 // accessor [no LineTerminator here] ClassElementName[?Yield, ?Await]
2648 // Initializer[~In, ?Yield, ?Await]opt ;
2649 Consume(Token::kAccessor);
2650 *name_token_position = scanner()->peek_location().beg_pos;
2651 // If there is a line terminator here, it cannot be an auto-accessor.
2652 if (scanner()->HasLineTerminatorBeforeNext()) {
2654 prop_info->name = impl()->GetIdentifier();
2655 *name_expression = factory()->NewStringLiteral(prop_info->name, position());
2656 return true;
2657 }
2658 if (ParseCurrentSymbolAsClassFieldOrMethod(prop_info, name_expression)) {
2659 return true;
2660 }
2661 *name_expression = ParseProperty(prop_info);
2662 return VerifyCanHaveAutoAccessorOrThrow(prop_info, *name_expression,
2663 *name_token_position);
2664}
2665
2666template <typename Impl>
2669 ParsePropertyInfo* prop_info,
2670 bool has_extends) {
2671 DCHECK_NOT_NULL(class_info);
2673
2674 int next_info_id = PeekNextInfoId();
2675
2676 Token::Value name_token = peek();
2677 int property_beg_pos = peek_position();
2678 int name_token_position = property_beg_pos;
2679 ExpressionT name_expression;
2680 if (name_token == Token::kStatic) {
2681 Consume(Token::kStatic);
2682 name_token_position = scanner()->peek_location().beg_pos;
2683 if (!ParseCurrentSymbolAsClassFieldOrMethod(prop_info, &name_expression)) {
2684 prop_info->is_static = true;
2685 if (v8_flags.js_decorators && peek() == Token::kAccessor) {
2686 if (!ParseAccessorPropertyOrAutoAccessors(prop_info, &name_expression,
2687 &name_token_position)) {
2688 return impl()->NullLiteralProperty();
2689 }
2690 } else {
2691 name_expression = ParseProperty(prop_info);
2692 }
2693 }
2694 } else if (v8_flags.js_decorators && name_token == Token::kAccessor) {
2695 if (!ParseAccessorPropertyOrAutoAccessors(prop_info, &name_expression,
2696 &name_token_position)) {
2697 return impl()->NullLiteralProperty();
2698 }
2699 } else {
2700 name_expression = ParseProperty(prop_info);
2701 }
2702
2703 switch (prop_info->kind) {
2708 case ParsePropertyKind::kNotSet: { // This case is a name followed by a
2709 // name or other property. Here we have
2710 // to assume that's an uninitialized
2711 // field followed by a linebreak
2712 // followed by a property, with ASI
2713 // adding the semicolon. If not, there
2714 // will be a syntax error after parsing
2715 // the first name as an uninitialized
2716 // field.
2717 DCHECK_IMPLIES(prop_info->is_computed_name, !prop_info->is_private);
2718
2719 if (prop_info->is_computed_name) {
2720 if (!has_error() && next_info_id != PeekNextInfoId() &&
2721 !(prop_info->is_static ? class_info->has_static_elements()
2722 : class_info->has_instance_members())) {
2723 impl()->ReindexComputedMemberName(name_expression);
2724 }
2725 } else {
2726 CheckClassFieldName(prop_info->name, prop_info->is_static);
2727 }
2728
2730 class_info, property_beg_pos, next_info_id, prop_info->is_static);
2732
2735 // Declare the auto-accessor synthetic getter and setter here where we
2736 // have access to the property position in parsing and preparsing.
2737 result = impl()->NewClassLiteralPropertyWithAccessorInfo(
2738 scope()->AsClassScope(), class_info, prop_info->name,
2739 name_expression, value, prop_info->is_static,
2740 prop_info->is_computed_name, prop_info->is_private,
2741 property_beg_pos);
2742 } else {
2744 result = factory()->NewClassLiteralProperty(
2745 name_expression, value, ClassLiteralProperty::FIELD,
2746 prop_info->is_static, prop_info->is_computed_name,
2747 prop_info->is_private);
2748 }
2749 impl()->SetFunctionNameFromPropertyName(result, prop_info->name);
2750
2751 return result;
2752 }
2754 // MethodDefinition
2755 // PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}'
2756 // '*' PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}'
2757 // async PropertyName '(' StrictFormalParameters ')'
2758 // '{' FunctionBody '}'
2759 // async '*' PropertyName '(' StrictFormalParameters ')'
2760 // '{' FunctionBody '}'
2761
2762 if (!prop_info->is_computed_name) {
2764 prop_info->function_flags, prop_info->is_static,
2765 &class_info->has_seen_constructor);
2766 }
2767
2769 MethodKindFor(prop_info->is_static, prop_info->function_flags);
2770
2771 if (!prop_info->is_static && impl()->IsConstructor(prop_info->name)) {
2772 class_info->has_seen_constructor = true;
2775 }
2776
2777 ExpressionT value = impl()->ParseFunctionLiteral(
2778 prop_info->name, scanner()->location(), kSkipFunctionNameCheck, kind,
2779 name_token_position, FunctionSyntaxKind::kAccessorOrMethod,
2780 language_mode(), nullptr);
2781
2782 ClassLiteralPropertyT result = factory()->NewClassLiteralProperty(
2783 name_expression, value, ClassLiteralProperty::METHOD,
2784 prop_info->is_static, prop_info->is_computed_name,
2785 prop_info->is_private);
2786 impl()->SetFunctionNameFromPropertyName(result, prop_info->name);
2787 return result;
2788 }
2789
2793 bool is_get = prop_info->kind == ParsePropertyKind::kAccessorGetter;
2794
2795 if (!prop_info->is_computed_name) {
2796 CheckClassMethodName(prop_info->name, prop_info->kind,
2798 &class_info->has_seen_constructor);
2799 // Make sure the name expression is a string since we need a Name for
2800 // Runtime_DefineAccessorPropertyUnchecked and since we can determine
2801 // this statically we can skip the extra runtime check.
2802 name_expression = factory()->NewStringLiteral(
2803 prop_info->name, name_expression->position());
2804 }
2805
2807 if (prop_info->is_static) {
2810 } else {
2813 }
2814
2815 FunctionLiteralT value = impl()->ParseFunctionLiteral(
2816 prop_info->name, scanner()->location(), kSkipFunctionNameCheck, kind,
2817 name_token_position, FunctionSyntaxKind::kAccessorOrMethod,
2818 language_mode(), nullptr);
2819
2820 ClassLiteralProperty::Kind property_kind =
2822 ClassLiteralPropertyT result = factory()->NewClassLiteralProperty(
2823 name_expression, value, property_kind, prop_info->is_static,
2824 prop_info->is_computed_name, prop_info->is_private);
2825 const AstRawString* prefix =
2826 is_get ? ast_value_factory()->get_space_string()
2827 : ast_value_factory()->set_space_string();
2828 impl()->SetFunctionNameFromPropertyName(result, prop_info->name, prefix);
2829 return result;
2830 }
2834 impl()->ReportUnexpectedTokenAt(
2835 Scanner::Location(name_token_position, name_expression->position()),
2836 name_token);
2837 return impl()->NullLiteralProperty();
2838 }
2839 UNREACHABLE();
2840}
2841
2842template <typename Impl>
2844 ClassInfo* class_info, int beg_pos, int info_id, bool is_static) {
2845 FunctionParsingScope body_parsing_scope(impl());
2846 DeclarationScope* initializer_scope =
2847 is_static
2848 ? class_info->EnsureStaticElementsScope(this, beg_pos, info_id)
2849 : class_info->EnsureInstanceMembersScope(this, beg_pos, info_id);
2850
2851 if (Check(Token::kAssign)) {
2852 FunctionState initializer_state(&function_state_, &scope_,
2853 initializer_scope);
2854
2855 AcceptINScope scope(this, true);
2857 initializer_scope->set_end_position(end_position());
2858 return result;
2859 }
2860 initializer_scope->set_end_position(end_position());
2861 return factory()->NewUndefinedLiteral(kNoSourcePosition);
2862}
2863
2864template <typename Impl>
2866 ClassInfo* class_info) {
2867 Consume(Token::kStatic);
2868
2869 DeclarationScope* initializer_scope =
2870 class_info->EnsureStaticElementsScope(this, position(), PeekNextInfoId());
2871
2872 FunctionState initializer_state(&function_state_, &scope_, initializer_scope);
2873 FunctionParsingScope body_parsing_scope(impl());
2874 AcceptINScope accept_in(this, true);
2875
2876 // Each static block has its own var and lexical scope, so make a new var
2877 // block scope instead of using the synthetic members initializer function
2878 // scope.
2879 DeclarationScope* static_block_var_scope = NewVarblockScope();
2880 BlockT static_block = ParseBlock(nullptr, static_block_var_scope);
2881 CheckConflictingVarDeclarations(static_block_var_scope);
2882 initializer_scope->set_end_position(end_position());
2883 return static_block;
2884}
2885
2886template <typename Impl>
2889 bool* has_seen_proto) {
2891 Token::Value name_token = peek();
2892 Scanner::Location next_loc = scanner()->peek_location();
2893
2894 ExpressionT name_expression = ParseProperty(prop_info);
2895
2896 DCHECK_IMPLIES(name_token == Token::kPrivateName, has_error());
2897
2898 IdentifierT name = prop_info->name;
2899 ParseFunctionFlags function_flags = prop_info->function_flags;
2900
2901 switch (prop_info->kind) {
2903 DCHECK_EQ(function_flags, ParseFunctionFlag::kIsNormal);
2904 DCHECK(!prop_info->is_computed_name);
2905 DCHECK_EQ(Token::kEllipsis, name_token);
2906
2907 prop_info->is_computed_name = true;
2908 prop_info->is_rest = true;
2909
2910 return factory()->NewObjectLiteralProperty(
2911 factory()->NewTheHoleLiteral(), name_expression,
2913
2915 DCHECK_EQ(function_flags, ParseFunctionFlag::kIsNormal);
2916
2917 if (!prop_info->is_computed_name &&
2918 scanner()->CurrentLiteralEquals("__proto__")) {
2919 if (*has_seen_proto) {
2920 expression_scope()->RecordExpressionError(
2921 scanner()->location(), MessageTemplate::kDuplicateProto);
2922 }
2923 *has_seen_proto = true;
2924 }
2925 Consume(Token::kColon);
2926 AcceptINScope scope(this, true);
2927 ExpressionT value =
2929
2930 ObjectLiteralPropertyT result = factory()->NewObjectLiteralProperty(
2931 name_expression, value, prop_info->is_computed_name);
2932 impl()->SetFunctionNameFromPropertyName(result, name);
2933 return result;
2934 }
2935
2939 // PropertyDefinition
2940 // IdentifierReference
2941 // CoverInitializedName
2942 //
2943 // CoverInitializedName
2944 // IdentifierReference Initializer?
2945 DCHECK_EQ(function_flags, ParseFunctionFlag::kIsNormal);
2946
2947 if (!ClassifyPropertyIdentifier(name_token, prop_info)) {
2948 return impl()->NullLiteralProperty();
2949 }
2950
2951 ExpressionT lhs =
2952 impl()->ExpressionFromIdentifier(name, next_loc.beg_pos);
2953 if (!IsAssignableIdentifier(lhs)) {
2954 expression_scope()->RecordPatternError(
2955 next_loc, MessageTemplate::kStrictEvalArguments);
2956 }
2957
2959 if (peek() == Token::kAssign) {
2960 Consume(Token::kAssign);
2961 {
2962 AcceptINScope scope(this, true);
2964 value = factory()->NewAssignment(Token::kAssign, lhs, rhs,
2966 impl()->SetFunctionNameFromIdentifierRef(rhs, lhs);
2967 }
2968 expression_scope()->RecordExpressionError(
2970 MessageTemplate::kInvalidCoverInitializedName);
2971 } else {
2972 value = lhs;
2973 }
2974
2975 ObjectLiteralPropertyT result = factory()->NewObjectLiteralProperty(
2976 name_expression, value, ObjectLiteralProperty::COMPUTED, false);
2977 impl()->SetFunctionNameFromPropertyName(result, name);
2978 return result;
2979 }
2980
2982 // MethodDefinition
2983 // PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}'
2984 // '*' PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}'
2985
2986 expression_scope()->RecordPatternError(
2988 MessageTemplate::kInvalidDestructuringTarget);
2989
2990 std::unique_ptr<BlockState> block_state;
2991 if (object_literal_scope_ != nullptr) {
2993 block_state.reset(new BlockState(&scope_, object_literal_scope_));
2994 }
2995 constexpr bool kIsStatic = false;
2996 FunctionKind kind = MethodKindFor(kIsStatic, function_flags);
2997
2998 ExpressionT value = impl()->ParseFunctionLiteral(
2999 name, scanner()->location(), kSkipFunctionNameCheck, kind,
3001 language_mode(), nullptr);
3002
3003 ObjectLiteralPropertyT result = factory()->NewObjectLiteralProperty(
3004 name_expression, value, ObjectLiteralProperty::COMPUTED,
3005 prop_info->is_computed_name);
3006 impl()->SetFunctionNameFromPropertyName(result, name);
3007 return result;
3008 }
3009
3012 DCHECK_EQ(function_flags, ParseFunctionFlag::kIsNormal);
3013 bool is_get = prop_info->kind == ParsePropertyKind::kAccessorGetter;
3014
3015 expression_scope()->RecordPatternError(
3017 MessageTemplate::kInvalidDestructuringTarget);
3018
3019 if (!prop_info->is_computed_name) {
3020 // Make sure the name expression is a string since we need a Name for
3021 // Runtime_DefineAccessorPropertyUnchecked and since we can determine
3022 // this statically we can skip the extra runtime check.
3023 name_expression =
3024 factory()->NewStringLiteral(name, name_expression->position());
3025 }
3026
3027 std::unique_ptr<BlockState> block_state;
3028 if (object_literal_scope_ != nullptr) {
3030 block_state.reset(new BlockState(&scope_, object_literal_scope_));
3031 }
3032
3035
3036 FunctionLiteralT value = impl()->ParseFunctionLiteral(
3037 name, scanner()->location(), kSkipFunctionNameCheck, kind,
3039 language_mode(), nullptr);
3040
3041 ObjectLiteralPropertyT result = factory()->NewObjectLiteralProperty(
3042 name_expression, value,
3045 prop_info->is_computed_name);
3046 const AstRawString* prefix =
3047 is_get ? ast_value_factory()->get_space_string()
3048 : ast_value_factory()->set_space_string();
3049 impl()->SetFunctionNameFromPropertyName(result, name, prefix);
3050 return result;
3051 }
3052
3057 return impl()->NullLiteralProperty();
3058 }
3059 UNREACHABLE();
3060}
3061
3062template <typename Impl>
3064 // ObjectLiteral ::
3065 // '{' (PropertyDefinition (',' PropertyDefinition)* ','? )? '}'
3066
3067 int pos = peek_position();
3068 ObjectPropertyListT properties(pointer_buffer());
3069 int number_of_boilerplate_properties = 0;
3070
3071 bool has_computed_names = false;
3072 bool has_rest_property = false;
3073 bool has_seen_proto = false;
3074
3075 Consume(Token::kLeftBrace);
3076 AccumulationScope accumulation_scope(expression_scope());
3077
3078 // If methods appear inside the object literal, we'll enter this scope.
3079 Scope* block_scope = NewBlockScopeForObjectLiteral();
3080 block_scope->set_start_position(pos);
3081 BlockState object_literal_scope_state(&object_literal_scope_, block_scope);
3082
3083 while (!Check(Token::kRightBrace)) {
3084 FuncNameInferrerState fni_state(&fni_);
3085
3086 ParsePropertyInfo prop_info(this, &accumulation_scope);
3088 ObjectLiteralPropertyT property =
3089 ParseObjectPropertyDefinition(&prop_info, &has_seen_proto);
3090 if (impl()->IsNull(property)) return impl()->FailureExpression();
3091
3092 if (prop_info.is_computed_name) {
3093 has_computed_names = true;
3094 }
3095
3096 if (prop_info.is_rest) {
3097 has_rest_property = true;
3098 }
3099
3100 if (impl()->IsBoilerplateProperty(property) && !has_computed_names) {
3101 // Count CONSTANT or COMPUTED properties to maintain the enumeration
3102 // order.
3103 number_of_boilerplate_properties++;
3104 }
3105
3106 properties.Add(property);
3107
3108 if (peek() != Token::kRightBrace) {
3109 Expect(Token::kComma);
3110 }
3111
3112 fni_.Infer();
3113 }
3114
3115 Variable* home_object = nullptr;
3116 if (block_scope->needs_home_object()) {
3117 home_object = block_scope->DeclareHomeObjectVariable(ast_value_factory());
3118 block_scope->set_end_position(end_position());
3119 } else {
3120 block_scope = block_scope->FinalizeBlockScope();
3121 DCHECK_NULL(block_scope);
3122 }
3123
3124 // In pattern rewriter, we rewrite rest property to call out to a
3125 // runtime function passing all the other properties as arguments to
3126 // this runtime function. Here, we make sure that the number of
3127 // properties is less than number of arguments allowed for a runtime
3128 // call.
3129 if (has_rest_property && properties.length() > Code::kMaxArguments) {
3130 expression_scope()->RecordPatternError(Scanner::Location(pos, position()),
3131 MessageTemplate::kTooManyArguments);
3132 }
3133
3134 return impl()->InitializeObjectLiteral(
3135 factory()->NewObjectLiteral(properties, number_of_boilerplate_properties,
3136 pos, has_rest_property, home_object));
3137}
3138
3139template <typename Impl>
3141 typename ParserBase<Impl>::ExpressionListT* args, bool* has_spread,
3142 ParsingArrowHeadFlag maybe_arrow) {
3143 // Arguments ::
3144 // '(' (AssignmentExpression)*[','] ')'
3145
3146 *has_spread = false;
3147 Consume(Token::kLeftParen);
3148 AccumulationScope accumulation_scope(expression_scope());
3149
3150 int variable_index = 0;
3151 while (peek() != Token::kRightParen) {
3152 int start_pos = peek_position();
3153 bool is_spread = Check(Token::kEllipsis);
3154 int expr_pos = peek_position();
3155
3156 AcceptINScope scope(this, true);
3158
3159 if (V8_UNLIKELY(maybe_arrow == kMaybeArrowHead)) {
3160 ClassifyArrowParameter(&accumulation_scope, expr_pos, argument);
3161 if (is_spread) {
3162 expression_scope()->RecordNonSimpleParameter();
3163 if (argument->IsAssignment()) {
3164 expression_scope()->RecordAsyncArrowParametersError(
3165 scanner()->location(), MessageTemplate::kRestDefaultInitializer);
3166 }
3167 if (peek() == Token::kComma) {
3168 expression_scope()->RecordAsyncArrowParametersError(
3169 scanner()->peek_location(), MessageTemplate::kParamAfterRest);
3170 }
3171 }
3172 }
3173 if (is_spread) {
3174 *has_spread = true;
3175 argument = factory()->NewSpread(argument, start_pos, expr_pos);
3176 }
3177 args->Add(argument);
3178
3179 variable_index =
3180 expression_scope()->SetInitializers(variable_index, peek_position());
3181
3182 if (!Check(Token::kComma)) break;
3183 }
3184
3185 if (args->length() + 1 /* receiver */ > Code::kMaxArguments) {
3186 ReportMessage(MessageTemplate::kTooManyArguments);
3187 return;
3188 }
3189
3190 Scanner::Location location = scanner_->location();
3191 if (!Check(Token::kRightParen)) {
3192 impl()->ReportMessageAt(location, MessageTemplate::kUnterminatedArgList);
3193 }
3194}
3195
3196template <typename Impl>
3199 // AssignmentExpression ::
3200 // ArrowFunction
3201 // YieldExpression
3202 // LeftHandSideExpression AssignmentOperator AssignmentExpression
3203 int lhs_beg_pos = peek_position();
3204
3205 if (peek() == Token::kYield && is_generator()) {
3206 return ParseYieldExpression();
3207 }
3208
3209 FuncNameInferrerState fni_state(&fni_);
3210
3212
3213 ExpressionT expression = ParseLogicalExpression();
3214
3215 Token::Value op = peek();
3216
3217 if (!Token::IsArrowOrAssignmentOp(op) || peek() == Token::kConditional)
3218 return expression;
3219
3221 expression);
3222}
3223
3224// Precedence = 2
3225template <typename Impl>
3228 // AssignmentExpression ::
3229 // ConditionalExpression
3230 // ArrowFunction
3231 // YieldExpression
3232 // LeftHandSideExpression AssignmentOperator AssignmentExpression
3233 int lhs_beg_pos = peek_position();
3234
3235 if (peek() == Token::kYield && is_generator()) {
3236 return ParseYieldExpression();
3237 }
3238
3239 FuncNameInferrerState fni_state(&fni_);
3240
3242
3244
3245 Token::Value op = peek();
3246
3248
3250 expression);
3251}
3252
3253// Precedence = 2
3254template <typename Impl>
3257 int lhs_beg_pos, ExpressionT expression) {
3258 // AssignmentExpression ::
3259 // ConditionalExpression
3260 // ArrowFunction
3261 // YieldExpression
3262 // LeftHandSideExpression AssignmentOperator AssignmentExpression
3263 Token::Value op = peek();
3264
3265 // Arrow functions.
3266 if (V8_UNLIKELY(op == Token::kArrow)) {
3267 Scanner::Location loc(lhs_beg_pos, end_position());
3268
3269 if (!impl()->IsIdentifier(expression) && !expression->is_parenthesized()) {
3270 impl()->ReportMessageAt(
3271 Scanner::Location(expression->position(), position()),
3272 MessageTemplate::kMalformedArrowFunParamList);
3273 return impl()->FailureExpression();
3274 }
3275
3277 int function_literal_id = next_arrow_function_info_.function_literal_id;
3278 scope->set_start_position(lhs_beg_pos);
3279
3280 FormalParametersT parameters(scope);
3281 parameters.set_strict_parameter_error(
3284 parameters.is_simple = scope->has_simple_parameters();
3285 bool could_be_immediately_invoked =
3288
3289 impl()->DeclareArrowFunctionFormalParameters(&parameters, expression, loc);
3290 // function_literal_id was reserved for the arrow function, but not actaully
3291 // allocated. This comparison allocates a function literal id for the arrow
3292 // function, and checks whether it's still the function id we wanted. If
3293 // not, we'll reindex the arrow function formal parameters to shift them all
3294 // 1 down to make space for the arrow function.
3295 if (function_literal_id != GetNextInfoId()) {
3296 impl()->ReindexArrowFunctionFormalParameters(&parameters);
3297 }
3298
3299 expression = ParseArrowFunctionLiteral(parameters, function_literal_id,
3300 could_be_immediately_invoked);
3301
3302 return expression;
3303 }
3304
3305 if (V8_LIKELY(impl()->IsAssignableIdentifier(expression))) {
3306 if (expression->is_parenthesized()) {
3307 expression_scope()->RecordDeclarationError(
3308 Scanner::Location(lhs_beg_pos, end_position()),
3309 MessageTemplate::kInvalidDestructuringTarget);
3310 }
3311 expression_scope()->MarkIdentifierAsAssigned();
3312 } else if (expression->IsProperty()) {
3313 expression_scope()->RecordDeclarationError(
3314 Scanner::Location(lhs_beg_pos, end_position()),
3315 MessageTemplate::kInvalidPropertyBindingPattern);
3316 expression_scope()->ValidateAsExpression();
3317 } else if (expression->IsPattern() && op == Token::kAssign) {
3318 // Destructuring assignmment.
3319 if (expression->is_parenthesized()) {
3320 Scanner::Location loc(lhs_beg_pos, end_position());
3321 if (expression_scope()->IsCertainlyDeclaration()) {
3322 impl()->ReportMessageAt(loc,
3323 MessageTemplate::kInvalidDestructuringTarget);
3324 } else {
3325 // Syntax Error if LHS is neither object literal nor an array literal
3326 // (Parenthesized literals are
3327 // CoverParenthesizedExpressionAndArrowParameterList).
3328 // #sec-assignment-operators-static-semantics-early-errors
3329 impl()->ReportMessageAt(loc, MessageTemplate::kInvalidLhsInAssignment);
3330 }
3331 }
3332 expression_scope()->ValidateAsPattern(expression, lhs_beg_pos,
3333 end_position());
3334 } else {
3335 DCHECK(!IsValidReferenceExpression(expression));
3336 // For web compatibility reasons, throw early errors only for logical
3337 // assignment, not for regular assignment.
3338 const bool early_error = Token::IsLogicalAssignmentOp(op);
3340 expression, lhs_beg_pos, end_position(),
3341 MessageTemplate::kInvalidLhsInAssignment, early_error);
3342 }
3343
3344 Consume(op);
3345 int op_position = position();
3346
3348
3349 // Anonymous function name inference applies to =, ||=, &&=, and ??=.
3350 if (op == Token::kAssign || Token::IsLogicalAssignmentOp(op)) {
3351 impl()->CheckAssigningFunctionLiteralToProperty(expression, right);
3352
3353 // Check if the right hand side is a call to avoid inferring a
3354 // name if we're dealing with "a = function(){...}();"-like
3355 // expression.
3356 if (right->IsCall() || right->IsCallNew()) {
3357 fni_.RemoveLastFunction();
3358 } else {
3359 fni_.Infer();
3360 }
3361
3362 impl()->SetFunctionNameFromIdentifierRef(right, expression);
3363 } else {
3364 fni_.RemoveLastFunction();
3365 }
3366
3367 if (op == Token::kAssign) {
3368 // We try to estimate the set of properties set by constructors. We define a
3369 // new property whenever there is an assignment to a property of 'this'. We
3370 // should probably only add properties if we haven't seen them before.
3371 // Otherwise we'll probably overestimate the number of properties.
3372 if (impl()->IsThisProperty(expression)) function_state_->AddProperty();
3373 } else {
3374 // Only initializers (i.e. no compound assignments) are allowed in patterns.
3375 expression_scope()->RecordPatternError(
3376 Scanner::Location(lhs_beg_pos, end_position()),
3377 MessageTemplate::kInvalidDestructuringTarget);
3378 }
3379
3380 return factory()->NewAssignment(op, expression, right, op_position);
3381}
3382
3383template <typename Impl>
3386 // YieldExpression ::
3387 // 'yield' ([no line terminator] '*'? AssignmentExpression)?
3388 int pos = peek_position();
3389 expression_scope()->RecordParameterInitializerError(
3390 scanner()->peek_location(), MessageTemplate::kYieldInParameter);
3391 Consume(Token::kYield);
3392 if (V8_UNLIKELY(scanner()->literal_contains_escapes())) {
3393 impl()->ReportUnexpectedToken(Token::kEscapedKeyword);
3394 }
3395
3397
3398 // The following initialization is necessary.
3399 ExpressionT expression = impl()->NullExpression();
3400 bool delegating = false; // yield*
3401 if (!scanner()->HasLineTerminatorBeforeNext()) {
3402 if (Check(Token::kMul)) delegating = true;
3403 switch (peek()) {
3404 case Token::kEos:
3405 case Token::kSemicolon:
3406 case Token::kRightBrace:
3407 case Token::kRightBracket:
3408 case Token::kRightParen:
3409 case Token::kColon:
3410 case Token::kComma:
3411 case Token::kIn:
3412 // The above set of tokens is the complete set of tokens that can appear
3413 // after an AssignmentExpression, and none of them can start an
3414 // AssignmentExpression. This allows us to avoid looking for an RHS for
3415 // a regular yield, given only one look-ahead token.
3416 if (!delegating) break;
3417 // Delegating yields require an RHS; fall through.
3418 [[fallthrough]];
3419 default:
3421 break;
3422 }
3423 }
3424
3425 if (delegating) {
3426 ExpressionT yieldstar = factory()->NewYieldStar(expression, pos);
3427 impl()->RecordSuspendSourceRange(yieldstar, PositionAfterSemicolon());
3430 // return, iterator_close and delegated_iterator_output suspend ids.
3434 }
3435 return yieldstar;
3436 }
3437
3438 // Hackily disambiguate o from o.next and o [Symbol.iterator]().
3439 // TODO(verwaest): Come up with a better solution.
3440 ExpressionT yield =
3441 factory()->NewYield(expression, pos, Suspend::kOnExceptionThrow);
3442 impl()->RecordSuspendSourceRange(yield, PositionAfterSemicolon());
3444 return yield;
3445}
3446
3447// Precedence = 3
3448template <typename Impl>
3451 // ConditionalExpression ::
3452 // LogicalExpression
3453 // LogicalExpression '?' AssignmentExpression ':' AssignmentExpression
3454 //
3455 int pos = peek_position();
3456 ExpressionT expression = ParseLogicalExpression();
3457 return peek() == Token::kConditional
3459 : expression;
3460}
3461
3462template <typename Impl>
3465 // LogicalExpression ::
3466 // LogicalORExpression
3467 // CoalesceExpression
3468
3469 // Both LogicalORExpression and CoalesceExpression start with BitwiseOR.
3470 // Parse for binary expressions >= 6 (BitwiseOR);
3471 ExpressionT expression = ParseBinaryExpression(6);
3472 if (peek() == Token::kAnd || peek() == Token::kOr) {
3473 // LogicalORExpression, pickup parsing where we left off.
3474 int prec1 = Token::Precedence(peek(), accept_IN_);
3475 expression = ParseBinaryContinuation(expression, 4, prec1);
3476 } else if (V8_UNLIKELY(peek() == Token::kNullish)) {
3477 expression = ParseCoalesceExpression(expression);
3478 }
3479 return expression;
3480}
3481
3482template <typename Impl>
3485 // CoalesceExpression ::
3486 // CoalesceExpressionHead ?? BitwiseORExpression
3487 //
3488 // CoalesceExpressionHead ::
3489 // CoalesceExpression
3490 // BitwiseORExpression
3491
3492 // We create a binary operation for the first nullish, otherwise collapse
3493 // into an nary expresion.
3494 bool first_nullish = true;
3495 while (peek() == Token::kNullish) {
3496 SourceRange right_range;
3497 int pos;
3498 ExpressionT y;
3499 {
3500 SourceRangeScope right_range_scope(scanner(), &right_range);
3501 Consume(Token::kNullish);
3502 pos = peek_position();
3503 // Parse BitwiseOR or higher.
3505 }
3506 if (first_nullish) {
3507 expression =
3508 factory()->NewBinaryOperation(Token::kNullish, expression, y, pos);
3509 impl()->RecordBinaryOperationSourceRange(expression, right_range);
3510 first_nullish = false;
3511 } else {
3512 impl()->CollapseNaryExpression(&expression, y, Token::kNullish, pos,
3513 right_range);
3514 }
3515 }
3516 return expression;
3517}
3518
3519template <typename Impl>
3522 int condition_pos) {
3523 // ConditionalChainExpression ::
3524 // ConditionalExpression_1 ? AssignmentExpression_1 :
3525 // ConditionalExpression_2 ? AssignmentExpression_2 :
3526 // ConditionalExpression_3 ? AssignmentExpression_3 :
3527 // ...
3528 // ConditionalExpression_n ? AssignmentExpression_n
3529
3530 ExpressionT expr = impl()->NullExpression();
3531 ExpressionT else_expression = impl()->NullExpression();
3532 bool else_found = false;
3533 ZoneVector<int> else_ranges_beg_pos(impl()->zone());
3534 do {
3535 SourceRange then_range;
3536 ExpressionT then_expression;
3537 {
3538 SourceRangeScope range_scope(scanner(), &then_range);
3539 Consume(Token::kConditional);
3540 // In parsing the first assignment expression in conditional
3541 // expressions we always accept the 'in' keyword; see ECMA-262,
3542 // section 11.12, page 58.
3543 AcceptINScope scope(this, true);
3544 then_expression = ParseAssignmentExpression();
3545 }
3546
3547 else_ranges_beg_pos.emplace_back(scanner()->peek_location().beg_pos);
3548 int condition_or_else_pos = peek_position();
3549 SourceRange condition_or_else_range = SourceRange();
3550 ExpressionT condition_or_else_expression;
3551 {
3552 SourceRangeScope condition_or_else_range_scope(scanner(),
3553 &condition_or_else_range);
3554 Expect(Token::kColon);
3555 condition_or_else_expression =
3557 }
3558
3559 else_found = (peek() != Token::kConditional);
3560
3561 if (else_found) {
3562 else_expression = condition_or_else_expression;
3563
3564 if (impl()->IsNull(expr)) {
3565 // When we have a single conditional expression, we don't create a
3566 // conditional chain expression. Instead, we just return a conditional
3567 // expression.
3568 SourceRange else_range = condition_or_else_range;
3569 expr = factory()->NewConditional(condition, then_expression,
3570 else_expression, condition_pos);
3571 impl()->RecordConditionalSourceRange(expr, then_range, else_range);
3572 return expr;
3573 }
3574 }
3575
3576 if (impl()->IsNull(expr)) {
3577 // For the first conditional expression, we create a conditional chain.
3578 expr = factory()->NewConditionalChain(1, condition_pos);
3579 }
3580
3581 impl()->CollapseConditionalChain(&expr, condition, then_expression,
3582 else_expression, condition_pos,
3583 then_range);
3584
3585 if (!else_found) {
3586 condition = condition_or_else_expression;
3587 condition_pos = condition_or_else_pos;
3588 }
3589 } while (!else_found);
3590
3591 int end_pos = scanner()->location().end_pos;
3592 for (const auto& else_range_beg_pos : else_ranges_beg_pos) {
3593 impl()->AppendConditionalChainElse(
3594 &expr, SourceRange(else_range_beg_pos, end_pos));
3595 }
3596
3597 return expr;
3598}
3599
3600template <typename Impl>
3603 int pos) {
3604 SourceRange then_range, else_range;
3605
3606 ExpressionT left;
3607 {
3608 SourceRangeScope range_scope(scanner(), &then_range);
3609 Consume(Token::kConditional);
3610 // In parsing the first assignment expression in conditional
3611 // expressions we always accept the 'in' keyword; see ECMA-262,
3612 // section 11.12, page 58.
3613 AcceptINScope scope(this, true);
3615 }
3616 ExpressionT right;
3617 {
3618 SourceRangeScope range_scope(scanner(), &else_range);
3619 Expect(Token::kColon);
3620 right = ParseAssignmentExpression();
3621 }
3622 ExpressionT expr = factory()->NewConditional(expression, left, right, pos);
3623 impl()->RecordConditionalSourceRange(expr, then_range, else_range);
3624 return expr;
3625}
3626
3627// Precedence >= 4
3628template <typename Impl>
3631 do {
3632 // prec1 >= 4
3633 while (Token::Precedence(peek(), accept_IN_) == prec1) {
3634 SourceRange right_range;
3635 int pos = peek_position();
3636 ExpressionT y;
3637 Token::Value op;
3638 {
3639 SourceRangeScope right_range_scope(scanner(), &right_range);
3640 op = Next();
3641
3642 const bool is_right_associative = op == Token::kExp;
3643 const int next_prec = is_right_associative ? prec1 : prec1 + 1;
3644 y = ParseBinaryExpression(next_prec);
3645 }
3646
3647 // For now we distinguish between comparisons and other binary
3648 // operations. (We could combine the two and get rid of this
3649 // code and AST node eventually.)
3650 if (Token::IsCompareOp(op)) {
3651 // We have a comparison.
3652 Token::Value cmp = op;
3653 switch (op) {
3654 case Token::kNotEq:
3655 cmp = Token::kEq;
3656 break;
3657 case Token::kNotEqStrict:
3658 cmp = Token::kEqStrict;
3659 break;
3660 default: break;
3661 }
3662 x = factory()->NewCompareOperation(cmp, x, y, pos);
3663 if (cmp != op) {
3664 // The comparison was negated - add a kNot.
3665 x = factory()->NewUnaryOperation(Token::kNot, x, pos);
3666 }
3667 } else if (!impl()->ShortcutLiteralBinaryExpression(&x, y, op, pos) &&
3668 !impl()->CollapseNaryExpression(&x, y, op, pos, right_range)) {
3669 // We have a "normal" binary operation.
3670 x = factory()->NewBinaryOperation(op, x, y, pos);
3671 if (op == Token::kOr || op == Token::kAnd) {
3672 impl()->RecordBinaryOperationSourceRange(x, right_range);
3673 }
3674 }
3675 }
3676 --prec1;
3677 } while (prec1 >= prec);
3678
3679 return x;
3680}
3681
3682// Precedence >= 4
3683template <typename Impl>
3685 int prec) {
3686 DCHECK_GE(prec, 4);
3687
3688 // "#foo in ShiftExpression" needs to be parsed separately, since private
3689 // identifiers are not valid PrimaryExpressions.
3690 if (V8_UNLIKELY(peek() == Token::kPrivateName)) {
3692 int prec1 = Token::Precedence(peek(), accept_IN_);
3693 if (peek() != Token::kIn || prec1 < prec) {
3694 ReportUnexpectedToken(Token::kPrivateName);
3695 return impl()->FailureExpression();
3696 }
3697 return ParseBinaryContinuation(x, prec, prec1);
3698 }
3699
3701 int prec1 = Token::Precedence(peek(), accept_IN_);
3702 if (prec1 >= prec) {
3703 return ParseBinaryContinuation(x, prec, prec1);
3704 }
3705 return x;
3706}
3707
3708template <typename Impl>
3711 Token::Value op = Next();
3712 int pos = position();
3713
3714 // Assume "! function ..." indicates the function is likely to be called.
3715 if (op == Token::kNot && peek() == Token::kFunction) {
3717 }
3718
3720
3721 int expression_position = peek_position();
3722 ExpressionT expression = ParseUnaryExpression();
3723
3724 if (Token::IsUnaryOp(op)) {
3725 if (op == Token::kDelete) {
3726 if (impl()->IsIdentifier(expression) && is_strict(language_mode())) {
3727 // "delete identifier" is a syntax error in strict mode.
3728 ReportMessage(MessageTemplate::kStrictDelete);
3729 return impl()->FailureExpression();
3730 }
3731
3732 if (impl()->IsPrivateReference(expression)) {
3733 ReportMessage(MessageTemplate::kDeletePrivateField);
3734 return impl()->FailureExpression();
3735 }
3736 }
3737
3738 if (peek() == Token::kExp) {
3739 impl()->ReportMessageAt(
3741 MessageTemplate::kUnexpectedTokenUnaryExponentiation);
3742 return impl()->FailureExpression();
3743 }
3744
3745 // Allow the parser's implementation to rewrite the expression.
3746 return impl()->BuildUnaryExpression(expression, op, pos);
3747 }
3748
3750
3751 if (V8_LIKELY(IsValidReferenceExpression(expression))) {
3752 if (impl()->IsIdentifier(expression)) {
3753 expression_scope()->MarkIdentifierAsAssigned();
3754 }
3755 } else {
3756 const bool early_error = false;
3758 expression, expression_position, end_position(),
3759 MessageTemplate::kInvalidLhsInPrefixOp, early_error);
3760 }
3761
3762 return factory()->NewCountOperation(op, true /* prefix */, expression,
3763 position());
3764}
3765
3766template <typename Impl>
3769 expression_scope()->RecordParameterInitializerError(
3770 scanner()->peek_location(),
3771 MessageTemplate::kAwaitExpressionFormalParameter);
3772 int await_pos = peek_position();
3773 Consume(Token::kAwait);
3774 if (V8_UNLIKELY(scanner()->literal_contains_escapes())) {
3775 impl()->ReportUnexpectedToken(Token::kEscapedKeyword);
3776 }
3777
3779
3781
3782 // 'await' is a unary operator according to the spec, even though it's treated
3783 // specially in the parser.
3784 if (peek() == Token::kExp) {
3785 impl()->ReportMessageAt(
3787 MessageTemplate::kUnexpectedTokenUnaryExponentiation);
3788 return impl()->FailureExpression();
3789 }
3790
3791 ExpressionT expr = factory()->NewAwait(value, await_pos);
3793 impl()->RecordSuspendSourceRange(expr, PositionAfterSemicolon());
3794 return expr;
3795}
3796
3797template <typename Impl>
3800 // UnaryExpression ::
3801 // PostfixExpression
3802 // 'delete' UnaryExpression
3803 // 'void' UnaryExpression
3804 // 'typeof' UnaryExpression
3805 // '++' UnaryExpression
3806 // '--' UnaryExpression
3807 // '+' UnaryExpression
3808 // '-' UnaryExpression
3809 // '~' UnaryExpression
3810 // '!' UnaryExpression
3811 // [+Await] AwaitExpression[?Yield]
3812
3813 Token::Value op = peek();
3815 if (is_await_allowed() && op == Token::kAwait) {
3816 return ParseAwaitExpression();
3817 }
3818 return ParsePostfixExpression();
3819}
3820
3821template <typename Impl>
3824 // PostfixExpression ::
3825 // LeftHandSideExpression ('++' | '--')?
3826
3827 int lhs_beg_pos = peek_position();
3830 scanner()->HasLineTerminatorBeforeNext())) {
3831 return expression;
3832 }
3833 return ParsePostfixContinuation(expression, lhs_beg_pos);
3834}
3835
3836template <typename Impl>
3839 int lhs_beg_pos) {
3840 if (V8_UNLIKELY(!IsValidReferenceExpression(expression))) {
3841 const bool early_error = false;
3843 expression, lhs_beg_pos, end_position(),
3844 MessageTemplate::kInvalidLhsInPostfixOp, early_error);
3845 }
3846 if (impl()->IsIdentifier(expression)) {
3847 expression_scope()->MarkIdentifierAsAssigned();
3848 }
3849
3850 Token::Value next = Next();
3851 return factory()->NewCountOperation(next, false /* postfix */, expression,
3852 position());
3853}
3854
3855template <typename Impl>
3858 // LeftHandSideExpression ::
3859 // (NewExpression | MemberExpression) ...
3860
3862 if (!Token::IsPropertyOrCall(peek())) return result;
3864}
3865
3866template <typename Impl>
3870
3871 if (V8_UNLIKELY(peek() == Token::kLeftParen && impl()->IsIdentifier(result) &&
3872 scanner()->current_token() == Token::kAsync &&
3873 !scanner()->HasLineTerminatorBeforeNext() &&
3874 !scanner()->literal_contains_escapes())) {
3875 DCHECK(impl()->IsAsync(impl()->AsIdentifier(result)));
3876 int pos = position();
3877
3879 PeekNextInfoId());
3880 Scope::Snapshot scope_snapshot(scope());
3881
3883 bool has_spread;
3884 ParseArguments(&args, &has_spread, kMaybeArrowHead);
3885 if (V8_LIKELY(peek() == Token::kArrow)) {
3886 fni_.RemoveAsyncKeywordFromEnd();
3887 next_arrow_function_info_.scope = maybe_arrow.ValidateAndCreateScope();
3889 maybe_arrow.function_literal_id();
3891 // async () => ...
3892 if (!args.length()) return factory()->NewEmptyParentheses(pos);
3893 // async ( Arguments ) => ...
3894 result = impl()->ExpressionListToExpression(args);
3895 result->mark_parenthesized();
3896 return result;
3897 }
3898
3899 result = factory()->NewCall(result, args, pos, has_spread);
3900
3901 maybe_arrow.ValidateExpression();
3902
3903 fni_.RemoveLastFunction();
3904 if (!Token::IsPropertyOrCall(peek())) return result;
3905 }
3906
3907 bool optional_chaining = false;
3908 bool is_optional = false;
3909 int optional_link_begin;
3910 do {
3911 switch (peek()) {
3912 case Token::kQuestionPeriod: {
3913 if (is_optional) {
3915 return impl()->FailureExpression();
3916 }
3917 // Include the ?. in the source range position.
3918 optional_link_begin = scanner()->peek_location().beg_pos;
3919 Consume(Token::kQuestionPeriod);
3920 is_optional = true;
3921 optional_chaining = true;
3922 if (Token::IsPropertyOrCall(peek())) continue;
3923 int pos = position();
3925 result = factory()->NewProperty(result, key, pos, is_optional);
3926 break;
3927 }
3928
3929 /* Property */
3930 case Token::kLeftBracket: {
3931 Consume(Token::kLeftBracket);
3932 int pos = position();
3933 AcceptINScope scope(this, true);
3935 result = factory()->NewProperty(result, index, pos, is_optional);
3936 Expect(Token::kRightBracket);
3937 break;
3938 }
3939
3940 /* Property */
3941 case Token::kPeriod: {
3942 if (is_optional) {
3944 return impl()->FailureExpression();
3945 }
3946 Consume(Token::kPeriod);
3947 int pos = position();
3949 result = factory()->NewProperty(result, key, pos, is_optional);
3950 break;
3951 }
3952
3953 /* Call */
3954 case Token::kLeftParen: {
3955 int pos;
3956 if (Token::IsCallable(scanner()->current_token())) {
3957 // For call of an identifier we want to report position of
3958 // the identifier as position of the call in the stack trace.
3959 pos = position();
3960 } else {
3961 // For other kinds of calls we record position of the parenthesis as
3962 // position of the call. Note that this is extremely important for
3963 // expressions of the form function(){...}() for which call position
3964 // should not point to the closing brace otherwise it will intersect
3965 // with positions recorded for function literal and confuse debugger.
3966 pos = peek_position();
3967 // Also the trailing parenthesis are a hint that the function will
3968 // be called immediately. If we happen to have parsed a preceding
3969 // function literal eagerly, we can also compile it eagerly.
3970 if (result->IsFunctionLiteral()) {
3971 result->AsFunctionLiteral()->SetShouldEagerCompile();
3972 }
3973 }
3974 bool has_spread;
3976 ParseArguments(&args, &has_spread);
3977
3978 // Keep track of eval() calls since they disable all local variable
3979 // optimizations.
3980 // The calls that need special treatment are the
3981 // direct eval calls. These calls are all of the form eval(...), with
3982 // no explicit receiver.
3983 // These calls are marked as potentially direct eval calls. Whether
3984 // they are actually direct calls to eval is determined at run time.
3985 int eval_scope_info_index = 0;
3986 if (CheckPossibleEvalCall(result, is_optional, scope())) {
3987 eval_scope_info_index = GetNextInfoId();
3988 }
3989
3990 result = factory()->NewCall(result, args, pos, has_spread,
3991 eval_scope_info_index, is_optional);
3992
3993 fni_.RemoveLastFunction();
3994 break;
3995 }
3996
3997 default:
3998 // Template literals in/after an Optional Chain not supported:
3999 if (optional_chaining) {
4000 impl()->ReportMessageAt(scanner()->peek_location(),
4001 MessageTemplate::kOptionalChainingNoTemplate);
4002 return impl()->FailureExpression();
4003 }
4004 /* Tagged Template */
4007 break;
4008 }
4009 if (is_optional) {
4010 SourceRange chain_link_range(optional_link_begin, end_position());
4011 impl()->RecordExpressionSourceRange(result, chain_link_range);
4012 is_optional = false;
4013 }
4014 } while (Token::IsPropertyOrCall(peek()));
4015 if (optional_chaining) return factory()->NewOptionalChain(result);
4016 return result;
4017}
4018
4019template <typename Impl>
4022 // NewExpression ::
4023 // ('new')+ MemberExpression
4024 //
4025 // NewTarget ::
4026 // 'new' '.' 'target'
4027 //
4028 // ImportMeta :
4029 // import . meta
4030
4031 // The grammar for new expressions is pretty warped. We can have several 'new'
4032 // keywords following each other, and then a MemberExpression. When we see '('
4033 // after the MemberExpression, it's associated with the rightmost unassociated
4034 // 'new' to create a NewExpression with arguments. However, a NewExpression
4035 // can also occur without arguments.
4036
4037 // Examples of new expression:
4038 // new foo.bar().baz means (new (foo.bar)()).baz
4039 // new foo()() means (new foo())()
4040 // new new foo()() means (new (new foo())())
4041 // new new foo means new (new foo)
4042 // new new foo() means new (new foo())
4043 // new new foo().bar().baz means (new (new foo()).bar()).baz
4044 // new super.x means new (super.x)
4045 // new import.meta.foo means (new (import.meta.foo)())
4046 Consume(Token::kNew);
4047 int new_pos = position();
4049
4051
4052 if (peek() == Token::kImport) {
4054 if (result->IsImportCallExpression()) {
4055 // new import() and new import.source() are never allowed.
4056 impl()->ReportMessageAt(scanner()->location(),
4057 MessageTemplate::kImportCallNotNewExpression);
4058 return impl()->FailureExpression();
4059 }
4060 } else if (peek() == Token::kPeriod) {
4063 } else {
4065 if (result->IsSuperCallReference()) {
4066 // new super() is never allowed
4067 impl()->ReportMessageAt(scanner()->location(),
4068 MessageTemplate::kUnexpectedSuper);
4069 return impl()->FailureExpression();
4070 }
4071 }
4072 if (peek() == Token::kLeftParen) {
4073 // NewExpression with arguments.
4074 {
4076 bool has_spread;
4077 ParseArguments(&args, &has_spread);
4078
4079 result = factory()->NewCallNew(result, args, new_pos, has_spread);
4080 }
4081 // The expression can still continue with . or [ after the arguments.
4083 }
4084
4085 if (peek() == Token::kQuestionPeriod) {
4086 impl()->ReportMessageAt(scanner()->peek_location(),
4087 MessageTemplate::kOptionalChainingNoNew);
4088 return impl()->FailureExpression();
4089 }
4090
4091 // NewExpression without arguments.
4093 return factory()->NewCallNew(result, args, new_pos, false);
4094}
4095
4096template <typename Impl>
4099 Consume(Token::kFunction);
4100 int function_token_position = position();
4101
4102 FunctionKind function_kind = Check(Token::kMul)
4105 IdentifierT name = impl()->NullIdentifier();
4106 bool is_strict_reserved_name = Token::IsStrictReservedWord(peek());
4107 Scanner::Location function_name_location = Scanner::Location::invalid();
4108 FunctionSyntaxKind function_syntax_kind =
4110 if (impl()->ParsingDynamicFunctionDeclaration()) {
4111 // We don't want dynamic functions to actually declare their name
4112 // "anonymous". We just want that name in the toString().
4113 Consume(Token::kIdentifier);
4115 scanner()->CurrentSymbol(ast_value_factory()) ==
4116 ast_value_factory()->anonymous_string());
4117 } else if (peek_any_identifier()) {
4118 name = ParseIdentifier(function_kind);
4119 function_name_location = scanner()->location();
4120 function_syntax_kind = FunctionSyntaxKind::kNamedExpression;
4121 }
4122 FunctionLiteralT result = impl()->ParseFunctionLiteral(
4123 name, function_name_location,
4124 is_strict_reserved_name ? kFunctionNameIsStrictReserved
4126 function_kind, function_token_position, function_syntax_kind,
4127 language_mode(), nullptr);
4128 // TODO(verwaest): FailureFunctionLiteral?
4129 if (impl()->IsNull(result)) return impl()->FailureExpression();
4130 return result;
4131}
4132
4133template <typename Impl>
4136 // MemberExpression ::
4137 // (PrimaryExpression | FunctionLiteral | ClassLiteral)
4138 // ('[' Expression ']' | '.' Identifier | Arguments | TemplateLiteral)*
4139 //
4140 // CallExpression ::
4141 // (SuperCall | ImportCall)
4142 // ('[' Expression ']' | '.' Identifier | Arguments | TemplateLiteral)*
4143 //
4144 // The '[' Expression ']' and '.' Identifier parts are parsed by
4145 // ParseMemberExpressionContinuation, and everything preceeding it is merged
4146 // into ParsePrimaryExpression.
4147
4148 // Parse the initial primary or function expression.
4151}
4152
4153template <typename Impl>
4156 // ImportCall[Yield, Await] :
4157 // import ( AssignmentExpression[+In, ?Yield, ?Await] )
4158 // import . source ( AssignmentExpression[+In, ?Yield, ?Await] )
4159 //
4160 // ImportMeta : import . meta
4161
4162 Consume(Token::kImport);
4163 int pos = position();
4164
4166
4167 // Distinguish import meta and import phase calls.
4168 if (Check(Token::kPeriod)) {
4169 if (v8_flags.js_source_phase_imports &&
4170 CheckContextualKeyword(ast_value_factory()->source_string())) {
4172 } else {
4173 ExpectContextualKeyword(ast_value_factory()->meta_string(), "import.meta",
4174 pos);
4175 if (!flags().is_module() && !IsParsingWhileDebugging()) {
4176 impl()->ReportMessageAt(scanner()->location(),
4177 MessageTemplate::kImportMetaOutsideModule);
4178 return impl()->FailureExpression();
4179 }
4180 return impl()->ImportMetaExpression(pos);
4181 }
4182 }
4183
4184 if (V8_UNLIKELY(peek() != Token::kLeftParen)) {
4185 if (!flags().is_module()) {
4186 impl()->ReportMessageAt(scanner()->location(),
4187 MessageTemplate::kImportOutsideModule);
4188 } else {
4190 }
4191 return impl()->FailureExpression();
4192 }
4193
4194 Consume(Token::kLeftParen);
4195 if (peek() == Token::kRightParen) {
4196 impl()->ReportMessageAt(scanner()->location(),
4197 MessageTemplate::kImportMissingSpecifier);
4198 return impl()->FailureExpression();
4199 }
4200
4201 AcceptINScope scope(this, true);
4203
4205 v8_flags.js_source_phase_imports);
4206 // TODO(42204365): Enable import attributes with source phase import once
4207 // specified.
4208 if (v8_flags.harmony_import_attributes &&
4209 phase == ModuleImportPhase::kEvaluation && Check(Token::kComma)) {
4210 if (Check(Token::kRightParen)) {
4211 // A trailing comma allowed after the specifier.
4212 return factory()->NewImportCallExpression(specifier, phase, pos);
4213 } else {
4215 Check(Token::kComma); // A trailing comma is allowed after the import
4216 // attributes.
4217 Expect(Token::kRightParen);
4218 return factory()->NewImportCallExpression(specifier, phase,
4219 import_options, pos);
4220 }
4221 }
4222
4223 Expect(Token::kRightParen);
4224 return factory()->NewImportCallExpression(specifier, phase, pos);
4225}
4226
4227template <typename Impl>
4230 Consume(Token::kSuper);
4231 int pos = position();
4232
4234 FunctionKind kind = scope->function_kind();
4237 if (Token::IsProperty(peek())) {
4238 if (peek() == Token::kPeriod && PeekAhead() == Token::kPrivateName) {
4239 Consume(Token::kPeriod);
4240 Consume(Token::kPrivateName);
4241
4242 impl()->ReportMessage(MessageTemplate::kUnexpectedPrivateField);
4243 return impl()->FailureExpression();
4244 }
4245 if (peek() == Token::kQuestionPeriod) {
4246 Consume(Token::kQuestionPeriod);
4247 impl()->ReportMessage(MessageTemplate::kOptionalChainingNoSuper);
4248 return impl()->FailureExpression();
4249 }
4250 scope->RecordSuperPropertyUsage();
4251 UseThis();
4252 return impl()->NewSuperPropertyReference(pos);
4253 }
4254 // super() is only allowed in derived constructor. new super() is never
4255 // allowed; it's reported as an error by
4256 // ParseMemberWithPresentNewPrefixesExpression.
4257 if (peek() == Token::kLeftParen && IsDerivedConstructor(kind)) {
4258 // TODO(rossberg): This might not be the correct FunctionState for the
4259 // method here.
4260 expression_scope()->RecordThisUse();
4261 UseThis();
4262 return impl()->NewSuperCallReference(pos);
4263 }
4264 }
4265
4266 impl()->ReportMessageAt(scanner()->location(),
4267 MessageTemplate::kUnexpectedSuper);
4268 return impl()->FailureExpression();
4269}
4270
4271template <typename Impl>
4274 int pos = position();
4275 Consume(Token::kPeriod);
4276 ExpectContextualKeyword(ast_value_factory()->target_string(), "new.target",
4277 pos);
4278
4279 if (!GetReceiverScope()->is_function_scope()) {
4280 impl()->ReportMessageAt(scanner()->location(),
4281 MessageTemplate::kUnexpectedNewTarget);
4282 return impl()->FailureExpression();
4283 }
4284
4285 return impl()->NewTargetExpression(pos);
4286}
4287
4288template <typename Impl>
4292 // Parses this part of MemberExpression:
4293 // ('[' Expression ']' | '.' Identifier | TemplateLiteral)*
4294 do {
4295 switch (peek()) {
4296 case Token::kLeftBracket: {
4297 Consume(Token::kLeftBracket);
4298 int pos = position();
4299 AcceptINScope scope(this, true);
4301 expression = factory()->NewProperty(expression, index, pos);
4302 impl()->PushPropertyName(index);
4303 Expect(Token::kRightBracket);
4304 break;
4305 }
4306 case Token::kPeriod: {
4307 Consume(Token::kPeriod);
4308 int pos = peek_position();
4310 expression = factory()->NewProperty(expression, key, pos);
4311 break;
4312 }
4313 default: {
4315 int pos;
4316 if (scanner()->current_token() == Token::kIdentifier) {
4317 pos = position();
4318 } else {
4319 pos = peek_position();
4320 if (expression->IsFunctionLiteral()) {
4321 // If the tag function looks like an IIFE, set_parenthesized() to
4322 // force eager compilation.
4323 expression->AsFunctionLiteral()->SetShouldEagerCompile();
4324 }
4325 }
4326 expression = ParseTemplateLiteral(expression, pos, true);
4327 break;
4328 }
4329 }
4330 } while (Token::IsMember(peek()));
4331 return expression;
4332}
4333
4334template <typename Impl>
4336 // FormalParameter[Yield,GeneratorParameter] :
4337 // BindingElement[?Yield, ?GeneratorParameter]
4338 FuncNameInferrerState fni_state(&fni_);
4339 int pos = peek_position();
4340 auto declaration_it = scope()->declarations()->end();
4342 if (impl()->IsIdentifier(pattern)) {
4343 ClassifyParameter(impl()->AsIdentifier(pattern), pos, end_position());
4344 } else {
4345 parameters->is_simple = false;
4346 }
4347
4348 ExpressionT initializer = impl()->NullExpression();
4349 if (Check(Token::kAssign)) {
4350 parameters->is_simple = false;
4351
4352 if (parameters->has_rest) {
4353 ReportMessage(MessageTemplate::kRestDefaultInitializer);
4354 return;
4355 }
4356
4357 AcceptINScope accept_in_scope(this, true);
4358 initializer = ParseAssignmentExpression();
4359 impl()->SetFunctionNameFromIdentifierRef(initializer, pattern);
4360 }
4361
4362 auto declaration_end = scope()->declarations()->end();
4363 int initializer_end = end_position();
4364 for (; declaration_it != declaration_end; ++declaration_it) {
4365 Variable* var = declaration_it->var();
4366
4367 // The first time a variable is initialized (i.e. when the initializer
4368 // position is unset), clear its maybe_assigned flag as it is not a true
4369 // assignment. Since this is done directly on the Variable objects, it has
4370 // no effect on VariableProxy objects appearing on the left-hand side of
4371 // true assignments, so x will be still be marked as maybe_assigned for:
4372 // (x = 1, y = (x = 2)) => {}
4373 // and even:
4374 // (x = (x = 2)) => {}.
4376 var->clear_maybe_assigned();
4377 var->set_initializer_position(initializer_end);
4378 }
4379
4380 impl()->AddFormalParameter(parameters, pattern, initializer, end_position(),
4381 parameters->has_rest);
4382}
4383
4384template <typename Impl>
4386 // FormalParameters[Yield] :
4387 // [empty]
4388 // FunctionRestParameter[?Yield]
4389 // FormalParameterList[?Yield]
4390 // FormalParameterList[?Yield] ,
4391 // FormalParameterList[?Yield] , FunctionRestParameter[?Yield]
4392 //
4393 // FormalParameterList[Yield] :
4394 // FormalParameter[?Yield]
4395 // FormalParameterList[?Yield] , FormalParameter[?Yield]
4396 ParameterParsingScope scope(impl(), parameters);
4397
4398 DCHECK_EQ(0, parameters->arity);
4399
4400 if (peek() != Token::kRightParen) {
4401 while (true) {
4402 parameters->has_rest = Check(Token::kEllipsis);
4403 ParseFormalParameter(parameters);
4404
4405 if (parameters->has_rest) {
4406 parameters->is_simple = false;
4407 if (peek() == Token::kComma) {
4408 impl()->ReportMessageAt(scanner()->peek_location(),
4409 MessageTemplate::kParamAfterRest);
4410 return;
4411 }
4412 break;
4413 }
4414 if (!Check(Token::kComma)) break;
4415 if (peek() == Token::kRightParen) {
4416 // allow the trailing comma
4417 break;
4418 }
4419 }
4420 }
4421
4422 if (parameters->arity + 1 /* receiver */ > Code::kMaxArguments) {
4423 ReportMessage(MessageTemplate::kTooManyParameters);
4424 return;
4425 }
4426
4427 impl()->DeclareFormalParameters(parameters);
4428}
4429
4430template <typename Impl>
4432 VariableDeclarationContext var_context,
4433 DeclarationParsingResult* parsing_result,
4435 // VariableDeclarations ::
4436 // ('var' | 'const' | 'let' | 'using' | 'await using') (Identifier ('='
4437 // AssignmentExpression)?)+[',']
4438 //
4439 // ES6:
4440 // FIXME(marja, nikolaos): Add an up-to-date comment about ES6 variable
4441 // declaration syntax.
4442
4443 DCHECK_NOT_NULL(parsing_result);
4444 parsing_result->descriptor.kind = NORMAL_VARIABLE;
4445 parsing_result->descriptor.declaration_pos = peek_position();
4446 parsing_result->descriptor.initialization_pos = peek_position();
4447
4448 Scope* target_scope = scope();
4449
4450 switch (peek()) {
4451 case Token::kVar:
4452 parsing_result->descriptor.mode = VariableMode::kVar;
4453 target_scope = scope()->GetDeclarationScope();
4454 Consume(Token::kVar);
4455 break;
4456 case Token::kConst:
4457 Consume(Token::kConst);
4458 DCHECK_NE(var_context, kStatement);
4459 parsing_result->descriptor.mode = VariableMode::kConst;
4460 break;
4461 case Token::kLet:
4462 Consume(Token::kLet);
4463 DCHECK_NE(var_context, kStatement);
4464 parsing_result->descriptor.mode = VariableMode::kLet;
4465 break;
4466 case Token::kUsing:
4467 // using [no LineTerminator here] BindingList[?In, ?Yield, ?Await,
4468 // ~Pattern] ;
4469 Consume(Token::kUsing);
4470 DCHECK(v8_flags.js_explicit_resource_management);
4471 DCHECK_NE(var_context, kStatement);
4473 DCHECK(!scanner()->HasLineTerminatorBeforeNext());
4474 DCHECK(peek() != Token::kLeftBracket && peek() != Token::kLeftBrace);
4476 parsing_result->descriptor.mode = VariableMode::kUsing;
4477 break;
4478 case Token::kAwait:
4479 // CoverAwaitExpressionAndAwaitUsingDeclarationHead[?Yield] [no
4480 // LineTerminator here] BindingList[?In, ?Yield, +Await, ~Pattern];
4481 Consume(Token::kAwait);
4482 DCHECK(v8_flags.js_explicit_resource_management);
4483 DCHECK_NE(var_context, kStatement);
4486 Consume(Token::kUsing);
4487 DCHECK(!scanner()->HasLineTerminatorBeforeNext());
4488 DCHECK(peek() != Token::kLeftBracket && peek() != Token::kLeftBrace);
4490 parsing_result->descriptor.mode = VariableMode::kAwaitUsing;
4491 if (!target_scope->has_await_using_declaration()) {
4493 }
4494 break;
4495 default:
4496 UNREACHABLE(); // by current callers
4497 break;
4498 }
4499
4501 impl(), parsing_result->descriptor.mode, names);
4502
4503 auto declaration_it = target_scope->declarations()->end();
4504
4505 int bindings_start = peek_position();
4506 do {
4507 // Parse binding pattern.
4508 FuncNameInferrerState fni_state(&fni_);
4509
4510 int decl_pos = peek_position();
4511
4514 // Check for an identifier first, so that we can elide the pattern in cases
4515 // where there is no initializer (and so no proxy needs to be created).
4519 impl()->IsEvalOrArguments(name))) {
4520 impl()->ReportMessageAt(scanner()->location(),
4521 MessageTemplate::kStrictEvalArguments);
4522 return;
4523 }
4524 if (peek() == Token::kAssign ||
4525 (var_context == kForStatement && PeekInOrOf()) ||
4526 parsing_result->descriptor.mode == VariableMode::kLet) {
4527 // Assignments need the variable expression for the assignment LHS, and
4528 // for of/in will need it later, so create the expression now.
4529 pattern = impl()->ExpressionFromIdentifier(name, decl_pos);
4530 } else {
4531 // Otherwise, elide the variable expression and just declare it.
4532 impl()->DeclareIdentifier(name, decl_pos);
4533 pattern = impl()->NullExpression();
4534 }
4535 } else if (parsing_result->descriptor.mode != VariableMode::kUsing &&
4536 parsing_result->descriptor.mode != VariableMode::kAwaitUsing) {
4537 name = impl()->NullIdentifier();
4539 DCHECK(!impl()->IsIdentifier(pattern));
4540 } else {
4541 // `using` declarations should have an identifier.
4542 impl()->ReportMessageAt(Scanner::Location(decl_pos, end_position()),
4543 MessageTemplate::kDeclarationMissingInitializer,
4544 "using");
4545 return;
4546 }
4547
4548 Scanner::Location variable_loc = scanner()->location();
4549
4550 ExpressionT value = impl()->NullExpression();
4551 int value_beg_pos = kNoSourcePosition;
4552 if (Check(Token::kAssign)) {
4553 DCHECK(!impl()->IsNull(pattern));
4554 {
4555 value_beg_pos = peek_position();
4556 AcceptINScope scope(this, var_context != kForStatement);
4557 value = ParseAssignmentExpression();
4558 }
4559 variable_loc.end_pos = end_position();
4560
4561 if (!parsing_result->first_initializer_loc.IsValid()) {
4562 parsing_result->first_initializer_loc = variable_loc;
4563 }
4564
4565 // Don't infer if it is "a = function(){...}();"-like expression.
4566 if (impl()->IsIdentifier(pattern)) {
4567 if (!value->IsCall() && !value->IsCallNew()) {
4568 fni_.Infer();
4569 } else {
4570 fni_.RemoveLastFunction();
4571 }
4572 }
4573
4574 impl()->SetFunctionNameFromIdentifierRef(value, pattern);
4575 } else {
4576#ifdef DEBUG
4577 // We can fall through into here on error paths, so don't DCHECK those.
4578 if (!has_error()) {
4579 // We should never get identifier patterns for the non-initializer path,
4580 // as those expressions should be elided.
4581 DCHECK_EQ(!impl()->IsNull(name),
4582 Token::IsAnyIdentifier(scanner()->current_token()));
4583 DCHECK_IMPLIES(impl()->IsNull(pattern), !impl()->IsNull(name));
4584 // The only times we have a non-null pattern are:
4585 // 1. This is a destructuring declaration (with no initializer, which
4586 // is immediately an error),
4587 // 2. This is a declaration in a for in/of loop, or
4588 // 3. This is a let (which has an implicit undefined initializer)
4590 !impl()->IsNull(pattern),
4591 !impl()->IsIdentifier(pattern) ||
4592 (var_context == kForStatement && PeekInOrOf()) ||
4593 parsing_result->descriptor.mode == VariableMode::kLet);
4594 }
4595#endif
4596
4597 if (var_context != kForStatement || !PeekInOrOf()) {
4598 // ES6 'const' and binding patterns require initializers.
4599 if (IsImmutableLexicalVariableMode(parsing_result->descriptor.mode) ||
4600 impl()->IsNull(name)) {
4601 impl()->ReportMessageAt(
4602 Scanner::Location(decl_pos, end_position()),
4603 MessageTemplate::kDeclarationMissingInitializer,
4604 impl()->IsNull(name) ? "destructuring"
4606 parsing_result->descriptor.mode));
4607 return;
4608 }
4609 // 'let x' initializes 'x' to undefined.
4610 if (parsing_result->descriptor.mode == VariableMode::kLet) {
4611 value = factory()->NewUndefinedLiteral(position());
4612 }
4613 }
4614 }
4615
4616 int initializer_position = end_position();
4617 auto declaration_end = target_scope->declarations()->end();
4618 for (; declaration_it != declaration_end; ++declaration_it) {
4619 declaration_it->var()->set_initializer_position(initializer_position);
4620 }
4621
4622 // Patterns should be elided iff. they don't have an initializer.
4624 impl()->IsNull(value) ||
4625 (var_context == kForStatement && PeekInOrOf()));
4626
4627 typename DeclarationParsingResult::Declaration decl(pattern, value);
4628 decl.value_beg_pos = value_beg_pos;
4629
4630 parsing_result->declarations.push_back(decl);
4631 } while (Check(Token::kComma));
4632
4633 parsing_result->bindings_loc =
4634 Scanner::Location(bindings_start, end_position());
4635}
4636
4637template <typename Impl>
4640 Consume(Token::kFunction);
4641
4642 int pos = position();
4644 if (Check(Token::kMul)) {
4645 impl()->ReportMessageAt(
4646 scanner()->location(),
4647 MessageTemplate::kGeneratorInSingleStatementContext);
4648 return impl()->NullStatement();
4649 }
4650 return ParseHoistableDeclaration(pos, flags, nullptr, false);
4651}
4652
4653template <typename Impl>
4656 ZonePtrList<const AstRawString>* names, bool default_export) {
4657 Consume(Token::kFunction);
4658
4659 int pos = position();
4661 if (Check(Token::kMul)) {
4663 }
4664 return ParseHoistableDeclaration(pos, flags, names, default_export);
4665}
4666
4667template <typename Impl>
4671 bool default_export) {
4673
4674 // FunctionDeclaration ::
4675 // 'function' Identifier '(' FormalParameters ')' '{' FunctionBody '}'
4676 // 'function' '(' FormalParameters ')' '{' FunctionBody '}'
4677 // GeneratorDeclaration ::
4678 // 'function' '*' Identifier '(' FormalParameters ')' '{' FunctionBody '}'
4679 // 'function' '*' '(' FormalParameters ')' '{' FunctionBody '}'
4680 //
4681 // The anonymous forms are allowed iff [default_export] is true.
4682 //
4683 // 'function' and '*' (if present) have been consumed by the caller.
4684
4686 (flags & ParseFunctionFlag::kIsGenerator) == 0);
4687
4688 if ((flags & ParseFunctionFlag::kIsAsync) != 0 && Check(Token::kMul)) {
4689 // Async generator
4691 }
4692
4694 FunctionNameValidity name_validity;
4695 IdentifierT variable_name;
4696 if (peek() == Token::kLeftParen) {
4697 if (default_export) {
4698 impl()->GetDefaultStrings(&name, &variable_name);
4699 name_validity = kSkipFunctionNameCheck;
4700 } else {
4701 ReportMessage(MessageTemplate::kMissingFunctionName);
4702 return impl()->NullStatement();
4703 }
4704 } else {
4705 bool is_strict_reserved = Token::IsStrictReservedWord(peek());
4706 name = ParseIdentifier();
4707 name_validity = is_strict_reserved ? kFunctionNameIsStrictReserved
4709 variable_name = name;
4710 }
4711
4712 FuncNameInferrerState fni_state(&fni_);
4713 impl()->PushEnclosingName(name);
4714
4715 FunctionKind function_kind = FunctionKindFor(flags);
4716
4717 FunctionLiteralT function = impl()->ParseFunctionLiteral(
4718 name, scanner()->location(), name_validity, function_kind, pos,
4720
4721 // In ES6, a function behaves as a lexical binding, except in
4722 // a script scope, or the initial scope of eval or another function.
4723 VariableMode mode =
4727 // Async functions don't undergo sloppy mode block scoped hoisting, and don't
4728 // allow duplicates in a block. Both are represented by the
4729 // sloppy_block_functions_. Don't add them to the map for async functions.
4730 // Generators are also supposed to be prohibited; currently doing this behind
4731 // a flag and UseCounting violations to assess web compatibility.
4737
4738 return impl()->DeclareFunction(variable_name, function, mode, kind, pos,
4739 end_position(), names);
4740}
4741
4742template <typename Impl>
4744 ZonePtrList<const AstRawString>* names, bool default_export) {
4745 // ClassDeclaration ::
4746 // 'class' Identifier ('extends' LeftHandExpression)? '{' ClassBody '}'
4747 // 'class' ('extends' LeftHandExpression)? '{' ClassBody '}'
4748 //
4749 // The anonymous form is allowed iff [default_export] is true.
4750 //
4751 // 'class' is expected to be consumed by the caller.
4752 //
4753 // A ClassDeclaration
4754 //
4755 // class C { ... }
4756 //
4757 // has the same semantics as:
4758 //
4759 // let C = class C { ... };
4760 //
4761 // so rewrite it as such.
4762
4763 int class_token_pos = position();
4764 IdentifierT name = impl()->EmptyIdentifierString();
4765 bool is_strict_reserved = Token::IsStrictReservedWord(peek());
4766 IdentifierT variable_name = impl()->NullIdentifier();
4767 if (default_export &&
4768 (peek() == Token::kExtends || peek() == Token::kLeftBrace)) {
4769 impl()->GetDefaultStrings(&name, &variable_name);
4770 } else {
4771 name = ParseIdentifier();
4772 variable_name = name;
4773 }
4774
4775 ExpressionParsingScope no_expression_scope(impl());
4776 ExpressionT value = ParseClassLiteral(scope(), name, scanner()->location(),
4777 is_strict_reserved, class_token_pos);
4778 no_expression_scope.ValidateExpression();
4779 int end_pos = position();
4780 return impl()->DeclareClass(variable_name, value, names, class_token_pos,
4781 end_pos);
4782}
4783
4784// Language extension which is only enabled for source files loaded
4785// through the API's extension mechanism. A native function
4786// declaration is resolved by looking up the function through a
4787// callback provided by the extension.
4788template <typename Impl>
4791 function_state_->DisableOptimization(BailoutReason::kNativeFunctionLiteral);
4792
4793 int pos = peek_position();
4794 Consume(Token::kFunction);
4795 // Allow "eval" or "arguments" for backward compatibility.
4797 Expect(Token::kLeftParen);
4798 if (peek() != Token::kRightParen) {
4799 do {
4801 } while (Check(Token::kComma));
4802 }
4803 Expect(Token::kRightParen);
4804 Expect(Token::kSemicolon);
4805 return impl()->DeclareNative(name, pos);
4806}
4807
4808template <typename Impl>
4811 ZonePtrList<const AstRawString>* names, bool default_export) {
4812 // AsyncFunctionDeclaration ::
4813 // async [no LineTerminator here] function BindingIdentifier[Await]
4814 // ( FormalParameters[Await] ) { AsyncFunctionBody }
4815 DCHECK_EQ(scanner()->current_token(), Token::kAsync);
4816 if (V8_UNLIKELY(scanner()->literal_contains_escapes())) {
4817 impl()->ReportUnexpectedToken(Token::kEscapedKeyword);
4818 }
4819 int pos = position();
4820 DCHECK(!scanner()->HasLineTerminatorBeforeNext());
4821 Consume(Token::kFunction);
4823 return ParseHoistableDeclaration(pos, flags, names, default_export);
4824}
4825
4826template <typename Impl>
4828 StatementListT* body, IdentifierT function_name, int pos,
4829 const FormalParametersT& parameters, FunctionKind kind,
4830 FunctionSyntaxKind function_syntax_kind, FunctionBodyType body_type) {
4832
4833 if (IsResumableFunction(kind)) impl()->PrepareGeneratorVariables();
4834
4835 DeclarationScope* function_scope = parameters.scope;
4836 DeclarationScope* inner_scope = function_scope;
4837
4838 // Building the parameter initialization block declares the parameters.
4839 // TODO(verwaest): Rely on ArrowHeadParsingScope instead.
4840 if (V8_UNLIKELY(!parameters.is_simple)) {
4841 if (has_error()) return;
4842 body->Add(impl()->BuildParameterInitializationBlock(parameters));
4843 if (has_error()) return;
4844
4845 inner_scope = NewVarblockScope();
4846 inner_scope->set_start_position(position());
4847 }
4848
4849 StatementListT inner_body(pointer_buffer());
4850
4851 {
4852 BlockState block_state(&scope_, inner_scope);
4853
4854 if (body_type == FunctionBodyType::kExpression) {
4856 inner_body.Add(BuildReturnStatement(expression, expression->position()));
4857 } else {
4860 // If we are parsing the source as if it is wrapped in a function, the
4861 // source ends without a closing brace.
4862 Token::Value closing_token =
4863 function_syntax_kind == FunctionSyntaxKind::kWrapped
4864 ? Token::kEos
4865 : Token::kRightBrace;
4866
4868 impl()->ParseAsyncGeneratorFunctionBody(pos, kind, &inner_body);
4869 } else if (IsGeneratorFunction(kind)) {
4870 impl()->ParseGeneratorFunctionBody(pos, kind, &inner_body);
4871 } else {
4872 ParseStatementList(&inner_body, closing_token);
4873 if (IsAsyncFunction(kind)) {
4874 inner_scope->set_end_position(end_position());
4875 }
4876 }
4878 // Derived constructors are implemented by returning `this` when the
4879 // original return value is undefined, so always use `this`.
4881 UseThis();
4882 expression_scope.ValidateExpression();
4883 }
4884 Expect(closing_token);
4885 }
4886 }
4887
4889
4890 bool allow_duplicate_parameters = false;
4891
4893
4894 if (V8_LIKELY(parameters.is_simple)) {
4895 DCHECK_EQ(inner_scope, function_scope);
4896 if (is_sloppy(function_scope->language_mode())) {
4897 impl()->InsertSloppyBlockFunctionVarBindings(function_scope);
4898 }
4899 allow_duplicate_parameters =
4900 is_sloppy(function_scope->language_mode()) && !IsConciseMethod(kind);
4901 } else {
4902 DCHECK_NOT_NULL(inner_scope);
4903 DCHECK_EQ(function_scope, scope());
4904 DCHECK_EQ(function_scope, inner_scope->outer_scope());
4905 impl()->SetLanguageMode(function_scope, inner_scope->language_mode());
4906
4907 if (is_sloppy(inner_scope->language_mode())) {
4908 impl()->InsertSloppyBlockFunctionVarBindings(inner_scope);
4909 }
4910
4911 inner_scope->set_end_position(end_position());
4912 if (inner_scope->FinalizeBlockScope() != nullptr) {
4913 BlockT inner_block = factory()->NewBlock(true, inner_body);
4914 inner_body.Rewind();
4915 inner_body.Add(inner_block);
4916 inner_block->set_scope(inner_scope);
4917 impl()->RecordBlockSourceRange(inner_block, scope()->end_position());
4918 if (!impl()->HasCheckedSyntax()) {
4919 const AstRawString* conflict = inner_scope->FindVariableDeclaredIn(
4921 if (conflict != nullptr) {
4922 impl()->ReportVarRedeclarationIn(conflict, inner_scope);
4923 }
4924 }
4925
4926 // According to ES#sec-functiondeclarationinstantiation step 27,28
4927 // when hasParameterExpressions is true, we need bind var declared
4928 // arguments to "arguments exotic object", so we here first declare
4929 // "arguments exotic object", then var declared arguments will be
4930 // initialized with "arguments exotic object"
4931 if (!IsArrowFunction(kind)) {
4932 function_scope->DeclareArguments(ast_value_factory());
4933 }
4934
4935 impl()->InsertShadowingVarBindingInitializers(inner_block);
4936 }
4937 }
4938
4940 allow_duplicate_parameters);
4941
4942 if (!IsArrowFunction(kind)) {
4943 function_scope->DeclareArguments(ast_value_factory());
4944 }
4945
4946 impl()->DeclareFunctionNameVar(function_name, function_syntax_kind,
4947 function_scope);
4948
4949 inner_body.MergeInto(body);
4950}
4951
4952template <typename Impl>
4954 FunctionKind function_kind,
4955 bool has_rest,
4956 int formals_start_pos,
4957 int formals_end_pos) {
4958 if (impl()->HasCheckedSyntax()) return;
4959 if (IsGetterFunction(function_kind)) {
4960 if (param_count != 0) {
4961 impl()->ReportMessageAt(
4962 Scanner::Location(formals_start_pos, formals_end_pos),
4963 MessageTemplate::kBadGetterArity);
4964 }
4965 } else if (IsSetterFunction(function_kind)) {
4966 if (param_count != 1) {
4967 impl()->ReportMessageAt(
4968 Scanner::Location(formals_start_pos, formals_end_pos),
4969 MessageTemplate::kBadSetterArity);
4970 }
4971 if (has_rest) {
4972 impl()->ReportMessageAt(
4973 Scanner::Location(formals_start_pos, formals_end_pos),
4974 MessageTemplate::kBadSetterRestParameter);
4975 }
4976 }
4977}
4978
4979template <typename Impl>
4981 DCHECK_EQ(Token::kLet, peek());
4982 Token::Value next_next = PeekAhead();
4983 switch (next_next) {
4984 case Token::kLeftBrace:
4985 case Token::kLeftBracket:
4986 case Token::kIdentifier:
4987 case Token::kStatic:
4988 case Token::kLet: // `let let;` is disallowed by static semantics, but the
4989 // token must be first interpreted as a keyword in order
4990 // for those semantics to apply. This ensures that ASI is
4991 // not honored when a LineTerminator separates the
4992 // tokens.
4993 case Token::kYield:
4994 case Token::kAwait:
4995 case Token::kGet:
4996 case Token::kSet:
4997 case Token::kOf:
4998 case Token::kUsing:
4999 case Token::kAccessor:
5000 case Token::kAsync:
5001 return true;
5002 case Token::kFutureStrictReservedWord:
5003 case Token::kEscapedStrictReservedWord:
5004 // The early error rule for future reserved keywords
5005 // (ES#sec-identifiers-static-semantics-early-errors) uses the static
5006 // semantics StringValue of IdentifierName, which normalizes escape
5007 // sequences. So, both escaped and unescaped future reserved keywords are
5008 // allowed as identifiers in sloppy mode.
5009 return is_sloppy(language_mode());
5010 default:
5011 return false;
5012 }
5013}
5014
5015template <typename Impl>
5018 const FormalParametersT& formal_parameters, int function_literal_id,
5019 bool could_be_immediately_invoked) {
5021 Impl::IsPreParser()
5022 ? RuntimeCallCounterId::kPreParseArrowFunctionLiteral
5023 : RuntimeCallCounterId::kParseArrowFunctionLiteral,
5024 RuntimeCallStats::kThreadSpecific);
5025 base::ElapsedTimer timer;
5026 if (V8_UNLIKELY(v8_flags.log_function_events)) timer.Start();
5027
5028 DCHECK_IMPLIES(!has_error(), peek() == Token::kArrow);
5029 if (!impl()->HasCheckedSyntax() && scanner_->HasLineTerminatorBeforeNext()) {
5030 // No line terminator allowed between the parameters and the arrow:
5031 // ArrowFunction[In, Yield, Await] :
5032 // ArrowParameters[?Yield, ?Await] [no LineTerminator here] =>
5033 // ConciseBody[?In]
5034 // If the next token is not `=>`, it's a syntax error anyway.
5035 impl()->ReportUnexpectedTokenAt(scanner_->peek_location(), Token::kArrow);
5036 return impl()->FailureExpression();
5037 }
5038
5039 int expected_property_count = 0;
5040 int suspend_count = 0;
5041
5042 FunctionKind kind = formal_parameters.scope->function_kind();
5043 int compile_hint_position = formal_parameters.scope->start_position();
5044 FunctionLiteral::EagerCompileHint eager_compile_hint =
5045 could_be_immediately_invoked ||
5049 scanner_->HasPerFunctionCompileHint(compile_hint_position))
5052
5053 eager_compile_hint =
5054 impl()->GetEmbedderCompileHint(eager_compile_hint, compile_hint_position);
5055
5056 bool can_preparse = impl()->parse_lazily() &&
5057 eager_compile_hint == FunctionLiteral::kShouldLazyCompile;
5058 // TODO(marja): consider lazy-parsing inner arrow functions too. is_this
5059 // handling in Scope::ResolveVariable needs to change.
5060 bool is_lazy_top_level_function =
5061 can_preparse && impl()->AllowsLazyParsingWithoutUnresolvedVariables();
5062 bool has_braces = true;
5063 ProducedPreparseData* produced_preparse_data = nullptr;
5065 {
5066 FunctionState function_state(&function_state_, &scope_,
5067 formal_parameters.scope);
5068
5069 Consume(Token::kArrow);
5070
5071 if (peek() == Token::kLeftBrace) {
5072 // Multiple statement body
5073 DCHECK_EQ(scope(), formal_parameters.scope);
5074
5075 if (is_lazy_top_level_function) {
5076 // FIXME(marja): Arrow function parameters will be parsed even if the
5077 // body is preparsed; move relevant parts of parameter handling to
5078 // simulate consistent parameter handling.
5079
5080 // Building the parameter initialization block declares the parameters.
5081 // TODO(verwaest): Rely on ArrowHeadParsingScope instead.
5082 if (!formal_parameters.is_simple) {
5083 impl()->BuildParameterInitializationBlock(formal_parameters);
5084 if (has_error()) return impl()->FailureExpression();
5085 }
5086
5087 // For arrow functions, we don't need to retrieve data about function
5088 // parameters.
5089 int dummy_num_parameters = -1;
5090 int dummy_function_length = -1;
5092 bool did_preparse_successfully = impl()->SkipFunction(
5094 formal_parameters.scope, &dummy_num_parameters,
5095 &dummy_function_length, &produced_preparse_data);
5096
5097 DCHECK_NULL(produced_preparse_data);
5098
5099 if (did_preparse_successfully) {
5100 // Validate parameter names. We can do this only after preparsing the
5101 // function, since the function can declare itself strict.
5102 ValidateFormalParameters(language_mode(), formal_parameters, false);
5103 } else {
5104 // In case we did not sucessfully preparse the function because of an
5105 // unidentified error we do a full reparse to return the error.
5106 // Parse again in the outer scope, since the language mode may change.
5107 BlockState block_state(&scope_, scope()->outer_scope());
5109 // Reparsing the head may have caused a stack overflow.
5110 if (has_error()) return impl()->FailureExpression();
5111
5113 FunctionState inner_function_state(&function_state_, &scope_,
5114 function_scope);
5115 Scanner::Location loc(function_scope->start_position(),
5116 end_position());
5117 FormalParametersT parameters(function_scope);
5118 parameters.is_simple = function_scope->has_simple_parameters();
5119 impl()->DeclareArrowFunctionFormalParameters(&parameters, expression,
5120 loc);
5122
5123 Consume(Token::kArrow);
5124 Consume(Token::kLeftBrace);
5125
5126 AcceptINScope scope(this, true);
5127 FunctionParsingScope body_parsing_scope(impl());
5128 ParseFunctionBody(&body, impl()->NullIdentifier(), kNoSourcePosition,
5129 parameters, kind,
5132 CHECK(has_error());
5133 return impl()->FailureExpression();
5134 }
5135 } else {
5136 Consume(Token::kLeftBrace);
5137 AcceptINScope scope(this, true);
5138 FunctionParsingScope body_parsing_scope(impl());
5139 ParseFunctionBody(&body, impl()->NullIdentifier(), kNoSourcePosition,
5140 formal_parameters, kind,
5143 expected_property_count = function_state.expected_property_count();
5144 }
5145 } else {
5146 // Single-expression body
5147 has_braces = false;
5148 FunctionParsingScope body_parsing_scope(impl());
5149 ParseFunctionBody(&body, impl()->NullIdentifier(), kNoSourcePosition,
5150 formal_parameters, kind,
5153 expected_property_count = function_state.expected_property_count();
5154 }
5155
5156 formal_parameters.scope->set_end_position(end_position());
5157
5158 // Validate strict mode.
5159 if (is_strict(language_mode())) {
5160 CheckStrictOctalLiteral(formal_parameters.scope->start_position(),
5161 end_position());
5162 }
5163 suspend_count = function_state.suspend_count();
5164 }
5165
5166 FunctionLiteralT function_literal = factory()->NewFunctionLiteral(
5167 impl()->EmptyIdentifierString(), formal_parameters.scope, body,
5168 expected_property_count, formal_parameters.num_parameters(),
5169 formal_parameters.function_length,
5171 FunctionSyntaxKind::kAnonymousExpression, eager_compile_hint,
5172 formal_parameters.scope->start_position(), has_braces,
5173 function_literal_id, produced_preparse_data);
5174
5175 function_literal->set_suspend_count(suspend_count);
5176 function_literal->set_function_token_position(
5177 formal_parameters.scope->start_position());
5178
5179 impl()->RecordFunctionLiteralSourceRange(function_literal);
5180 impl()->AddFunctionForNameInference(function_literal);
5181
5182 if (V8_UNLIKELY(v8_flags.log_function_events)) {
5183 Scope* scope = formal_parameters.scope;
5184 double ms = timer.Elapsed().InMillisecondsF();
5185 const char* event_name =
5186 is_lazy_top_level_function ? "preparse-no-resolution" : "parse";
5187 const char* name = "arrow function";
5188 v8_file_logger_->FunctionEvent(event_name, flags().script_id(), ms,
5190 scope->end_position(), name, strlen(name));
5191 }
5192
5193 return function_literal;
5194}
5195
5196template <typename Impl>
5198 Scope* outer_scope) {
5199 Consume(Token::kClass);
5200 int class_token_pos = position();
5201 IdentifierT name = impl()->EmptyIdentifierString();
5202 bool is_strict_reserved_name = false;
5203 Scanner::Location class_name_location = Scanner::Location::invalid();
5204 if (peek_any_identifier()) {
5206 class_name_location = scanner()->location();
5207 is_strict_reserved_name =
5208 Token::IsStrictReservedWord(scanner()->current_token());
5209 }
5210 return ParseClassLiteral(outer_scope, name, class_name_location,
5211 is_strict_reserved_name, class_token_pos);
5212}
5213
5214template <typename Impl>
5216 Scope* outer_scope, IdentifierT name, Scanner::Location class_name_location,
5217 bool name_is_strict_reserved, int class_token_pos) {
5218 bool is_anonymous = impl()->IsEmptyIdentifier(name);
5219
5220 // All parts of a ClassDeclaration and ClassExpression are strict code.
5221 if (!impl()->HasCheckedSyntax() && !is_anonymous) {
5222 if (name_is_strict_reserved) {
5223 impl()->ReportMessageAt(class_name_location,
5224 MessageTemplate::kUnexpectedStrictReserved);
5225 return impl()->FailureExpression();
5226 }
5227 if (impl()->IsEvalOrArguments(name)) {
5228 impl()->ReportMessageAt(class_name_location,
5229 MessageTemplate::kStrictEvalArguments);
5230 return impl()->FailureExpression();
5231 }
5232 }
5233
5234 ClassScope* class_scope = NewClassScope(outer_scope, is_anonymous);
5235 BlockState block_state(&scope_, class_scope);
5237
5238 BlockState object_literal_scope_state(&object_literal_scope_, nullptr);
5239
5240 ClassInfo class_info(this);
5241 class_info.is_anonymous = is_anonymous;
5242
5243 scope()->set_start_position(class_token_pos);
5244 if (Check(Token::kExtends)) {
5245 ClassScope::HeritageParsingScope heritage(class_scope);
5246 FuncNameInferrerState fni_state(&fni_);
5248 class_info.extends = ParseLeftHandSideExpression();
5249 scope.ValidateExpression();
5250 }
5251
5252 Expect(Token::kLeftBrace);
5253
5254 ParseClassLiteralBody(class_info, name, class_token_pos, Token::kRightBrace);
5255
5256 CheckStrictOctalLiteral(scope()->start_position(), scope()->end_position());
5257
5258 VariableProxy* unresolvable = class_scope->ResolvePrivateNamesPartially();
5259 if (unresolvable != nullptr) {
5260 impl()->ReportMessageAt(Scanner::Location(unresolvable->position(),
5261 unresolvable->position() + 1),
5262 MessageTemplate::kInvalidPrivateFieldResolution,
5263 unresolvable->raw_name());
5264 return impl()->FailureExpression();
5265 }
5266
5267 if (class_info.requires_brand) {
5268 class_scope->DeclareBrandVariable(
5270 }
5271
5272 if (class_scope->needs_home_object()) {
5273 class_info.home_object_variable =
5275 class_info.static_home_object_variable =
5277 }
5278
5279 bool should_save_class_variable_index =
5280 class_scope->should_save_class_variable_index();
5281 if (!class_info.is_anonymous || should_save_class_variable_index) {
5282 impl()->DeclareClassVariable(class_scope, name, &class_info,
5283 class_token_pos);
5284 if (should_save_class_variable_index) {
5285 class_scope->class_variable()->set_is_used();
5286 class_scope->class_variable()->ForceContextAllocation();
5287 }
5288 }
5289
5290 return impl()->RewriteClassLiteral(class_scope, name, &class_info,
5291 class_token_pos);
5292}
5293
5294template <typename Impl>
5296 IdentifierT name,
5297 int class_token_pos,
5298 Token::Value end_token) {
5299 bool has_extends = !impl()->IsNull(class_info.extends);
5300
5301 while (peek() != end_token) {
5302 if (Check(Token::kSemicolon)) continue;
5303
5304 // Either we're parsing a `static { }` initialization block or a property.
5305 if (peek() == Token::kStatic && PeekAhead() == Token::kLeftBrace) {
5306 BlockT static_block = ParseClassStaticBlock(&class_info);
5307 impl()->AddClassStaticBlock(static_block, &class_info);
5308 continue;
5309 }
5310
5311 FuncNameInferrerState fni_state(&fni_);
5312 // If we haven't seen the constructor yet, it potentially is the next
5313 // property.
5314 bool is_constructor = !class_info.has_seen_constructor;
5315 ParsePropertyInfo prop_info(this);
5317
5318 ClassLiteralPropertyT property =
5319 ParseClassPropertyDefinition(&class_info, &prop_info, has_extends);
5320
5321 if (has_error()) return;
5322
5323 ClassLiteralProperty::Kind property_kind =
5324 ClassPropertyKindFor(prop_info.kind);
5325
5326 if (!class_info.has_static_computed_names && prop_info.is_static &&
5327 prop_info.is_computed_name) {
5328 class_info.has_static_computed_names = true;
5329 }
5331
5332 bool is_field = property_kind == ClassLiteralProperty::FIELD;
5333
5334 if (V8_UNLIKELY(prop_info.is_private)) {
5336 class_info.requires_brand |= (!is_field && !prop_info.is_static);
5338 (prop_info.is_static && !is_field);
5339
5340 impl()->DeclarePrivateClassMember(scope()->AsClassScope(), prop_info.name,
5341 property, property_kind,
5342 prop_info.is_static, &class_info);
5343 impl()->InferFunctionName();
5344 continue;
5345 }
5346
5347 if (V8_UNLIKELY(is_field)) {
5348 DCHECK(!prop_info.is_private);
5349 // If we're reparsing, we might not have a class scope. We only need a
5350 // class scope if we have a computed name though, and in that case we're
5351 // certain that the current scope must be a class scope.
5352 ClassScope* class_scope = nullptr;
5353 if (prop_info.is_computed_name) {
5354 class_info.computed_field_count++;
5355 class_scope = scope()->AsClassScope();
5356 }
5357
5358 impl()->DeclarePublicClassField(class_scope, property,
5359 prop_info.is_static,
5360 prop_info.is_computed_name, &class_info);
5361 impl()->InferFunctionName();
5362 continue;
5363 }
5364
5365 if (property_kind == ClassLiteralProperty::Kind::AUTO_ACCESSOR) {
5366 // Private auto-accessors are handled above with the other private
5367 // properties.
5368 DCHECK(!prop_info.is_private);
5369 impl()->AddInstanceFieldOrStaticElement(property, &class_info,
5370 prop_info.is_static);
5371 }
5372
5373 impl()->DeclarePublicClassMethod(name, property, is_constructor,
5374 &class_info);
5375 impl()->InferFunctionName();
5376 }
5377
5378 Expect(end_token);
5380}
5381
5382template <typename Impl>
5385 // AsyncFunctionLiteral ::
5386 // async [no LineTerminator here] function ( FormalParameters[Await] )
5387 // { AsyncFunctionBody }
5388 //
5389 // async [no LineTerminator here] function BindingIdentifier[Await]
5390 // ( FormalParameters[Await] ) { AsyncFunctionBody }
5391 DCHECK_EQ(scanner()->current_token(), Token::kAsync);
5392 if (V8_UNLIKELY(scanner()->literal_contains_escapes())) {
5393 impl()->ReportUnexpectedToken(Token::kEscapedKeyword);
5394 }
5395 int pos = position();
5396 Consume(Token::kFunction);
5397 IdentifierT name = impl()->NullIdentifier();
5399
5401 if (Check(Token::kMul)) flags |= ParseFunctionFlag::kIsGenerator;
5402 const FunctionKind kind = FunctionKindFor(flags);
5403 bool is_strict_reserved = Token::IsStrictReservedWord(peek());
5404
5405 if (impl()->ParsingDynamicFunctionDeclaration()) {
5406 // We don't want dynamic functions to actually declare their name
5407 // "anonymous". We just want that name in the toString().
5408
5409 // Consuming token we did not peek yet, which could lead to a kIllegal token
5410 // in the case of a stackoverflow.
5411 Consume(Token::kIdentifier);
5413 scanner()->CurrentSymbol(ast_value_factory()) ==
5414 ast_value_factory()->anonymous_string());
5415 } else if (peek_any_identifier()) {
5417 name = ParseIdentifier(kind);
5418 }
5419 FunctionLiteralT result = impl()->ParseFunctionLiteral(
5420 name, scanner()->location(),
5421 is_strict_reserved ? kFunctionNameIsStrictReserved
5423 kind, pos, syntax_kind, language_mode(), nullptr);
5424 if (impl()->IsNull(result)) return impl()->FailureExpression();
5425 return result;
5426}
5427
5428template <typename Impl>
5430 ExpressionT tag, int start, bool tagged) {
5431 // A TemplateLiteral is made up of 0 or more kTemplateSpan tokens (literal
5432 // text followed by a substitution expression), finalized by a single
5433 // kTemplateTail.
5434 //
5435 // In terms of draft language, kTemplateSpan may be either the TemplateHead or
5436 // TemplateMiddle productions, while kTemplateTail is either TemplateTail, or
5437 // NoSubstitutionTemplate.
5438 //
5439 // When parsing a TemplateLiteral, we must have scanned either an initial
5440 // kTemplateSpan, or a kTemplateTail.
5441 DCHECK(peek() == Token::kTemplateSpan || peek() == Token::kTemplateTail);
5442
5443 if (tagged) {
5444 // TaggedTemplate expressions prevent the eval compilation cache from being
5445 // used. This flag is only used if an eval is being parsed.
5446 set_allow_eval_cache(false);
5447 }
5448
5449 bool forbid_illegal_escapes = !tagged;
5450
5451 // If we reach a kTemplateTail first, we are parsing a NoSubstitutionTemplate.
5452 // In this case we may simply consume the token and build a template with a
5453 // single kTemplateSpan and no expressions.
5454 if (peek() == Token::kTemplateTail) {
5455 Consume(Token::kTemplateTail);
5456 int pos = position();
5457 typename Impl::TemplateLiteralState ts = impl()->OpenTemplateLiteral(pos);
5458 bool is_valid = CheckTemplateEscapes(forbid_illegal_escapes);
5459 impl()->AddTemplateSpan(&ts, is_valid, true);
5460 return impl()->CloseTemplateLiteral(&ts, start, tag);
5461 }
5462
5463 Consume(Token::kTemplateSpan);
5464 int pos = position();
5465 typename Impl::TemplateLiteralState ts = impl()->OpenTemplateLiteral(pos);
5466 bool is_valid = CheckTemplateEscapes(forbid_illegal_escapes);
5467 impl()->AddTemplateSpan(&ts, is_valid, false);
5468 Token::Value next;
5469
5470 // If we open with a kTemplateSpan, we must scan the subsequent expression,
5471 // and repeat if the following token is a kTemplateSpan as well (in this
5472 // case, representing a TemplateMiddle).
5473
5474 do {
5475 next = peek();
5476
5477 int expr_pos = peek_position();
5478 AcceptINScope scope(this, true);
5480 impl()->AddTemplateExpression(&ts, expression);
5481
5482 if (peek() != Token::kRightBrace) {
5483 impl()->ReportMessageAt(Scanner::Location(expr_pos, peek_position()),
5484 MessageTemplate::kUnterminatedTemplateExpr);
5485 return impl()->FailureExpression();
5486 }
5487
5488 // If we didn't die parsing that expression, our next token should be a
5489 // kTemplateSpan or kTemplateTail.
5491 Next();
5492 pos = position();
5493
5494 is_valid = CheckTemplateEscapes(forbid_illegal_escapes);
5495 impl()->AddTemplateSpan(&ts, is_valid, next == Token::kTemplateTail);
5496 } while (next == Token::kTemplateSpan);
5497
5498 DCHECK_IMPLIES(!has_error(), next == Token::kTemplateTail);
5499 // Once we've reached a kTemplateTail, we can close the TemplateLiteral.
5500 return impl()->CloseTemplateLiteral(&ts, start, tag);
5501}
5502
5503template <typename Impl>
5506 int beg_pos, int end_pos,
5507 MessageTemplate message,
5508 bool early_error) {
5509 DCHECK(!IsValidReferenceExpression(expression));
5510 if (impl()->IsIdentifier(expression)) {
5512 DCHECK(impl()->IsEvalOrArguments(impl()->AsIdentifier(expression)));
5513
5514 ReportMessageAt(Scanner::Location(beg_pos, end_pos),
5515 MessageTemplate::kStrictEvalArguments);
5516 return impl()->FailureExpression();
5517 }
5518 if (expression->IsCall() && !expression->AsCall()->is_tagged_template() &&
5519 !early_error) {
5520 expression_scope()->RecordPatternError(
5521 Scanner::Location(beg_pos, end_pos),
5522 MessageTemplate::kInvalidDestructuringTarget);
5523 // If it is a call, make it a runtime error for legacy web compatibility.
5524 // Bug: https://bugs.chromium.org/p/v8/issues/detail?id=4480
5525 // Rewrite `expr' to `expr[throw ReferenceError]'.
5526 impl()->CountUsage(
5530 ExpressionT error = impl()->NewThrowReferenceError(message, beg_pos);
5531 return factory()->NewProperty(expression, error, beg_pos);
5532 }
5533 // Tagged templates and other modern language features (which pass early_error
5534 // = true) are exempt from the web compatibility hack. Throw a regular early
5535 // error.
5536 ReportMessageAt(Scanner::Location(beg_pos, end_pos), message);
5537 return impl()->FailureExpression();
5538}
5539
5540template <typename Impl>
5542 int end) {
5543 if (impl()->IsEvalOrArguments(parameter)) {
5544 expression_scope()->RecordStrictModeParameterError(
5545 Scanner::Location(begin, end), MessageTemplate::kStrictEvalArguments);
5546 }
5547}
5548
5549template <typename Impl>
5551 AccumulationScope* accumulation_scope, int position,
5552 ExpressionT parameter) {
5553 accumulation_scope->Accumulate();
5554 if (parameter->is_parenthesized() ||
5555 !(impl()->IsIdentifier(parameter) || parameter->IsPattern() ||
5556 parameter->IsAssignment())) {
5557 expression_scope()->RecordDeclarationError(
5559 MessageTemplate::kInvalidDestructuringTarget);
5560 } else if (impl()->IsIdentifier(parameter)) {
5561 ClassifyParameter(impl()->AsIdentifier(parameter), position,
5562 end_position());
5563 } else {
5564 expression_scope()->RecordNonSimpleParameter();
5565 }
5566}
5567
5568template <typename Impl>
5570 return IsAssignableIdentifier(expression) || expression->IsProperty();
5571}
5572
5573template <typename Impl>
5577 if (scope) scope->Accumulate();
5578 int begin = peek_position();
5580
5582 // Parenthesized identifiers and property references are allowed as part of
5583 // a larger assignment pattern, even though parenthesized patterns
5584 // themselves are not allowed, e.g., "[(x)] = []". Only accumulate
5585 // assignment pattern errors if the parsed expression is more complex.
5586 if (impl()->IsIdentifier(result)) {
5587 if (result->is_parenthesized()) {
5588 expression_scope()->RecordDeclarationError(
5590 MessageTemplate::kInvalidDestructuringTarget);
5591 }
5592 IdentifierT identifier = impl()->AsIdentifier(result);
5594 } else {
5595 DCHECK(result->IsProperty());
5596 expression_scope()->RecordDeclarationError(
5598 MessageTemplate::kInvalidPropertyBindingPattern);
5599 if (scope != nullptr) scope->ValidateExpression();
5600 }
5601 } else if (result->is_parenthesized() ||
5602 (!result->IsPattern() && !result->IsAssignment())) {
5603 expression_scope()->RecordPatternError(
5605 MessageTemplate::kInvalidDestructuringTarget);
5606 }
5607
5608 return result;
5609}
5610
5611template <typename Impl>
5613 // CallRuntime ::
5614 // '%' Identifier Arguments
5615
5616 int pos = peek_position();
5617 Consume(Token::kMod);
5618 // Allow "eval" or "arguments" for backward compatibility.
5620 if (peek() != Token::kLeftParen) {
5621 impl()->ReportUnexpectedToken(peek());
5622 return impl()->FailureExpression();
5623 }
5624 bool has_spread;
5626 ParseArguments(&args, &has_spread);
5627
5628 if (has_spread) {
5630 MessageTemplate::kIntrinsicWithSpread);
5631 return impl()->FailureExpression();
5632 }
5633
5634 return impl()->NewV8Intrinsic(name, args, pos);
5635}
5636
5637template <typename Impl>
5639 Token::Value end_token) {
5640 // StatementList ::
5641 // (StatementListItem)* <end_token>
5642 DCHECK_NOT_NULL(body);
5643
5644 while (peek() == Token::kString) {
5645 bool use_strict = false;
5646#if V8_ENABLE_WEBASSEMBLY
5647 bool use_asm = false;
5648#endif // V8_ENABLE_WEBASSEMBLY
5649
5650 Scanner::Location token_loc = scanner()->peek_location();
5651
5652 if (scanner()->NextLiteralExactlyEquals("use strict")) {
5653 use_strict = true;
5654#if V8_ENABLE_WEBASSEMBLY
5655 } else if (scanner()->NextLiteralExactlyEquals("use asm")) {
5656 use_asm = true;
5657#endif // V8_ENABLE_WEBASSEMBLY
5658 }
5659
5661 if (impl()->IsNull(stat)) return;
5662
5663 body->Add(stat);
5664
5665 if (!impl()->IsStringLiteral(stat)) break;
5666
5667 if (use_strict) {
5668 // Directive "use strict" (ES5 14.1).
5670 if (!scope()->HasSimpleParameters()) {
5671 // TC39 deemed "use strict" directives to be an error when occurring
5672 // in the body of a function with non-simple parameter list, on
5673 // 29/7/2015. https://goo.gl/ueA7Ln
5674 impl()->ReportMessageAt(token_loc,
5675 MessageTemplate::kIllegalLanguageModeDirective,
5676 "use strict");
5677 return;
5678 }
5679#if V8_ENABLE_WEBASSEMBLY
5680 } else if (use_asm) {
5681 // Directive "use asm".
5682 impl()->SetAsmModule();
5683#endif // V8_ENABLE_WEBASSEMBLY
5684 } else {
5685 // Possibly an unknown directive.
5686 // Should not change mode, but will increment usage counters
5687 // as appropriate. Ditto usages below.
5689 }
5690 }
5691
5692 while (peek() != end_token) {
5694 if (impl()->IsNull(stat)) return;
5695 if (stat->IsEmptyStatement()) continue;
5696 body->Add(stat);
5697 }
5698}
5699
5700template <typename Impl>
5703 // ECMA 262 6th Edition
5704 // StatementListItem[Yield, Return] :
5705 // Statement[?Yield, ?Return]
5706 // Declaration[?Yield]
5707 //
5708 // Declaration[Yield] :
5709 // HoistableDeclaration[?Yield]
5710 // ClassDeclaration[?Yield]
5711 // LexicalDeclaration[In, ?Yield]
5712 //
5713 // HoistableDeclaration[Yield, Default] :
5714 // FunctionDeclaration[?Yield, ?Default]
5715 // GeneratorDeclaration[?Yield, ?Default]
5716 //
5717 // LexicalDeclaration[In, Yield, Await] :
5718 // LetOrConst BindingList[?In, ?Yield, ?Await, +Pattern] ;
5719 // UsingDeclaration[?In, ?Yield, ?Await, ~Pattern];
5720 // [+Await] AwaitUsingDeclaration[?In, ?Yield];
5721
5722 switch (peek()) {
5723 case Token::kFunction:
5724 return ParseHoistableDeclaration(nullptr, false);
5725 case Token::kClass:
5726 Consume(Token::kClass);
5727 return ParseClassDeclaration(nullptr, false);
5728 case Token::kVar:
5729 case Token::kConst:
5731 case Token::kLet:
5732 if (IsNextLetKeyword()) {
5734 }
5735 break;
5736 case Token::kUsing:
5737 if (!v8_flags.js_explicit_resource_management) break;
5738 if (!is_using_allowed()) break;
5739 if (!(scanner()->HasLineTerminatorAfterNext()) &&
5742 }
5743 break;
5744 case Token::kAwait:
5745 if (!v8_flags.js_explicit_resource_management) break;
5746 if (!is_await_allowed()) break;
5747 if (!is_using_allowed()) break;
5748 if (!(scanner()->HasLineTerminatorAfterNext()) &&
5749 PeekAhead() == Token::kUsing &&
5750 !(scanner()->HasLineTerminatorAfterNextNext()) &&
5753 }
5754 break;
5755 case Token::kAsync:
5756 if (PeekAhead() == Token::kFunction &&
5757 !scanner()->HasLineTerminatorAfterNext()) {
5758 Consume(Token::kAsync);
5759 return ParseAsyncFunctionDeclaration(nullptr, false);
5760 }
5761 break;
5762 default:
5763 break;
5764 }
5765 return ParseStatement(nullptr, nullptr, kAllowLabelledFunctionStatement);
5766}
5767
5768template <typename Impl>
5772 AllowLabelledFunctionStatement allow_function) {
5773 // Statement ::
5774 // Block
5775 // VariableStatement
5776 // EmptyStatement
5777 // ExpressionStatement
5778 // IfStatement
5779 // IterationStatement
5780 // ContinueStatement
5781 // BreakStatement
5782 // ReturnStatement
5783 // WithStatement
5784 // LabelledStatement
5785 // SwitchStatement
5786 // ThrowStatement
5787 // TryStatement
5788 // DebuggerStatement
5789
5790 // {own_labels} is always a subset of {labels}.
5791 DCHECK_IMPLIES(labels == nullptr, own_labels == nullptr);
5792
5793 // Note: Since labels can only be used by 'break' and 'continue'
5794 // statements, which themselves are only valid within blocks,
5795 // iterations or 'switch' statements (i.e., BreakableStatements),
5796 // labels can be simply ignored in all other cases; except for
5797 // trivial labeled break statements 'label: break label' which is
5798 // parsed into an empty statement.
5799 switch (peek()) {
5800 case Token::kLeftBrace:
5801 return ParseBlock(labels);
5802 case Token::kSemicolon:
5803 Next();
5804 return factory()->EmptyStatement();
5805 case Token::kIf:
5806 return ParseIfStatement(labels);
5807 case Token::kDo:
5808 return ParseDoWhileStatement(labels, own_labels);
5809 case Token::kWhile:
5810 return ParseWhileStatement(labels, own_labels);
5811 case Token::kFor:
5812 if (V8_UNLIKELY(is_await_allowed() && PeekAhead() == Token::kAwait)) {
5813 return ParseForAwaitStatement(labels, own_labels);
5814 }
5815 return ParseForStatement(labels, own_labels);
5816 case Token::kContinue:
5817 return ParseContinueStatement();
5818 case Token::kBreak:
5819 return ParseBreakStatement(labels);
5820 case Token::kReturn:
5821 return ParseReturnStatement();
5822 case Token::kThrow:
5823 return ParseThrowStatement();
5824 case Token::kTry: {
5825 // It is somewhat complicated to have labels on try-statements.
5826 // When breaking out of a try-finally statement, one must take
5827 // great care not to treat it as a fall-through. It is much easier
5828 // just to wrap the entire try-statement in a statement block and
5829 // put the labels there.
5830 if (labels == nullptr) return ParseTryStatement();
5831 StatementListT statements(pointer_buffer());
5832 BlockT result = factory()->NewBlock(false, true);
5833 Target target(this, result, labels, nullptr,
5836 statements.Add(statement);
5837 result->InitializeStatements(statements, zone());
5838 return result;
5839 }
5840 case Token::kWith:
5841 return ParseWithStatement(labels);
5842 case Token::kSwitch:
5843 return ParseSwitchStatement(labels);
5844 case Token::kFunction:
5845 // FunctionDeclaration only allowed as a StatementListItem, not in
5846 // an arbitrary Statement position. Exceptions such as
5847 // ES#sec-functiondeclarations-in-ifstatement-statement-clauses
5848 // are handled by calling ParseScopedStatement rather than
5849 // ParseStatement directly.
5850 impl()->ReportMessageAt(scanner()->peek_location(),
5852 ? MessageTemplate::kStrictFunction
5853 : MessageTemplate::kSloppyFunction);
5854 return impl()->NullStatement();
5855 case Token::kDebugger:
5856 return ParseDebuggerStatement();
5857 case Token::kVar:
5858 return ParseVariableStatement(kStatement, nullptr);
5859 case Token::kAsync:
5860 if (!impl()->HasCheckedSyntax() &&
5861 !scanner()->HasLineTerminatorAfterNext() &&
5862 PeekAhead() == Token::kFunction) {
5863 impl()->ReportMessageAt(
5864 scanner()->peek_location(),
5865 MessageTemplate::kAsyncFunctionInSingleStatementContext);
5866 return impl()->NullStatement();
5867 }
5868 [[fallthrough]];
5869 default:
5870 return ParseExpressionOrLabelledStatement(labels, own_labels,
5871 allow_function);
5872 }
5873}
5874
5875template <typename Impl>
5877 ZonePtrList<const AstRawString>* labels, Scope* block_scope) {
5878 // Block ::
5879 // '{' StatementList '}'
5880
5881 // Parse the statements and collect escaping labels.
5882 BlockT body = factory()->NewBlock(false, labels != nullptr);
5883 StatementListT statements(pointer_buffer());
5884
5886
5887 {
5888 BlockState block_state(&scope_, block_scope);
5890 Target target(this, body, labels, nullptr, Target::TARGET_FOR_NAMED_ONLY);
5891
5892 Expect(Token::kLeftBrace);
5893
5894 while (peek() != Token::kRightBrace) {
5896 if (impl()->IsNull(stat)) return body;
5897 if (stat->IsEmptyStatement()) continue;
5898 statements.Add(stat);
5899 }
5900
5901 Expect(Token::kRightBrace);
5902
5903 int end_pos = end_position();
5904 scope()->set_end_position(end_pos);
5905
5906 impl()->RecordBlockSourceRange(body, end_pos);
5907 body->set_scope(scope()->FinalizeBlockScope());
5908 }
5909
5910 body->InitializeStatements(statements, zone());
5911 return body;
5912}
5913
5914template <typename Impl>
5919
5920template <typename Impl>
5923 if (is_strict(language_mode()) || peek() != Token::kFunction) {
5924 return ParseStatement(labels, nullptr);
5925 } else {
5926 // Make a block around the statement for a lexical binding
5927 // is introduced by a FunctionDeclaration.
5928 BlockState block_state(zone(), &scope_);
5929 scope()->set_start_position(scanner()->location().beg_pos);
5930 BlockT block = factory()->NewBlock(1, false);
5932 block->statements()->Add(body, zone());
5934 block->set_scope(scope()->FinalizeBlockScope());
5935 return block;
5936 }
5937}
5938
5939template <typename Impl>
5941 VariableDeclarationContext var_context,
5943 // VariableStatement ::
5944 // VariableDeclarations ';'
5945
5946 // The scope of a var declared variable anywhere inside a function
5947 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can
5948 // transform a source-level var declaration into a (Function) Scope
5949 // declaration, and rewrite the source-level initialization into an assignment
5950 // statement. We use a block to collect multiple assignments.
5951 //
5952 // We mark the block as initializer block because we don't want the
5953 // rewriter to add a '.result' assignment to such a block (to get compliant
5954 // behavior for code such as print(eval('var x = 7')), and for cosmetic
5955 // reasons when pretty-printing. Also, unless an assignment (initialization)
5956 // is inside an initializer block, it is ignored.
5957
5958 DeclarationParsingResult parsing_result;
5959 ParseVariableDeclarations(var_context, &parsing_result, names);
5961 return impl()->BuildInitializationBlock(&parsing_result);
5962}
5963
5964template <typename Impl>
5967 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
5968 // contexts this is used as a statement which invokes the debugger as i a
5969 // break point is present.
5970 // DebuggerStatement ::
5971 // 'debugger' ';'
5972
5973 int pos = peek_position();
5974 Consume(Token::kDebugger);
5976 return factory()->NewDebuggerStatement(pos);
5977}
5978
5979template <typename Impl>
5984 AllowLabelledFunctionStatement allow_function) {
5985 // ExpressionStatement | LabelledStatement ::
5986 // Expression ';'
5987 // Identifier ':' Statement
5988 //
5989 // ExpressionStatement[Yield] :
5990 // [lookahead notin {{, function, class, let [}] Expression[In, ?Yield] ;
5991
5992 int pos = peek_position();
5993
5994 switch (peek()) {
5995 case Token::kFunction:
5996 case Token::kLeftBrace:
5997 UNREACHABLE(); // Always handled by the callers.
5998 case Token::kClass:
6000 return impl()->NullStatement();
6001 case Token::kLet: {
6002 Token::Value next_next = PeekAhead();
6003 // "let" followed by either "[", "{" or an identifier means a lexical
6004 // declaration, which should not appear here.
6005 // However, ASI may insert a line break before an identifier or a brace.
6006 if (next_next != Token::kLeftBracket &&
6007 ((next_next != Token::kLeftBrace &&
6008 next_next != Token::kIdentifier) ||
6010 break;
6011 }
6012 impl()->ReportMessageAt(scanner()->peek_location(),
6013 MessageTemplate::kUnexpectedLexicalDeclaration);
6014 return impl()->NullStatement();
6015 }
6016 default:
6017 break;
6018 }
6019
6020 bool starts_with_identifier = peek_any_identifier();
6021
6022 ExpressionT expr;
6023 {
6024 // Effectively inlines ParseExpression, so potential labels can be extracted
6025 // from expression_scope.
6027 AcceptINScope scope(this, true);
6029 expression_scope.ValidateExpression();
6030
6031 if (peek() == Token::kColon && starts_with_identifier &&
6032 impl()->IsIdentifier(expr)) {
6033 // The whole expression was a single identifier, and not, e.g.,
6034 // something starting with an identifier or a parenthesized identifier.
6035 DCHECK_EQ(expression_scope.variable_list()->length(), 1);
6036 VariableProxy* label = expression_scope.variable_list()->at(0).first;
6037 impl()->DeclareLabel(&labels, &own_labels, label->raw_name());
6038
6039 // Remove the "ghost" variable that turned out to be a label from the top
6040 // scope. This way, we don't try to resolve it during the scope
6041 // processing.
6042 this->scope()->DeleteUnresolved(label);
6043
6044 Consume(Token::kColon);
6045 // ES#sec-labelled-function-declarations Labelled Function Declarations
6046 if (peek() == Token::kFunction && is_sloppy(language_mode()) &&
6047 allow_function == kAllowLabelledFunctionStatement) {
6048 return ParseFunctionDeclaration();
6049 }
6050 return ParseStatement(labels, own_labels, allow_function);
6051 }
6052 }
6053
6054 // We allow a native function declaration if we're parsing the source for an
6055 // extension. A native function declaration starts with "native function"
6056 // with no line-terminator between the two words.
6057 if (impl()->ParsingExtension() && peek() == Token::kFunction &&
6058 !scanner()->HasLineTerminatorBeforeNext() && impl()->IsNative(expr) &&
6059 !scanner()->literal_contains_escapes()) {
6060 return ParseNativeDeclaration();
6061 }
6062
6063 // Parsed expression statement, followed by semicolon.
6065 if (expr->IsFailureExpression()) return impl()->NullStatement();
6066 return factory()->NewExpressionStatement(expr, pos);
6067}
6068
6069template <typename Impl>
6072 // IfStatement ::
6073 // 'if' '(' Expression ')' Statement ('else' Statement)?
6074
6075 int pos = peek_position();
6076 Consume(Token::kIf);
6077 Expect(Token::kLeftParen);
6079 Expect(Token::kRightParen);
6080
6081 SourceRange then_range, else_range;
6082 StatementT then_statement = impl()->NullStatement();
6083 {
6084 SourceRangeScope range_scope(scanner(), &then_range);
6085 // Make a copy of {labels} to avoid conflicts with any
6086 // labels that may be applied to the else clause below.
6087 auto labels_copy =
6088 labels == nullptr
6089 ? labels
6090 : zone()->template New<ZonePtrList<const AstRawString>>(*labels,
6091 zone());
6092 then_statement = ParseScopedStatement(labels_copy);
6093 }
6094
6095 StatementT else_statement = impl()->NullStatement();
6096 if (Check(Token::kElse)) {
6097 else_statement = ParseScopedStatement(labels);
6098 else_range = SourceRange::ContinuationOf(then_range, end_position());
6099 } else {
6100 else_statement = factory()->EmptyStatement();
6101 }
6102 StatementT stmt =
6103 factory()->NewIfStatement(condition, then_statement, else_statement, pos);
6104 impl()->RecordIfStatementSourceRange(stmt, then_range, else_range);
6105 return stmt;
6106}
6107
6108template <typename Impl>
6111 // ContinueStatement ::
6112 // 'continue' Identifier? ';'
6113
6114 int pos = peek_position();
6115 Consume(Token::kContinue);
6116 IdentifierT label = impl()->NullIdentifier();
6117 Token::Value tok = peek();
6118 if (!scanner()->HasLineTerminatorBeforeNext() &&
6119 !Token::IsAutoSemicolon(tok)) {
6120 // ECMA allows "eval" or "arguments" as labels even in strict mode.
6122 }
6124 if (impl()->IsNull(target)) {
6125 // Illegal continue statement.
6126 MessageTemplate message = MessageTemplate::kIllegalContinue;
6127 BreakableStatementT breakable_target = LookupBreakTarget(label);
6128 if (impl()->IsNull(label)) {
6129 message = MessageTemplate::kNoIterationStatement;
6130 } else if (impl()->IsNull(breakable_target)) {
6131 message = MessageTemplate::kUnknownLabel;
6132 }
6133 ReportMessage(message, label);
6134 return impl()->NullStatement();
6135 }
6137 StatementT stmt = factory()->NewContinueStatement(target, pos);
6138 impl()->RecordJumpStatementSourceRange(stmt, end_position());
6139 return stmt;
6140}
6141
6142template <typename Impl>
6145 // BreakStatement ::
6146 // 'break' Identifier? ';'
6147
6148 int pos = peek_position();
6149 Consume(Token::kBreak);
6150 IdentifierT label = impl()->NullIdentifier();
6151 Token::Value tok = peek();
6152 if (!scanner()->HasLineTerminatorBeforeNext() &&
6153 !Token::IsAutoSemicolon(tok)) {
6154 // ECMA allows "eval" or "arguments" as labels even in strict mode.
6156 }
6157 // Parse labeled break statements that target themselves into
6158 // empty statements, e.g. 'l1: l2: l3: break l2;'
6159 if (!impl()->IsNull(label) &&
6160 impl()->ContainsLabel(labels, impl()->GetRawNameFromIdentifier(label))) {
6162 return factory()->EmptyStatement();
6163 }
6165 if (impl()->IsNull(target)) {
6166 // Illegal break statement.
6167 MessageTemplate message = MessageTemplate::kIllegalBreak;
6168 if (!impl()->IsNull(label)) {
6169 message = MessageTemplate::kUnknownLabel;
6170 }
6171 ReportMessage(message, label);
6172 return impl()->NullStatement();
6173 }
6175 StatementT stmt = factory()->NewBreakStatement(target, pos);
6176 impl()->RecordJumpStatementSourceRange(stmt, end_position());
6177 return stmt;
6178}
6179
6180template <typename Impl>
6182 // ReturnStatement ::
6183 // 'return' [no line terminator] Expression? ';'
6184
6185 // Consume the return token. It is necessary to do that before
6186 // reporting any errors on it, because of the way errors are
6187 // reported (underlining).
6188 Consume(Token::kReturn);
6190
6191 switch (GetDeclarationScope()->scope_type()) {
6192 case SCRIPT_SCOPE:
6193 case REPL_MODE_SCOPE:
6194 case EVAL_SCOPE:
6195 case MODULE_SCOPE:
6196 impl()->ReportMessageAt(loc, MessageTemplate::kIllegalReturn);
6197 return impl()->NullStatement();
6198 case BLOCK_SCOPE:
6199 // Class static blocks disallow return. They are their own var scopes and
6200 // have a varblock scope.
6201 if (function_state_->kind() ==
6203 impl()->ReportMessageAt(loc, MessageTemplate::kIllegalReturn);
6204 return impl()->NullStatement();
6205 }
6206 break;
6207 default:
6208 break;
6209 }
6210
6211 Token::Value tok = peek();
6212 ExpressionT return_value = impl()->NullExpression();
6213 if (!scanner()->HasLineTerminatorBeforeNext() &&
6214 !Token::IsAutoSemicolon(tok)) {
6215 return_value = ParseExpression();
6216 }
6218
6219 int continuation_pos = end_position();
6220 StatementT stmt =
6221 BuildReturnStatement(return_value, loc.beg_pos, continuation_pos);
6222 impl()->RecordJumpStatementSourceRange(stmt, end_position());
6223 return stmt;
6224}
6225
6226template <typename Impl>
6229 // WithStatement ::
6230 // 'with' '(' Expression ')' Statement
6231
6232 Consume(Token::kWith);
6233 int pos = position();
6234
6235 if (is_strict(language_mode())) {
6236 ReportMessage(MessageTemplate::kStrictWith);
6237 return impl()->NullStatement();
6238 }
6239
6240 Expect(Token::kLeftParen);
6242 Expect(Token::kRightParen);
6243
6244 Scope* with_scope = NewScope(WITH_SCOPE);
6245 StatementT body = impl()->NullStatement();
6246 {
6247 BlockState block_state(&scope_, with_scope);
6248 with_scope->set_start_position(position());
6249 body = ParseStatement(labels, nullptr);
6250 with_scope->set_end_position(end_position());
6251 }
6252 return factory()->NewWithStatement(with_scope, expr, body, pos);
6253}
6254
6255template <typename Impl>
6258 ZonePtrList<const AstRawString>* own_labels) {
6259 // DoStatement ::
6260 // 'do' Statement 'while' '(' Expression ')' ';'
6261 typename FunctionState::LoopScope loop_scope(function_state_);
6262
6263 auto loop = factory()->NewDoWhileStatement(peek_position());
6264 Target target(this, loop, labels, own_labels, Target::TARGET_FOR_ANONYMOUS);
6265
6266 SourceRange body_range;
6267 StatementT body = impl()->NullStatement();
6268
6269 Consume(Token::kDo);
6270
6272 {
6273 SourceRangeScope range_scope(scanner(), &body_range);
6274 body = ParseStatement(nullptr, nullptr);
6275 }
6276 Expect(Token::kWhile);
6277 Expect(Token::kLeftParen);
6278
6280 Expect(Token::kRightParen);
6281
6282 // Allow do-statements to be terminated with and without
6283 // semi-colons. This allows code such as 'do;while(0)return' to
6284 // parse, which would not be the case if we had used the
6285 // ExpectSemicolon() functionality here.
6286 Check(Token::kSemicolon);
6287
6288 loop->Initialize(cond, body);
6289 impl()->RecordIterationStatementSourceRange(loop, body_range);
6290
6291 return loop;
6292}
6293
6294template <typename Impl>
6297 ZonePtrList<const AstRawString>* own_labels) {
6298 // WhileStatement ::
6299 // 'while' '(' Expression ')' Statement
6300 typename FunctionState::LoopScope loop_scope(function_state_);
6301
6302 auto loop = factory()->NewWhileStatement(peek_position());
6303 Target target(this, loop, labels, own_labels, Target::TARGET_FOR_ANONYMOUS);
6304
6305 SourceRange body_range;
6306 StatementT body = impl()->NullStatement();
6307
6308 Consume(Token::kWhile);
6309 Expect(Token::kLeftParen);
6311 Expect(Token::kRightParen);
6312 {
6313 SourceRangeScope range_scope(scanner(), &body_range);
6314 body = ParseStatement(nullptr, nullptr);
6315 }
6316
6317 loop->Initialize(cond, body);
6318 impl()->RecordIterationStatementSourceRange(loop, body_range);
6319
6320 return loop;
6321}
6322
6323template <typename Impl>
6325 // ThrowStatement ::
6326 // 'throw' Expression ';'
6327
6328 Consume(Token::kThrow);
6329 int pos = position();
6330 if (scanner()->HasLineTerminatorBeforeNext()) {
6331 ReportMessage(MessageTemplate::kNewlineAfterThrow);
6332 return impl()->NullStatement();
6333 }
6334 ExpressionT exception = ParseExpression();
6336
6337 StatementT stmt = impl()->NewThrowStatement(exception, pos);
6338 impl()->RecordThrowSourceRange(stmt, end_position());
6339
6340 return stmt;
6341}
6342
6343template <typename Impl>
6346 // SwitchStatement ::
6347 // 'switch' '(' Expression ')' '{' CaseClause* '}'
6348 // CaseClause ::
6349 // 'case' Expression ':' StatementList
6350 // 'default' ':' StatementList
6351 int switch_pos = peek_position();
6352
6353 Consume(Token::kSwitch);
6354 Expect(Token::kLeftParen);
6356 Expect(Token::kRightParen);
6357
6358 auto switch_statement = factory()->NewSwitchStatement(tag, switch_pos);
6359
6360 {
6361 BlockState cases_block_state(zone(), &scope_);
6362 scope()->set_start_position(switch_pos);
6363 scope()->SetNonlinear();
6364 Target target(this, switch_statement, labels, nullptr,
6366
6367 bool default_seen = false;
6368 Expect(Token::kLeftBrace);
6369 while (peek() != Token::kRightBrace) {
6370 // An empty label indicates the default case.
6371 ExpressionT label = impl()->NullExpression();
6372 StatementListT statements(pointer_buffer());
6373 SourceRange clause_range;
6374 {
6375 SourceRangeScope range_scope(scanner(), &clause_range);
6376 if (Check(Token::kCase)) {
6378 } else {
6379 Expect(Token::kDefault);
6380 if (default_seen) {
6381 ReportMessage(MessageTemplate::kMultipleDefaultsInSwitch);
6382 return impl()->NullStatement();
6383 }
6384 default_seen = true;
6385 }
6386 Expect(Token::kColon);
6387 while (peek() != Token::kCase && peek() != Token::kDefault &&
6388 peek() != Token::kRightBrace) {
6390 if (impl()->IsNull(stat)) return stat;
6391 if (stat->IsEmptyStatement()) continue;
6392 statements.Add(stat);
6393 }
6394 }
6395 auto clause = factory()->NewCaseClause(label, statements);
6396 impl()->RecordCaseClauseSourceRange(clause, clause_range);
6397 switch_statement->cases()->Add(clause, zone());
6398 }
6399 Expect(Token::kRightBrace);
6400
6401 int end_pos = end_position();
6402 scope()->set_end_position(end_pos);
6403 impl()->RecordSwitchStatementSourceRange(switch_statement, end_pos);
6404 Scope* switch_scope = scope()->FinalizeBlockScope();
6405 if (switch_scope != nullptr) {
6406 return impl()->RewriteSwitchStatement(switch_statement, switch_scope);
6407 }
6408 return switch_statement;
6409 }
6410}
6411
6412template <typename Impl>
6414 // TryStatement ::
6415 // 'try' Block Catch
6416 // 'try' Block Finally
6417 // 'try' Block Catch Finally
6418 //
6419 // Catch ::
6420 // 'catch' '(' Identifier ')' Block
6421 //
6422 // Finally ::
6423 // 'finally' Block
6424
6425 Consume(Token::kTry);
6426 int pos = position();
6427
6428 BlockT try_block = ParseBlock(nullptr);
6429
6430 CatchInfo catch_info(this);
6431
6432 if (peek() != Token::kCatch && peek() != Token::kFinally) {
6433 ReportMessage(MessageTemplate::kNoCatchOrFinally);
6434 return impl()->NullStatement();
6435 }
6436
6437 SourceRange catch_range, finally_range;
6438
6439 BlockT catch_block = impl()->NullBlock();
6440 {
6441 SourceRangeScope catch_range_scope(scanner(), &catch_range);
6442 if (Check(Token::kCatch)) {
6443 bool has_binding;
6444 has_binding = Check(Token::kLeftParen);
6445
6446 if (has_binding) {
6447 catch_info.scope = NewScope(CATCH_SCOPE);
6448 catch_info.scope->set_start_position(position());
6449
6450 {
6451 BlockState catch_block_state(&scope_, catch_info.scope);
6452 StatementListT catch_statements(pointer_buffer());
6453
6454 // Create a block scope to hold any lexical declarations created
6455 // as part of destructuring the catch parameter.
6456 {
6457 BlockState catch_variable_block_state(zone(), &scope_);
6459
6460 if (peek_any_identifier()) {
6463 catch_info.variable = impl()->DeclareCatchVariableName(
6464 catch_info.scope, identifier);
6465 } else {
6466 catch_info.variable = catch_info.scope->DeclareCatchVariableName(
6467 ast_value_factory()->dot_catch_string());
6468
6469 auto declaration_it = scope()->declarations()->end();
6470
6471 VariableDeclarationParsingScope destructuring(
6472 impl(), VariableMode::kLet, nullptr);
6473 catch_info.pattern = ParseBindingPattern();
6474
6475 int initializer_position = end_position();
6476 auto declaration_end = scope()->declarations()->end();
6477 for (; declaration_it != declaration_end; ++declaration_it) {
6478 declaration_it->var()->set_initializer_position(
6479 initializer_position);
6480 }
6481
6483 catch_statements.Add(impl()->RewriteCatchPattern(&catch_info));
6484 }
6485
6486 Expect(Token::kRightParen);
6487
6488 BlockT inner_block = ParseBlock(nullptr);
6489 catch_statements.Add(inner_block);
6490
6491 // Check for `catch(e) { let e; }` and similar errors.
6492 if (!impl()->HasCheckedSyntax()) {
6493 Scope* inner_scope = inner_block->scope();
6494 if (inner_scope != nullptr) {
6495 const AstRawString* conflict = nullptr;
6496 if (impl()->IsNull(catch_info.pattern)) {
6497 const AstRawString* name = catch_info.variable->raw_name();
6498 if (inner_scope->LookupLocal(name)) conflict = name;
6499 } else {
6500 conflict = inner_scope->FindVariableDeclaredIn(
6502 }
6503 if (conflict != nullptr) {
6504 impl()->ReportVarRedeclarationIn(conflict, inner_scope);
6505 }
6506 }
6507 }
6508
6510 catch_block = factory()->NewBlock(false, catch_statements);
6511 catch_block->set_scope(scope()->FinalizeBlockScope());
6512 }
6513 }
6514
6515 catch_info.scope->set_end_position(end_position());
6516 } else {
6517 catch_block = ParseBlock(nullptr);
6518 }
6519 }
6520 }
6521
6522 BlockT finally_block = impl()->NullBlock();
6523 DCHECK(has_error() || peek() == Token::kFinally ||
6524 !impl()->IsNull(catch_block));
6525 {
6526 SourceRangeScope range_scope(scanner(), &finally_range);
6527 if (Check(Token::kFinally)) {
6528 finally_block = ParseBlock(nullptr);
6529 }
6530 }
6531
6533 return impl()->RewriteTryStatement(try_block, catch_block, catch_range,
6534 finally_block, finally_range, catch_info,
6535 pos);
6536}
6537
6538template <typename Impl>
6541 ZonePtrList<const AstRawString>* own_labels) {
6542 // Either a standard for loop
6543 // for (<init>; <cond>; <next>) { ... }
6544 // or a for-each loop
6545 // for (<each> of|in <iterable>) { ... }
6546 //
6547 // We parse a declaration/expression after the 'for (' and then read the first
6548 // expression/declaration before we know if this is a for or a for-each.
6549 typename FunctionState::LoopScope loop_scope(function_state_);
6550
6551 int stmt_pos = peek_position();
6552 ForInfo for_info(this);
6553
6554 Consume(Token::kFor);
6555 Expect(Token::kLeftParen);
6556
6557 bool starts_with_let = peek() == Token::kLet;
6558 bool starts_with_using_or_await_using_keyword =
6560 if (peek() == Token::kConst || (starts_with_let && IsNextLetKeyword()) ||
6561 starts_with_using_or_await_using_keyword) {
6562 // The initializer contains lexical declarations,
6563 // so create an in-between scope.
6564 BlockState for_state(zone(), &scope_);
6566
6567 // Also record whether inner functions or evals are found inside
6568 // this loop, as this information is used to simplify the desugaring
6569 // if none are found.
6570 typename FunctionState::FunctionOrEvalRecordingScope recording_scope(
6572
6573 // Create an inner block scope which will be the parent scope of scopes
6574 // possibly created by ParseVariableDeclarations.
6575 Scope* inner_block_scope = NewScope(BLOCK_SCOPE);
6576 inner_block_scope->set_start_position(end_position());
6577 {
6578 BlockState inner_state(&scope_, inner_block_scope);
6580 &for_info.bound_names);
6581 }
6583 for_info.position = position();
6584
6585 if (CheckInOrOf(&for_info.mode)) {
6586 scope()->set_is_hidden();
6587 if (starts_with_using_or_await_using_keyword &&
6588 for_info.mode == ForEachStatement::ENUMERATE) {
6589 impl()->ReportMessageAt(scanner()->location(),
6590 MessageTemplate::kInvalidUsingInForInLoop);
6591 }
6593 stmt_pos, &for_info, labels, own_labels, inner_block_scope);
6594 }
6595
6596 Expect(Token::kSemicolon);
6597
6598 // Parse the remaining code in the inner block scope since the declaration
6599 // above was parsed there. We'll finalize the unnecessary outer block scope
6600 // after parsing the rest of the loop.
6601 StatementT result = impl()->NullStatement();
6602 {
6603 BlockState inner_state(&scope_, inner_block_scope);
6604 StatementT init =
6605 impl()->BuildInitializationBlock(&for_info.parsing_result);
6606
6608 stmt_pos, init, &for_info, labels, own_labels);
6609 }
6610 Scope* finalized = scope()->FinalizeBlockScope();
6611 DCHECK_NULL(finalized);
6612 USE(finalized);
6613 return result;
6614 }
6615
6616 StatementT init = impl()->NullStatement();
6617 if (peek() == Token::kVar) {
6619 &for_info.bound_names);
6621 for_info.position = position();
6622
6623 if (CheckInOrOf(&for_info.mode)) {
6624 return ParseForEachStatementWithDeclarations(stmt_pos, &for_info, labels,
6625 own_labels, scope());
6626 }
6627
6628 init = impl()->BuildInitializationBlock(&for_info.parsing_result);
6629 } else if (peek() != Token::kSemicolon) {
6630 // The initializer does not contain declarations.
6631 Scanner::Location next_loc = scanner()->peek_location();
6632 int lhs_beg_pos = next_loc.beg_pos;
6633 int lhs_end_pos;
6634 bool is_for_each;
6636
6637 {
6638 ExpressionParsingScope parsing_scope(impl());
6639 AcceptINScope scope(this, false);
6640 expression = ParseExpressionCoverGrammar();
6641 // `for (async of` is disallowed but `for (async.x of` is allowed, so
6642 // check if the token is kAsync after parsing the expression.
6643 bool expression_is_async = scanner()->current_token() == Token::kAsync &&
6645 // Initializer is reference followed by in/of.
6646 lhs_end_pos = end_position();
6647 is_for_each = CheckInOrOf(&for_info.mode);
6648 if (is_for_each) {
6649 if ((starts_with_let || expression_is_async) &&
6650 for_info.mode == ForEachStatement::ITERATE) {
6651 impl()->ReportMessageAt(next_loc, starts_with_let
6652 ? MessageTemplate::kForOfLet
6653 : MessageTemplate::kForOfAsync);
6654 return impl()->NullStatement();
6655 }
6656 if (expression->IsPattern()) {
6657 parsing_scope.ValidatePattern(expression, lhs_beg_pos, lhs_end_pos);
6658 } else {
6659 expression = parsing_scope.ValidateAndRewriteReference(
6660 expression, lhs_beg_pos, lhs_end_pos);
6661 }
6662 } else {
6663 parsing_scope.ValidateExpression();
6664 }
6665 }
6666
6667 if (is_for_each) {
6669 stmt_pos, expression, lhs_beg_pos, lhs_end_pos, &for_info, labels,
6670 own_labels);
6671 }
6672 // Initializer is just an expression.
6673 init = factory()->NewExpressionStatement(expression, lhs_beg_pos);
6674 }
6675
6676 Expect(Token::kSemicolon);
6677
6678 // Standard 'for' loop, we have parsed the initializer at this point.
6679 ExpressionT cond = impl()->NullExpression();
6680 StatementT next = impl()->NullStatement();
6681 StatementT body = impl()->NullStatement();
6682 ForStatementT loop =
6683 ParseStandardForLoop(stmt_pos, labels, own_labels, &cond, &next, &body);
6685 loop->Initialize(init, cond, next, body);
6686 return loop;
6687}
6688
6689template <typename Impl>
6692 int stmt_pos, ForInfo* for_info, ZonePtrList<const AstRawString>* labels,
6693 ZonePtrList<const AstRawString>* own_labels, Scope* inner_block_scope) {
6694 // Just one declaration followed by in/of.
6695 if (for_info->parsing_result.declarations.size() != 1) {
6696 impl()->ReportMessageAt(for_info->parsing_result.bindings_loc,
6697 MessageTemplate::kForInOfLoopMultiBindings,
6699 return impl()->NullStatement();
6700 }
6703 for_info->mode == ForEachStatement::ITERATE ||
6705 !impl()->IsIdentifier(
6706 for_info->parsing_result.declarations[0].pattern))) {
6707 impl()->ReportMessageAt(for_info->parsing_result.first_initializer_loc,
6708 MessageTemplate::kForInOfLoopInitializer,
6710 return impl()->NullStatement();
6711 }
6712
6713 BlockT init_block = impl()->RewriteForVarInLegacy(*for_info);
6714
6715 auto loop = factory()->NewForEachStatement(for_info->mode, stmt_pos);
6716 Target target(this, loop, labels, own_labels, Target::TARGET_FOR_ANONYMOUS);
6717
6718 Scope* enumerable_block_scope = NewScope(BLOCK_SCOPE);
6719 enumerable_block_scope->set_start_position(position());
6720 enumerable_block_scope->set_is_hidden();
6721 ExpressionT enumerable = impl()->NullExpression();
6722 {
6723 BlockState block_state(&scope_, enumerable_block_scope);
6724
6725 if (for_info->mode == ForEachStatement::ITERATE) {
6726 AcceptINScope scope(this, true);
6727 enumerable = ParseAssignmentExpression();
6728 } else {
6729 enumerable = ParseExpression();
6730 }
6731 }
6732 enumerable_block_scope->set_end_position(end_position());
6733
6734 Expect(Token::kRightParen);
6735
6736 ExpressionT each_variable = impl()->NullExpression();
6737 BlockT body_block = impl()->NullBlock();
6738 {
6739 BlockState block_state(&scope_, inner_block_scope);
6740
6741 SourceRange body_range;
6742 StatementT body = impl()->NullStatement();
6743 {
6744 SourceRangeScope range_scope(scanner(), &body_range);
6745 body = ParseStatement(nullptr, nullptr);
6746 }
6747 impl()->RecordIterationStatementSourceRange(loop, body_range);
6748
6749 impl()->DesugarBindingInForEachStatement(for_info, &body_block,
6750 &each_variable);
6751 body_block->statements()->Add(body, zone());
6752
6755 body_block->set_scope(scope()->FinalizeBlockScope());
6756 }
6757 }
6758
6759 loop->Initialize(each_variable, enumerable, body_block,
6760 enumerable_block_scope);
6761
6762 init_block = impl()->CreateForEachStatementTDZ(init_block, *for_info);
6763
6764 // Parsed for-in loop w/ variable declarations.
6765 if (!impl()->IsNull(init_block)) {
6766 init_block->statements()->Add(loop, zone());
6769 init_block->set_scope(scope()->FinalizeBlockScope());
6770 }
6771 return init_block;
6772 }
6773
6774 return loop;
6775}
6776
6777template <typename Impl>
6780 int stmt_pos, ExpressionT expression, int lhs_beg_pos, int lhs_end_pos,
6781 ForInfo* for_info, ZonePtrList<const AstRawString>* labels,
6782 ZonePtrList<const AstRawString>* own_labels) {
6783 auto loop = factory()->NewForEachStatement(for_info->mode, stmt_pos);
6784 Target target(this, loop, labels, own_labels, Target::TARGET_FOR_ANONYMOUS);
6785
6786 ExpressionT enumerable = impl()->NullExpression();
6787 if (for_info->mode == ForEachStatement::ITERATE) {
6788 AcceptINScope scope(this, true);
6789 enumerable = ParseAssignmentExpression();
6790 } else {
6791 enumerable = ParseExpression();
6792 }
6793
6794 Expect(Token::kRightParen);
6795
6796 StatementT body = impl()->NullStatement();
6797 SourceRange body_range;
6798 {
6799 SourceRangeScope range_scope(scanner(), &body_range);
6800 body = ParseStatement(nullptr, nullptr);
6801 }
6802 impl()->RecordIterationStatementSourceRange(loop, body_range);
6804 loop->Initialize(expression, enumerable, body, nullptr);
6805 return loop;
6806}
6807
6808template <typename Impl>
6811 int stmt_pos, StatementT init, ForInfo* for_info,
6813 ZonePtrList<const AstRawString>* own_labels) {
6814 // The condition and the next statement of the for loop must be parsed
6815 // in a new scope.
6816 Scope* inner_scope = NewScope(BLOCK_SCOPE);
6817 ForStatementT loop = impl()->NullStatement();
6818 ExpressionT cond = impl()->NullExpression();
6819 StatementT next = impl()->NullStatement();
6820 StatementT body = impl()->NullStatement();
6821 {
6822 BlockState block_state(&scope_, inner_scope);
6823 scope()->set_start_position(scanner()->location().beg_pos);
6824 loop =
6825 ParseStandardForLoop(stmt_pos, labels, own_labels, &cond, &next, &body);
6828 }
6829
6831 if (for_info->bound_names.length() > 0 &&
6833 scope()->set_is_hidden();
6834 return impl()->DesugarLexicalBindingsInForStatement(
6835 loop, init, cond, next, body, inner_scope, *for_info);
6836 } else {
6837 inner_scope = inner_scope->FinalizeBlockScope();
6838 DCHECK_NULL(inner_scope);
6839 USE(inner_scope);
6840 }
6841
6842 Scope* for_scope = scope()->FinalizeBlockScope();
6843 if (for_scope != nullptr) {
6844 // Rewrite a for statement of the form
6845 // for (const x = i; c; n) b
6846 //
6847 // into
6848 //
6849 // {
6850 // const x = i;
6851 // for (; c; n) b
6852 // }
6853 //
6854 DCHECK(!impl()->IsNull(init));
6855 BlockT block = factory()->NewBlock(2, false);
6856 block->statements()->Add(init, zone());
6857 block->statements()->Add(loop, zone());
6858 block->set_scope(for_scope);
6859 loop->Initialize(impl()->NullStatement(), cond, next, body);
6860 return block;
6861 }
6862
6863 loop->Initialize(init, cond, next, body);
6864 return loop;
6865}
6866
6867template <typename Impl>
6869 int stmt_pos, ZonePtrList<const AstRawString>* labels,
6871 StatementT* next, StatementT* body) {
6873 ForStatementT loop = factory()->NewForStatement(stmt_pos);
6874 Target target(this, loop, labels, own_labels, Target::TARGET_FOR_ANONYMOUS);
6875
6876 if (peek() != Token::kSemicolon) {
6877 *cond = ParseExpression();
6878 }
6879 Expect(Token::kSemicolon);
6880
6881 if (peek() != Token::kRightParen) {
6883 *next = factory()->NewExpressionStatement(exp, exp->position());
6884 }
6885 Expect(Token::kRightParen);
6886
6887 SourceRange body_range;
6888 {
6889 SourceRangeScope range_scope(scanner(), &body_range);
6890 *body = ParseStatement(nullptr, nullptr);
6891 }
6892 impl()->RecordIterationStatementSourceRange(loop, body_range);
6893
6894 return loop;
6895}
6896
6897template <typename Impl>
6900 ZonePtrList<const AstRawString>* own_labels) {
6901 // for await '(' ForDeclaration of AssignmentExpression ')'
6903 typename FunctionState::LoopScope loop_scope(function_state_);
6904
6905 int stmt_pos = peek_position();
6906
6907 ForInfo for_info(this);
6909
6910 // Create an in-between scope for let-bound iteration variables.
6911 BlockState for_state(zone(), &scope_);
6912 Expect(Token::kFor);
6913 Expect(Token::kAwait);
6914 Expect(Token::kLeftParen);
6916 scope()->set_is_hidden();
6917
6918 auto loop = factory()->NewForOfStatement(stmt_pos, IteratorType::kAsync);
6919 // Two suspends: one for next() and one for return()
6922
6923 Target target(this, loop, labels, own_labels, Target::TARGET_FOR_ANONYMOUS);
6924
6925 ExpressionT each_variable = impl()->NullExpression();
6926
6927 bool has_declarations = false;
6928 Scope* inner_block_scope = NewScope(BLOCK_SCOPE);
6929 inner_block_scope->set_start_position(peek_position());
6930
6931 bool starts_with_let = peek() == Token::kLet;
6932 if (peek() == Token::kVar || peek() == Token::kConst ||
6933 (starts_with_let && IsNextLetKeyword()) ||
6935 // The initializer contains declarations
6936 // 'for' 'await' '(' ForDeclaration 'of' AssignmentExpression ')'
6937 // Statement
6938 // 'for' 'await' '(' 'var' ForBinding 'of' AssignmentExpression ')'
6939 // Statement
6940 has_declarations = true;
6941
6942 {
6943 BlockState inner_state(&scope_, inner_block_scope);
6945 &for_info.bound_names);
6946 }
6947 for_info.position = position();
6948
6949 // Only a single declaration is allowed in for-await-of loops
6950 if (for_info.parsing_result.declarations.size() != 1) {
6951 impl()->ReportMessageAt(for_info.parsing_result.bindings_loc,
6952 MessageTemplate::kForInOfLoopMultiBindings,
6953 "for-await-of");
6954 return impl()->NullStatement();
6955 }
6956
6957 // for-await-of's declarations do not permit initializers.
6959 impl()->ReportMessageAt(for_info.parsing_result.first_initializer_loc,
6960 MessageTemplate::kForInOfLoopInitializer,
6961 "for-await-of");
6962 return impl()->NullStatement();
6963 }
6964 } else {
6965 // The initializer does not contain declarations.
6966 // 'for' 'await' '(' LeftHandSideExpression 'of' AssignmentExpression ')'
6967 // Statement
6968 if (starts_with_let) {
6969 impl()->ReportMessageAt(scanner()->peek_location(),
6970 MessageTemplate::kForOfLet);
6971 return impl()->NullStatement();
6972 }
6973 int lhs_beg_pos = peek_position();
6974 BlockState inner_state(&scope_, inner_block_scope);
6975 ExpressionParsingScope parsing_scope(impl());
6976 ExpressionT lhs = each_variable = ParseLeftHandSideExpression();
6977 int lhs_end_pos = end_position();
6978
6979 if (lhs->IsPattern()) {
6980 parsing_scope.ValidatePattern(lhs, lhs_beg_pos, lhs_end_pos);
6981 } else {
6982 each_variable = parsing_scope.ValidateAndRewriteReference(
6983 lhs, lhs_beg_pos, lhs_end_pos);
6984 }
6985 }
6986
6987 ExpectContextualKeyword(Token::kOf);
6988
6989 const bool kAllowIn = true;
6990 ExpressionT iterable = impl()->NullExpression();
6991 Scope* iterable_block_scope = NewScope(BLOCK_SCOPE);
6992 iterable_block_scope->set_start_position(position());
6993 iterable_block_scope->set_is_hidden();
6994
6995 {
6996 BlockState block_state(&scope_, iterable_block_scope);
6997 AcceptINScope scope(this, kAllowIn);
6998 iterable = ParseAssignmentExpression();
6999 }
7000 iterable_block_scope->set_end_position(end_position());
7001
7002 Expect(Token::kRightParen);
7003
7004 StatementT body = impl()->NullStatement();
7005 {
7006 BlockState block_state(&scope_, inner_block_scope);
7007
7008 SourceRange body_range;
7009 {
7010 SourceRangeScope range_scope(scanner(), &body_range);
7011 body = ParseStatement(nullptr, nullptr);
7013 }
7014 impl()->RecordIterationStatementSourceRange(loop, body_range);
7015
7016 if (has_declarations) {
7017 BlockT body_block = impl()->NullBlock();
7018 impl()->DesugarBindingInForEachStatement(&for_info, &body_block,
7019 &each_variable);
7020 body_block->statements()->Add(body, zone());
7021 body_block->set_scope(scope()->FinalizeBlockScope());
7022 body = body_block;
7023 } else {
7024 Scope* block_scope = scope()->FinalizeBlockScope();
7025 DCHECK_NULL(block_scope);
7026 USE(block_scope);
7027 }
7028 }
7029
7030 loop->Initialize(each_variable, iterable, body, iterable_block_scope);
7031
7032 if (!has_declarations) {
7033 Scope* for_scope = scope()->FinalizeBlockScope();
7034 DCHECK_NULL(for_scope);
7035 USE(for_scope);
7036 return loop;
7037 }
7038
7039 BlockT init_block =
7040 impl()->CreateForEachStatementTDZ(impl()->NullBlock(), for_info);
7041
7043 Scope* for_scope = scope()->FinalizeBlockScope();
7044 // Parsed for-in loop w/ variable declarations.
7045 if (!impl()->IsNull(init_block)) {
7046 init_block->statements()->Add(loop, zone());
7047 init_block->set_scope(for_scope);
7048 return init_block;
7049 }
7050 DCHECK_NULL(for_scope);
7051 return loop;
7052}
7053
7054template <typename Impl>
7056 ParsePropertyKind type,
7057 ParseFunctionFlags flags,
7058 bool is_static,
7059 bool* has_seen_constructor) {
7061
7063
7064 if (impl()->IdentifierEquals(name, avf->private_constructor_string())) {
7065 ReportMessage(MessageTemplate::kConstructorIsPrivate);
7066 return;
7067 } else if (is_static) {
7068 if (impl()->IdentifierEquals(name, avf->prototype_string())) {
7069 ReportMessage(MessageTemplate::kStaticPrototype);
7070 return;
7071 }
7072 } else if (impl()->IdentifierEquals(name, avf->constructor_string())) {
7073 if (flags != ParseFunctionFlag::kIsNormal || IsAccessor(type)) {
7075 ? MessageTemplate::kConstructorIsGenerator
7076 : (flags & ParseFunctionFlag::kIsAsync) != 0
7077 ? MessageTemplate::kConstructorIsAsync
7078 : MessageTemplate::kConstructorIsAccessor;
7079 ReportMessage(msg);
7080 return;
7081 }
7082 if (*has_seen_constructor) {
7083 ReportMessage(MessageTemplate::kDuplicateConstructor);
7084 return;
7085 }
7086 *has_seen_constructor = true;
7087 return;
7088 }
7089}
7090
7091template <typename Impl>
7094 if (is_static && impl()->IdentifierEquals(name, avf->prototype_string())) {
7095 ReportMessage(MessageTemplate::kStaticPrototype);
7096 return;
7097 }
7098
7099 if (impl()->IdentifierEquals(name, avf->constructor_string()) ||
7100 impl()->IdentifierEquals(name, avf->private_constructor_string())) {
7101 ReportMessage(MessageTemplate::kConstructorClassField);
7102 return;
7103 }
7104}
7105
7106#undef RETURN_IF_PARSE_ERROR
7107
7108} // namespace v8::internal
7109
7110#endif // V8_PARSING_PARSER_BASE_H_
Builtins::Kind kind
Definition builtins.cc:40
SourcePosition pos
@ kExplicitResourceManagement
Definition v8-isolate.h:635
@ kDecimalWithLeadingZeroInStrictMode
Definition v8-isolate.h:501
@ kAssigmentExpressionLHSIsCallInSloppy
Definition v8-isolate.h:505
@ kVarRedeclaredCatchBinding
Definition v8-isolate.h:576
@ kAssigmentExpressionLHSIsCallInStrict
Definition v8-isolate.h:506
int position() const
Definition ast.h:155
const AstRawString * GetOneByteString(base::Vector< const uint8_t > literal)
bool should_save_class_variable_index() const
Definition scopes.h:1472
Variable * class_variable()
Definition scopes.h:1453
VariableProxy * ResolvePrivateNamesPartially()
Definition scopes.cc:3113
Variable * DeclareBrandVariable(AstValueFactory *ast_value_factory, IsStaticFlag is_static_flag, int class_token_pos)
Definition scopes.cc:3175
static const int kMaxArguments
Definition code.h:463
FunctionKind function_kind() const
Definition scopes.h:863
void DeclareArguments(AstValueFactory *ast_value_factory)
Definition scopes.cc:760
bool has_simple_parameters() const
Definition scopes.h:1076
Variable * var() const
Definition ast.h:375
static const char * VisitModeString(VisitMode mode)
Definition ast.h:543
SourceTextModuleDescriptor * module() const
Definition scopes.h:1379
AcceptINScope(ParserBase *parser, bool accept_IN)
BlockState(Zone *zone, Scope **scope_stack)
BlockState(Scope **scope_stack, Scope *scope)
base::PointerWithPayload< FunctionState, bool, 1 > state_and_prev_value_
void DisableOptimization(BailoutReason reason)
FunctionState(FunctionState **function_state_stack, Scope **scope_stack, DeclarationScope *scope)
DeclarationScope * scope() const
ParameterParsingScope(Impl *parser, FormalParametersT *parameters)
const BreakableStatementT statement() const
const BreakableStatementT statement_
const ZonePtrList< const AstRawString > *const labels_
const ZonePtrList< const AstRawString > * own_labels() const
const ZonePtrList< const AstRawString > * labels() const
Target(ParserBase *parser, BreakableStatementT statement, ZonePtrList< const AstRawString > *labels, ZonePtrList< const AstRawString > *own_labels, TargetType target_type)
const Target * previous() const
const ZonePtrList< const AstRawString > *const own_labels_
Scanner * scanner() const
V8_INLINE void ParseStatementList(StatementListT *body, Token::Value end_token)
RuntimeCallStats * runtime_call_stats_
typename Types::Expression ExpressionT
ExpressionT ParseConditionalContinuation(ExpressionT expression, int pos)
V8_INLINE ExpressionT ParseAssignmentExpression()
ExpressionT ParseExpressionCoverGrammar()
AstValueFactory * ast_value_factory_
FunctionKind FunctionKindForImpl(SubFunctionKind sub_function_kind, ParseFunctionFlags flags)
V8_NOINLINE void ReportMessageAt(Scanner::Location source_location, MessageTemplate message, const PreParserIdentifier &arg0)
DeclarationScope * GetReceiverScope() const
V8_INLINE DeclarationScope * GetDeclarationScope() const
BreakableStatementT LookupBreakTarget(IdentifierT label)
StatementT ParseThrowStatement()
StatementT ParseDebuggerStatement()
typename Types::StatementList StatementListT
V8_INLINE bool ParseCurrentSymbolAsClassFieldOrMethod(ParsePropertyInfo *prop_info, ExpressionT *name_expression)
bool IsParsingWhileDebugging() const
bool CheckInOrOf(ForEachStatement::VisitMode *visit_mode)
ExpressionT ParseFunctionExpression()
V8_INLINE ExpressionScope * expression_scope() const
ExpressionT ParseBindingPattern()
V8_INLINE Token::Value PeekAhead()
void ParseFormalParameterList(FormalParametersT *parameters)
IdentifierT ParseNonRestrictedIdentifier()
void CheckConflictingVarDeclarations(DeclarationScope *scope)
bool CheckContextualKeyword(Token::Value token)
typename v8::internal::ExpressionParsingScope< Types > ExpressionParsingScope
StatementT ParseNativeDeclaration()
StatementT ParseWhileStatement(ZonePtrList< const AstRawString > *labels, ZonePtrList< const AstRawString > *own_labels)
void ClassifyArrowParameter(AccumulationScope *accumulation_scope, int position, ExpressionT parameter)
StatementT ParseAsyncFunctionDeclaration(ZonePtrList< const AstRawString > *names, bool default_export)
int peek_end_position() const
StatementT ParseForStatement(ZonePtrList< const AstRawString > *labels, ZonePtrList< const AstRawString > *own_labels)
bool IsAssignableIdentifier(ExpressionT expression)
V8_INLINE ExpressionT ParseExpression()
V8_INLINE IdentifierT ParsePropertyName()
typename v8::internal::VariableDeclarationParsingScope< Types > VariableDeclarationParsingScope
FuncNameInferrer fni_
bool stack_overflow() const
void ValidateFormalParameters(LanguageMode language_mode, const FormalParametersT &parameters, bool allow_duplicates)
ExpressionT ParseArrowParametersWithRest(ExpressionListT *list, AccumulationScope *scope, int seen_variables)
VariableProxy * NewRawVariable(const AstRawString *name, int pos)
ExpressionT RewriteInvalidReferenceExpression(ExpressionT expression, int beg_pos, int end_pos, MessageTemplate message, bool early_error)
ExpressionT ParseLeftHandSideContinuation(ExpressionT expression)
void CheckStrictOctalLiteral(int beg_pos, int end_pos)
typename Types::Factory FactoryT
ExpressionT ParseAwaitExpression()
Scope * NewScopeWithParent(Scope *parent, ScopeType scope_type) const
typename Types::ForStatement ForStatementT
const AstRawString * ClassFieldVariableName(AstValueFactory *ast_value_factory, int index)
FunctionLiteral::EagerCompileHint default_eager_compile_hint_
StatementT ParseBreakStatement(ZonePtrList< const AstRawString > *labels)
FunctionState * function_state_
PendingCompilationErrorHandler * pending_error_handler()
V8_INLINE IdentifierT ParseAndClassifyIdentifier(Token::Value token)
typename Types::SourceRangeScope SourceRangeScope
V8_INLINE bool IsLet(const AstRawString *identifier) const
V8_NOINLINE void ReportMessage(MessageTemplate message, const Ts &... args)
ExpressionT ParseConditionalChainExpression(ExpressionT condition, int condition_pos)
V8_INLINE bool IsExtraordinaryPrivateNameAccessAllowed() const
DeclarationScope * NewFunctionScope(FunctionKind kind, Zone *parse_zone=nullptr) const
void CheckFunctionName(LanguageMode language_mode, IdentifierT function_name, FunctionNameValidity function_name_validity, const Scanner::Location &function_name_loc)
IterationStatementT LookupContinueTarget(IdentifierT label)
V8_INLINE ExpressionT ParseMemberExpressionContinuation(ExpressionT expression)
V8_INLINE bool ParseAccessorPropertyOrAutoAccessors(ParsePropertyInfo *prop_info, ExpressionT *name_expression, int *name_token_position)
StatementT ParseScopedStatement(ZonePtrList< const AstRawString > *labels)
typename Types::ClassLiteralProperty ClassLiteralPropertyT
VariableMode GetVariableMode(ClassLiteralProperty::Kind kind)
ExpressionT ParseImportExpressions()
static bool IsAccessor(ParsePropertyKind kind)
ClassScope * NewClassScope(Scope *parent, bool is_anonymous) const
void Expect(Token::Value token)
void CheckClassMethodName(IdentifierT name, ParsePropertyKind type, ParseFunctionFlags flags, bool is_static, bool *has_seen_constructor)
StatementT ParseStatementListItem()
DeclarationScope * NewScriptScope(REPLMode repl_mode) const
internal::V8FileLogger * v8_file_logger_
ExpressionT ParseAsyncFunctionLiteral()
typename Types::SourceRange SourceRange
void set_default_eager_compile_hint(FunctionLiteral::EagerCompileHint eager_compile_hint)
V8_INLINE Token::Value peek()
ObjectLiteralPropertyT ParseObjectPropertyDefinition(ParsePropertyInfo *prop_info, bool *has_seen_proto)
ExpressionT ParseV8Intrinsic()
typename Types::FunctionLiteral FunctionLiteralT
bool IsAwaitAsIdentifierDisallowed(FunctionKind kind) const
V8_INLINE Token::Value PeekAheadAhead()
V8_INLINE ExpressionT ParseBinaryExpression(int prec)
V8_INLINE ExpressionT ParsePostfixExpression()
bool PeekContextualKeyword(const AstRawString *name)
bool PeekContextualKeyword(Token::Value token)
Zone * main_zone() const
ExpressionT ParsePrimaryExpression()
ExpressionT ParseLogicalExpression()
std::vector< std::pair< VariableProxy *, int > > * variable_buffer()
const Impl * impl() const
void set_allow_eval_cache(bool allow)
V8_INLINE ExpressionT ParseConditionalExpression()
void CheckArityRestrictions(int param_count, FunctionKind function_type, bool has_rest, int formals_start_pos, int formals_end_pos)
typename Types::ClassStaticElementList ClassStaticElementListT
V8_INLINE bool ClassifyPropertyIdentifier(Token::Value token, ParsePropertyInfo *prop_info)
StatementT ParseForEachStatementWithDeclarations(int stmt_pos, ForInfo *for_info, ZonePtrList< const AstRawString > *labels, ZonePtrList< const AstRawString > *own_labels, Scope *inner_block_scope)
std::vector< std::pair< VariableProxy *, int > > variable_buffer_
ClassLiteralPropertyT ParseClassPropertyDefinition(ClassInfo *class_info, ParsePropertyInfo *prop_info, bool has_extends)
typename Types::FuncNameInferrer FuncNameInferrer
bool is_using_allowed() const
NextArrowFunctionInfo next_arrow_function_info_
bool is_async_generator() const
ForStatementT ParseStandardForLoop(int stmt_pos, ZonePtrList< const AstRawString > *labels, ZonePtrList< const AstRawString > *own_labels, ExpressionT *cond, StatementT *next, StatementT *body)
typename Types::Identifier IdentifierT
V8_INLINE void Consume(Token::Value token)
StatementT ParseContinueStatement()
StatementT ParseReturnStatement()
SourceTextModuleDescriptor * module() const
typename v8::internal::AccumulationScope< Types > AccumulationScope
V8_INLINE bool VerifyCanHaveAutoAccessorOrThrow(ParsePropertyInfo *prop_info, ExpressionT name_expression, int name_token_position)
const UnoptimizedCompileFlags & flags() const
BlockT ParseBlock(ZonePtrList< const AstRawString > *labels, Scope *block_scope)
StatementT ParseFunctionDeclaration()
ExpressionT ParseMemberWithPresentNewPrefixesExpression()
ExpressionT ParseAssignmentExpressionCoverGrammar()
V8_INLINE Token::Value Next()
ExpressionT DoParseMemberExpressionContinuation(ExpressionT expression)
typename Types::Statement StatementT
const AstRawString * AutoAccessorVariableName(AstValueFactory *ast_value_factory, int index)
ExpressionT ParseProperty(ParsePropertyInfo *prop_info)
ExpressionT ParseObjectLiteral()
bool ValidateRegExpLiteral(const AstRawString *pattern, RegExpFlags flags, RegExpError *regexp_error)
typename Types::BreakableStatement BreakableStatementT
const UnoptimizedCompileFlags flags_
ExpressionT ParseTemplateLiteral(ExpressionT tag, int start, bool tagged)
StatementT ParseStatement(ZonePtrList< const AstRawString > *labels, ZonePtrList< const AstRawString > *own_labels)
ExpressionT ParseCoalesceExpression(ExpressionT expression)
bool has_module_in_scope_chain() const
FunctionKind FunctionKindFor(ParseFunctionFlags flags)
int loop_nesting_depth() const
Types::Factory * factory()
V8_INLINE void ParseFormalParameter(FormalParametersT *parameters)
bool CheckContextualKeyword(const AstRawString *name)
ExpressionT ParseRegExpLiteral()
StatementT ParseStandardForLoopWithLexicalDeclarations(int stmt_pos, StatementT init, ForInfo *for_info, ZonePtrList< const AstRawString > *labels, ZonePtrList< const AstRawString > *own_labels)
void ExpectContextualKeyword(const AstRawString *name, const char *fullname=nullptr, int pos=-1)
ExpressionT ParseMemberInitializer(ClassInfo *class_info, int beg_pos, int info_id, bool is_static)
VariableProxy * NewUnresolved(const AstRawString *name)
AstValueFactory * ast_value_factory() const
bool is_async_function() const
PendingCompilationErrorHandler * pending_error_handler_
void ParseArguments(ExpressionListT *args, bool *has_spread, ParsingArrowHeadFlag maybe_arrow=kCertainlyNotArrowHead)
V8_INLINE bool Check(Token::Value token)
void ParseFunctionBody(StatementListT *body, IdentifierT function_name, int pos, const FormalParametersT &parameters, FunctionKind kind, FunctionSyntaxKind function_syntax_kind, FunctionBodyType body_type)
StatementT ParseClassDeclaration(ZonePtrList< const AstRawString > *names, bool default_export)
bool allow_eval_cache() const
ExpressionT ParseUnaryOrPrefixExpression()
V8_INLINE DeclarationScope * GetClosureScope() const
ExpressionT ParseClassExpression(Scope *outer_scope)
ExpressionT ParseClassLiteral(Scope *outer_scope, IdentifierT name, Scanner::Location class_name_location, bool name_is_strict_reserved, int class_token_pos)
bool TargetStackContainsLabel(const AstRawString *label)
bool MaybeParsingArrowhead() const
ExpressionT ParseSuperExpression()
bool is_await_as_identifier_disallowed() const
typename Types::ExpressionList ExpressionListT
typename Types::ObjectPropertyList ObjectPropertyListT
ParserBase(Zone *zone, Scanner *scanner, uintptr_t stack_limit, AstValueFactory *ast_value_factory, PendingCompilationErrorHandler *pending_error_handler, RuntimeCallStats *runtime_call_stats, V8FileLogger *v8_file_logger, UnoptimizedCompileFlags flags, bool parsing_on_main_thread, bool compile_hints_magic_enabled, bool compile_hints_per_function_magic_enabled)
V8_INLINE void UseThis()
typename v8::internal::ArrowHeadParsingScope< Types > ArrowHeadParsingScope
std::vector< void * > pointer_buffer_
bool ContainsLabel(const ZonePtrList< const AstRawString > *labels, const AstRawString *label)
void CheckClassFieldName(IdentifierT name, bool is_static)
bool IsValidReferenceExpression(ExpressionT expression)
StatementT ParseVariableStatement(VariableDeclarationContext var_context, ZonePtrList< const AstRawString > *names)
ExpressionT ParsePossibleDestructuringSubPattern(AccumulationScope *scope)
ExpressionT ParseArrayLiteral()
BlockT ParseClassStaticBlock(ClassInfo *class_info)
V8_INLINE IdentifierT ParseIdentifier(FunctionKind function_kind)
BlockT ParseBlock(ZonePtrList< const AstRawString > *labels)
const PendingCompilationErrorHandler * pending_error_handler() const
Scope * NewScope(ScopeType scope_type) const
ExpressionT ParseAssignmentExpressionCoverGrammarContinuation(int lhs_beg_pos, ExpressionT expression)
ExpressionT ParsePropertyOrPrivatePropertyName()
typename v8::internal::ExpressionScope< Types > ExpressionScope
StatementT ParseForEachStatementWithoutDeclarations(int stmt_pos, ExpressionT expression, int lhs_beg_pos, int lhs_end_pos, ForInfo *for_info, ZonePtrList< const AstRawString > *labels, ZonePtrList< const AstRawString > *own_labels)
V8_INLINE ExpressionT ParseUnaryExpression()
typename Types::Block BlockT
StatementT ParseHoistableDeclaration(ZonePtrList< const AstRawString > *names, bool default_export)
Types::Factory ast_node_factory_
bool is_await_allowed() const
DeclarationScope * NewEvalScope(Scope *parent) const
ExpressionT ParseNewTargetExpression()
ExpressionT ParseBinaryContinuation(ExpressionT x, int prec, int prec1)
bool ValidateRegExpFlags(RegExpFlags flags)
void RaiseLanguageMode(LanguageMode mode)
V8_INLINE ExpressionT ParseLeftHandSideExpression()
void DeclareLabel(ZonePtrList< const AstRawString > **labels, ZonePtrList< const AstRawString > **own_labels, const AstRawString *label)
V8_INLINE bool has_error() const
typename Types::ObjectLiteralProperty ObjectLiteralPropertyT
StatementT ParseForAwaitStatement(ZonePtrList< const AstRawString > *labels, ZonePtrList< const AstRawString > *own_labels)
StatementT BuildReturnStatement(ExpressionT expr, int pos, int end_pos=ReturnStatement::kFunctionLiteralReturnPosition)
StatementT ParseDoWhileStatement(ZonePtrList< const AstRawString > *labels, ZonePtrList< const AstRawString > *own_labels)
V8_NOINLINE void ReportMessageAt(Scanner::Location source_location, MessageTemplate message, const Ts &... args)
ExpressionT ParseConditionalChainAssignmentExpressionCoverGrammar()
typename Types::FuncNameInferrer::State FuncNameInferrerState
bool IsNextUsingKeyword(Token::Value token_after_using, bool is_await_using)
StatementT ParseIfStatement(ZonePtrList< const AstRawString > *labels)
V8_NOINLINE ExpressionT ParsePostfixContinuation(ExpressionT expression, int lhs_beg_pos)
void ParseClassLiteralBody(ClassInfo &class_info, IdentifierT name, int class_token_pos, Token::Value end_token)
StatementT ParseStatement(ZonePtrList< const AstRawString > *labels, ZonePtrList< const AstRawString > *own_labels, AllowLabelledFunctionStatement allow_function)
Scope * NewBlockScopeForObjectLiteral()
FormalParametersT * parameters_
V8_INLINE IdentifierT ParseIdentifier()
void SkipInfos(int delta)
bool CheckTemplateEscapes(bool should_throw)
StatementT ParseSwitchStatement(ZonePtrList< const AstRawString > *labels)
StatementT ParseWithStatement(ZonePtrList< const AstRawString > *labels)
V8_INLINE StatementT ParseTryStatement()
FunctionLiteral::EagerCompileHint default_eager_compile_hint() const
const AstRawString * GetNextSymbolForRegExpLiteral() const
typename Types::Suspend SuspendExpressionT
V8_NOINLINE void ReportUnexpectedToken(Token::Value token)
DeclarationScope * NewVarblockScope() const
int position_after_last_primary_expression_open_parenthesis_
ModuleScope * NewModuleScope(DeclarationScope *parent) const
void ExpectContextualKeyword(Token::Value token)
V8_INLINE ExpressionT ParseConditionalChainAssignmentExpression()
typename Types::ClassPropertyList ClassPropertyListT
V8_INLINE ExpressionT ParseMemberExpression()
bool CheckPossibleEvalCall(ExpressionT expression, bool is_optional_call, Scope *scope)
bool compile_hints_per_function_magic_enabled_
uintptr_t stack_limit() const
std::vector< void * > * pointer_buffer()
void ClassifyParameter(IdentifierT parameter, int beg_pos, int end_pos)
typename v8::internal::ParameterDeclarationParsingScope< Types > ParameterDeclarationParsingScope
LanguageMode language_mode()
VariableProxy * NewUnresolved(const AstRawString *name, int begin_pos, VariableKind kind=NORMAL_VARIABLE)
ClassLiteralProperty::Kind ClassPropertyKindFor(ParsePropertyKind kind)
ExpressionT ParseYieldExpression()
typename Types::IterationStatement IterationStatementT
StatementT ParseExpressionOrLabelledStatement(ZonePtrList< const AstRawString > *labels, ZonePtrList< const AstRawString > *own_labels, AllowLabelledFunctionStatement allow_function)
FunctionKind MethodKindFor(bool is_static, ParseFunctionFlags flags)
ExpressionT ParseArrowFunctionLiteral(const FormalParametersT &parameters, int function_literal_id, bool could_be_immediately_invoked)
void ParseVariableDeclarations(VariableDeclarationContext var_context, DeclarationParsingResult *parsing_result, ZonePtrList< const AstRawString > *names)
typename Types::FormalParameters FormalParametersT
ExpressionScope * expression_scope_
void set_stack_limit(uintptr_t stack_limit)
bool IfStartsWithUsingOrAwaitUsingKeyword()
StatementT ParseHoistableDeclaration(int pos, ParseFunctionFlags flags, ZonePtrList< const AstRawString > *names, bool default_export)
static bool VerifySyntax(Zone *zone, uintptr_t stack_limit, const CharT *input, int input_length, RegExpFlags flags, RegExpError *regexp_error_out, const DisallowGarbageCollection &no_gc)
Definition regexp.cc:124
static V8_EXPORT_PRIVATE bool VerifyFlags(RegExpFlags flags)
Definition regexp.cc:117
static constexpr int kFunctionLiteralReturnPosition
Definition ast.h:666
Token::Value Next()
Definition scanner.cc:162
Token::Value peek() const
Definition scanner.h:326
void clear_invalid_template_escape_message()
Definition scanner.h:313
bool SawMagicCommentCompileHintsAll() const
Definition scanner.h:437
bool next_literal_contains_escapes() const
Definition scanner.h:334
uint32_t smi_value() const
Definition scanner.h:389
bool literal_contains_escapes() const
Definition scanner.h:330
const Location & location() const
Definition scanner.h:298
Token::Value current_token() const
Definition scanner.h:294
V8_INLINE bool has_parser_error() const
Definition scanner.h:258
Token::Value ScanTemplateContinuation()
Definition scanner.h:422
bool HasLineTerminatorBeforeNext() const
Definition scanner.h:399
Token::Value PeekAhead()
Definition scanner.cc:193
Token::Value PeekAheadAhead()
Definition scanner.cc:209
V8_INLINE void set_parser_error()
Definition scanner.h:246
MessageTemplate octal_message() const
Definition scanner.h:386
std::optional< RegExpFlags > ScanRegExpFlags()
Definition scanner.cc:1092
const AstRawString * NextSymbol(AstValueFactory *ast_value_factory) const
Definition scanner.cc:1118
void clear_octal_position()
Definition scanner.h:382
const Location & peek_location() const
Definition scanner.h:328
bool HasPerFunctionCompileHint(int position)
Definition scanner.cc:348
Location octal_position() const
Definition scanner.h:381
bool HasLineTerminatorAfterNext()
Definition scanner.h:403
void Reparent(DeclarationScope *new_parent)
Definition scopes.cc:908
void set_is_block_scope_for_object_literal()
Definition scopes.h:382
void SetLanguageMode(LanguageMode language_mode)
Definition scopes.h:288
void set_end_position(int statement_pos)
Definition scopes.h:343
base::ThreadedList< Declaration > * declarations()
Definition scopes.h:229
bool is_reparsed() const
Definition scopes.h:116
Scope * outer_scope() const
Definition scopes.h:488
DeclarationScope * AsDeclarationScope()
VariableProxy * NewUnresolved(AstNodeFactory *factory, const AstRawString *name, int start_pos, VariableKind kind=NORMAL_VARIABLE)
Definition scopes.h:234
ClassScope * AsClassScope()
Definition scopes.cc:566
ModuleScope * AsModuleScope()
Definition scopes.cc:556
DeclarationScope * GetReceiverScope()
Definition scopes.cc:1501
void DeleteUnresolved(VariableProxy *var)
Definition scopes.cc:1245
Variable * DeclareHomeObjectVariable(AstValueFactory *ast_value_factory)
Definition scopes.cc:114
Variable * DeclareCatchVariableName(const AstRawString *name)
Definition scopes.cc:1213
ScopeType scope_type() const
Definition scopes.h:474
Variable * DeclareStaticHomeObjectVariable(AstValueFactory *ast_value_factory)
Definition scopes.cc:126
DeclarationScope * GetClosureScope()
Definition scopes.cc:1480
bool has_await_using_declaration() const
Definition scopes.h:393
void set_is_hidden()
Definition scopes.h:347
bool needs_home_object() const
Definition scopes.h:612
const AstRawString * FindVariableDeclaredIn(Scope *scope, VariableMode mode_limit)
Definition scopes.cc:1331
void set_start_position(int statement_pos)
Definition scopes.h:339
void RecordEvalCall()
Definition scopes.h:1340
Scope * FinalizeBlockScope()
Definition scopes.cc:847
int end_position() const
Definition scopes.h:342
DeclarationScope * GetDeclarationScope()
Definition scopes.cc:1456
LanguageMode language_mode() const
Definition scopes.h:477
void SetNonlinear()
Definition scopes.h:302
int start_position() const
Definition scopes.h:338
bool is_module_scope() const
Definition scopes.h:363
bool is_declaration_scope() const
Definition scopes.h:372
Variable * LookupLocal(const AstRawString *name)
Definition scopes.h:200
SourceRangeScope(const Scanner *scanner, SourceRange *range)
Definition parser-base.h:86
DISALLOW_IMPLICIT_CONSTRUCTORS(SourceRangeScope)
static bool IsArrowOrAssignmentOp(Value token)
Definition token.h:283
static V8_INLINE bool IsValidIdentifier(Value token, LanguageMode language_mode, bool is_generator, bool disallow_await)
Definition token.h:237
static bool IsAutoSemicolon(Value token)
Definition token.h:251
static bool IsTemplate(Value token)
Definition token.h:267
static bool IsAnyIdentifier(Value token)
Definition token.h:255
static bool IsMember(Value token)
Definition token.h:271
static bool IsCompareOp(Value op)
Definition token.h:297
static bool IsLogicalAssignmentOp(Value token)
Definition token.h:291
static bool IsUnaryOrCountOp(Value op)
Definition token.h:320
static bool IsProperty(Value token)
Definition token.h:275
static bool IsUnaryOp(Value op)
Definition token.h:318
static bool IsCallable(Value token)
Definition token.h:247
static bool IsLiteral(Value token)
Definition token.h:263
static bool IsPropertyOrCall(Value token)
Definition token.h:279
static bool IsCountOp(Value op)
Definition token.h:319
static bool IsStrictReservedWord(Value token)
Definition token.h:259
static bool IsPropertyName(Value token)
Definition token.h:233
static int Precedence(Value token, bool accept_IN)
Definition token.h:340
void FunctionEvent(const char *reason, int script_id, double time_delta_ms, int start_position, int end_position, Tagged< String > function_name)
Definition log.cc:1830
const AstRawString * raw_name() const
Definition ast.h:1513
void set_initializer_position(int pos)
Definition variables.h:122
const AstRawString * raw_name() const
Definition variables.h:65
void ForceContextAllocation()
Definition variables.h:81
V8_INLINE int length() const
Definition zone-list.h:101
T & at(int i) const
Definition zone-list.h:88
T & emplace_back(Args &&... args)
int start
int end
DeclarationScope * scope_
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
Label label
TNode< Object > target
std::string pattern
RpoNumber block
ZoneVector< RpoNumber > & result
int x
constexpr bool IsInRange(T value, U lower_limit, U higher_limit)
Definition bounds.h:20
bool IsArrowFunction(FunctionKind kind)
bool is_sloppy(LanguageMode language_mode)
Definition globals.h:773
constexpr int kNoSourcePosition
Definition globals.h:850
bool IsClassConstructor(FunctionKind kind)
bool IsLexicalVariableMode(VariableMode mode)
Definition globals.h:2155
SharedFunctionInfo::HasStaticPrivateMethodsOrAccessorsBit SharedFunctionInfo::MaglevCompilationFailedBit syntax_kind
@ SHADOW_REALM_SCOPE
Definition globals.h:1903
bool IsGeneratorFunction(FunctionKind kind)
bool IsDerivedConstructor(FunctionKind kind)
bool IsResumableFunction(FunctionKind kind)
bool IsConciseMethod(FunctionKind kind)
bool IsAsyncFunction(FunctionKind kind)
bool IsAccessorFunction(FunctionKind kind)
too high values may cause the compiler to set high thresholds for inlining to as much as possible avoid inlined allocation of objects that cannot escape trace load stores from virtual maglev objects use TurboFan fast string builder analyze liveness of environment slots and zap dead values trace TurboFan load elimination emit data about basic block usage in builtins to this enable builtin reordering when run mksnapshot flag for emit warnings when applying builtin profile data verify register allocation in TurboFan randomly schedule instructions to stress dependency tracking enable store store elimination in TurboFan rewrite far to near simulate GC compiler thread race related to allow float parameters to be passed in simulator mode JS Wasm Run additional turbo_optimize_inlined_js_wasm_wrappers enable experimental feedback collection in generic lowering enable Turboshaft s WasmLoadElimination enable Turboshaft s low level load elimination for JS enable Turboshaft s escape analysis for string concatenation use enable Turbolev features that we want to ship in the not too far future trace individual Turboshaft reduction steps trace intermediate Turboshaft reduction steps invocation count threshold for early optimization Enables optimizations which favor memory size over execution speed Enables sampling allocation profiler with X as a sample interval min size of a semi the new space consists of two semi spaces max size of the Collect garbage after Collect garbage after keeps maps alive for< n > old space garbage collections print one detailed trace line in name
Definition flags.cc:2086
bool IsImmutableLexicalVariableMode(VariableMode mode)
Definition globals.h:2145
@ SLOPPY_BLOCK_FUNCTION_VARIABLE
Definition globals.h:2112
bool IsAsyncGeneratorFunction(FunctionKind kind)
uintptr_t GetCurrentStackPosition()
Definition utils.cc:222
bool IsModule(FunctionKind kind)
constexpr bool RegExpErrorIsStackOverflow(RegExpError error)
constexpr int kFunctionLiteralIdTopLevel
Definition globals.h:2767
AllowLabelledFunctionStatement
Definition parser-base.h:44
@ kAllowLabelledFunctionStatement
Definition parser-base.h:45
@ kDisallowLabelledFunctionStatement
Definition parser-base.h:46
const char * RegExpErrorString(RegExpError error)
bool is_strict(LanguageMode language_mode)
Definition globals.h:777
V8_EXPORT_PRIVATE FlagValues v8_flags
bool IsGetterFunction(FunctionKind kind)
return value
Definition map-inl.h:893
@ kSkipFunctionNameCheck
Definition parser-base.h:40
@ kFunctionNameIsStrictReserved
Definition parser-base.h:39
@ kFunctionNameValidityUnknown
Definition parser-base.h:41
@ kCertainlyNotArrowHead
Definition parser-base.h:49
kInstanceDescriptorsOffset kTransitionsOrPrototypeInfoOffset IsNull(value)||IsJSProxy(value)||IsWasmObject(value)||(IsJSObject(value) &&(HeapLayout
Definition map-inl.h:70
bool IsSetterFunction(FunctionKind kind)
const char * ImmutableLexicalVariableModeToString(VariableMode mode)
Definition globals.h:2095
ModuleImportPhase
#define RETURN_IF_PARSE_ERROR
RegExpParserImpl< CharT > *const parser_
#define RCS_SCOPE(...)
#define DCHECK_NULL(val)
Definition logging.h:491
#define CHECK(condition)
Definition logging.h:124
#define DCHECK_NOT_NULL(val)
Definition logging.h:492
#define DCHECK_IMPLIES(v1, v2)
Definition logging.h:493
#define DCHECK_NE(v1, v2)
Definition logging.h:486
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define USE(...)
Definition macros.h:293
FormalParametersBase(DeclarationScope *scope)
Definition parser-base.h:60
void UpdateArityAndFunctionLength(bool is_optional, bool is_rest)
Definition parser-base.h:69
ClassStaticElementListT static_elements
DeclarationScope * EnsureInstanceMembersScope(ParserBase *parser, int beg_pos, int info_id)
DeclarationScope * EnsureStaticElementsScope(ParserBase *parser, int beg_pos, int info_id)
DeclarationScope * static_elements_scope
DeclarationScope * instance_members_scope
Declaration(ExpressionT pattern, ExpressionT initializer)
ForEachStatement::VisitMode mode
ZonePtrList< const AstRawString > bound_names
DeclarationParsingResult parsing_result
bool ParsePropertyKindFromToken(Token::Value token)
ParsePropertyInfo(ParserBase *parser, AccumulationScope *accumulation_scope=nullptr)
static Location invalid()
Definition scanner.h:270
static SourceRange ContinuationOf(const SourceRange &that, int end=kNoSourcePosition)
Symbol identifier
Symbol declaration
Symbol * expression
Symbol statement
#define V8_INLINE
Definition v8config.h:500
#define V8_LIKELY(condition)
Definition v8config.h:661
#define V8_UNLIKELY(condition)
Definition v8config.h:660
#define V8_NOINLINE
Definition v8config.h:586
#define V8_NODISCARD
Definition v8config.h:693
Node ** parameters_