From f6ad916870ee8b1ad6a6c75a3d12d8bfc55805e1 Mon Sep 17 00:00:00 2001 From: Shelley Vohr Date: Wed, 10 Jun 2020 20:32:30 -0700 Subject: [PATCH] fix: fs.readdir should support withFileTypes --- lib/common/asar.js | 35 +++++++++++++++++++++++++++++++++-- spec/asar-spec.js | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/lib/common/asar.js b/lib/common/asar.js index 804d98cf43500..a23f34d8bf392 100644 --- a/lib/common/asar.js +++ b/lib/common/asar.js @@ -572,7 +572,7 @@ }; const { readdir } = fs; - fs.readdir = function (pathArgument, options, callback) { + fs.readdir = function (pathArgument, options = {}, callback) { const { isAsar, asarPath, filePath } = splitPath(pathArgument); if (typeof options === 'function') { callback = options; @@ -594,13 +594,29 @@ return; } + if (options.withFileTypes) { + const dirents = []; + for (const file of files) { + const stats = archive.stat(file); + if (stats.isFile) { + dirents.push(new fs.Dirent(file, fs.constants.UV_DIRENT_FILE)); + } else if (stats.isDirectory) { + dirents.push(new fs.Dirent(file, fs.constants.UV_DIRENT_DIR)); + } else if (stats.isLink) { + dirents.push(new fs.Dirent(file, fs.constants.UV_DIRENT_LINK)); + } + } + nextTick(callback, [null, dirents]); + return; + } + nextTick(callback, [null, files]); }; fs.promises.readdir = util.promisify(fs.readdir); const { readdirSync } = fs; - fs.readdirSync = function (pathArgument, options) { + fs.readdirSync = function (pathArgument, options = {}) { const { isAsar, asarPath, filePath } = splitPath(pathArgument); if (!isAsar) return readdirSync.apply(this, arguments); @@ -614,6 +630,21 @@ throw createError(AsarError.NOT_FOUND, { asarPath, filePath }); } + if (options.withFileTypes) { + const dirents = []; + for (const file of files) { + const stats = archive.stat(file); + if (stats.isFile) { + dirents.push(new fs.Dirent(file, fs.constants.UV_DIRENT_FILE)); + } else if (stats.isDirectory) { + dirents.push(new fs.Dirent(file, fs.constants.UV_DIRENT_DIR)); + } else if (stats.isLink) { + dirents.push(new fs.Dirent(file, fs.constants.UV_DIRENT_LINK)); + } + } + return dirents; + } + return files; }; diff --git a/spec/asar-spec.js b/spec/asar-spec.js index de6be9d54e650..29656fb3ba5d1 100644 --- a/spec/asar-spec.js +++ b/spec/asar-spec.js @@ -792,6 +792,16 @@ describe('asar package', function () { expect(dirs).to.deep.equal(['file1', 'file2', 'file3', 'link1', 'link2']); }); + it('supports withFileTypes', function () { + const p = path.join(asarDir, 'a.asar'); + const dirs = fs.readdirSync(p, { withFileTypes: true }); + for (const dir of dirs) { + expect(dir instanceof fs.Dirent).to.be.true(); + } + const names = dirs.map(a => a.name); + expect(names).to.deep.equal(['dir1', 'dir2', 'dir3', 'file1', 'file2', 'file3', 'link1', 'link2', 'ping.js']); + }); + it('reads dirs from a linked dir', function () { const p = path.join(asarDir, 'a.asar', 'link2', 'link2'); const dirs = fs.readdirSync(p); @@ -816,6 +826,21 @@ describe('asar package', function () { }); }); + it('supports withFileTypes', function (done) { + const p = path.join(asarDir, 'a.asar'); + + fs.readdir(p, { withFileTypes: true }, (err, dirs) => { + expect(err).to.be.null(); + for (const dir of dirs) { + expect(dir instanceof fs.Dirent).to.be.true(); + } + + const names = dirs.map(a => a.name); + expect(names).to.deep.equal(['dir1', 'dir2', 'dir3', 'file1', 'file2', 'file3', 'link1', 'link2', 'ping.js']); + done(); + }); + }); + it('reads dirs from a normal dir', function (done) { const p = path.join(asarDir, 'a.asar', 'dir1'); fs.readdir(p, function (err, dirs) { @@ -824,6 +849,7 @@ describe('asar package', function () { done(); }); }); + it('reads dirs from a linked dir', function (done) { const p = path.join(asarDir, 'a.asar', 'link2', 'link2'); fs.readdir(p, function (err, dirs) { @@ -849,6 +875,16 @@ describe('asar package', function () { expect(dirs).to.deep.equal(['dir1', 'dir2', 'dir3', 'file1', 'file2', 'file3', 'link1', 'link2', 'ping.js']); }); + it('supports withFileTypes', async function () { + const p = path.join(asarDir, 'a.asar'); + const dirs = await fs.promises.readdir(p, { withFileTypes: true }); + for (const dir of dirs) { + expect(dir instanceof fs.Dirent).to.be.true(); + } + const names = dirs.map(a => a.name); + expect(names).to.deep.equal(['dir1', 'dir2', 'dir3', 'file1', 'file2', 'file3', 'link1', 'link2', 'ping.js']); + }); + it('reads dirs from a normal dir', async function () { const p = path.join(asarDir, 'a.asar', 'dir1'); const dirs = await fs.promises.readdir(p);