Browse Source

fix: fs.readdir should support withFileTypes (#24107)

Co-authored-by: Shelley Vohr <[email protected]>
trop[bot] 4 years ago
parent
commit
4c28b23b06
2 changed files with 69 additions and 2 deletions
  1. 33 2
      lib/common/asar.js
  2. 36 0
      spec/asar-spec.js

+ 33 - 2
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;
     };
 

+ 36 - 0
spec/asar-spec.js

@@ -796,6 +796,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);
@@ -820,6 +830,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) {
@@ -828,6 +853,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) {
@@ -853,6 +879,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);