• 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(), v8::NewStringType::kNormal)
53           .ToLocalChecked());
54 }
55 
56 // External JavaScript API for returning a report
GetReport(const FunctionCallbackInfo<Value> & info)57 void GetReport(const FunctionCallbackInfo<Value>& info) {
58   Environment* env = Environment::GetCurrent(info);
59   Isolate* isolate = env->isolate();
60   HandleScope scope(isolate);
61   Local<Object> error;
62   std::ostringstream out;
63 
64   CHECK_EQ(info.Length(), 1);
65   if (!info[0].IsEmpty() && info[0]->IsObject())
66     error = info[0].As<Object>();
67   else
68     error = Local<Object>();
69 
70   GetNodeReport(
71       isolate, env, "JavaScript API", __func__, error, out);
72 
73   // Return value is the contents of a report as a string.
74   info.GetReturnValue().Set(String::NewFromUtf8(isolate,
75                                                 out.str().c_str(),
76                                                 v8::NewStringType::kNormal)
77                                 .ToLocalChecked());
78 }
79 
GetCompact(const FunctionCallbackInfo<Value> & info)80 static void GetCompact(const FunctionCallbackInfo<Value>& info) {
81   node::Mutex::ScopedLock lock(node::per_process::cli_options_mutex);
82   info.GetReturnValue().Set(node::per_process::cli_options->report_compact);
83 }
84 
SetCompact(const FunctionCallbackInfo<Value> & info)85 static void SetCompact(const FunctionCallbackInfo<Value>& info) {
86   node::Mutex::ScopedLock lock(node::per_process::cli_options_mutex);
87   Environment* env = Environment::GetCurrent(info);
88   Isolate* isolate = env->isolate();
89   bool compact = info[0]->ToBoolean(isolate)->Value();
90   node::per_process::cli_options->report_compact = compact;
91 }
92 
GetDirectory(const FunctionCallbackInfo<Value> & info)93 static void GetDirectory(const FunctionCallbackInfo<Value>& info) {
94   node::Mutex::ScopedLock lock(node::per_process::cli_options_mutex);
95   Environment* env = Environment::GetCurrent(info);
96   std::string directory = node::per_process::cli_options->report_directory;
97   auto result = String::NewFromUtf8(env->isolate(),
98                                     directory.c_str(),
99                                     v8::NewStringType::kNormal);
100   info.GetReturnValue().Set(result.ToLocalChecked());
101 }
102 
SetDirectory(const FunctionCallbackInfo<Value> & info)103 static void SetDirectory(const FunctionCallbackInfo<Value>& info) {
104   node::Mutex::ScopedLock lock(node::per_process::cli_options_mutex);
105   Environment* env = Environment::GetCurrent(info);
106   CHECK(info[0]->IsString());
107   Utf8Value dir(env->isolate(), info[0].As<String>());
108   node::per_process::cli_options->report_directory = *dir;
109 }
110 
GetFilename(const FunctionCallbackInfo<Value> & info)111 static void GetFilename(const FunctionCallbackInfo<Value>& info) {
112   node::Mutex::ScopedLock lock(node::per_process::cli_options_mutex);
113   Environment* env = Environment::GetCurrent(info);
114   std::string filename = node::per_process::cli_options->report_filename;
115   auto result = String::NewFromUtf8(env->isolate(),
116                                     filename.c_str(),
117                                     v8::NewStringType::kNormal);
118   info.GetReturnValue().Set(result.ToLocalChecked());
119 }
120 
SetFilename(const FunctionCallbackInfo<Value> & info)121 static void SetFilename(const FunctionCallbackInfo<Value>& info) {
122   node::Mutex::ScopedLock lock(node::per_process::cli_options_mutex);
123   Environment* env = Environment::GetCurrent(info);
124   CHECK(info[0]->IsString());
125   Utf8Value name(env->isolate(), info[0].As<String>());
126   node::per_process::cli_options->report_filename = *name;
127 }
128 
GetSignal(const FunctionCallbackInfo<Value> & info)129 static void GetSignal(const FunctionCallbackInfo<Value>& info) {
130   Environment* env = Environment::GetCurrent(info);
131   std::string signal = env->isolate_data()->options()->report_signal;
132   auto result = String::NewFromUtf8(env->isolate(),
133                                     signal.c_str(),
134                                     v8::NewStringType::kNormal);
135   info.GetReturnValue().Set(result.ToLocalChecked());
136 }
137 
SetSignal(const FunctionCallbackInfo<Value> & info)138 static void SetSignal(const FunctionCallbackInfo<Value>& info) {
139   Environment* env = Environment::GetCurrent(info);
140   CHECK(info[0]->IsString());
141   Utf8Value signal(env->isolate(), info[0].As<String>());
142   env->isolate_data()->options()->report_signal = *signal;
143 }
144 
ShouldReportOnFatalError(const FunctionCallbackInfo<Value> & info)145 static void ShouldReportOnFatalError(const FunctionCallbackInfo<Value>& info) {
146   Mutex::ScopedLock lock(node::per_process::cli_options_mutex);
147   info.GetReturnValue().Set(
148       node::per_process::cli_options->report_on_fatalerror);
149 }
150 
SetReportOnFatalError(const FunctionCallbackInfo<Value> & info)151 static void SetReportOnFatalError(const FunctionCallbackInfo<Value>& info) {
152   CHECK(info[0]->IsBoolean());
153   Mutex::ScopedLock lock(node::per_process::cli_options_mutex);
154   node::per_process::cli_options->report_on_fatalerror = info[0]->IsTrue();
155 }
156 
ShouldReportOnSignal(const FunctionCallbackInfo<Value> & info)157 static void ShouldReportOnSignal(const FunctionCallbackInfo<Value>& info) {
158   Environment* env = Environment::GetCurrent(info);
159   info.GetReturnValue().Set(env->isolate_data()->options()->report_on_signal);
160 }
161 
SetReportOnSignal(const FunctionCallbackInfo<Value> & info)162 static void SetReportOnSignal(const FunctionCallbackInfo<Value>& info) {
163   Environment* env = Environment::GetCurrent(info);
164   CHECK(info[0]->IsBoolean());
165   env->isolate_data()->options()->report_on_signal = info[0]->IsTrue();
166 }
167 
ShouldReportOnUncaughtException(const FunctionCallbackInfo<Value> & info)168 static void ShouldReportOnUncaughtException(
169     const FunctionCallbackInfo<Value>& info) {
170   Environment* env = Environment::GetCurrent(info);
171   info.GetReturnValue().Set(
172       env->isolate_data()->options()->report_uncaught_exception);
173 }
174 
SetReportOnUncaughtException(const FunctionCallbackInfo<Value> & info)175 static void SetReportOnUncaughtException(
176     const FunctionCallbackInfo<Value>& info) {
177   Environment* env = Environment::GetCurrent(info);
178   CHECK(info[0]->IsBoolean());
179   env->isolate_data()->options()->report_uncaught_exception = info[0]->IsTrue();
180 }
181 
Initialize(Local<Object> exports,Local<Value> unused,Local<Context> context,void * priv)182 static void Initialize(Local<Object> exports,
183                        Local<Value> unused,
184                        Local<Context> context,
185                        void* priv) {
186   Environment* env = Environment::GetCurrent(context);
187 
188   env->SetMethod(exports, "writeReport", WriteReport);
189   env->SetMethod(exports, "getReport", GetReport);
190   env->SetMethod(exports, "getCompact", GetCompact);
191   env->SetMethod(exports, "setCompact", SetCompact);
192   env->SetMethod(exports, "getDirectory", GetDirectory);
193   env->SetMethod(exports, "setDirectory", SetDirectory);
194   env->SetMethod(exports, "getFilename", GetFilename);
195   env->SetMethod(exports, "setFilename", SetFilename);
196   env->SetMethod(exports, "getSignal", GetSignal);
197   env->SetMethod(exports, "setSignal", SetSignal);
198   env->SetMethod(exports, "shouldReportOnFatalError", ShouldReportOnFatalError);
199   env->SetMethod(exports, "setReportOnFatalError", SetReportOnFatalError);
200   env->SetMethod(exports, "shouldReportOnSignal", ShouldReportOnSignal);
201   env->SetMethod(exports, "setReportOnSignal", SetReportOnSignal);
202   env->SetMethod(exports, "shouldReportOnUncaughtException",
203                  ShouldReportOnUncaughtException);
204   env->SetMethod(exports, "setReportOnUncaughtException",
205                  SetReportOnUncaughtException);
206 }
207 
208 }  // namespace report
209 
210 NODE_MODULE_CONTEXT_AWARE_INTERNAL(report, report::Initialize)
211