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: 74 76 97.4 %
Date: 2019-09-24 22:36:24 Branches: 39 48 81.3 %

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 errors::TryCatchScope;
14
using v8::Array;
15
using v8::Context;
16
using v8::Function;
17
using v8::FunctionCallbackInfo;
18
using v8::Isolate;
19
using v8::kPromiseHandlerAddedAfterReject;
20
using v8::kPromiseRejectAfterResolved;
21
using v8::kPromiseRejectWithNoHandler;
22
using v8::kPromiseResolveAfterResolved;
23
using v8::Local;
24
using v8::Message;
25
using v8::MicrotasksScope;
26
using v8::Number;
27
using v8::Object;
28
using v8::Promise;
29
using v8::PromiseRejectEvent;
30
using v8::PromiseRejectMessage;
31
using v8::Value;
32
33
namespace task_queue {
34
35
182
static void EnqueueMicrotask(const FunctionCallbackInfo<Value>& args) {
36
182
  Environment* env = Environment::GetCurrent(args);
37
182
  Isolate* isolate = env->isolate();
38
39
364
  CHECK(args[0]->IsFunction());
40
41
364
  isolate->EnqueueMicrotask(args[0].As<Function>());
42
182
}
43
44
// Should be in sync with runNextTicks in internal/process/task_queues.js
45
4851
bool RunNextTicksNative(Environment* env) {
46
4851
  TickInfo* tick_info = env->tick_info();
47

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

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

3676
    TRACE_COUNTER2(TRACING_CATEGORY_NODE2(promises, rejections),
92
                  "rejections",
93
                  "unhandled", unhandledRejections,
94
                  "handledAfter", rejectionsHandledAfter);
95
417
  } else if (event == kPromiseHandlerAddedAfterReject) {
96
354
    value = Undefined(isolate);
97
354
    rejectionsHandledAfter++;
98

708
    TRACE_COUNTER2(TRACING_CATEGORY_NODE2(promises, rejections),
99
                  "rejections",
100
                  "unhandled", unhandledRejections,
101
                  "handledAfter", rejectionsHandledAfter);
102
63
  } else if (event == kPromiseResolveAfterResolved) {
103
60
    value = message.GetValue();
104
3
  } else if (event == kPromiseRejectAfterResolved) {
105
3
    value = message.GetValue();
106
  } else {
107
    return;
108
  }
109
110
2255
  if (value.IsEmpty()) {
111
    value = Undefined(isolate);
112
  }
113
114
4510
  Local<Value> args[] = { type, promise, value };
115
116
  // V8 does not expect this callback to have a scheduled exceptions once it
117
  // returns, so we print them out in a best effort to do something about it
118
  // without failing silently and without crashing the process.
119
2255
  TryCatchScope try_catch(env);
120
  USE(callback->Call(
121
6765
      env->context(), Undefined(isolate), arraysize(args), args));
122

2255
  if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
123
422
    fprintf(stderr, "Exception in PromiseRejectCallback:\n");
124
422
    PrintCaughtException(isolate, env->context(), try_catch);
125
2255
  }
126
}
127
128
5103
static void SetPromiseRejectCallback(
129
    const FunctionCallbackInfo<Value>& args) {
130
5103
  Environment* env = Environment::GetCurrent(args);
131
132
10206
  CHECK(args[0]->IsFunction());
133
10206
  env->set_promise_reject_callback(args[0].As<Function>());
134
5103
}
135
136
5103
static void Initialize(Local<Object> target,
137
                       Local<Value> unused,
138
                       Local<Context> context,
139
                       void* priv) {
140
5103
  Environment* env = Environment::GetCurrent(context);
141
5103
  Isolate* isolate = env->isolate();
142
143
5103
  env->SetMethod(target, "enqueueMicrotask", EnqueueMicrotask);
144
5103
  env->SetMethod(target, "setTickCallback", SetTickCallback);
145
5103
  env->SetMethod(target, "runMicrotasks", RunMicrotasks);
146
  target->Set(env->context(),
147
              FIXED_ONE_BYTE_STRING(isolate, "tickInfo"),
148
25515
              env->tick_info()->fields().GetJSArray()).Check();
149
150
5103
  Local<Object> events = Object::New(isolate);
151
20412
  NODE_DEFINE_CONSTANT(events, kPromiseRejectWithNoHandler);
152
20412
  NODE_DEFINE_CONSTANT(events, kPromiseHandlerAddedAfterReject);
153
20412
  NODE_DEFINE_CONSTANT(events, kPromiseResolveAfterResolved);
154
20412
  NODE_DEFINE_CONSTANT(events, kPromiseRejectAfterResolved);
155
156
  target->Set(env->context(),
157
              FIXED_ONE_BYTE_STRING(isolate, "promiseRejectEvents"),
158
20412
              events).Check();
159
  env->SetMethod(target,
160
                 "setPromiseRejectCallback",
161
5103
                 SetPromiseRejectCallback);
162
5103
}
163
164
}  // namespace task_queue
165
}  // namespace node
166
167
4957
NODE_MODULE_CONTEXT_AWARE_INTERNAL(task_queue, node::task_queue::Initialize)