Add mount/unmount lifecycle on `VirtualFileSystem`, a handler registry that fs.js and fs/promises.js consult via `vfsState.handlers`, and a router that maps absolute paths to the VFS that owns them. When a VFS is mounted, the public `fs.*` and `fs/promises` APIs (including streams, `fs.watch`, and `opendir`) dispatch to the provider for paths under the mount point, and fall through to the real filesystem otherwise. Includes per-method dispatch tests, error-path coverage, multi-mount routing tests, and router unit tests. Ref: https://github.com/nodejs/node/pull/63115 Signed-off-by: Matteo Collina <hello@matteocollina.com> PR-URL: https://github.com/nodejs/node/pull/63537 Refs: https://github.com/nodejs/node/pull/63115 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Paolo Insogna <paolo@cowtech.it>
46 lines
1.4 KiB
JavaScript
46 lines
1.4 KiB
JavaScript
'use strict';
|
|
|
|
const {
|
|
ArrayPrototypeJoin,
|
|
StringPrototypeSplit,
|
|
StringPrototypeStartsWith,
|
|
} = primordials;
|
|
|
|
const { isAbsolute, relative, sep } = require('path');
|
|
|
|
// `path.sep` is required here because on Windows `path.resolve('/virtual')`
|
|
// produces 'C:\virtual' and all resolved paths use backslashes - a hardcoded
|
|
// '/' check would never match. The trailing-separator guard handles root
|
|
// mount points like 'C:\' so we don't end up with 'C:\\'.
|
|
function isUnderMountPoint(normalizedPath, mountPoint) {
|
|
if (normalizedPath === mountPoint) {
|
|
return true;
|
|
}
|
|
if (mountPoint === '/') {
|
|
return StringPrototypeStartsWith(normalizedPath, '/');
|
|
}
|
|
const prefix = mountPoint[mountPoint.length - 1] === sep ?
|
|
mountPoint : mountPoint + sep;
|
|
return StringPrototypeStartsWith(normalizedPath, prefix);
|
|
}
|
|
|
|
// Returns a POSIX-style relative path the provider can consume. Uses
|
|
// `path.relative()` so Windows backslash paths are handled correctly, then
|
|
// re-joins with forward slashes for the provider's internal POSIX format.
|
|
function getRelativePath(normalizedPath, mountPoint) {
|
|
if (normalizedPath === mountPoint) {
|
|
return '/';
|
|
}
|
|
if (mountPoint === '/') {
|
|
return normalizedPath;
|
|
}
|
|
const rel = relative(mountPoint, normalizedPath);
|
|
const segments = StringPrototypeSplit(rel, sep);
|
|
return '/' + ArrayPrototypeJoin(segments, '/');
|
|
}
|
|
|
|
module.exports = {
|
|
isUnderMountPoint,
|
|
getRelativePath,
|
|
isAbsolutePath: isAbsolute,
|
|
};
|