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-02-23 22:23:05 Branches: 73 90 81.1 %

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
using AsyncHooks = Environment::AsyncHooks;
21
22
630
CallbackScope::CallbackScope(Isolate* isolate,
23
                             Local<Object> object,
24
                             async_context asyncContext)
25
  : private_(new InternalCallbackScope(Environment::GetCurrent(isolate),
26
                                       object,
27
630
                                       asyncContext)),
28
1260
    try_catch_(isolate) {
29
630
  try_catch_.SetVerbose(true);
30
630
}
31
32
1258
CallbackScope::~CallbackScope() {
33
629
  if (try_catch_.HasCaught())
34
1
    private_->MarkAsFailed();
35
629
  delete private_;
36
629
}
37
38
1582
InternalCallbackScope::InternalCallbackScope(AsyncWrap* async_wrap)
39
    : InternalCallbackScope(async_wrap->env(),
40
                            async_wrap->object(),
41
1582
                            { async_wrap->get_async_id(),
42
1582
                              async_wrap->get_trigger_async_id() }) {}
43
44
1233555
InternalCallbackScope::InternalCallbackScope(Environment* env,
45
                                             Local<Object> object,
46
                                             const async_context& asyncContext,
47
                                             ResourceExpectation expect)
48
  : env_(env),
49
    async_context_(asyncContext),
50
    object_(object),
51
1233555
    callback_scope_(env) {
52

2435323
  CHECK_IMPLIES(expect == kRequireResource, !object.IsEmpty());
53
1233558
  CHECK_NOT_NULL(env);
54
55
1233558
  if (!env->can_call_into_js()) {
56
4452
    failed_ = true;
57
1238007
    return;
58
  }
59
60
1229104
  HandleScope handle_scope(env->isolate());
61
  // If you hit this assertion, you forgot to enter the v8::Context first.
62
1229101
  CHECK_EQ(Environment::GetCurrent(env->isolate()), env);
63
64
1229104
  if (asyncContext.async_id != 0) {
65
    // No need to check a return value because the application will exit if
66
    // an exception occurs.
67
1128138
    AsyncWrap::EmitBefore(env, asyncContext.async_id);
68
  }
69
70
  env->async_hooks()->push_async_ids(async_context_.async_id,
71
1229106
                               async_context_.trigger_async_id);
72
1229103
  pushed_ids_ = true;
73
}
74
75
2466836
InternalCallbackScope::~InternalCallbackScope() {
76
1233419
  Close();
77
1233417
}
78
79
2426076
void InternalCallbackScope::Close() {
80
4283879
  if (closed_) return;
81
1233491
  closed_ = true;
82
1233491
  HandleScope handle_scope(env_->isolate());
83
84
1233490
  if (!env_->can_call_into_js()) return;
85


1229008
  if (failed_ && !env_->is_main_thread() && env_->is_stopping_worker()) {
86
    env_->async_hooks()->clear_async_id_stack();
87
  }
88
89
1229008
  if (pushed_ids_)
90
1229008
    env_->async_hooks()->pop_async_id(async_context_.async_id);
91
92
1229008
  if (failed_) return;
93
94
1228446
  if (async_context_.async_id != 0) {
95
1128052
    AsyncWrap::EmitAfter(env_, async_context_.async_id);
96
  }
97
98
1228446
  if (env_->makecallback_depth() > 1) {
99
217079
    return;
100
  }
101
102
1011367
  Environment::TickInfo* tick_info = env_->tick_info();
103
104
1011367
  if (!env_->can_call_into_js()) return;
105
1011367
  if (!tick_info->has_tick_scheduled()) {
106
443475
    env_->isolate()->RunMicrotasks();
107
  }
108
109
  // Make sure the stack unwound properly. If there are nested MakeCallback's
110
  // then it should return early and not reach this code.
111
1011361
  if (env_->async_hooks()->fields()[AsyncHooks::kTotals]) {
112
37265
    CHECK_EQ(env_->execution_async_id(), 0);
113
37265
    CHECK_EQ(env_->trigger_async_id(), 0);
114
  }
115
116

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


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

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