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