Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions lib/internal/vfs/file_handle.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ const kMode = Symbol('kMode');
const kPosition = Symbol('kPosition');
const kClosed = Symbol('kClosed');

function isCurrentPosition(position) {
return position === null || position === undefined || position === -1;
}

/**
* Base class for virtual file handles.
* Provides the interface that file handles must implement.
Expand Down Expand Up @@ -467,8 +471,8 @@ class MemoryFileHandle extends VirtualFileHandle {

// Get content (resolves dynamic content providers)
const content = this.content;
const readPos = position !== null && position !== undefined ?
Number(position) : this.position;
const useCurrentPosition = isCurrentPosition(position);
const readPos = useCurrentPosition ? this.position : Number(position);
const available = content.length - readPos;

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

// Update position if not using explicit position
if (position === null || position === undefined) {
if (useCurrentPosition) {
this.position = readPos + bytesToRead;
}

Expand Down Expand Up @@ -512,10 +516,10 @@ class MemoryFileHandle extends VirtualFileHandle {
this.#checkWritable();

// In append mode, always write at the end
const useCurrentPosition = isCurrentPosition(position);
const writePos = this.#isAppend() ?
this.#size :
(position !== null && position !== undefined ?
Number(position) : this.position);
(useCurrentPosition ? this.position : Number(position));
const data = buffer.subarray(offset, offset + length);

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

// Update position if not using explicit position
if (position === null || position === undefined) {
if (useCurrentPosition) {
this.position = writePos + length;
}

Expand Down
20 changes: 20 additions & 0 deletions test/parallel/test-vfs-fd.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,26 @@ const vfs = require('node:vfs');
myVfs.closeSync(fd);
}

// Test readSync with Node's current-position sentinel
{
const myVfs = vfs.create();
myVfs.writeFileSync('/file.txt', 'hello world');

const fd = myVfs.openSync('/file.txt');
const buffer1 = Buffer.alloc(5);
const buffer2 = Buffer.alloc(6);

let bytesRead = myVfs.readSync(fd, buffer1, 0, 5, -1);
assert.strictEqual(bytesRead, 5);
assert.strictEqual(buffer1.toString(), 'hello');

bytesRead = myVfs.readSync(fd, buffer2, 0, 6, -1);
assert.strictEqual(bytesRead, 6);
assert.strictEqual(buffer2.toString(), ' world');

myVfs.closeSync(fd);
}

// Test readSync with explicit position
{
const myVfs = vfs.create();
Expand Down
6 changes: 6 additions & 0 deletions test/parallel/test-vfs-file-handle.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ myVfs.writeFileSync('/file.txt', 'hello world');
myVfs.writeSync(fd, buf, 0, 3, 0);
myVfs.closeSync(fd);

const fd3 = myVfs.openSync('/sync-current.txt', 'w');
myVfs.writeSync(fd3, Buffer.from('abc'), 0, 3, -1);
myVfs.writeSync(fd3, Buffer.from('def'), 0, 3, -1);
myVfs.closeSync(fd3);
assert.strictEqual(myVfs.readFileSync('/sync-current.txt', 'utf8'), 'abcdef');

const fd2 = myVfs.openSync('/sync.txt', 'r');
const out = Buffer.alloc(3);
myVfs.readSync(fd2, out, 0, 3, 0);
Expand Down
13 changes: 13 additions & 0 deletions test/parallel/test-vfs-fs-openSync.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,19 @@ myVfs.mount(mountPoint);
fs.closeSync(fd);
}

// readSync with position null uses and advances the current file position
{
const fd = fs.openSync(path.join(mountPoint, 'src/hello.txt'), 'r');
const b1 = Buffer.alloc(5);
const b2 = Buffer.alloc(6);

assert.strictEqual(fs.readSync(fd, b1, 0, 5, null), 5);
assert.strictEqual(fs.readSync(fd, b2, 0, 6, null), 6);
assert.strictEqual(b1.toString(), 'hello');
assert.strictEqual(b2.toString(), ' world');
fs.closeSync(fd);
}

// openSync + writeSync (buffer) + closeSync
{
const fd = fs.openSync(path.join(mountPoint, 'src/wfd.txt'), 'w');
Expand Down
Loading