GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/node_report_module.cc Lines: 107 131 81.7 %
Date: 2019-02-23 22:23:05 Branches: 72 134 53.7 %

Line Branch Exec Source
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.h"
7
8
#include "env-inl.h"
9
#include "handle_wrap.h"
10
#include "node_buffer.h"
11
#include "stream_base-inl.h"
12
#include "stream_wrap.h"
13
#include "util-inl.h"
14
15
#include <v8.h>
16
#include <atomic>
17
#include <sstream>
18
19
namespace report {
20
using node::Environment;
21
using node::FIXED_ONE_BYTE_STRING;
22
using node::PerIsolateOptions;
23
using node::Utf8Value;
24
using v8::Array;
25
using v8::Boolean;
26
using v8::Context;
27
using v8::Function;
28
using v8::FunctionCallbackInfo;
29
using v8::HandleScope;
30
using v8::Isolate;
31
using v8::Local;
32
using v8::Object;
33
using v8::String;
34
using v8::V8;
35
using v8::Value;
36
37
// Internal/static function declarations
38
void OnUncaughtException(const FunctionCallbackInfo<Value>& info);
39
static void Initialize(Local<Object> exports,
40
                       Local<Value> unused,
41
                       Local<Context> context);
42
43
// External JavaScript API for triggering a report
44
4
void TriggerReport(const FunctionCallbackInfo<Value>& info) {
45
4
  Environment* env = Environment::GetCurrent(info);
46
4
  Isolate* isolate = env->isolate();
47
4
  HandleScope scope(isolate);
48
8
  std::string filename;
49
  Local<String> stackstr;
50
51
4
  if (info.Length() == 1) {
52
6
    stackstr = info[0].As<String>();
53
  } else {
54
1
    filename = *String::Utf8Value(isolate, info[0]);
55
2
    stackstr = info[1].As<String>();
56
  }
57
58
8
  filename = TriggerNodeReport(
59
4
      isolate, env, "JavaScript API", __func__, filename, stackstr);
60
  // Return value is the report filename
61
  info.GetReturnValue().Set(
62
4
      String::NewFromUtf8(isolate, filename.c_str(), v8::NewStringType::kNormal)
63
16
          .ToLocalChecked());
64
4
}
65
66
// External JavaScript API for returning a report
67
3
void GetReport(const FunctionCallbackInfo<Value>& info) {
68
3
  Environment* env = Environment::GetCurrent(info);
69
3
  Isolate* isolate = env->isolate();
70
3
  HandleScope scope(isolate);
71
6
  std::ostringstream out;
72
73
  GetNodeReport(
74
6
      isolate, env, "JavaScript API", __func__, info[0].As<String>(), out);
75
76
  // Return value is the contents of a report as a string.
77
  info.GetReturnValue().Set(String::NewFromUtf8(isolate,
78
                                                out.str().c_str(),
79
6
                                                v8::NewStringType::kNormal)
80
12
                                .ToLocalChecked());
81
3
}
82
83
// Callbacks for triggering report on uncaught exception.
84
// Calls triggered from JS land.
85
1
void OnUncaughtException(const FunctionCallbackInfo<Value>& info) {
86
1
  Environment* env = Environment::GetCurrent(info);
87
1
  Isolate* isolate = env->isolate();
88
1
  HandleScope scope(isolate);
89
2
  std::string filename;
90
2
  std::shared_ptr<PerIsolateOptions> options = env->isolate_data()->options();
91
92
  // Trigger report if requested
93
1
  if (options->report_uncaught_exception) {
94
    TriggerNodeReport(
95
2
        isolate, env, "exception", __func__, filename, info[0].As<String>());
96
1
  }
97
1
}
98
99
// Signal handler for report action, called from JS land (util.js)
100
void OnUserSignal(const FunctionCallbackInfo<Value>& info) {
101
  Environment* env = Environment::GetCurrent(info);
102
  Isolate* isolate = env->isolate();
103
  CHECK(info[0]->IsString());
104
  Local<String> str = info[0].As<String>();
105
  String::Utf8Value value(isolate, str);
106
  std::string filename;
107
  TriggerNodeReport(
108
      isolate, env, *value, __func__, filename, info[0].As<String>());
109
}
110
111
// A method to sync up data elements in the JS land with its
112
// corresponding elements in the C++ world. Required because
113
// (i) the tunables are first intercepted through the CLI but
114
// later modified via APIs. (ii) the report generation events
115
// are controlled partly from C++ and partly from JS.
116
11
void SyncConfig(const FunctionCallbackInfo<Value>& info) {
117
11
  Environment* env = Environment::GetCurrent(info);
118
11
  Local<Context> context = env->context();
119
11
  std::shared_ptr<PerIsolateOptions> options = env->isolate_data()->options();
120
121
11
  CHECK_EQ(info.Length(), 2);
122
  Local<Object> obj;
123
33
  if (!info[0]->ToObject(context).ToLocal(&obj)) return;
124
33
  bool sync = info[1].As<Boolean>()->Value();
125
126
  // Events array
127
11
  Local<String> eventskey = FIXED_ONE_BYTE_STRING(env->isolate(), "events");
128
  Local<Value> events_unchecked;
129
22
  if (!obj->Get(context, eventskey).ToLocal(&events_unchecked)) return;
130
  Local<Array> events;
131

42
  if (events_unchecked->IsUndefined() || events_unchecked->IsNull()) {
132
2
    events_unchecked = Array::New(env->isolate(), 0);
133
2
    if (obj->Set(context, eventskey, events_unchecked).IsNothing()) return;
134
  }
135
11
  events = events_unchecked.As<Array>();
136
137
  // Signal
138
11
  Local<String> signalkey = env->signal_string();
139
  Local<Value> signal_unchecked;
140
22
  if (!obj->Get(context, signalkey).ToLocal(&signal_unchecked)) return;
141
  Local<String> signal;
142

42
  if (signal_unchecked->IsUndefined() || signal_unchecked->IsNull())
143
1
    signal_unchecked = signalkey;
144
11
  signal = signal_unchecked.As<String>();
145
146
22
  Utf8Value signalstr(env->isolate(), signal);
147
148
  // Report file
149
11
  Local<String> filekey = FIXED_ONE_BYTE_STRING(env->isolate(), "filename");
150
  Local<Value> file_unchecked;
151
22
  if (!obj->Get(context, filekey).ToLocal(&file_unchecked)) return;
152
  Local<String> file;
153

42
  if (file_unchecked->IsUndefined() || file_unchecked->IsNull())
154
1
    file_unchecked = filekey;
155
11
  file = file_unchecked.As<String>();
156
157
22
  Utf8Value filestr(env->isolate(), file);
158
159
  // Report file path
160
11
  Local<String> pathkey = FIXED_ONE_BYTE_STRING(env->isolate(), "path");
161
  Local<Value> path_unchecked;
162
22
  if (!obj->Get(context, pathkey).ToLocal(&path_unchecked)) return;
163
  Local<String> path;
164

42
  if (path_unchecked->IsUndefined() || path_unchecked->IsNull())
165
1
    path_unchecked = pathkey;
166
11
  path = path_unchecked.As<String>();
167
168
22
  Utf8Value pathstr(env->isolate(), path);
169
170
11
  if (sync) {
171

2
    static const std::string e = "exception";
172

2
    static const std::string s = "signal";
173

2
    static const std::string f = "fatalerror";
174
4
    for (uint32_t i = 0; i < events->Length(); i++) {
175
      Local<Value> v;
176
      if (!events->Get(context, i).ToLocal(&v)) return;
177
      Local<String> elem;
178
      if (!v->ToString(context).ToLocal(&elem)) return;
179
      String::Utf8Value buf(env->isolate(), elem);
180
      if (*buf == e) {
181
        options->report_uncaught_exception = true;
182
      } else if (*buf == s) {
183
        options->report_on_signal = true;
184
      } else if (*buf == f) {
185
        options->report_on_fatalerror = true;
186
      }
187
    }
188
2
    CHECK_NOT_NULL(*signalstr);
189
2
    options->report_signal = *signalstr;
190
2
    CHECK_NOT_NULL(*filestr);
191
2
    options->report_filename = *filestr;
192
2
    CHECK_NOT_NULL(*pathstr);
193
2
    options->report_directory = *pathstr;
194
  } else {
195
9
    int i = 0;
196

29
    if (options->report_uncaught_exception &&
197
        events
198
2
            ->Set(context,
199
                  i++,
200
15
                  FIXED_ONE_BYTE_STRING(env->isolate(), "exception"))
201
15
            .IsNothing())
202
      return;
203

27
    if (options->report_on_signal &&
204
        events
205
9
            ->Set(context, i++, FIXED_ONE_BYTE_STRING(env->isolate(), "signal"))
206
9
            .IsNothing())
207
      return;
208

27
    if (options->report_on_fatalerror &&
209
        events
210
            ->Set(
211
9
                context, i, FIXED_ONE_BYTE_STRING(env->isolate(), "fatalerror"))
212
9
            .IsNothing())
213
      return;
214
215
    Local<Value> signal_value;
216
    Local<Value> file_value;
217
    Local<Value> path_value;
218
9
    std::string signal = options->report_signal;
219
9
    if (signal.empty()) signal = "SIGUSR2";
220
18
    if (!node::ToV8Value(context, signal).ToLocal(&signal_value))
221
      return;
222
18
    if (!obj->Set(context, signalkey, signal_value).FromJust()) return;
223
224
27
    if (!node::ToV8Value(context, options->report_filename)
225
27
             .ToLocal(&file_value))
226
      return;
227
18
    if (!obj->Set(context, filekey, file_value).FromJust()) return;
228
229
27
    if (!node::ToV8Value(context, options->report_directory)
230
27
             .ToLocal(&path_value))
231
      return;
232

18
    if (!obj->Set(context, pathkey, path_value).FromJust()) return;
233
11
  }
234
}
235
236
265
static void Initialize(Local<Object> exports,
237
                       Local<Value> unused,
238
                       Local<Context> context) {
239
265
  Environment* env = Environment::GetCurrent(context);
240
265
  std::shared_ptr<PerIsolateOptions> options = env->isolate_data()->options();
241
265
  env->SetMethod(exports, "triggerReport", TriggerReport);
242
265
  env->SetMethod(exports, "getReport", GetReport);
243
265
  env->SetMethod(exports, "onUnCaughtException", OnUncaughtException);
244
265
  env->SetMethod(exports, "onUserSignal", OnUserSignal);
245
265
  env->SetMethod(exports, "syncConfig", SyncConfig);
246
265
}
247
248
}  // namespace report
249
250

17152
NODE_MODULE_CONTEXT_AWARE_INTERNAL(report, report::Initialize)