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: 69 71 97.2 %
Date: 2019-09-12 22:30:12 Branches: 34 42 81.0 %

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 "util-inl.h"
7
#include "v8.h"
8
9
#include <atomic>
10
11
namespace node {
12
13
using v8::Array;
14
using v8::Context;
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::MicrotasksScope;
25
using v8::Number;
26
using v8::Object;
27
using v8::Promise;
28
using v8::PromiseRejectEvent;
29
using v8::PromiseRejectMessage;
30
using v8::Value;
31
32
namespace task_queue {
33
34
80
static void EnqueueMicrotask(const FunctionCallbackInfo<Value>& args) {
35
80
  Environment* env = Environment::GetCurrent(args);
36
80
  Isolate* isolate = env->isolate();
37
38
160
  CHECK(args[0]->IsFunction());
39
40
160
  isolate->EnqueueMicrotask(args[0].As<Function>());
41
80
}
42
43
// Should be in sync with runNextTicks in internal/process/task_queues.js
44
4851
bool RunNextTicksNative(Environment* env) {
45
4851
  TickInfo* tick_info = env->tick_info();
46

4851
  if (!tick_info->has_tick_scheduled() && !tick_info->has_rejection_to_warn())
47
1600
    MicrotasksScope::PerformCheckpoint(env->isolate());
48

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

3674
    TRACE_COUNTER2(TRACING_CATEGORY_NODE2(promises, rejections),
91
                  "rejections",
92
                  "unhandled", unhandledRejections,
93
                  "handledAfter", rejectionsHandledAfter);
94
416
  } else if (event == kPromiseHandlerAddedAfterReject) {
95
353
    value = Undefined(isolate);
96
353
    rejectionsHandledAfter++;
97

706
    TRACE_COUNTER2(TRACING_CATEGORY_NODE2(promises, rejections),
98
                  "rejections",
99
                  "unhandled", unhandledRejections,
100
                  "handledAfter", rejectionsHandledAfter);
101
63
  } else if (event == kPromiseResolveAfterResolved) {
102
60
    value = message.GetValue();
103
3
  } else if (event == kPromiseRejectAfterResolved) {
104
3
    value = message.GetValue();
105
  } else {
106
    return;
107
  }
108
109
2253
  if (value.IsEmpty()) {
110
    value = Undefined(isolate);
111
  }
112
113
4506
  Local<Value> args[] = { type, promise, value };
114
  USE(callback->Call(
115
6759
      env->context(), Undefined(isolate), arraysize(args), args));
116
}
117
118
5100
static void SetPromiseRejectCallback(
119
    const FunctionCallbackInfo<Value>& args) {
120
5100
  Environment* env = Environment::GetCurrent(args);
121
122
10200
  CHECK(args[0]->IsFunction());
123
10200
  env->set_promise_reject_callback(args[0].As<Function>());
124
5100
}
125
126
5101
static void Initialize(Local<Object> target,
127
                       Local<Value> unused,
128
                       Local<Context> context,
129
                       void* priv) {
130
5101
  Environment* env = Environment::GetCurrent(context);
131
5101
  Isolate* isolate = env->isolate();
132
133
5101
  env->SetMethod(target, "enqueueMicrotask", EnqueueMicrotask);
134
5101
  env->SetMethod(target, "setTickCallback", SetTickCallback);
135
5101
  env->SetMethod(target, "runMicrotasks", RunMicrotasks);
136
  target->Set(env->context(),
137
              FIXED_ONE_BYTE_STRING(isolate, "tickInfo"),
138
25505
              env->tick_info()->fields().GetJSArray()).Check();
139
140
5101
  Local<Object> events = Object::New(isolate);
141
20404
  NODE_DEFINE_CONSTANT(events, kPromiseRejectWithNoHandler);
142
20404
  NODE_DEFINE_CONSTANT(events, kPromiseHandlerAddedAfterReject);
143
20404
  NODE_DEFINE_CONSTANT(events, kPromiseResolveAfterResolved);
144
20404
  NODE_DEFINE_CONSTANT(events, kPromiseRejectAfterResolved);
145
146
  target->Set(env->context(),
147
              FIXED_ONE_BYTE_STRING(isolate, "promiseRejectEvents"),
148
20404
              events).Check();
149
  env->SetMethod(target,
150
                 "setPromiseRejectCallback",
151
5101
                 SetPromiseRejectCallback);
152
5101
}
153
154
}  // namespace task_queue
155
}  // namespace node
156
157
4955
NODE_MODULE_CONTEXT_AWARE_INTERNAL(task_queue, node::task_queue::Initialize)