fs: make Dir disposers idempotent

PR-URL: https://github.com/nodejs/node/pull/58692
Refs: https://github.com/nodejs/node/pull/58206
Reviewed-By: Ethan Arrowood <ethan@arrowood.dev>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
This commit is contained in:
René 2025-06-20 20:03:34 +01:00 committed by GitHub
parent 88f4cef8b9
commit ce546e468a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 21 additions and 24 deletions

View File

@ -6773,8 +6773,8 @@ changes:
description: No longer experimental.
-->
Calls `dir.close()` and returns a promise that fulfills when the
dir is closed.
Calls `dir.close()` if the directory handle is open, and returns a promise that
fulfills when disposal is complete.
#### `dir[Symbol.dispose]()`
@ -6786,7 +6786,8 @@ changes:
description: No longer experimental.
-->
Calls `dir.closeSync()` and returns `undefined`.
Calls `dir.closeSync()` if the directory handle is open, and returns
`undefined`.
### Class: `fs.Dirent`

View File

@ -24,7 +24,6 @@ const {
const { FSReqCallback } = binding;
const {
assignFunctionName,
promisify,
} = require('internal/util');
const {
@ -296,31 +295,24 @@ class Dir {
await this.#closePromisified();
}
}
[SymbolDispose]() {
if (this.#closed) return;
this.closeSync();
}
async [SymbolAsyncDispose]() {
if (this.#closed) return;
await this.#closePromisified();
}
}
const nonEnumerableDescriptor = {
enumerable: false,
writable: true,
configurable: true,
};
ObjectDefineProperties(Dir.prototype, {
[SymbolDispose]: {
__proto__: null,
...nonEnumerableDescriptor,
value: assignFunctionName(SymbolDispose, function() {
this.closeSync();
}),
},
[SymbolAsyncDispose]: {
__proto__: null,
...nonEnumerableDescriptor,
value: assignFunctionName(SymbolAsyncDispose, function() {
this.close();
}),
},
[SymbolAsyncIterator]: {
__proto__: null,
...nonEnumerableDescriptor,
enumerable: false,
writable: true,
configurable: true,
value: Dir.prototype.entries,
},
});

View File

@ -11,10 +11,14 @@ async function explicitCall() {
const dh = await fs.opendir(__dirname);
await dh[Symbol.asyncDispose]();
// Repeat invocations should not reject
await dh[Symbol.asyncDispose]();
await assert.rejects(dh.read(), { code: 'ERR_DIR_CLOSED' });
const dhSync = opendirSync(__dirname);
dhSync[Symbol.dispose]();
// Repeat invocations should not throw
dhSync[Symbol.dispose]();
assert.throws(() => dhSync.readSync(), { code: 'ERR_DIR_CLOSED' });
}