diff --git a/lib/fs.js b/lib/fs.js index e05b8335f89c47..a0f501f012034d 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -103,6 +103,8 @@ const { }, copyObject, Dirent, + join, + relative, getDirent, getDirents, getOptions, @@ -1401,7 +1403,7 @@ function handleDirents({ result, currentPath, context }) { for (let i = 0; i < length; i++) { // Avoid excluding symlinks, as they are not directories. // Refs: https://github.com/nodejs/node/issues/52663 - const fullPath = pathModule.join(currentPath, names[i]); + const fullPath = join(currentPath, names[i]); const dirent = getDirent(currentPath, names[i], types[i]); ArrayPrototypePush(context.readdirResults, dirent); @@ -1413,8 +1415,8 @@ function handleDirents({ result, currentPath, context }) { function handleFilePaths({ result, currentPath, context }) { for (let i = 0; i < result.length; i++) { - const resultPath = pathModule.join(currentPath, result[i]); - const relativeResultPath = pathModule.relative(context.basePath, resultPath); + const resultPath = join(currentPath, result[i]); + const relativeResultPath = relative(context.basePath, resultPath); const stat = binding.internalModuleStat(resultPath); ArrayPrototypePush(context.readdirResults, relativeResultPath); diff --git a/lib/internal/fs/utils.js b/lib/internal/fs/utils.js index 0f788ce4dbc3a3..5f421faffe818b 100644 --- a/lib/internal/fs/utils.js +++ b/lib/internal/fs/utils.js @@ -229,6 +229,11 @@ function join(path, name) { return Buffer.concat([pathBuffer, name]); } + if (isUint8Array(path) && typeof name === 'string') { + const nameBuffer = Buffer.from(name); + return Buffer.concat([path, bufferSep, nameBuffer]); + } + if (typeof path === 'string' && typeof name === 'string') { return pathModule.join(path, name); } @@ -241,6 +246,28 @@ function join(path, name) { 'path', ['string', 'Buffer'], path); } +function relative(from, to) { + if (typeof from === 'string' && isUint8Array(to)) { + return pathModule.relative(from, Buffer.from(to)); + } + + if (isUint8Array(from) && typeof to === 'string') { + return Buffer.from(pathModule.relative(Buffer.from(from), to)); + } + + if (isUint8Array(from) && isUint8Array(to)) { + const fromPath = Buffer.from(from); + const toPath = Buffer.from(to); + return pathModule.relative(fromPath.toString(), toPath.toString()); + } + + if (typeof from === 'string' && typeof to === 'string') { + return pathModule.relative(from, to); + } + + throw new ERR_INVALID_ARG_TYPE('from', ['string', 'Buffer'], from); +} + function getDirents(path, { 0: names, 1: types }, callback) { let i; if (typeof callback === 'function') { @@ -719,6 +746,9 @@ const validatePath = hideStackFrames((path, propName = 'path') => { ); }); +/** + * @returns {string|Buffer} + */ const getValidatedPath = hideStackFrames((fileURLOrPath, propName = 'path') => { const path = toPathIfFileURL(fileURLOrPath); validatePath(path, propName); @@ -925,6 +955,8 @@ module.exports = { kReadFileUnknownBufferLength, kWriteFileMaxChunkSize, }, + join, + relative, assertEncoding, BigIntStats, // for testing copyObject, diff --git a/src/node_file.cc b/src/node_file.cc index 2a2384c88c63d7..26edb09cd245cd 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -1053,7 +1053,7 @@ static void InternalModuleStat(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); CHECK_EQ(args.Length(), 1); - CHECK(args[0]->IsString()); + CHECK(args[0]->IsString() || args[0]->IsArrayBufferView()); BufferValue path(env->isolate(), args[0]); CHECK_NOT_NULL(*path); ToNamespacedPath(env, &path); diff --git a/test/parallel/test-fs-readdir-buffer.js b/test/parallel/test-fs-readdir-buffer.js index 54b7353cb1b3b2..04db54a1fd67b0 100644 --- a/test/parallel/test-fs-readdir-buffer.js +++ b/test/parallel/test-fs-readdir-buffer.js @@ -6,12 +6,8 @@ if (!common.isMacOS) { common.skip('this tests works only on MacOS'); } -const assert = require('assert'); - fs.readdir( Buffer.from('/dev'), { withFileTypes: true, encoding: 'buffer' }, - common.mustCall((e, d) => { - assert.strictEqual(e, null); - }) + common.mustSucceed() ); diff --git a/test/parallel/test-fs-readdir-recursive.js b/test/parallel/test-fs-readdir-recursive.js index 7cfc0903faa0b4..acc943ca2ac5a5 100644 --- a/test/parallel/test-fs-readdir-recursive.js +++ b/test/parallel/test-fs-readdir-recursive.js @@ -12,6 +12,8 @@ test('readdir should not recurse into Unix domain sockets', (t, done) => { // The process should not crash // See https://github.com/nodejs/node/issues/52159 fs.readdirSync(tmpdir.path, { recursive: true }); + // Buffer with utf8 default encoding + fs.readdirSync(Buffer.from(tmpdir.path), { recursive: true }); server.close(); done(); })); diff --git a/test/parallel/test-fs-readdir.js b/test/parallel/test-fs-readdir.js index 6ae29045cdd7a3..d56925edc1f184 100644 --- a/test/parallel/test-fs-readdir.js +++ b/test/parallel/test-fs-readdir.js @@ -20,11 +20,25 @@ files.forEach(function(currentFile) { // Check the readdir Sync version assert.deepStrictEqual(files, fs.readdirSync(readdirDir).sort()); +// Check the readdir Sync version (Buffer with utf8 default encoding) +assert.deepStrictEqual( + files, + fs.readdirSync(Buffer.from(readdirDir)).sort() +); + // Check the readdir async version fs.readdir(readdirDir, common.mustSucceed((f) => { assert.deepStrictEqual(files, f.sort()); })); +// Check the readdir async version (Buffer with utf8 default encoding) +fs.readdir( + Buffer.from(readdirDir), + common.mustSucceed((f) => { + assert.deepStrictEqual(files, f.sort()); + }) +); + // readdir() on file should throw ENOTDIR // https://github.com/joyent/node/issues/1869 assert.throws(function() {