diff options
author | Michaƫl Zasso <targos@protonmail.com> | 2020-09-27 15:34:05 +0300 |
---|---|---|
committer | Node.js GitHub Bot <github-bot@iojs.org> | 2020-09-29 17:23:52 +0300 |
commit | 56e36f41aae54fcde72c1cd52fd5792667219b74 (patch) | |
tree | 6f348eb379b9df65727e552b3bf4b3530d6a64b0 | |
parent | 1390574d66c1be8da899d18fe09afc5cc568fb79 (diff) |
fs: fix fs.promises.writeFile with typed arrays
Before this change, only the first part of typed arrays which have more
than 1 byte per element (e.g. Uint16Array) would be written.
This also removes the use of the `slice` method to avoid unnecessary
copying the data.
Fixes: https://github.com/nodejs/node/issues/35343
PR-URL: https://github.com/nodejs/node/pull/35376
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Zeyu Yang <himself65@outlook.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
-rw-r--r-- | lib/internal/fs/promises.js | 13 | ||||
-rw-r--r-- | test/parallel/test-fs-promises-writefile-typedarray.js | 24 |
2 files changed, 34 insertions, 3 deletions
diff --git a/lib/internal/fs/promises.js b/lib/internal/fs/promises.js index a938b382eb1..60a28735a98 100644 --- a/lib/internal/fs/promises.js +++ b/lib/internal/fs/promises.js @@ -10,12 +10,13 @@ const kReadFileMaxChunkSize = 2 ** 14; const kWriteFileMaxChunkSize = 2 ** 14; const { + Error, MathMax, MathMin, NumberIsSafeInteger, - Symbol, - Error, Promise, + Symbol, + Uint8Array, } = primordials; const { @@ -237,6 +238,8 @@ async function fsCall(fn, handle, ...args) { } async function writeFileHandle(filehandle, data) { + // `data` could be any kind of typed array. + data = new Uint8Array(data.buffer, data.byteOffset, data.byteLength); let remaining = data.length; if (remaining === 0) return; do { @@ -244,7 +247,11 @@ async function writeFileHandle(filehandle, data) { await write(filehandle, data, 0, MathMin(kWriteFileMaxChunkSize, data.length)); remaining -= bytesWritten; - data = data.slice(bytesWritten); + data = new Uint8Array( + data.buffer, + data.byteOffset + bytesWritten, + data.byteLength - bytesWritten + ); } while (remaining > 0); } diff --git a/test/parallel/test-fs-promises-writefile-typedarray.js b/test/parallel/test-fs-promises-writefile-typedarray.js new file mode 100644 index 00000000000..32d9cffa236 --- /dev/null +++ b/test/parallel/test-fs-promises-writefile-typedarray.js @@ -0,0 +1,24 @@ +'use strict'; + +const common = require('../common'); +const fs = require('fs'); +const fsPromises = fs.promises; +const path = require('path'); +const tmpdir = require('../common/tmpdir'); +const assert = require('assert'); +const tmpDir = tmpdir.path; + +tmpdir.refresh(); + +const dest = path.resolve(tmpDir, 'tmp.txt'); +// Use a file size larger than `kReadFileMaxChunkSize`. +const buffer = Buffer.from('012'.repeat(2 ** 14)); + +(async () => { + for (const Constructor of [Uint8Array, Uint16Array, Uint32Array]) { + const array = new Constructor(buffer.buffer); + await fsPromises.writeFile(dest, array); + const data = await fsPromises.readFile(dest); + assert.deepStrictEqual(data, buffer); + } +})().then(common.mustCall()); |