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: 66 68 97.1 %
Date: 2020-06-24 22:13:30 Branches: 26 34 76.5 %

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

3792
    TRACE_COUNTER2(TRACING_CATEGORY_NODE2(promises, rejections),
76
                  "rejections",
77
                  "unhandled", unhandledRejections,
78
                  "handledAfter", rejectionsHandledAfter);
79
477
  } else if (event == kPromiseHandlerAddedAfterReject) {
80
403
    value = Undefined(isolate);
81
403
    rejectionsHandledAfter++;
82

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

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