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