LCOV - code coverage report
Current view: top level - src/parsing - expression-scope.h (source / functions) Hit Total Coverage
Test: app.info Lines: 139 139 100.0 %
Date: 2019-01-20 Functions: 46 46 100.0 %

          Line data    Source code
       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/message-template.h"
      10             : #include "src/parsing/scanner.h"
      11             : #include "src/zone/zone.h"  // For ScopedPtrList.
      12             : 
      13             : namespace v8 {
      14             : namespace internal {
      15             : 
      16             : template <typename Types>
      17             : class ExpressionParsingScope;
      18             : template <typename Types>
      19             : class AccumulationScope;
      20             : template <typename Types>
      21             : class ArrowHeadParsingScope;
      22             : class VariableProxy;
      23             : 
      24             : // ExpressionScope is used in a stack fashion, and is used to specialize
      25             : // expression parsing for the task at hand. It allows the parser to reuse the
      26             : // same code to parse destructuring declarations, assignment patterns,
      27             : // expressions, and (async) arrow function heads.
      28             : //
      29             : // One of the specific subclasses needs to be instantiated to tell the parser
      30             : // the meaning of the expression it will parse next. The parser then calls
      31             : // Record* on the expression_scope() to indicate errors. The expression_scope
      32             : // will either discard those errors, immediately report those errors, or
      33             : // classify the errors for later validation.
      34             : // TODO(verwaest): Record is a slightly odd name since it will directly throw
      35             : // for unambiguous scopes.
      36             : template <typename Types>
      37             : class ExpressionScope {
      38             :  public:
      39             :   typedef typename Types::Impl ParserT;
      40             :   typedef typename Types::Expression ExpressionT;
      41             : 
      42    71499954 :   VariableProxy* NewVariable(const AstRawString* name,
      43    71505143 :                              int pos = kNoSourcePosition) {
      44    84802991 :     VariableProxy* result = parser_->NewRawVariable(name, pos);
      45    71505143 :     if (CanBeExpression()) {
      46    48183523 :       AsExpressionParsingScope()->TrackVariable(result);
      47    36624657 :     } else if (type_ == kVarDeclaration && parser_->loop_nesting_depth() > 0) {
      48             :       // Due to hoisting, the value of a 'var'-declared variable may actually
      49             :       // change even if the code contains only the "initial" assignment, namely
      50             :       // when that assignment occurs inside a loop.  For example:
      51             :       //
      52             :       //   let i = 10;
      53             :       //   do { var x = i } while (i--):
      54             :       //
      55             :       // Note that non-lexical variables include temporaries, which may also get
      56             :       // assigned inside a loop due to the various rewritings that the parser
      57             :       // performs.
      58             :       //
      59             :       // Pessimistically mark all vars in loops as assigned. This
      60             :       // overapproximates the actual assigned vars due to unassigned var without
      61             :       // initializer, but that's unlikely anyway.
      62             :       //
      63             :       // This also handles marking of loop variables in for-in and for-of loops,
      64             :       // as determined by loop-nesting-depth.
      65             :       result->set_is_assigned();
      66             :     }
      67    71503006 :     return result;
      68             :   }
      69             : 
      70     4206288 :   void MarkIdentifierAsAssigned() {
      71     4970447 :     if (!CanBeExpression()) return;
      72     4150343 :     AsExpressionParsingScope()->MarkIdentifierAsAssigned();
      73             :   }
      74             : 
      75      183867 :   void ValidateAsPattern(ExpressionT expression, int begin, int end) {
      76      183867 :     if (!CanBeExpression()) return;
      77      182599 :     AsExpressionParsingScope()->ValidatePattern(expression, begin, end);
      78             :     AsExpressionParsingScope()->ClearExpressionError();
      79             :   }
      80             : 
      81             :   // Record async arrow parameters errors in all ambiguous async arrow scopes in
      82             :   // the chain up to the first unambiguous scope.
      83       22337 :   void RecordAsyncArrowParametersError(const Scanner::Location& loc,
      84       22906 :                                        MessageTemplate message) {
      85             :     // Only ambiguous scopes (ExpressionParsingScope, *ArrowHeadParsingScope)
      86             :     // need to propagate errors to a possible kAsyncArrowHeadParsingScope, so
      87             :     // immediately return if the current scope is not ambiguous.
      88       45243 :     if (!CanBeExpression()) return;
      89             :     AsExpressionParsingScope()->RecordAsyncArrowParametersError(loc, message);
      90             :   }
      91             : 
      92             :   // Record initializer errors in all scopes that can turn into parameter scopes
      93             :   // (ArrowHeadParsingScopes) up to the first known unambiguous parameter scope.
      94       96645 :   void RecordParameterInitializerError(const Scanner::Location& loc,
      95        7740 :                                        MessageTemplate message) {
      96      306969 :     ExpressionScope* scope = this;
      97      283304 :     while (!scope->IsCertainlyParameterDeclaration()) {
      98      178919 :       if (!has_possible_parameter_in_scope_chain_) return;
      99      120310 :       if (scope->CanBeParameterDeclaration()) {
     100             :         scope->AsArrowHeadParsingScope()->RecordDeclarationError(loc, message);
     101             :       }
     102             :       scope = scope->parent();
     103      120310 :       if (scope == nullptr) return;
     104             :     }
     105             :     Report(loc, message);
     106             :   }
     107             : 
     108    10690276 :   void RecordPatternError(const Scanner::Location& loc,
     109       42468 :                           MessageTemplate message) {
     110             :     // TODO(verwaest): Non-assigning expression?
     111    10690276 :     if (IsCertainlyPattern()) {
     112             :       Report(loc, message);
     113             :     } else {
     114             :       AsExpressionParsingScope()->RecordPatternError(loc, message);
     115             :     }
     116    10690276 :   }
     117             : 
     118       59315 :   void RecordStrictModeParameterError(const Scanner::Location& loc,
     119       59315 :                                       MessageTemplate message) {
     120             :     DCHECK_IMPLIES(!has_error(), loc.IsValid());
     121      118630 :     if (!CanBeParameterDeclaration()) return;
     122       20469 :     if (IsCertainlyParameterDeclaration()) {
     123       17006 :       if (is_strict(parser_->language_mode())) {
     124             :         Report(loc, message);
     125             :       } else {
     126        8503 :         parser_->parameters_->set_strict_parameter_error(loc, message);
     127             :       }
     128             :     } else {
     129       11966 :       parser_->next_arrow_function_info_.strict_parameter_error_location = loc;
     130       11966 :       parser_->next_arrow_function_info_.strict_parameter_error_message =
     131             :           message;
     132             :     }
     133             :   }
     134             : 
     135    31522892 :   void RecordDeclarationError(const Scanner::Location& loc,
     136    31526745 :                               MessageTemplate message) {
     137    63045784 :     if (!CanBeDeclaration()) return;
     138     2813903 :     if (IsCertainlyDeclaration()) {
     139             :       Report(loc, message);
     140             :     } else {
     141             :       AsArrowHeadParsingScope()->RecordDeclarationError(loc, message);
     142             :     }
     143             :   }
     144             : 
     145             :   void RecordExpressionError(const Scanner::Location& loc,
     146       33387 :                              MessageTemplate message) {
     147       33387 :     if (!CanBeExpression()) return;
     148             :     // TODO(verwaest): Non-assigning expression?
     149             :     // if (IsCertainlyExpression()) Report(loc, message);
     150             :     AsExpressionParsingScope()->RecordExpressionError(loc, message);
     151             :   }
     152             : 
     153             :   void RecordLexicalDeclarationError(const Scanner::Location& loc,
     154        2812 :                                      MessageTemplate message) {
     155        1612 :     if (IsLexicalDeclaration()) Report(loc, message);
     156             :   }
     157             : 
     158    11349323 :   void RecordNonSimpleParameter() {
     159    11349323 :     if (!IsArrowHeadParsingScope()) return;
     160             :     AsArrowHeadParsingScope()->RecordNonSimpleParameter();
     161             :   }
     162             : 
     163             :  protected:
     164             :   enum ScopeType : uint8_t {
     165             :     // Expression or assignment target.
     166             :     kExpression,
     167             : 
     168             :     // Declaration or expression or assignment target.
     169             :     kMaybeArrowParameterDeclaration,
     170             :     kMaybeAsyncArrowParameterDeclaration,
     171             : 
     172             :     // Declarations.
     173             :     kParameterDeclaration,
     174             :     kVarDeclaration,
     175             :     kLexicalDeclaration,
     176             :   };
     177             : 
     178             :   ParserT* parser() const { return parser_; }
     179             :   ExpressionScope* parent() const { return parent_; }
     180             : 
     181             :   void Report(const Scanner::Location& loc, MessageTemplate message) const {
     182       98741 :     parser_->ReportMessageAt(loc, message);
     183             :   }
     184             : 
     185             :   ExpressionScope(ParserT* parser, ScopeType type)
     186             :       : parser_(parser),
     187             :         parent_(parser->expression_scope_),
     188             :         type_(type),
     189             :         has_possible_parameter_in_scope_chain_(
     190             :             CanBeParameterDeclaration() ||
     191   149010951 :             (parent_ && parent_->has_possible_parameter_in_scope_chain_)) {
     192    76661330 :     parser->expression_scope_ = this;
     193             :   }
     194             : 
     195             :   ~ExpressionScope() {
     196             :     DCHECK(parser_->expression_scope_ == this ||
     197             :            parser_->expression_scope_ == parent_);
     198    76664957 :     parser_->expression_scope_ = parent_;
     199             :   }
     200             : 
     201             :   ExpressionParsingScope<Types>* AsExpressionParsingScope() {
     202             :     DCHECK(CanBeExpression());
     203             :     return static_cast<ExpressionParsingScope<Types>*>(this);
     204             :   }
     205             : 
     206             : #ifdef DEBUG
     207             :   bool has_error() const { return parser_->has_error(); }
     208             : #endif
     209             : 
     210             :   bool CanBeExpression() const {
     211             :     return IsInRange(type_, kExpression, kMaybeAsyncArrowParameterDeclaration);
     212             :   }
     213             :   bool CanBeDeclaration() const {
     214             :     return IsInRange(type_, kMaybeArrowParameterDeclaration,
     215             :                      kLexicalDeclaration);
     216             :   }
     217             :   bool IsCertainlyDeclaration() const {
     218             :     return IsInRange(type_, kParameterDeclaration, kLexicalDeclaration);
     219             :   }
     220             :   bool IsVariableDeclaration() const {
     221             :     return IsInRange(type_, kVarDeclaration, kLexicalDeclaration);
     222             :   }
     223             :   bool IsAsyncArrowHeadParsingScope() const {
     224             :     return type_ == kMaybeAsyncArrowParameterDeclaration;
     225             :   }
     226             : 
     227             :  private:
     228             :   friend class AccumulationScope<Types>;
     229             :   friend class ExpressionParsingScope<Types>;
     230             : 
     231             :   ArrowHeadParsingScope<Types>* AsArrowHeadParsingScope() {
     232             :     DCHECK(IsArrowHeadParsingScope());
     233             :     return static_cast<ArrowHeadParsingScope<Types>*>(this);
     234             :   }
     235             : 
     236             :   bool IsArrowHeadParsingScope() const {
     237             :     return IsInRange(type_, kMaybeArrowParameterDeclaration,
     238             :                      kMaybeAsyncArrowParameterDeclaration);
     239             :   }
     240    10690276 :   bool IsCertainlyPattern() const { return IsCertainlyDeclaration(); }
     241             :   bool CanBeParameterDeclaration() const {
     242             :     return IsInRange(type_, kMaybeArrowParameterDeclaration,
     243             :                      kParameterDeclaration);
     244             :   }
     245             :   bool IsCertainlyParameterDeclaration() const {
     246             :     return type_ == kParameterDeclaration;
     247             :   }
     248             :   bool IsLexicalDeclaration() const { return type_ == kLexicalDeclaration; }
     249             : 
     250             :   ParserT* parser_;
     251             :   ExpressionScope<Types>* parent_;
     252             :   ScopeType type_;
     253             :   bool has_possible_parameter_in_scope_chain_;
     254             : 
     255             :   DISALLOW_COPY_AND_ASSIGN(ExpressionScope);
     256             : };
     257             : 
     258             : // Used to unambiguously parse var, let, const declarations.
     259             : template <typename Types>
     260       18190 : class VariableDeclarationParsingScope : public ExpressionScope<Types> {
     261             :  public:
     262             :   typedef typename Types::Impl ParserT;
     263             :   typedef class ExpressionScope<Types> ExpressionScopeT;
     264             :   typedef typename ExpressionScopeT::ScopeType ScopeType;
     265             : 
     266        9095 :   VariableDeclarationParsingScope(ParserT* parser, VariableMode mode)
     267             :       : ExpressionScopeT(parser, IsLexicalVariableMode(mode)
     268             :                                      ? ExpressionScopeT::kLexicalDeclaration
     269             :                                      : ExpressionScopeT::kVarDeclaration),
     270    28703916 :         mode_(mode) {}
     271             : 
     272             :  private:
     273             :   VariableMode mode_;
     274             : 
     275             :   DISALLOW_COPY_AND_ASSIGN(VariableDeclarationParsingScope);
     276             : };
     277             : 
     278             : template <typename Types>
     279             : class ParameterDeclarationParsingScope : public ExpressionScope<Types> {
     280             :  public:
     281             :   typedef typename Types::Impl ParserT;
     282             :   typedef class ExpressionScope<Types> ExpressionScopeT;
     283             :   typedef typename ExpressionScopeT::ScopeType ScopeType;
     284             : 
     285             :   explicit ParameterDeclarationParsingScope(ParserT* parser)
     286             :       : ExpressionScopeT(parser, ExpressionScopeT::kParameterDeclaration) {}
     287             : 
     288             :  private:
     289             :   DISALLOW_COPY_AND_ASSIGN(ParameterDeclarationParsingScope);
     290             : };
     291             : 
     292             : // Parsing expressions is always ambiguous between at least left-hand-side and
     293             : // right-hand-side of assignments. This class is used to keep track of errors
     294             : // relevant for either side until it is clear what was being parsed.
     295             : // The class also keeps track of all variable proxies that are created while the
     296             : // scope was active. If the scope is an expression, the variable proxies will be
     297             : // added to the unresolved list. Otherwise they are declarations and aren't
     298             : // added. The list is also used to mark the variables as assigned in case we are
     299             : // parsing an assignment expression.
     300             : template <typename Types>
     301             : class ExpressionParsingScope : public ExpressionScope<Types> {
     302             :  public:
     303             :   typedef typename Types::Impl ParserT;
     304             :   typedef typename Types::Expression ExpressionT;
     305             :   typedef class ExpressionScope<Types> ExpressionScopeT;
     306             :   typedef typename ExpressionScopeT::ScopeType ScopeType;
     307             : 
     308    57997663 :   ExpressionParsingScope(ParserT* parser,
     309             :                          ScopeType type = ExpressionScopeT::kExpression)
     310             :       : ExpressionScopeT(parser, type),
     311             :         variable_list_(parser->variable_buffer()),
     312             :         has_async_arrow_in_scope_chain_(
     313             :             type == ExpressionScopeT::kMaybeAsyncArrowParameterDeclaration ||
     314    22124156 :             (this->parent() && this->parent()->CanBeExpression() &&
     315             :              this->parent()
     316             :                  ->AsExpressionParsingScope()
     317   312112603 :                  ->has_async_arrow_in_scope_chain_)) {
     318             :     DCHECK(this->CanBeExpression());
     319             :     clear(kExpressionIndex);
     320             :     clear(kPatternIndex);
     321    57997663 :   }
     322             : 
     323             :   void RecordAsyncArrowParametersError(const Scanner::Location& loc,
     324             :                                        MessageTemplate message) {
     325       18858 :     for (ExpressionScopeT* scope = this; scope != nullptr;
     326             :          scope = scope->parent()) {
     327       16049 :       if (!has_async_arrow_in_scope_chain_) break;
     328        8098 :       if (scope->type_ ==
     329             :           ExpressionScopeT::kMaybeAsyncArrowParameterDeclaration) {
     330             :         scope->AsArrowHeadParsingScope()->RecordDeclarationError(loc, message);
     331             :       }
     332             :     }
     333             :   }
     334             : 
     335   108323501 :   ~ExpressionParsingScope() { DCHECK(this->has_error() || verified_); }
     336             : 
     337      104463 :   ExpressionT ValidateAndRewriteReference(ExpressionT expression, int beg_pos,
     338             :                                           int end_pos) {
     339      113476 :     if (V8_LIKELY(this->parser()->IsAssignableIdentifier(expression))) {
     340       93128 :       MarkIdentifierAsAssigned();
     341             :       this->mark_verified();
     342       93128 :       return expression;
     343       11335 :     } else if (V8_LIKELY(expression->IsProperty())) {
     344             :       ValidateExpression();
     345        2322 :       return expression;
     346             :     }
     347             :     this->mark_verified();
     348             :     return this->parser()->RewriteInvalidReferenceExpression(
     349             :         expression, beg_pos, end_pos, MessageTemplate::kInvalidLhsInFor,
     350        9013 :         kSyntaxError);
     351             :   }
     352             : 
     353             :   void RecordExpressionError(const Scanner::Location& loc,
     354             :                              MessageTemplate message) {
     355             :     Record(kExpressionIndex, loc, message);
     356             :   }
     357             : 
     358             :   void RecordPatternError(const Scanner::Location& loc,
     359             :                           MessageTemplate message) {
     360             :     Record(kPatternIndex, loc, message);
     361             :   }
     362             : 
     363    57721986 :   void ValidateExpression() { Validate(kExpressionIndex); }
     364             : 
     365      350119 :   void ValidatePattern(ExpressionT expression, int begin, int end) {
     366      234868 :     Validate(kPatternIndex);
     367      354485 :     if (expression->is_parenthesized()) {
     368             :       ExpressionScopeT::Report(Scanner::Location(begin, end),
     369        3414 :                                MessageTemplate::kInvalidDestructuringTarget);
     370             :     }
     371      770096 :     for (int i = 0; i < variable_list_.length(); i++) {
     372      770096 :       variable_list_.at(i)->set_is_assigned();
     373             :     }
     374      234868 :   }
     375             : 
     376             :   void ClearExpressionError() {
     377             :     DCHECK(verified_);
     378             : #ifdef DEBUG
     379             :     verified_ = false;
     380             : #endif
     381             :     clear(kExpressionIndex);
     382             :   }
     383             : 
     384    48183263 :   void TrackVariable(VariableProxy* variable) {
     385    96366526 :     if (!this->CanBeDeclaration()) {
     386    44648971 :       this->parser()->scope()->AddUnresolved(variable);
     387             :     }
     388    48182835 :     variable_list_.Add(variable);
     389    48181570 :   }
     390             : 
     391     4243369 :   void MarkIdentifierAsAssigned() {
     392             :     // It's possible we're parsing a syntax error. In that case it's not
     393             :     // guaranteed that there's a variable in the list.
     394    16971131 :     if (variable_list_.length() == 0) return;
     395     4241024 :     variable_list_.at(variable_list_.length() - 1)->set_is_assigned();
     396             :   }
     397             : 
     398             :  protected:
     399             :   bool is_verified() const {
     400             : #ifdef DEBUG
     401             :     return verified_;
     402             : #else
     403             :     return false;
     404             : #endif
     405             :   }
     406             : 
     407      420056 :   void ValidatePattern() { Validate(kPatternIndex); }
     408             : 
     409             :   ScopedPtrList<VariableProxy>* variable_list() { return &variable_list_; }
     410             : 
     411             :  private:
     412             :   friend class AccumulationScope<Types>;
     413             : 
     414             :   enum ErrorNumber : uint8_t {
     415             :     kExpressionIndex = 0,
     416             :     kPatternIndex = 1,
     417             :     kNumberOfErrors = 2,
     418             :   };
     419             :   void clear(int index) {
     420   318145179 :     messages_[index] = MessageTemplate::kNone;
     421   318145179 :     locations_[index] = Scanner::Location::invalid();
     422             :   }
     423   163710260 :   bool is_valid(int index) const { return !locations_[index].IsValid(); }
     424             :   void Record(int index, const Scanner::Location& loc,
     425             :               MessageTemplate message) {
     426             :     DCHECK_IMPLIES(!this->has_error(), loc.IsValid());
     427    10666011 :     if (!is_valid(index)) return;
     428     7907685 :     messages_[index] = message;
     429     7907685 :     locations_[index] = loc;
     430             :   }
     431    58374544 :   void Validate(int index) {
     432             :     DCHECK(!this->is_verified());
     433    58374544 :     if (!is_valid(index)) Report(index);
     434             :     this->mark_verified();
     435    58374544 :   }
     436             :   void Report(int index) const {
     437       26341 :     ExpressionScopeT::Report(locations_[index], messages_[index]);
     438             :   }
     439             : 
     440             :   // Debug verification to make sure every scope is validated exactly once.
     441             :   void mark_verified() {
     442             : #ifdef DEBUG
     443             :     verified_ = true;
     444             : #endif
     445             :   }
     446             :   void clear_verified() {
     447             : #ifdef DEBUG
     448             :     verified_ = false;
     449             : #endif
     450             :   }
     451             : #ifdef DEBUG
     452             :   bool verified_ = false;
     453             : #endif
     454             : 
     455             :   ScopedPtrList<VariableProxy> variable_list_;
     456             :   MessageTemplate messages_[kNumberOfErrors];
     457             :   Scanner::Location locations_[kNumberOfErrors];
     458             :   bool has_async_arrow_in_scope_chain_;
     459             : 
     460             :   DISALLOW_COPY_AND_ASSIGN(ExpressionParsingScope);
     461             : };
     462             : 
     463             : // This class is used to parse multiple ambiguous expressions and declarations
     464             : // in the same scope. E.g., in async(X,Y,Z) or [X,Y,Z], X and Y and Z will all
     465             : // be parsed in the respective outer ArrowHeadParsingScope and
     466             : // ExpressionParsingScope. It provides a clean error state in the underlying
     467             : // scope to parse the individual expressions, while keeping track of the
     468             : // expression and pattern errors since the start. The AccumulationScope is only
     469             : // used to keep track of the errors so far, and the underlying ExpressionScope
     470             : // keeps being used as the expression_scope(). If the expression_scope() isn't
     471             : // ambiguous, this class does not do anything.
     472             : template <typename Types>
     473             : class AccumulationScope {
     474             :  public:
     475             :   typedef typename Types::Impl ParserT;
     476             : 
     477             :   static const int kNumberOfErrors =
     478             :       ExpressionParsingScope<Types>::kNumberOfErrors;
     479   158732700 :   explicit AccumulationScope(ExpressionScope<Types>* scope) : scope_(nullptr) {
     480   105824860 :     if (!scope->CanBeExpression()) return;
     481    52670529 :     scope_ = scope->AsExpressionParsingScope();
     482   157936492 :     for (int i = 0; i < kNumberOfErrors; i++) {
     483             :       // If the underlying scope is already invalid at the start, stop
     484             :       // accumulating. That means an error was found outside of an
     485             :       // accumulating path.
     486   105335716 :       if (!scope_->is_valid(i)) {
     487       69753 :         scope_ = nullptr;
     488       69753 :         break;
     489             :       }
     490             :       copy(i);
     491             :     }
     492             :   }
     493             : 
     494             :   // Merge errors from the underlying ExpressionParsingScope into this scope.
     495             :   // Only keeps the first error across all accumulate calls, and removes the
     496             :   // error from the underlying scope.
     497   105112527 :   void Accumulate() {
     498   210225054 :     if (scope_ == nullptr) return;
     499             :     DCHECK(!scope_->is_verified());
     500   201671954 :     for (int i = 0; i < kNumberOfErrors; i++) {
     501   403343908 :       if (!locations_[i].IsValid()) copy(i);
     502   201671954 :       scope_->clear(i);
     503             :     }
     504             :   }
     505             : 
     506             :   // This is called instead of Accumulate in case the parsed member is already
     507             :   // known to be an expression. In that case we don't need to accumulate the
     508             :   // expression but rather validate it immediately. We also ignore the pattern
     509             :   // error since the parsed member is known to not be a pattern. This is
     510             :   // necessary for "{x:1}.y" parsed as part of an assignment pattern. {x:1} will
     511             :   // record a pattern error, but "{x:1}.y" is actually a valid as part of an
     512             :   // assignment pattern since it's a property access.
     513      295890 :   void ValidateExpression() {
     514      591777 :     if (scope_ == nullptr) return;
     515             :     DCHECK(!scope_->is_verified());
     516             :     scope_->ValidateExpression();
     517             :     DCHECK(scope_->is_verified());
     518      295300 :     scope_->clear(ExpressionParsingScope<Types>::kPatternIndex);
     519             : #ifdef DEBUG
     520             :     scope_->clear_verified();
     521             : #endif
     522             :   }
     523             : 
     524    52911729 :   ~AccumulationScope() {
     525    52911729 :     if (scope_ == nullptr) return;
     526    52597704 :     Accumulate();
     527   157787247 :     for (int i = 0; i < kNumberOfErrors; i++) copy_back(i);
     528    52912272 :   }
     529             : 
     530             :  private:
     531             :   void copy(int entry) {
     532   299207123 :     messages_[entry] = scope_->messages_[entry];
     533   299207123 :     locations_[entry] = scope_->locations_[entry];
     534             :   }
     535             : 
     536             :   void copy_back(int entry) {
     537   210378000 :     if (!locations_[entry].IsValid()) return;
     538     1988880 :     scope_->messages_[entry] = messages_[entry];
     539     1988880 :     scope_->locations_[entry] = locations_[entry];
     540             :   }
     541             : 
     542             :   ExpressionParsingScope<Types>* scope_;
     543             :   MessageTemplate messages_[2];
     544             :   Scanner::Location locations_[2];
     545             : 
     546             :   DISALLOW_COPY_AND_ASSIGN(AccumulationScope);
     547             : };
     548             : 
     549             : // The head of an arrow function is ambiguous between expression, assignment
     550             : // pattern and declaration. This keeps track of the additional declaration
     551             : // error and allows the scope to be validated as a declaration rather than an
     552             : // expression or a pattern.
     553             : template <typename Types>
     554             : class ArrowHeadParsingScope : public ExpressionParsingScope<Types> {
     555             :  public:
     556             :   typedef typename Types::Impl ParserT;
     557             :   typedef typename ExpressionScope<Types>::ScopeType ScopeType;
     558             : 
     559             :   ArrowHeadParsingScope(ParserT* parser, FunctionKind kind)
     560             :       : ExpressionParsingScope<Types>(
     561             :             parser,
     562             :             kind == FunctionKind::kArrowFunction
     563             :                 ? ExpressionScope<Types>::kMaybeArrowParameterDeclaration
     564             :                 : ExpressionScope<
     565     3362005 :                       Types>::kMaybeAsyncArrowParameterDeclaration) {
     566             :     DCHECK(kind == FunctionKind::kAsyncArrowFunction ||
     567             :            kind == FunctionKind::kArrowFunction);
     568             :     DCHECK(this->CanBeDeclaration());
     569             :     DCHECK(!this->IsCertainlyDeclaration());
     570             :   }
     571             : 
     572     2941905 :   void ValidateExpression() {
     573             :     // Turns out this is not an arrow head. Clear any possible tracked strict
     574             :     // parameter errors, and reinterpret tracked variables as unresolved
     575             :     // references.
     576     5999831 :     this->parser()->next_arrow_function_info_.ClearStrictParameterError();
     577     2941905 :     ExpressionParsingScope<Types>::ValidateExpression();
     578    11999728 :     for (int i = 0; i < this->variable_list()->length(); i++) {
     579     6115852 :       this->parser()->scope()->AddUnresolved(this->variable_list()->at(i));
     580             :     }
     581     2941938 :   }
     582             : 
     583      420056 :   DeclarationScope* ValidateAndCreateScope() {
     584             :     DCHECK(!this->is_verified());
     585      420056 :     if (declaration_error_location.IsValid()) {
     586             :       ExpressionScope<Types>::Report(declaration_error_location,
     587      435493 :                                      declaration_error_message);
     588             :     }
     589      420056 :     this->ValidatePattern();
     590             : 
     591      840122 :     DeclarationScope* result = this->parser()->NewFunctionScope(kind());
     592      420082 :     if (!has_simple_parameter_list_) result->SetHasNonSimpleParameters();
     593             :     // TODO(verwaest): Add declarations.
     594      420082 :     return result;
     595             :   }
     596             : 
     597             :   void RecordDeclarationError(const Scanner::Location& loc,
     598             :                               MessageTemplate message) {
     599             :     DCHECK_IMPLIES(!this->has_error(), loc.IsValid());
     600     2856598 :     declaration_error_location = loc;
     601     2856598 :     declaration_error_message = message;
     602             :   }
     603             : 
     604      196970 :   void RecordNonSimpleParameter() { has_simple_parameter_list_ = false; }
     605             : 
     606             :  private:
     607             :   FunctionKind kind() const {
     608             :     return this->IsAsyncArrowHeadParsingScope()
     609      420061 :                ? FunctionKind::kAsyncArrowFunction
     610      420061 :                : FunctionKind::kArrowFunction;
     611             :   }
     612             : 
     613             :   Scanner::Location declaration_error_location = Scanner::Location::invalid();
     614             :   MessageTemplate declaration_error_message = MessageTemplate::kNone;
     615             :   bool has_simple_parameter_list_ = true;
     616             : 
     617             :   DISALLOW_COPY_AND_ASSIGN(ArrowHeadParsingScope);
     618             : };
     619             : 
     620             : }  // namespace internal
     621             : }  // namespace v8
     622             : 
     623             : #endif  // V8_PARSING_EXPRESSION_SCOPE_H_

Generated by: LCOV version 1.10