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

3688
    TRACE_COUNTER2(TRACING_CATEGORY_NODE2(promises, rejections),
78
                  "rejections",
79
                  "unhandled", unhandledRejections,
80
                  "handledAfter", rejectionsHandledAfter);
81
419
  } else if (event == kPromiseHandlerAddedAfterReject) {
82
353
    value = Undefined(isolate);
83
353
    rejectionsHandledAfter++;
84

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

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