diff options
author | cjihrig <cjihrig@gmail.com> | 2019-08-17 14:56:13 -0400 |
---|---|---|
committer | cjihrig <cjihrig@gmail.com> | 2019-08-19 15:34:25 -0400 |
commit | 3273d0e9514da750405cc2e3662d72dcbb489380 (patch) | |
tree | a4b120f260dfc643a99dbfc6fa78b20901cb4ddd | |
parent | 9f9a201cc67d09c7c61169f9e274a76afd4159fe (diff) | |
download | android-node-v8-3273d0e9514da750405cc2e3662d72dcbb489380.tar.gz android-node-v8-3273d0e9514da750405cc2e3662d72dcbb489380.tar.bz2 android-node-v8-3273d0e9514da750405cc2e3662d72dcbb489380.zip |
fs: add writev() promises version
https://github.com/nodejs/node/pull/25925 added fs.writev()
and fs.writevSync(), but did not include a Promises based
equivalent. This commit adds the missing method.
Refs: https://github.com/nodejs/node/pull/25925
PR-URL: https://github.com/nodejs/node/pull/29186
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
-rw-r--r-- | doc/api/fs.md | 26 | ||||
-rw-r--r-- | lib/internal/fs/promises.js | 17 | ||||
-rw-r--r-- | lib/internal/fs/utils.js | 14 | ||||
-rw-r--r-- | test/parallel/test-fs-writev-promises.js | 51 |
4 files changed, 108 insertions, 0 deletions
diff --git a/doc/api/fs.md b/doc/api/fs.md index d71f8afd82..58b17c3b21 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -4274,6 +4274,32 @@ If one or more `filehandle.write()` calls are made on a file handle and then a current position till the end of the file. It doesn't always write from the beginning of the file. +#### filehandle.writev(buffers[, position]) +<!-- YAML +added: REPLACEME +--> + +* `buffers` {ArrayBufferView[]} +* `position` {integer} +* Returns: {Promise} + +Write an array of `ArrayBufferView`s to the file. + +The `Promise` is resolved with an object containing a `bytesWritten` property +identifying the number of bytes written, and a `buffers` property containing +a reference to the `buffers` input. + +`position` is the offset from the beginning of the file where this data +should be written. If `typeof position !== 'number'`, the data will be written +at the current position. + +It is unsafe to call `writev()` multiple times on the same file without waiting +for the previous operation to complete. + +On Linux, positional writes don't work when the file is opened in append mode. +The kernel ignores the position argument and always appends the data to +the end of the file. + ### fsPromises.access(path[, mode]) <!-- YAML added: v10.0.0 diff --git a/lib/internal/fs/promises.js b/lib/internal/fs/promises.js index e796520b26..7e6fae9273 100644 --- a/lib/internal/fs/promises.js +++ b/lib/internal/fs/promises.js @@ -29,6 +29,7 @@ const { stringToFlags, stringToSymlinkType, toUnixTimestamp, + validateBufferArray, validateOffsetLengthRead, validateOffsetLengthWrite, warnOnNonPortableTemplate @@ -104,6 +105,10 @@ class FileHandle { return write(this, buffer, offset, length, position); } + writev(buffers, position) { + return writev(this, buffers, position); + } + writeFile(data, options) { return writeFile(this, data, options); } @@ -263,6 +268,18 @@ async function write(handle, buffer, offset, length, position) { return { bytesWritten, buffer }; } +async function writev(handle, buffers, position) { + validateFileHandle(handle); + validateBufferArray(buffers); + + if (typeof position !== 'number') + position = null; + + const bytesWritten = (await binding.writeBuffers(handle.fd, buffers, position, + kUsePromises)) || 0; + return { bytesWritten, buffers }; +} + async function rename(oldPath, newPath) { oldPath = getValidatedPath(oldPath, 'oldPath'); newPath = getValidatedPath(newPath, 'newPath'); diff --git a/lib/internal/fs/utils.js b/lib/internal/fs/utils.js index 2924f7582e..600d118db3 100644 --- a/lib/internal/fs/utils.js +++ b/lib/internal/fs/utils.js @@ -15,6 +15,7 @@ const { hideStackFrames } = require('internal/errors'); const { + isArrayBufferView, isUint8Array, isDate, isBigUint64Array @@ -500,6 +501,18 @@ const getValidatedPath = hideStackFrames((fileURLOrPath, propName = 'path') => { return path; }); +const validateBufferArray = hideStackFrames((buffers, propName = 'buffers') => { + if (!Array.isArray(buffers)) + throw new ERR_INVALID_ARG_TYPE(propName, 'ArrayBufferView[]', buffers); + + for (let i = 0; i < buffers.length; i++) { + if (!isArrayBufferView(buffers[i])) + throw new ERR_INVALID_ARG_TYPE(propName, 'ArrayBufferView[]', buffers); + } + + return buffers; +}); + let nonPortableTemplateWarn = true; function warnOnNonPortableTemplate(template) { @@ -528,6 +541,7 @@ module.exports = { stringToSymlinkType, Stats, toUnixTimestamp, + validateBufferArray, validateOffsetLengthRead, validateOffsetLengthWrite, validatePath, diff --git a/test/parallel/test-fs-writev-promises.js b/test/parallel/test-fs-writev-promises.js new file mode 100644 index 0000000000..ea349796cc --- /dev/null +++ b/test/parallel/test-fs-writev-promises.js @@ -0,0 +1,51 @@ +'use strict'; + +require('../common'); +const assert = require('assert'); +const path = require('path'); +const fs = require('fs').promises; +const tmpdir = require('../common/tmpdir'); +const expected = 'ümlaut. Лорем 運務ホソモ指及 आपको करने विकास 紙読決多密所 أضف'; +let cnt = 0; + +function getFileName() { + return path.join(tmpdir.path, `writev_promises_${++cnt}.txt`); +} + +tmpdir.refresh(); + +(async () => { + { + const filename = getFileName(); + const handle = await fs.open(filename, 'w'); + const buffer = Buffer.from(expected); + const bufferArr = [buffer, buffer]; + const expectedLength = bufferArr.length * buffer.byteLength; + let { bytesWritten, buffers } = await handle.writev([Buffer.from('')], + null); + assert.deepStrictEqual(bytesWritten, 0); + assert.deepStrictEqual(buffers, [Buffer.from('')]); + ({ bytesWritten, buffers } = await handle.writev(bufferArr, null)); + assert.deepStrictEqual(bytesWritten, expectedLength); + assert.deepStrictEqual(buffers, bufferArr); + assert(Buffer.concat(bufferArr).equals(await fs.readFile(filename))); + handle.close(); + } + + // fs.promises.writev() with an array of buffers without position. + { + const filename = getFileName(); + const handle = await fs.open(filename, 'w'); + const buffer = Buffer.from(expected); + const bufferArr = [buffer, buffer, buffer]; + const expectedLength = bufferArr.length * buffer.byteLength; + let { bytesWritten, buffers } = await handle.writev([Buffer.from('')]); + assert.deepStrictEqual(bytesWritten, 0); + assert.deepStrictEqual(buffers, [Buffer.from('')]); + ({ bytesWritten, buffers } = await handle.writev(bufferArr)); + assert.deepStrictEqual(bytesWritten, expectedLength); + assert.deepStrictEqual(buffers, bufferArr); + assert(Buffer.concat(bufferArr).equals(await fs.readFile(filename))); + handle.close(); + } +})(); |