Skip to content

Commit 60a2fe7

Browse files
addaleaxjasnell
authored andcommitted
async_hooks: implement C++ embedder API
PR-URL: #13142 Reviewed-By: Matthew Loring <mattloring@google.com> Reviewed-By: Andreas Madsen <amwebdk@gmail.com> Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com>
1 parent 220186c commit 60a2fe7

7 files changed

+342
-152
lines changed

src/async-wrap.cc

+89-32
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ using v8::Object;
4747
using v8::Promise;
4848
using v8::PromiseHookType;
4949
using v8::RetainedObjectInfo;
50+
using v8::String;
5051
using v8::Symbol;
5152
using v8::TryCatch;
5253
using v8::Uint32Array;
@@ -216,23 +217,28 @@ bool DomainExit(Environment* env, v8::Local<v8::Object> object) {
216217

217218

218219
static bool PreCallbackExecution(AsyncWrap* wrap, bool run_domain_cbs) {
219-
AsyncHooks* async_hooks = wrap->env()->async_hooks();
220-
221220
if (wrap->env()->using_domains() && run_domain_cbs) {
222221
bool is_disposed = DomainEnter(wrap->env(), wrap->object());
223222
if (is_disposed)
224223
return false;
225224
}
226225

226+
return AsyncWrap::EmitBefore(wrap->env(), wrap->get_id());
227+
}
228+
229+
230+
bool AsyncWrap::EmitBefore(Environment* env, double async_id) {
231+
AsyncHooks* async_hooks = env->async_hooks();
232+
227233
if (async_hooks->fields()[AsyncHooks::kBefore] > 0) {
228-
Local<Value> uid = Number::New(wrap->env()->isolate(), wrap->get_id());
229-
Local<Function> fn = wrap->env()->async_hooks_before_function();
230-
TryCatch try_catch(wrap->env()->isolate());
234+
Local<Value> uid = Number::New(env->isolate(), async_id);
235+
Local<Function> fn = env->async_hooks_before_function();
236+
TryCatch try_catch(env->isolate());
231237
MaybeLocal<Value> ar = fn->Call(
232-
wrap->env()->context(), Undefined(wrap->env()->isolate()), 1, &uid);
238+
env->context(), Undefined(env->isolate()), 1, &uid);
233239
if (ar.IsEmpty()) {
234-
ClearFatalExceptionHandlers(wrap->env());
235-
FatalException(wrap->env()->isolate(), try_catch);
240+
ClearFatalExceptionHandlers(env);
241+
FatalException(env->isolate(), try_catch);
236242
return false;
237243
}
238244
}
@@ -242,29 +248,36 @@ static bool PreCallbackExecution(AsyncWrap* wrap, bool run_domain_cbs) {
242248

243249

244250
static bool PostCallbackExecution(AsyncWrap* wrap, bool run_domain_cbs) {
245-
AsyncHooks* async_hooks = wrap->env()->async_hooks();
251+
if (!AsyncWrap::EmitAfter(wrap->env(), wrap->get_id()))
252+
return false;
253+
254+
if (wrap->env()->using_domains() && run_domain_cbs) {
255+
bool is_disposed = DomainExit(wrap->env(), wrap->object());
256+
if (is_disposed)
257+
return false;
258+
}
259+
260+
return true;
261+
}
262+
263+
bool AsyncWrap::EmitAfter(Environment* env, double async_id) {
264+
AsyncHooks* async_hooks = env->async_hooks();
246265

247266
// If the callback failed then the after() hooks will be called at the end
248267
// of _fatalException().
249268
if (async_hooks->fields()[AsyncHooks::kAfter] > 0) {
250-
Local<Value> uid = Number::New(wrap->env()->isolate(), wrap->get_id());
251-
Local<Function> fn = wrap->env()->async_hooks_after_function();
252-
TryCatch try_catch(wrap->env()->isolate());
269+
Local<Value> uid = Number::New(env->isolate(), async_id);
270+
Local<Function> fn = env->async_hooks_after_function();
271+
TryCatch try_catch(env->isolate());
253272
MaybeLocal<Value> ar = fn->Call(
254-
wrap->env()->context(), Undefined(wrap->env()->isolate()), 1, &uid);
273+
env->context(), Undefined(env->isolate()), 1, &uid);
255274
if (ar.IsEmpty()) {
256-
ClearFatalExceptionHandlers(wrap->env());
257-
FatalException(wrap->env()->isolate(), try_catch);
275+
ClearFatalExceptionHandlers(env);
276+
FatalException(env->isolate(), try_catch);
258277
return false;
259278
}
260279
}
261280

262-
if (wrap->env()->using_domains() && run_domain_cbs) {
263-
bool is_disposed = DomainExit(wrap->env(), wrap->object());
264-
if (is_disposed)
265-
return false;
266-
}
267-
268281
return true;
269282
}
270283

@@ -526,32 +539,44 @@ AsyncWrap::~AsyncWrap() {
526539
// and reused over their lifetime. This way a new uid can be assigned when
527540
// the resource is pulled out of the pool and put back into use.
528541
void AsyncWrap::AsyncReset() {
529-
AsyncHooks* async_hooks = env()->async_hooks();
530542
async_id_ = env()->new_async_id();
531543
trigger_id_ = env()->get_init_trigger_id();
532544

545+
EmitAsyncInit(env(), object(),
546+
env()->async_hooks()->provider_string(provider_type()),
547+
async_id_, trigger_id_);
548+
}
549+
550+
551+
void AsyncWrap::EmitAsyncInit(Environment* env,
552+
Local<Object> object,
553+
Local<String> type,
554+
double async_id,
555+
double trigger_id) {
556+
AsyncHooks* async_hooks = env->async_hooks();
557+
533558
// Nothing to execute, so can continue normally.
534559
if (async_hooks->fields()[AsyncHooks::kInit] == 0) {
535560
return;
536561
}
537562

538-
HandleScope scope(env()->isolate());
539-
Local<Function> init_fn = env()->async_hooks_init_function();
563+
HandleScope scope(env->isolate());
564+
Local<Function> init_fn = env->async_hooks_init_function();
540565

541566
Local<Value> argv[] = {
542-
Number::New(env()->isolate(), get_id()),
543-
env()->async_hooks()->provider_string(provider_type()),
544-
object(),
545-
Number::New(env()->isolate(), get_trigger_id()),
567+
Number::New(env->isolate(), async_id),
568+
type,
569+
object,
570+
Number::New(env->isolate(), trigger_id),
546571
};
547572

548-
TryCatch try_catch(env()->isolate());
573+
TryCatch try_catch(env->isolate());
549574
MaybeLocal<Value> ret = init_fn->Call(
550-
env()->context(), object(), arraysize(argv), argv);
575+
env->context(), object, arraysize(argv), argv);
551576

552577
if (ret.IsEmpty()) {
553-
ClearFatalExceptionHandlers(env());
554-
FatalException(env()->isolate(), try_catch);
578+
ClearFatalExceptionHandlers(env);
579+
FatalException(env->isolate(), try_catch);
555580
}
556581
}
557582

@@ -620,6 +645,38 @@ Local<Value> AsyncWrap::MakeCallback(const Local<Function> cb,
620645
return rcheck.IsEmpty() ? Local<Value>() : ret_v;
621646
}
622647

648+
649+
/* Public C++ embedder API */
650+
651+
652+
async_uid AsyncHooksGetCurrentId(Isolate* isolate) {
653+
return Environment::GetCurrent(isolate)->current_async_id();
654+
}
655+
656+
657+
async_uid AsyncHooksGetTriggerId(Isolate* isolate) {
658+
return Environment::GetCurrent(isolate)->get_init_trigger_id();
659+
}
660+
661+
662+
async_uid EmitAsyncInit(Isolate* isolate,
663+
Local<Object> resource,
664+
const char* name,
665+
async_uid trigger_id) {
666+
Environment* env = Environment::GetCurrent(isolate);
667+
async_uid async_id = env->new_async_id();
668+
669+
Local<String> type =
670+
String::NewFromUtf8(isolate, name, v8::NewStringType::kInternalized)
671+
.ToLocalChecked();
672+
AsyncWrap::EmitAsyncInit(env, resource, type, async_id, trigger_id);
673+
return async_id;
674+
}
675+
676+
void EmitAsyncDestroy(Isolate* isolate, async_uid id) {
677+
PushBackDestroyId(Environment::GetCurrent(isolate), id);
678+
}
679+
623680
} // namespace node
624681

625682
NODE_MODULE_CONTEXT_AWARE_BUILTIN(async_wrap, node::AsyncWrap::Initialize)

src/async-wrap.h

+9
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,15 @@ class AsyncWrap : public BaseObject {
101101
static void AsyncReset(const v8::FunctionCallbackInfo<v8::Value>& args);
102102
static void QueueDestroyId(const v8::FunctionCallbackInfo<v8::Value>& args);
103103

104+
static void EmitAsyncInit(Environment* env,
105+
v8::Local<v8::Object> object,
106+
v8::Local<v8::String> type,
107+
double id,
108+
double trigger_id);
109+
110+
static bool EmitBefore(Environment* env, double id);
111+
static bool EmitAfter(Environment* env, double id);
112+
104113
inline ProviderType provider_type() const;
105114

106115
inline double get_id() const;

src/inspector_agent.cc

+2-2
Original file line numberDiff line numberDiff line change
@@ -597,8 +597,8 @@ bool Agent::StartIoThread(bool wait_for_connect) {
597597
FIXED_ONE_BYTE_STRING(isolate, "internalMessage"),
598598
message
599599
};
600-
MakeCallback(parent_env_, process_object.As<Value>(), emit_fn.As<Function>(),
601-
arraysize(argv), argv);
600+
MakeCallback(parent_env_->isolate(), process_object, emit_fn.As<Function>(),
601+
arraysize(argv), argv, 0, 0);
602602

603603
return true;
604604
}

0 commit comments

Comments
 (0)