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-26 22:23:30 Branches: 77 136 56.6 %

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

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

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

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

34
  if (path_unchecked->IsUndefined() || path_unchecked->IsNull())
164
1
    path_unchecked = pathkey;
165
9
  path = path_unchecked.As<String>();
166
167
18
  Utf8Value pathstr(env->isolate(), path);
168
169
9
  if (sync) {
170

3
    static const std::string e = "exception";
171

3
    static const std::string s = "signal";
172

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

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

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

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

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

17128
NODE_MODULE_CONTEXT_AWARE_INTERNAL(report, report::Initialize)