Version
main
Platform
Subsystem
vfs
What steps will reproduce the bug?
import { create } from 'node:vfs';
const { provider: p } = create();
p.writeFileSync('/f', 'AAAA');
const h = p.openSync('/f', 'r');
p.writeFileSync('/f', '0123456789');
const b = Buffer.alloc(10);
console.log('readSync:', h.readSync(b, 0, 10, 0), JSON.stringify(b.subarray(0, 4).toString()));
console.log('readFileSync:', JSON.stringify(h.readFileSync('utf8')));
console.log('fstat:', h.statSync().size, 'stat:', p.statSync('/f').size);
h.readFile('utf8').then((s) => console.log('readFile:', JSON.stringify(s)));
How often does it reproduce? Is there a required condition?
Always
What is the expected behavior? Why is that the expected behavior?
The already-open descriptor should observe the file's current content and size. On a real filesystem an open descriptor is a live view of the inode, not a snapshot.
What do you see instead?
readSync: 4 "AAAA"
readFileSync: "AAAA"
fstat: 4 stat: 10
readFile: "0123456789"
The pre-existing handle keeps serving the bytes that were in the file when it was opened: readSync/read/readFileSync are stale, fstat reports the pre-mutation size, and the async readFile disagrees with the sync readFileSync on the very same handle.
Additional information
fs equivalent
import { writeFileSync, openSync, readSync, readFileSync, fstatSync, statSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
const file = join(tmpdir(), 'vfs-native-repro.txt');
writeFileSync(file, 'AAAA');
const fd = openSync(file, 'r');
writeFileSync(file, '0123456789');
const b = Buffer.alloc(10);
console.log('readSync:', readSync(fd, b, 0, 10, 0), JSON.stringify(b.subarray(0, 4).toString()));
console.log('readFileSync:', readFileSync(fd, 'utf8'));
console.log('fstatSync:', fstatSync(fd).size, 'stat:', statSync(file).size);
Output
readSync: 10 "0123"
readFileSync: 0123456789
fstatSync: 10 stat: 10
Version
main
Platform
Subsystem
vfs
What steps will reproduce the bug?
How often does it reproduce? Is there a required condition?
Always
What is the expected behavior? Why is that the expected behavior?
The already-open descriptor should observe the file's current content and size. On a real filesystem an open descriptor is a live view of the inode, not a snapshot.
What do you see instead?
The pre-existing handle keeps serving the bytes that were in the file when it was opened:
readSync/read/readFileSyncare stale,fstatreports the pre-mutation size, and the asyncreadFiledisagrees with the syncreadFileSyncon the very same handle.Additional information
fs equivalent
Output