@@ -345,44 +345,51 @@ MaybeLocal<Promise> FileHandle::ClosePromise() {
345345 Isolate* isolate = env()->isolate();
346346 EscapableHandleScope scope(isolate);
347347 Local<Context> context = env()->context();
348+
349+ Local<Value> close_resolver =
350+ object()->GetInternalField(FileHandle::kClosingPromiseSlot);
351+ if (!close_resolver.IsEmpty() && !close_resolver->IsUndefined()) {
352+ CHECK(close_resolver->IsPromise());
353+ return close_resolver.As<Promise>();
354+ }
355+
356+ CHECK(!closed_);
357+ CHECK(!closing_);
358+ CHECK(!reading_);
359+
348360 auto maybe_resolver = Promise::Resolver::New(context);
349361 CHECK(!maybe_resolver.IsEmpty());
350362 Local<Promise::Resolver> resolver = maybe_resolver.ToLocalChecked();
351363 Local<Promise> promise = resolver.As<Promise>();
352- CHECK(!reading_);
353- if (!closed_ && !closing_) {
354- closing_ = true;
355- Local<Object> close_req_obj;
356- if (!env()
357- ->fdclose_constructor_template()
358- ->NewInstance(env()->context())
359- .ToLocal(&close_req_obj)) {
360- return MaybeLocal<Promise>();
361- }
362- CloseReq* req = new CloseReq(env(), close_req_obj, promise, object());
363- auto AfterClose = uv_fs_callback_t{[](uv_fs_t* req) {
364- std::unique_ptr<CloseReq> close(CloseReq::from_req(req));
365- CHECK_NOT_NULL(close);
366- close->file_handle()->AfterClose();
367- Isolate* isolate = close->env()->isolate();
368- if (req->result < 0) {
369- HandleScope handle_scope(isolate);
370- close->Reject(
371- UVException(isolate, static_cast<int>(req->result), "close"));
372- } else {
373- close->Resolve();
374- }
375- }};
376- int ret = req->Dispatch(uv_fs_close, fd_, AfterClose);
377- if (ret < 0) {
378- req->Reject(UVException(isolate, ret, "close"));
379- delete req;
364+
365+ Local<Object> close_req_obj;
366+ if (!env()->fdclose_constructor_template()
367+ ->NewInstance(env()->context()).ToLocal(&close_req_obj)) {
368+ return MaybeLocal<Promise>();
369+ }
370+ closing_ = true;
371+ object()->SetInternalField(FileHandle::kClosingPromiseSlot, promise);
372+
373+ CloseReq* req = new CloseReq(env(), close_req_obj, promise, object());
374+ auto AfterClose = uv_fs_callback_t{[](uv_fs_t* req) {
375+ std::unique_ptr<CloseReq> close(CloseReq::from_req(req));
376+ CHECK_NOT_NULL(close);
377+ close->file_handle()->AfterClose();
378+ Isolate* isolate = close->env()->isolate();
379+ if (req->result < 0) {
380+ HandleScope handle_scope(isolate);
381+ close->Reject(
382+ UVException(isolate, static_cast<int>(req->result), "close"));
383+ } else {
384+ close->Resolve();
380385 }
381- } else {
382- // Already closed. Just reject the promise immediately
383- resolver->Reject(context, UVException(isolate, UV_EBADF, "close"))
384- .Check();
386+ }};
387+ int ret = req->Dispatch(uv_fs_close, fd_, AfterClose);
388+ if (ret < 0) {
389+ req->Reject(UVException(isolate, ret, "close"));
390+ delete req;
385391 }
392+
386393 return scope.Escape(promise);
387394}
388395
@@ -2538,7 +2545,7 @@ void Initialize(Local<Object> target,
25382545 env->SetProtoMethod(fd, "close", FileHandle::Close);
25392546 env->SetProtoMethod(fd, "releaseFD", FileHandle::ReleaseFD);
25402547 Local<ObjectTemplate> fdt = fd->InstanceTemplate();
2541- fdt->SetInternalFieldCount(StreamBase ::kInternalFieldCount);
2548+ fdt->SetInternalFieldCount(FileHandle ::kInternalFieldCount);
25422549 StreamBase::AddMethods(env, fd);
25432550 env->SetConstructorFunction(target, "FileHandle", fd);
25442551 env->set_fd_constructor_template(fdt);
0 commit comments