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