GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/api/callback.cc Lines: 94 107 87.9 %
Date: 2019-10-08 22:34:21 Branches: 72 90 80.0 %

Line Branch Exec Source
1
#include "node.h"
2
#include "async_wrap-inl.h"
3
#include "env-inl.h"
4
#include "v8.h"
5
6
namespace node {
7
8
using v8::Context;
9
using v8::EscapableHandleScope;
10
using v8::Function;
11
using v8::HandleScope;
12
using v8::Isolate;
13
using v8::Local;
14
using v8::MaybeLocal;
15
using v8::MicrotasksScope;
16
using v8::NewStringType;
17
using v8::Object;
18
using v8::String;
19
using v8::Value;
20
21
647
CallbackScope::CallbackScope(Isolate* isolate,
22
                             Local<Object> object,
23
                             async_context asyncContext)
24
  : private_(new InternalCallbackScope(Environment::GetCurrent(isolate),
25
                                       object,
26
647
                                       asyncContext)),
27
1294
    try_catch_(isolate) {
28
647
  try_catch_.SetVerbose(true);
29
647
}
30
31
1292
CallbackScope::~CallbackScope() {
32
646
  if (try_catch_.HasCaught())
33
1
    private_->MarkAsFailed();
34
646
  delete private_;
35
646
}
36
37
3676
InternalCallbackScope::InternalCallbackScope(AsyncWrap* async_wrap)
38
    : InternalCallbackScope(async_wrap->env(),
39
                            async_wrap->object(),
40
3676
                            { async_wrap->get_async_id(),
41
3676
                              async_wrap->get_trigger_async_id() }) {}
42
43
1194086
InternalCallbackScope::InternalCallbackScope(Environment* env,
44
                                             Local<Object> object,
45
                                             const async_context& asyncContext,
46
                                             ResourceExpectation expect)
47
  : env_(env),
48
    async_context_(asyncContext),
49
    object_(object),
50
1194086
    callback_scope_(env) {
51

2380581
  CHECK_IMPLIES(expect == kRequireResource, !object.IsEmpty());
52
1194316
  CHECK_NOT_NULL(env);
53
54
1194316
  if (!env->can_call_into_js()) {
55
1267
    failed_ = true;
56
1195621
    return;
57
  }
58
59
1193120
  HandleScope handle_scope(env->isolate());
60
  // If you hit this assertion, you forgot to enter the v8::Context first.
61
1193092
  CHECK_EQ(Environment::GetCurrent(env->isolate()), env);
62
63
1193090
  if (asyncContext.async_id != 0) {
64
    // No need to check a return value because the application will exit if
65
    // an exception occurs.
66
1107123
    AsyncWrap::EmitBefore(env, asyncContext.async_id);
67
  }
68
69
  env->async_hooks()->push_async_ids(async_context_.async_id,
70
1193085
                               async_context_.trigger_async_id);
71
1193063
  pushed_ids_ = true;
72
}
73
74
2388502
InternalCallbackScope::~InternalCallbackScope() {
75
1194251
  Close();
76
1194251
}
77
78
2369901
void InternalCallbackScope::Close() {
79
4137401
  if (closed_) return;
80
1194320
  closed_ = true;
81
82
1194320
  if (!env_->can_call_into_js()) return;
83


1193020
  if (failed_ && !env_->is_main_thread() && env_->is_stopping()) {
84
    env_->async_hooks()->clear_async_id_stack();
85
  }
86
87
1193013
  if (pushed_ids_)
88
1193014
    env_->async_hooks()->pop_async_id(async_context_.async_id);
89
90
1193025
  if (failed_) return;
91
92
1192463
  if (async_context_.async_id != 0) {
93
1107036
    AsyncWrap::EmitAfter(env_, async_context_.async_id);
94
  }
95
96
1192462
  if (env_->async_callback_scope_depth() > 1) {
97
292676
    return;
98
  }
99
100
899794
  TickInfo* tick_info = env_->tick_info();
101
102
899792
  if (!env_->can_call_into_js()) return;
103
899796
  if (!tick_info->has_tick_scheduled()) {
104
297798
    MicrotasksScope::PerformCheckpoint(env_->isolate());
105
  }
106
107
  // Make sure the stack unwound properly. If there are nested MakeCallback's
108
  // then it should return early and not reach this code.
109
899785
  if (env_->async_hooks()->fields()[AsyncHooks::kTotals]) {
110
37541
    CHECK_EQ(env_->execution_async_id(), 0);
111
37541
    CHECK_EQ(env_->trigger_async_id(), 0);
112
  }
113
114

899788
  if (!tick_info->has_tick_scheduled() && !tick_info->has_rejection_to_warn()) {
115
297379
    return;
116
  }
117
118
602406
  HandleScope handle_scope(env_->isolate());
119
602406
  Local<Object> process = env_->process_object();
120
121
602406
  if (!env_->can_call_into_js()) return;
122
123
602406
  Local<Function> tick_callback = env_->tick_callback_function();
124
125
  // The tick is triggered before JS land calls SetTickCallback
126
  // to initializes the tick callback during bootstrap.
127
602406
  CHECK(!tick_callback.IsEmpty());
128
129
1807141
  if (tick_callback->Call(env_->context(), process, 0, nullptr).IsEmpty()) {
130
550
    failed_ = true;
131
602329
  }
132
}
133
134
1176555
MaybeLocal<Value> InternalMakeCallback(Environment* env,
135
                                       Local<Object> recv,
136
                                       const Local<Function> callback,
137
                                       int argc,
138
                                       Local<Value> argv[],
139
                                       async_context asyncContext) {
140
1176555
  CHECK(!recv.IsEmpty());
141
#ifdef DEBUG
142
  for (int i = 0; i < argc; i++)
143
    CHECK(!argv[i].IsEmpty());
144
#endif
145
146
1176555
  InternalCallbackScope scope(env, recv, asyncContext);
147
1176696
  if (scope.Failed()) {
148
452
    return MaybeLocal<Value>();
149
  }
150
151
1176244
  Local<Function> domain_cb = env->domain_callback();
152
  MaybeLocal<Value> ret;
153


1251596
  if (asyncContext.async_id != 0 || domain_cb.IsEmpty() || recv.IsEmpty()) {
154
2348377
    ret = callback->Call(env->context(), recv, argc, argv);
155
  } else {
156
1990
    std::vector<Local<Value>> args(1 + argc);
157
3980
    args[0] = callback;
158
1990
    std::copy(&argv[0], &argv[argc], args.begin() + 1);
159
5970
    ret = domain_cb->Call(env->context(), recv, args.size(), &args[0]);
160
  }
161
162
1176235
  if (ret.IsEmpty()) {
163
586
    scope.MarkAsFailed();
164
586
    return MaybeLocal<Value>();
165
  }
166
167
1175649
  scope.Close();
168
1175583
  if (scope.Failed()) {
169
533
    return MaybeLocal<Value>();
170
  }
171
172
1175051
  return ret;
173
}
174
175
// Public MakeCallback()s
176
177
9417
MaybeLocal<Value> MakeCallback(Isolate* isolate,
178
                               Local<Object> recv,
179
                               const char* method,
180
                               int argc,
181
                               Local<Value> argv[],
182
                               async_context asyncContext) {
183
  Local<String> method_string =
184
      String::NewFromUtf8(isolate, method, NewStringType::kNormal)
185
18834
          .ToLocalChecked();
186
9417
  return MakeCallback(isolate, recv, method_string, argc, argv, asyncContext);
187
}
188
189
9426
MaybeLocal<Value> MakeCallback(Isolate* isolate,
190
                               Local<Object> recv,
191
                               Local<String> symbol,
192
                               int argc,
193
                               Local<Value> argv[],
194
                               async_context asyncContext) {
195
  Local<Value> callback_v =
196
28278
      recv->Get(isolate->GetCurrentContext(), symbol).ToLocalChecked();
197
9426
  if (callback_v.IsEmpty()) return Local<Value>();
198
9500
  if (!callback_v->IsFunction()) return Local<Value>();
199
9352
  Local<Function> callback = callback_v.As<Function>();
200
9352
  return MakeCallback(isolate, recv, callback, argc, argv, asyncContext);
201
}
202
203
73491
MaybeLocal<Value> MakeCallback(Isolate* isolate,
204
                               Local<Object> recv,
205
                               Local<Function> callback,
206
                               int argc,
207
                               Local<Value> argv[],
208
                               async_context asyncContext) {
209
  // Observe the following two subtleties:
210
  //
211
  // 1. The environment is retrieved from the callback function's context.
212
  // 2. The context to enter is retrieved from the environment.
213
  //
214
  // Because of the AssignToContext() call in src/node_contextify.cc,
215
  // the two contexts need not be the same.
216
73491
  Environment* env = Environment::GetCurrent(callback->CreationContext());
217
73491
  CHECK_NOT_NULL(env);
218
73491
  Context::Scope context_scope(env->context());
219
  MaybeLocal<Value> ret =
220
73491
      InternalMakeCallback(env, recv, callback, argc, argv, asyncContext);
221

73476
  if (ret.IsEmpty() && env->async_callback_scope_depth() == 0) {
222
    // This is only for legacy compatibility and we may want to look into
223
    // removing/adjusting it.
224
2078
    return Undefined(env->isolate());
225
  }
226
72437
  return ret;
227
}
228
229
// Legacy MakeCallback()s
230
231
Local<Value> MakeCallback(Isolate* isolate,
232
                          Local<Object> recv,
233
                          const char* method,
234
                          int argc,
235
                          Local<Value>* argv) {
236
  EscapableHandleScope handle_scope(isolate);
237
  return handle_scope.Escape(
238
      MakeCallback(isolate, recv, method, argc, argv, {0, 0})
239
          .FromMaybe(Local<Value>()));
240
}
241
242
Local<Value> MakeCallback(Isolate* isolate,
243
                          Local<Object> recv,
244
                          Local<String> symbol,
245
                          int argc,
246
                          Local<Value>* argv) {
247
  EscapableHandleScope handle_scope(isolate);
248
  return handle_scope.Escape(
249
      MakeCallback(isolate, recv, symbol, argc, argv, {0, 0})
250
          .FromMaybe(Local<Value>()));
251
}
252
253
Local<Value> MakeCallback(Isolate* isolate,
254
                          Local<Object> recv,
255
                          Local<Function> callback,
256
                          int argc,
257
                          Local<Value>* argv) {
258
  EscapableHandleScope handle_scope(isolate);
259
  return handle_scope.Escape(
260
      MakeCallback(isolate, recv, callback, argc, argv, {0, 0})
261
          .FromMaybe(Local<Value>()));
262
}
263
264
}  // namespace node