Skip to content

vfs: answer for unowned paths under reserved root - #65814

Open
pipobscure wants to merge 1 commit into
nodejs:mainfrom
pipobscure:vfs-reserved-root-lookup
Open

vfs: answer for unowned paths under reserved root#65814
pipobscure wants to merge 1 commit into
nodejs:mainfrom
pipobscure:vfs-reserved-root-lookup

Conversation

@pipobscure

@pipobscure pipobscure commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

The module loader manufactures paths under the reserved VFS root that no layer owns: resolving a mount point as a directory first probes the sibling names <mount>.js, <mount>.json and <mount>.node, and a package.json walk-up passes the parents of the mount point. The lookup declined those because their layer segment is not a plain id, so they fell through to the native loader and the real file system.

On POSIX that is harmless (ENOTDIR under /dev/null), but on Windows the root sits under \\.\nul, and \\.\nul\<anything> opens the NUL device: libuv reports it as a character device and a read returns nothing. The loader therefore picked \\.\nul\vfs\<id>.js as an existing file, and the native walk-up above it then read the device as an empty package.json and failed with ERR_INVALID_PACKAGE_CONFIG for \\.\nul\package.json. Any require() of a mount point hits this on Windows.

Distinguish "under the root but unowned" from "outside the root" in the lookup and have every loader override report the former as not found: stat gives ENOENT, reads and realpath throw ENOENT, the package.json lookups return their "no package.json" results, and upward walks stop at the reserved root. Paths outside the root still go to the native loader as before.

NOTE: This was only validated agains a pretty bad Windows VM on my end. So if someone that has access to a better Windows environment could double check this work, I'd appreciate it.

@nodejs-github-bot nodejs-github-bot added needs-ci PRs that need a full CI run. vfs Issues and PRs related to the virtual filesystem subsystem. labels Sep 5, 2026
The module loader manufactures paths under the reserved VFS root that
no layer owns: resolving a mount point as a directory first probes the
sibling names `<mount>.js`, `<mount>.json` and `<mount>.node`, and a
package.json walk-up passes the parents of the mount point. The lookup
declined those because their layer segment is not a plain id, so they
fell through to the native loader and the real file system.

On POSIX that is harmless (ENOTDIR under /dev/null), but on Windows
the root sits under `\\.\nul`, and `\\.\nul\<anything>` opens the NUL
device: libuv reports it as a character device and a read returns
nothing. The loader therefore picked `\\.\nul\vfs\<id>.js` as an
existing file, and the native walk-up above it then read the device as
an empty package.json and failed with ERR_INVALID_PACKAGE_CONFIG for
`\\.\nul\package.json`. Any require() of a mount point hits this on
Windows.

Distinguish "under the root but unowned" from "outside the root" in the
lookup and have every loader override report the former as not found:
stat gives ENOENT, reads and realpath throw ENOENT, the package.json
lookups return their "no package.json" results, and upward walks stop
at the reserved root. Paths outside the root still go to the native
loader as before.

Refs: nodejs#65748
Signed-off-by: Philipp Dunkel <[email protected]>
@pipobscure pipobscure changed the title vfs: answer for unowned paths under the reserved root vfs: answer for unowned paths under reserved root Sep 5, 2026
@pipobscure
pipobscure force-pushed the vfs-reserved-root-lookup branch from e1c6827 to fc612c8 Compare September 5, 2026 14:43

@mcollina mcollina left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

lgtm

@mcollina mcollina added the request-ci Add this label to start a Jenkins CI on a PR. label Sep 5, 2026
@mcollina

mcollina commented Sep 5, 2026

Copy link
Copy Markdown
Member

let’s see what CI thinks

@codecov

codecov Bot commented Sep 5, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.59459% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.18%. Comparing base (2d22505) to head (fc612c8).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
lib/internal/vfs/setup.js 94.59% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #65814      +/-   ##
==========================================
- Coverage   90.19%   90.18%   -0.01%     
==========================================
  Files         770      770              
  Lines      264410   264448      +38     
  Branches    50243    50248       +5     
==========================================
+ Hits       238479   238491      +12     
- Misses      16926    16974      +48     
+ Partials     9005     8983      -22     
Files with missing lines Coverage Δ
lib/internal/vfs/setup.js 87.79% <94.59%> (+0.27%) ⬆️

... and 37 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.

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

Copy link
Copy Markdown
Collaborator

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

Labels

needs-ci PRs that need a full CI run. vfs Issues and PRs related to the virtual filesystem subsystem.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants