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