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>
This commit is contained in:
parent
9f9a201cc6
commit
3273d0e951
@ -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
|
current position till the end of the file. It doesn't always write from the
|
||||||
beginning of the file.
|
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])
|
### fsPromises.access(path[, mode])
|
||||||
<!-- YAML
|
<!-- YAML
|
||||||
added: v10.0.0
|
added: v10.0.0
|
||||||
|
@ -29,6 +29,7 @@ const {
|
|||||||
stringToFlags,
|
stringToFlags,
|
||||||
stringToSymlinkType,
|
stringToSymlinkType,
|
||||||
toUnixTimestamp,
|
toUnixTimestamp,
|
||||||
|
validateBufferArray,
|
||||||
validateOffsetLengthRead,
|
validateOffsetLengthRead,
|
||||||
validateOffsetLengthWrite,
|
validateOffsetLengthWrite,
|
||||||
warnOnNonPortableTemplate
|
warnOnNonPortableTemplate
|
||||||
@ -104,6 +105,10 @@ class FileHandle {
|
|||||||
return write(this, buffer, offset, length, position);
|
return write(this, buffer, offset, length, position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
writev(buffers, position) {
|
||||||
|
return writev(this, buffers, position);
|
||||||
|
}
|
||||||
|
|
||||||
writeFile(data, options) {
|
writeFile(data, options) {
|
||||||
return writeFile(this, data, options);
|
return writeFile(this, data, options);
|
||||||
}
|
}
|
||||||
@ -263,6 +268,18 @@ async function write(handle, buffer, offset, length, position) {
|
|||||||
return { bytesWritten, buffer };
|
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) {
|
async function rename(oldPath, newPath) {
|
||||||
oldPath = getValidatedPath(oldPath, 'oldPath');
|
oldPath = getValidatedPath(oldPath, 'oldPath');
|
||||||
newPath = getValidatedPath(newPath, 'newPath');
|
newPath = getValidatedPath(newPath, 'newPath');
|
||||||
|
@ -15,6 +15,7 @@ const {
|
|||||||
hideStackFrames
|
hideStackFrames
|
||||||
} = require('internal/errors');
|
} = require('internal/errors');
|
||||||
const {
|
const {
|
||||||
|
isArrayBufferView,
|
||||||
isUint8Array,
|
isUint8Array,
|
||||||
isDate,
|
isDate,
|
||||||
isBigUint64Array
|
isBigUint64Array
|
||||||
@ -500,6 +501,18 @@ const getValidatedPath = hideStackFrames((fileURLOrPath, propName = 'path') => {
|
|||||||
return 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;
|
let nonPortableTemplateWarn = true;
|
||||||
|
|
||||||
function warnOnNonPortableTemplate(template) {
|
function warnOnNonPortableTemplate(template) {
|
||||||
@ -528,6 +541,7 @@ module.exports = {
|
|||||||
stringToSymlinkType,
|
stringToSymlinkType,
|
||||||
Stats,
|
Stats,
|
||||||
toUnixTimestamp,
|
toUnixTimestamp,
|
||||||
|
validateBufferArray,
|
||||||
validateOffsetLengthRead,
|
validateOffsetLengthRead,
|
||||||
validateOffsetLengthWrite,
|
validateOffsetLengthWrite,
|
||||||
validatePath,
|
validatePath,
|
||||||
|
51
test/parallel/test-fs-writev-promises.js
Normal file
51
test/parallel/test-fs-writev-promises.js
Normal file
@ -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();
|
||||||
|
}
|
||||||
|
})();
|
Loading…
x
Reference in New Issue
Block a user