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 16namespace v8 { 17namespace internal { 18 19template <typename Types> 20class ExpressionParsingScope; 21template <typename Types> 22class AccumulationScope; 23template <typename Types> 24class ArrowHeadParsingScope; 25template <typename Types> 26class ParameterDeclarationParsingScope; 27template <typename Types> 28class VariableDeclarationParsingScope; 29class 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. 43template <typename Types> 44class 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* masking_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 (masking_var != nullptr) { 72 result->set_is_assigned(); 73 if (passed_through_with) break; 74 result->BindTo(masking_var); 75 masking_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 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 118 void MarkIdentifierAsAssigned() { 119 if (!CanBeExpression()) return; 120 AsExpressionParsingScope()->MarkIdentifierAsAssigned(); 121 } 122 123 void ValidateAsPattern(ExpressionT expression, int begin, int end) { 124 if (!CanBeExpression()) return; 125 AsExpressionParsingScope()->ValidatePattern(expression, begin, end); 126 AsExpressionParsingScope()->ClearExpressionError(); 127 } 128 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. 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. 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 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 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 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 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 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 217 void RecordNonSimpleParameter() { 218 if (!IsArrowHeadParsingScope()) return; 219 AsArrowHeadParsingScope()->RecordNonSimpleParameter(); 220 } 221 222 bool IsCertainlyDeclaration() const { 223 return base::IsInRange(type_, kParameterDeclaration, kLexicalDeclaration); 224 } 225 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 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 253 ParserT* parser() const { return parser_; } 254 ExpressionScope* parent() const { return parent_; } 255 256 void Report(const Scanner::Location& loc, MessageTemplate message) const { 257 parser_->ReportMessageAt(loc, message); 258 } 259 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 274 ~ExpressionScope() { 275 DCHECK(parser_->expression_scope_ == this || 276 parser_->expression_scope_ == parent_); 277 parser_->expression_scope_ = parent_; 278 } 279 280 ExpressionParsingScope<Types>* AsExpressionParsingScope() { 281 DCHECK(CanBeExpression()); 282 return static_cast<ExpressionParsingScope<Types>*>(this); 283 } 284 285#ifdef DEBUG 286 bool has_error() const { return parser_->has_error(); } 287#endif 288 289 bool CanBeExpression() const { 290 return base::IsInRange(type_, kExpression, 291 kMaybeAsyncArrowParameterDeclaration); 292 } 293 bool CanBeDeclaration() const { 294 return base::IsInRange(type_, kMaybeArrowParameterDeclaration, 295 kLexicalDeclaration); 296 } 297 bool IsVariableDeclaration() const { 298 return base::IsInRange(type_, kVarDeclaration, kLexicalDeclaration); 299 } 300 bool IsLexicalDeclaration() const { return type_ == kLexicalDeclaration; } 301 bool IsAsyncArrowHeadParsingScope() const { 302 return type_ == kMaybeAsyncArrowParameterDeclaration; 303 } 304 bool IsVarDeclaration() const { return type_ == kVarDeclaration; } 305 306 private: 307 friend class AccumulationScope<Types>; 308 friend class ExpressionParsingScope<Types>; 309 310 ArrowHeadParsingScope<Types>* AsArrowHeadParsingScope() { 311 DCHECK(IsArrowHeadParsingScope()); 312 return static_cast<ArrowHeadParsingScope<Types>*>(this); 313 } 314 315 ParameterDeclarationParsingScope<Types>* 316 AsParameterDeclarationParsingScope() { 317 DCHECK(IsCertainlyParameterDeclaration()); 318 return static_cast<ParameterDeclarationParsingScope<Types>*>(this); 319 } 320 321 VariableDeclarationParsingScope<Types>* AsVariableDeclarationParsingScope() { 322 DCHECK(IsVariableDeclaration()); 323 return static_cast<VariableDeclarationParsingScope<Types>*>(this); 324 } 325 326 bool IsArrowHeadParsingScope() const { 327 return base::IsInRange(type_, kMaybeArrowParameterDeclaration, 328 kMaybeAsyncArrowParameterDeclaration); 329 } 330 bool IsCertainlyPattern() const { return IsCertainlyDeclaration(); } 331 bool CanBeParameterDeclaration() const { 332 return base::IsInRange(type_, kMaybeArrowParameterDeclaration, 333 kParameterDeclaration); 334 } 335 bool CanBeArrowParameterDeclaration() const { 336 return base::IsInRange(type_, kMaybeArrowParameterDeclaration, 337 kMaybeAsyncArrowParameterDeclaration); 338 } 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. 351template <typename Types> 352class VariableDeclarationParsingScope : public ExpressionScope<Types> { 353 public: 354 using ParserT = typename Types::Impl; 355 using ExpressionScopeT = ExpressionScope<Types>; 356 using ScopeType = typename ExpressionScopeT::ScopeType; 357 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 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 424template <typename Types> 425class ParameterDeclarationParsingScope : public ExpressionScope<Types> { 426 public: 427 using ParserT = typename Types::Impl; 428 using ExpressionScopeT = ExpressionScope<Types>; 429 using ScopeType = typename ExpressionScopeT::ScopeType; 430 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 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 452 bool has_duplicate() const { return duplicate_loc_.IsValid(); } 453 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. 468template <typename Types> 469class 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) 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 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 506 ~ExpressionParsingScope() { DCHECK(this->has_error() || verified_); } 507 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 525 void RecordExpressionError(const Scanner::Location& loc, 526 MessageTemplate message) { 527 Record(kExpressionIndex, loc, message); 528 } 529 530 void RecordPatternError(const Scanner::Location& loc, 531 MessageTemplate message) { 532 Record(kPatternIndex, loc, message); 533 } 534 535 void ValidateExpression() { Validate(kExpressionIndex); } 536 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 548 void ClearExpressionError() { 549 DCHECK(verified_); 550#ifdef DEBUG 551 verified_ = false; 552#endif 553 clear(kExpressionIndex); 554 } 555 556 void ClearPatternError() { 557 DCHECK(verified_); 558#ifdef DEBUG 559 verified_ = false; 560#endif 561 clear(kPatternIndex); 562 } 563 564 void TrackVariable(VariableProxy* variable) { 565 if (!this->CanBeDeclaration()) { 566 this->parser()->scope()->AddUnresolved(variable); 567 } 568 variable_list_.Add({variable, kNoSourcePosition}); 569 } 570 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 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 594 ScopedList<std::pair<VariableProxy*, int>>* variable_list() { 595 return &variable_list_; 596 } 597 598 protected: 599 bool is_verified() const { 600#ifdef DEBUG 601 return verified_; 602#else 603 return false; 604#endif 605 } 606 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 }; 617 void clear(int index) { 618 messages_[index] = MessageTemplate::kNone; 619 locations_[index] = Scanner::Location::invalid(); 620 } 621 bool is_valid(int index) const { return !locations_[index].IsValid(); } 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 } 629 void Validate(int index) { 630 DCHECK(!this->is_verified()); 631 if (!is_valid(index)) Report(index); 632 this->mark_verified(); 633 } 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. 639 void mark_verified() { 640#ifdef DEBUG 641 verified_ = true; 642#endif 643 } 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. 668template <typename Types> 669class AccumulationScope { 670 public: 671 using ParserT = typename Types::Impl; 672 673 static const int kNumberOfErrors = 674 ExpressionParsingScope<Types>::kNumberOfErrors; 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. 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. 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 717 ~AccumulationScope() { 718 if (scope_ == nullptr) return; 719 Accumulate(); 720 for (int i = 0; i < kNumberOfErrors; i++) copy_back(i); 721 } 722 723 private: 724 void copy(int entry) { 725 messages_[entry] = scope_->messages_[entry]; 726 locations_[entry] = scope_->locations_[entry]; 727 } 728 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. 744template <typename Types> 745class ArrowHeadParsingScope : public ExpressionParsingScope<Types> { 746 public: 747 using ParserT = typename Types::Impl; 748 using ScopeType = typename ExpressionScope<Types>::ScopeType; 749 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 // clear last next_arrow_function_info tracked strict parameters error. 762 parser->next_arrow_function_info_.ClearStrictParameterError(); 763 } 764 765 ArrowHeadParsingScope(const ArrowHeadParsingScope&) = delete; 766 ArrowHeadParsingScope& operator=(const ArrowHeadParsingScope&) = delete; 767 768 void ValidateExpression() { 769 // Turns out this is not an arrow head. Clear any possible tracked strict 770 // parameter errors, and reinterpret tracked variables as unresolved 771 // references. 772 this->parser()->next_arrow_function_info_.ClearStrictParameterError(); 773 ExpressionParsingScope<Types>::ValidateExpression(); 774 this->parent()->MergeVariableList(this->variable_list()); 775 } 776 777 DeclarationScope* ValidateAndCreateScope() { 778 DCHECK(!this->is_verified()); 779 DeclarationScope* result = this->parser()->NewFunctionScope(kind()); 780 if (declaration_error_location.IsValid()) { 781 ExpressionScope<Types>::Report(declaration_error_location, 782 declaration_error_message); 783 return result; 784 } 785 this->ValidatePattern(); 786 787 if (!has_simple_parameter_list_) result->SetHasNonSimpleParameters(); 788 VariableKind kind = PARAMETER_VARIABLE; 789 VariableMode mode = 790 has_simple_parameter_list_ ? VariableMode::kVar : VariableMode::kLet; 791 for (auto& proxy_initializer_pair : *this->variable_list()) { 792 VariableProxy* proxy = proxy_initializer_pair.first; 793 int initializer_position = proxy_initializer_pair.second; 794 // Default values for parameters will have been parsed as assignments so 795 // clear the is_assigned bit as they are not actually assignments. 796 proxy->clear_is_assigned(); 797 bool was_added; 798 this->parser()->DeclareAndBindVariable(proxy, kind, mode, result, 799 &was_added, initializer_position); 800 if (!was_added) { 801 ExpressionScope<Types>::Report(proxy->location(), 802 MessageTemplate::kParamDupe); 803 } 804 } 805 806#ifdef DEBUG 807 if (!this->has_error()) { 808 for (auto declaration : *result->declarations()) { 809 DCHECK_NE(declaration->var()->initializer_position(), 810 kNoSourcePosition); 811 } 812 } 813#endif // DEBUG 814 815 if (uses_this_) result->UsesThis(); 816 return result; 817 } 818 819 void RecordDeclarationError(const Scanner::Location& loc, 820 MessageTemplate message) { 821 DCHECK_IMPLIES(!this->has_error(), loc.IsValid()); 822 declaration_error_location = loc; 823 declaration_error_message = message; 824 } 825 826 void RecordNonSimpleParameter() { has_simple_parameter_list_ = false; } 827 void RecordThisUse() { uses_this_ = true; } 828 829 private: 830 FunctionKind kind() const { 831 return this->IsAsyncArrowHeadParsingScope() 832 ? FunctionKind::kAsyncArrowFunction 833 : FunctionKind::kArrowFunction; 834 } 835 836 Scanner::Location declaration_error_location = Scanner::Location::invalid(); 837 MessageTemplate declaration_error_message = MessageTemplate::kNone; 838 bool has_simple_parameter_list_ = true; 839 bool uses_this_ = false; 840}; 841 842} // namespace internal 843} // namespace v8 844 845#endif // V8_PARSING_EXPRESSION_SCOPE_H_ 846