Skip to content

vfs: add minimal node:vfs subsystem#63115

Merged
nodejs-github-bot merged 32 commits into
nodejs:mainfrom
mcollina:vfs-minimal
May 23, 2026
Merged

vfs: add minimal node:vfs subsystem#63115
nodejs-github-bot merged 32 commits into
nodejs:mainfrom
mcollina:vfs-minimal

Conversation

@mcollina

@mcollina mcollina commented May 4, 2026

Copy link
Copy Markdown
Member

Adds an experimental node:vfs builtin (gated behind --experimental-vfs) with VirtualFileSystem, VirtualProvider, MemoryProvider, and RealFSProvider. No integration with node:fs, the module loader, or SEA those are intended to land in follow-up PRs.

Extracted from: #61478

Approximate line counts: code ~4k / docs ~1k / tests ~5k — total ~10k lines, with tests being the largest share.

@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/config
  • @nodejs/loaders
  • @nodejs/startup

@nodejs-github-bot nodejs-github-bot added lib / src Issues and PRs related to general changes in the lib or src directory. needs-ci PRs that need a full CI run. labels May 4, 2026
@bakkot

bakkot commented May 4, 2026

Copy link
Copy Markdown
Contributor

No integration with node:fs

The docs in this PR claim that you can call myVfs.mount('/virtual') and subsequently regular node:fs operations which read from paths beginning with /virtual will read from the VFS. That sounds like integration to me. Are the docs wrong, or am I misunderstanding what "no integration" means?

@mcollina mcollina force-pushed the vfs-minimal branch 2 times, most recently from 30f5755 to 779fc37 Compare May 5, 2026 09:30
@mcollina mcollina marked this pull request as ready for review May 5, 2026 10:04
@mcollina

mcollina commented May 5, 2026

Copy link
Copy Markdown
Member Author

No integration with node:fs

The docs in this PR claim that you can call myVfs.mount('/virtual') and subsequently regular node:fs operations which read from paths beginning with /virtual will read from the VFS. That sounds like integration to me. Are the docs wrong, or am I misunderstanding what "no integration" means?

Fixed, good spot.

@codecov

codecov Bot commented May 5, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.69149% with 191 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.31%. Comparing base (8d3245e) to head (1088e5f).
⚠️ Report is 5 commits behind head on main.

Files with missing lines Patch % Lines
lib/internal/vfs/providers/memory.js 93.64% 61 Missing and 4 partials ⚠️
lib/internal/vfs/file_system.js 96.68% 38 Missing ⚠️
lib/internal/vfs/watcher.js 95.20% 32 Missing and 1 partial ⚠️
lib/internal/vfs/providers/real.js 96.01% 19 Missing ⚠️
lib/internal/vfs/streams.js 95.46% 16 Missing ⚠️
lib/internal/vfs/provider.js 98.38% 10 Missing ⚠️
lib/internal/vfs/file_handle.js 98.88% 7 Missing and 1 partial ⚠️
lib/internal/vfs/fd.js 97.70% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #63115      +/-   ##
==========================================
+ Coverage   90.14%   90.31%   +0.16%     
==========================================
  Files         718      730      +12     
  Lines      227984   233756    +5772     
  Branches    42835    43803     +968     
==========================================
+ Hits       205522   211121    +5599     
- Misses      14235    14400     +165     
- Partials     8227     8235       +8     
Files with missing lines Coverage Δ
lib/internal/bootstrap/realm.js 96.29% <100.00%> (+0.06%) ⬆️
lib/internal/modules/cjs/loader.js 98.05% <100.00%> (+<0.01%) ⬆️
lib/internal/process/pre_execution.js 97.93% <100.00%> (+0.14%) ⬆️
lib/internal/vfs/dir.js 100.00% <100.00%> (ø)
lib/internal/vfs/errors.js 100.00% <100.00%> (ø)
lib/internal/vfs/stats.js 100.00% <100.00%> (ø)
lib/vfs.js 100.00% <100.00%> (ø)
src/node_builtins.cc 76.37% <100.00%> (+0.23%) ⬆️
src/node_options.cc 76.67% <100.00%> (+0.02%) ⬆️
src/node_options.h 98.00% <100.00%> (+<0.01%) ⬆️
... and 8 more

... and 36 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@mcollina mcollina added help wanted Issues that need assistance from volunteers or PRs that need help to proceed. request-ci Add this label to start a Jenkins CI on a PR. labels May 6, 2026
@github-actions github-actions Bot removed the request-ci Add this label to start a Jenkins CI on a PR. label May 6, 2026
@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

@mcollina mcollina added the request-ci Add this label to start a Jenkins CI on a PR. label May 7, 2026
@github-actions github-actions Bot removed the request-ci Add this label to start a Jenkins CI on a PR. label May 7, 2026
@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

Comment thread doc/api/vfs.md Outdated
Comment thread doc/api/vfs.md Outdated
Comment thread lib/internal/bootstrap/realm.js Outdated
@aduh95

aduh95 commented May 7, 2026

Copy link
Copy Markdown
Contributor

Can you add a test for #63158?

@mcollina mcollina added the request-ci Add this label to start a Jenkins CI on a PR. label May 11, 2026
@github-actions github-actions Bot removed the request-ci Add this label to start a Jenkins CI on a PR. label May 11, 2026
mcollina and others added 6 commits May 23, 2026 15:11
Co-authored-by: Antoine du Hamel <duhamelantoine1995@gmail.com>
Co-authored-by: Matteo Collina <matteo.collina@gmail.com>
* test-vfs-stream-errors: drop the unused `assert` import.
* test-vfs-streams: capitalize a lowercase comment to satisfy
  capitalized-comments.

Signed-off-by: Matteo Collina <hello@matteocollina.com>
Co-authored-by: Antoine du Hamel <duhamelantoine1995@gmail.com>
spawnSyncAndAssert handles the expected stderr/status, so the
top-level `assert` is no longer referenced.

Signed-off-by: Matteo Collina <hello@matteocollina.com>
Signed-off-by: Matteo Collina <hello@matteocollina.com>
The currentPath segment used for symlink resolution and for the
#ensurePopulated call below was being computed twice in the loop
body. Compute it once at the top of the iteration and reuse it in
both branches.

Signed-off-by: Matteo Collina <hello@matteocollina.com>
@mcollina mcollina added the request-ci Add this label to start a Jenkins CI on a PR. label May 23, 2026
@github-actions github-actions Bot removed the request-ci Add this label to start a Jenkins CI on a PR. label May 23, 2026
@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

@mcollina mcollina added commit-queue Add this label to land a pull request using GitHub Actions. commit-queue-squash Add this label to instruct the Commit Queue to squash all the PR commits into the first one. labels May 23, 2026
@nodejs-github-bot nodejs-github-bot removed the commit-queue Add this label to land a pull request using GitHub Actions. label May 23, 2026
@nodejs-github-bot nodejs-github-bot merged commit c9562dd into nodejs:main May 23, 2026
77 checks passed
@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

Landed in c9562dd

mcollina added a commit to mcollina/node that referenced this pull request May 25, 2026
Add mount/unmount lifecycle on `VirtualFileSystem`, a handler registry
that fs.js and fs/promises.js consult via `vfsState.handlers`, and a
router that maps absolute paths to the VFS that owns them. When a VFS
is mounted, the public `fs.*` and `fs/promises` APIs (including
streams, `fs.watch`, and `opendir`) dispatch to the provider for paths
under the mount point, and fall through to the real filesystem
otherwise. Includes per-method dispatch tests, error-path coverage,
multi-mount routing tests, and router unit tests.

Ref: nodejs#63115

Signed-off-by: Matteo Collina <hello@matteocollina.com>
araujogui pushed a commit to araujogui/node that referenced this pull request May 26, 2026
Adds the node:vfs builtin module with VirtualFileSystem and
provider classes. No integration with fs, modules, or SEA.

Assisted-by: Claude-Opus4.7
Signed-off-by: Matteo Collina <hello@matteocollina.com>
PR-URL: nodejs#63115
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
Reviewed-By: Robert Nagy <ronagy@icloud.com>
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
mcollina added a commit to mcollina/node that referenced this pull request May 29, 2026
Add mount/unmount lifecycle on `VirtualFileSystem`, a handler registry
that fs.js and fs/promises.js consult via `vfsState.handlers`, and a
router that maps absolute paths to the VFS that owns them. When a VFS
is mounted, the public `fs.*` and `fs/promises` APIs (including
streams, `fs.watch`, and `opendir`) dispatch to the provider for paths
under the mount point, and fall through to the real filesystem
otherwise. Includes per-method dispatch tests, error-path coverage,
multi-mount routing tests, and router unit tests.

Ref: nodejs#63115

Signed-off-by: Matteo Collina <hello@matteocollina.com>
mcollina added a commit to mcollina/node that referenced this pull request May 29, 2026
Add mount/unmount lifecycle on `VirtualFileSystem`, a handler registry
that fs.js and fs/promises.js consult via `vfsState.handlers`, and a
router that maps absolute paths to the VFS that owns them. When a VFS
is mounted, the public `fs.*` and `fs/promises` APIs (including
streams, `fs.watch`, and `opendir`) dispatch to the provider for paths
under the mount point, and fall through to the real filesystem
otherwise. Includes per-method dispatch tests, error-path coverage,
multi-mount routing tests, and router unit tests.

Ref: nodejs#63115

Signed-off-by: Matteo Collina <hello@matteocollina.com>
nodejs-github-bot pushed a commit that referenced this pull request May 29, 2026
Add mount/unmount lifecycle on `VirtualFileSystem`, a handler registry
that fs.js and fs/promises.js consult via `vfsState.handlers`, and a
router that maps absolute paths to the VFS that owns them. When a VFS
is mounted, the public `fs.*` and `fs/promises` APIs (including
streams, `fs.watch`, and `opendir`) dispatch to the provider for paths
under the mount point, and fall through to the real filesystem
otherwise. Includes per-method dispatch tests, error-path coverage,
multi-mount routing tests, and router unit tests.

Ref: #63115

Signed-off-by: Matteo Collina <hello@matteocollina.com>
PR-URL: #63537
Refs: #63115
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
littledivy pushed a commit to denoland/deno that referenced this pull request Jun 2, 2026
The original draft was ported from @platformatic/vfs (extracted from the
still-open nodejs/node#61478). Node has since merged the experimental
subsystem in nodejs/node#63115, with a slightly different public surface.
Rebase the polyfill on the merged source so the API matches what landed
in Node behind --experimental-vfs:

- Stats objects are now real fs.Stats / BigIntStats instances (no more
  custom VirtualStats shape).
- Adds RealFSProvider, VirtualDir, plus the polling watcher classes
  (VFSWatcher / VFSStatWatcher / VFSWatchAsyncIterable).
- Adds rmSync/rm, truncateSync, linkSync, chmodSync, chownSync,
  utimesSync, lutimesSync, mkdtempSync, opendirSync, openAsBlob, the
  matching callback wrappers, and the matching promises API.
- Drops the Deno-specific extensions from the previous draft
  (mount/unmount/mounted/shouldHandle, virtualCwd/chdir, vfs-mount and
  vfs-unmount process events, internalModuleStat); they have no
  counterpart in the merged Node API and the module-loader integration
  is intentionally left for a follow-up upstream.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
aduh95 pushed a commit that referenced this pull request Jun 20, 2026
Adds the node:vfs builtin module with VirtualFileSystem and
provider classes. No integration with fs, modules, or SEA.

Assisted-by: Claude-Opus4.7
Signed-off-by: Matteo Collina <hello@matteocollina.com>
PR-URL: #63115
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
Reviewed-By: Robert Nagy <ronagy@icloud.com>
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
aduh95 pushed a commit that referenced this pull request Jun 20, 2026
Add mount/unmount lifecycle on `VirtualFileSystem`, a handler registry
that fs.js and fs/promises.js consult via `vfsState.handlers`, and a
router that maps absolute paths to the VFS that owns them. When a VFS
is mounted, the public `fs.*` and `fs/promises` APIs (including
streams, `fs.watch`, and `opendir`) dispatch to the provider for paths
under the mount point, and fall through to the real filesystem
otherwise. Includes per-method dispatch tests, error-path coverage,
multi-mount routing tests, and router unit tests.

Ref: #63115

Signed-off-by: Matteo Collina <hello@matteocollina.com>
PR-URL: #63537
Refs: #63115
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
nodejs-github-bot added a commit that referenced this pull request Jun 22, 2026
Notable changes:

build, doc:
  * generate node.1 with doc-kit (Aviv Keller) #62044
deps:
  * (SEMVER-MINOR) update OpenSSL build config to support compression (Tim Perry) #62217
doc:
  * (SEMVER-MINOR) update `blockList` stability status to release candidate (alphaleadership) #63050
fs:
  * (SEMVER-MINOR) support caller-supplied readFile() buffers (Matteo Collina) #63634
http:
  * (SEMVER-MINOR) close pre-request sockets in closeIdleConnections (semimikoh) #63470
loader:
  * (SEMVER-MINOR) implement package maps (Maël Nison) #62239
net:
  * (SEMVER-MINOR) support TCP_KEEPINTVL and TCP_KEEPCNT in setKeepAlive (Guy Bedford) #63825
tls:
  * (SEMVER-MINOR) add certificateCompression option (Tim Perry) #62217
vfs:
  * (SEMVER-MINOR) dispatch fs/promises to mounted VFS instances (Matteo Collina) #63537
  * (SEMVER-MINOR) add minimal node:vfs subsystem (Matteo Collina) #63115

PR-URL: #64058
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

commit-queue-squash Add this label to instruct the Commit Queue to squash all the PR commits into the first one. lib / src Issues and PRs related to general changes in the lib or src directory. semver-minor PRs that contain new features and should be released in the next minor version.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants