Skip to content

Commit abde764

Browse files
committed
fs: support Uint8Array input to methods
Allow `fs.read`, `fs.write` and `fs.writeFile` to take `Uint8Array` arguments. PR-URL: #10382 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Michaël Zasso <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Italo A. Casas <[email protected]>
1 parent d1843ec commit abde764

File tree

6 files changed

+87
-28
lines changed

6 files changed

+87
-28
lines changed

doc/api/fs.md

+6-6
Original file line numberDiff line numberDiff line change
@@ -1281,7 +1281,7 @@ added: v0.0.2
12811281
-->
12821282

12831283
* `fd` {Integer}
1284-
* `buffer` {String | Buffer}
1284+
* `buffer` {String | Buffer | Uint8Array}
12851285
* `offset` {Integer}
12861286
* `length` {Integer}
12871287
* `position` {Integer}
@@ -1427,7 +1427,7 @@ added: v0.1.21
14271427
-->
14281428

14291429
* `fd` {Integer}
1430-
* `buffer` {String | Buffer}
1430+
* `buffer` {String | Buffer | Uint8Array}
14311431
* `offset` {Integer}
14321432
* `length` {Integer}
14331433
* `position` {Integer}
@@ -1824,7 +1824,7 @@ added: v0.0.2
18241824
-->
18251825

18261826
* `fd` {Integer}
1827-
* `buffer` {Buffer}
1827+
* `buffer` {Buffer | Uint8Array}
18281828
* `offset` {Integer}
18291829
* `length` {Integer}
18301830
* `position` {Integer}
@@ -1891,7 +1891,7 @@ added: v0.1.29
18911891
-->
18921892

18931893
* `file` {String | Buffer | Integer} filename or file descriptor
1894-
* `data` {String | Buffer}
1894+
* `data` {String | Buffer | Uint8Array}
18951895
* `options` {Object | String}
18961896
* `encoding` {String | Null} default = `'utf8'`
18971897
* `mode` {Integer} default = `0o666`
@@ -1934,7 +1934,7 @@ added: v0.1.29
19341934
-->
19351935

19361936
* `file` {String | Buffer | Integer} filename or file descriptor
1937-
* `data` {String | Buffer}
1937+
* `data` {String | Buffer | Uint8Array}
19381938
* `options` {Object | String}
19391939
* `encoding` {String | Null} default = `'utf8'`
19401940
* `mode` {Integer} default = `0o666`
@@ -1948,7 +1948,7 @@ added: v0.1.21
19481948
-->
19491949

19501950
* `fd` {Integer}
1951-
* `buffer` {Buffer}
1951+
* `buffer` {Buffer | Uint8Array}
19521952
* `offset` {Integer}
19531953
* `length` {Integer}
19541954
* `position` {Integer}

lib/fs.js

+7-6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
const constants = process.binding('constants').fs;
77
const util = require('util');
88
const pathModule = require('path');
9+
const { isUint8Array } = process.binding('util');
910

1011
const binding = process.binding('fs');
1112
const fs = exports;
@@ -559,7 +560,7 @@ fs.openSync = function(path, flags, mode) {
559560

560561
var readWarned = false;
561562
fs.read = function(fd, buffer, offset, length, position, callback) {
562-
if (!(buffer instanceof Buffer)) {
563+
if (!isUint8Array(buffer)) {
563564
// legacy string interface (fd, length, position, encoding, callback)
564565
if (!readWarned) {
565566
readWarned = true;
@@ -623,7 +624,7 @@ fs.readSync = function(fd, buffer, offset, length, position) {
623624
var legacy = false;
624625
var encoding;
625626

626-
if (!(buffer instanceof Buffer)) {
627+
if (!isUint8Array(buffer)) {
627628
// legacy string interface (fd, length, position, encoding, callback)
628629
if (!readSyncWarned) {
629630
readSyncWarned = true;
@@ -674,7 +675,7 @@ fs.write = function(fd, buffer, offset, length, position, callback) {
674675
var req = new FSReqWrap();
675676
req.oncomplete = wrapper;
676677

677-
if (buffer instanceof Buffer) {
678+
if (isUint8Array(buffer)) {
678679
callback = maybeCallback(callback || position || length || offset);
679680
if (typeof offset !== 'number') {
680681
offset = 0;
@@ -708,7 +709,7 @@ fs.write = function(fd, buffer, offset, length, position, callback) {
708709
// OR
709710
// fs.writeSync(fd, string[, position[, encoding]]);
710711
fs.writeSync = function(fd, buffer, offset, length, position) {
711-
if (buffer instanceof Buffer) {
712+
if (isUint8Array(buffer)) {
712713
if (position === undefined)
713714
position = null;
714715
if (typeof offset !== 'number')
@@ -1206,7 +1207,7 @@ fs.writeFile = function(path, data, options, callback) {
12061207
});
12071208

12081209
function writeFd(fd, isUserFd) {
1209-
var buffer = (data instanceof Buffer) ?
1210+
var buffer = isUint8Array(data) ?
12101211
data : Buffer.from('' + data, options.encoding || 'utf8');
12111212
var position = /a/.test(flag) ? null : 0;
12121213

@@ -1221,7 +1222,7 @@ fs.writeFileSync = function(path, data, options) {
12211222
var isUserFd = isFd(path); // file descriptor ownership
12221223
var fd = isUserFd ? path : fs.openSync(path, flag, options.mode);
12231224

1224-
if (!(data instanceof Buffer)) {
1225+
if (!isUint8Array(data)) {
12251226
data = Buffer.from('' + data, options.encoding || 'utf8');
12261227
}
12271228
var offset = 0;

src/node_util.cc

+2-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ using v8::Value;
2929
V(isSet, IsSet) \
3030
V(isSetIterator, IsSetIterator) \
3131
V(isSharedArrayBuffer, IsSharedArrayBuffer) \
32-
V(isTypedArray, IsTypedArray)
32+
V(isTypedArray, IsTypedArray) \
33+
V(isUint8Array, IsUint8Array)
3334

3435

3536
#define V(_, ucname) \

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

+24-15
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,29 @@ const Buffer = require('buffer').Buffer;
66
const fs = require('fs');
77
const filepath = path.join(common.fixturesDir, 'x.txt');
88
const fd = fs.openSync(filepath, 'r');
9-
const expected = 'xyz\n';
10-
const bufferAsync = Buffer.allocUnsafe(expected.length);
11-
const bufferSync = Buffer.allocUnsafe(expected.length);
129

13-
fs.read(fd,
14-
bufferAsync,
15-
0,
16-
expected.length,
17-
0,
18-
common.mustCall(function(err, bytesRead) {
19-
assert.equal(bytesRead, expected.length);
20-
assert.deepStrictEqual(bufferAsync, Buffer.from(expected));
21-
}));
10+
const expected = Buffer.from('xyz\n');
2211

23-
var r = fs.readSync(fd, bufferSync, 0, expected.length, 0);
24-
assert.deepStrictEqual(bufferSync, Buffer.from(expected));
25-
assert.equal(r, expected.length);
12+
function test(bufferAsync, bufferSync, expected) {
13+
fs.read(fd,
14+
bufferAsync,
15+
0,
16+
expected.length,
17+
0,
18+
common.mustCall((err, bytesRead) => {
19+
assert.strictEqual(bytesRead, expected.length);
20+
assert.deepStrictEqual(bufferAsync, Buffer.from(expected));
21+
}));
22+
23+
const r = fs.readSync(fd, bufferSync, 0, expected.length, 0);
24+
assert.deepStrictEqual(bufferSync, Buffer.from(expected));
25+
assert.strictEqual(r, expected.length);
26+
}
27+
28+
test(Buffer.allocUnsafe(expected.length),
29+
Buffer.allocUnsafe(expected.length),
30+
expected);
31+
32+
test(new Uint8Array(expected.length),
33+
new Uint8Array(expected.length),
34+
Uint8Array.from(expected));

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

+20
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,23 @@ common.refreshTmpDir();
106106
fs.write(fd, expected, undefined, undefined, cb);
107107
}));
108108
}
109+
110+
// fs.write with a Uint8Array, without the offset and length parameters:
111+
{
112+
const filename = path.join(common.tmpDir, 'write6.txt');
113+
fs.open(filename, 'w', 0o644, common.mustCall(function(err, fd) {
114+
assert.ifError(err);
115+
116+
const cb = common.mustCall(function(err, written) {
117+
assert.ifError(err);
118+
119+
assert.strictEqual(expected.length, written);
120+
fs.closeSync(fd);
121+
122+
const found = fs.readFileSync(filename, 'utf8');
123+
assert.deepStrictEqual(expected.toString(), found);
124+
});
125+
126+
fs.write(fd, Uint8Array.from(expected), cb);
127+
}));
128+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
'use strict';
2+
const common = require('../common');
3+
const assert = require('assert');
4+
const fs = require('fs');
5+
const join = require('path').join;
6+
7+
common.refreshTmpDir();
8+
9+
const filename = join(common.tmpDir, 'test.txt');
10+
11+
const s = '南越国是前203年至前111年存在于岭南地区的一个国家,国都位于番禺,疆域包括今天中国的广东、' +
12+
'广西两省区的大部份地区,福建省、湖南、贵州、云南的一小部份地区和越南的北部。' +
13+
'南越国是秦朝灭亡后,由南海郡尉赵佗于前203年起兵兼并桂林郡和象郡后建立。' +
14+
'前196年和前179年,南越国曾先后两次名义上臣属于西汉,成为西汉的“外臣”。前112年,' +
15+
'南越国末代君主赵建德与西汉发生战争,被汉武帝于前111年所灭。南越国共存在93年,' +
16+
'历经五代君主。南越国是岭南地区的第一个有记载的政权国家,采用封建制和郡县制并存的制度,' +
17+
'它的建立保证了秦末乱世岭南地区社会秩序的稳定,有效的改善了岭南地区落后的政治、##济现状。\n';
18+
19+
const input = Uint8Array.from(Buffer.from(s, 'utf8'));
20+
21+
fs.writeFileSync(filename, input);
22+
assert.strictEqual(fs.readFileSync(filename, 'utf8'), s);
23+
24+
fs.writeFile(filename, input, common.mustCall((e) => {
25+
assert.ifError(e);
26+
27+
assert.strictEqual(fs.readFileSync(filename, 'utf8'), s);
28+
}));

0 commit comments

Comments
 (0)