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