diff --git a/src/async-wrap.cc b/src/async-wrap.cc index 4ba7d1ad4a4d8d..26332ce3562660 100644 --- a/src/async-wrap.cc +++ b/src/async-wrap.cc @@ -151,32 +151,37 @@ static void SetupHooks(const FunctionCallbackInfo& args) { if (!args[0]->IsObject()) return env->ThrowTypeError("first argument must be an object"); + // All of init, before, after, destroy are supplied by async_hooks + // internally, so this should every only be called once. At which time all + // the functions should be set. Detect this by checking if init !IsEmpty() + // and returning early if that's the case. + if (!env->async_hooks_init_function().IsEmpty()) + return env->ThrowError("async_hook callbacks have already been setup"); + Local fn_obj = args[0].As(); Local init_v = fn_obj->Get( env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), "init")).ToLocalChecked(); - Local pre_v = fn_obj->Get( + Local before_v = fn_obj->Get( env->context(), - FIXED_ONE_BYTE_STRING(env->isolate(), "pre")).ToLocalChecked(); - Local post_v = fn_obj->Get( + FIXED_ONE_BYTE_STRING(env->isolate(), "before")).ToLocalChecked(); + Local after_v = fn_obj->Get( env->context(), - FIXED_ONE_BYTE_STRING(env->isolate(), "post")).ToLocalChecked(); + FIXED_ONE_BYTE_STRING(env->isolate(), "after")).ToLocalChecked(); Local destroy_v = fn_obj->Get( env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), "destroy")).ToLocalChecked(); - if (!init_v->IsFunction()) - return env->ThrowTypeError("init callback must be a function"); + if (!init_v->IsFunction() || !before_v->IsFunction() || + !after_v->IsFunction() || !destroy_v->IsFunction()) { + return env->ThrowTypeError("all callbacks must be functions"); + } env->set_async_hooks_init_function(init_v.As()); - - if (pre_v->IsFunction()) - env->set_async_hooks_pre_function(pre_v.As()); - if (post_v->IsFunction()) - env->set_async_hooks_post_function(post_v.As()); - if (destroy_v->IsFunction()) - env->set_async_hooks_destroy_function(destroy_v.As()); + env->set_async_hooks_before_function(before_v.As()); + env->set_async_hooks_after_function(after_v.As()); + env->set_async_hooks_destroy_function(destroy_v.As()); } @@ -200,8 +205,8 @@ void AsyncWrap::Initialize(Local target, target->Set(FIXED_ONE_BYTE_STRING(isolate, "Providers"), async_providers); env->set_async_hooks_init_function(Local()); - env->set_async_hooks_pre_function(Local()); - env->set_async_hooks_post_function(Local()); + env->set_async_hooks_before_function(Local()); + env->set_async_hooks_after_function(Local()); env->set_async_hooks_destroy_function(Local()); } @@ -328,8 +333,8 @@ Local AsyncWrap::MakeCallback(const Local cb, Local* argv) { CHECK(env()->context() == env()->isolate()->GetCurrentContext()); - Local pre_fn = env()->async_hooks_pre_function(); - Local post_fn = env()->async_hooks_post_function(); + Local before_fn = env()->async_hooks_before_function(); + Local after_fn = env()->async_hooks_after_function(); Local uid = Number::New(env()->isolate(), get_id()); Local context = object(); Local domain; @@ -357,9 +362,9 @@ Local AsyncWrap::MakeCallback(const Local cb, } } - if (ran_init_callback() && !pre_fn.IsEmpty()) { + if (ran_init_callback() && !before_fn.IsEmpty()) { TryCatch try_catch(env()->isolate()); - MaybeLocal ar = pre_fn->Call(env()->context(), context, 1, &uid); + MaybeLocal ar = before_fn->Call(env()->context(), context, 1, &uid); if (ar.IsEmpty()) { ClearFatalExceptionHandlers(env()); FatalException(env()->isolate(), try_catch); @@ -369,12 +374,12 @@ Local AsyncWrap::MakeCallback(const Local cb, Local ret = cb->Call(context, argc, argv); - if (ran_init_callback() && !post_fn.IsEmpty()) { + if (ran_init_callback() && !after_fn.IsEmpty()) { Local did_throw = Boolean::New(env()->isolate(), ret.IsEmpty()); Local vals[] = { uid, did_throw }; TryCatch try_catch(env()->isolate()); MaybeLocal ar = - post_fn->Call(env()->context(), context, arraysize(vals), vals); + after_fn->Call(env()->context(), context, arraysize(vals), vals); if (ar.IsEmpty()) { ClearFatalExceptionHandlers(env()); FatalException(env()->isolate(), try_catch); diff --git a/src/env.h b/src/env.h index d26f2d2132dedc..ed59a29f8ce95c 100644 --- a/src/env.h +++ b/src/env.h @@ -245,8 +245,8 @@ namespace node { V(as_external, v8::External) \ V(async_hooks_destroy_function, v8::Function) \ V(async_hooks_init_function, v8::Function) \ - V(async_hooks_post_function, v8::Function) \ - V(async_hooks_pre_function, v8::Function) \ + V(async_hooks_before_function, v8::Function) \ + V(async_hooks_after_function, v8::Function) \ V(binding_cache_object, v8::Object) \ V(buffer_constructor_function, v8::Function) \ V(buffer_prototype_object, v8::Object) \ diff --git a/src/node.cc b/src/node.cc index fda6c3f257730b..e386c4265d4e2b 100644 --- a/src/node.cc +++ b/src/node.cc @@ -1228,8 +1228,8 @@ Local MakeCallback(Environment* env, // If you hit this assertion, you forgot to enter the v8::Context first. CHECK_EQ(env->context(), env->isolate()->GetCurrentContext()); - Local pre_fn = env->async_hooks_pre_function(); - Local post_fn = env->async_hooks_post_function(); + Local before_fn = env->async_hooks_before_function(); + Local after_fn = env->async_hooks_after_function(); Local object, domain; bool ran_init_callback = false; bool has_domain = false; @@ -1266,9 +1266,9 @@ Local MakeCallback(Environment* env, } } - if (ran_init_callback && !pre_fn.IsEmpty()) { + if (ran_init_callback && !before_fn.IsEmpty()) { TryCatch try_catch(env->isolate()); - MaybeLocal ar = pre_fn->Call(env->context(), object, 0, nullptr); + MaybeLocal ar = before_fn->Call(env->context(), object, 0, nullptr); if (ar.IsEmpty()) { ClearFatalExceptionHandlers(env); FatalException(env->isolate(), try_catch); @@ -1278,7 +1278,7 @@ Local MakeCallback(Environment* env, Local ret = callback->Call(recv, argc, argv); - if (ran_init_callback && !post_fn.IsEmpty()) { + if (ran_init_callback && !after_fn.IsEmpty()) { Local did_throw = Boolean::New(env->isolate(), ret.IsEmpty()); // Currently there's no way to retrieve an uid from node::MakeCallback(). // This needs to be fixed. @@ -1286,7 +1286,7 @@ Local MakeCallback(Environment* env, { Undefined(env->isolate()).As(), did_throw }; TryCatch try_catch(env->isolate()); MaybeLocal ar = - post_fn->Call(env->context(), object, arraysize(vals), vals); + after_fn->Call(env->context(), object, arraysize(vals), vals); if (ar.IsEmpty()) { ClearFatalExceptionHandlers(env); FatalException(env->isolate(), try_catch);