Repository: streamich/memfs
Pull request #1058 (2024-09-05 10:39:18)

fix: add `parentPath` to `Dirent`
# Changes

- Add missing `parentPath` property to `Dirent` which is equal to the `path` property

The `parentPath` property will replace the `path` property on `Dirent` in future node versions (see [Docs](https://nodejs.org/api/fs.html#class-fsdirent)).

References #735

SoulKa: I fixed the tests that were broken due to the new `parentPath` property. Is that enough? I also changed the one occurrence where `Dirent#path` was used.

Patch:
diff --git a/docs/snapshot/index.md b/docs/snapshot/index.md
index e860d985..d9541686 100644
--- a/docs/snapshot/index.md
+++ b/docs/snapshot/index.md
@@ -30,15 +30,15 @@ import * as snapshot from 'memfs/lib/snapshot';
 You can convert any folder of an `fs`-like file system into a POJO snapshot.
 
 ```ts
-const snap = snapshot.toSnapshotSync({ fs, dir });
-const snap = await snapshot.toSnapshot({ fs: fs.promises, dir });
+const snap = snapshot.toSnapshotSync({ fs, path });
+const snap = await snapshot.toSnapshot({ fs: fs.promises, path });
 ```
 
 Then import it back from snapshot.
 
 ```ts
-snapshot.fromSnapshotSync(snap, { fs, dir });
-await snapshot.fromSnapshot(snap, { fs: fs.promises, dir });
+snapshot.fromSnapshotSync(snap, { fs, path });
+await snapshot.fromSnapshot(snap, { fs: fs.promises, path });
 ```
 
 ## Binary snapshot
@@ -47,15 +47,15 @@ Binary snapshots are encoded as CBOR `Uint8Array` buffers. You can convert any
 folder of an `fs`-like file system into a `Uint8Array` snapshot.
 
 ```ts
-const uint8 = snapshot.toBinarySnapshotSync({ fs, dir });
-const uint8 = await snapshot.toBinarySnapshot({ fs: fs.promises, dir });
+const uint8 = snapshot.toBinarySnapshotSync({ fs, path });
+const uint8 = await snapshot.toBinarySnapshot({ fs: fs.promises, path });
 ```
 
 Then import it back from `Uint8Array` snapshot.
 
 ```ts
-snapshot.fromBinarySnapshotSync(uint8, { fs, dir });
-await snapshot.fromBinarySnapshot(uint8, { fs: fs.promises, dir });
+snapshot.fromBinarySnapshotSync(uint8, { fs, path });
+await snapshot.fromBinarySnapshot(uint8, { fs: fs.promises, path });
 ```
 
 ## JSON snapshot
@@ -67,15 +67,15 @@ data is encoded as Base64 data URL strings. The resulting JSON is returned as
 You can convert any folder of an `fs`-like file system into a `Uint8Array` snapshot.
 
 ```ts
-const uint8 = snapshot.toJsonSnapshotSync({ fs, dir });
-const uint8 = await snapshot.toJsonSnapshot({ fs: fs.promises, dir });
+const uint8 = snapshot.toJsonSnapshotSync({ fs, path });
+const uint8 = await snapshot.toJsonSnapshot({ fs: fs.promises, path });
 ```
 
 Then import it back from `Uint8Array` snapshot.
 
 ```ts
-snapshot.fromJsonSnapshotSync(uint8, { fs, dir });
-await snapshot.fromJsonSnapshot(uint8, { fs: fs.promises, dir });
+snapshot.fromJsonSnapshotSync(uint8, { fs, path });
+await snapshot.fromJsonSnapshot(uint8, { fs: fs.promises, path });
 ```
 
 ## Encoding format
diff --git a/src/Dirent.ts b/src/Dirent.ts
index 32cafd51..237598f1 100644
--- a/src/Dirent.ts
+++ b/src/Dirent.ts
@@ -16,12 +16,14 @@ export class Dirent implements IDirent {
     dirent.name = strToEncoding(link.getName(), encoding);
     dirent.mode = mode;
     dirent.path = link.getParentPath();
+    dirent.parentPath = dirent.path;
 
     return dirent;
   }
 
   name: TDataOut = '';
   path = '';
+  parentPath = '';
   private mode: number = 0;
 
   private _checkModeProperty(property: number): boolean {
diff --git a/src/volume.ts b/src/volume.ts
index 43f31406..8bff6883 100644
--- a/src/volume.ts
+++ b/src/volume.ts
@@ -1499,7 +1499,7 @@ export class Volume implements FsCallbackApi, FsSynchronousApi {
 
     return list.map(dirent => {
       if (options.recursive) {
-        let fullPath = pathModule.join(dirent.path, dirent.name.toString());
+        let fullPath = pathModule.join(dirent.parentPath, dirent.name.toString());
         if (isWin) {
           fullPath = fullPath.replace(/\\/g, '/');
         }


Test patch:
diff --git a/src/__tests__/volume/readdirSync.test.ts b/src/__tests__/volume/readdirSync.test.ts
index adf03fd2..2a33301b 100644
--- a/src/__tests__/volume/readdirSync.test.ts
+++ b/src/__tests__/volume/readdirSync.test.ts
@@ -67,9 +67,9 @@ describe('readdirSync()', () => {
       return { ...dirent };
     });
     expect(mapped).toEqual([
-      { mode: 33206, name: 'af', path: '/x' },
-      { mode: 16895, name: 'b', path: '/x' },
-      { mode: 16895, name: 'c', path: '/x' },
+      { mode: 33206, name: 'af', path: '/x', parentPath: '/x' },
+      { mode: 16895, name: 'b', path: '/x', parentPath: '/x' },
+      { mode: 16895, name: 'c', path: '/x', parentPath: '/x' },
     ]);
   });
 
@@ -105,16 +105,16 @@ describe('readdirSync()', () => {
       })
       .sort((a, b) => a.path.localeCompare(b.path));
     expect(mapped).toEqual([
-      { mode: 33206, name: 'af1', path: '/z' },
-      { mode: 33206, name: 'af2', path: '/z' },
-      { mode: 16895, name: 'b', path: '/z' },
-      { mode: 16895, name: 'c', path: '/z' },
-      { mode: 33206, name: 'bf1', path: '/z/b' },
-      { mode: 33206, name: 'bf2', path: '/z/b' },
-      { mode: 16895, name: 'c', path: '/z/c' },
-      { mode: 33206, name: '.cf0', path: '/z/c/c' },
-      { mode: 33206, name: 'cf1', path: '/z/c/c' },
-      { mode: 33206, name: 'cf2', path: '/z/c/c' },
+      { mode: 33206, name: 'af1', path: '/z', parentPath: '/z' },
+      { mode: 33206, name: 'af2', path: '/z', parentPath: '/z' },
+      { mode: 16895, name: 'b', path: '/z', parentPath: '/z' },
+      { mode: 16895, name: 'c', path: '/z', parentPath: '/z' },
+      { mode: 33206, name: 'bf1', path: '/z/b', parentPath: '/z/b' },
+      { mode: 33206, name: 'bf2', path: '/z/b', parentPath: '/z/b' },
+      { mode: 16895, name: 'c', path: '/z/c', parentPath: '/z/c' },
+      { mode: 33206, name: '.cf0', path: '/z/c/c', parentPath: '/z/c/c' },
+      { mode: 33206, name: 'cf1', path: '/z/c/c', parentPath: '/z/c/c' },
+      { mode: 33206, name: 'cf2', path: '/z/c/c', parentPath: '/z/c/c' },
     ]);
   });
 });