Skip to content

Commit a94343b

Browse files
committed
vfs: return FileHandle from fs.promises.open
Wrap mounted virtual file descriptors in the public FileHandle interface while delegating operations to the underlying provider handle. Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com> Assisted-by: codex:gpt-5.6-sol
1 parent b4c83f5 commit a94343b

3 files changed

Lines changed: 44 additions & 3 deletions

File tree

lib/internal/vfs/fd.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
'use strict';
22

33
const {
4+
FunctionPrototypeBind,
5+
ObjectDefineProperty,
46
SafeMap,
57
Symbol,
68
} = primordials;
@@ -46,6 +48,42 @@ class VirtualFD {
4648
get entry() {
4749
return this[kEntry];
4850
}
51+
52+
getAsyncId() {
53+
return this[kFd];
54+
}
55+
56+
async close() {
57+
await this[kEntry].close();
58+
closeVirtualFd(this[kFd]);
59+
}
60+
61+
closeSync() {
62+
this[kEntry].closeSync();
63+
closeVirtualFd(this[kFd]);
64+
}
65+
}
66+
67+
const vfsFileHandleMethods = [
68+
'appendFile', 'chmod', 'chown', 'datasync', 'sync', 'read', 'readv',
69+
'readFile', 'stat', 'truncate', 'utimes', 'write', 'writev', 'writeFile',
70+
];
71+
let FileHandle;
72+
73+
function createVfsFileHandle(vfd) {
74+
FileHandle ??= require('internal/fs/promises').FileHandle;
75+
const fileHandle = new FileHandle(vfd);
76+
const entry = vfd.entry;
77+
for (let i = 0; i < vfsFileHandleMethods.length; i++) {
78+
const method = vfsFileHandleMethods[i];
79+
ObjectDefineProperty(fileHandle, method, {
80+
__proto__: null,
81+
configurable: true,
82+
value: FunctionPrototypeBind(entry[method], entry),
83+
writable: true,
84+
});
85+
}
86+
return fileHandle;
4987
}
5088

5189
/**
@@ -81,6 +119,7 @@ function closeVirtualFd(fd) {
81119
module.exports = {
82120
VFS_FD_MASK,
83121
VirtualFD,
122+
createVfsFileHandle,
84123
openVirtualFd,
85124
getVirtualFd,
86125
closeVirtualFd,

lib/internal/vfs/setup.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ const {
3030
getLayerIdFromPath,
3131
getNormalizedVfsRoot,
3232
} = require('internal/vfs/router');
33-
const { getVirtualFd, closeVirtualFd } = require('internal/vfs/fd');
33+
const { getVirtualFd, closeVirtualFd, createVfsFileHandle } = require('internal/vfs/fd');
3434
const { assertEncoding, setVfsHandlers } = require('internal/fs/utils');
3535
const permission = require('internal/process/permission');
3636
const { getOptionValue } = require('internal/options');
@@ -786,8 +786,7 @@ function createVfsHandlers() {
786786
const r = findVFSForPath(pathStr);
787787
if (r !== null) {
788788
const fd = r.vfs.openSync(r.path, flags, mode);
789-
const vfd = getVirtualFd(fd);
790-
return PromiseResolve(vfd.entry);
789+
return PromiseResolve(createVfsFileHandle(getVirtualFd(fd)));
791790
}
792791
}
793792
return undefined;

test/parallel/test-vfs-fs-promises.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ const vfs = require('node:vfs');
8686

8787
// FileHandle via fsp.open
8888
const handle = await fsp.open(p('src/hello.txt'), 'r');
89+
assert.strictEqual(handle.constructor.name, 'FileHandle');
90+
assert.strictEqual(typeof handle.fd, 'number');
91+
assert.strictEqual(typeof handle.createReadStream, 'function');
8992
assert.strictEqual(await handle.readFile('utf8'), 'hello');
9093
await handle.close();
9194

0 commit comments

Comments
 (0)