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