diff --git a/src/async-wrap.cc b/src/async-wrap.cc index 304e5d0c956490..11ed67d24207c0 100644 --- a/src/async-wrap.cc +++ b/src/async-wrap.cc @@ -180,6 +180,14 @@ static void SetupHooks(const FunctionCallbackInfo& args) { } +void AsyncWrap::GetAsyncId(const FunctionCallbackInfo& args) { + AsyncWrap* wrap; + args.GetReturnValue().Set(-1); + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); + args.GetReturnValue().Set(wrap->get_id()); +} + + void AsyncWrap::Initialize(Local target, Local unused, Local context) { diff --git a/src/async-wrap.h b/src/async-wrap.h index ecf8db9fc5eea9..7ccae02cced05b 100644 --- a/src/async-wrap.h +++ b/src/async-wrap.h @@ -85,6 +85,8 @@ class AsyncWrap : public BaseObject { v8::Local unused, v8::Local context); + static void GetAsyncId(const v8::FunctionCallbackInfo& args); + static void DestroyIdsCb(uv_idle_t* handle); inline ProviderType provider_type() const; diff --git a/src/cares_wrap.cc b/src/cares_wrap.cc index 7a9102ff3dc529..15c261b6f165f5 100644 --- a/src/cares_wrap.cc +++ b/src/cares_wrap.cc @@ -104,6 +104,7 @@ inline const char* ToErrorCodeString(int status) { class GetAddrInfoReqWrap : public ReqWrap { public: GetAddrInfoReqWrap(Environment* env, Local req_wrap_obj); + ~GetAddrInfoReqWrap(); size_t self_size() const override { return sizeof(*this); } }; @@ -114,10 +115,15 @@ GetAddrInfoReqWrap::GetAddrInfoReqWrap(Environment* env, Wrap(req_wrap_obj, this); } +GetAddrInfoReqWrap::~GetAddrInfoReqWrap() { + ClearWrap(object()); +} + class GetNameInfoReqWrap : public ReqWrap { public: GetNameInfoReqWrap(Environment* env, Local req_wrap_obj); + ~GetNameInfoReqWrap(); size_t self_size() const override { return sizeof(*this); } }; @@ -128,6 +134,10 @@ GetNameInfoReqWrap::GetNameInfoReqWrap(Environment* env, Wrap(req_wrap_obj, this); } +GetNameInfoReqWrap::~GetNameInfoReqWrap() { + ClearWrap(object()); +} + int cmp_ares_tasks(const node_ares_task* a, const node_ares_task* b) { if (a->sock < b->sock) @@ -293,6 +303,7 @@ class QueryWrap : public AsyncWrap { : AsyncWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_QUERYWRAP) { if (env->in_domain()) req_wrap_obj->Set(env->domain_string(), env->domain_array()->Get(0)); + Wrap(req_wrap_obj, this); } ~QueryWrap() override { @@ -1388,10 +1399,12 @@ void Initialize(Local target, auto is_construct_call_callback = [](const FunctionCallbackInfo& args) { CHECK(args.IsConstructCall()); + ClearWrap(args.This()); }; Local aiw = FunctionTemplate::New(env->isolate(), is_construct_call_callback); aiw->InstanceTemplate()->SetInternalFieldCount(1); + env->SetProtoMethod(aiw, "getAsyncId", AsyncWrap::GetAsyncId); aiw->SetClassName( FIXED_ONE_BYTE_STRING(env->isolate(), "GetAddrInfoReqWrap")); target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "GetAddrInfoReqWrap"), @@ -1400,6 +1413,7 @@ void Initialize(Local target, Local niw = FunctionTemplate::New(env->isolate(), is_construct_call_callback); niw->InstanceTemplate()->SetInternalFieldCount(1); + env->SetProtoMethod(niw, "getAsyncId", AsyncWrap::GetAsyncId); niw->SetClassName( FIXED_ONE_BYTE_STRING(env->isolate(), "GetNameInfoReqWrap")); target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "GetNameInfoReqWrap"), @@ -1408,6 +1422,7 @@ void Initialize(Local target, Local qrw = FunctionTemplate::New(env->isolate(), is_construct_call_callback); qrw->InstanceTemplate()->SetInternalFieldCount(1); + env->SetProtoMethod(qrw, "getAsyncId", AsyncWrap::GetAsyncId); qrw->SetClassName( FIXED_ONE_BYTE_STRING(env->isolate(), "QueryReqWrap")); target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "QueryReqWrap"), diff --git a/src/connect_wrap.cc b/src/connect_wrap.cc index df3f093e732972..e373b5a36e33e6 100644 --- a/src/connect_wrap.cc +++ b/src/connect_wrap.cc @@ -19,4 +19,9 @@ ConnectWrap::ConnectWrap(Environment* env, Wrap(req_wrap_obj, this); } + +ConnectWrap::~ConnectWrap() { + ClearWrap(object()); +} + } // namespace node diff --git a/src/connect_wrap.h b/src/connect_wrap.h index 28d4872d7ed416..7b16a5448745aa 100644 --- a/src/connect_wrap.h +++ b/src/connect_wrap.h @@ -15,6 +15,7 @@ class ConnectWrap : public ReqWrap { ConnectWrap(Environment* env, v8::Local req_wrap_obj, AsyncWrap::ProviderType provider); + ~ConnectWrap(); size_t self_size() const override { return sizeof(*this); } }; diff --git a/src/fs_event_wrap.cc b/src/fs_event_wrap.cc index bc3b33027ac3a6..228c3a344edf3c 100644 --- a/src/fs_event_wrap.cc +++ b/src/fs_event_wrap.cc @@ -94,6 +94,7 @@ void FSEventWrap::Initialize(Local target, t->InstanceTemplate()->SetInternalFieldCount(1); t->SetClassName(fsevent_string); + env->SetProtoMethod(t, "getAsyncId", AsyncWrap::GetAsyncId); env->SetProtoMethod(t, "start", Start); env->SetProtoMethod(t, "close", Close); diff --git a/src/js_stream.cc b/src/js_stream.cc index e51c4ae9b35084..1d20e1c6d77dfb 100644 --- a/src/js_stream.cc +++ b/src/js_stream.cc @@ -221,6 +221,8 @@ void JSStream::Initialize(Local target, t->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "JSStream")); t->InstanceTemplate()->SetInternalFieldCount(1); + env->SetProtoMethod(t, "getAsyncId", AsyncWrap::GetAsyncId); + env->SetProtoMethod(t, "doAlloc", DoAlloc); env->SetProtoMethod(t, "doRead", DoRead); env->SetProtoMethod(t, "doAfterWrite", DoAfterWrite); diff --git a/src/node_crypto.cc b/src/node_crypto.cc index 87e008acd97e10..dac4a2e76bfe76 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -2737,6 +2737,7 @@ void Connection::Initialize(Environment* env, Local target) { t->InstanceTemplate()->SetInternalFieldCount(1); t->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "Connection")); + env->SetProtoMethod(t, "getAsyncId", AsyncWrap::GetAsyncId); env->SetProtoMethod(t, "encIn", Connection::EncIn); env->SetProtoMethod(t, "clearOut", Connection::ClearOut); env->SetProtoMethod(t, "clearIn", Connection::ClearIn); @@ -6258,12 +6259,14 @@ void InitCrypto(Local target, Local pb = FunctionTemplate::New(env->isolate()); pb->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "PBKDF2")); + env->SetProtoMethod(pb, "getAsyncId", AsyncWrap::GetAsyncId); Local pbt = pb->InstanceTemplate(); pbt->SetInternalFieldCount(1); env->set_pbkdf2_constructor_template(pbt); Local rb = FunctionTemplate::New(env->isolate()); rb->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "RandomBytes")); + env->SetProtoMethod(rb, "getAsyncId", AsyncWrap::GetAsyncId); Local rbt = rb->InstanceTemplate(); rbt->SetInternalFieldCount(1); env->set_randombytes_constructor_template(rbt); diff --git a/src/node_crypto.h b/src/node_crypto.h index 90e268456a4f12..ad1b493596aa7a 100644 --- a/src/node_crypto.h +++ b/src/node_crypto.h @@ -408,6 +408,7 @@ class Connection : public AsyncWrap, public SSLWrap { bio_write_(nullptr), hello_offset_(0) { MakeWeak(this); + Wrap(wrap, this); hello_parser_.Start(SSLWrap::OnClientHello, OnClientHelloParseEnd, this); diff --git a/src/node_file.cc b/src/node_file.cc index 4a0b1527d6aca4..7a3be9db541a16 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -110,7 +110,10 @@ class FSReqWrap: public ReqWrap { Wrap(object(), this); } - ~FSReqWrap() { ReleaseEarly(); } + ~FSReqWrap() { + ReleaseEarly(); + ClearWrap(object()); + } void* operator new(size_t size) = delete; void* operator new(size_t size, char* storage) { return storage; } @@ -151,6 +154,7 @@ void FSReqWrap::Dispose() { void NewFSReqWrap(const FunctionCallbackInfo& args) { CHECK(args.IsConstructCall()); + ClearWrap(args.This()); } @@ -1474,6 +1478,7 @@ void InitFs(Local target, Local fst = FunctionTemplate::New(env->isolate(), NewFSReqWrap); fst->InstanceTemplate()->SetInternalFieldCount(1); + env->SetProtoMethod(fst, "getAsyncId", AsyncWrap::GetAsyncId); fst->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "FSReqWrap")); target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "FSReqWrap"), fst->GetFunction()); diff --git a/src/node_http_parser.cc b/src/node_http_parser.cc index d504f42f35107b..531a83392c291f 100644 --- a/src/node_http_parser.cc +++ b/src/node_http_parser.cc @@ -785,6 +785,7 @@ void InitHttpParser(Local target, #undef V target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "methods"), methods); + env->SetProtoMethod(t, "getAsyncId", AsyncWrap::GetAsyncId); env->SetProtoMethod(t, "close", Parser::Close); env->SetProtoMethod(t, "execute", Parser::Execute); env->SetProtoMethod(t, "finish", Parser::Finish); diff --git a/src/node_stat_watcher.cc b/src/node_stat_watcher.cc index 9eeed77476be56..18bf2c54193d7b 100644 --- a/src/node_stat_watcher.cc +++ b/src/node_stat_watcher.cc @@ -49,6 +49,7 @@ void StatWatcher::Initialize(Environment* env, Local target) { t->InstanceTemplate()->SetInternalFieldCount(1); t->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "StatWatcher")); + env->SetProtoMethod(t, "getAsyncId", AsyncWrap::GetAsyncId); env->SetProtoMethod(t, "start", StatWatcher::Start); env->SetProtoMethod(t, "stop", StatWatcher::Stop); @@ -66,6 +67,7 @@ StatWatcher::StatWatcher(Environment* env, Local wrap) : AsyncWrap(env, wrap, AsyncWrap::PROVIDER_STATWATCHER), watcher_(new uv_fs_poll_t) { MakeWeak(this); + Wrap(wrap, this); uv_fs_poll_init(env->event_loop(), watcher_); watcher_->data = static_cast(this); } diff --git a/src/node_zlib.cc b/src/node_zlib.cc index 054023ca10360f..e4adda52026c87 100644 --- a/src/node_zlib.cc +++ b/src/node_zlib.cc @@ -88,6 +88,7 @@ class ZCtx : public AsyncWrap { refs_(0), gzip_id_bytes_read_(0) { MakeWeak(this); + Wrap(wrap, this); } @@ -678,6 +679,7 @@ void InitZlib(Local target, z->InstanceTemplate()->SetInternalFieldCount(1); + env->SetProtoMethod(z, "getAsyncId", AsyncWrap::GetAsyncId); env->SetProtoMethod(z, "write", ZCtx::Write); env->SetProtoMethod(z, "writeSync", ZCtx::Write); env->SetProtoMethod(z, "init", ZCtx::Init); diff --git a/src/pipe_wrap.cc b/src/pipe_wrap.cc index 132b2662f516f3..8c251f1f741461 100644 --- a/src/pipe_wrap.cc +++ b/src/pipe_wrap.cc @@ -69,6 +69,8 @@ void PipeWrap::Initialize(Local target, t->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "Pipe")); t->InstanceTemplate()->SetInternalFieldCount(1); + env->SetProtoMethod(t, "getAsyncId", AsyncWrap::GetAsyncId); + env->SetProtoMethod(t, "close", HandleWrap::Close); env->SetProtoMethod(t, "unref", HandleWrap::Unref); env->SetProtoMethod(t, "ref", HandleWrap::Ref); @@ -95,9 +97,11 @@ void PipeWrap::Initialize(Local target, // Create FunctionTemplate for PipeConnectWrap. auto constructor = [](const FunctionCallbackInfo& args) { CHECK(args.IsConstructCall()); + ClearWrap(args.This()); }; auto cwt = FunctionTemplate::New(env->isolate(), constructor); cwt->InstanceTemplate()->SetInternalFieldCount(1); + env->SetProtoMethod(cwt, "getAsyncId", AsyncWrap::GetAsyncId); cwt->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "PipeConnectWrap")); target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "PipeConnectWrap"), cwt->GetFunction()); diff --git a/src/process_wrap.cc b/src/process_wrap.cc index 2780adad74afca..cae0788927bc89 100644 --- a/src/process_wrap.cc +++ b/src/process_wrap.cc @@ -55,6 +55,8 @@ class ProcessWrap : public HandleWrap { constructor->InstanceTemplate()->SetInternalFieldCount(1); constructor->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "Process")); + env->SetProtoMethod(constructor, "getAsyncId", AsyncWrap::GetAsyncId); + env->SetProtoMethod(constructor, "close", HandleWrap::Close); env->SetProtoMethod(constructor, "spawn", Spawn); diff --git a/src/req-wrap-inl.h b/src/req-wrap-inl.h index 84af22023dc3b9..e21fb1bdad9363 100644 --- a/src/req-wrap-inl.h +++ b/src/req-wrap-inl.h @@ -30,7 +30,6 @@ template ReqWrap::~ReqWrap() { CHECK_EQ(req_.data, this); // Assert that someone has called Dispatched(). CHECK_EQ(false, persistent().IsEmpty()); - ClearWrap(object()); persistent().Reset(); } diff --git a/src/signal_wrap.cc b/src/signal_wrap.cc index 36b862ce82523f..ccd1b0ec411dc8 100644 --- a/src/signal_wrap.cc +++ b/src/signal_wrap.cc @@ -51,6 +51,7 @@ class SignalWrap : public HandleWrap { constructor->InstanceTemplate()->SetInternalFieldCount(1); constructor->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "Signal")); + env->SetProtoMethod(constructor, "getAsyncId", AsyncWrap::GetAsyncId); env->SetProtoMethod(constructor, "close", HandleWrap::Close); env->SetProtoMethod(constructor, "ref", HandleWrap::Ref); env->SetProtoMethod(constructor, "unref", HandleWrap::Unref); diff --git a/src/stream_base.h b/src/stream_base.h index e2ef8d8d396b87..581c5405aaf594 100644 --- a/src/stream_base.h +++ b/src/stream_base.h @@ -53,6 +53,10 @@ class ShutdownWrap : public ReqWrap, Wrap(req_wrap_obj, this); } + ~ShutdownWrap() { + ClearWrap(object()); + } + static ShutdownWrap* from_req(uv_shutdown_t* req) { return ContainerOf(&ShutdownWrap::req_, req); } @@ -98,6 +102,10 @@ class WriteWrap: public ReqWrap, Wrap(obj, this); } + ~WriteWrap() { + ClearWrap(object()); + } + void* operator new(size_t size) = delete; void* operator new(size_t size, char* storage) { return storage; } diff --git a/src/stream_wrap.cc b/src/stream_wrap.cc index 83c375b54b8a75..065505af1971ac 100644 --- a/src/stream_wrap.cc +++ b/src/stream_wrap.cc @@ -62,11 +62,13 @@ void StreamWrap::Initialize(Local target, auto is_construct_call_callback = [](const FunctionCallbackInfo& args) { CHECK(args.IsConstructCall()); + ClearWrap(args.This()); }; Local sw = FunctionTemplate::New(env->isolate(), is_construct_call_callback); sw->InstanceTemplate()->SetInternalFieldCount(1); sw->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "ShutdownWrap")); + env->SetProtoMethod(sw, "getAsyncId", AsyncWrap::GetAsyncId); target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "ShutdownWrap"), sw->GetFunction()); @@ -74,6 +76,7 @@ void StreamWrap::Initialize(Local target, FunctionTemplate::New(env->isolate(), is_construct_call_callback); ww->InstanceTemplate()->SetInternalFieldCount(1); ww->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "WriteWrap")); + env->SetProtoMethod(ww, "getAsyncId", AsyncWrap::GetAsyncId); target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "WriteWrap"), ww->GetFunction()); env->set_write_wrap_constructor_function(ww->GetFunction()); diff --git a/src/tcp_wrap.cc b/src/tcp_wrap.cc index f2525b1fb1b22a..931b637751e610 100644 --- a/src/tcp_wrap.cc +++ b/src/tcp_wrap.cc @@ -84,6 +84,7 @@ void TCPWrap::Initialize(Local target, "onconnection"), Null(env->isolate())); + env->SetProtoMethod(t, "getAsyncId", AsyncWrap::GetAsyncId); env->SetProtoMethod(t, "close", HandleWrap::Close); @@ -116,9 +117,11 @@ void TCPWrap::Initialize(Local target, // Create FunctionTemplate for TCPConnectWrap. auto constructor = [](const FunctionCallbackInfo& args) { CHECK(args.IsConstructCall()); + ClearWrap(args.This()); }; auto cwt = FunctionTemplate::New(env->isolate(), constructor); cwt->InstanceTemplate()->SetInternalFieldCount(1); + env->SetProtoMethod(cwt, "getAsyncId", AsyncWrap::GetAsyncId); cwt->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "TCPConnectWrap")); target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "TCPConnectWrap"), cwt->GetFunction()); diff --git a/src/timer_wrap.cc b/src/timer_wrap.cc index 382bcaacb6c02d..609d087e334f72 100644 --- a/src/timer_wrap.cc +++ b/src/timer_wrap.cc @@ -57,6 +57,8 @@ class TimerWrap : public HandleWrap { env->SetTemplateMethod(constructor, "now", Now); + env->SetProtoMethod(constructor, "getAsyncId", AsyncWrap::GetAsyncId); + env->SetProtoMethod(constructor, "close", HandleWrap::Close); env->SetProtoMethod(constructor, "ref", HandleWrap::Ref); env->SetProtoMethod(constructor, "unref", HandleWrap::Unref); diff --git a/src/tls_wrap.cc b/src/tls_wrap.cc index 6f2d0e4c16d576..05349b2f55230d 100644 --- a/src/tls_wrap.cc +++ b/src/tls_wrap.cc @@ -939,6 +939,7 @@ void TLSWrap::Initialize(Local target, t->InstanceTemplate()->SetInternalFieldCount(1); t->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "TLSWrap")); + env->SetProtoMethod(t, "getAsyncId", AsyncWrap::GetAsyncId); env->SetProtoMethod(t, "receive", Receive); env->SetProtoMethod(t, "start", Start); env->SetProtoMethod(t, "setVerifyMode", SetVerifyMode); diff --git a/src/tty_wrap.cc b/src/tty_wrap.cc index b6e3efcc100a34..f3f1edfe5d3248 100644 --- a/src/tty_wrap.cc +++ b/src/tty_wrap.cc @@ -53,6 +53,8 @@ void TTYWrap::Initialize(Local target, t->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "TTY")); t->InstanceTemplate()->SetInternalFieldCount(1); + env->SetProtoMethod(t, "getAsyncId", AsyncWrap::GetAsyncId); + env->SetProtoMethod(t, "close", HandleWrap::Close); env->SetProtoMethod(t, "unref", HandleWrap::Unref); env->SetProtoMethod(t, "ref", HandleWrap::Ref); diff --git a/src/udp_wrap.cc b/src/udp_wrap.cc index 4f5388080e2bfe..fe2b10661fd7c3 100644 --- a/src/udp_wrap.cc +++ b/src/udp_wrap.cc @@ -54,6 +54,7 @@ using v8::Value; class SendWrap : public ReqWrap { public: SendWrap(Environment* env, Local req_wrap_obj, bool have_callback); + ~SendWrap(); inline bool have_callback() const; size_t msg_size; size_t self_size() const override { return sizeof(*this); } @@ -71,6 +72,11 @@ SendWrap::SendWrap(Environment* env, } +SendWrap::~SendWrap() { + ClearWrap(object()); +} + + inline bool SendWrap::have_callback() const { return have_callback_; } @@ -78,6 +84,7 @@ inline bool SendWrap::have_callback() const { static void NewSendWrap(const FunctionCallbackInfo& args) { CHECK(args.IsConstructCall()); + ClearWrap(args.This()); } @@ -129,6 +136,8 @@ void UDPWrap::Initialize(Local target, env->SetProtoMethod(t, "unref", HandleWrap::Unref); env->SetProtoMethod(t, "hasRef", HandleWrap::HasRef); + env->SetProtoMethod(t, "getAsyncId", AsyncWrap::GetAsyncId); + target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "UDP"), t->GetFunction()); env->set_udp_constructor_function(t->GetFunction()); @@ -136,6 +145,7 @@ void UDPWrap::Initialize(Local target, Local swt = FunctionTemplate::New(env->isolate(), NewSendWrap); swt->InstanceTemplate()->SetInternalFieldCount(1); + env->SetProtoMethod(swt, "getAsyncId", AsyncWrap::GetAsyncId); swt->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "SendWrap")); target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "SendWrap"), swt->GetFunction()); diff --git a/test/parallel/test-async-wrap-getasyncid.js b/test/parallel/test-async-wrap-getasyncid.js new file mode 100644 index 00000000000000..5e2ce3a820381c --- /dev/null +++ b/test/parallel/test-async-wrap-getasyncid.js @@ -0,0 +1,241 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const fs = require('fs'); +const net = require('net'); +const providers = Object.assign({}, process.binding('async_wrap').Providers); + +// Make sure that all Providers are tested. +{ + const hooks = require('async_hooks').createHook({ + init(id, type) { + if (type === 'NONE') + throw new Error('received a provider type of NONE'); + delete providers[type]; + }, + }).enable(); + process.on('beforeExit', common.mustCall(() => { + process.removeAllListeners('uncaughtException'); + hooks.disable(); + delete providers.NONE; // Should never be used. + const obj_keys = Object.keys(providers); + if (obj_keys.length > 0) + process._rawDebug(obj_keys); + assert.strictEqual(obj_keys.length, 0); + })); +} + +function testUninitialized(req, ctor_name) { + assert.strictEqual(typeof req.getAsyncId, 'function'); + assert.strictEqual(req.getAsyncId(), -1); + assert.strictEqual(req.constructor.name, ctor_name); +} + +function testInitialized(req, ctor_name) { + assert.strictEqual(typeof req.getAsyncId, 'function'); + assert(Number.isSafeInteger(req.getAsyncId())); + assert(req.getAsyncId() > 0); + assert.strictEqual(req.constructor.name, ctor_name); +} + + +{ + const cares = process.binding('cares_wrap'); + const dns = require('dns'); + + testUninitialized(new cares.GetAddrInfoReqWrap(), 'GetAddrInfoReqWrap'); + testUninitialized(new cares.GetNameInfoReqWrap(), 'GetNameInfoReqWrap'); + testUninitialized(new cares.QueryReqWrap(), 'QueryReqWrap'); + + testInitialized(dns.lookup('www.google.com', () => {}), 'GetAddrInfoReqWrap'); + testInitialized(dns.lookupService('::1', 22, () => {}), 'GetNameInfoReqWrap'); + testInitialized(dns.resolve6('::1', () => {}), 'QueryReqWrap'); +} + + +{ + const FSEvent = process.binding('fs_event_wrap').FSEvent; + testInitialized(new FSEvent(), 'FSEvent'); +} + + +{ + const JSStream = process.binding('js_stream').JSStream; + testInitialized(new JSStream(), 'JSStream'); +} + + +if (common.hasCrypto) { + const tls = require('tls'); + // SecurePair + testInitialized(tls.createSecurePair().ssl, 'Connection'); +} + + +if (common.hasCrypto) { + const crypto = require('crypto'); + + // The handle for PBKDF2 and RandomBytes isn't returned by the function call, + // so need to check it from the callback. + + const mc = common.mustCall(function pb() { + testInitialized(this, 'PBKDF2'); + }); + crypto.pbkdf2('password', 'salt', 1, 20, 'sha256', mc); + + crypto.randomBytes(1, common.mustCall(function rb() { + testInitialized(this, 'RandomBytes'); + })); +} + + +{ + const binding = process.binding('fs'); + const path = require('path'); + + const FSReqWrap = binding.FSReqWrap; + const req = new FSReqWrap(); + req.oncomplete = () => { }; + + testUninitialized(req, 'FSReqWrap'); + binding.access(path._makeLong('../'), fs.F_OK, req); + testInitialized(req, 'FSReqWrap'); + + const StatWatcher = binding.StatWatcher; + testInitialized(new StatWatcher(), 'StatWatcher'); +} + + +{ + const HTTPParser = process.binding('http_parser').HTTPParser; + testInitialized(new HTTPParser(), 'HTTPParser'); +} + + +{ + const Gzip = require('zlib').Gzip; + testInitialized(new Gzip()._handle, 'Zlib'); +} + + +{ + const binding = process.binding('pipe_wrap'); + const handle = new binding.Pipe(); + testInitialized(handle, 'Pipe'); + const req = new binding.PipeConnectWrap(); + testUninitialized(req, 'PipeConnectWrap'); + req.address = common.PIPE; + req.oncomplete = common.mustCall(() => handle.close()); + handle.connect(req, req.address, req.oncomplete); + testInitialized(req, 'PipeConnectWrap'); +} + + +{ + const Process = process.binding('process_wrap').Process; + testInitialized(new Process(), 'Process'); +} + + +{ + const Signal = process.binding('signal_wrap').Signal; + testInitialized(new Signal(), 'Signal'); +} + + +{ + const binding = process.binding('stream_wrap'); + testUninitialized(new binding.WriteWrap(), 'WriteWrap'); +} + +{ + const stream_wrap = process.binding('stream_wrap'); + const tcp_wrap = process.binding('tcp_wrap'); + const server = net.createServer(common.mustCall((socket) => { + socket.on('data', (x) => { + socket.end(); + socket.destroy(); + }); + socket.resume(); + })).listen(0, common.localhostIPv4, common.mustCall(() => { + const handle = new tcp_wrap.TCP(); + const req = new tcp_wrap.TCPConnectWrap(); + const sreq = new stream_wrap.ShutdownWrap(); + const wreq = new stream_wrap.WriteWrap(); + testInitialized(handle, 'TCP'); + testUninitialized(req, 'TCPConnectWrap'); + testUninitialized(sreq, 'ShutdownWrap'); + + sreq.oncomplete = common.mustCall(() => { + handle.close(); + server.close(); + }); + + wreq.handle = handle; + wreq.oncomplete = common.mustCall(() => { + handle.shutdown(sreq); + testInitialized(sreq, 'ShutdownWrap'); + }); + wreq.async = true; + + req.oncomplete = common.mustCall(() => { + // Use a long string to make sure the write happens asynchronously. + const err = handle.writeLatin1String(wreq, 'hi'.repeat(100000)); + if (err) + throw new Error(`write failed: ${process.binding('uv').errname(err)}`); + testInitialized(wreq, 'WriteWrap'); + }); + req.address = common.localhostIPv4; + req.port = server.address().port; + const err = handle.connect(req, req.address, req.port); + assert.strictEqual(err, 0); + testInitialized(req, 'TCPConnectWrap'); + })); +} + + +{ + const TimerWrap = process.binding('timer_wrap').Timer; + testInitialized(new TimerWrap(), 'Timer'); +} + + +if (common.hasCrypto) { + const TCP = process.binding('tcp_wrap').TCP; + const tcp = new TCP(); + + const ca = fs.readFileSync(common.fixturesDir + '/test_ca.pem', 'ascii'); + const cert = fs.readFileSync(common.fixturesDir + '/test_cert.pem', 'ascii'); + const key = fs.readFileSync(common.fixturesDir + '/test_key.pem', 'ascii'); + const credentials = require('tls').createSecureContext({ ca, cert, key }); + + // TLSWrap is exposed, but needs to be instantiated via tls_wrap.wrap(). + const tls_wrap = process.binding('tls_wrap'); + testInitialized( + tls_wrap.wrap(tcp._externalStream, credentials.context, true), 'TLSWrap'); +} + + +{ + const tty_wrap = process.binding('tty_wrap'); + if (tty_wrap.isTTY(0)) { + testInitialized(new tty_wrap.TTY(0, false), 'TTY'); + } +} + + +{ + const binding = process.binding('udp_wrap'); + const handle = new binding.UDP(); + const req = new binding.SendWrap(); + testInitialized(handle, 'UDP'); + testUninitialized(req, 'SendWrap'); + + handle.bind('0.0.0.0', common.PORT, undefined); + req.address = '127.0.0.1'; + req.port = common.PORT; + req.oncomplete = () => handle.close(); + handle.send(req, [Buffer.alloc(1)], 1, req.port, req.address, true); + testInitialized(req, 'SendWrap'); +}