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-07-27 22:37:30 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::NewStringType;
16
using v8::Object;
17
using v8::String;
18
using v8::Value;
19
20
647
CallbackScope::CallbackScope(Isolate* isolate,
21
                             Local<Object> object,
22
                             async_context asyncContext)
23
  : private_(new InternalCallbackScope(Environment::GetCurrent(isolate),
24
                                       object,
25
647
                                       asyncContext)),
26
1294
    try_catch_(isolate) {
27
647
  try_catch_.SetVerbose(true);
28
647
}
29
30
1292
CallbackScope::~CallbackScope() {
31
646
  if (try_catch_.HasCaught())
32
1
    private_->MarkAsFailed();
33
646
  delete private_;
34
646
}
35
36
2672
InternalCallbackScope::InternalCallbackScope(AsyncWrap* async_wrap)
37
    : InternalCallbackScope(async_wrap->env(),
38
                            async_wrap->object(),
39
2672
                            { async_wrap->get_async_id(),
40
2672
                              async_wrap->get_trigger_async_id() }) {}
41
42
1010563
InternalCallbackScope::InternalCallbackScope(Environment* env,
43
                                             Local<Object> object,
44
                                             const async_context& asyncContext,
45
                                             ResourceExpectation expect)
46
  : env_(env),
47
    async_context_(asyncContext),
48
    object_(object),
49
1010563
    callback_scope_(env) {
50

2014151
  CHECK_IMPLIES(expect == kRequireResource, !object.IsEmpty());
51
1010566
  CHECK_NOT_NULL(env);
52
53
1010566
  if (!env->can_call_into_js()) {
54
517
    failed_ = true;
55
1011079
    return;
56
  }
57
58
1010050
  HandleScope handle_scope(env->isolate());
59
  // If you hit this assertion, you forgot to enter the v8::Context first.
60
1010042
  CHECK_EQ(Environment::GetCurrent(env->isolate()), env);
61
62
1010064
  if (asyncContext.async_id != 0) {
63
    // No need to check a return value because the application will exit if
64
    // an exception occurs.
65
932746
    AsyncWrap::EmitBefore(env, asyncContext.async_id);
66
  }
67
68
  env->async_hooks()->push_async_ids(async_context_.async_id,
69
1010052
                               async_context_.trigger_async_id);
70
1010043
  pushed_ids_ = true;
71
}
72
73
2020859
InternalCallbackScope::~InternalCallbackScope() {
74
1010430
  Close();
75
1010431
}
76
77
2004613
void InternalCallbackScope::Close() {
78
3491700
  if (closed_) return;
79
1010509
  closed_ = true;
80
81
1010509
  if (!env_->can_call_into_js()) return;
82


1009965
  if (failed_ && !env_->is_main_thread() && env_->is_stopping()) {
83
    env_->async_hooks()->clear_async_id_stack();
84
  }
85
86
1009964
  if (pushed_ids_)
87
1009964
    env_->async_hooks()->pop_async_id(async_context_.async_id);
88
89
1009965
  if (failed_) return;
90
91
1009403
  if (async_context_.async_id != 0) {
92
932658
    AsyncWrap::EmitAfter(env_, async_context_.async_id);
93
  }
94
95
1009403
  if (env_->async_callback_scope_depth() > 1) {
96
203128
    return;
97
  }
98
99
806276
  TickInfo* tick_info = env_->tick_info();
100
101
806275
  if (!env_->can_call_into_js()) return;
102
806274
  if (!tick_info->has_tick_scheduled()) {
103
289103
    env_->isolate()->RunMicrotasks();
104
  }
105
106
  // Make sure the stack unwound properly. If there are nested MakeCallback's
107
  // then it should return early and not reach this code.
108
806267
  if (env_->async_hooks()->fields()[AsyncHooks::kTotals]) {
109
37580
    CHECK_EQ(env_->execution_async_id(), 0);
110
37580
    CHECK_EQ(env_->trigger_async_id(), 0);
111
  }
112
113

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


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

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