fs: introduce `opendir()` and `fs.Dir`
This adds long-requested methods for asynchronously interacting and iterating through directory entries by using uv_fs_opendir
, uv_fs_readdir
, and uv_fs_closedir
.
const fs = require('fs');
async function print(path) {
const dir = await fs.promises.opendir(path);
for await (const dirent of dir) {
console.log(dirent.name);
}
}
print('./').catch(console.error);
fs.opendir()
and friends return an fs.Dir
, which contains methods for doing reads and cleanup. fs.Dir
also has the async iterator symbol exposed.
The read()
method and friends only return fs.Dirent
s for this API.
Having a entry type or doing a stat
call is deemed to be necessary in the majority of cases, so just returning dirents seems like the logical choice for a new api.
Reading when there are no more entries returns null
instead of a dirent. However the async iterator hides that (and does automatic cleanup).
The code lives in separate files from the rest of fs, this is done partially to prevent over-pollution of those (already very large) files, but also in the case of js allows loading into fsPromises
.
Due to async_hooks, this introduces a new handle type of DIRHANDLE
.
This PR does not attempt to make complete optimization of this feature. Notable future improvements include:
- Moving promise work into C++ land like FileHandle.
Makinguv_dir_t
keep a record of its path (or a way to retrieve it).- Possibly adding
readv()
to do multi-entry directory reads. - Aliasing
fs.readdir
tofs.scandir
and doing a deprecation.
Refs: https://github.com/nodejs/node-v0.x-archive/issues/388 Refs: https://github.com/nodejs/node/issues/583 Refs: https://github.com/libuv/libuv/pull/2057
Checklist
-
make -j4 test
(UNIX), orvcbuild test
(Windows) passes -
tests and/or benchmarks are included -
documentation is changed or added -
commit message follows commit guidelines
I am open to discussing the api shapes, I found that this fs.Dir
api made it easiest to reconcile the callback and promise apis into "one" reasonably nice (hopefully future proof) api, but I feel folks might have strong feelings about that. It does make a bit of mess in the docs though.
Also please tell me any C++ nonsense I got terribly wrong, haha.