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
9 namespace v8 {
10
11 namespace {
WriteToFile(const char * prefix,FILE * file,Isolate * isolate,const debug::ConsoleCallArguments & args)12 void 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
D8Console(Isolate * isolate)36 D8Console::D8Console(Isolate* isolate) : isolate_(isolate) {
37 default_timer_ = base::TimeTicks::HighResolutionNow();
38 }
39
Assert(const debug::ConsoleCallArguments & args,const v8::debug::ConsoleContext &)40 void D8Console::Assert(const debug::ConsoleCallArguments& args,
41 const v8::debug::ConsoleContext&) {
42 Local<Boolean> arg;
43 if (args.Length() > 0) {
44 if (!args[0]->ToBoolean(isolate_->GetCurrentContext()).ToLocal(&arg)) {
45 return;
46 }
47 } else {
48 // No arguments given, the "first" argument is undefined which is false-ish.
49 arg = v8::False(isolate_);
50 }
51 if (arg->IsTrue()) return;
52 WriteToFile("console.assert", stdout, isolate_, args);
53 isolate_->ThrowException(v8::Exception::Error(
54 v8::String::NewFromUtf8(isolate_, "console.assert failed",
55 v8::NewStringType::kNormal)
56 .ToLocalChecked()));
57 }
58
Log(const debug::ConsoleCallArguments & args,const v8::debug::ConsoleContext &)59 void D8Console::Log(const debug::ConsoleCallArguments& args,
60 const v8::debug::ConsoleContext&) {
61 WriteToFile(nullptr, stdout, isolate_, args);
62 }
63
Error(const debug::ConsoleCallArguments & args,const v8::debug::ConsoleContext &)64 void D8Console::Error(const debug::ConsoleCallArguments& args,
65 const v8::debug::ConsoleContext&) {
66 WriteToFile("console.error", stderr, isolate_, args);
67 }
68
Warn(const debug::ConsoleCallArguments & args,const v8::debug::ConsoleContext &)69 void D8Console::Warn(const debug::ConsoleCallArguments& args,
70 const v8::debug::ConsoleContext&) {
71 WriteToFile("console.warn", stdout, isolate_, args);
72 }
73
Info(const debug::ConsoleCallArguments & args,const v8::debug::ConsoleContext &)74 void D8Console::Info(const debug::ConsoleCallArguments& args,
75 const v8::debug::ConsoleContext&) {
76 WriteToFile("console.info", stdout, isolate_, args);
77 }
78
Debug(const debug::ConsoleCallArguments & args,const v8::debug::ConsoleContext &)79 void D8Console::Debug(const debug::ConsoleCallArguments& args,
80 const v8::debug::ConsoleContext&) {
81 WriteToFile("console.debug", stdout, isolate_, args);
82 }
83
Time(const debug::ConsoleCallArguments & args,const v8::debug::ConsoleContext &)84 void D8Console::Time(const debug::ConsoleCallArguments& args,
85 const v8::debug::ConsoleContext&) {
86 if (args.Length() == 0) {
87 default_timer_ = base::TimeTicks::HighResolutionNow();
88 } else {
89 Local<Value> arg = args[0];
90 Local<String> label;
91 v8::TryCatch try_catch(isolate_);
92 if (!arg->ToString(isolate_->GetCurrentContext()).ToLocal(&label)) return;
93 v8::String::Utf8Value utf8(isolate_, label);
94 std::string string(*utf8);
95 auto find = timers_.find(string);
96 if (find != timers_.end()) {
97 find->second = base::TimeTicks::HighResolutionNow();
98 } else {
99 timers_.insert(std::pair<std::string, base::TimeTicks>(
100 string, base::TimeTicks::HighResolutionNow()));
101 }
102 }
103 }
104
TimeEnd(const debug::ConsoleCallArguments & args,const v8::debug::ConsoleContext &)105 void D8Console::TimeEnd(const debug::ConsoleCallArguments& args,
106 const v8::debug::ConsoleContext&) {
107 base::TimeDelta delta;
108 if (args.Length() == 0) {
109 delta = base::TimeTicks::HighResolutionNow() - default_timer_;
110 printf("console.timeEnd: default, %f\n", delta.InMillisecondsF());
111 } else {
112 base::TimeTicks now = base::TimeTicks::HighResolutionNow();
113 Local<Value> arg = args[0];
114 Local<String> label;
115 v8::TryCatch try_catch(isolate_);
116 if (!arg->ToString(isolate_->GetCurrentContext()).ToLocal(&label)) return;
117 v8::String::Utf8Value utf8(isolate_, label);
118 std::string string(*utf8);
119 auto find = timers_.find(string);
120 if (find != timers_.end()) {
121 delta = now - find->second;
122 }
123 printf("console.timeEnd: %s, %f\n", *utf8, delta.InMillisecondsF());
124 }
125 }
126
TimeStamp(const debug::ConsoleCallArguments & args,const v8::debug::ConsoleContext &)127 void D8Console::TimeStamp(const debug::ConsoleCallArguments& args,
128 const v8::debug::ConsoleContext&) {
129 base::TimeDelta delta = base::TimeTicks::HighResolutionNow() - default_timer_;
130 if (args.Length() == 0) {
131 printf("console.timeStamp: default, %f\n", delta.InMillisecondsF());
132 } else {
133 Local<Value> arg = args[0];
134 Local<String> label;
135 v8::TryCatch try_catch(isolate_);
136 if (!arg->ToString(isolate_->GetCurrentContext()).ToLocal(&label)) return;
137 v8::String::Utf8Value utf8(isolate_, label);
138 std::string string(*utf8);
139 printf("console.timeStamp: %s, %f\n", *utf8, delta.InMillisecondsF());
140 }
141 }
142
Trace(const debug::ConsoleCallArguments & args,const v8::debug::ConsoleContext &)143 void D8Console::Trace(const debug::ConsoleCallArguments& args,
144 const v8::debug::ConsoleContext&) {
145 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate_);
146 i_isolate->PrintStack(stderr, i::Isolate::kPrintStackConcise);
147 }
148
149 } // namespace v8
150