GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/node_task_queue.cc Lines: 79 83 95.2 %
Date: 2019-05-05 22:32:45 Branches: 37 48 77.1 %

Line Branch Exec Source
1
#include "env-inl.h"
2
#include "node.h"
3
#include "node_errors.h"
4
#include "node_internals.h"
5
#include "node_process.h"
6
#include "v8.h"
7
8
#include <atomic>
9
10
namespace node {
11
12
using v8::Array;
13
using v8::Context;
14
using v8::Exception;
15
using v8::Function;
16
using v8::FunctionCallbackInfo;
17
using v8::Isolate;
18
using v8::kPromiseHandlerAddedAfterReject;
19
using v8::kPromiseRejectAfterResolved;
20
using v8::kPromiseRejectWithNoHandler;
21
using v8::kPromiseResolveAfterResolved;
22
using v8::Local;
23
using v8::Message;
24
using v8::Number;
25
using v8::Object;
26
using v8::Promise;
27
using v8::PromiseRejectEvent;
28
using v8::PromiseRejectMessage;
29
using v8::Value;
30
31
namespace task_queue {
32
33
16
static void EnqueueMicrotask(const FunctionCallbackInfo<Value>& args) {
34
16
  Environment* env = Environment::GetCurrent(args);
35
16
  Isolate* isolate = env->isolate();
36
37
32
  CHECK(args[0]->IsFunction());
38
39
32
  isolate->EnqueueMicrotask(args[0].As<Function>());
40
16
}
41
42
// Should be in sync with runNextTicks in internal/process/task_queues.js
43
4404
bool RunNextTicksNative(Environment* env) {
44
4404
  TickInfo* tick_info = env->tick_info();
45

4404
  if (!tick_info->has_tick_scheduled() && !tick_info->has_rejection_to_warn())
46
1596
    env->isolate()->RunMicrotasks();
47

4403
  if (!tick_info->has_tick_scheduled() && !tick_info->has_rejection_to_warn())
48
1582
    return true;
49
50
2821
  Local<Function> callback = env->tick_callback_function();
51
2821
  CHECK(!callback.IsEmpty());
52
11259
  return !callback->Call(env->context(), env->process_object(), 0, nullptr)
53
5617
              .IsEmpty();
54
}
55
56
558045
static void RunMicrotasks(const FunctionCallbackInfo<Value>& args) {
57
558045
  args.GetIsolate()->RunMicrotasks();
58
558039
}
59
60
4643
static void SetTickCallback(const FunctionCallbackInfo<Value>& args) {
61
4643
  Environment* env = Environment::GetCurrent(args);
62
9286
  CHECK(args[0]->IsFunction());
63
9286
  env->set_tick_callback_function(args[0].As<Function>());
64
4643
}
65
66
2012
void PromiseRejectCallback(PromiseRejectMessage message) {
67
  static std::atomic<uint64_t> unhandledRejections{0};
68
  static std::atomic<uint64_t> rejectionsHandledAfter{0};
69
70
2012
  Local<Promise> promise = message.GetPromise();
71
2012
  Isolate* isolate = promise->GetIsolate();
72
2012
  PromiseRejectEvent event = message.GetEvent();
73
74
2012
  Environment* env = Environment::GetCurrent(isolate);
75
76
2012
  if (env == nullptr) return;
77
78
2012
  Local<Function> callback = env->promise_reject_callback();
79
  // The promise is rejected before JS land calls SetPromiseRejectCallback
80
  // to initializes the promise reject callback during bootstrap.
81
2012
  CHECK(!callback.IsEmpty());
82
83
  Local<Value> value;
84
2012
  Local<Value> type = Number::New(env->isolate(), event);
85
86
2012
  if (event == kPromiseRejectWithNoHandler) {
87
1716
    value = message.GetValue();
88
1716
    unhandledRejections++;
89

3432
    TRACE_COUNTER2(TRACING_CATEGORY_NODE2(promises, rejections),
90
                  "rejections",
91
                  "unhandled", unhandledRejections,
92
                  "handledAfter", rejectionsHandledAfter);
93
296
  } else if (event == kPromiseHandlerAddedAfterReject) {
94
235
    value = Undefined(isolate);
95
235
    rejectionsHandledAfter++;
96

470
    TRACE_COUNTER2(TRACING_CATEGORY_NODE2(promises, rejections),
97
                  "rejections",
98
                  "unhandled", unhandledRejections,
99
                  "handledAfter", rejectionsHandledAfter);
100
61
  } else if (event == kPromiseResolveAfterResolved) {
101
58
    value = message.GetValue();
102
3
  } else if (event == kPromiseRejectAfterResolved) {
103
3
    value = message.GetValue();
104
  } else {
105
    return;
106
  }
107
108
2012
  if (value.IsEmpty()) {
109
    value = Undefined(isolate);
110
  }
111
112
4024
  Local<Value> args[] = { type, promise, value };
113
  USE(callback->Call(
114
6036
      env->context(), Undefined(isolate), arraysize(args), args));
115
}
116
117
4643
static void SetPromiseRejectCallback(
118
    const FunctionCallbackInfo<Value>& args) {
119
4643
  Environment* env = Environment::GetCurrent(args);
120
121
9286
  CHECK(args[0]->IsFunction());
122
9286
  env->set_promise_reject_callback(args[0].As<Function>());
123
4643
}
124
125
20
static void TriggerFatalException(const FunctionCallbackInfo<Value>& args) {
126
20
  Isolate* isolate = args.GetIsolate();
127
20
  Environment* env = Environment::GetCurrent(isolate);
128
20
  Local<Value> exception = args[0];
129
20
  Local<Message> message = Exception::CreateMessage(isolate, exception);
130

20
  if (env != nullptr && env->abort_on_uncaught_exception()) {
131
    ReportException(env, exception, message);
132
    Abort();
133
  }
134
40
  bool from_promise = args[1]->IsTrue();
135
20
  FatalException(isolate, exception, message, from_promise);
136
5
}
137
138
4646
static void Initialize(Local<Object> target,
139
                       Local<Value> unused,
140
                       Local<Context> context,
141
                       void* priv) {
142
4646
  Environment* env = Environment::GetCurrent(context);
143
4646
  Isolate* isolate = env->isolate();
144
145
4646
  env->SetMethod(target, "triggerFatalException", TriggerFatalException);
146
4646
  env->SetMethod(target, "enqueueMicrotask", EnqueueMicrotask);
147
4646
  env->SetMethod(target, "setTickCallback", SetTickCallback);
148
4646
  env->SetMethod(target, "runMicrotasks", RunMicrotasks);
149
  target->Set(env->context(),
150
              FIXED_ONE_BYTE_STRING(isolate, "tickInfo"),
151
23230
              env->tick_info()->fields().GetJSArray()).Check();
152
153
4646
  Local<Object> events = Object::New(isolate);
154
18584
  NODE_DEFINE_CONSTANT(events, kPromiseRejectWithNoHandler);
155
18584
  NODE_DEFINE_CONSTANT(events, kPromiseHandlerAddedAfterReject);
156
18584
  NODE_DEFINE_CONSTANT(events, kPromiseResolveAfterResolved);
157
18584
  NODE_DEFINE_CONSTANT(events, kPromiseRejectAfterResolved);
158
159
  target->Set(env->context(),
160
              FIXED_ONE_BYTE_STRING(isolate, "promiseRejectEvents"),
161
18584
              events).Check();
162
  env->SetMethod(target,
163
                 "setPromiseRejectCallback",
164
4646
                 SetPromiseRejectCallback);
165
4646
}
166
167
}  // namespace task_queue
168
}  // namespace node
169
170
4524
NODE_MODULE_CONTEXT_AWARE_INTERNAL(task_queue, node::task_queue::Initialize)