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