| #include "env.h" |
| #include "node_errors.h" |
| #include "node_external_reference.h" |
| #include "node_internals.h" |
| #include "node_options.h" |
| #include "node_report.h" |
| #include "util-inl.h" |
| |
| #include "handle_wrap.h" |
| #include "node_buffer.h" |
| #include "stream_base-inl.h" |
| #include "stream_wrap.h" |
| |
| #include <v8.h> |
| #include <atomic> |
| #include <sstream> |
| |
| namespace node { |
| namespace report { |
| using v8::Context; |
| using v8::FunctionCallbackInfo; |
| using v8::HandleScope; |
| using v8::Isolate; |
| using v8::Local; |
| using v8::Object; |
| using v8::String; |
| using v8::Value; |
| |
| void WriteReport(const FunctionCallbackInfo<Value>& info) { |
| Environment* env = Environment::GetCurrent(info); |
| Isolate* isolate = env->isolate(); |
| HandleScope scope(isolate); |
| std::string filename; |
| Local<Value> error; |
| |
| CHECK_EQ(info.Length(), 4); |
| Utf8Value message(isolate, info[0].As<String>()); |
| Utf8Value trigger(isolate, info[1].As<String>()); |
| |
| if (info[2]->IsString()) filename = Utf8Value(isolate, info[2]).ToString(); |
| if (!info[3].IsEmpty()) |
| error = info[3]; |
| else |
| error = Local<Value>(); |
| |
| // Return value is the report filename |
| filename = TriggerNodeReport( |
| env, message.ToStringView(), trigger.ToStringView(), filename, error); |
| Local<Value> ret; |
| if (ToV8Value(env->context(), filename, env->isolate()).ToLocal(&ret)) { |
| info.GetReturnValue().Set(ret); |
| } |
| } |
| |
| // External JavaScript API for returning a report |
| void GetReport(const FunctionCallbackInfo<Value>& info) { |
| Environment* env = Environment::GetCurrent(info); |
| Isolate* isolate = env->isolate(); |
| HandleScope scope(isolate); |
| Local<Object> error; |
| std::ostringstream out; |
| |
| CHECK_EQ(info.Length(), 1); |
| if (!info[0].IsEmpty() && info[0]->IsObject()) |
| error = info[0].As<Object>(); |
| else |
| error = Local<Object>(); |
| |
| GetNodeReport(env, "JavaScript API", __func__, error, out); |
| |
| // Return value is the contents of a report as a string. |
| Local<Value> ret; |
| if (ToV8Value(env->context(), out.str(), env->isolate()).ToLocal(&ret)) { |
| info.GetReturnValue().Set(ret); |
| } |
| } |
| |
| static void GetCompact(const FunctionCallbackInfo<Value>& info) { |
| Mutex::ScopedLock lock(per_process::cli_options_mutex); |
| info.GetReturnValue().Set(per_process::cli_options->report_compact); |
| } |
| |
| static void SetCompact(const FunctionCallbackInfo<Value>& info) { |
| Mutex::ScopedLock lock(per_process::cli_options_mutex); |
| Isolate* isolate = info.GetIsolate(); |
| bool compact = info[0]->ToBoolean(isolate)->Value(); |
| per_process::cli_options->report_compact = compact; |
| } |
| |
| static void GetExcludeNetwork(const FunctionCallbackInfo<Value>& info) { |
| Environment* env = Environment::GetCurrent(info); |
| info.GetReturnValue().Set(env->options()->report_exclude_network); |
| } |
| |
| static void SetExcludeNetwork(const FunctionCallbackInfo<Value>& info) { |
| Environment* env = Environment::GetCurrent(info); |
| CHECK(info[0]->IsBoolean()); |
| env->options()->report_exclude_network = info[0]->IsTrue(); |
| } |
| |
| static void GetExcludeEnv(const FunctionCallbackInfo<Value>& info) { |
| Environment* env = Environment::GetCurrent(info); |
| info.GetReturnValue().Set(env->report_exclude_env()); |
| } |
| |
| static void SetExcludeEnv(const FunctionCallbackInfo<Value>& info) { |
| Environment* env = Environment::GetCurrent(info); |
| CHECK(info[0]->IsBoolean()); |
| env->options()->report_exclude_env = info[0]->IsTrue(); |
| } |
| |
| static void GetDirectory(const FunctionCallbackInfo<Value>& info) { |
| Mutex::ScopedLock lock(per_process::cli_options_mutex); |
| Environment* env = Environment::GetCurrent(info); |
| std::string directory = per_process::cli_options->report_directory; |
| Local<Value> ret; |
| if (ToV8Value(env->context(), directory, env->isolate()).ToLocal(&ret)) { |
| info.GetReturnValue().Set(ret); |
| } |
| } |
| |
| static void SetDirectory(const FunctionCallbackInfo<Value>& info) { |
| Mutex::ScopedLock lock(per_process::cli_options_mutex); |
| CHECK(info[0]->IsString()); |
| Utf8Value dir(info.GetIsolate(), info[0].As<String>()); |
| per_process::cli_options->report_directory = *dir; |
| } |
| |
| static void GetFilename(const FunctionCallbackInfo<Value>& info) { |
| Mutex::ScopedLock lock(per_process::cli_options_mutex); |
| Environment* env = Environment::GetCurrent(info); |
| std::string filename = per_process::cli_options->report_filename; |
| Local<Value> ret; |
| if (ToV8Value(env->context(), filename, env->isolate()).ToLocal(&ret)) { |
| info.GetReturnValue().Set(ret); |
| } |
| } |
| |
| static void SetFilename(const FunctionCallbackInfo<Value>& info) { |
| Mutex::ScopedLock lock(per_process::cli_options_mutex); |
| CHECK(info[0]->IsString()); |
| Utf8Value name(info.GetIsolate(), info[0].As<String>()); |
| per_process::cli_options->report_filename = *name; |
| } |
| |
| static void GetSignal(const FunctionCallbackInfo<Value>& info) { |
| Environment* env = Environment::GetCurrent(info); |
| std::string signal = env->isolate_data()->options()->report_signal; |
| Local<Value> ret; |
| if (ToV8Value(env->context(), signal, env->isolate()).ToLocal(&ret)) { |
| info.GetReturnValue().Set(ret); |
| } |
| } |
| |
| static void SetSignal(const FunctionCallbackInfo<Value>& info) { |
| Environment* env = Environment::GetCurrent(info); |
| CHECK(info[0]->IsString()); |
| Utf8Value signal(env->isolate(), info[0].As<String>()); |
| env->isolate_data()->options()->report_signal = *signal; |
| } |
| |
| static void ShouldReportOnFatalError(const FunctionCallbackInfo<Value>& info) { |
| Mutex::ScopedLock lock(per_process::cli_options_mutex); |
| info.GetReturnValue().Set(per_process::cli_options->report_on_fatalerror); |
| } |
| |
| static void SetReportOnFatalError(const FunctionCallbackInfo<Value>& info) { |
| CHECK(info[0]->IsBoolean()); |
| Mutex::ScopedLock lock(per_process::cli_options_mutex); |
| per_process::cli_options->report_on_fatalerror = info[0]->IsTrue(); |
| } |
| |
| static void ShouldReportOnSignal(const FunctionCallbackInfo<Value>& info) { |
| Environment* env = Environment::GetCurrent(info); |
| info.GetReturnValue().Set(env->isolate_data()->options()->report_on_signal); |
| } |
| |
| static void SetReportOnSignal(const FunctionCallbackInfo<Value>& info) { |
| Environment* env = Environment::GetCurrent(info); |
| CHECK(info[0]->IsBoolean()); |
| env->isolate_data()->options()->report_on_signal = info[0]->IsTrue(); |
| } |
| |
| static void ShouldReportOnUncaughtException( |
| const FunctionCallbackInfo<Value>& info) { |
| Environment* env = Environment::GetCurrent(info); |
| info.GetReturnValue().Set( |
| env->isolate_data()->options()->report_uncaught_exception); |
| } |
| |
| static void SetReportOnUncaughtException( |
| const FunctionCallbackInfo<Value>& info) { |
| Environment* env = Environment::GetCurrent(info); |
| CHECK(info[0]->IsBoolean()); |
| env->isolate_data()->options()->report_uncaught_exception = info[0]->IsTrue(); |
| } |
| |
| static void Initialize(Local<Object> exports, |
| Local<Value> unused, |
| Local<Context> context, |
| void* priv) { |
| SetMethod(context, exports, "writeReport", WriteReport); |
| SetMethod(context, exports, "getReport", GetReport); |
| SetMethod(context, exports, "getCompact", GetCompact); |
| SetMethod(context, exports, "setCompact", SetCompact); |
| SetMethod(context, exports, "getExcludeNetwork", GetExcludeNetwork); |
| SetMethod(context, exports, "setExcludeNetwork", SetExcludeNetwork); |
| SetMethod(context, exports, "getExcludeEnv", GetExcludeEnv); |
| SetMethod(context, exports, "setExcludeEnv", SetExcludeEnv); |
| SetMethod(context, exports, "getDirectory", GetDirectory); |
| SetMethod(context, exports, "setDirectory", SetDirectory); |
| SetMethod(context, exports, "getFilename", GetFilename); |
| SetMethod(context, exports, "setFilename", SetFilename); |
| SetMethod(context, exports, "getSignal", GetSignal); |
| SetMethod(context, exports, "setSignal", SetSignal); |
| SetMethod( |
| context, exports, "shouldReportOnFatalError", ShouldReportOnFatalError); |
| SetMethod(context, exports, "setReportOnFatalError", SetReportOnFatalError); |
| SetMethod(context, exports, "shouldReportOnSignal", ShouldReportOnSignal); |
| SetMethod(context, exports, "setReportOnSignal", SetReportOnSignal); |
| SetMethod(context, |
| exports, |
| "shouldReportOnUncaughtException", |
| ShouldReportOnUncaughtException); |
| SetMethod(context, |
| exports, |
| "setReportOnUncaughtException", |
| SetReportOnUncaughtException); |
| } |
| |
| void RegisterExternalReferences(ExternalReferenceRegistry* registry) { |
| registry->Register(WriteReport); |
| registry->Register(GetReport); |
| registry->Register(GetCompact); |
| registry->Register(SetCompact); |
| registry->Register(GetExcludeNetwork); |
| registry->Register(SetExcludeNetwork); |
| registry->Register(GetExcludeEnv); |
| registry->Register(SetExcludeEnv); |
| registry->Register(GetDirectory); |
| registry->Register(SetDirectory); |
| registry->Register(GetFilename); |
| registry->Register(SetFilename); |
| registry->Register(GetSignal); |
| registry->Register(SetSignal); |
| registry->Register(ShouldReportOnFatalError); |
| registry->Register(SetReportOnFatalError); |
| registry->Register(ShouldReportOnSignal); |
| registry->Register(SetReportOnSignal); |
| registry->Register(ShouldReportOnUncaughtException); |
| registry->Register(SetReportOnUncaughtException); |
| } |
| |
| } // namespace report |
| } // namespace node |
| |
| NODE_BINDING_CONTEXT_AWARE_INTERNAL(report, node::report::Initialize) |
| NODE_BINDING_EXTERNAL_REFERENCE(report, |
| node::report::RegisterExternalReferences) |