fs: pass ERR_DIR_CLOSED asynchronously to dir.close

Pass the error to the callback or returns a rejected Promise instead of
throwing a synchonous error.

Fixes: https://github.com/nodejs/node/issues/36237

PR-URL: https://github.com/nodejs/node/pull/36243
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Yongsheng Zhang <zyszys98@gmail.com>
This commit is contained in:
Zijian Liu 2020-11-24 14:30:26 +08:00 committed by Antoine du Hamel
parent 8d6c2f2ada
commit b938f88204
2 changed files with 32 additions and 8 deletions

View File

@ -6,6 +6,7 @@ const {
ArrayPrototypeSplice,
FunctionPrototypeBind,
ObjectDefineProperty,
PromiseReject,
Symbol,
SymbolAsyncIterator,
} = primordials;
@ -164,16 +165,24 @@ class Dir {
}
close(callback) {
if (this[kDirClosed] === true) {
throw new ERR_DIR_CLOSED();
// Promise
if (callback === undefined) {
if (this[kDirClosed] === true) {
return PromiseReject(new ERR_DIR_CLOSED());
}
return this[kDirClosePromisified]();
}
if (callback === undefined) {
return this[kDirClosePromisified]();
} else if (typeof callback !== 'function') {
// callback
if (typeof callback !== 'function') {
throw new ERR_INVALID_CALLBACK(callback);
}
if (this[kDirClosed] === true) {
process.nextTick(callback, new ERR_DIR_CLOSED());
return;
}
if (this[kDirOperationQueue] !== null) {
this[kDirOperationQueue].push(() => {
this.close(callback);

View File

@ -223,12 +223,11 @@ async function doAsyncIterInvalidCallbackTest() {
}
doAsyncIterInvalidCallbackTest().then(common.mustCall());
// Check if directory already closed - throw an exception
// Check first call to close() - should not report an error.
async function doAsyncIterDirClosedTest() {
const dir = await fs.promises.opendir(testDir);
await dir.close();
assert.throws(() => dir.close(), dirclosedError);
await assert.rejects(() => dir.close(), dirclosedError);
}
doAsyncIterDirClosedTest().then(common.mustCall());
@ -267,3 +266,19 @@ async function doConcurrentAsyncMixedOps() {
await promise2;
}
doConcurrentAsyncMixedOps().then(common.mustCall());
// Check if directory already closed - the callback should pass an error.
{
const dir = fs.opendirSync(testDir);
dir.closeSync();
dir.close(common.mustCall((error) => {
assert.strictEqual(error.code, dirclosedError.code);
}));
}
// Check if directory already closed - throw an promise exception.
{
const dir = fs.opendirSync(testDir);
dir.closeSync();
assert.rejects(dir.close(), dirclosedError).then(common.mustCall());
}