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: 73 75 97.3 %
Date: 2020-08-17 22:13:26 Branches: 29 38 76.3 %

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
namespace task_queue {
33
34
209
static void EnqueueMicrotask(const FunctionCallbackInfo<Value>& args) {
35
209
  Environment* env = Environment::GetCurrent(args);
36
209
  Isolate* isolate = env->isolate();
37
38
418
  CHECK(args[0]->IsFunction());
39
40
418
  isolate->EnqueueMicrotask(args[0].As<Function>());
41
209
}
42
43
449795
static void RunMicrotasks(const FunctionCallbackInfo<Value>& args) {
44
449795
  MicrotasksScope::PerformCheckpoint(args.GetIsolate());
45
449792
}
46
47
387
static void SetTickCallback(const FunctionCallbackInfo<Value>& args) {
48
387
  Environment* env = Environment::GetCurrent(args);
49
774
  CHECK(args[0]->IsFunction());
50
774
  env->set_tick_callback_function(args[0].As<Function>());
51
387
}
52
53
2440
void PromiseRejectCallback(PromiseRejectMessage message) {
54
  static std::atomic<uint64_t> unhandledRejections{0};
55
  static std::atomic<uint64_t> rejectionsHandledAfter{0};
56
57
2440
  Local<Promise> promise = message.GetPromise();
58
2440
  Isolate* isolate = promise->GetIsolate();
59
2440
  PromiseRejectEvent event = message.GetEvent();
60
61
2440
  Environment* env = Environment::GetCurrent(isolate);
62
63
2440
  if (env == nullptr) return;
64
65
2440
  Local<Function> callback = env->promise_reject_callback();
66
  // The promise is rejected before JS land calls SetPromiseRejectCallback
67
  // to initializes the promise reject callback during bootstrap.
68
2440
  CHECK(!callback.IsEmpty());
69
70
  Local<Value> value;
71
2440
  Local<Value> type = Number::New(env->isolate(), event);
72
73
2440
  if (event == kPromiseRejectWithNoHandler) {
74
1930
    value = message.GetValue();
75
1930
    unhandledRejections++;
76

3860
    TRACE_COUNTER2(TRACING_CATEGORY_NODE2(promises, rejections),
77
                  "rejections",
78
                  "unhandled", unhandledRejections,
79
                  "handledAfter", rejectionsHandledAfter);
80
510
  } else if (event == kPromiseHandlerAddedAfterReject) {
81
436
    value = Undefined(isolate);
82
436
    rejectionsHandledAfter++;
83

872
    TRACE_COUNTER2(TRACING_CATEGORY_NODE2(promises, rejections),
84
                  "rejections",
85
                  "unhandled", unhandledRejections,
86
                  "handledAfter", rejectionsHandledAfter);
87
74
  } else if (event == kPromiseResolveAfterResolved) {
88
71
    value = message.GetValue();
89
3
  } else if (event == kPromiseRejectAfterResolved) {
90
3
    value = message.GetValue();
91
  } else {
92
    return;
93
  }
94
95
2440
  if (value.IsEmpty()) {
96
    value = Undefined(isolate);
97
  }
98
99
4880
  Local<Value> args[] = { type, promise, value };
100
101
  // V8 does not expect this callback to have a scheduled exceptions once it
102
  // returns, so we print them out in a best effort to do something about it
103
  // without failing silently and without crashing the process.
104
4880
  TryCatchScope try_catch(env);
105
4880
  USE(callback->Call(
106
12200
      env->context(), Undefined(isolate), arraysize(args), args));
107

2440
  if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
108
423
    fprintf(stderr, "Exception in PromiseRejectCallback:\n");
109
423
    PrintCaughtException(isolate, env->context(), try_catch);
110
  }
111
}
112
113
387
static void SetPromiseRejectCallback(
114
    const FunctionCallbackInfo<Value>& args) {
115
387
  Environment* env = Environment::GetCurrent(args);
116
117
774
  CHECK(args[0]->IsFunction());
118
774
  env->set_promise_reject_callback(args[0].As<Function>());
119
387
}
120
121
387
static void Initialize(Local<Object> target,
122
                       Local<Value> unused,
123
                       Local<Context> context,
124
                       void* priv) {
125
387
  Environment* env = Environment::GetCurrent(context);
126
387
  Isolate* isolate = env->isolate();
127
128
387
  env->SetMethod(target, "enqueueMicrotask", EnqueueMicrotask);
129
387
  env->SetMethod(target, "setTickCallback", SetTickCallback);
130
387
  env->SetMethod(target, "runMicrotasks", RunMicrotasks);
131
774
  target->Set(env->context(),
132
              FIXED_ONE_BYTE_STRING(isolate, "tickInfo"),
133
1935
              env->tick_info()->fields().GetJSArray()).Check();
134
135
387
  Local<Object> events = Object::New(isolate);
136
1548
  NODE_DEFINE_CONSTANT(events, kPromiseRejectWithNoHandler);
137
1548
  NODE_DEFINE_CONSTANT(events, kPromiseHandlerAddedAfterReject);
138
1548
  NODE_DEFINE_CONSTANT(events, kPromiseResolveAfterResolved);
139
1548
  NODE_DEFINE_CONSTANT(events, kPromiseRejectAfterResolved);
140
141
774
  target->Set(env->context(),
142
              FIXED_ONE_BYTE_STRING(isolate, "promiseRejectEvents"),
143
1548
              events).Check();
144
  env->SetMethod(target,
145
                 "setPromiseRejectCallback",
146
387
                 SetPromiseRejectCallback);
147
387
}
148
149
4390
void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
150
4390
  registry->Register(EnqueueMicrotask);
151
4390
  registry->Register(SetTickCallback);
152
4390
  registry->Register(RunMicrotasks);
153
4390
  registry->Register(SetPromiseRejectCallback);
154
4390
}
155
156
}  // namespace task_queue
157
}  // namespace node
158
159
4459
NODE_MODULE_CONTEXT_AWARE_INTERNAL(task_queue, node::task_queue::Initialize)
160

17770
NODE_MODULE_EXTERNAL_REFERENCE(task_queue,
161
                               node::task_queue::RegisterExternalReferences)