LCOV - code coverage report
Current view: top level - src/ast - prettyprinter.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 299 351 85.2 %
Date: 2019-03-21 Functions: 46 67 68.7 %

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

Generated by: LCOV version 1.10