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