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