From 23fdb7a6adda23007bf481ad7a7f111ac9c1a470 Mon Sep 17 00:00:00 2001 From: RafaelGSS Date: Tue, 26 Jul 2022 10:53:00 -0300 Subject: [PATCH] src: make ReqWrap weak This commit allows throwing an exception after creating `FSReqCallback` Co-authored-by: Anna Henningsen --- lib/fs.js | 4 ---- src/cares_wrap.cc | 4 ++-- src/connection_wrap.cc | 6 +++--- src/node_file.cc | 4 ++-- src/req_wrap-inl.h | 10 ++++++---- 5 files changed, 13 insertions(+), 15 deletions(-) diff --git a/lib/fs.js b/lib/fs.js index 874b6259431ba0..8dcea37596cde5 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -24,10 +24,6 @@ 'use strict'; -// When using FSReqCallback, make sure to create the object only *after* all -// parameter validation has happened, so that the objects are not kept in memory -// in case they are created but never used due to an exception. - const { ArrayPrototypePush, BigIntPrototypeToString, diff --git a/src/cares_wrap.cc b/src/cares_wrap.cc index a16a0dcbd1bcec..b998ed4c3f12fa 100644 --- a/src/cares_wrap.cc +++ b/src/cares_wrap.cc @@ -1429,7 +1429,7 @@ static void Query(const FunctionCallbackInfo& args) { void AfterGetAddrInfo(uv_getaddrinfo_t* req, int status, struct addrinfo* res) { auto cleanup = OnScopeLeave([&]() { uv_freeaddrinfo(res); }); - std::unique_ptr req_wrap { + BaseObjectPtr req_wrap { static_cast(req->data)}; Environment* env = req_wrap->env(); @@ -1502,7 +1502,7 @@ void AfterGetNameInfo(uv_getnameinfo_t* req, int status, const char* hostname, const char* service) { - std::unique_ptr req_wrap { + BaseObjectPtr req_wrap { static_cast(req->data)}; Environment* env = req_wrap->env(); diff --git a/src/connection_wrap.cc b/src/connection_wrap.cc index 29815eee4381a0..cd1c9510bf1105 100644 --- a/src/connection_wrap.cc +++ b/src/connection_wrap.cc @@ -77,9 +77,9 @@ void ConnectionWrap::OnConnection(uv_stream_t* handle, template void ConnectionWrap::AfterConnect(uv_connect_t* req, int status) { - std::unique_ptr req_wrap - (static_cast(req->data)); - CHECK_NOT_NULL(req_wrap); + BaseObjectPtr req_wrap + { static_cast(req->data) }; + CHECK(req_wrap); WrapType* wrap = static_cast(req->handle->data); CHECK_EQ(req_wrap->env(), wrap->env()); Environment* env = wrap->env(); diff --git a/src/node_file.cc b/src/node_file.cc index a010479cd71c56..aa26e8df5bbf27 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -374,8 +374,8 @@ MaybeLocal FileHandle::ClosePromise() { CloseReq* req = new CloseReq(env(), close_req_obj, promise, object()); auto AfterClose = uv_fs_callback_t{[](uv_fs_t* req) { - std::unique_ptr close(CloseReq::from_req(req)); - CHECK_NOT_NULL(close); + BaseObjectPtr close(CloseReq::from_req(req)); + CHECK(close); close->file_handle()->AfterClose(); if (!close->env()->can_call_into_js()) return; Isolate* isolate = close->env()->isolate(); diff --git a/src/req_wrap-inl.h b/src/req_wrap-inl.h index c905b605cbde97..a2d322521e50f1 100644 --- a/src/req_wrap-inl.h +++ b/src/req_wrap-inl.h @@ -20,12 +20,12 @@ ReqWrap::ReqWrap(Environment* env, AsyncWrap::ProviderType provider) : AsyncWrap(env, object, provider), ReqWrapBase(env) { + MakeWeak(); Reset(); } template ReqWrap::~ReqWrap() { - CHECK_EQ(false, persistent().IsEmpty()); } template @@ -120,7 +120,8 @@ struct MakeLibuvRequestCallback { using F = void(*)(ReqT* req, Args... args); static void Wrapper(ReqT* req, Args... args) { - ReqWrap* req_wrap = ReqWrap::from_req(req); + BaseObjectPtr> req_wrap { ReqWrap::from_req(req) }; + req_wrap->MakeWeak(); req_wrap->env()->DecreaseWaitingRequestCounter(); F original_callback = reinterpret_cast(req_wrap->original_callback_); original_callback(req, args...); @@ -138,7 +139,6 @@ template template int ReqWrap::Dispatch(LibuvFunction fn, Args... args) { Dispatched(); - // This expands as: // // int err = fn(env()->event_loop(), req(), arg1, arg2, Wrapper, arg3, ...) @@ -158,8 +158,10 @@ int ReqWrap::Dispatch(LibuvFunction fn, Args... args) { env()->event_loop(), req(), MakeLibuvRequestCallback::For(this, args)...); - if (err >= 0) + if (err >= 0) { + ClearWeak(); env()->IncreaseWaitingRequestCounter(); + } return err; }