GeezerVison is showing github.com — fs: make params in writing methods optional · nodejs/node@4648309
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: doc/api/fs.md +63-4Lines changed: 63 additions & 4 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -561,7 +561,7 @@ added: v10.0.0 | 561 | 561 | Change the file system timestamps of the object referenced by the {FileHandle} | 562 | 562 | then resolves the promise with no arguments upon success. | 563 | 563 |
| 564 | | -#### `filehandle.write(buffer[, offset[, length[, position]]])` | | 564 | +#### `filehandle.write(buffer, offset[, length[, position]])` | 565 | 565 |
| 566 | 566 | <!-- YAML | 567 | 567 | added: v10.0.0 | @@ -574,7 +574,7 @@ changes: | 574 | 574 |
| 575 | 575 | * `buffer` {Buffer|TypedArray|DataView} | 576 | 576 | * `offset` {integer} The start position from within `buffer` where the data | 577 | | - to write begins. **Default:** `0` | | 577 | + to write begins. | 578 | 578 | * `length` {integer} The number of bytes from `buffer` to write. **Default:** | 579 | 579 | `buffer.byteLength - offset` | 580 | 580 | * `position` {integer|null} The offset from the beginning of the file where the | @@ -599,6 +599,25 @@ On Linux, positional writes do not work when the file is opened in append mode. | 599 | 599 | The kernel ignores the position argument and always appends the data to | 600 | 600 | the end of the file. | 601 | 601 |
| | 602 | +#### `filehandle.write(buffer[, options])` | | 603 | +
| | 604 | +<!-- YAML | | 605 | +added: REPLACEME | | 606 | +--> | | 607 | +
| | 608 | +* `buffer` {Buffer|TypedArray|DataView} | | 609 | +* `options` {Object} | | 610 | + * `offset` {integer} **Default:** `0` | | 611 | + * `length` {integer} **Default:** `buffer.byteLength - offset` | | 612 | + * `position` {integer} **Default:** `null` | | 613 | +* Returns: {Promise} | | 614 | +
| | 615 | +Write `buffer` to the file. | | 616 | +
| | 617 | +Similar to the above `filehandle.write` function, this version takes an | | 618 | +optional `options` object. If no `options` object is specified, it will | | 619 | +default with the above values. | | 620 | +
| 602 | 621 | #### `filehandle.write(string[, position[, encoding]])` | 603 | 622 |
| 604 | 623 | <!-- YAML | @@ -4144,7 +4163,7 @@ This happens when: | 4144 | 4163 | * the file is deleted, followed by a restore | 4145 | 4164 | * the file is renamed and then renamed a second time back to its original name | 4146 | 4165 |
| 4147 | | -### `fs.write(fd, buffer[, offset[, length[, position]]], callback)` | | 4166 | +### `fs.write(fd, buffer, offset[, length[, position]], callback)` | 4148 | 4167 |
| 4149 | 4168 | <!-- YAML | 4150 | 4169 | added: v0.0.2 | @@ -4206,6 +4225,29 @@ On Linux, positional writes don't work when the file is opened in append mode. | 4206 | 4225 | The kernel ignores the position argument and always appends the data to | 4207 | 4226 | the end of the file. | 4208 | 4227 |
| | 4228 | +### `fs.write(fd, buffer[, options], callback)` | | 4229 | +
| | 4230 | +<!-- YAML | | 4231 | +added: REPLACEME | | 4232 | +--> | | 4233 | +
| | 4234 | +* `fd` {integer} | | 4235 | +* `buffer` {Buffer|TypedArray|DataView} | | 4236 | +* `options` {Object} | | 4237 | + * `offset` {integer} **Default:** `0` | | 4238 | + * `length` {integer} **Default:** `buffer.byteLength - offset` | | 4239 | + * `position` {integer} **Default:** `null` | | 4240 | +* `callback` {Function} | | 4241 | + * `err` {Error} | | 4242 | + * `bytesWritten` {integer} | | 4243 | + * `buffer` {Buffer|TypedArray|DataView} | | 4244 | +
| | 4245 | +Write `buffer` to the file specified by `fd`. | | 4246 | +
| | 4247 | +Similar to the above `fs.write` function, this version takes an | | 4248 | +optional `options` object. If no `options` object is specified, it will | | 4249 | +default with the above values. | | 4250 | +
| 4209 | 4251 | ### `fs.write(fd, string[, position[, encoding]], callback)` | 4210 | 4252 |
| 4211 | 4253 | <!-- YAML | @@ -5531,7 +5573,7 @@ for more details. | 5531 | 5573 | For detailed information, see the documentation of the asynchronous version of | 5532 | 5574 | this API: [`fs.writeFile()`][]. | 5533 | 5575 |
| 5534 | | -### `fs.writeSync(fd, buffer[, offset[, length[, position]]])` | | 5576 | +### `fs.writeSync(fd, buffer, offset[, length[, position]])` | 5535 | 5577 |
| 5536 | 5578 | <!-- YAML | 5537 | 5579 | added: v0.1.21 | @@ -5562,6 +5604,23 @@ changes: | 5562 | 5604 | For detailed information, see the documentation of the asynchronous version of | 5563 | 5605 | this API: [`fs.write(fd, buffer...)`][]. | 5564 | 5606 |
| | 5607 | +### `fs.writeSync(fd, buffer[, options])` | | 5608 | +
| | 5609 | +<!-- YAML | | 5610 | +added: REPLACEME | | 5611 | +--> | | 5612 | +
| | 5613 | +* `fd` {integer} | | 5614 | +* `buffer` {Buffer|TypedArray|DataView} | | 5615 | +* `options` {Object} | | 5616 | + * `offset` {integer} **Default:** `0` | | 5617 | + * `length` {integer} **Default:** `buffer.byteLength - offset` | | 5618 | + * `position` {integer} **Default:** `null` | | 5619 | +* Returns: {number} The number of bytes written. | | 5620 | +
| | 5621 | +For detailed information, see the documentation of the asynchronous version of | | 5622 | +this API: [`fs.write(fd, buffer...)`][]. | | 5623 | +
| 5565 | 5624 | ### `fs.writeSync(fd, string[, position[, encoding]])` | 5566 | 5625 |
| 5567 | 5626 | <!-- YAML | |
Collapse file Copy file name to clipboardExpand all lines: lib/fs.js +29-8Lines changed: 29 additions & 8 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -630,7 +630,7 @@ function read(fd, buffer, offsetOrOptions, length, position, callback) { | 630 | 630 | ({ | 631 | 631 | offset = 0, | 632 | 632 | length = buffer.byteLength - offset, | 633 | | - position = null | | 633 | + position = null, | 634 | 634 | } = params ?? ObjectCreate(null)); | 635 | 635 | } | 636 | 636 |
| @@ -701,7 +701,7 @@ function readSync(fd, buffer, offset, length, position) { | 701 | 701 | ({ | 702 | 702 | offset = 0, | 703 | 703 | length = buffer.byteLength - offset, | 704 | | - position = null | | 704 | + position = null, | 705 | 705 | } = options); | 706 | 706 | } | 707 | 707 |
| @@ -797,7 +797,7 @@ function readvSync(fd, buffers, position) { | 797 | 797 | * Writes `buffer` to the specified `fd` (file descriptor). | 798 | 798 | * @param {number} fd | 799 | 799 | * @param {Buffer | TypedArray | DataView | string | object} buffer | 800 | | - * @param {number} [offset] | | 800 | + * @param {number | object} [offsetOrOptions] | 801 | 801 | * @param {number} [length] | 802 | 802 | * @param {number | null} [position] | 803 | 803 | * @param {( | @@ -807,16 +807,26 @@ function readvSync(fd, buffers, position) { | 807 | 807 | * ) => any} callback | 808 | 808 | * @returns {void} | 809 | 809 | */ | 810 | | -function write(fd, buffer, offset, length, position, callback) { | | 810 | +function write(fd, buffer, offsetOrOptions, length, position, callback) { | 811 | 811 | function wrapper(err, written) { | 812 | 812 | // Retain a reference to buffer so that it can't be GC'ed too soon. | 813 | 813 | callback(err, written || 0, buffer); | 814 | 814 | } | 815 | 815 |
| 816 | 816 | fd = getValidatedFd(fd); | 817 | 817 |
| | 818 | + let offset = offsetOrOptions; | 818 | 819 | if (isArrayBufferView(buffer)) { | 819 | 820 | callback = maybeCallback(callback || position || length || offset); | | 821 | + | | 822 | + if (typeof offset === 'object') { | | 823 | + ({ | | 824 | + offset = 0, | | 825 | + length = buffer.byteLength - offset, | | 826 | + position = null, | | 827 | + } = offsetOrOptions ?? ObjectCreate(null)); | | 828 | + } | | 829 | + | 820 | 830 | if (offset == null || typeof offset === 'function') { | 821 | 831 | offset = 0; | 822 | 832 | } else { | @@ -862,16 +872,27 @@ ObjectDefineProperty(write, internalUtil.customPromisifyArgs, | 862 | 872 | * specified `fd` (file descriptor). | 863 | 873 | * @param {number} fd | 864 | 874 | * @param {Buffer | TypedArray | DataView | string} buffer | 865 | | - * @param {number} [offset] | 866 | | - * @param {number} [length] | 867 | | - * @param {number | null} [position] | | 875 | + * @param {{ | | 876 | + * offset?: number; | | 877 | + * length?: number; | | 878 | + * position?: number | null; | | 879 | + * }} [offsetOrOptions] | 868 | 880 | * @returns {number} | 869 | 881 | */ | 870 | | -function writeSync(fd, buffer, offset, length, position) { | | 882 | +function writeSync(fd, buffer, offsetOrOptions, length, position) { | 871 | 883 | fd = getValidatedFd(fd); | 872 | 884 | const ctx = {}; | 873 | 885 | let result; | | 886 | + | | 887 | + let offset = offsetOrOptions; | 874 | 888 | if (isArrayBufferView(buffer)) { | | 889 | + if (typeof offset === 'object') { | | 890 | + ({ | | 891 | + offset = 0, | | 892 | + length = buffer.byteLength - offset, | | 893 | + position = null | | 894 | + } = offsetOrOptions ?? ObjectCreate(null)); | | 895 | + } | 875 | 896 | if (position === undefined) | 876 | 897 | position = null; | 877 | 898 | if (offset == null) { | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/fs/promises.js +10-1Lines changed: 10 additions & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -517,11 +517,20 @@ async function readv(handle, buffers, position) { | 517 | 517 | return { bytesRead, buffers }; | 518 | 518 | } | 519 | 519 |
| 520 | | -async function write(handle, buffer, offset, length, position) { | | 520 | +async function write(handle, buffer, offsetOrOptions, length, position) { | 521 | 521 | if (buffer?.byteLength === 0) | 522 | 522 | return { bytesWritten: 0, buffer }; | 523 | 523 |
| | 524 | + let offset = offsetOrOptions; | 524 | 525 | if (isArrayBufferView(buffer)) { | | 526 | + if (typeof offset === 'object') { | | 527 | + ({ | | 528 | + offset = 0, | | 529 | + length = buffer.byteLength - offset, | | 530 | + position = null | | 531 | + } = offsetOrOptions ?? ObjectCreate(null)); | | 532 | + } | | 533 | + | 525 | 534 | if (offset == null) { | 526 | 535 | offset = 0; | 527 | 536 | } else { | |
Collapse file Copy file name to clipboard +95Lines changed: 95 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +'use strict'; | | 2 | + | | 3 | +const common = require('../common'); | | 4 | + | | 5 | +// This test ensures that filehandle.write accepts "named parameters" object | | 6 | +// and doesn't interpret objects as strings | | 7 | + | | 8 | +const assert = require('assert'); | | 9 | +const fsPromises = require('fs').promises; | | 10 | +const path = require('path'); | | 11 | +const tmpdir = require('../common/tmpdir'); | | 12 | + | | 13 | +tmpdir.refresh(); | | 14 | + | | 15 | +const dest = path.resolve(tmpdir.path, 'tmp.txt'); | | 16 | +const buffer = Buffer.from('zyx'); | | 17 | + | | 18 | +async function testInvalid(dest, expectedCode, ...params) { | | 19 | + let fh; | | 20 | + try { | | 21 | + fh = await fsPromises.open(dest, 'w+'); | | 22 | + await assert.rejects( | | 23 | + fh.write(...params), | | 24 | + { code: expectedCode }); | | 25 | + } finally { | | 26 | + await fh?.close(); | | 27 | + } | | 28 | +} | | 29 | + | | 30 | +async function testValid(dest, buffer, options) { | | 31 | + let fh; | | 32 | + try { | | 33 | + fh = await fsPromises.open(dest, 'w+'); | | 34 | + const writeResult = await fh.write(buffer, options); | | 35 | + const writeBufCopy = Uint8Array.prototype.slice.call(writeResult.buffer); | | 36 | + | | 37 | + const readResult = await fh.read(buffer, options); | | 38 | + const readBufCopy = Uint8Array.prototype.slice.call(readResult.buffer); | | 39 | + | | 40 | + assert.ok(writeResult.bytesWritten >= readResult.bytesRead); | | 41 | + if (options.length !== undefined && options.length !== null) { | | 42 | + assert.strictEqual(writeResult.bytesWritten, options.length); | | 43 | + } | | 44 | + if (options.offset === undefined || options.offset === 0) { | | 45 | + assert.deepStrictEqual(writeBufCopy, readBufCopy); | | 46 | + } | | 47 | + assert.deepStrictEqual(writeResult.buffer, readResult.buffer); | | 48 | + } finally { | | 49 | + await fh?.close(); | | 50 | + } | | 51 | +} | | 52 | + | | 53 | +(async () => { | | 54 | + // Test if first argument is not wrongly interpreted as ArrayBufferView|string | | 55 | + for (const badBuffer of [ | | 56 | + undefined, null, true, 42, 42n, Symbol('42'), NaN, [], () => {}, | | 57 | + Promise.resolve(new Uint8Array(1)), | | 58 | + {}, | | 59 | + { buffer: 'amNotParam' }, | | 60 | + { string: 'amNotParam' }, | | 61 | + { buffer: new Uint8Array(1).buffer }, | | 62 | + new Date(), | | 63 | + new String('notPrimitive'), | | 64 | + { toString() { return 'amObject'; } }, | | 65 | + { [Symbol.toPrimitive]: (hint) => 'amObject' }, | | 66 | + ]) { | | 67 | + await testInvalid(dest, 'ERR_INVALID_ARG_TYPE', badBuffer, {}); | | 68 | + } | | 69 | + | | 70 | + // First argument (buffer or string) is mandatory | | 71 | + await testInvalid(dest, 'ERR_INVALID_ARG_TYPE'); | | 72 | + | | 73 | + // Various invalid options | | 74 | + await testInvalid(dest, 'ERR_OUT_OF_RANGE', buffer, { length: 5 }); | | 75 | + await testInvalid(dest, 'ERR_OUT_OF_RANGE', buffer, { offset: 5 }); | | 76 | + await testInvalid(dest, 'ERR_OUT_OF_RANGE', buffer, { length: 1, offset: 3 }); | | 77 | + await testInvalid(dest, 'ERR_OUT_OF_RANGE', buffer, { length: -1 }); | | 78 | + await testInvalid(dest, 'ERR_OUT_OF_RANGE', buffer, { offset: -1 }); | | 79 | + await testInvalid(dest, 'ERR_INVALID_ARG_TYPE', buffer, { offset: false }); | | 80 | + await testInvalid(dest, 'ERR_INVALID_ARG_TYPE', buffer, { offset: true }); | | 81 | + | | 82 | + // Test compatibility with filehandle.read counterpart | | 83 | + for (const options of [ | | 84 | + {}, | | 85 | + { length: 1 }, | | 86 | + { position: 5 }, | | 87 | + { length: 1, position: 5 }, | | 88 | + { length: 1, position: -1, offset: 2 }, | | 89 | + { length: null }, | | 90 | + { position: null }, | | 91 | + { offset: 1 }, | | 92 | + ]) { | | 93 | + await testValid(dest, buffer, options); | | 94 | + } | | 95 | +})().then(common.mustCall()); |
|