diff options
-rw-r--r-- | src/async_wrap.cc | 21 | ||||
-rw-r--r-- | src/async_wrap.h | 6 | ||||
-rw-r--r-- | src/node.cc | 12 |
3 files changed, 30 insertions, 9 deletions
diff --git a/src/async_wrap.cc b/src/async_wrap.cc index 9d9d03b0fa..d47c0d6cfb 100644 --- a/src/async_wrap.cc +++ b/src/async_wrap.cc @@ -734,6 +734,27 @@ std::string AsyncWrap::diagnostic_name() const { std::to_string(static_cast<int64_t>(async_id_)) + ")"; } +Local<Object> AsyncWrap::GetOwner() { + return GetOwner(env(), object()); +} + +Local<Object> AsyncWrap::GetOwner(Environment* env, Local<Object> obj) { + v8::EscapableHandleScope handle_scope(env->isolate()); + CHECK(!obj.IsEmpty()); + + v8::TryCatch ignore_exceptions(env->isolate()); + while (true) { + Local<Value> owner; + if (!obj->Get(env->context(), + env->owner_symbol()).ToLocal(&owner) || + !owner->IsObject()) { + return handle_scope.Escape(obj); + } + + obj = owner.As<Object>(); + } +} + } // namespace node NODE_BUILTIN_MODULE_CONTEXT_AWARE(async_wrap, node::AsyncWrap::Initialize) diff --git a/src/async_wrap.h b/src/async_wrap.h index 60078ee093..ee04479de0 100644 --- a/src/async_wrap.h +++ b/src/async_wrap.h @@ -178,6 +178,12 @@ class AsyncWrap : public BaseObject { static void WeakCallback(const v8::WeakCallbackInfo<DestroyParam> &info); + // Returns the object that 'owns' an async wrap. For example, for a + // TCP connection handle, this is the corresponding net.Socket. + v8::Local<v8::Object> GetOwner(); + static v8::Local<v8::Object> GetOwner(Environment* env, + v8::Local<v8::Object> obj); + // This is a simplified version of InternalCallbackScope that only runs // the `before` and `after` hooks. Only use it when not actually calling // back into JS; otherwise, use InternalCallbackScope. diff --git a/src/node.cc b/src/node.cc index 886243fd5c..a6bf512e04 100644 --- a/src/node.cc +++ b/src/node.cc @@ -1138,7 +1138,7 @@ static void GetActiveRequests(const FunctionCallbackInfo<Value>& args) { for (auto w : *env->req_wrap_queue()) { if (w->persistent().IsEmpty()) continue; - argv[idx] = w->object(); + argv[idx] = w->GetOwner(); if (++idx >= arraysize(argv)) { fn->Call(ctx, ary, idx, argv).ToLocalChecked(); idx = 0; @@ -1164,16 +1164,10 @@ void GetActiveHandles(const FunctionCallbackInfo<Value>& args) { Local<Value> argv[NODE_PUSH_VAL_TO_ARRAY_MAX]; size_t idx = 0; - Local<String> owner_sym = env->owner_string(); - for (auto w : *env->handle_wrap_queue()) { - if (w->persistent().IsEmpty() || !HandleWrap::HasRef(w)) + if (!HandleWrap::HasRef(w)) continue; - Local<Object> object = w->object(); - Local<Value> owner = object->Get(owner_sym); - if (owner->IsUndefined()) - owner = object; - argv[idx] = owner; + argv[idx] = w->GetOwner(); if (++idx >= arraysize(argv)) { fn->Call(ctx, ary, idx, argv).ToLocalChecked(); idx = 0; |