1// Copyright 2012 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#include "src/ast/prettyprinter.h" 6 7#include <stdarg.h> 8 9#include "src/ast/ast-value-factory.h" 10#include "src/ast/scopes.h" 11#include "src/base/platform/platform.h" 12#include "src/base/strings.h" 13#include "src/base/vector.h" 14#include "src/common/globals.h" 15#include "src/objects/objects-inl.h" 16#include "src/regexp/regexp-flags.h" 17#include "src/strings/string-builder-inl.h" 18 19namespace v8 { 20namespace internal { 21 22CallPrinter::CallPrinter(Isolate* isolate, bool is_user_js, 23 SpreadErrorInArgsHint error_in_spread_args) 24 : builder_(new IncrementalStringBuilder(isolate)) { 25 isolate_ = isolate; 26 position_ = 0; 27 num_prints_ = 0; 28 found_ = false; 29 done_ = false; 30 is_call_error_ = false; 31 is_iterator_error_ = false; 32 is_async_iterator_error_ = false; 33 destructuring_prop_ = nullptr; 34 destructuring_assignment_ = nullptr; 35 is_user_js_ = is_user_js; 36 error_in_spread_args_ = error_in_spread_args; 37 spread_arg_ = nullptr; 38 function_kind_ = FunctionKind::kNormalFunction; 39 InitializeAstVisitor(isolate); 40} 41 42CallPrinter::~CallPrinter() = default; 43 44CallPrinter::ErrorHint CallPrinter::GetErrorHint() const { 45 if (is_call_error_) { 46 if (is_iterator_error_) return ErrorHint::kCallAndNormalIterator; 47 if (is_async_iterator_error_) return ErrorHint::kCallAndAsyncIterator; 48 } else { 49 if (is_iterator_error_) return ErrorHint::kNormalIterator; 50 if (is_async_iterator_error_) return ErrorHint::kAsyncIterator; 51 } 52 return ErrorHint::kNone; 53} 54 55Handle<String> CallPrinter::Print(FunctionLiteral* program, int position) { 56 num_prints_ = 0; 57 position_ = position; 58 Find(program); 59 return builder_->Finish().ToHandleChecked(); 60} 61 62 63void CallPrinter::Find(AstNode* node, bool print) { 64 if (found_) { 65 if (print) { 66 int prev_num_prints = num_prints_; 67 Visit(node); 68 if (prev_num_prints != num_prints_) return; 69 } 70 Print("(intermediate value)"); 71 } else { 72 Visit(node); 73 } 74} 75 76void CallPrinter::Print(char c) { 77 if (!found_ || done_) return; 78 num_prints_++; 79 builder_->AppendCharacter(c); 80} 81 82void CallPrinter::Print(const char* str) { 83 if (!found_ || done_) return; 84 num_prints_++; 85 builder_->AppendCString(str); 86} 87 88void CallPrinter::Print(Handle<String> str) { 89 if (!found_ || done_) return; 90 num_prints_++; 91 builder_->AppendString(str); 92} 93 94void CallPrinter::VisitBlock(Block* node) { 95 FindStatements(node->statements()); 96} 97 98 99void CallPrinter::VisitVariableDeclaration(VariableDeclaration* node) {} 100 101 102void CallPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) {} 103 104 105void CallPrinter::VisitExpressionStatement(ExpressionStatement* node) { 106 Find(node->expression()); 107} 108 109 110void CallPrinter::VisitEmptyStatement(EmptyStatement* node) {} 111 112 113void CallPrinter::VisitSloppyBlockFunctionStatement( 114 SloppyBlockFunctionStatement* node) { 115 Find(node->statement()); 116} 117 118 119void CallPrinter::VisitIfStatement(IfStatement* node) { 120 Find(node->condition()); 121 Find(node->then_statement()); 122 if (node->HasElseStatement()) { 123 Find(node->else_statement()); 124 } 125} 126 127 128void CallPrinter::VisitContinueStatement(ContinueStatement* node) {} 129 130 131void CallPrinter::VisitBreakStatement(BreakStatement* node) {} 132 133 134void CallPrinter::VisitReturnStatement(ReturnStatement* node) { 135 Find(node->expression()); 136} 137 138 139void CallPrinter::VisitWithStatement(WithStatement* node) { 140 Find(node->expression()); 141 Find(node->statement()); 142} 143 144 145void CallPrinter::VisitSwitchStatement(SwitchStatement* node) { 146 Find(node->tag()); 147 for (CaseClause* clause : *node->cases()) { 148 if (!clause->is_default()) Find(clause->label()); 149 FindStatements(clause->statements()); 150 } 151} 152 153 154void CallPrinter::VisitDoWhileStatement(DoWhileStatement* node) { 155 Find(node->body()); 156 Find(node->cond()); 157} 158 159 160void CallPrinter::VisitWhileStatement(WhileStatement* node) { 161 Find(node->cond()); 162 Find(node->body()); 163} 164 165 166void CallPrinter::VisitForStatement(ForStatement* node) { 167 if (node->init() != nullptr) { 168 Find(node->init()); 169 } 170 if (node->cond() != nullptr) Find(node->cond()); 171 if (node->next() != nullptr) Find(node->next()); 172 Find(node->body()); 173} 174 175 176void CallPrinter::VisitForInStatement(ForInStatement* node) { 177 Find(node->each()); 178 Find(node->subject()); 179 Find(node->body()); 180} 181 182 183void CallPrinter::VisitForOfStatement(ForOfStatement* node) { 184 Find(node->each()); 185 186 // Check the subject's position in case there was a GetIterator error. 187 bool was_found = false; 188 if (node->subject()->position() == position_) { 189 is_async_iterator_error_ = node->type() == IteratorType::kAsync; 190 is_iterator_error_ = !is_async_iterator_error_; 191 was_found = !found_; 192 if (was_found) { 193 found_ = true; 194 } 195 } 196 Find(node->subject(), true); 197 if (was_found) { 198 done_ = true; 199 found_ = false; 200 } 201 202 Find(node->body()); 203} 204 205 206void CallPrinter::VisitTryCatchStatement(TryCatchStatement* node) { 207 Find(node->try_block()); 208 Find(node->catch_block()); 209} 210 211 212void CallPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) { 213 Find(node->try_block()); 214 Find(node->finally_block()); 215} 216 217 218void CallPrinter::VisitDebuggerStatement(DebuggerStatement* node) {} 219 220 221void CallPrinter::VisitFunctionLiteral(FunctionLiteral* node) { 222 FunctionKind last_function_kind = function_kind_; 223 function_kind_ = node->kind(); 224 FindStatements(node->body()); 225 function_kind_ = last_function_kind; 226} 227 228 229void CallPrinter::VisitClassLiteral(ClassLiteral* node) { 230 if (node->extends()) Find(node->extends()); 231 for (int i = 0; i < node->public_members()->length(); i++) { 232 Find(node->public_members()->at(i)->value()); 233 } 234 for (int i = 0; i < node->private_members()->length(); i++) { 235 Find(node->private_members()->at(i)->value()); 236 } 237} 238 239void CallPrinter::VisitInitializeClassMembersStatement( 240 InitializeClassMembersStatement* node) { 241 for (int i = 0; i < node->fields()->length(); i++) { 242 Find(node->fields()->at(i)->value()); 243 } 244} 245 246void CallPrinter::VisitInitializeClassStaticElementsStatement( 247 InitializeClassStaticElementsStatement* node) { 248 for (int i = 0; i < node->elements()->length(); i++) { 249 ClassLiteral::StaticElement* element = node->elements()->at(i); 250 if (element->kind() == ClassLiteral::StaticElement::PROPERTY) { 251 Find(element->property()->value()); 252 } else { 253 Find(element->static_block()); 254 } 255 } 256} 257 258void CallPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) {} 259 260 261void CallPrinter::VisitConditional(Conditional* node) { 262 Find(node->condition()); 263 Find(node->then_expression()); 264 Find(node->else_expression()); 265} 266 267 268void CallPrinter::VisitLiteral(Literal* node) { 269 // TODO(adamk): Teach Literal how to print its values without 270 // allocating on the heap. 271 PrintLiteral(node->BuildValue(isolate_), true); 272} 273 274 275void CallPrinter::VisitRegExpLiteral(RegExpLiteral* node) { 276 Print("/"); 277 PrintLiteral(node->pattern(), false); 278 Print("/"); 279#define V(Lower, Camel, LowerCamel, Char, Bit) \ 280 if (node->flags() & RegExp::k##Camel) Print(Char); 281 REGEXP_FLAG_LIST(V) 282#undef V 283} 284 285 286void CallPrinter::VisitObjectLiteral(ObjectLiteral* node) { 287 Print("{"); 288 for (int i = 0; i < node->properties()->length(); i++) { 289 Find(node->properties()->at(i)->value()); 290 } 291 Print("}"); 292} 293 294 295void CallPrinter::VisitArrayLiteral(ArrayLiteral* node) { 296 Print("["); 297 for (int i = 0; i < node->values()->length(); i++) { 298 if (i != 0) Print(","); 299 Expression* subexpr = node->values()->at(i); 300 Spread* spread = subexpr->AsSpread(); 301 if (spread != nullptr && !found_ && 302 position_ == spread->expression()->position()) { 303 found_ = true; 304 is_iterator_error_ = true; 305 Find(spread->expression(), true); 306 done_ = true; 307 return; 308 } 309 Find(subexpr, true); 310 } 311 Print("]"); 312} 313 314 315void CallPrinter::VisitVariableProxy(VariableProxy* node) { 316 if (is_user_js_) { 317 PrintLiteral(node->name(), false); 318 } else { 319 // Variable names of non-user code are meaningless due to minification. 320 Print("(var)"); 321 } 322} 323 324 325void CallPrinter::VisitAssignment(Assignment* node) { 326 bool was_found = false; 327 if (node->target()->IsObjectLiteral()) { 328 ObjectLiteral* target = node->target()->AsObjectLiteral(); 329 if (target->position() == position_) { 330 was_found = !found_; 331 found_ = true; 332 destructuring_assignment_ = node; 333 } else { 334 for (ObjectLiteralProperty* prop : *target->properties()) { 335 if (prop->value()->position() == position_) { 336 was_found = !found_; 337 found_ = true; 338 destructuring_prop_ = prop; 339 destructuring_assignment_ = node; 340 break; 341 } 342 } 343 } 344 } 345 if (!was_found) { 346 Find(node->target()); 347 if (node->target()->IsArrayLiteral()) { 348 // Special case the visit for destructuring array assignment. 349 if (node->value()->position() == position_) { 350 is_iterator_error_ = true; 351 was_found = !found_; 352 found_ = true; 353 } 354 Find(node->value(), true); 355 } else { 356 Find(node->value()); 357 } 358 } else { 359 Find(node->value(), true); 360 } 361 362 if (was_found) { 363 done_ = true; 364 found_ = false; 365 } 366} 367 368void CallPrinter::VisitCompoundAssignment(CompoundAssignment* node) { 369 VisitAssignment(node); 370} 371 372void CallPrinter::VisitYield(Yield* node) { Find(node->expression()); } 373 374void CallPrinter::VisitYieldStar(YieldStar* node) { 375 if (!found_ && position_ == node->expression()->position()) { 376 found_ = true; 377 if (IsAsyncFunction(function_kind_)) 378 is_async_iterator_error_ = true; 379 else 380 is_iterator_error_ = true; 381 Print("yield* "); 382 } 383 Find(node->expression()); 384} 385 386void CallPrinter::VisitAwait(Await* node) { Find(node->expression()); } 387 388void CallPrinter::VisitThrow(Throw* node) { Find(node->exception()); } 389 390void CallPrinter::VisitOptionalChain(OptionalChain* node) { 391 Find(node->expression()); 392} 393 394void CallPrinter::VisitProperty(Property* node) { 395 Expression* key = node->key(); 396 Literal* literal = key->AsLiteral(); 397 if (literal != nullptr && 398 literal->BuildValue(isolate_)->IsInternalizedString()) { 399 Find(node->obj(), true); 400 if (node->is_optional_chain_link()) { 401 Print("?"); 402 } 403 Print("."); 404 // TODO(adamk): Teach Literal how to print its values without 405 // allocating on the heap. 406 PrintLiteral(literal->BuildValue(isolate_), false); 407 } else { 408 Find(node->obj(), true); 409 if (node->is_optional_chain_link()) { 410 Print("?."); 411 } 412 Print("["); 413 Find(key, true); 414 Print("]"); 415 } 416} 417 418void CallPrinter::VisitCall(Call* node) { 419 bool was_found = false; 420 if (node->position() == position_) { 421 if (error_in_spread_args_ == SpreadErrorInArgsHint::kErrorInArgs) { 422 found_ = true; 423 spread_arg_ = node->arguments()->last()->AsSpread()->expression(); 424 Find(spread_arg_, true); 425 426 done_ = true; 427 found_ = false; 428 return; 429 } 430 431 is_call_error_ = true; 432 was_found = !found_; 433 } 434 435 if (was_found) { 436 // Bail out if the error is caused by a direct call to a variable in 437 // non-user JS code. The variable name is meaningless due to minification. 438 if (!is_user_js_ && node->expression()->IsVariableProxy()) { 439 done_ = true; 440 return; 441 } 442 found_ = true; 443 } 444 Find(node->expression(), true); 445 if (!was_found && !is_iterator_error_) Print("(...)"); 446 FindArguments(node->arguments()); 447 if (was_found) { 448 done_ = true; 449 found_ = false; 450 } 451} 452 453 454void CallPrinter::VisitCallNew(CallNew* node) { 455 bool was_found = false; 456 if (node->position() == position_) { 457 if (error_in_spread_args_ == SpreadErrorInArgsHint::kErrorInArgs) { 458 found_ = true; 459 spread_arg_ = node->arguments()->last()->AsSpread()->expression(); 460 Find(spread_arg_, true); 461 462 done_ = true; 463 found_ = false; 464 return; 465 } 466 467 is_call_error_ = true; 468 was_found = !found_; 469 } 470 if (was_found) { 471 // Bail out if the error is caused by a direct call to a variable in 472 // non-user JS code. The variable name is meaningless due to minification. 473 if (!is_user_js_ && node->expression()->IsVariableProxy()) { 474 done_ = true; 475 return; 476 } 477 found_ = true; 478 } 479 Find(node->expression(), was_found || is_iterator_error_); 480 FindArguments(node->arguments()); 481 if (was_found) { 482 done_ = true; 483 found_ = false; 484 } 485} 486 487 488void CallPrinter::VisitCallRuntime(CallRuntime* node) { 489 FindArguments(node->arguments()); 490} 491 492 493void CallPrinter::VisitUnaryOperation(UnaryOperation* node) { 494 Token::Value op = node->op(); 495 bool needsSpace = 496 op == Token::DELETE || op == Token::TYPEOF || op == Token::VOID; 497 Print("("); 498 Print(Token::String(op)); 499 if (needsSpace) Print(" "); 500 Find(node->expression(), true); 501 Print(")"); 502} 503 504 505void CallPrinter::VisitCountOperation(CountOperation* node) { 506 Print("("); 507 if (node->is_prefix()) Print(Token::String(node->op())); 508 Find(node->expression(), true); 509 if (node->is_postfix()) Print(Token::String(node->op())); 510 Print(")"); 511} 512 513 514void CallPrinter::VisitBinaryOperation(BinaryOperation* node) { 515 Print("("); 516 Find(node->left(), true); 517 Print(" "); 518 Print(Token::String(node->op())); 519 Print(" "); 520 Find(node->right(), true); 521 Print(")"); 522} 523 524void CallPrinter::VisitNaryOperation(NaryOperation* node) { 525 Print("("); 526 Find(node->first(), true); 527 for (size_t i = 0; i < node->subsequent_length(); ++i) { 528 Print(" "); 529 Print(Token::String(node->op())); 530 Print(" "); 531 Find(node->subsequent(i), true); 532 } 533 Print(")"); 534} 535 536void CallPrinter::VisitCompareOperation(CompareOperation* node) { 537 Print("("); 538 Find(node->left(), true); 539 Print(" "); 540 Print(Token::String(node->op())); 541 Print(" "); 542 Find(node->right(), true); 543 Print(")"); 544} 545 546 547void CallPrinter::VisitSpread(Spread* node) { 548 Print("(..."); 549 Find(node->expression(), true); 550 Print(")"); 551} 552 553void CallPrinter::VisitEmptyParentheses(EmptyParentheses* node) { 554 UNREACHABLE(); 555} 556 557void CallPrinter::VisitGetTemplateObject(GetTemplateObject* node) {} 558 559void CallPrinter::VisitTemplateLiteral(TemplateLiteral* node) { 560 for (Expression* substitution : *node->substitutions()) { 561 Find(substitution, true); 562 } 563} 564 565void CallPrinter::VisitImportCallExpression(ImportCallExpression* node) { 566 Print("ImportCall("); 567 Find(node->specifier(), true); 568 if (node->import_assertions()) { 569 Find(node->import_assertions(), true); 570 } 571 Print(")"); 572} 573 574void CallPrinter::VisitThisExpression(ThisExpression* node) { Print("this"); } 575 576void CallPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) {} 577 578 579void CallPrinter::VisitSuperCallReference(SuperCallReference* node) { 580 Print("super"); 581} 582 583 584void CallPrinter::FindStatements(const ZonePtrList<Statement>* statements) { 585 if (statements == nullptr) return; 586 for (int i = 0; i < statements->length(); i++) { 587 Find(statements->at(i)); 588 } 589} 590 591void CallPrinter::FindArguments(const ZonePtrList<Expression>* arguments) { 592 if (found_) return; 593 for (int i = 0; i < arguments->length(); i++) { 594 Find(arguments->at(i)); 595 } 596} 597 598void CallPrinter::PrintLiteral(Handle<Object> value, bool quote) { 599 if (value->IsString()) { 600 if (quote) Print("\""); 601 Print(Handle<String>::cast(value)); 602 if (quote) Print("\""); 603 } else if (value->IsNull(isolate_)) { 604 Print("null"); 605 } else if (value->IsTrue(isolate_)) { 606 Print("true"); 607 } else if (value->IsFalse(isolate_)) { 608 Print("false"); 609 } else if (value->IsUndefined(isolate_)) { 610 Print("undefined"); 611 } else if (value->IsNumber()) { 612 Print(isolate_->factory()->NumberToString(value)); 613 } else if (value->IsSymbol()) { 614 // Symbols can only occur as literals if they were inserted by the parser. 615 PrintLiteral(handle(Handle<Symbol>::cast(value)->description(), isolate_), 616 false); 617 } 618} 619 620 621void CallPrinter::PrintLiteral(const AstRawString* value, bool quote) { 622 PrintLiteral(value->string(), quote); 623} 624 625//----------------------------------------------------------------------------- 626 627 628#ifdef DEBUG 629 630const char* AstPrinter::Print(AstNode* node) { 631 Init(); 632 Visit(node); 633 return output_; 634} 635 636void AstPrinter::Init() { 637 if (size_ == 0) { 638 DCHECK_NULL(output_); 639 const int initial_size = 256; 640 output_ = NewArray<char>(initial_size); 641 size_ = initial_size; 642 } 643 output_[0] = '\0'; 644 pos_ = 0; 645} 646 647void AstPrinter::Print(const char* format, ...) { 648 for (;;) { 649 va_list arguments; 650 va_start(arguments, format); 651 int n = base::VSNPrintF(base::Vector<char>(output_, size_) + pos_, format, 652 arguments); 653 va_end(arguments); 654 655 if (n >= 0) { 656 // there was enough space - we are done 657 pos_ += n; 658 return; 659 } else { 660 // there was not enough space - allocate more and try again 661 const int slack = 32; 662 int new_size = size_ + (size_ >> 1) + slack; 663 char* new_output = NewArray<char>(new_size); 664 MemCopy(new_output, output_, pos_); 665 DeleteArray(output_); 666 output_ = new_output; 667 size_ = new_size; 668 } 669 } 670} 671 672void AstPrinter::PrintLiteral(Literal* literal, bool quote) { 673 switch (literal->type()) { 674 case Literal::kString: 675 PrintLiteral(literal->AsRawString(), quote); 676 break; 677 case Literal::kSmi: 678 Print("%d", Smi::ToInt(literal->AsSmiLiteral())); 679 break; 680 case Literal::kHeapNumber: 681 Print("%g", literal->AsNumber()); 682 break; 683 case Literal::kBigInt: 684 Print("%sn", literal->AsBigInt().c_str()); 685 break; 686 case Literal::kNull: 687 Print("null"); 688 break; 689 case Literal::kUndefined: 690 Print("undefined"); 691 break; 692 case Literal::kTheHole: 693 Print("the hole"); 694 break; 695 case Literal::kBoolean: 696 if (literal->ToBooleanIsTrue()) { 697 Print("true"); 698 } else { 699 Print("false"); 700 } 701 break; 702 } 703} 704 705void AstPrinter::PrintLiteral(const AstRawString* value, bool quote) { 706 if (quote) Print("\""); 707 if (value != nullptr) { 708 const char* format = value->is_one_byte() ? "%c" : "%lc"; 709 const int increment = value->is_one_byte() ? 1 : 2; 710 const unsigned char* raw_bytes = value->raw_data(); 711 for (int i = 0; i < value->length(); i += increment) { 712 Print(format, raw_bytes[i]); 713 } 714 } 715 if (quote) Print("\""); 716} 717 718void AstPrinter::PrintLiteral(const AstConsString* value, bool quote) { 719 if (quote) Print("\""); 720 if (value != nullptr) { 721 std::forward_list<const AstRawString*> strings = value->ToRawStrings(); 722 for (const AstRawString* string : strings) { 723 PrintLiteral(string, false); 724 } 725 } 726 if (quote) Print("\""); 727} 728 729//----------------------------------------------------------------------------- 730 731class V8_NODISCARD IndentedScope { 732 public: 733 IndentedScope(AstPrinter* printer, const char* txt) 734 : ast_printer_(printer) { 735 ast_printer_->PrintIndented(txt); 736 ast_printer_->Print("\n"); 737 ast_printer_->inc_indent(); 738 } 739 740 IndentedScope(AstPrinter* printer, const char* txt, int pos) 741 : ast_printer_(printer) { 742 ast_printer_->PrintIndented(txt); 743 ast_printer_->Print(" at %d\n", pos); 744 ast_printer_->inc_indent(); 745 } 746 747 virtual ~IndentedScope() { 748 ast_printer_->dec_indent(); 749 } 750 751 private: 752 AstPrinter* ast_printer_; 753}; 754 755//----------------------------------------------------------------------------- 756 757AstPrinter::AstPrinter(uintptr_t stack_limit) 758 : output_(nullptr), size_(0), pos_(0), indent_(0) { 759 InitializeAstVisitor(stack_limit); 760} 761 762AstPrinter::~AstPrinter() { 763 DCHECK_EQ(indent_, 0); 764 DeleteArray(output_); 765} 766 767 768void AstPrinter::PrintIndented(const char* txt) { 769 for (int i = 0; i < indent_; i++) { 770 Print(". "); 771 } 772 Print("%s", txt); 773} 774 775void AstPrinter::PrintLiteralIndented(const char* info, Literal* literal, 776 bool quote) { 777 PrintIndented(info); 778 Print(" "); 779 PrintLiteral(literal, quote); 780 Print("\n"); 781} 782 783void AstPrinter::PrintLiteralIndented(const char* info, 784 const AstRawString* value, bool quote) { 785 PrintIndented(info); 786 Print(" "); 787 PrintLiteral(value, quote); 788 Print("\n"); 789} 790 791void AstPrinter::PrintLiteralIndented(const char* info, 792 const AstConsString* value, bool quote) { 793 PrintIndented(info); 794 Print(" "); 795 PrintLiteral(value, quote); 796 Print("\n"); 797} 798 799void AstPrinter::PrintLiteralWithModeIndented(const char* info, Variable* var, 800 const AstRawString* value) { 801 if (var == nullptr) { 802 PrintLiteralIndented(info, value, true); 803 } else { 804 base::EmbeddedVector<char, 256> buf; 805 int pos = 806 SNPrintF(buf, "%s (%p) (mode = %s, assigned = %s", info, 807 reinterpret_cast<void*>(var), VariableMode2String(var->mode()), 808 var->maybe_assigned() == kMaybeAssigned ? "true" : "false"); 809 SNPrintF(buf + pos, ")"); 810 PrintLiteralIndented(buf.begin(), value, true); 811 } 812} 813 814void AstPrinter::PrintIndentedVisit(const char* s, AstNode* node) { 815 if (node != nullptr) { 816 IndentedScope indent(this, s, node->position()); 817 Visit(node); 818 } 819} 820 821 822const char* AstPrinter::PrintProgram(FunctionLiteral* program) { 823 Init(); 824 { IndentedScope indent(this, "FUNC", program->position()); 825 PrintIndented("KIND"); 826 Print(" %d\n", static_cast<uint32_t>(program->kind())); 827 PrintIndented("LITERAL ID"); 828 Print(" %d\n", program->function_literal_id()); 829 PrintIndented("SUSPEND COUNT"); 830 Print(" %d\n", program->suspend_count()); 831 PrintLiteralIndented("NAME", program->raw_name(), true); 832 if (program->raw_inferred_name()) { 833 PrintLiteralIndented("INFERRED NAME", program->raw_inferred_name(), true); 834 } 835 if (program->requires_instance_members_initializer()) { 836 Print(" REQUIRES INSTANCE FIELDS INITIALIZER\n"); 837 } 838 if (program->class_scope_has_private_brand()) { 839 Print(" CLASS SCOPE HAS PRIVATE BRAND\n"); 840 } 841 if (program->has_static_private_methods_or_accessors()) { 842 Print(" HAS STATIC PRIVATE METHODS\n"); 843 } 844 PrintParameters(program->scope()); 845 PrintDeclarations(program->scope()->declarations()); 846 PrintStatements(program->body()); 847 } 848 return output_; 849} 850 851 852void AstPrinter::PrintOut(Isolate* isolate, AstNode* node) { 853 AstPrinter printer(isolate->stack_guard()->real_climit()); 854 printer.Init(); 855 printer.Visit(node); 856 PrintF("%s", printer.output_); 857} 858 859void AstPrinter::PrintDeclarations(Declaration::List* declarations) { 860 if (!declarations->is_empty()) { 861 IndentedScope indent(this, "DECLS"); 862 for (Declaration* decl : *declarations) Visit(decl); 863 } 864} 865 866void AstPrinter::PrintParameters(DeclarationScope* scope) { 867 if (scope->num_parameters() > 0) { 868 IndentedScope indent(this, "PARAMS"); 869 for (int i = 0; i < scope->num_parameters(); i++) { 870 PrintLiteralWithModeIndented("VAR", scope->parameter(i), 871 scope->parameter(i)->raw_name()); 872 } 873 } 874} 875 876void AstPrinter::PrintStatements(const ZonePtrList<Statement>* statements) { 877 for (int i = 0; i < statements->length(); i++) { 878 Visit(statements->at(i)); 879 } 880} 881 882void AstPrinter::PrintArguments(const ZonePtrList<Expression>* arguments) { 883 for (int i = 0; i < arguments->length(); i++) { 884 Visit(arguments->at(i)); 885 } 886} 887 888 889void AstPrinter::VisitBlock(Block* node) { 890 const char* block_txt = 891 node->ignore_completion_value() ? "BLOCK NOCOMPLETIONS" : "BLOCK"; 892 IndentedScope indent(this, block_txt, node->position()); 893 PrintStatements(node->statements()); 894} 895 896 897// TODO(svenpanne) Start with IndentedScope. 898void AstPrinter::VisitVariableDeclaration(VariableDeclaration* node) { 899 PrintLiteralWithModeIndented("VARIABLE", node->var(), 900 node->var()->raw_name()); 901} 902 903 904// TODO(svenpanne) Start with IndentedScope. 905void AstPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) { 906 PrintIndented("FUNCTION "); 907 PrintLiteral(node->var()->raw_name(), true); 908 Print(" = function "); 909 PrintLiteral(node->fun()->raw_name(), false); 910 Print("\n"); 911} 912 913 914void AstPrinter::VisitExpressionStatement(ExpressionStatement* node) { 915 IndentedScope indent(this, "EXPRESSION STATEMENT", node->position()); 916 Visit(node->expression()); 917} 918 919 920void AstPrinter::VisitEmptyStatement(EmptyStatement* node) { 921 IndentedScope indent(this, "EMPTY", node->position()); 922} 923 924 925void AstPrinter::VisitSloppyBlockFunctionStatement( 926 SloppyBlockFunctionStatement* node) { 927 Visit(node->statement()); 928} 929 930 931void AstPrinter::VisitIfStatement(IfStatement* node) { 932 IndentedScope indent(this, "IF", node->position()); 933 PrintIndentedVisit("CONDITION", node->condition()); 934 PrintIndentedVisit("THEN", node->then_statement()); 935 if (node->HasElseStatement()) { 936 PrintIndentedVisit("ELSE", node->else_statement()); 937 } 938} 939 940 941void AstPrinter::VisitContinueStatement(ContinueStatement* node) { 942 IndentedScope indent(this, "CONTINUE", node->position()); 943} 944 945 946void AstPrinter::VisitBreakStatement(BreakStatement* node) { 947 IndentedScope indent(this, "BREAK", node->position()); 948} 949 950 951void AstPrinter::VisitReturnStatement(ReturnStatement* node) { 952 IndentedScope indent(this, "RETURN", node->position()); 953 Visit(node->expression()); 954} 955 956 957void AstPrinter::VisitWithStatement(WithStatement* node) { 958 IndentedScope indent(this, "WITH", node->position()); 959 PrintIndentedVisit("OBJECT", node->expression()); 960 PrintIndentedVisit("BODY", node->statement()); 961} 962 963 964void AstPrinter::VisitSwitchStatement(SwitchStatement* node) { 965 IndentedScope switch_indent(this, "SWITCH", node->position()); 966 PrintIndentedVisit("TAG", node->tag()); 967 for (CaseClause* clause : *node->cases()) { 968 if (clause->is_default()) { 969 IndentedScope indent(this, "DEFAULT"); 970 PrintStatements(clause->statements()); 971 } else { 972 IndentedScope indent(this, "CASE"); 973 Visit(clause->label()); 974 PrintStatements(clause->statements()); 975 } 976 } 977} 978 979 980void AstPrinter::VisitDoWhileStatement(DoWhileStatement* node) { 981 IndentedScope indent(this, "DO", node->position()); 982 PrintIndentedVisit("BODY", node->body()); 983 PrintIndentedVisit("COND", node->cond()); 984} 985 986 987void AstPrinter::VisitWhileStatement(WhileStatement* node) { 988 IndentedScope indent(this, "WHILE", node->position()); 989 PrintIndentedVisit("COND", node->cond()); 990 PrintIndentedVisit("BODY", node->body()); 991} 992 993 994void AstPrinter::VisitForStatement(ForStatement* node) { 995 IndentedScope indent(this, "FOR", node->position()); 996 if (node->init()) PrintIndentedVisit("INIT", node->init()); 997 if (node->cond()) PrintIndentedVisit("COND", node->cond()); 998 PrintIndentedVisit("BODY", node->body()); 999 if (node->next()) PrintIndentedVisit("NEXT", node->next()); 1000} 1001 1002 1003void AstPrinter::VisitForInStatement(ForInStatement* node) { 1004 IndentedScope indent(this, "FOR IN", node->position()); 1005 PrintIndentedVisit("FOR", node->each()); 1006 PrintIndentedVisit("IN", node->subject()); 1007 PrintIndentedVisit("BODY", node->body()); 1008} 1009 1010 1011void AstPrinter::VisitForOfStatement(ForOfStatement* node) { 1012 IndentedScope indent(this, "FOR OF", node->position()); 1013 const char* for_type; 1014 switch (node->type()) { 1015 case IteratorType::kNormal: 1016 for_type = "FOR"; 1017 break; 1018 case IteratorType::kAsync: 1019 for_type = "FOR AWAIT"; 1020 break; 1021 } 1022 PrintIndentedVisit(for_type, node->each()); 1023 PrintIndentedVisit("OF", node->subject()); 1024 PrintIndentedVisit("BODY", node->body()); 1025} 1026 1027 1028void AstPrinter::VisitTryCatchStatement(TryCatchStatement* node) { 1029 IndentedScope indent(this, "TRY CATCH", node->position()); 1030 PrintIndentedVisit("TRY", node->try_block()); 1031 PrintIndented("CATCH PREDICTION"); 1032 const char* prediction = ""; 1033 switch (node->GetCatchPrediction(HandlerTable::UNCAUGHT)) { 1034 case HandlerTable::UNCAUGHT: 1035 prediction = "UNCAUGHT"; 1036 break; 1037 case HandlerTable::CAUGHT: 1038 prediction = "CAUGHT"; 1039 break; 1040 case HandlerTable::ASYNC_AWAIT: 1041 prediction = "ASYNC_AWAIT"; 1042 break; 1043 case HandlerTable::UNCAUGHT_ASYNC_AWAIT: 1044 prediction = "UNCAUGHT_ASYNC_AWAIT"; 1045 break; 1046 case HandlerTable::PROMISE: 1047 // Catch prediction resulting in promise rejections aren't 1048 // parsed by the parser. 1049 UNREACHABLE(); 1050 } 1051 Print(" %s\n", prediction); 1052 if (node->scope()) { 1053 PrintLiteralWithModeIndented("CATCHVAR", node->scope()->catch_variable(), 1054 node->scope()->catch_variable()->raw_name()); 1055 } 1056 PrintIndentedVisit("CATCH", node->catch_block()); 1057} 1058 1059void AstPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) { 1060 IndentedScope indent(this, "TRY FINALLY", node->position()); 1061 PrintIndentedVisit("TRY", node->try_block()); 1062 PrintIndentedVisit("FINALLY", node->finally_block()); 1063} 1064 1065void AstPrinter::VisitDebuggerStatement(DebuggerStatement* node) { 1066 IndentedScope indent(this, "DEBUGGER", node->position()); 1067} 1068 1069 1070void AstPrinter::VisitFunctionLiteral(FunctionLiteral* node) { 1071 IndentedScope indent(this, "FUNC LITERAL", node->position()); 1072 PrintIndented("LITERAL ID"); 1073 Print(" %d\n", node->function_literal_id()); 1074 PrintLiteralIndented("NAME", node->raw_name(), false); 1075 PrintLiteralIndented("INFERRED NAME", node->raw_inferred_name(), false); 1076 // We don't want to see the function literal in this case: it 1077 // will be printed via PrintProgram when the code for it is 1078 // generated. 1079 // PrintParameters(node->scope()); 1080 // PrintStatements(node->body()); 1081} 1082 1083 1084void AstPrinter::VisitClassLiteral(ClassLiteral* node) { 1085 IndentedScope indent(this, "CLASS LITERAL", node->position()); 1086 PrintLiteralIndented("NAME", node->constructor()->raw_name(), false); 1087 if (node->extends() != nullptr) { 1088 PrintIndentedVisit("EXTENDS", node->extends()); 1089 } 1090 Scope* outer = node->constructor()->scope()->outer_scope(); 1091 if (outer->is_class_scope()) { 1092 Variable* brand = outer->AsClassScope()->brand(); 1093 if (brand != nullptr) { 1094 PrintLiteralWithModeIndented("BRAND", brand, brand->raw_name()); 1095 } 1096 } 1097 if (node->static_initializer() != nullptr) { 1098 PrintIndentedVisit("STATIC INITIALIZER", node->static_initializer()); 1099 } 1100 if (node->instance_members_initializer_function() != nullptr) { 1101 PrintIndentedVisit("INSTANCE MEMBERS INITIALIZER", 1102 node->instance_members_initializer_function()); 1103 } 1104 PrintClassProperties(node->private_members()); 1105 PrintClassProperties(node->public_members()); 1106} 1107 1108void AstPrinter::VisitInitializeClassMembersStatement( 1109 InitializeClassMembersStatement* node) { 1110 IndentedScope indent(this, "INITIALIZE CLASS MEMBERS", node->position()); 1111 PrintClassProperties(node->fields()); 1112} 1113 1114void AstPrinter::VisitInitializeClassStaticElementsStatement( 1115 InitializeClassStaticElementsStatement* node) { 1116 IndentedScope indent(this, "INITIALIZE CLASS STATIC ELEMENTS", 1117 node->position()); 1118 PrintClassStaticElements(node->elements()); 1119} 1120 1121void AstPrinter::PrintClassProperty(ClassLiteral::Property* property) { 1122 const char* prop_kind = nullptr; 1123 switch (property->kind()) { 1124 case ClassLiteral::Property::METHOD: 1125 prop_kind = "METHOD"; 1126 break; 1127 case ClassLiteral::Property::GETTER: 1128 prop_kind = "GETTER"; 1129 break; 1130 case ClassLiteral::Property::SETTER: 1131 prop_kind = "SETTER"; 1132 break; 1133 case ClassLiteral::Property::FIELD: 1134 prop_kind = "FIELD"; 1135 break; 1136 } 1137 base::EmbeddedVector<char, 128> buf; 1138 SNPrintF(buf, "PROPERTY%s%s - %s", property->is_static() ? " - STATIC" : "", 1139 property->is_private() ? " - PRIVATE" : " - PUBLIC", prop_kind); 1140 IndentedScope prop(this, buf.begin()); 1141 PrintIndentedVisit("KEY", property->key()); 1142 PrintIndentedVisit("VALUE", property->value()); 1143} 1144 1145void AstPrinter::PrintClassProperties( 1146 const ZonePtrList<ClassLiteral::Property>* properties) { 1147 for (int i = 0; i < properties->length(); i++) { 1148 PrintClassProperty(properties->at(i)); 1149 } 1150} 1151 1152void AstPrinter::PrintClassStaticElements( 1153 const ZonePtrList<ClassLiteral::StaticElement>* static_elements) { 1154 for (int i = 0; i < static_elements->length(); i++) { 1155 ClassLiteral::StaticElement* element = static_elements->at(i); 1156 switch (element->kind()) { 1157 case ClassLiteral::StaticElement::PROPERTY: 1158 PrintClassProperty(element->property()); 1159 break; 1160 case ClassLiteral::StaticElement::STATIC_BLOCK: 1161 PrintIndentedVisit("STATIC BLOCK", element->static_block()); 1162 break; 1163 } 1164 } 1165} 1166 1167void AstPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) { 1168 IndentedScope indent(this, "NATIVE FUNC LITERAL", node->position()); 1169 PrintLiteralIndented("NAME", node->raw_name(), false); 1170} 1171 1172 1173void AstPrinter::VisitConditional(Conditional* node) { 1174 IndentedScope indent(this, "CONDITIONAL", node->position()); 1175 PrintIndentedVisit("CONDITION", node->condition()); 1176 PrintIndentedVisit("THEN", node->then_expression()); 1177 PrintIndentedVisit("ELSE", node->else_expression()); 1178} 1179 1180 1181void AstPrinter::VisitLiteral(Literal* node) { 1182 PrintLiteralIndented("LITERAL", node, true); 1183} 1184 1185 1186void AstPrinter::VisitRegExpLiteral(RegExpLiteral* node) { 1187 IndentedScope indent(this, "REGEXP LITERAL", node->position()); 1188 PrintLiteralIndented("PATTERN", node->raw_pattern(), false); 1189 int i = 0; 1190 base::EmbeddedVector<char, 128> buf; 1191#define V(Lower, Camel, LowerCamel, Char, Bit) \ 1192 if (node->flags() & RegExp::k##Camel) buf[i++] = Char; 1193 REGEXP_FLAG_LIST(V) 1194#undef V 1195 buf[i] = '\0'; 1196 PrintIndented("FLAGS "); 1197 Print("%s", buf.begin()); 1198 Print("\n"); 1199} 1200 1201 1202void AstPrinter::VisitObjectLiteral(ObjectLiteral* node) { 1203 IndentedScope indent(this, "OBJ LITERAL", node->position()); 1204 PrintObjectProperties(node->properties()); 1205} 1206 1207void AstPrinter::PrintObjectProperties( 1208 const ZonePtrList<ObjectLiteral::Property>* properties) { 1209 for (int i = 0; i < properties->length(); i++) { 1210 ObjectLiteral::Property* property = properties->at(i); 1211 const char* prop_kind = nullptr; 1212 switch (property->kind()) { 1213 case ObjectLiteral::Property::CONSTANT: 1214 prop_kind = "CONSTANT"; 1215 break; 1216 case ObjectLiteral::Property::COMPUTED: 1217 prop_kind = "COMPUTED"; 1218 break; 1219 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 1220 prop_kind = "MATERIALIZED_LITERAL"; 1221 break; 1222 case ObjectLiteral::Property::PROTOTYPE: 1223 prop_kind = "PROTOTYPE"; 1224 break; 1225 case ObjectLiteral::Property::GETTER: 1226 prop_kind = "GETTER"; 1227 break; 1228 case ObjectLiteral::Property::SETTER: 1229 prop_kind = "SETTER"; 1230 break; 1231 case ObjectLiteral::Property::SPREAD: 1232 prop_kind = "SPREAD"; 1233 break; 1234 } 1235 base::EmbeddedVector<char, 128> buf; 1236 SNPrintF(buf, "PROPERTY - %s", prop_kind); 1237 IndentedScope prop(this, buf.begin()); 1238 PrintIndentedVisit("KEY", properties->at(i)->key()); 1239 PrintIndentedVisit("VALUE", properties->at(i)->value()); 1240 } 1241} 1242 1243 1244void AstPrinter::VisitArrayLiteral(ArrayLiteral* node) { 1245 IndentedScope array_indent(this, "ARRAY LITERAL", node->position()); 1246 if (node->values()->length() > 0) { 1247 IndentedScope indent(this, "VALUES", node->position()); 1248 for (int i = 0; i < node->values()->length(); i++) { 1249 Visit(node->values()->at(i)); 1250 } 1251 } 1252} 1253 1254 1255void AstPrinter::VisitVariableProxy(VariableProxy* node) { 1256 base::EmbeddedVector<char, 128> buf; 1257 int pos = SNPrintF(buf, "VAR PROXY"); 1258 1259 if (!node->is_resolved()) { 1260 SNPrintF(buf + pos, " unresolved"); 1261 PrintLiteralWithModeIndented(buf.begin(), nullptr, node->raw_name()); 1262 } else { 1263 Variable* var = node->var(); 1264 switch (var->location()) { 1265 case VariableLocation::UNALLOCATED: 1266 SNPrintF(buf + pos, " unallocated"); 1267 break; 1268 case VariableLocation::PARAMETER: 1269 SNPrintF(buf + pos, " parameter[%d]", var->index()); 1270 break; 1271 case VariableLocation::LOCAL: 1272 SNPrintF(buf + pos, " local[%d]", var->index()); 1273 break; 1274 case VariableLocation::CONTEXT: 1275 SNPrintF(buf + pos, " context[%d]", var->index()); 1276 break; 1277 case VariableLocation::LOOKUP: 1278 SNPrintF(buf + pos, " lookup"); 1279 break; 1280 case VariableLocation::MODULE: 1281 SNPrintF(buf + pos, " module"); 1282 break; 1283 case VariableLocation::REPL_GLOBAL: 1284 SNPrintF(buf + pos, " repl global[%d]", var->index()); 1285 break; 1286 } 1287 PrintLiteralWithModeIndented(buf.begin(), var, node->raw_name()); 1288 } 1289} 1290 1291 1292void AstPrinter::VisitAssignment(Assignment* node) { 1293 IndentedScope indent(this, Token::Name(node->op()), node->position()); 1294 Visit(node->target()); 1295 Visit(node->value()); 1296} 1297 1298void AstPrinter::VisitCompoundAssignment(CompoundAssignment* node) { 1299 VisitAssignment(node); 1300} 1301 1302void AstPrinter::VisitYield(Yield* node) { 1303 base::EmbeddedVector<char, 128> buf; 1304 SNPrintF(buf, "YIELD"); 1305 IndentedScope indent(this, buf.begin(), node->position()); 1306 Visit(node->expression()); 1307} 1308 1309void AstPrinter::VisitYieldStar(YieldStar* node) { 1310 base::EmbeddedVector<char, 128> buf; 1311 SNPrintF(buf, "YIELD_STAR"); 1312 IndentedScope indent(this, buf.begin(), node->position()); 1313 Visit(node->expression()); 1314} 1315 1316void AstPrinter::VisitAwait(Await* node) { 1317 base::EmbeddedVector<char, 128> buf; 1318 SNPrintF(buf, "AWAIT"); 1319 IndentedScope indent(this, buf.begin(), node->position()); 1320 Visit(node->expression()); 1321} 1322 1323void AstPrinter::VisitThrow(Throw* node) { 1324 IndentedScope indent(this, "THROW", node->position()); 1325 Visit(node->exception()); 1326} 1327 1328void AstPrinter::VisitOptionalChain(OptionalChain* node) { 1329 IndentedScope indent(this, "OPTIONAL_CHAIN", node->position()); 1330 Visit(node->expression()); 1331} 1332 1333void AstPrinter::VisitProperty(Property* node) { 1334 base::EmbeddedVector<char, 128> buf; 1335 SNPrintF(buf, "PROPERTY"); 1336 IndentedScope indent(this, buf.begin(), node->position()); 1337 1338 Visit(node->obj()); 1339 AssignType type = Property::GetAssignType(node); 1340 switch (type) { 1341 case NAMED_PROPERTY: 1342 case NAMED_SUPER_PROPERTY: { 1343 PrintLiteralIndented("NAME", node->key()->AsLiteral(), false); 1344 break; 1345 } 1346 case PRIVATE_METHOD: { 1347 PrintIndentedVisit("PRIVATE_METHOD", node->key()); 1348 break; 1349 } 1350 case PRIVATE_GETTER_ONLY: { 1351 PrintIndentedVisit("PRIVATE_GETTER_ONLY", node->key()); 1352 break; 1353 } 1354 case PRIVATE_SETTER_ONLY: { 1355 PrintIndentedVisit("PRIVATE_SETTER_ONLY", node->key()); 1356 break; 1357 } 1358 case PRIVATE_GETTER_AND_SETTER: { 1359 PrintIndentedVisit("PRIVATE_GETTER_AND_SETTER", node->key()); 1360 break; 1361 } 1362 case KEYED_PROPERTY: 1363 case KEYED_SUPER_PROPERTY: { 1364 PrintIndentedVisit("KEY", node->key()); 1365 break; 1366 } 1367 case NON_PROPERTY: 1368 UNREACHABLE(); 1369 } 1370} 1371 1372void AstPrinter::VisitCall(Call* node) { 1373 base::EmbeddedVector<char, 128> buf; 1374 SNPrintF(buf, "CALL"); 1375 IndentedScope indent(this, buf.begin()); 1376 1377 Visit(node->expression()); 1378 PrintArguments(node->arguments()); 1379} 1380 1381 1382void AstPrinter::VisitCallNew(CallNew* node) { 1383 IndentedScope indent(this, "CALL NEW", node->position()); 1384 Visit(node->expression()); 1385 PrintArguments(node->arguments()); 1386} 1387 1388 1389void AstPrinter::VisitCallRuntime(CallRuntime* node) { 1390 base::EmbeddedVector<char, 128> buf; 1391 SNPrintF(buf, "CALL RUNTIME %s%s", node->debug_name(), 1392 node->is_jsruntime() ? " (JS function)" : ""); 1393 IndentedScope indent(this, buf.begin(), node->position()); 1394 PrintArguments(node->arguments()); 1395} 1396 1397 1398void AstPrinter::VisitUnaryOperation(UnaryOperation* node) { 1399 IndentedScope indent(this, Token::Name(node->op()), node->position()); 1400 Visit(node->expression()); 1401} 1402 1403 1404void AstPrinter::VisitCountOperation(CountOperation* node) { 1405 base::EmbeddedVector<char, 128> buf; 1406 SNPrintF(buf, "%s %s", (node->is_prefix() ? "PRE" : "POST"), 1407 Token::Name(node->op())); 1408 IndentedScope indent(this, buf.begin(), node->position()); 1409 Visit(node->expression()); 1410} 1411 1412 1413void AstPrinter::VisitBinaryOperation(BinaryOperation* node) { 1414 IndentedScope indent(this, Token::Name(node->op()), node->position()); 1415 Visit(node->left()); 1416 Visit(node->right()); 1417} 1418 1419void AstPrinter::VisitNaryOperation(NaryOperation* node) { 1420 IndentedScope indent(this, Token::Name(node->op()), node->position()); 1421 Visit(node->first()); 1422 for (size_t i = 0; i < node->subsequent_length(); ++i) { 1423 Visit(node->subsequent(i)); 1424 } 1425} 1426 1427void AstPrinter::VisitCompareOperation(CompareOperation* node) { 1428 IndentedScope indent(this, Token::Name(node->op()), node->position()); 1429 Visit(node->left()); 1430 Visit(node->right()); 1431} 1432 1433 1434void AstPrinter::VisitSpread(Spread* node) { 1435 IndentedScope indent(this, "SPREAD", node->position()); 1436 Visit(node->expression()); 1437} 1438 1439void AstPrinter::VisitEmptyParentheses(EmptyParentheses* node) { 1440 IndentedScope indent(this, "()", node->position()); 1441} 1442 1443void AstPrinter::VisitGetTemplateObject(GetTemplateObject* node) { 1444 IndentedScope indent(this, "GET-TEMPLATE-OBJECT", node->position()); 1445} 1446 1447void AstPrinter::VisitTemplateLiteral(TemplateLiteral* node) { 1448 IndentedScope indent(this, "TEMPLATE-LITERAL", node->position()); 1449 const AstRawString* string = node->string_parts()->first(); 1450 if (!string->IsEmpty()) PrintLiteralIndented("SPAN", string, true); 1451 for (int i = 0; i < node->substitutions()->length();) { 1452 PrintIndentedVisit("EXPR", node->substitutions()->at(i++)); 1453 if (i < node->string_parts()->length()) { 1454 string = node->string_parts()->at(i); 1455 if (!string->IsEmpty()) PrintLiteralIndented("SPAN", string, true); 1456 } 1457 } 1458} 1459 1460void AstPrinter::VisitImportCallExpression(ImportCallExpression* node) { 1461 IndentedScope indent(this, "IMPORT-CALL", node->position()); 1462 Visit(node->specifier()); 1463 if (node->import_assertions()) { 1464 Visit(node->import_assertions()); 1465 } 1466} 1467 1468void AstPrinter::VisitThisExpression(ThisExpression* node) { 1469 IndentedScope indent(this, "THIS-EXPRESSION", node->position()); 1470} 1471 1472void AstPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) { 1473 IndentedScope indent(this, "SUPER-PROPERTY-REFERENCE", node->position()); 1474} 1475 1476 1477void AstPrinter::VisitSuperCallReference(SuperCallReference* node) { 1478 IndentedScope indent(this, "SUPER-CALL-REFERENCE", node->position()); 1479} 1480 1481 1482#endif // DEBUG 1483 1484} // namespace internal 1485} // namespace v8 1486