diff --git a/src/node_file.cc b/src/node_file.cc index 7eb0de310f7e1dc..243075edad4c1e6 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -345,44 +345,48 @@ MaybeLocal FileHandle::ClosePromise() { Isolate* isolate = env()->isolate(); EscapableHandleScope scope(isolate); Local context = env()->context(); + + Local close_resolver = close_promise_.Get(isolate); + if (!close_resolver.IsEmpty()) + return close_resolver.As(); + + CHECK(!closed_); + CHECK(!closing_); + CHECK(!reading_); + auto maybe_resolver = Promise::Resolver::New(context); CHECK(!maybe_resolver.IsEmpty()); Local resolver = maybe_resolver.ToLocalChecked(); Local promise = resolver.As(); - CHECK(!reading_); - if (!closed_ && !closing_) { - closing_ = true; - Local close_req_obj; - if (!env() - ->fdclose_constructor_template() - ->NewInstance(env()->context()) - .ToLocal(&close_req_obj)) { - return MaybeLocal(); - } - 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); - close->file_handle()->AfterClose(); - Isolate* isolate = close->env()->isolate(); - if (req->result < 0) { - HandleScope handle_scope(isolate); - close->Reject( - UVException(isolate, static_cast(req->result), "close")); - } else { - close->Resolve(); - } - }}; - int ret = req->Dispatch(uv_fs_close, fd_, AfterClose); - if (ret < 0) { - req->Reject(UVException(isolate, ret, "close")); - delete req; + + Local close_req_obj; + if (!env()->fdclose_constructor_template() + ->NewInstance(env()->context()).ToLocal(&close_req_obj)) { + return MaybeLocal(); + } + closing_ = true; + close_promise_.Reset(isolate, resolver); + + 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); + close->file_handle()->AfterClose(); + Isolate* isolate = close->env()->isolate(); + if (req->result < 0) { + HandleScope handle_scope(isolate); + close->Reject( + UVException(isolate, static_cast(req->result), "close")); + } else { + close->Resolve(); } - } else { - // Already closed. Just reject the promise immediately - resolver->Reject(context, UVException(isolate, UV_EBADF, "close")) - .Check(); + }}; + int ret = req->Dispatch(uv_fs_close, fd_, AfterClose); + if (ret < 0) { + req->Reject(UVException(isolate, ret, "close")); + delete req; } + return scope.Escape(promise); } diff --git a/src/node_file.h b/src/node_file.h index f1515a3e25d6d18..5449b97ab32b4af 100644 --- a/src/node_file.h +++ b/src/node_file.h @@ -351,6 +351,8 @@ class FileHandle final : public AsyncWrap, public StreamBase { BaseObjectPtr current_read_; BaseObjectPtr binding_data_; + + v8::Global close_promise_{}; }; int MKDirpSync(uv_loop_t* loop,