Skip to content

Implement realpath.native support for memfs#1117

Merged
streamich merged 4 commits intomasterfrom
copilot/fix-1116
Jul 27, 2025
Merged

Implement realpath.native support for memfs#1117
streamich merged 4 commits intomasterfrom
copilot/fix-1116

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Jul 26, 2025

This PR adds support for fs.realpath.native() and fs.realpathSync.native() to memfs, bringing full compatibility with Node.js filesystem API.

What's Added

  • fs.realpath.native(path[, options], callback) - Asynchronous native realpath
  • fs.realpathSync.native(path[, options]) - Synchronous native realpath

Both methods support the same parameter combinations as Node.js:

  • Path as string, Buffer, or URL
  • Optional encoding options (string or object with encoding property)
  • Full error handling and callback patterns

Implementation Details

The implementation delegates to the existing realpathBase method used by regular realpath functions. This is appropriate since memfs operates as a virtual filesystem and doesn't require actual native system calls. The native methods behave identically to their regular counterparts.

Key changes:

  • Added realpathNative and realpathNativeSync methods to Volume class
  • Extended TypeScript interfaces (FsCallbackApi, FsSynchronousApi, IFs) to include native methods
  • Updated createFsFromVolume to bind native methods as properties of realpath functions
  • Added comprehensive test coverage for all parameter combinations and edge cases

Example Usage

const { fs } = require('memfs');

// Setup filesystem
fs.mkdirSync('/app');
fs.writeFileSync('/app/index.js', 'console.log("Hello")');
fs.symlinkSync('/app', '/link');

// Use native realpath methods
fs.realpath.native('/link/index.js', (err, resolved) => {
  console.log(resolved); // '/app/index.js'
});

const resolved = fs.realpathSync.native('/link/index.js');
console.log(resolved); // '/app/index.js'

Testing

Added 23 comprehensive tests covering:

  • Async and sync variants with various parameter combinations
  • Different encoding options (utf8, buffer)
  • Error handling for non-existent paths and permission issues
  • Comparison with regular realpath methods to ensure identical behavior
  • Edge cases like deep symlink chains and root path resolution

All existing tests continue to pass (1075 tests total, 0 regressions).

Fixes #1116.


💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.

Co-authored-by: streamich <9773803+streamich@users.noreply.github.com>
Copilot AI changed the title [WIP] Implement realpath.native Implement realpath.native support for memfs Jul 26, 2025
Copilot AI requested a review from streamich July 26, 2025 23:48
@streamich streamich marked this pull request as ready for review July 27, 2025 08:42
Copy link
Copy Markdown
Owner

@streamich streamich left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implement only realpath.native and realpathSync.native, make them reuse functionality of realpath and realpathSync, where possible. Do not implement realPathNative and realpathNativeSync.

Refactor realpath to be a Volume member set in constructor, and attach .native to it:

class Volume {
  // ...
   constructor() {
     // ...
     this.realpath = function ralpath() {};
     this.realpath.native = () => {};
   }

When done, reformat codebase with yarn prettier.

Co-authored-by: streamich <9773803+streamich@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Jul 27, 2025

Implement only realpath.native and realpathSync.native, make them reuse functionality of realpath and realpathSync, where possible. Do not implement realPathNative and realpathNativeSync.
...

I've refactored the implementation as requested:

  • Removed realpathNative and realpathNativeSync methods from the Volume class
  • Refactored realpath and realpathSync to be constructor-assigned functions with .native properties
  • Updated TypeScript interfaces and API lists accordingly
  • Updated tests to use the new .native syntax
  • Ran prettier to reformat the codebase

The implementation now follows the pattern you specified where realpath.native and realpathSync.native are properties of the main functions, all set up in the constructor.

Commit: 4390275

Copilot AI requested a review from streamich July 27, 2025 09:29
Copy link
Copy Markdown
Owner

@streamich streamich left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make sure native variants are also created in createFsFromVolume().

Make sure tests pass yarn test.

Make sure to run yarn prettier.

Comment thread src/volume.ts Outdated
Comment on lines +364 to +382
const realpathImpl = (
path: PathLike,
a: TCallback<TDataOut> | opts.IRealpathOptions | string,
b?: TCallback<TDataOut>,
) => {
const [opts, callback] = getRealpathOptsAndCb(a, b);
const pathFilename = pathToFilename(path);
self.wrapAsync(self.realpathBase, [pathFilename, opts.encoding], callback);
};

const realpathNativeImpl = (
path: PathLike,
a: TCallback<TDataOut> | opts.IRealpathOptions | string,
b?: TCallback<TDataOut>,
) => {
const [opts, callback] = getRealpathOptsAndCb(a, b);
const pathFilename = pathToFilename(path);
self.wrapAsync(self.realpathBase, [pathFilename, opts.encoding], callback);
};
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these two functions the same? If so, reuse just one.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in commit cf7a19f. Consolidated the duplicate implementations - now using the same function for both regular and native variants since they are identical. Both realpathImpl and realpathSyncImpl are reused for their respective .native properties.

Comment thread src/volume.ts Outdated

this.root = root;

// Set up realpath as function properties with native variants
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this comment.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the comment in commit cf7a19f.

Comment thread src/volume.ts Outdated
WriteStream: new (...args) => IWriteStream;
FSWatcher: new () => FSWatcher;

// realpath function properties with native variants
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this comment.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the comment in commit cf7a19f.

Co-authored-by: streamich <9773803+streamich@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Jul 27, 2025

Make sure native variants are also created in createFsFromVolume().

Make sure tests pass yarn test.
...

Fixed in commit cf7a19f. Updated createFsFromVolume() to properly handle the .native properties for both realpath and realpathSync functions. The native variants are now correctly bound as properties of the main functions in the created filesystem interface.

Copilot AI requested a review from streamich July 27, 2025 10:09
Copy link
Copy Markdown
Owner

@streamich streamich left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@streamich streamich merged commit 89d7e54 into master Jul 27, 2025
12 checks passed
@streamich streamich deleted the copilot/fix-1116 branch July 27, 2025 10:15
@github-actions
Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 4.22.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement realpath.native

2 participants