LCOV - code coverage report
Current view: top level - src/parsing - expression-scope.h (source / functions) Hit Total Coverage
Test: app.info Lines: 152 153 99.3 %
Date: 2019-04-18 Functions: 41 41 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/function-kind.h"
      10             : #include "src/message-template.h"
      11             : #include "src/parsing/scanner.h"
      12             : #include "src/zone/zone.h"  // For ScopedPtrList.
      13             : 
      14             : namespace v8 {
      15             : namespace internal {
      16             : 
      17             : template <typename Types>
      18             : class ExpressionParsingScope;
      19             : template <typename Types>
      20             : class AccumulationScope;
      21             : template <typename Types>
      22             : class ArrowHeadParsingScope;
      23             : template <typename Types>
      24             : class ParameterDeclarationParsingScope;
      25             : template <typename Types>
      26             : class VariableDeclarationParsingScope;
      27             : class 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.
      41             : template <typename Types>
      42             : class ExpressionScope {
      43             :  public:
      44             :   using ParserT = typename Types::Impl;
      45             :   using ExpressionT = typename Types::Expression;
      46             : 
      47    71779987 :   VariableProxy* NewVariable(const AstRawString* name,
      48             :                              int pos = kNoSourcePosition) {
      49    71779987 :     VariableProxy* result = parser_->NewRawVariable(name, pos);
      50    71783960 :     if (CanBeExpression()) {
      51    50435311 :       AsExpressionParsingScope()->TrackVariable(result);
      52             :     } else {
      53    21348649 :       Variable* var = Declare(name, pos);
      54    32268621 :       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      938739 :         parser()->scope()->AddUnresolved(result);
      59             :       } else {
      60             :         DCHECK_NOT_NULL(var);
      61    20409955 :         result->BindTo(var);
      62             :       }
      63             :     }
      64    71783034 :     return result;
      65             :   }
      66             : 
      67    23589873 :   Variable* Declare(const AstRawString* name, int pos = kNoSourcePosition) {
      68    23589873 :     if (type_ == kParameterDeclaration) {
      69     7918261 :       return AsParameterDeclarationParsingScope()->Declare(name, pos);
      70             :     }
      71    15671612 :     return AsVariableDeclarationParsingScope()->Declare(name, pos);
      72             :   }
      73             : 
      74             :   void MarkIdentifierAsAssigned() {
      75     4298288 :     if (!CanBeExpression()) return;
      76     4242850 :     AsExpressionParsingScope()->MarkIdentifierAsAssigned();
      77             :   }
      78             : 
      79             :   void ValidateAsPattern(ExpressionT expression, int begin, int end) {
      80      189862 :     if (!CanBeExpression()) return;
      81      188594 :     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       22968 :     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       97560 :   void RecordParameterInitializerError(const Scanner::Location& loc,
      99             :                                        MessageTemplate message) {
     100             :     ExpressionScope* scope = this;
     101      140580 :     while (!scope->IsCertainlyParameterDeclaration()) {
     102      132828 :       if (!has_possible_parameter_in_scope_chain_) return;
     103       56677 :       if (scope->CanBeParameterDeclaration()) {
     104             :         scope->AsArrowHeadParsingScope()->RecordDeclarationError(loc, message);
     105             :       }
     106             :       scope = scope->parent();
     107       56677 :       if (scope == nullptr) return;
     108             :     }
     109             :     Report(loc, message);
     110             :   }
     111             : 
     112     2462019 :   void RecordThisUse() {
     113             :     ExpressionScope* scope = this;
     114     5793782 :     do {
     115     5793782 :       if (scope->IsArrowHeadParsingScope()) {
     116             :         scope->AsArrowHeadParsingScope()->RecordThisUse();
     117             :       }
     118             :       scope = scope->parent();
     119             :     } while (scope != nullptr);
     120     2462019 :   }
     121             : 
     122     9825727 :   void RecordPatternError(const Scanner::Location& loc,
     123             :                           MessageTemplate message) {
     124             :     // TODO(verwaest): Non-assigning expression?
     125     9825727 :     if (IsCertainlyPattern()) {
     126             :       Report(loc, message);
     127             :     } else {
     128             :       AsExpressionParsingScope()->RecordPatternError(loc, message);
     129             :     }
     130     9825727 :   }
     131             : 
     132       59570 :   void RecordStrictModeParameterError(const Scanner::Location& loc,
     133             :                                       MessageTemplate message) {
     134             :     DCHECK_IMPLIES(!has_error(), loc.IsValid());
     135       59570 :     if (!CanBeParameterDeclaration()) return;
     136       20565 :     if (IsCertainlyParameterDeclaration()) {
     137       17112 :       if (is_strict(parser_->language_mode())) {
     138             :         Report(loc, message);
     139             :       } else {
     140        8556 :         parser_->parameters_->set_strict_parameter_error(loc, message);
     141             :       }
     142             :     } else {
     143       12009 :       parser_->next_arrow_function_info_.strict_parameter_error_location = loc;
     144       12009 :       parser_->next_arrow_function_info_.strict_parameter_error_message =
     145             :           message;
     146             :     }
     147             :   }
     148             : 
     149    38324691 :   void RecordDeclarationError(const Scanner::Location& loc,
     150             :                               MessageTemplate message) {
     151    38324691 :     if (!CanBeDeclaration()) return;
     152     2850400 :     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       33123 :     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    11460588 :     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       97069 :     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   150160808 :             (parent_ && parent_->has_possible_parameter_in_scope_chain_)) {
     205    77307320 :     parser->expression_scope_ = this;
     206             :   }
     207             : 
     208             :   ~ExpressionScope() {
     209             :     DCHECK(parser_->expression_scope_ == this ||
     210             :            parser_->expression_scope_ == parent_);
     211    77311407 :     parser_->expression_scope_ = parent_;
     212    77311407 :   }
     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.
     281             : template <typename Types>
     282    13809260 : class 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    27609375 :         names_(names) {}
     295             : 
     296    15671597 :   Variable* Declare(const AstRawString* name, int pos) {
     297             :     VariableKind kind = NORMAL_VARIABLE;
     298             :     bool was_added;
     299             :     Variable* var = this->parser()->DeclareVariable(
     300    15671597 :         name, kind, mode_, Variable::DefaultInitializationFlag(mode_),
     301    15671597 :         this->parser()->scope(), &was_added, pos);
     302    29482695 :     if (was_added &&
     303             :         this->parser()->scope()->num_var() > kMaxNumFunctionLocals) {
     304           0 :       this->parser()->ReportMessage(MessageTemplate::kTooManyVariables);
     305             :     }
     306    15671666 :     if (names_) names_->Add(name, this->parser()->zone());
     307    15671662 :     if (this->IsLexicalDeclaration()) {
     308     2515554 :       if (this->parser()->IsLet(name)) {
     309        6836 :         this->parser()->ReportMessageAt(
     310             :             Scanner::Location(pos, pos + name->length()),
     311             :             MessageTemplate::kLetInLexicalBinding);
     312             :       }
     313             :     } else {
     314    13156108 :       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    15671662 :     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             : 
     351             : template <typename Types>
     352     4444852 : class 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     4444857 :       : ExpressionScopeT(parser, ExpressionScopeT::kParameterDeclaration) {}
     360             : 
     361     7918257 :   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     3919121 :         this->parser()->scope(), &was_added, pos);
     368     7918279 :     if (!has_duplicate() && !was_added) {
     369        7202 :       duplicate_loc_ = Scanner::Location(pos, pos + name->length());
     370             :     }
     371     7918279 :     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.
     391             : template <typename Types>
     392             : class 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    59053288 :   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    15831592 :             (this->parent() && this->parent()->CanBeExpression() &&
     406             :              this->parent()
     407             :                  ->AsExpressionParsingScope()
     408   252045988 :                  ->has_async_arrow_in_scope_chain_)) {
     409             :     DCHECK(this->CanBeExpression());
     410             :     clear(kExpressionIndex);
     411             :     clear(kPatternIndex);
     412    59053288 :   }
     413             : 
     414             :   void RecordAsyncArrowParametersError(const Scanner::Location& loc,
     415             :                                        MessageTemplate message) {
     416       10806 :     for (ExpressionScopeT* scope = this; scope != nullptr;
     417             :          scope = scope->parent()) {
     418       18205 :       if (!has_async_arrow_in_scope_chain_) break;
     419       10226 :       if (scope->type_ ==
     420             :           ExpressionScopeT::kMaybeAsyncArrowParameterDeclaration) {
     421             :         scope->AsArrowHeadParsingScope()->RecordDeclarationError(loc, message);
     422             :       }
     423             :     }
     424             :   }
     425             : 
     426    60082614 :   ~ExpressionParsingScope() { DCHECK(this->has_error() || verified_); }
     427             : 
     428      104455 :   ExpressionT ValidateAndRewriteReference(ExpressionT expression, int beg_pos,
     429             :                                           int end_pos) {
     430      104455 :     if (V8_LIKELY(this->parser()->IsAssignableIdentifier(expression))) {
     431       93096 :       MarkIdentifierAsAssigned();
     432             :       this->mark_verified();
     433       93096 :       return expression;
     434       11359 :     } else if (V8_LIKELY(expression->IsProperty())) {
     435        2322 :       ValidateExpression();
     436        2322 :       return expression;
     437             :     }
     438             :     this->mark_verified();
     439             :     return this->parser()->RewriteInvalidReferenceExpression(
     440             :         expression, beg_pos, end_pos, MessageTemplate::kInvalidLhsInFor,
     441        9037 :         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   117399176 :   void ValidateExpression() { Validate(kExpressionIndex); }
     455             : 
     456      240880 :   void ValidatePattern(ExpressionT expression, int begin, int end) {
     457             :     Validate(kPatternIndex);
     458      240880 :     if (expression->is_parenthesized()) {
     459        1716 :       ExpressionScopeT::Report(Scanner::Location(begin, end),
     460             :                                MessageTemplate::kInvalidDestructuringTarget);
     461             :     }
     462      788126 :     for (VariableProxy* proxy : variable_list_) {
     463             :       proxy->set_is_assigned();
     464             :     }
     465      240880 :   }
     466             : 
     467             :   void ClearExpressionError() {
     468             :     DCHECK(verified_);
     469             : #ifdef DEBUG
     470             :     verified_ = false;
     471             : #endif
     472             :     clear(kExpressionIndex);
     473             :   }
     474             : 
     475    50435181 :   void TrackVariable(VariableProxy* variable) {
     476    50435181 :     if (!this->CanBeDeclaration()) {
     477    46748748 :       this->parser()->scope()->AddUnresolved(variable);
     478             :     }
     479             :     variable_list_.Add(variable);
     480    50434361 :   }
     481             : 
     482     4335915 :   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     4335915 :     if (variable_list_.length() == 0) return;
     486     4333538 :     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     1034860 :   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   336733333 :     messages_[index] = MessageTemplate::kNone;
     512   336733333 :     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     9801586 :     if (!is_valid(index)) return;
     519     7938781 :     messages_[index] = message;
     520     7938781 :     locations_[index] = loc;
     521             :   }
     522             :   void Validate(int index) {
     523             :     DCHECK(!this->is_verified());
     524    59457898 :     if (!is_valid(index)) Report(index);
     525             :     this->mark_verified();
     526             :   }
     527             :   void Report(int index) const {
     528       24649 :     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.
     563             : template <typename Types>
     564             : class AccumulationScope {
     565             :  public:
     566             :   using ParserT = typename Types::Impl;
     567             : 
     568             :   static const int kNumberOfErrors =
     569             :       ExpressionParsingScope<Types>::kNumberOfErrors;
     570   162713162 :   explicit AccumulationScope(ExpressionScope<Types>* scope) : scope_(nullptr) {
     571    54239332 :     if (!scope->CanBeExpression()) return;
     572    53995678 :     scope_ = scope->AsExpressionParsingScope();
     573   269828146 :     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   107989980 :       if (!scope_->is_valid(i)) {
     578       73746 :         scope_ = nullptr;
     579       73746 :         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   112443577 :     if (scope_ == nullptr) return;
     590             :     DCHECK(!scope_->is_verified());
     591   545300891 :     for (int i = 0; i < kNumberOfErrors; i++) {
     592   218119936 :       if (!locations_[i].IsValid()) copy(i);
     593   218119936 :       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      318820 :     if (scope_ == nullptr) return;
     606             :     DCHECK(!scope_->is_verified());
     607      318227 :     scope_->ValidateExpression();
     608             :     DCHECK(scope_->is_verified());
     609      318227 :     scope_->clear(ExpressionParsingScope<Types>::kPatternIndex);
     610             : #ifdef DEBUG
     611             :     scope_->clear_verified();
     612             : #endif
     613             :   }
     614             : 
     615    54239754 :   ~AccumulationScope() {
     616    54239754 :     if (scope_ == nullptr) return;
     617             :     Accumulate();
     618   269610052 :     for (int i = 0; i < kNumberOfErrors; i++) copy_back(i);
     619    53922178 :   }
     620             : 
     621             :  private:
     622             :   void copy(int entry) {
     623   318278875 :     messages_[entry] = scope_->messages_[entry];
     624   318278875 :     locations_[entry] = scope_->locations_[entry];
     625             :   }
     626             : 
     627             :   void copy_back(int entry) {
     628   107843937 :     if (!locations_[entry].IsValid()) return;
     629     2059959 :     scope_->messages_[entry] = messages_[entry];
     630     2059959 :     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.
     644             : template <typename Types>
     645     3501882 : class 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     3501866 :                       Types>::kMaybeAsyncArrowParameterDeclaration) {
     657             :     DCHECK(kind == FunctionKind::kAsyncArrowFunction ||
     658             :            kind == FunctionKind::kArrowFunction);
     659             :     DCHECK(this->CanBeDeclaration());
     660             :     DCHECK(!this->IsCertainlyDeclaration());
     661             :   }
     662             : 
     663     2984456 :   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     2984456 :     ExpressionParsingScope<Types>::ValidateExpression();
     669     9205617 :     for (VariableProxy* proxy : *this->variable_list()) {
     670     3110580 :       this->parser()->scope()->AddUnresolved(proxy);
     671             :     }
     672     2984458 :   }
     673             : 
     674      517430 :   DeclarationScope* ValidateAndCreateScope() {
     675             :     DCHECK(!this->is_verified());
     676      517430 :     if (declaration_error_location.IsValid()) {
     677       15462 :       ExpressionScope<Types>::Report(declaration_error_location,
     678             :                                      declaration_error_message);
     679             :     }
     680      517430 :     this->ValidatePattern();
     681             : 
     682      517429 :     DeclarationScope* result = this->parser()->NewFunctionScope(kind());
     683      517425 :     if (!has_simple_parameter_list_) result->SetHasNonSimpleParameters();
     684             :     VariableKind kind = PARAMETER_VARIABLE;
     685             :     VariableMode mode =
     686      517425 :         has_simple_parameter_list_ ? VariableMode::kVar : VariableMode::kLet;
     687     1671825 :     for (VariableProxy* proxy : *this->variable_list()) {
     688             :       bool was_added;
     689      144186 :       this->parser()->DeclareAndBindVariable(
     690             :           proxy, kind, mode, Variable::DefaultInitializationFlag(mode), result,
     691             :           &was_added, proxy->position());
     692      577200 :       if (!was_added) {
     693        2562 :         ExpressionScope<Types>::Report(proxy->location(),
     694             :                                        MessageTemplate::kParamDupe);
     695             :       }
     696             :     }
     697             : 
     698             :     int initializer_position = this->parser()->end_position();
     699      661613 :     for (auto declaration : *result->declarations()) {
     700             :       declaration->var()->set_initializer_position(initializer_position);
     701             :     }
     702      517428 :     if (uses_this_) result->UsesThis();
     703      517428 :     return result;
     704             :   }
     705             : 
     706             :   void RecordDeclarationError(const Scanner::Location& loc,
     707             :                               MessageTemplate message) {
     708             :     DCHECK_IMPLIES(!this->has_error(), loc.IsValid());
     709     2869921 :     declaration_error_location = loc;
     710     2869921 :     declaration_error_message = message;
     711             :   }
     712             : 
     713      204440 :   void RecordNonSimpleParameter() { has_simple_parameter_list_ = false; }
     714        2564 :   void RecordThisUse() { uses_this_ = true; }
     715             : 
     716             :  private:
     717             :   FunctionKind kind() const {
     718             :     return this->IsAsyncArrowHeadParsingScope()
     719             :                ? FunctionKind::kAsyncArrowFunction
     720      517429 :                : 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_

Generated by: LCOV version 1.10