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