Skip to content

Commit ee1d13c

Browse files
committed
fs: use byteLength to handle ArrayBuffer views
Unlike TypedArray, DataView doesn't have a length property. PR-URL: #38187 Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Darshan Sen <[email protected]>
1 parent 4cf4ee9 commit ee1d13c

File tree

4 files changed

+57
-34
lines changed

4 files changed

+57
-34
lines changed

doc/api/fs.md

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -257,18 +257,20 @@ added: v10.0.0
257257
added: v10.0.0
258258
-->
259259
260-
* `buffer` {Buffer|Uint8Array} A buffer that will be filled with the file
261-
data read.
260+
* `buffer` {Buffer|TypedArray|DataView} A buffer that will be filled with the
261+
file data read.
262262
* `offset` {integer} The location in the buffer at which to start filling.
263263
**Default:** `0`
264-
* `length` {integer} The number of bytes to read. **Default:** `buffer.length`
264+
* `length` {integer} The number of bytes to read. **Default:**
265+
`buffer.byteLength`
265266
* `position` {integer} The location where to begin reading data from the
266267
file. If `null`, data will be read from the current file position, and
267268
the position will be updated. If `position` is an integer, the current
268269
file position will remain unchanged.
269270
* Returns: {Promise} Fulfills upon success with an object with two properties:
270271
* `bytesRead` {integer} The number of bytes read
271-
* `buffer` {Buffer|Uint8Array} A reference to the passed in `buffer` argument.
272+
* `buffer` {Buffer|TypedArray|DataView} A reference to the passed in `buffer`
273+
argument.
272274
273275
Reads data from the file and stores that in the given buffer.
274276
@@ -282,19 +284,20 @@ added:
282284
- v12.17.0
283285
-->
284286
* `options` {Object}
285-
* `buffer` {Buffer|Uint8Array} A buffer that will be filled with the file
286-
data read. **Default:** `Buffer.alloc(16384)`
287+
* `buffer` {Buffer|TypedArray|DataView} A buffer that will be filled with the
288+
file data read. **Default:** `Buffer.alloc(16384)`
287289
* `offset` {integer} The location in the buffer at which to start filling.
288290
**Default:** `0`
289-
* `length` {integer} The number of bytes to read. **Default:** `buffer.length`
291+
* `length` {integer} The number of bytes to read. **Default:**
292+
`buffer.byteLength`
290293
* `position` {integer} The location where to begin reading data from the
291294
file. If `null`, data will be read from the current file position, and
292295
the position will be updated. If `position` is an integer, the current
293296
file position will remain unchanged. **Default:**: `null`
294297
* Returns: {Promise} Fulfills upon success with an object with two properties:
295298
* `bytesRead` {integer} The number of bytes read
296-
* `buffer` {Buffer|Uint8Array} A reference to the passed in `buffer`
297-
argument.
299+
* `buffer` {Buffer|TypedArray|DataView} A reference to the passed in `buffer`
300+
argument.
298301
299302
Reads data from the file and stores that in the given buffer.
300303
@@ -429,10 +432,11 @@ changes:
429432
buffers anymore.
430433
-->
431434
432-
* `buffer` {Buffer|Uint8Array|string|Object}
435+
* `buffer` {Buffer|TypedArray|DataView|string|Object}
433436
* `offset` {integer} The start position from within `buffer` where the data
434-
to write begins.
435-
* `length` {integer} The number of bytes from `buffer` to write.
437+
to write begins. **Default:** `0`
438+
* `length` {integer} The number of bytes from `buffer` to write. **Default:**
439+
`buffer.byteLength`
436440
* `position` {integer} The offset from the beginning of the file where the
437441
data from `buffer` should be written. If `position` is not a `number`,
438442
the data will be written at the current position. See the POSIX pwrite(2)
@@ -444,8 +448,8 @@ Write `buffer` to the file.
444448
The promise is resolved with an object containing two properties:
445449
446450
* `bytesWritten` {integer} the number of bytes written
447-
* `buffer` {Buffer|Uint8Array|string|Object} a reference to the `buffer`
448-
written.
451+
* `buffer` {Buffer|TypedArray|DataView|string|Object} a reference to the
452+
`buffer` written.
449453
450454
It is unsafe to use `filehandle.write()` multiple times on the same file
451455
without waiting for the promise to be resolved (or rejected). For this
@@ -510,7 +514,7 @@ changes:
510514
strings anymore.
511515
-->
512516
513-
* `data` {string|Buffer|Uint8Array|Object|AsyncIterable|Iterable
517+
* `data` {string|Buffer|TypedArray|DataView|Object|AsyncIterable|Iterable
514518
|Stream}
515519
* `options` {Object|string}
516520
* `encoding` {string|null} The expected character encoding when `data` is a
@@ -1263,7 +1267,7 @@ changes:
12631267
-->
12641268
12651269
* `file` {string|Buffer|URL|FileHandle} filename or `FileHandle`
1266-
* `data` {string|Buffer|Uint8Array|Object|AsyncIterable|Iterable
1270+
* `data` {string|Buffer|TypedArray|DataView|Object|AsyncIterable|Iterable
12671271
|Stream}
12681272
* `options` {Object|string}
12691273
* `encoding` {string|null} **Default:** `'utf8'`
@@ -2709,9 +2713,11 @@ changes:
27092713
27102714
* `fd` {integer}
27112715
* `buffer` {Buffer|TypedArray|DataView} The buffer that the data will be
2712-
written to.
2713-
* `offset` {integer} The position in `buffer` to write the data to.
2714-
* `length` {integer} The number of bytes to read.
2716+
written to. **Default:** `Buffer.alloc(16384)`
2717+
* `offset` {integer} The position in `buffer` to write the data to. **Default:**
2718+
`0`
2719+
* `length` {integer} The number of bytes to read. **Default:**
2720+
`buffer.byteLength`
27152721
* `position` {integer|bigint} Specifies where to begin reading from in the
27162722
file. If `position` is `null` or `-1 `, data will be read from the current
27172723
file position, and the file position will be updated. If `position` is an
@@ -2748,7 +2754,7 @@ changes:
27482754
* `options` {Object}
27492755
* `buffer` {Buffer|TypedArray|DataView} **Default:** `Buffer.alloc(16384)`
27502756
* `offset` {integer} **Default:** `0`
2751-
* `length` {integer} **Default:** `buffer.length`
2757+
* `length` {integer} **Default:** `buffer.byteLength`
27522758
* `position` {integer|bigint} **Default:** `null`
27532759
* `callback` {Function}
27542760
* `err` {Error}
@@ -4657,7 +4663,7 @@ changes:
46574663
* `buffer` {Buffer|TypedArray|DataView}
46584664
* `options` {Object}
46594665
* `offset` {integer} **Default:** `0`
4660-
* `length` {integer} **Default:** `buffer.length`
4666+
* `length` {integer} **Default:** `buffer.byteLength`
46614667
* `position` {integer|bigint} **Default:** `null`
46624668
* Returns: {number}
46634669

lib/fs.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,7 @@ function read(fd, buffer, offset, length, position, callback) {
523523
({
524524
buffer = Buffer.alloc(16384),
525525
offset = 0,
526-
length = buffer.length,
526+
length = buffer.byteLength,
527527
position
528528
} = options);
529529
}
@@ -578,15 +578,15 @@ ObjectDefineProperty(read, internalUtil.customPromisifyArgs,
578578
function readSync(fd, buffer, offset, length, position) {
579579
validateInt32(fd, 'fd', 0);
580580

581+
validateBuffer(buffer);
582+
581583
if (arguments.length <= 3) {
582584
// Assume fs.read(fd, buffer, options)
583585
const options = offset || {};
584586

585-
({ offset = 0, length = buffer.length, position } = options);
587+
({ offset = 0, length = buffer.byteLength, position } = options);
586588
}
587589

588-
validateBuffer(buffer);
589-
590590
if (offset == null) {
591591
offset = 0;
592592
} else {
@@ -673,7 +673,7 @@ function write(fd, buffer, offset, length, position, callback) {
673673
validateInteger(offset, 'offset', 0);
674674
}
675675
if (typeof length !== 'number')
676-
length = buffer.length - offset;
676+
length = buffer.byteLength - offset;
677677
if (typeof position !== 'number')
678678
position = null;
679679
validateOffsetLengthWrite(offset, length, buffer.byteLength);

lib/internal/fs/promises.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -265,21 +265,21 @@ async function writeFileHandle(filehandle, data, signal, encoding) {
265265
checkAborted(signal);
266266
await write(
267267
filehandle, buf, undefined,
268-
isArrayBufferView(buf) ? buf.length : encoding);
268+
isArrayBufferView(buf) ? buf.byteLength : encoding);
269269
checkAborted(signal);
270270
}
271271
return;
272272
}
273273
data = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
274-
let remaining = data.length;
274+
let remaining = data.byteLength;
275275
if (remaining === 0) return;
276276
do {
277277
if (signal?.aborted) {
278278
throw lazyDOMException('The operation was aborted', 'AbortError');
279279
}
280280
const { bytesWritten } =
281281
await write(filehandle, data, 0,
282-
MathMin(kWriteFileMaxChunkSize, data.length));
282+
MathMin(kWriteFileMaxChunkSize, data.byteLength));
283283
remaining -= bytesWritten;
284284
data = new Uint8Array(
285285
data.buffer,
@@ -399,7 +399,7 @@ async function read(handle, bufferOrOptions, offset, length, position) {
399399
buffer = Buffer.alloc(16384);
400400
}
401401
offset = bufferOrOptions.offset || 0;
402-
length = buffer.length;
402+
length = buffer.byteLength;
403403
position = bufferOrOptions.position || null;
404404
}
405405

@@ -414,12 +414,12 @@ async function read(handle, bufferOrOptions, offset, length, position) {
414414
if (length === 0)
415415
return { bytesRead: length, buffer };
416416

417-
if (buffer.length === 0) {
417+
if (buffer.byteLength === 0) {
418418
throw new ERR_INVALID_ARG_VALUE('buffer', buffer,
419419
'is empty and cannot be written');
420420
}
421421

422-
validateOffsetLengthRead(offset, length, buffer.length);
422+
validateOffsetLengthRead(offset, length, buffer.byteLength);
423423

424424
if (!NumberIsSafeInteger(position))
425425
position = -1;
@@ -442,7 +442,7 @@ async function readv(handle, buffers, position) {
442442
}
443443

444444
async function write(handle, buffer, offset, length, position) {
445-
if (buffer && buffer.length === 0)
445+
if (buffer && buffer.byteLength === 0)
446446
return { bytesWritten: 0, buffer };
447447

448448
if (isArrayBufferView(buffer)) {
@@ -452,7 +452,7 @@ async function write(handle, buffer, offset, length, position) {
452452
validateInteger(offset, 'offset', 0);
453453
}
454454
if (typeof length !== 'number')
455-
length = buffer.length - offset;
455+
length = buffer.byteLength - offset;
456456
if (typeof position !== 'number')
457457
position = null;
458458
validateOffsetLengthWrite(offset, length, buffer.byteLength);

test/parallel/test-fs-write-buffer.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,3 +146,20 @@ tmpdir.refresh();
146146
fs.closeSync(fd);
147147
}));
148148
}
149+
150+
// fs.write with a DataView, without the offset and length parameters:
151+
{
152+
const filename = path.join(tmpdir.path, 'write8.txt');
153+
fs.open(filename, 'w', 0o644, common.mustSucceed((fd) => {
154+
const cb = common.mustSucceed((written) => {
155+
assert.strictEqual(written, expected.length);
156+
fs.closeSync(fd);
157+
158+
const found = fs.readFileSync(filename, 'utf8');
159+
assert.strictEqual(found, expected.toString());
160+
});
161+
162+
const uint8 = Uint8Array.from(expected);
163+
fs.write(fd, new DataView(uint8.buffer), cb);
164+
}));
165+
}

0 commit comments

Comments
 (0)