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: 102 115 88.7 %
Date: 2020-02-27 22:14:15 Branches: 79 94 84.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
647
                             async_context asyncContext)
24
647
  : 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
34831
InternalCallbackScope::InternalCallbackScope(AsyncWrap* async_wrap, int flags)
38
    : InternalCallbackScope(async_wrap->env(),
39
                            async_wrap->GetResource(),
40
34831
                            { async_wrap->get_async_id(),
41
34831
                              async_wrap->get_trigger_async_id() },
42
69662
                            flags) {}
43
44
648250
InternalCallbackScope::InternalCallbackScope(Environment* env,
45
                                             Local<Object> object,
46
                                             const async_context& asyncContext,
47
648250
                                             int flags)
48
  : env_(env),
49
    async_context_(asyncContext),
50
    object_(object),
51
648250
    skip_hooks_(flags & kSkipAsyncHooks),
52
1296500
    skip_task_queues_(flags & kSkipTaskQueues) {
53
648250
  CHECK_NOT_NULL(env);
54
648250
  env->PushAsyncCallbackScope();
55
56
648372
  if (!env->can_call_into_js()) {
57
608
    failed_ = true;
58
608
    return;
59
  }
60
61
1295513
  HandleScope handle_scope(env->isolate());
62
  // If you hit this assertion, you forgot to enter the v8::Context first.
63
647748
  CHECK_EQ(Environment::GetCurrent(env->isolate()), env);
64
65
1295533
  env->async_hooks()->push_async_context(
66
647767
    async_context_.async_id, async_context_.trigger_async_id, object);
67
68
647761
  pushed_ids_ = true;
69
70

647761
  if (asyncContext.async_id != 0 && !skip_hooks_) {
71
    // No need to check a return value because the application will exit if
72
    // an exception occurs.
73
594853
    AsyncWrap::EmitBefore(env, asyncContext.async_id);
74
  }
75
}
76
77
1295965
InternalCallbackScope::~InternalCallbackScope() {
78
647995
  Close();
79
647974
  env_->PopAsyncCallbackScope();
80
647970
}
81
82
1244561
void InternalCallbackScope::Close() {
83
2089622
  if (closed_) return;
84
648068
  closed_ = true;
85
86
648068
  if (!env_->can_call_into_js()) return;
87


647417
  if (failed_ && !env_->is_main_thread() && env_->is_stopping()) {
88
    env_->async_hooks()->clear_async_id_stack();
89
  }
90
91

647424
  if (!failed_ && async_context_.async_id != 0 && !skip_hooks_) {
92
594752
    AsyncWrap::EmitAfter(env_, async_context_.async_id);
93
  }
94
95
647378
  if (pushed_ids_)
96
647378
    env_->async_hooks()->pop_async_context(async_context_.async_id);
97
98
647428
  if (failed_) return;
99
100

646859
  if (env_->async_callback_scope_depth() > 1 || skip_task_queues_) {
101
61533
    return;
102
  }
103
104
585329
  TickInfo* tick_info = env_->tick_info();
105
106
585328
  if (!env_->can_call_into_js()) return;
107
108
1569947
  auto weakref_cleanup = OnScopeLeave([&]() { env_->RunWeakRefCleanup(); });
109
110
585318
  if (!tick_info->has_tick_scheduled()) {
111
186226
    MicrotasksScope::PerformCheckpoint(env_->isolate());
112
  }
113
114
  // Make sure the stack unwound properly. If there are nested MakeCallback's
115
  // then it should return early and not reach this code.
116
585318
  if (env_->async_hooks()->fields()[AsyncHooks::kTotals]) {
117
37490
    CHECK_EQ(env_->execution_async_id(), 0);
118
37490
    CHECK_EQ(env_->trigger_async_id(), 0);
119
  }
120
121

585317
  if (!tick_info->has_tick_scheduled() && !tick_info->has_rejection_to_warn()) {
122
185823
    return;
123
  }
124
125
798901
  HandleScope handle_scope(env_->isolate());
126
399498
  Local<Object> process = env_->process_object();
127
128
399498
  if (!env_->can_call_into_js()) return;
129
130
399498
  Local<Function> tick_callback = env_->tick_callback_function();
131
132
  // The tick is triggered before JS land calls SetTickCallback
133
  // to initializes the tick callback during bootstrap.
134
399498
  CHECK(!tick_callback.IsEmpty());
135
136
1198399
  if (tick_callback->Call(env_->context(), process, 0, nullptr).IsEmpty()) {
137
566
    failed_ = true;
138
  }
139
}
140
141
597644
MaybeLocal<Value> InternalMakeCallback(Environment* env,
142
                                       Local<Object> recv,
143
                                       const Local<Function> callback,
144
                                       int argc,
145
                                       Local<Value> argv[],
146
                                       async_context asyncContext) {
147
597644
  CHECK(!recv.IsEmpty());
148
#ifdef DEBUG
149
  for (int i = 0; i < argc; i++)
150
    CHECK(!argv[i].IsEmpty());
151
#endif
152
153
1195236
  InternalCallbackScope scope(env, recv, asyncContext);
154
597698
  if (scope.Failed()) {
155
498
    return MaybeLocal<Value>();
156
  }
157
158
597199
  Local<Function> domain_cb = env->domain_callback();
159
  MaybeLocal<Value> ret;
160

635034
  if (asyncContext.async_id != 0 || domain_cb.IsEmpty()) {
161
1191231
    ret = callback->Call(env->context(), recv, argc, argv);
162
  } else {
163
3194
    std::vector<Local<Value>> args(1 + argc);
164
3196
    args[0] = callback;
165
1598
    std::copy(&argv[0], &argv[argc], args.begin() + 1);
166
4794
    ret = domain_cb->Call(env->context(), recv, args.size(), &args[0]);
167
  }
168
169
597173
  if (ret.IsEmpty()) {
170
589
    scope.MarkAsFailed();
171
589
    return MaybeLocal<Value>();
172
  }
173
174
596584
  scope.Close();
175
596505
  if (scope.Failed()) {
176
529
    return MaybeLocal<Value>();
177
  }
178
179
595976
  return ret;
180
}
181
182
// Public MakeCallback()s
183
184
7909
MaybeLocal<Value> MakeCallback(Isolate* isolate,
185
                               Local<Object> recv,
186
                               const char* method,
187
                               int argc,
188
                               Local<Value> argv[],
189
                               async_context asyncContext) {
190
  Local<String> method_string =
191
15818
      String::NewFromUtf8(isolate, method, NewStringType::kNormal)
192
7909
          .ToLocalChecked();
193
7909
  return MakeCallback(isolate, recv, method_string, argc, argv, asyncContext);
194
}
195
196
7919
MaybeLocal<Value> MakeCallback(Isolate* isolate,
197
                               Local<Object> recv,
198
                               Local<String> symbol,
199
                               int argc,
200
                               Local<Value> argv[],
201
                               async_context asyncContext) {
202
  Local<Value> callback_v =
203
23759
      recv->Get(isolate->GetCurrentContext(), symbol).ToLocalChecked();
204
7919
  if (callback_v.IsEmpty()) return Local<Value>();
205
7992
  if (!callback_v->IsFunction()) return Local<Value>();
206
7848
  Local<Function> callback = callback_v.As<Function>();
207
7848
  return MakeCallback(isolate, recv, callback, argc, argv, asyncContext);
208
}
209
210
37845
MaybeLocal<Value> MakeCallback(Isolate* isolate,
211
                               Local<Object> recv,
212
                               Local<Function> callback,
213
                               int argc,
214
                               Local<Value> argv[],
215
                               async_context asyncContext) {
216
  // Observe the following two subtleties:
217
  //
218
  // 1. The environment is retrieved from the callback function's context.
219
  // 2. The context to enter is retrieved from the environment.
220
  //
221
  // Because of the AssignToContext() call in src/node_contextify.cc,
222
  // the two contexts need not be the same.
223
37845
  Environment* env = Environment::GetCurrent(callback->CreationContext());
224
37845
  CHECK_NOT_NULL(env);
225
37845
  Context::Scope context_scope(env->context());
226
  MaybeLocal<Value> ret =
227
37843
      InternalMakeCallback(env, recv, callback, argc, argv, asyncContext);
228

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