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