1// Copyright 2018 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_EXPRESSION_SCOPE_H_
6#define V8_PARSING_EXPRESSION_SCOPE_H_
7
8#include "src/ast/scopes.h"
9#include "src/function-kind.h"
10#include "src/message-template.h"
11#include "src/parsing/scanner.h"
12#include "src/zone/zone.h" // For ScopedPtrList.
13
14namespace v8 {
15namespace internal {
16
17template <typename Types>
18class ExpressionParsingScope;
19template <typename Types>
20class AccumulationScope;
21template <typename Types>
22class ArrowHeadParsingScope;
23template <typename Types>
24class ParameterDeclarationParsingScope;
25template <typename Types>
26class VariableDeclarationParsingScope;
27class VariableProxy;
28
29// ExpressionScope is used in a stack fashion, and is used to specialize
30// expression parsing for the task at hand. It allows the parser to reuse the
31// same code to parse destructuring declarations, assignment patterns,
32// expressions, and (async) arrow function heads.
33//
34// One of the specific subclasses needs to be instantiated to tell the parser
35// the meaning of the expression it will parse next. The parser then calls
36// Record* on the expression_scope() to indicate errors. The expression_scope
37// will either discard those errors, immediately report those errors, or
38// classify the errors for later validation.
39// TODO(verwaest): Record is a slightly odd name since it will directly throw
40// for unambiguous scopes.
41template <typename Types>
42class ExpressionScope {
43 public:
44 using ParserT = typename Types::Impl;
45 using ExpressionT = typename Types::Expression;
46
47 VariableProxy* NewVariable(const AstRawString* name,
48 int pos = kNoSourcePosition) {
49 VariableProxy* result = parser_->NewRawVariable(name, pos);
50 if (CanBeExpression()) {
51 AsExpressionParsingScope()->TrackVariable(result);
52 } else {
53 Variable* var = Declare(name, pos);
54 if (IsVarDeclaration() && !parser()->scope()->is_declaration_scope()) {
55 // Make sure we'll properly resolve the variable since we might be in a
56 // with or catch scope. In those cases the proxy isn't guaranteed to
57 // refer to the declared variable, so consider it unresolved.
58 parser()->scope()->AddUnresolved(result);
59 } else {
60 DCHECK_NOT_NULL(var);
61 result->BindTo(var);
62 }
63 }
64 return result;
65 }
66
67 Variable* Declare(const AstRawString* name, int pos = kNoSourcePosition) {
68 if (type_ == kParameterDeclaration) {
69 return AsParameterDeclarationParsingScope()->Declare(name, pos);
70 }
71 return AsVariableDeclarationParsingScope()->Declare(name, pos);
72 }
73
74 void MarkIdentifierAsAssigned() {
75 if (!CanBeExpression()) return;
76 AsExpressionParsingScope()->MarkIdentifierAsAssigned();
77 }
78
79 void ValidateAsPattern(ExpressionT expression, int begin, int end) {
80 if (!CanBeExpression()) return;
81 AsExpressionParsingScope()->ValidatePattern(expression, begin, end);
82 AsExpressionParsingScope()->ClearExpressionError();
83 }
84
85 // Record async arrow parameters errors in all ambiguous async arrow scopes in
86 // the chain up to the first unambiguous scope.
87 void RecordAsyncArrowParametersError(const Scanner::Location& loc,
88 MessageTemplate message) {
89 // Only ambiguous scopes (ExpressionParsingScope, *ArrowHeadParsingScope)
90 // need to propagate errors to a possible kAsyncArrowHeadParsingScope, so
91 // immediately return if the current scope is not ambiguous.
92 if (!CanBeExpression()) return;
93 AsExpressionParsingScope()->RecordAsyncArrowParametersError(loc, message);
94 }
95
96 // Record initializer errors in all scopes that can turn into parameter scopes
97 // (ArrowHeadParsingScopes) up to the first known unambiguous parameter scope.
98 void RecordParameterInitializerError(const Scanner::Location& loc,
99 MessageTemplate message) {
100 ExpressionScope* scope = this;
101 while (!scope->IsCertainlyParameterDeclaration()) {
102 if (!has_possible_parameter_in_scope_chain_) return;
103 if (scope->CanBeParameterDeclaration()) {
104 scope->AsArrowHeadParsingScope()->RecordDeclarationError(loc, message);
105 }
106 scope = scope->parent();
107 if (scope == nullptr) return;
108 }
109 Report(loc, message);
110 }
111
112 void RecordThisUse() {
113 ExpressionScope* scope = this;
114 do {
115 if (scope->IsArrowHeadParsingScope()) {
116 scope->AsArrowHeadParsingScope()->RecordThisUse();
117 }
118 scope = scope->parent();
119 } while (scope != nullptr);
120 }
121
122 void RecordPatternError(const Scanner::Location& loc,
123 MessageTemplate message) {
124 // TODO(verwaest): Non-assigning expression?
125 if (IsCertainlyPattern()) {
126 Report(loc, message);
127 } else {
128 AsExpressionParsingScope()->RecordPatternError(loc, message);
129 }
130 }
131
132 void RecordStrictModeParameterError(const Scanner::Location& loc,
133 MessageTemplate message) {
134 DCHECK_IMPLIES(!has_error(), loc.IsValid());
135 if (!CanBeParameterDeclaration()) return;
136 if (IsCertainlyParameterDeclaration()) {
137 if (is_strict(parser_->language_mode())) {
138 Report(loc, message);
139 } else {
140 parser_->parameters_->set_strict_parameter_error(loc, message);
141 }
142 } else {
143 parser_->next_arrow_function_info_.strict_parameter_error_location = loc;
144 parser_->next_arrow_function_info_.strict_parameter_error_message =
145 message;
146 }
147 }
148
149 void RecordDeclarationError(const Scanner::Location& loc,
150 MessageTemplate message) {
151 if (!CanBeDeclaration()) return;
152 if (IsCertainlyDeclaration()) {
153 Report(loc, message);
154 } else {
155 AsArrowHeadParsingScope()->RecordDeclarationError(loc, message);
156 }
157 }
158
159 void RecordExpressionError(const Scanner::Location& loc,
160 MessageTemplate message) {
161 if (!CanBeExpression()) return;
162 // TODO(verwaest): Non-assigning expression?
163 // if (IsCertainlyExpression()) Report(loc, message);
164 AsExpressionParsingScope()->RecordExpressionError(loc, message);
165 }
166
167 void RecordNonSimpleParameter() {
168 if (!IsArrowHeadParsingScope()) return;
169 AsArrowHeadParsingScope()->RecordNonSimpleParameter();
170 }
171
172 bool IsCertainlyDeclaration() const {
173 return IsInRange(type_, kParameterDeclaration, kLexicalDeclaration);
174 }
175
176 protected:
177 enum ScopeType : uint8_t {
178 // Expression or assignment target.
179 kExpression,
180
181 // Declaration or expression or assignment target.
182 kMaybeArrowParameterDeclaration,
183 kMaybeAsyncArrowParameterDeclaration,
184
185 // Declarations.
186 kParameterDeclaration,
187 kVarDeclaration,
188 kLexicalDeclaration,
189 };
190
191 ParserT* parser() const { return parser_; }
192 ExpressionScope* parent() const { return parent_; }
193
194 void Report(const Scanner::Location& loc, MessageTemplate message) const {
195 parser_->ReportMessageAt(loc, message);
196 }
197
198 ExpressionScope(ParserT* parser, ScopeType type)
199 : parser_(parser),
200 parent_(parser->expression_scope_),
201 type_(type),
202 has_possible_parameter_in_scope_chain_(
203 CanBeParameterDeclaration() ||
204 (parent_ && parent_->has_possible_parameter_in_scope_chain_)) {
205 parser->expression_scope_ = this;
206 }
207
208 ~ExpressionScope() {
209 DCHECK(parser_->expression_scope_ == this ||
210 parser_->expression_scope_ == parent_);
211 parser_->expression_scope_ = parent_;
212 }
213
214 ExpressionParsingScope<Types>* AsExpressionParsingScope() {
215 DCHECK(CanBeExpression());
216 return static_cast<ExpressionParsingScope<Types>*>(this);
217 }
218
219#ifdef DEBUG
220 bool has_error() const { return parser_->has_error(); }
221#endif
222
223 bool CanBeExpression() const {
224 return IsInRange(type_, kExpression, kMaybeAsyncArrowParameterDeclaration);
225 }
226 bool CanBeDeclaration() const {
227 return IsInRange(type_, kMaybeArrowParameterDeclaration,
228 kLexicalDeclaration);
229 }
230 bool IsVariableDeclaration() const {
231 return IsInRange(type_, kVarDeclaration, kLexicalDeclaration);
232 }
233 bool IsLexicalDeclaration() const { return type_ == kLexicalDeclaration; }
234 bool IsAsyncArrowHeadParsingScope() const {
235 return type_ == kMaybeAsyncArrowParameterDeclaration;
236 }
237 bool IsVarDeclaration() const { return type_ == kVarDeclaration; }
238
239 private:
240 friend class AccumulationScope<Types>;
241 friend class ExpressionParsingScope<Types>;
242
243 ArrowHeadParsingScope<Types>* AsArrowHeadParsingScope() {
244 DCHECK(IsArrowHeadParsingScope());
245 return static_cast<ArrowHeadParsingScope<Types>*>(this);
246 }
247
248 ParameterDeclarationParsingScope<Types>*
249 AsParameterDeclarationParsingScope() {
250 DCHECK(IsCertainlyParameterDeclaration());
251 return static_cast<ParameterDeclarationParsingScope<Types>*>(this);
252 }
253
254 VariableDeclarationParsingScope<Types>* AsVariableDeclarationParsingScope() {
255 DCHECK(IsVariableDeclaration());
256 return static_cast<VariableDeclarationParsingScope<Types>*>(this);
257 }
258
259 bool IsArrowHeadParsingScope() const {
260 return IsInRange(type_, kMaybeArrowParameterDeclaration,
261 kMaybeAsyncArrowParameterDeclaration);
262 }
263 bool IsCertainlyPattern() const { return IsCertainlyDeclaration(); }
264 bool CanBeParameterDeclaration() const {
265 return IsInRange(type_, kMaybeArrowParameterDeclaration,
266 kParameterDeclaration);
267 }
268 bool IsCertainlyParameterDeclaration() const {
269 return type_ == kParameterDeclaration;
270 }
271
272 ParserT* parser_;
273 ExpressionScope<Types>* parent_;
274 ScopeType type_;
275 bool has_possible_parameter_in_scope_chain_;
276
277 DISALLOW_COPY_AND_ASSIGN(ExpressionScope);
278};
279
280// Used to unambiguously parse var, let, const declarations.
281template <typename Types>
282class VariableDeclarationParsingScope : public ExpressionScope<Types> {
283 public:
284 using ParserT = typename Types::Impl;
285 using ExpressionScopeT = ExpressionScope<Types>;
286 using ScopeType = typename ExpressionScopeT::ScopeType;
287
288 VariableDeclarationParsingScope(ParserT* parser, VariableMode mode,
289 ZonePtrList<const AstRawString>* names)
290 : ExpressionScopeT(parser, IsLexicalVariableMode(mode)
291 ? ExpressionScopeT::kLexicalDeclaration
292 : ExpressionScopeT::kVarDeclaration),
293 mode_(mode),
294 names_(names) {}
295
296 Variable* Declare(const AstRawString* name, int pos) {
297 VariableKind kind = NORMAL_VARIABLE;
298 bool was_added;
299 Variable* var = this->parser()->DeclareVariable(
300 name, kind, mode_, Variable::DefaultInitializationFlag(mode_),
301 this->parser()->scope(), &was_added, pos);
302 if (was_added &&
303 this->parser()->scope()->num_var() > kMaxNumFunctionLocals) {
304 this->parser()->ReportMessage(MessageTemplate::kTooManyVariables);
305 }
306 if (names_) names_->Add(name, this->parser()->zone());
307 if (this->IsLexicalDeclaration()) {
308 if (this->parser()->IsLet(name)) {
309 this->parser()->ReportMessageAt(
310 Scanner::Location(pos, pos + name->length()),
311 MessageTemplate::kLetInLexicalBinding);
312 }
313 } else {
314 if (this->parser()->loop_nesting_depth() > 0) {
315 // Due to hoisting, the value of a 'var'-declared variable may actually
316 // change even if the code contains only the "initial" assignment,
317 // namely when that assignment occurs inside a loop. For example:
318 //
319 // let i = 10;
320 // do { var x = i } while (i--):
321 //
322 // Note that non-lexical variables include temporaries, which may also
323 // get assigned inside a loop due to the various rewritings that the
324 // parser performs.
325 //
326 // Pessimistically mark all vars in loops as assigned. This
327 // overapproximates the actual assigned vars due to unassigned var
328 // without initializer, but that's unlikely anyway.
329 //
330 // This also handles marking of loop variables in for-in and for-of
331 // loops, as determined by loop-nesting-depth.
332 DCHECK_NOT_NULL(var);
333 var->set_maybe_assigned();
334 }
335 }
336 return var;
337 }
338
339 private:
340 // Limit the allowed number of local variables in a function. The hard limit
341 // in Ignition is 2^31-1 due to the size of register operands. We limit it to
342 // a more reasonable lower up-limit.
343 static const int kMaxNumFunctionLocals = (1 << 23) - 1;
344
345 VariableMode mode_;
346 ZonePtrList<const AstRawString>* names_;
347
348 DISALLOW_COPY_AND_ASSIGN(VariableDeclarationParsingScope);
349};
350
351template <typename Types>
352class ParameterDeclarationParsingScope : public ExpressionScope<Types> {
353 public:
354 using ParserT = typename Types::Impl;
355 using ExpressionScopeT = ExpressionScope<Types>;
356 using ScopeType = typename ExpressionScopeT::ScopeType;
357
358 explicit ParameterDeclarationParsingScope(ParserT* parser)
359 : ExpressionScopeT(parser, ExpressionScopeT::kParameterDeclaration) {}
360
361 Variable* Declare(const AstRawString* name, int pos) {
362 VariableKind kind = PARAMETER_VARIABLE;
363 VariableMode mode = VariableMode::kVar;
364 bool was_added;
365 Variable* var = this->parser()->DeclareVariable(
366 name, kind, mode, Variable::DefaultInitializationFlag(mode),
367 this->parser()->scope(), &was_added, pos);
368 if (!has_duplicate() && !was_added) {
369 duplicate_loc_ = Scanner::Location(pos, pos + name->length());
370 }
371 return var;
372 }
373
374 bool has_duplicate() const { return duplicate_loc_.IsValid(); }
375
376 const Scanner::Location& duplicate_location() const { return duplicate_loc_; }
377
378 private:
379 Scanner::Location duplicate_loc_ = Scanner::Location::invalid();
380 DISALLOW_COPY_AND_ASSIGN(ParameterDeclarationParsingScope);
381};
382
383// Parsing expressions is always ambiguous between at least left-hand-side and
384// right-hand-side of assignments. This class is used to keep track of errors
385// relevant for either side until it is clear what was being parsed.
386// The class also keeps track of all variable proxies that are created while the
387// scope was active. If the scope is an expression, the variable proxies will be
388// added to the unresolved list. Otherwise they are declarations and aren't
389// added. The list is also used to mark the variables as assigned in case we are
390// parsing an assignment expression.
391template <typename Types>
392class ExpressionParsingScope : public ExpressionScope<Types> {
393 public:
394 using ParserT = typename Types::Impl;
395 using ExpressionT = typename Types::Expression;
396 using ExpressionScopeT = ExpressionScope<Types>;
397 using ScopeType = typename ExpressionScopeT::ScopeType;
398
399 ExpressionParsingScope(ParserT* parser,
400 ScopeType type = ExpressionScopeT::kExpression)
401 : ExpressionScopeT(parser, type),
402 variable_list_(parser->variable_buffer()),
403 has_async_arrow_in_scope_chain_(
404 type == ExpressionScopeT::kMaybeAsyncArrowParameterDeclaration ||
405 (this->parent() && this->parent()->CanBeExpression() &&
406 this->parent()
407 ->AsExpressionParsingScope()
408 ->has_async_arrow_in_scope_chain_)) {
409 DCHECK(this->CanBeExpression());
410 clear(kExpressionIndex);
411 clear(kPatternIndex);
412 }
413
414 void RecordAsyncArrowParametersError(const Scanner::Location& loc,
415 MessageTemplate message) {
416 for (ExpressionScopeT* scope = this; scope != nullptr;
417 scope = scope->parent()) {
418 if (!has_async_arrow_in_scope_chain_) break;
419 if (scope->type_ ==
420 ExpressionScopeT::kMaybeAsyncArrowParameterDeclaration) {
421 scope->AsArrowHeadParsingScope()->RecordDeclarationError(loc, message);
422 }
423 }
424 }
425
426 ~ExpressionParsingScope() { DCHECK(this->has_error() || verified_); }
427
428 ExpressionT ValidateAndRewriteReference(ExpressionT expression, int beg_pos,
429 int end_pos) {
430 if (V8_LIKELY(this->parser()->IsAssignableIdentifier(expression))) {
431 MarkIdentifierAsAssigned();
432 this->mark_verified();
433 return expression;
434 } else if (V8_LIKELY(expression->IsProperty())) {
435 ValidateExpression();
436 return expression;
437 }
438 this->mark_verified();
439 return this->parser()->RewriteInvalidReferenceExpression(
440 expression, beg_pos, end_pos, MessageTemplate::kInvalidLhsInFor,
441 kSyntaxError);
442 }
443
444 void RecordExpressionError(const Scanner::Location& loc,
445 MessageTemplate message) {
446 Record(kExpressionIndex, loc, message);
447 }
448
449 void RecordPatternError(const Scanner::Location& loc,
450 MessageTemplate message) {
451 Record(kPatternIndex, loc, message);
452 }
453
454 void ValidateExpression() { Validate(kExpressionIndex); }
455
456 void ValidatePattern(ExpressionT expression, int begin, int end) {
457 Validate(kPatternIndex);
458 if (expression->is_parenthesized()) {
459 ExpressionScopeT::Report(Scanner::Location(begin, end),
460 MessageTemplate::kInvalidDestructuringTarget);
461 }
462 for (VariableProxy* proxy : variable_list_) {
463 proxy->set_is_assigned();
464 }
465 }
466
467 void ClearExpressionError() {
468 DCHECK(verified_);
469#ifdef DEBUG
470 verified_ = false;
471#endif
472 clear(kExpressionIndex);
473 }
474
475 void TrackVariable(VariableProxy* variable) {
476 if (!this->CanBeDeclaration()) {
477 this->parser()->scope()->AddUnresolved(variable);
478 }
479 variable_list_.Add(variable);
480 }
481
482 void MarkIdentifierAsAssigned() {
483 // It's possible we're parsing a syntax error. In that case it's not
484 // guaranteed that there's a variable in the list.
485 if (variable_list_.length() == 0) return;
486 variable_list_.at(variable_list_.length() - 1)->set_is_assigned();
487 }
488
489 protected:
490 bool is_verified() const {
491#ifdef DEBUG
492 return verified_;
493#else
494 return false;
495#endif
496 }
497
498 void ValidatePattern() { Validate(kPatternIndex); }
499
500 ScopedPtrList<VariableProxy>* variable_list() { return &variable_list_; }
501
502 private:
503 friend class AccumulationScope<Types>;
504
505 enum ErrorNumber : uint8_t {
506 kExpressionIndex = 0,
507 kPatternIndex = 1,
508 kNumberOfErrors = 2,
509 };
510 void clear(int index) {
511 messages_[index] = MessageTemplate::kNone;
512 locations_[index] = Scanner::Location::invalid();
513 }
514 bool is_valid(int index) const { return !locations_[index].IsValid(); }
515 void Record(int index, const Scanner::Location& loc,
516 MessageTemplate message) {
517 DCHECK_IMPLIES(!this->has_error(), loc.IsValid());
518 if (!is_valid(index)) return;
519 messages_[index] = message;
520 locations_[index] = loc;
521 }
522 void Validate(int index) {
523 DCHECK(!this->is_verified());
524 if (!is_valid(index)) Report(index);
525 this->mark_verified();
526 }
527 void Report(int index) const {
528 ExpressionScopeT::Report(locations_[index], messages_[index]);
529 }
530
531 // Debug verification to make sure every scope is validated exactly once.
532 void mark_verified() {
533#ifdef DEBUG
534 verified_ = true;
535#endif
536 }
537 void clear_verified() {
538#ifdef DEBUG
539 verified_ = false;
540#endif
541 }
542#ifdef DEBUG
543 bool verified_ = false;
544#endif
545
546 ScopedPtrList<VariableProxy> variable_list_;
547 MessageTemplate messages_[kNumberOfErrors];
548 Scanner::Location locations_[kNumberOfErrors];
549 bool has_async_arrow_in_scope_chain_;
550
551 DISALLOW_COPY_AND_ASSIGN(ExpressionParsingScope);
552};
553
554// This class is used to parse multiple ambiguous expressions and declarations
555// in the same scope. E.g., in async(X,Y,Z) or [X,Y,Z], X and Y and Z will all
556// be parsed in the respective outer ArrowHeadParsingScope and
557// ExpressionParsingScope. It provides a clean error state in the underlying
558// scope to parse the individual expressions, while keeping track of the
559// expression and pattern errors since the start. The AccumulationScope is only
560// used to keep track of the errors so far, and the underlying ExpressionScope
561// keeps being used as the expression_scope(). If the expression_scope() isn't
562// ambiguous, this class does not do anything.
563template <typename Types>
564class AccumulationScope {
565 public:
566 using ParserT = typename Types::Impl;
567
568 static const int kNumberOfErrors =
569 ExpressionParsingScope<Types>::kNumberOfErrors;
570 explicit AccumulationScope(ExpressionScope<Types>* scope) : scope_(nullptr) {
571 if (!scope->CanBeExpression()) return;
572 scope_ = scope->AsExpressionParsingScope();
573 for (int i = 0; i < kNumberOfErrors; i++) {
574 // If the underlying scope is already invalid at the start, stop
575 // accumulating. That means an error was found outside of an
576 // accumulating path.
577 if (!scope_->is_valid(i)) {
578 scope_ = nullptr;
579 break;
580 }
581 copy(i);
582 }
583 }
584
585 // Merge errors from the underlying ExpressionParsingScope into this scope.
586 // Only keeps the first error across all accumulate calls, and removes the
587 // error from the underlying scope.
588 void Accumulate() {
589 if (scope_ == nullptr) return;
590 DCHECK(!scope_->is_verified());
591 for (int i = 0; i < kNumberOfErrors; i++) {
592 if (!locations_[i].IsValid()) copy(i);
593 scope_->clear(i);
594 }
595 }
596
597 // This is called instead of Accumulate in case the parsed member is already
598 // known to be an expression. In that case we don't need to accumulate the
599 // expression but rather validate it immediately. We also ignore the pattern
600 // error since the parsed member is known to not be a pattern. This is
601 // necessary for "{x:1}.y" parsed as part of an assignment pattern. {x:1} will
602 // record a pattern error, but "{x:1}.y" is actually a valid as part of an
603 // assignment pattern since it's a property access.
604 void ValidateExpression() {
605 if (scope_ == nullptr) return;
606 DCHECK(!scope_->is_verified());
607 scope_->ValidateExpression();
608 DCHECK(scope_->is_verified());
609 scope_->clear(ExpressionParsingScope<Types>::kPatternIndex);
610#ifdef DEBUG
611 scope_->clear_verified();
612#endif
613 }
614
615 ~AccumulationScope() {
616 if (scope_ == nullptr) return;
617 Accumulate();
618 for (int i = 0; i < kNumberOfErrors; i++) copy_back(i);
619 }
620
621 private:
622 void copy(int entry) {
623 messages_[entry] = scope_->messages_[entry];
624 locations_[entry] = scope_->locations_[entry];
625 }
626
627 void copy_back(int entry) {
628 if (!locations_[entry].IsValid()) return;
629 scope_->messages_[entry] = messages_[entry];
630 scope_->locations_[entry] = locations_[entry];
631 }
632
633 ExpressionParsingScope<Types>* scope_;
634 MessageTemplate messages_[2];
635 Scanner::Location locations_[2];
636
637 DISALLOW_COPY_AND_ASSIGN(AccumulationScope);
638};
639
640// The head of an arrow function is ambiguous between expression, assignment
641// pattern and declaration. This keeps track of the additional declaration
642// error and allows the scope to be validated as a declaration rather than an
643// expression or a pattern.
644template <typename Types>
645class ArrowHeadParsingScope : public ExpressionParsingScope<Types> {
646 public:
647 using ParserT = typename Types::Impl;
648 using ScopeType = typename ExpressionScope<Types>::ScopeType;
649
650 ArrowHeadParsingScope(ParserT* parser, FunctionKind kind)
651 : ExpressionParsingScope<Types>(
652 parser,
653 kind == FunctionKind::kArrowFunction
654 ? ExpressionScope<Types>::kMaybeArrowParameterDeclaration
655 : ExpressionScope<
656 Types>::kMaybeAsyncArrowParameterDeclaration) {
657 DCHECK(kind == FunctionKind::kAsyncArrowFunction ||
658 kind == FunctionKind::kArrowFunction);
659 DCHECK(this->CanBeDeclaration());
660 DCHECK(!this->IsCertainlyDeclaration());
661 }
662
663 void ValidateExpression() {
664 // Turns out this is not an arrow head. Clear any possible tracked strict
665 // parameter errors, and reinterpret tracked variables as unresolved
666 // references.
667 this->parser()->next_arrow_function_info_.ClearStrictParameterError();
668 ExpressionParsingScope<Types>::ValidateExpression();
669 for (VariableProxy* proxy : *this->variable_list()) {
670 this->parser()->scope()->AddUnresolved(proxy);
671 }
672 }
673
674 DeclarationScope* ValidateAndCreateScope() {
675 DCHECK(!this->is_verified());
676 if (declaration_error_location.IsValid()) {
677 ExpressionScope<Types>::Report(declaration_error_location,
678 declaration_error_message);
679 }
680 this->ValidatePattern();
681
682 DeclarationScope* result = this->parser()->NewFunctionScope(kind());
683 if (!has_simple_parameter_list_) result->SetHasNonSimpleParameters();
684 VariableKind kind = PARAMETER_VARIABLE;
685 VariableMode mode =
686 has_simple_parameter_list_ ? VariableMode::kVar : VariableMode::kLet;
687 for (VariableProxy* proxy : *this->variable_list()) {
688 bool was_added;
689 this->parser()->DeclareAndBindVariable(
690 proxy, kind, mode, Variable::DefaultInitializationFlag(mode), result,
691 &was_added, proxy->position());
692 if (!was_added) {
693 ExpressionScope<Types>::Report(proxy->location(),
694 MessageTemplate::kParamDupe);
695 }
696 }
697
698 int initializer_position = this->parser()->end_position();
699 for (auto declaration : *result->declarations()) {
700 declaration->var()->set_initializer_position(initializer_position);
701 }
702 if (uses_this_) result->UsesThis();
703 return result;
704 }
705
706 void RecordDeclarationError(const Scanner::Location& loc,
707 MessageTemplate message) {
708 DCHECK_IMPLIES(!this->has_error(), loc.IsValid());
709 declaration_error_location = loc;
710 declaration_error_message = message;
711 }
712
713 void RecordNonSimpleParameter() { has_simple_parameter_list_ = false; }
714 void RecordThisUse() { uses_this_ = true; }
715
716 private:
717 FunctionKind kind() const {
718 return this->IsAsyncArrowHeadParsingScope()
719 ? FunctionKind::kAsyncArrowFunction
720 : FunctionKind::kArrowFunction;
721 }
722
723 Scanner::Location declaration_error_location = Scanner::Location::invalid();
724 MessageTemplate declaration_error_message = MessageTemplate::kNone;
725 bool has_simple_parameter_list_ = true;
726 bool uses_this_ = false;
727
728 DISALLOW_COPY_AND_ASSIGN(ArrowHeadParsingScope);
729};
730
731} // namespace internal
732} // namespace v8
733
734#endif // V8_PARSING_EXPRESSION_SCOPE_H_
735