• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "env.h"
2 #include "node_errors.h"
3 #include "node_internals.h"
4 #include "node_options.h"
5 #include "node_report.h"
6 #include "util-inl.h"
7 
8 #include "handle_wrap.h"
9 #include "node_buffer.h"
10 #include "stream_base-inl.h"
11 #include "stream_wrap.h"
12 
13 #include <v8.h>
14 #include <atomic>
15 #include <sstream>
16 
17 namespace report {
18 using node::Environment;
19 using node::Mutex;
20 using node::Utf8Value;
21 using v8::Context;
22 using v8::FunctionCallbackInfo;
23 using v8::HandleScope;
24 using v8::Isolate;
25 using v8::Local;
26 using v8::Object;
27 using v8::String;
28 using v8::Value;
29 
WriteReport(const FunctionCallbackInfo<Value> & info)30 void WriteReport(const FunctionCallbackInfo<Value>& info) {
31   Environment* env = Environment::GetCurrent(info);
32   Isolate* isolate = env->isolate();
33   HandleScope scope(isolate);
34   std::string filename;
35   Local<Object> error;
36 
37   CHECK_EQ(info.Length(), 4);
38   String::Utf8Value message(isolate, info[0].As<String>());
39   String::Utf8Value trigger(isolate, info[1].As<String>());
40 
41   if (info[2]->IsString())
42     filename = *String::Utf8Value(isolate, info[2]);
43   if (!info[3].IsEmpty() && info[3]->IsObject())
44     error = info[3].As<Object>();
45   else
46     error = Local<Object>();
47 
48   filename = TriggerNodeReport(
49       isolate, env, *message, *trigger, filename, error);
50   // Return value is the report filename
51   info.GetReturnValue().Set(
52       String::NewFromUtf8(isolate, filename.c_str()).ToLocalChecked());
53 }
54 
55 // External JavaScript API for returning a report
GetReport(const FunctionCallbackInfo<Value> & info)56 void GetReport(const FunctionCallbackInfo<Value>& info) {
57   Environment* env = Environment::GetCurrent(info);
58   Isolate* isolate = env->isolate();
59   HandleScope scope(isolate);
60   Local<Object> error;
61   std::ostringstream out;
62 
63   CHECK_EQ(info.Length(), 1);
64   if (!info[0].IsEmpty() && info[0]->IsObject())
65     error = info[0].As<Object>();
66   else
67     error = Local<Object>();
68 
69   GetNodeReport(
70       isolate, env, "JavaScript API", __func__, error, out);
71 
72   // Return value is the contents of a report as a string.
73   info.GetReturnValue().Set(
74       String::NewFromUtf8(isolate, out.str().c_str()).ToLocalChecked());
75 }
76 
GetCompact(const FunctionCallbackInfo<Value> & info)77 static void GetCompact(const FunctionCallbackInfo<Value>& info) {
78   node::Mutex::ScopedLock lock(node::per_process::cli_options_mutex);
79   info.GetReturnValue().Set(node::per_process::cli_options->report_compact);
80 }
81 
SetCompact(const FunctionCallbackInfo<Value> & info)82 static void SetCompact(const FunctionCallbackInfo<Value>& info) {
83   node::Mutex::ScopedLock lock(node::per_process::cli_options_mutex);
84   Environment* env = Environment::GetCurrent(info);
85   Isolate* isolate = env->isolate();
86   bool compact = info[0]->ToBoolean(isolate)->Value();
87   node::per_process::cli_options->report_compact = compact;
88 }
89 
GetDirectory(const FunctionCallbackInfo<Value> & info)90 static void GetDirectory(const FunctionCallbackInfo<Value>& info) {
91   node::Mutex::ScopedLock lock(node::per_process::cli_options_mutex);
92   Environment* env = Environment::GetCurrent(info);
93   std::string directory = node::per_process::cli_options->report_directory;
94   auto result = String::NewFromUtf8(env->isolate(), directory.c_str());
95   info.GetReturnValue().Set(result.ToLocalChecked());
96 }
97 
SetDirectory(const FunctionCallbackInfo<Value> & info)98 static void SetDirectory(const FunctionCallbackInfo<Value>& info) {
99   node::Mutex::ScopedLock lock(node::per_process::cli_options_mutex);
100   Environment* env = Environment::GetCurrent(info);
101   CHECK(info[0]->IsString());
102   Utf8Value dir(env->isolate(), info[0].As<String>());
103   node::per_process::cli_options->report_directory = *dir;
104 }
105 
GetFilename(const FunctionCallbackInfo<Value> & info)106 static void GetFilename(const FunctionCallbackInfo<Value>& info) {
107   node::Mutex::ScopedLock lock(node::per_process::cli_options_mutex);
108   Environment* env = Environment::GetCurrent(info);
109   std::string filename = node::per_process::cli_options->report_filename;
110   auto result = String::NewFromUtf8(env->isolate(), filename.c_str());
111   info.GetReturnValue().Set(result.ToLocalChecked());
112 }
113 
SetFilename(const FunctionCallbackInfo<Value> & info)114 static void SetFilename(const FunctionCallbackInfo<Value>& info) {
115   node::Mutex::ScopedLock lock(node::per_process::cli_options_mutex);
116   Environment* env = Environment::GetCurrent(info);
117   CHECK(info[0]->IsString());
118   Utf8Value name(env->isolate(), info[0].As<String>());
119   node::per_process::cli_options->report_filename = *name;
120 }
121 
GetSignal(const FunctionCallbackInfo<Value> & info)122 static void GetSignal(const FunctionCallbackInfo<Value>& info) {
123   Environment* env = Environment::GetCurrent(info);
124   std::string signal = env->isolate_data()->options()->report_signal;
125   auto result = String::NewFromUtf8(env->isolate(), signal.c_str());
126   info.GetReturnValue().Set(result.ToLocalChecked());
127 }
128 
SetSignal(const FunctionCallbackInfo<Value> & info)129 static void SetSignal(const FunctionCallbackInfo<Value>& info) {
130   Environment* env = Environment::GetCurrent(info);
131   CHECK(info[0]->IsString());
132   Utf8Value signal(env->isolate(), info[0].As<String>());
133   env->isolate_data()->options()->report_signal = *signal;
134 }
135 
ShouldReportOnFatalError(const FunctionCallbackInfo<Value> & info)136 static void ShouldReportOnFatalError(const FunctionCallbackInfo<Value>& info) {
137   Mutex::ScopedLock lock(node::per_process::cli_options_mutex);
138   info.GetReturnValue().Set(
139       node::per_process::cli_options->report_on_fatalerror);
140 }
141 
SetReportOnFatalError(const FunctionCallbackInfo<Value> & info)142 static void SetReportOnFatalError(const FunctionCallbackInfo<Value>& info) {
143   CHECK(info[0]->IsBoolean());
144   Mutex::ScopedLock lock(node::per_process::cli_options_mutex);
145   node::per_process::cli_options->report_on_fatalerror = info[0]->IsTrue();
146 }
147 
ShouldReportOnSignal(const FunctionCallbackInfo<Value> & info)148 static void ShouldReportOnSignal(const FunctionCallbackInfo<Value>& info) {
149   Environment* env = Environment::GetCurrent(info);
150   info.GetReturnValue().Set(env->isolate_data()->options()->report_on_signal);
151 }
152 
SetReportOnSignal(const FunctionCallbackInfo<Value> & info)153 static void SetReportOnSignal(const FunctionCallbackInfo<Value>& info) {
154   Environment* env = Environment::GetCurrent(info);
155   CHECK(info[0]->IsBoolean());
156   env->isolate_data()->options()->report_on_signal = info[0]->IsTrue();
157 }
158 
ShouldReportOnUncaughtException(const FunctionCallbackInfo<Value> & info)159 static void ShouldReportOnUncaughtException(
160     const FunctionCallbackInfo<Value>& info) {
161   Environment* env = Environment::GetCurrent(info);
162   info.GetReturnValue().Set(
163       env->isolate_data()->options()->report_uncaught_exception);
164 }
165 
SetReportOnUncaughtException(const FunctionCallbackInfo<Value> & info)166 static void SetReportOnUncaughtException(
167     const FunctionCallbackInfo<Value>& info) {
168   Environment* env = Environment::GetCurrent(info);
169   CHECK(info[0]->IsBoolean());
170   env->isolate_data()->options()->report_uncaught_exception = info[0]->IsTrue();
171 }
172 
Initialize(Local<Object> exports,Local<Value> unused,Local<Context> context,void * priv)173 static void Initialize(Local<Object> exports,
174                        Local<Value> unused,
175                        Local<Context> context,
176                        void* priv) {
177   Environment* env = Environment::GetCurrent(context);
178 
179   env->SetMethod(exports, "writeReport", WriteReport);
180   env->SetMethod(exports, "getReport", GetReport);
181   env->SetMethod(exports, "getCompact", GetCompact);
182   env->SetMethod(exports, "setCompact", SetCompact);
183   env->SetMethod(exports, "getDirectory", GetDirectory);
184   env->SetMethod(exports, "setDirectory", SetDirectory);
185   env->SetMethod(exports, "getFilename", GetFilename);
186   env->SetMethod(exports, "setFilename", SetFilename);
187   env->SetMethod(exports, "getSignal", GetSignal);
188   env->SetMethod(exports, "setSignal", SetSignal);
189   env->SetMethod(exports, "shouldReportOnFatalError", ShouldReportOnFatalError);
190   env->SetMethod(exports, "setReportOnFatalError", SetReportOnFatalError);
191   env->SetMethod(exports, "shouldReportOnSignal", ShouldReportOnSignal);
192   env->SetMethod(exports, "setReportOnSignal", SetReportOnSignal);
193   env->SetMethod(exports, "shouldReportOnUncaughtException",
194                  ShouldReportOnUncaughtException);
195   env->SetMethod(exports, "setReportOnUncaughtException",
196                  SetReportOnUncaughtException);
197 }
198 
199 }  // namespace report
200 
201 NODE_MODULE_CONTEXT_AWARE_INTERNAL(report, report::Initialize)
202