summaryrefslogtreecommitdiff
path: root/src/async_wrap.cc
diff options
context:
space:
mode:
authorStephen Belanger <stephen.belanger@datadoghq.com>2021-06-23 22:35:46 -0700
committerNode.js GitHub Bot <github-bot@iojs.org>2021-07-23 03:54:31 +0000
commit84dfa1f3e315b8016264dce46e6782bb55693917 (patch)
tree9726eb6f8728cdaac49c4760d15810d8ef8ceb90 /src/async_wrap.cc
parent44ee6c26232622c286d7b221f07b7014b031e064 (diff)
downloadnode-new-84dfa1f3e315b8016264dce46e6782bb55693917.tar.gz
async_hooks: eliminate native PromiseHook
PR-URL: https://github.com/nodejs/node/pull/39135 Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Gerhard Stöbich <deb2001-github@yahoo.de>
Diffstat (limited to 'src/async_wrap.cc')
-rw-r--r--src/async_wrap.cc287
1 files changed, 0 insertions, 287 deletions
diff --git a/src/async_wrap.cc b/src/async_wrap.cc
index 1bca27d6a0..3fb2f8c309 100644
--- a/src/async_wrap.cc
+++ b/src/async_wrap.cc
@@ -39,19 +39,12 @@ using v8::Global;
using v8::HandleScope;
using v8::Integer;
using v8::Isolate;
-using v8::Just;
using v8::Local;
-using v8::Maybe;
using v8::MaybeLocal;
-using v8::Name;
using v8::Nothing;
using v8::Number;
using v8::Object;
-using v8::ObjectTemplate;
-using v8::Promise;
-using v8::PromiseHookType;
using v8::PropertyAttribute;
-using v8::PropertyCallbackInfo;
using v8::ReadOnly;
using v8::String;
using v8::Undefined;
@@ -161,255 +154,6 @@ void AsyncWrap::EmitAfter(Environment* env, double async_id) {
// TODO(addaleax): Remove once we're on C++17.
constexpr double AsyncWrap::kInvalidAsyncId;
-static Maybe<double> GetAssignedPromiseAsyncId(Environment* env,
- Local<Promise> promise,
- Local<Value> id_symbol) {
- Local<Value> maybe_async_id;
- if (!promise->Get(env->context(), id_symbol).ToLocal(&maybe_async_id)) {
- return Nothing<double>();
- }
- return maybe_async_id->IsNumber()
- ? maybe_async_id->NumberValue(env->context())
- : Just(AsyncWrap::kInvalidAsyncId);
-}
-
-class PromiseWrap : public AsyncWrap {
- public:
- PromiseWrap(Environment* env, Local<Object> object, bool silent)
- : AsyncWrap(env, object, PROVIDER_PROMISE, kInvalidAsyncId, silent) {
- MakeWeak();
- }
-
- PromiseWrap(Environment* env, Local<Object> object, double asyncId,
- double triggerAsyncId)
- : AsyncWrap(env, object, PROVIDER_PROMISE, asyncId, triggerAsyncId) {
- MakeWeak();
- }
-
- SET_NO_MEMORY_INFO()
- SET_MEMORY_INFO_NAME(PromiseWrap)
- SET_SELF_SIZE(PromiseWrap)
-
- static PromiseWrap* New(Environment* env,
- Local<Promise> promise,
- bool silent);
- static void GetAsyncId(Local<Name> property,
- const PropertyCallbackInfo<Value>& args);
- static void GetTriggerAsyncId(Local<Name> property,
- const PropertyCallbackInfo<Value>& args);
-
- static void Initialize(Environment* env);
-};
-
-PromiseWrap* PromiseWrap::New(Environment* env,
- Local<Promise> promise,
- bool silent) {
- Local<Context> context = env->context();
-
- Local<Object> obj;
- if (!env->promise_wrap_template()->NewInstance(context).ToLocal(&obj))
- return nullptr;
-
- CHECK_NULL(promise->GetAlignedPointerFromInternalField(0));
- promise->SetInternalField(0, obj);
-
- // Skip for init events
- if (silent) {
- double async_id;
- double trigger_async_id;
- if (!GetAssignedPromiseAsyncId(env, promise, env->async_id_symbol())
- .To(&async_id)) return nullptr;
- if (!GetAssignedPromiseAsyncId(env, promise, env->trigger_async_id_symbol())
- .To(&trigger_async_id)) return nullptr;
-
- if (async_id != AsyncWrap::kInvalidAsyncId &&
- trigger_async_id != AsyncWrap::kInvalidAsyncId) {
- return new PromiseWrap(
- env, obj, async_id, trigger_async_id);
- }
- }
-
- return new PromiseWrap(env, obj, silent);
-}
-
-void PromiseWrap::GetAsyncId(Local<Name> property,
- const PropertyCallbackInfo<Value>& info) {
- Isolate* isolate = info.GetIsolate();
- HandleScope scope(isolate);
-
- PromiseWrap* wrap = Unwrap<PromiseWrap>(info.Holder());
- double value = wrap->get_async_id();
-
- info.GetReturnValue().Set(Number::New(isolate, value));
-}
-
-void PromiseWrap::GetTriggerAsyncId(Local<Name> property,
- const PropertyCallbackInfo<Value>& info) {
- Isolate* isolate = info.GetIsolate();
- HandleScope scope(isolate);
-
- PromiseWrap* wrap = Unwrap<PromiseWrap>(info.Holder());
- double value = wrap->get_trigger_async_id();
-
- info.GetReturnValue().Set(Number::New(isolate, value));
-}
-
-void PromiseWrap::Initialize(Environment* env) {
- Isolate* isolate = env->isolate();
- HandleScope scope(isolate);
-
- Local<FunctionTemplate> ctor = FunctionTemplate::New(isolate);
- ctor->SetClassName(FIXED_ONE_BYTE_STRING(isolate, "PromiseWrap"));
-
- Local<ObjectTemplate> promise_wrap_template = ctor->InstanceTemplate();
- env->set_promise_wrap_template(promise_wrap_template);
-
- promise_wrap_template->SetInternalFieldCount(
- PromiseWrap::kInternalFieldCount);
-
- promise_wrap_template->SetAccessor(
- env->async_id_symbol(),
- PromiseWrap::GetAsyncId);
-
- promise_wrap_template->SetAccessor(
- env->trigger_async_id_symbol(),
- PromiseWrap::GetTriggerAsyncId);
-}
-
-static PromiseWrap* extractPromiseWrap(Local<Promise> promise) {
- // This check is imperfect. If the internal field is set, it should
- // be an object. If it's not, we just ignore it. Ideally v8 would
- // have had GetInternalField returning a MaybeLocal but this works
- // for now.
- Local<Value> obj = promise->GetInternalField(0);
- return obj->IsObject() ? Unwrap<PromiseWrap>(obj.As<Object>()) : nullptr;
-}
-
-static uint16_t ToAsyncHooksType(PromiseHookType type) {
- switch (type) {
- case PromiseHookType::kInit: return AsyncHooks::kInit;
- case PromiseHookType::kBefore: return AsyncHooks::kBefore;
- case PromiseHookType::kAfter: return AsyncHooks::kAfter;
- case PromiseHookType::kResolve: return AsyncHooks::kPromiseResolve;
- }
- UNREACHABLE();
-}
-
-// Simplified JavaScript hook fast-path for when there is no destroy hook
-static void FastPromiseHook(PromiseHookType type, Local<Promise> promise,
- Local<Value> parent) {
- Local<Context> context = promise->GetCreationContext().ToLocalChecked();
- Environment* env = Environment::GetCurrent(context);
- if (env == nullptr) return;
-
- if (type == PromiseHookType::kBefore &&
- env->async_hooks()->fields()[AsyncHooks::kBefore] == 0) {
- double async_id;
- double trigger_async_id;
- if (!GetAssignedPromiseAsyncId(env, promise, env->async_id_symbol())
- .To(&async_id)) return;
- if (!GetAssignedPromiseAsyncId(env, promise, env->trigger_async_id_symbol())
- .To(&trigger_async_id)) return;
-
- if (async_id != AsyncWrap::kInvalidAsyncId &&
- trigger_async_id != AsyncWrap::kInvalidAsyncId) {
- env->async_hooks()->push_async_context(
- async_id, trigger_async_id, promise);
- return;
- }
- }
-
- if (type == PromiseHookType::kAfter &&
- env->async_hooks()->fields()[AsyncHooks::kAfter] == 0) {
- double async_id;
- if (!GetAssignedPromiseAsyncId(env, promise, env->async_id_symbol())
- .To(&async_id)) return;
-
- if (async_id != AsyncWrap::kInvalidAsyncId) {
- if (env->execution_async_id() == async_id) {
- // This condition might not be true if async_hooks was enabled during
- // the promise callback execution.
- env->async_hooks()->pop_async_context(async_id);
- }
- return;
- }
- }
-
- if (type == PromiseHookType::kResolve &&
- env->async_hooks()->fields()[AsyncHooks::kPromiseResolve] == 0) {
- return;
- }
-
- // Getting up to this point means either init type or
- // that there are active hooks of another type.
- // In both cases fast-path JS hook should be called.
-
- Local<Value> argv[] = {
- Integer::New(env->isolate(), ToAsyncHooksType(type)),
- promise,
- parent
- };
-
- TryCatchScope try_catch(env, TryCatchScope::CatchMode::kFatal);
- Local<Function> promise_hook = env->promise_hook_handler();
- USE(promise_hook->Call(context, Undefined(env->isolate()), 3, argv));
-}
-
-static void FullPromiseHook(PromiseHookType type, Local<Promise> promise,
- Local<Value> parent) {
- Local<Context> context = promise->GetCreationContext().ToLocalChecked();
-
- Environment* env = Environment::GetCurrent(context);
- if (env == nullptr) return;
- TraceEventScope trace_scope(TRACING_CATEGORY_NODE1(environment),
- "EnvPromiseHook", env);
-
- PromiseWrap* wrap = extractPromiseWrap(promise);
- if (type == PromiseHookType::kInit || wrap == nullptr) {
- bool silent = type != PromiseHookType::kInit;
-
- // set parent promise's async Id as this promise's triggerAsyncId
- if (parent->IsPromise()) {
- // parent promise exists, current promise
- // is a chained promise, so we set parent promise's id as
- // current promise's triggerAsyncId
- Local<Promise> parent_promise = parent.As<Promise>();
- PromiseWrap* parent_wrap = extractPromiseWrap(parent_promise);
- if (parent_wrap == nullptr) {
- parent_wrap = PromiseWrap::New(env, parent_promise, true);
- if (parent_wrap == nullptr) return;
- }
-
- AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(parent_wrap);
- wrap = PromiseWrap::New(env, promise, silent);
- } else {
- wrap = PromiseWrap::New(env, promise, silent);
- }
- }
-
- if (wrap == nullptr) return;
-
- if (type == PromiseHookType::kBefore) {
- env->async_hooks()->push_async_context(wrap->get_async_id(),
- wrap->get_trigger_async_id(), wrap->object());
- wrap->EmitTraceEventBefore();
- AsyncWrap::EmitBefore(wrap->env(), wrap->get_async_id());
- } else if (type == PromiseHookType::kAfter) {
- wrap->EmitTraceEventAfter(wrap->provider_type(), wrap->get_async_id());
- AsyncWrap::EmitAfter(wrap->env(), wrap->get_async_id());
- if (env->execution_async_id() == wrap->get_async_id()) {
- // This condition might not be true if async_hooks was enabled during
- // the promise callback execution.
- // Popping it off the stack can be skipped in that case, because it is
- // known that it would correspond to exactly one call with
- // PromiseHookType::kBefore that was not witnessed by the PromiseHook.
- env->async_hooks()->pop_async_context(wrap->get_async_id());
- }
- } else if (type == PromiseHookType::kResolve) {
- AsyncWrap::EmitPromiseResolve(wrap->env(), wrap->get_async_id());
- }
-}
-
static void SetupHooks(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
@@ -441,17 +185,6 @@ static void SetupHooks(const FunctionCallbackInfo<Value>& args) {
#undef SET_HOOK_FN
}
-static void EnablePromiseHook(const FunctionCallbackInfo<Value>& args) {
- Environment* env = Environment::GetCurrent(args);
-
- if (args[0]->IsFunction()) {
- env->set_promise_hook_handler(args[0].As<Function>());
- args.GetIsolate()->SetPromiseHook(FastPromiseHook);
- } else {
- args.GetIsolate()->SetPromiseHook(FullPromiseHook);
- }
-}
-
static void SetPromiseHooks(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
@@ -462,17 +195,6 @@ static void SetPromiseHooks(const FunctionCallbackInfo<Value>& args) {
args[3]->IsFunction() ? args[3].As<Function>() : Local<Function>());
}
-static void DisablePromiseHook(const FunctionCallbackInfo<Value>& args) {
- Environment* env = Environment::GetCurrent(args);
- env->set_promise_hook_handler(Local<Function>());
-
- // The per-Isolate API provides no way of knowing whether there are multiple
- // users of the PromiseHook. That hopefully goes away when V8 introduces
- // a per-context API.
- args.GetIsolate()->SetPromiseHook(nullptr);
-}
-
-
class DestroyParam {
public:
double asyncId;
@@ -639,9 +361,7 @@ void AsyncWrap::Initialize(Local<Object> target,
env->SetMethod(target, "executionAsyncResource", ExecutionAsyncResource);
env->SetMethod(target, "clearAsyncIdStack", ClearAsyncIdStack);
env->SetMethod(target, "queueDestroyAsyncId", QueueDestroyAsyncId);
- env->SetMethod(target, "enablePromiseHook", EnablePromiseHook);
env->SetMethod(target, "setPromiseHooks", SetPromiseHooks);
- env->SetMethod(target, "disablePromiseHook", DisablePromiseHook);
env->SetMethod(target, "registerDestroyHook", RegisterDestroyHook);
PropertyAttribute ReadOnlyDontDelete =
@@ -720,9 +440,6 @@ void AsyncWrap::Initialize(Local<Object> target,
env->set_async_hooks_destroy_function(Local<Function>());
env->set_async_hooks_promise_resolve_function(Local<Function>());
env->set_async_hooks_binding(target);
-
- // TODO(qard): maybe this should be GetConstructorTemplate instead?
- PromiseWrap::Initialize(env);
}
void AsyncWrap::RegisterExternalReferences(
@@ -734,15 +451,11 @@ void AsyncWrap::RegisterExternalReferences(
registry->Register(ExecutionAsyncResource);
registry->Register(ClearAsyncIdStack);
registry->Register(QueueDestroyAsyncId);
- registry->Register(EnablePromiseHook);
registry->Register(SetPromiseHooks);
- registry->Register(DisablePromiseHook);
registry->Register(RegisterDestroyHook);
registry->Register(AsyncWrap::GetAsyncId);
registry->Register(AsyncWrap::AsyncReset);
registry->Register(AsyncWrap::GetProviderType);
- registry->Register(PromiseWrap::GetAsyncId);
- registry->Register(PromiseWrap::GetTriggerAsyncId);
}
AsyncWrap::AsyncWrap(Environment* env,