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 81 97.5 %
Date: 2020-12-12 04:11:07 Branches: 32 42 76.2 %

Line Branch Exec Source
1
#include "env-inl.h"
2
#include "node.h"
3
#include "node_errors.h"
4
#include "node_external_reference.h"
5
#include "node_internals.h"
6
#include "node_process.h"
7
#include "util-inl.h"
8
#include "v8.h"
9
10
#include <atomic>
11
12
namespace node {
13
14
using errors::TryCatchScope;
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::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
15777
void PromiseRejectCallback(PromiseRejectMessage message) {
33
  static std::atomic<uint64_t> unhandledRejections{0};
34
  static std::atomic<uint64_t> rejectionsHandledAfter{0};
35
36
15777
  Local<Promise> promise = message.GetPromise();
37
15777
  Isolate* isolate = promise->GetIsolate();
38
15777
  PromiseRejectEvent event = message.GetEvent();
39
40
15777
  Environment* env = Environment::GetCurrent(isolate);
41
42

15778
  if (env == nullptr || !env->can_call_into_js()) return;
43
44
15776
  Local<Function> callback = env->promise_reject_callback();
45
  // The promise is rejected before JS land calls SetPromiseRejectCallback
46
  // to initializes the promise reject callback during bootstrap.
47
15776
  CHECK(!callback.IsEmpty());
48
49
  Local<Value> value;
50
15776
  Local<Value> type = Number::New(env->isolate(), event);
51
52
15776
  if (event == kPromiseRejectWithNoHandler) {
53
8547
    value = message.GetValue();
54
8547
    unhandledRejections++;
55
8547
    TRACE_COUNTER2(TRACING_CATEGORY_NODE2(promises, rejections),
56
                  "rejections",
57
                  "unhandled", unhandledRejections,
58
138
                  "handledAfter", rejectionsHandledAfter);
59

24461
  } else if (event == kPromiseHandlerAddedAfterReject) {
60
15700
    value = Undefined(isolate);
61
7153
    rejectionsHandledAfter++;
62
4
    TRACE_COUNTER2(TRACING_CATEGORY_NODE2(promises, rejections),
63
7157
                  "rejections",
64
                  "unhandled", unhandledRejections,
65
119
                  "handledAfter", rejectionsHandledAfter);
66

14501
  } else if (event == kPromiseResolveAfterResolved) {
67
7224
    value = message.GetValue();
68
5
  } else if (event == kPromiseRejectAfterResolved) {
69
7
    value = message.GetValue();
70
2
  } else {
71
    return;
72
  }
73
74
15776
  if (value.IsEmpty()) {
75
    value = Undefined(isolate);
76
  }
77
78
31552
  Local<Value> args[] = { type, promise, value };
79
80
  // V8 does not expect this callback to have a scheduled exceptions once it
81
  // returns, so we print them out in a best effort to do something about it
82
  // without failing silently and without crashing the process.
83
31552
  TryCatchScope try_catch(env);
84
31552
  USE(callback->Call(
85
78880
      env->context(), Undefined(isolate), arraysize(args), args));
86

15776
  if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
87
394
    fprintf(stderr, "Exception in PromiseRejectCallback:\n");
88
394
    PrintCaughtException(isolate, env->context(), try_catch);
89
  }
90
}
91
namespace task_queue {
92
93
313
static void EnqueueMicrotask(const FunctionCallbackInfo<Value>& args) {
94
313
  Environment* env = Environment::GetCurrent(args);
95
313
  Isolate* isolate = env->isolate();
96
97
626
  CHECK(args[0]->IsFunction());
98
99
626
  isolate->EnqueueMicrotask(args[0].As<Function>());
100
313
}
101
102
443494
static void RunMicrotasks(const FunctionCallbackInfo<Value>& args) {
103
443494
  MicrotasksScope::PerformCheckpoint(args.GetIsolate());
104
443491
}
105
106
444
static void SetTickCallback(const FunctionCallbackInfo<Value>& args) {
107
444
  Environment* env = Environment::GetCurrent(args);
108
888
  CHECK(args[0]->IsFunction());
109
888
  env->set_tick_callback_function(args[0].As<Function>());
110
444
}
111
112
444
static void SetPromiseRejectCallback(
113
    const FunctionCallbackInfo<Value>& args) {
114
444
  Environment* env = Environment::GetCurrent(args);
115
116
888
  CHECK(args[0]->IsFunction());
117
888
  env->set_promise_reject_callback(args[0].As<Function>());
118
444
}
119
120
444
static void Initialize(Local<Object> target,
121
                       Local<Value> unused,
122
                       Local<Context> context,
123
                       void* priv) {
124
444
  Environment* env = Environment::GetCurrent(context);
125
444
  Isolate* isolate = env->isolate();
126
127
444
  env->SetMethod(target, "enqueueMicrotask", EnqueueMicrotask);
128
444
  env->SetMethod(target, "setTickCallback", SetTickCallback);
129
444
  env->SetMethod(target, "runMicrotasks", RunMicrotasks);
130
888
  target->Set(env->context(),
131
              FIXED_ONE_BYTE_STRING(isolate, "tickInfo"),
132
2220
              env->tick_info()->fields().GetJSArray()).Check();
133
134
444
  Local<Object> events = Object::New(isolate);
135
888
  NODE_DEFINE_CONSTANT(events, kPromiseRejectWithNoHandler);
136
444
  NODE_DEFINE_CONSTANT(events, kPromiseHandlerAddedAfterReject);
137
2220
  NODE_DEFINE_CONSTANT(events, kPromiseResolveAfterResolved);
138
2220
  NODE_DEFINE_CONSTANT(events, kPromiseRejectAfterResolved);
139
2664
140
3108
  target->Set(env->context(),
141
1332
              FIXED_ONE_BYTE_STRING(isolate, "promiseRejectEvents"),
142
2664
              events).Check();
143
  env->SetMethod(target,
144
                 "setPromiseRejectCallback",
145
444
                 SetPromiseRejectCallback);
146
444
}
147
148
4614
void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
149
4614
  registry->Register(EnqueueMicrotask);
150
4614
  registry->Register(SetTickCallback);
151
4614
  registry->Register(RunMicrotasks);
152
4614
  registry->Register(SetPromiseRejectCallback);
153
4614
}
154
155
}  // namespace task_queue
156
}  // namespace node
157
158
4683
NODE_MODULE_CONTEXT_AWARE_INTERNAL(task_queue, node::task_queue::Initialize)
159

18687
NODE_MODULE_EXTERNAL_REFERENCE(task_queue,
160
                               node::task_queue::RegisterExternalReferences)