Skip to content

Commit a104bce

Browse files
committed
vfs: handle current-position sentinel in memory files
Treat -1 as the current file position in MemoryFileHandle read and write operations. This matches the value passed by fs.readSync() after normalizing a null position. Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com> Assisted-by: openai:gpt-5.5
1 parent 8cb8312 commit a104bce

4 files changed

Lines changed: 49 additions & 6 deletions

File tree

lib/internal/vfs/file_handle.js

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ const kMode = Symbol('kMode');
2828
const kPosition = Symbol('kPosition');
2929
const kClosed = Symbol('kClosed');
3030

31+
function isCurrentPosition(position) {
32+
return position === null || position === undefined || position === -1;
33+
}
34+
3135
/**
3236
* Base class for virtual file handles.
3337
* Provides the interface that file handles must implement.
@@ -467,8 +471,8 @@ class MemoryFileHandle extends VirtualFileHandle {
467471

468472
// Get content (resolves dynamic content providers)
469473
const content = this.content;
470-
const readPos = position !== null && position !== undefined ?
471-
Number(position) : this.position;
474+
const useCurrentPosition = isCurrentPosition(position);
475+
const readPos = useCurrentPosition ? this.position : Number(position);
472476
const available = content.length - readPos;
473477

474478
if (available <= 0) {
@@ -479,7 +483,7 @@ class MemoryFileHandle extends VirtualFileHandle {
479483
content.copy(buffer, offset, readPos, readPos + bytesToRead);
480484

481485
// Update position if not using explicit position
482-
if (position === null || position === undefined) {
486+
if (useCurrentPosition) {
483487
this.position = readPos + bytesToRead;
484488
}
485489

@@ -512,10 +516,10 @@ class MemoryFileHandle extends VirtualFileHandle {
512516
this.#checkWritable();
513517

514518
// In append mode, always write at the end
519+
const useCurrentPosition = isCurrentPosition(position);
515520
const writePos = this.#isAppend() ?
516521
this.#size :
517-
(position !== null && position !== undefined ?
518-
Number(position) : this.position);
522+
(useCurrentPosition ? this.position : Number(position));
519523
const data = buffer.subarray(offset, offset + length);
520524

521525
// Expand buffer if needed (geometric doubling for amortized O(1) appends)
@@ -544,7 +548,7 @@ class MemoryFileHandle extends VirtualFileHandle {
544548
}
545549

546550
// Update position if not using explicit position
547-
if (position === null || position === undefined) {
551+
if (useCurrentPosition) {
548552
this.position = writePos + length;
549553
}
550554

test/parallel/test-vfs-fd.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,26 @@ const vfs = require('node:vfs');
8080
myVfs.closeSync(fd);
8181
}
8282

83+
// Test readSync with Node's current-position sentinel
84+
{
85+
const myVfs = vfs.create();
86+
myVfs.writeFileSync('/file.txt', 'hello world');
87+
88+
const fd = myVfs.openSync('/file.txt');
89+
const buffer1 = Buffer.alloc(5);
90+
const buffer2 = Buffer.alloc(6);
91+
92+
let bytesRead = myVfs.readSync(fd, buffer1, 0, 5, -1);
93+
assert.strictEqual(bytesRead, 5);
94+
assert.strictEqual(buffer1.toString(), 'hello');
95+
96+
bytesRead = myVfs.readSync(fd, buffer2, 0, 6, -1);
97+
assert.strictEqual(bytesRead, 6);
98+
assert.strictEqual(buffer2.toString(), ' world');
99+
100+
myVfs.closeSync(fd);
101+
}
102+
83103
// Test readSync with explicit position
84104
{
85105
const myVfs = vfs.create();

test/parallel/test-vfs-file-handle.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@ myVfs.writeFileSync('/file.txt', 'hello world');
8282
myVfs.writeSync(fd, buf, 0, 3, 0);
8383
myVfs.closeSync(fd);
8484

85+
const fd3 = myVfs.openSync('/sync-current.txt', 'w');
86+
myVfs.writeSync(fd3, Buffer.from('abc'), 0, 3, -1);
87+
myVfs.writeSync(fd3, Buffer.from('def'), 0, 3, -1);
88+
myVfs.closeSync(fd3);
89+
assert.strictEqual(myVfs.readFileSync('/sync-current.txt', 'utf8'), 'abcdef');
90+
8591
const fd2 = myVfs.openSync('/sync.txt', 'r');
8692
const out = Buffer.alloc(3);
8793
myVfs.readSync(fd2, out, 0, 3, 0);

test/parallel/test-vfs-fs-openSync.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,19 @@ myVfs.mount(mountPoint);
3030
fs.closeSync(fd);
3131
}
3232

33+
// readSync with position null uses and advances the current file position
34+
{
35+
const fd = fs.openSync(path.join(mountPoint, 'src/hello.txt'), 'r');
36+
const b1 = Buffer.alloc(5);
37+
const b2 = Buffer.alloc(6);
38+
39+
assert.strictEqual(fs.readSync(fd, b1, 0, 5, null), 5);
40+
assert.strictEqual(fs.readSync(fd, b2, 0, 6, null), 6);
41+
assert.strictEqual(b1.toString(), 'hello');
42+
assert.strictEqual(b2.toString(), ' world');
43+
fs.closeSync(fd);
44+
}
45+
3346
// openSync + writeSync (buffer) + closeSync
3447
{
3548
const fd = fs.openSync(path.join(mountPoint, 'src/wfd.txt'), 'w');

0 commit comments

Comments
 (0)