Adds the node:vfs builtin module with VirtualFileSystem and provider classes. No integration with fs, modules, or SEA. Assisted-by: Claude-Opus4.7 Signed-off-by: Matteo Collina <hello@matteocollina.com> PR-URL: https://github.com/nodejs/node/pull/63115 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Paolo Insogna <paolo@cowtech.it> Reviewed-By: Robert Nagy <ronagy@icloud.com> Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
104 lines
1.9 KiB
JavaScript
104 lines
1.9 KiB
JavaScript
'use strict';
|
|
|
|
const {
|
|
SymbolAsyncDispose,
|
|
SymbolAsyncIterator,
|
|
SymbolDispose,
|
|
} = primordials;
|
|
|
|
const {
|
|
codes: {
|
|
ERR_DIR_CLOSED,
|
|
},
|
|
} = require('internal/errors');
|
|
|
|
/**
|
|
* Virtual directory handle returned by VFS opendir/opendirSync.
|
|
* Mimics the subset of the native Dir interface used by Node.js internals
|
|
* (e.g. fs.cp, fs.promises.cp).
|
|
*/
|
|
class VirtualDir {
|
|
#path;
|
|
#entries;
|
|
#index;
|
|
#closed;
|
|
|
|
constructor(dirPath, entries) {
|
|
this.#path = dirPath;
|
|
this.#entries = entries;
|
|
this.#index = 0;
|
|
this.#closed = false;
|
|
}
|
|
|
|
get path() {
|
|
return this.#path;
|
|
}
|
|
|
|
readSync() {
|
|
if (this.#closed) {
|
|
throw new ERR_DIR_CLOSED();
|
|
}
|
|
if (this.#index >= this.#entries.length) {
|
|
return null;
|
|
}
|
|
return this.#entries[this.#index++];
|
|
}
|
|
|
|
async read(callback) {
|
|
if (typeof callback === 'function') {
|
|
try {
|
|
const result = this.readSync();
|
|
process.nextTick(callback, null, result);
|
|
} catch (err) {
|
|
process.nextTick(callback, err);
|
|
}
|
|
return;
|
|
}
|
|
return this.readSync();
|
|
}
|
|
|
|
closeSync() {
|
|
if (this.#closed) {
|
|
throw new ERR_DIR_CLOSED();
|
|
}
|
|
this.#closed = true;
|
|
}
|
|
|
|
async close(callback) {
|
|
if (typeof callback === 'function') {
|
|
this.closeSync();
|
|
process.nextTick(callback, null);
|
|
return;
|
|
}
|
|
this.closeSync();
|
|
}
|
|
|
|
async *entries() {
|
|
if (this.#closed) {
|
|
throw new ERR_DIR_CLOSED();
|
|
}
|
|
try {
|
|
let entry;
|
|
while ((entry = this.readSync()) !== null) {
|
|
yield entry;
|
|
}
|
|
} finally {
|
|
if (!this.#closed) {
|
|
this.closeSync();
|
|
}
|
|
}
|
|
}
|
|
|
|
[SymbolDispose]() {
|
|
if (!this.#closed) {
|
|
this.closeSync();
|
|
}
|
|
}
|
|
}
|
|
|
|
VirtualDir.prototype[SymbolAsyncIterator] = VirtualDir.prototype.entries;
|
|
VirtualDir.prototype[SymbolAsyncDispose] = VirtualDir.prototype.close;
|
|
|
|
module.exports = {
|
|
VirtualDir,
|
|
};
|