1// Copyright 2017 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/d8-console.h"
6#include "src/d8.h"
7#include "src/isolate.h"
8
9namespace v8 {
10
11namespace {
12void WriteToFile(const char* prefix, FILE* file, Isolate* isolate,
13 const debug::ConsoleCallArguments& args) {
14 if (prefix) fprintf(file, "%s: ", prefix);
15 for (int i = 0; i < args.Length(); i++) {
16 HandleScope handle_scope(isolate);
17 if (i > 0) fprintf(file, " ");
18
19 Local<Value> arg = args[i];
20 Local<String> str_obj;
21
22 if (arg->IsSymbol()) arg = Local<Symbol>::Cast(arg)->Name();
23 if (!arg->ToString(isolate->GetCurrentContext()).ToLocal(&str_obj)) return;
24
25 v8::String::Utf8Value str(isolate, str_obj);
26 int n = static_cast<int>(fwrite(*str, sizeof(**str), str.length(), file));
27 if (n != str.length()) {
28 printf("Error in fwrite\n");
29 base::OS::ExitProcess(1);
30 }
31 }
32 fprintf(file, "\n");
33}
34} // anonymous namespace
35
36D8Console::D8Console(Isolate* isolate) : isolate_(isolate) {
37 default_timer_ = base::TimeTicks::HighResolutionNow();
38}
39
40void D8Console::Assert(const debug::ConsoleCallArguments& args,
41 const v8::debug::ConsoleContext&) {
42 // If no arguments given, the "first" argument is undefined which is
43 // false-ish.
44 if (args.Length() > 0 && args[0]->BooleanValue(isolate_)) return;
45 WriteToFile("console.assert", stdout, isolate_, args);
46 isolate_->ThrowException(v8::Exception::Error(
47 v8::String::NewFromUtf8(isolate_, "console.assert failed",
48 v8::NewStringType::kNormal)
49 .ToLocalChecked()));
50}
51
52void D8Console::Log(const debug::ConsoleCallArguments& args,
53 const v8::debug::ConsoleContext&) {
54 WriteToFile(nullptr, stdout, isolate_, args);
55}
56
57void D8Console::Error(const debug::ConsoleCallArguments& args,
58 const v8::debug::ConsoleContext&) {
59 WriteToFile("console.error", stderr, isolate_, args);
60}
61
62void D8Console::Warn(const debug::ConsoleCallArguments& args,
63 const v8::debug::ConsoleContext&) {
64 WriteToFile("console.warn", stdout, isolate_, args);
65}
66
67void D8Console::Info(const debug::ConsoleCallArguments& args,
68 const v8::debug::ConsoleContext&) {
69 WriteToFile("console.info", stdout, isolate_, args);
70}
71
72void D8Console::Debug(const debug::ConsoleCallArguments& args,
73 const v8::debug::ConsoleContext&) {
74 WriteToFile("console.debug", stdout, isolate_, args);
75}
76
77void D8Console::Time(const debug::ConsoleCallArguments& args,
78 const v8::debug::ConsoleContext&) {
79 if (args.Length() == 0) {
80 default_timer_ = base::TimeTicks::HighResolutionNow();
81 } else {
82 Local<Value> arg = args[0];
83 Local<String> label;
84 v8::TryCatch try_catch(isolate_);
85 if (!arg->ToString(isolate_->GetCurrentContext()).ToLocal(&label)) return;
86 v8::String::Utf8Value utf8(isolate_, label);
87 std::string string(*utf8);
88 auto find = timers_.find(string);
89 if (find != timers_.end()) {
90 find->second = base::TimeTicks::HighResolutionNow();
91 } else {
92 timers_.insert(std::pair<std::string, base::TimeTicks>(
93 string, base::TimeTicks::HighResolutionNow()));
94 }
95 }
96}
97
98void D8Console::TimeEnd(const debug::ConsoleCallArguments& args,
99 const v8::debug::ConsoleContext&) {
100 base::TimeDelta delta;
101 if (args.Length() == 0) {
102 delta = base::TimeTicks::HighResolutionNow() - default_timer_;
103 printf("console.timeEnd: default, %f\n", delta.InMillisecondsF());
104 } else {
105 base::TimeTicks now = base::TimeTicks::HighResolutionNow();
106 Local<Value> arg = args[0];
107 Local<String> label;
108 v8::TryCatch try_catch(isolate_);
109 if (!arg->ToString(isolate_->GetCurrentContext()).ToLocal(&label)) return;
110 v8::String::Utf8Value utf8(isolate_, label);
111 std::string string(*utf8);
112 auto find = timers_.find(string);
113 if (find != timers_.end()) {
114 delta = now - find->second;
115 }
116 printf("console.timeEnd: %s, %f\n", *utf8, delta.InMillisecondsF());
117 }
118}
119
120void D8Console::TimeStamp(const debug::ConsoleCallArguments& args,
121 const v8::debug::ConsoleContext&) {
122 base::TimeDelta delta = base::TimeTicks::HighResolutionNow() - default_timer_;
123 if (args.Length() == 0) {
124 printf("console.timeStamp: default, %f\n", delta.InMillisecondsF());
125 } else {
126 Local<Value> arg = args[0];
127 Local<String> label;
128 v8::TryCatch try_catch(isolate_);
129 if (!arg->ToString(isolate_->GetCurrentContext()).ToLocal(&label)) return;
130 v8::String::Utf8Value utf8(isolate_, label);
131 std::string string(*utf8);
132 printf("console.timeStamp: %s, %f\n", *utf8, delta.InMillisecondsF());
133 }
134}
135
136void D8Console::Trace(const debug::ConsoleCallArguments& args,
137 const v8::debug::ConsoleContext&) {
138 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate_);
139 i_isolate->PrintStack(stderr, i::Isolate::kPrintStackConcise);
140}
141
142} // namespace v8
143