Skip to content

Commit

Permalink
fs: allow writing files with ArrayBuffers
Browse files Browse the repository at this point in the history
Extended most file writing functions to accept ArrayBuffers rather
than only strings, buffers, or data views. Does not include
functions that accept arrays of dataviews, such as writev.

Fixes: #42228
  • Loading branch information
SRHerzog committed Feb 3, 2023
1 parent 3000d77 commit 74ff0bd
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 5 deletions.
15 changes: 13 additions & 2 deletions lib/fs.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const {
StringPrototypeCharCodeAt,
StringPrototypeIndexOf,
StringPrototypeSlice,
Uint8Array,
} = primordials;

const { fs: constants } = internalBinding('constants');
Expand All @@ -56,7 +57,7 @@ const {
} = constants;

const pathModule = require('path');
const { isArrayBufferView } = require('internal/util/types');
const { isArrayBufferView, isArrayBuffer } = require('internal/util/types');

// We need to get the statValues from the binding at the callsite since
// it's re-initialized after deserialization.
Expand Down Expand Up @@ -819,6 +820,9 @@ function write(fd, buffer, offsetOrOptions, length, position, callback) {
fd = getValidatedFd(fd);

let offset = offsetOrOptions;
if (isArrayBuffer(buffer)) {
buffer = new Uint8Array(buffer);
}
if (isArrayBufferView(buffer)) {
callback = maybeCallback(callback || position || length || offset);

Expand Down Expand Up @@ -888,6 +892,9 @@ function writeSync(fd, buffer, offsetOrOptions, length, position) {
let result;

let offset = offsetOrOptions;
if (isArrayBuffer(buffer)) {
buffer = new Uint8Array(buffer);
}
if (isArrayBufferView(buffer)) {
if (typeof offset === 'object') {
({
Expand Down Expand Up @@ -2178,6 +2185,10 @@ function writeFile(path, data, options, callback) {
options = getOptions(options, { encoding: 'utf8', mode: 0o666, flag: 'w' });
const flag = options.flag || 'w';

if (isArrayBuffer(data)) {
data = new Uint8Array(data);
}

if (!isArrayBufferView(data)) {
validateStringAfterArrayBufferView(data, 'data');
data = Buffer.from(data, options.encoding || 'utf8');
Expand Down Expand Up @@ -2218,7 +2229,7 @@ function writeFile(path, data, options, callback) {
function writeFileSync(path, data, options) {
options = getOptions(options, { encoding: 'utf8', mode: 0o666, flag: 'w' });

if (!isArrayBufferView(data)) {
if (!isArrayBufferView(data) && !isArrayBuffer(data)) {
validateStringAfterArrayBufferView(data, 'data');
data = Buffer.from(data, options.encoding || 'utf8');
}
Expand Down
13 changes: 10 additions & 3 deletions lib/internal/fs/promises.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const {
AbortError,
aggregateTwoErrors,
} = require('internal/errors');
const { isArrayBufferView } = require('internal/util/types');
const { isArrayBuffer, isArrayBufferView } = require('internal/util/types');
const { rimrafPromises } = require('internal/fs/rimraf');
const {
constants: {
Expand Down Expand Up @@ -409,7 +409,11 @@ async function writeFileHandle(filehandle, data, signal, encoding) {
}
return;
}
data = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
if (isArrayBuffer(data)) {
data = new Uint8Array(data);
} else {
data = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
}
let remaining = data.byteLength;
if (remaining === 0) return;
do {
Expand Down Expand Up @@ -610,6 +614,9 @@ async function readv(handle, buffers, position) {
}

async function write(handle, buffer, offsetOrOptions, length, position) {
if (isArrayBuffer(buffer)) {
buffer = new Uint8Array(buffer);
}
if (buffer?.byteLength === 0)
return { __proto__: null, bytesWritten: 0, buffer };

Expand Down Expand Up @@ -884,7 +891,7 @@ async function writeFile(path, data, options) {
options = getOptions(options, { encoding: 'utf8', mode: 0o666, flag: 'w' });
const flag = options.flag || 'w';

if (!isArrayBufferView(data) && !isCustomIterable(data)) {
if (!isArrayBufferView(data) && !isArrayBuffer(data) && !isCustomIterable(data)) {
validateStringAfterArrayBufferView(data, 'data');
data = Buffer.from(data, options.encoding || 'utf8');
}
Expand Down

0 comments on commit 74ff0bd

Please sign in to comment.