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 { |
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 | |
36 | D8Console::D8Console(Isolate* isolate) : isolate_(isolate) { |
37 | default_timer_ = base::TimeTicks::HighResolutionNow(); |
38 | } |
39 | |
40 | void 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 | |
52 | void D8Console::Log(const debug::ConsoleCallArguments& args, |
53 | const v8::debug::ConsoleContext&) { |
54 | WriteToFile(nullptr, stdout, isolate_, args); |
55 | } |
56 | |
57 | void D8Console::Error(const debug::ConsoleCallArguments& args, |
58 | const v8::debug::ConsoleContext&) { |
59 | WriteToFile("console.error" , stderr, isolate_, args); |
60 | } |
61 | |
62 | void D8Console::Warn(const debug::ConsoleCallArguments& args, |
63 | const v8::debug::ConsoleContext&) { |
64 | WriteToFile("console.warn" , stdout, isolate_, args); |
65 | } |
66 | |
67 | void D8Console::Info(const debug::ConsoleCallArguments& args, |
68 | const v8::debug::ConsoleContext&) { |
69 | WriteToFile("console.info" , stdout, isolate_, args); |
70 | } |
71 | |
72 | void D8Console::Debug(const debug::ConsoleCallArguments& args, |
73 | const v8::debug::ConsoleContext&) { |
74 | WriteToFile("console.debug" , stdout, isolate_, args); |
75 | } |
76 | |
77 | void 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 | |
98 | void 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 | |
120 | void 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 | |
136 | void 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 | |