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