diff --git a/lib/internal/vfs/file_handle.js b/lib/internal/vfs/file_handle.js index e8a37e07f26495..7b60c9def2b5b4 100644 --- a/lib/internal/vfs/file_handle.js +++ b/lib/internal/vfs/file_handle.js @@ -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. @@ -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) { @@ -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; } @@ -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) @@ -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; } diff --git a/test/parallel/test-vfs-fd.js b/test/parallel/test-vfs-fd.js index ec9145189da299..f9f6b25f51ce57 100644 --- a/test/parallel/test-vfs-fd.js +++ b/test/parallel/test-vfs-fd.js @@ -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(); diff --git a/test/parallel/test-vfs-file-handle.js b/test/parallel/test-vfs-file-handle.js index 6c653593ce7ea2..d9d919446b8ea6 100644 --- a/test/parallel/test-vfs-file-handle.js +++ b/test/parallel/test-vfs-file-handle.js @@ -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); diff --git a/test/parallel/test-vfs-fs-openSync.js b/test/parallel/test-vfs-fs-openSync.js index f2c73f0d634469..28fa17d28b3cf6 100644 --- a/test/parallel/test-vfs-fs-openSync.js +++ b/test/parallel/test-vfs-fs-openSync.js @@ -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');