GeezerVison is showing github.com — fs: remove coercion to string in writing methods · nodejs/node@950a441
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/deprecations.md +4-1Lines changed: 4 additions & 1 deletion - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -3131,6 +3131,9 @@ resources and not the actual references. | 3131 | 3131 |
| 3132 | 3132 | <!-- YAML | 3133 | 3133 | changes: | | 3134 | + - version: REPLACEME | | 3135 | + pr-url: https://github.com/nodejs/node/pull/42796 | | 3136 | + description: End-of-Life. | 3134 | 3137 | - version: v18.0.0 | 3135 | 3138 | pr-url: https://github.com/nodejs/node/pull/42607 | 3136 | 3139 | description: Runtime deprecation. | @@ -3141,7 +3144,7 @@ changes: | 3141 | 3144 | description: Documentation-only deprecation. | 3142 | 3145 | --> | 3143 | 3146 |
| 3144 | | -Type: Runtime | | 3147 | +Type: End-of-Life | 3145 | 3148 |
| 3146 | 3149 | Implicit coercion of objects with own `toString` property, passed as second | 3147 | 3150 | parameter in [`fs.write()`][], [`fs.writeFile()`][], [`fs.appendFile()`][], | |
Collapse file Copy file name to clipboardExpand all lines: doc/api/fs.md +17-5Lines changed: 17 additions & 5 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -4534,6 +4534,10 @@ default with the above values. | 4534 | 4534 | <!-- YAML | 4535 | 4535 | added: v0.11.5 | 4536 | 4536 | changes: | | 4537 | + - version: REPLACEME | | 4538 | + pr-url: https://github.com/nodejs/node/pull/42796 | | 4539 | + description: Passing to the `string` parameter an object with an own | | 4540 | + `toString` function is no longer supported. | 4537 | 4541 | - version: v17.8.0 | 4538 | 4542 | pr-url: https://github.com/nodejs/node/pull/42149 | 4539 | 4543 | description: Passing to the `string` parameter an object with an own | @@ -4560,16 +4564,16 @@ changes: | 4560 | 4564 | --> | 4561 | 4565 |
| 4562 | 4566 | * `fd` {integer} | 4563 | | -* `string` {string|Object} | | 4567 | +* `string` {string} | 4564 | 4568 | * `position` {integer|null} **Default:** `null` | 4565 | 4569 | * `encoding` {string} **Default:** `'utf8'` | 4566 | 4570 | * `callback` {Function} | 4567 | 4571 | * `err` {Error} | 4568 | 4572 | * `written` {integer} | 4569 | 4573 | * `string` {string} | 4570 | 4574 |
| 4571 | | -Write `string` to the file specified by `fd`. If `string` is not a string, or an | 4572 | | -object with an own `toString` function property, then an exception is thrown. | | 4575 | +Write `string` to the file specified by `fd`. If `string` is not a string, | | 4576 | +an exception is thrown. | 4573 | 4577 |
| 4574 | 4578 | `position` refers to the offset from the beginning of the file where this data | 4575 | 4579 | should be written. If `typeof position !== 'number'` the data will be written at | @@ -4602,6 +4606,10 @@ details. | 4602 | 4606 | <!-- YAML | 4603 | 4607 | added: v0.1.29 | 4604 | 4608 | changes: | | 4609 | + - version: REPLACEME | | 4610 | + pr-url: https://github.com/nodejs/node/pull/42796 | | 4611 | + description: Passing to the `string` parameter an object with an own | | 4612 | + `toString` function is no longer supported. | 4605 | 4613 | - version: v18.0.0 | 4606 | 4614 | pr-url: https://github.com/nodejs/node/pull/41678 | 4607 | 4615 | description: Passing an invalid callback to the `callback` argument | @@ -4650,7 +4658,7 @@ changes: | 4650 | 4658 | --> | 4651 | 4659 |
| 4652 | 4660 | * `file` {string|Buffer|URL|integer} filename or file descriptor | 4653 | | -* `data` {string|Buffer|TypedArray|DataView|Object} | | 4661 | +* `data` {string|Buffer|TypedArray|DataView} | 4654 | 4662 | * `options` {Object|string} | 4655 | 4663 | * `encoding` {string|null} **Default:** `'utf8'` | 4656 | 4664 | * `mode` {integer} **Default:** `0o666` | @@ -5840,6 +5848,10 @@ this API: [`fs.utimes()`][]. | 5840 | 5848 | <!-- YAML | 5841 | 5849 | added: v0.1.29 | 5842 | 5850 | changes: | | 5851 | + - version: REPLACEME | | 5852 | + pr-url: https://github.com/nodejs/node/pull/42796 | | 5853 | + description: Passing to the `data` parameter an object with an own | | 5854 | + `toString` function is no longer supported. | 5843 | 5855 | - version: v17.8.0 | 5844 | 5856 | pr-url: https://github.com/nodejs/node/pull/42149 | 5845 | 5857 | description: Passing to the `data` parameter an object with an own | @@ -5865,7 +5877,7 @@ changes: | 5865 | 5877 | --> | 5866 | 5878 |
| 5867 | 5879 | * `file` {string|Buffer|URL|integer} filename or file descriptor | 5868 | | -* `data` {string|Buffer|TypedArray|DataView|Object} | | 5880 | +* `data` {string|Buffer|TypedArray|DataView} | 5869 | 5881 | * `options` {Object|string} | 5870 | 5882 | * `encoding` {string|null} **Default:** `'utf8'` | 5871 | 5883 | * `mode` {integer} **Default:** `0o666` | |
Collapse file Copy file name to clipboardExpand all lines: lib/fs.js +7-24Lines changed: 7 additions & 24 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -39,7 +39,6 @@ const { | 39 | 39 | ReflectApply, | 40 | 40 | SafeMap, | 41 | 41 | SafeSet, | 42 | | - String, | 43 | 42 | StringPrototypeCharCodeAt, | 44 | 43 | StringPrototypeIndexOf, | 45 | 44 | StringPrototypeSlice, | @@ -84,7 +83,6 @@ const { FSReqCallback } = binding; | 84 | 83 | const { toPathIfFileURL } = require('internal/url'); | 85 | 84 | const { | 86 | 85 | customPromisifyArgs: kCustomPromisifyArgsSymbol, | 87 | | - deprecate, | 88 | 86 | kEmptyObject, | 89 | 87 | promisify: { | 90 | 88 | custom: kCustomPromisifiedSymbol, | @@ -123,7 +121,6 @@ const { | 123 | 121 | validateRmOptionsSync, | 124 | 122 | validateRmdirOptions, | 125 | 123 | validateStringAfterArrayBufferView, | 126 | | - validatePrimitiveStringAfterArrayBufferView, | 127 | 124 | warnOnNonPortableTemplate | 128 | 125 | } = require('internal/fs/utils'); | 129 | 126 | const { | @@ -171,11 +168,6 @@ const isWindows = process.platform === 'win32'; | 171 | 168 | const isOSX = process.platform === 'darwin'; | 172 | 169 |
| 173 | 170 |
| 174 | | -const showStringCoercionDeprecation = deprecate( | 175 | | - () => {}, | 176 | | - 'Implicit coercion of objects with own toString property is deprecated.', | 177 | | - 'DEP0162' | 178 | | -); | 179 | 171 | function showTruncateDeprecation() { | 180 | 172 | if (truncateWarn) { | 181 | 173 | process.emitWarning( | @@ -813,7 +805,7 @@ function readvSync(fd, buffers, position) { | 813 | 805 | /** | 814 | 806 | * Writes `buffer` to the specified `fd` (file descriptor). | 815 | 807 | * @param {number} fd | 816 | | - * @param {Buffer | TypedArray | DataView | string | object} buffer | | 808 | + * @param {Buffer | TypedArray | DataView | string} buffer | 817 | 809 | * @param {number | object} [offsetOrOptions] | 818 | 810 | * @param {number} [length] | 819 | 811 | * @param {number | null} [position] | @@ -861,9 +853,6 @@ function write(fd, buffer, offsetOrOptions, length, position, callback) { | 861 | 853 | } | 862 | 854 |
| 863 | 855 | validateStringAfterArrayBufferView(buffer, 'buffer'); | 864 | | - if (typeof buffer !== 'string') { | 865 | | - showStringCoercionDeprecation(); | 866 | | - } | 867 | 856 |
| 868 | 857 | if (typeof position !== 'function') { | 869 | 858 | if (typeof offset === 'function') { | @@ -875,7 +864,7 @@ function write(fd, buffer, offsetOrOptions, length, position, callback) { | 875 | 864 | length = 'utf8'; | 876 | 865 | } | 877 | 866 |
| 878 | | - const str = String(buffer); | | 867 | + const str = buffer; | 879 | 868 | validateEncoding(str, length); | 880 | 869 | callback = maybeCallback(position); | 881 | 870 |
| @@ -926,7 +915,7 @@ function writeSync(fd, buffer, offsetOrOptions, length, position) { | 926 | 915 | result = binding.writeBuffer(fd, buffer, offset, length, position, | 927 | 916 | undefined, ctx); | 928 | 917 | } else { | 929 | | - validatePrimitiveStringAfterArrayBufferView(buffer, 'buffer'); | | 918 | + validateStringAfterArrayBufferView(buffer, 'buffer'); | 930 | 919 | validateEncoding(buffer, length); | 931 | 920 |
| 932 | 921 | if (offset === undefined) | @@ -2154,7 +2143,7 @@ function writeAll(fd, isUserFd, buffer, offset, length, signal, callback) { | 2154 | 2143 | /** | 2155 | 2144 | * Asynchronously writes data to the file. | 2156 | 2145 | * @param {string | Buffer | URL | number} path | 2157 | | - * @param {string | Buffer | TypedArray | DataView | object} data | | 2146 | + * @param {string | Buffer | TypedArray | DataView} data | 2158 | 2147 | * @param {{ | 2159 | 2148 | * encoding?: string | null; | 2160 | 2149 | * mode?: number; | @@ -2171,10 +2160,7 @@ function writeFile(path, data, options, callback) { | 2171 | 2160 |
| 2172 | 2161 | if (!isArrayBufferView(data)) { | 2173 | 2162 | validateStringAfterArrayBufferView(data, 'data'); | 2174 | | - if (typeof data !== 'string') { | 2175 | | - showStringCoercionDeprecation(); | 2176 | | - } | 2177 | | - data = Buffer.from(String(data), options.encoding || 'utf8'); | | 2163 | + data = Buffer.from(data, options.encoding || 'utf8'); | 2178 | 2164 | } | 2179 | 2165 |
| 2180 | 2166 | if (isFd(path)) { | @@ -2201,7 +2187,7 @@ function writeFile(path, data, options, callback) { | 2201 | 2187 | /** | 2202 | 2188 | * Synchronously writes data to the file. | 2203 | 2189 | * @param {string | Buffer | URL | number} path | 2204 | | - * @param {string | Buffer | TypedArray | DataView | object} data | | 2190 | + * @param {string | Buffer | TypedArray | DataView} data | 2205 | 2191 | * @param {{ | 2206 | 2192 | * encoding?: string | null; | 2207 | 2193 | * mode?: number; | @@ -2214,10 +2200,7 @@ function writeFileSync(path, data, options) { | 2214 | 2200 |
| 2215 | 2201 | if (!isArrayBufferView(data)) { | 2216 | 2202 | validateStringAfterArrayBufferView(data, 'data'); | 2217 | | - if (typeof data !== 'string') { | 2218 | | - showStringCoercionDeprecation(); | 2219 | | - } | 2220 | | - data = Buffer.from(String(data), options.encoding || 'utf8'); | | 2203 | + data = Buffer.from(data, options.encoding || 'utf8'); | 2221 | 2204 | } | 2222 | 2205 |
| 2223 | 2206 | const flag = options.flag || 'w'; | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/fs/promises.js +3-3Lines changed: 3 additions & 3 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -66,7 +66,7 @@ const { | 66 | 66 | validateOffsetLengthWrite, | 67 | 67 | validateRmOptions, | 68 | 68 | validateRmdirOptions, | 69 | | - validatePrimitiveStringAfterArrayBufferView, | | 69 | + validateStringAfterArrayBufferView, | 70 | 70 | warnOnNonPortableTemplate, | 71 | 71 | } = require('internal/fs/utils'); | 72 | 72 | const { opendir } = require('internal/fs/dir'); | @@ -608,7 +608,7 @@ async function write(handle, buffer, offsetOrOptions, length, position) { | 608 | 608 | return { bytesWritten, buffer }; | 609 | 609 | } | 610 | 610 |
| 611 | | - validatePrimitiveStringAfterArrayBufferView(buffer, 'buffer'); | | 611 | + validateStringAfterArrayBufferView(buffer, 'buffer'); | 612 | 612 | validateEncoding(buffer, length); | 613 | 613 | const bytesWritten = (await binding.writeString(handle.fd, buffer, offset, | 614 | 614 | length, kUsePromises)) || 0; | @@ -838,7 +838,7 @@ async function writeFile(path, data, options) { | 838 | 838 | const flag = options.flag || 'w'; | 839 | 839 |
| 840 | 840 | if (!isArrayBufferView(data) && !isCustomIterable(data)) { | 841 | | - validatePrimitiveStringAfterArrayBufferView(data, 'data'); | | 841 | + validateStringAfterArrayBufferView(data, 'data'); | 842 | 842 | data = Buffer.from(data, options.encoding || 'utf8'); | 843 | 843 | } | 844 | 844 |
| |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/fs/utils.js -23Lines changed: 0 additions & 23 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -14,7 +14,6 @@ const { | 14 | 14 | MathMin, | 15 | 15 | MathRound, | 16 | 16 | ObjectIs, | 17 | | - ObjectPrototypeHasOwnProperty, | 18 | 17 | ObjectSetPrototypeOf, | 19 | 18 | ReflectApply, | 20 | 19 | ReflectOwnKeys, | @@ -874,27 +873,6 @@ const getValidMode = hideStackFrames((mode, type) => { | 874 | 873 | }); | 875 | 874 |
| 876 | 875 | const validateStringAfterArrayBufferView = hideStackFrames((buffer, name) => { | 877 | | - if (typeof buffer === 'string') { | 878 | | - return; | 879 | | - } | 880 | | - | 881 | | - if ( | 882 | | - typeof buffer === 'object' && | 883 | | - buffer !== null && | 884 | | - typeof buffer.toString === 'function' && | 885 | | - ObjectPrototypeHasOwnProperty(buffer, 'toString') | 886 | | - ) { | 887 | | - return; | 888 | | - } | 889 | | - | 890 | | - throw new ERR_INVALID_ARG_TYPE( | 891 | | - name, | 892 | | - ['string', 'Buffer', 'TypedArray', 'DataView'], | 893 | | - buffer | 894 | | - ); | 895 | | -}); | 896 | | - | 897 | | -const validatePrimitiveStringAfterArrayBufferView = hideStackFrames((buffer, name) => { | 898 | 876 | if (typeof buffer !== 'string') { | 899 | 877 | throw new ERR_INVALID_ARG_TYPE( | 900 | 878 | name, | @@ -958,6 +936,5 @@ module.exports = { | 958 | 936 | validateRmOptionsSync, | 959 | 937 | validateRmdirOptions, | 960 | 938 | validateStringAfterArrayBufferView, | 961 | | - validatePrimitiveStringAfterArrayBufferView, | 962 | 939 | warnOnNonPortableTemplate | 963 | 940 | }; |
Collapse file Copy file name to clipboardExpand all lines: test/parallel/test-fs-write-file-sync.js +15-15Lines changed: 15 additions & 15 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -102,20 +102,20 @@ tmpdir.refresh(); | 102 | 102 | assert.strictEqual(content, 'hello world!'); | 103 | 103 | } | 104 | 104 |
| 105 | | -// Test writeFileSync with an object with an own toString function | | 105 | +// Test writeFileSync with an invalid input | 106 | 106 | { | 107 | | - // Runtime deprecated by DEP0162 | 108 | | - common.expectWarning('DeprecationWarning', | 109 | | - 'Implicit coercion of objects with own toString property is deprecated.', | 110 | | - 'DEP0162'); | 111 | | - const file = path.join(tmpdir.path, 'testWriteFileSyncStringify.txt'); | 112 | | - const data = { | 113 | | - toString() { | 114 | | - return 'hello world!'; | 115 | | - } | 116 | | - }; | 117 | | - | 118 | | - fs.writeFileSync(file, data, { encoding: 'utf8', flag: 'a' }); | 119 | | - const content = fs.readFileSync(file, { encoding: 'utf8' }); | 120 | | - assert.strictEqual(content, String(data)); | | 107 | + const file = path.join(tmpdir.path, 'testWriteFileSyncInvalid.txt'); | | 108 | + for (const data of [ | | 109 | + false, 5, {}, [], null, undefined, true, 5n, () => {}, Symbol(), new Map(), | | 110 | + new String('notPrimitive'), | | 111 | + { [Symbol.toPrimitive]: (hint) => 'amObject' }, | | 112 | + { toString() { return 'amObject'; } }, | | 113 | + Promise.resolve('amPromise'), | | 114 | + common.mustNotCall(), | | 115 | + ]) { | | 116 | + assert.throws( | | 117 | + () => fs.writeFileSync(file, data, { encoding: 'utf8', flag: 'a' }), | | 118 | + { code: 'ERR_INVALID_ARG_TYPE' } | | 119 | + ); | | 120 | + } | 121 | 121 | } |
Collapse file Copy file name to clipboardExpand all lines: test/parallel/test-fs-write.js +5-20Lines changed: 5 additions & 20 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -33,7 +33,6 @@ const fn = path.join(tmpdir.path, 'write.txt'); | 33 | 33 | const fn2 = path.join(tmpdir.path, 'write2.txt'); | 34 | 34 | const fn3 = path.join(tmpdir.path, 'write3.txt'); | 35 | 35 | const fn4 = path.join(tmpdir.path, 'write4.txt'); | 36 | | -const fn5 = path.join(tmpdir.path, 'write5.txt'); | 37 | 36 | const expected = 'ümlaut.'; | 38 | 37 | const constants = fs.constants; | 39 | 38 |
| @@ -127,23 +126,6 @@ fs.open(fn3, 'w', 0o644, common.mustSucceed((fd) => { | 127 | 126 | })); | 128 | 127 |
| 129 | 128 |
| 130 | | -// Test write with an object with an own toString function | 131 | | -// Runtime deprecated by DEP0162 | 132 | | -common.expectWarning('DeprecationWarning', | 133 | | - 'Implicit coercion of objects with own toString property is deprecated.', | 134 | | - 'DEP0162'); | 135 | | -fs.open(fn4, 'w', 0o644, common.mustSucceed((fd) => { | 136 | | - const done = common.mustSucceed((written) => { | 137 | | - assert.strictEqual(written, Buffer.byteLength(expected)); | 138 | | - fs.closeSync(fd); | 139 | | - }); | 140 | | - | 141 | | - const data = { | 142 | | - toString() { return expected; } | 143 | | - }; | 144 | | - fs.write(fd, data, done); | 145 | | -})); | 146 | | - | 147 | 129 | [false, 'test', {}, [], null, undefined].forEach((i) => { | 148 | 130 | assert.throws( | 149 | 131 | () => fs.write(i, common.mustNotCall()), | @@ -162,9 +144,12 @@ fs.open(fn4, 'w', 0o644, common.mustSucceed((fd) => { | 162 | 144 | }); | 163 | 145 |
| 164 | 146 | [ | 165 | | - false, 5, {}, [], null, undefined, | | 147 | + false, 5, {}, [], null, undefined, true, 5n, () => {}, Symbol(), new Map(), | 166 | 148 | new String('notPrimitive'), | 167 | 149 | { [Symbol.toPrimitive]: (hint) => 'amObject' }, | | 150 | + { toString() { return 'amObject'; } }, | | 151 | + Promise.resolve('amPromise'), | | 152 | + common.mustNotCall(), | 168 | 153 | ].forEach((data) => { | 169 | 154 | assert.throws( | 170 | 155 | () => fs.write(1, data, common.mustNotCall()), | @@ -184,7 +169,7 @@ fs.open(fn4, 'w', 0o644, common.mustSucceed((fd) => { | 184 | 169 |
| 185 | 170 | { | 186 | 171 | // Regression test for https://github.com/nodejs/node/issues/38168 | 187 | | - const fd = fs.openSync(fn5, 'w'); | | 172 | + const fd = fs.openSync(fn4, 'w'); | 188 | 173 |
| 189 | 174 | assert.throws( | 190 | 175 | () => fs.writeSync(fd, 'abc', 0, 'hex'), | |
|