diff options
author | Nathan Whitaker <17734409+nathanwhit@users.noreply.github.com> | 2024-08-14 09:42:31 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-14 09:42:31 -0700 |
commit | 1f2d48cd975b719f0248e471f3b503cb01398dfb (patch) | |
tree | f9ac89ff011566aad45456e6d49e2802ce6f345b /ext | |
parent | c765d9ad2fbd82be1b025cae3930fdfe8e30f9e2 (diff) |
fix(node/fs): node:fs.read and write should accept typed arrays other than Uint8Array (#25030)
Part of #25028.
Our underlying read/write operations in `io` assume the buffer is a
Uint8Array, but we were passing in other typed arrays (in the case above
it was `Int8Array`).
Diffstat (limited to 'ext')
-rw-r--r-- | ext/node/polyfills/_fs/_fs_common.ts | 2 | ||||
-rw-r--r-- | ext/node/polyfills/_fs/_fs_read.ts | 26 | ||||
-rw-r--r-- | ext/node/polyfills/_fs/_fs_write.mjs | 9 | ||||
-rw-r--r-- | ext/node/polyfills/internal/fs/utils.mjs | 10 |
4 files changed, 31 insertions, 16 deletions
diff --git a/ext/node/polyfills/_fs/_fs_common.ts b/ext/node/polyfills/_fs/_fs_common.ts index 069f9a3a1..ac0bf5a55 100644 --- a/ext/node/polyfills/_fs/_fs_common.ts +++ b/ext/node/polyfills/_fs/_fs_common.ts @@ -38,7 +38,7 @@ export type BinaryOptionsArgument = export type FileOptionsArgument = Encodings | FileOptions; export type ReadOptions = { - buffer: Buffer | Uint8Array; + buffer: Buffer | ArrayBufferView; offset: number; length: number; position: number | null; diff --git a/ext/node/polyfills/_fs/_fs_read.ts b/ext/node/polyfills/_fs/_fs_read.ts index e25f41e76..7b3d9fccd 100644 --- a/ext/node/polyfills/_fs/_fs_read.ts +++ b/ext/node/polyfills/_fs/_fs_read.ts @@ -9,6 +9,7 @@ import * as io from "ext:deno_io/12_io.js"; import * as fs from "ext:deno_fs/30_fs.js"; import { ReadOptions } from "ext:deno_node/_fs/_fs_common.ts"; import { + arrayBufferViewToUint8Array, validateOffsetLengthRead, validatePosition, } from "ext:deno_node/internal/fs/utils.mjs"; @@ -16,6 +17,7 @@ import { validateBuffer, validateInteger, } from "ext:deno_node/internal/validators.mjs"; +import { isArrayBufferView } from "ext:deno_node/internal/util/types.ts"; type readSyncOptions = { offset: number; @@ -38,7 +40,7 @@ export function read( ): void; export function read( fd: number, - buffer: Buffer | Uint8Array, + buffer: ArrayBufferView, offset: number, length: number, position: number | null, @@ -46,7 +48,7 @@ export function read( ): void; export function read( fd: number, - optOrBufferOrCb?: Buffer | Uint8Array | ReadOptions | Callback, + optOrBufferOrCb?: ArrayBufferView | ReadOptions | Callback, offsetOrCallback?: number | Callback, length?: number, position?: number | null, @@ -75,9 +77,9 @@ export function read( } if ( - optOrBufferOrCb instanceof Buffer || optOrBufferOrCb instanceof Uint8Array + isArrayBufferView(optOrBufferOrCb) ) { - buffer = optOrBufferOrCb; + buffer = arrayBufferViewToUint8Array(optOrBufferOrCb); } else if (typeof optOrBufferOrCb === "function") { offset = 0; buffer = Buffer.alloc(16384); @@ -86,7 +88,7 @@ export function read( } else { const opt = optOrBufferOrCb as ReadOptions; if ( - !(opt.buffer instanceof Buffer) && !(opt.buffer instanceof Uint8Array) + !isArrayBufferView(opt.buffer) ) { throw new ERR_INVALID_ARG_TYPE("buffer", [ "Buffer", @@ -94,8 +96,12 @@ export function read( "DataView", ], optOrBufferOrCb); } + if (opt.buffer === undefined) { + buffer = Buffer.alloc(16384); + } else { + buffer = arrayBufferViewToUint8Array(opt.buffer); + } offset = opt.offset ?? 0; - buffer = opt.buffer ?? Buffer.alloc(16384); length = opt.length ?? buffer.byteLength; position = opt.position ?? null; } @@ -131,19 +137,19 @@ export function read( export function readSync( fd: number, - buffer: Buffer | Uint8Array, + buffer: ArrayBufferView, offset: number, length: number, position: number | null, ): number; export function readSync( fd: number, - buffer: Buffer | Uint8Array, + buffer: ArrayBufferView, opt: readSyncOptions, ): number; export function readSync( fd: number, - buffer: Buffer | Uint8Array, + buffer: ArrayBufferView, offsetOrOpt?: number | readSyncOptions, length?: number, position?: number | null, @@ -156,6 +162,8 @@ export function readSync( validateBuffer(buffer); + buffer = arrayBufferViewToUint8Array(buffer); + if (length == null) { length = 0; } diff --git a/ext/node/polyfills/_fs/_fs_write.mjs b/ext/node/polyfills/_fs/_fs_write.mjs index c0ae129d3..b4b133222 100644 --- a/ext/node/polyfills/_fs/_fs_write.mjs +++ b/ext/node/polyfills/_fs/_fs_write.mjs @@ -12,6 +12,7 @@ import { import * as io from "ext:deno_io/12_io.js"; import * as fs from "ext:deno_fs/30_fs.js"; import { + arrayBufferViewToUint8Array, getValidatedFd, validateOffsetLengthWrite, validateStringAfterArrayBufferView, @@ -23,9 +24,7 @@ export function writeSync(fd, buffer, offset, length, position) { fd = getValidatedFd(fd); const innerWriteSync = (fd, buffer, offset, length, position) => { - if (buffer instanceof DataView) { - buffer = new Uint8Array(buffer.buffer); - } + buffer = arrayBufferViewToUint8Array(buffer); if (typeof position === "number") { fs.seekSync(fd, position, io.SeekMode.Start); } @@ -69,9 +68,7 @@ export function write(fd, buffer, offset, length, position, callback) { fd = getValidatedFd(fd); const innerWrite = async (fd, buffer, offset, length, position) => { - if (buffer instanceof DataView) { - buffer = new Uint8Array(buffer.buffer); - } + buffer = arrayBufferViewToUint8Array(buffer); if (typeof position === "number") { await fs.seek(fd, position, io.SeekMode.Start); } diff --git a/ext/node/polyfills/internal/fs/utils.mjs b/ext/node/polyfills/internal/fs/utils.mjs index 9f3322bae..53184b9c3 100644 --- a/ext/node/polyfills/internal/fs/utils.mjs +++ b/ext/node/polyfills/internal/fs/utils.mjs @@ -986,6 +986,16 @@ export const validatePosition = hideStackFrames((position) => { } }); +/** @type {(buffer: ArrayBufferView) => Uint8Array} */ +export const arrayBufferViewToUint8Array = hideStackFrames( + (buffer) => { + if (!(buffer instanceof Uint8Array)) { + return new Uint8Array(buffer.buffer); + } + return buffer; + }, +); + export const realpathCacheKey = Symbol("realpathCacheKey"); export const constants = { kIoMaxLength, |