summaryrefslogtreecommitdiff
path: root/ext/node/polyfills
diff options
context:
space:
mode:
authorNathan Whitaker <17734409+nathanwhit@users.noreply.github.com>2024-08-14 09:42:31 -0700
committerGitHub <noreply@github.com>2024-08-14 09:42:31 -0700
commit1f2d48cd975b719f0248e471f3b503cb01398dfb (patch)
treef9ac89ff011566aad45456e6d49e2802ce6f345b /ext/node/polyfills
parentc765d9ad2fbd82be1b025cae3930fdfe8e30f9e2 (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/node/polyfills')
-rw-r--r--ext/node/polyfills/_fs/_fs_common.ts2
-rw-r--r--ext/node/polyfills/_fs/_fs_read.ts26
-rw-r--r--ext/node/polyfills/_fs/_fs_write.mjs9
-rw-r--r--ext/node/polyfills/internal/fs/utils.mjs10
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,