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