Skip to content

vfs: write RealFSProvider files to open fd - #65885

Open
christianaurichzm wants to merge 1 commit into
nodejs:mainfrom
christianaurichzm:vfs-write-to-open-fd
Open

vfs: write RealFSProvider files to open fd#65885
christianaurichzm wants to merge 1 commit into
nodejs:mainfrom
christianaurichzm:vfs-write-to-open-fd

Conversation

@christianaurichzm

Copy link
Copy Markdown
Contributor

RealFileHandle.writeFile() and writeFileSync() reopen the original real path instead of writing through the handle's file descriptor. A write after the backing file is renamed can recreate the old path, and a read-only handle can write because the path is reopened with the default w flag.

// Flags: --experimental-vfs
const provider = new vfs.RealFSProvider(root);

const ro = await provider.open('/a.txt', 'r');
await ro.writeFile('CLOBBERED');

const rw = await provider.open('/b.txt', 'r+');
fs.renameSync(path.join(root, 'b.txt'), path.join(root, 'c.txt'));
await rw.writeFile('NEW');

On main:

a.txt: CLOBBERED
c.txt: bbb
b.txt: NEW

Write through the open fd instead, mirroring #64104 for reads. The async path keeps iterable input support and follows filehandle.writeFile() current-position semantics, which is what #65854 is applying to the memory and zip handles. flush remains one fsync per call.

Tests cover writes after rename, read-only handles, iterable input, option and abort handling, and flush. Two existing assertions encoded the replacing behaviour and are updated.

On linux-x64, make lint, all 115 test-vfs-* tests, and the configured parallel and sequential suites pass.

Refs: #64104
Refs: #64103
Refs: #65854

Write RealFileHandle contents through the open file descriptor instead
of reopening the original real path, mirroring 8cb8312 for reads.
This keeps writes attached to the opened file across renames and makes
them honor the handle's access mode.

Preserve iterable support and filehandle.writeFile() current-position
semantics.

Signed-off-by: Christian Aurich <christian.aurichzm@gmail.com>
@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 7, 2026
@codecov

codecov Bot commented Sep 7, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.87640% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 90.17%. Comparing base (b113d09) to head (7865323).
⚠️ Report is 26 commits behind head on main.

Files with missing lines Patch % Lines
lib/internal/vfs/providers/real.js 98.87% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main   #65885   +/-   ##
=======================================
  Coverage   90.16%   90.17%           
=======================================
  Files         771      771           
  Lines      265094   265172   +78     
  Branches    50355    50383   +28     
=======================================
+ Hits       239027   239111   +84     
+ Misses      17011    17006    -5     
+ Partials     9056     9055    -1     
Files with missing lines Coverage Δ
lib/internal/vfs/providers/real.js 95.53% <98.87%> (+0.43%) ⬆️

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

Comment on lines +38 to +47
function isCustomIterable(obj) {
return isIterable(obj) && !isArrayBufferView(obj) && typeof obj !== 'string';
}

function checkAborted(signal) {
if (signal?.aborted) {
throw new AbortError(undefined, { cause: signal.reason });
}
}

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.

nit: isCustomIterable() and checkAborted() already exist in lib/internal/fs/promises.js. Worth considering whether we can reuse them.

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.

Thanks. I looked into this. Both helpers are currently module-local in internal/fs/promises.js, so reusing them would require exporting them or moving them to a shared utility. checkAborted also already has a separate module-local implementation in lib/fs.js. I kept the small copies local to avoid broadening this fix, but I'm happy to extract them if you prefer.

@meixg meixg added the request-ci Add this label to start a Jenkins CI on a PR. Only starts once the PR has an approving review. label Sep 8, 2026
@github-actions github-actions Bot removed the request-ci Add this label to start a Jenkins CI on a PR. Only starts once the PR has an approving review. label Sep 8, 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