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 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 59 void D8Console::Log(const debug::ConsoleCallArguments& args, 60 const v8::debug::ConsoleContext&) { 61 WriteToFile(nullptr, stdout, isolate_, args); 62 } 63 64 void D8Console::Error(const debug::ConsoleCallArguments& args, 65 const v8::debug::ConsoleContext&) { 66 WriteToFile("console.error", stderr, isolate_, args); 67 } 68 69 void D8Console::Warn(const debug::ConsoleCallArguments& args, 70 const v8::debug::ConsoleContext&) { 71 WriteToFile("console.warn", stdout, isolate_, args); 72 } 73 74 void D8Console::Info(const debug::ConsoleCallArguments& args, 75 const v8::debug::ConsoleContext&) { 76 WriteToFile("console.info", stdout, isolate_, args); 77 } 78 79 void D8Console::Debug(const debug::ConsoleCallArguments& args, 80 const v8::debug::ConsoleContext&) { 81 WriteToFile("console.debug", stdout, isolate_, args); 82 } 83 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 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 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 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