Skip to content

Commit 950a441

Browse files
fs: remove coercion to string in writing methods
Moves DEP0162 to End-of-Life. PR-URL: #42796 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
1 parent 047cd61 commit 950a441

7 files changed

Lines changed: 51 additions & 91 deletions

File tree

‎doc/api/deprecations.md‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3131,6 +3131,9 @@ resources and not the actual references.
31313131

31323132
<!-- YAML
31333133
changes:
3134+
- version: REPLACEME
3135+
pr-url: https://github.com/nodejs/node/pull/42796
3136+
description: End-of-Life.
31343137
- version: v18.0.0
31353138
pr-url: https://github.com/nodejs/node/pull/42607
31363139
description: Runtime deprecation.
@@ -3141,7 +3144,7 @@ changes:
31413144
description: Documentation-only deprecation.
31423145
-->
31433146

3144-
Type: Runtime
3147+
Type: End-of-Life
31453148

31463149
Implicit coercion of objects with own `toString` property, passed as second
31473150
parameter in [`fs.write()`][], [`fs.writeFile()`][], [`fs.appendFile()`][],

‎doc/api/fs.md‎

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4534,6 +4534,10 @@ default with the above values.
45344534
<!-- YAML
45354535
added: v0.11.5
45364536
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.
45374541
- version: v17.8.0
45384542
pr-url: https://github.com/nodejs/node/pull/42149
45394543
description: Passing to the `string` parameter an object with an own
@@ -4560,16 +4564,16 @@ changes:
45604564
-->
45614565

45624566
*`fd` {integer}
4563-
*`string` {string|Object}
4567+
*`string` {string}
45644568
*`position` {integer|null} **Default:**`null`
45654569
*`encoding` {string} **Default:**`'utf8'`
45664570
*`callback` {Function}
45674571
*`err` {Error}
45684572
*`written` {integer}
45694573
*`string` {string}
45704574

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.
45734577

45744578
`position` refers to the offset from the beginning of the file where this data
45754579
should be written. If`typeof position !== 'number'` the data will be written at
@@ -4602,6 +4606,10 @@ details.
46024606
<!-- YAML
46034607
added: v0.1.29
46044608
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.
46054613
- version: v18.0.0
46064614
pr-url: https://github.com/nodejs/node/pull/41678
46074615
description: Passing an invalid callback to the `callback` argument
@@ -4650,7 +4658,7 @@ changes:
46504658
-->
46514659

46524660
*`file` {string|Buffer|URL|integer} filename or file descriptor
4653-
*`data` {string|Buffer|TypedArray|DataView|Object}
4661+
*`data` {string|Buffer|TypedArray|DataView}
46544662
*`options` {Object|string}
46554663
*`encoding` {string|null} **Default:**`'utf8'`
46564664
*`mode` {integer} **Default:**`0o666`
@@ -5840,6 +5848,10 @@ this API: [`fs.utimes()`][].
58405848
<!--YAML
58415849
added: v0.1.29
58425850
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.
58435855
- version: v17.8.0
58445856
pr-url: https://github.com/nodejs/node/pull/42149
58455857
description: Passing to the `data` parameter an object with an own
@@ -5865,7 +5877,7 @@ changes:
58655877
-->
58665878

58675879
* `file` {string|Buffer|URL|integer} filename or file descriptor
5868-
* `data` {string|Buffer|TypedArray|DataView|Object}
5880+
* `data` {string|Buffer|TypedArray|DataView}
58695881
* `options` {Object|string}
58705882
* `encoding` {string|null} **Default:** `'utf8'`
58715883
* `mode` {integer} **Default:** `0o666`

‎lib/fs.js‎

Lines changed: 7 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ const {
3939
ReflectApply,
4040
SafeMap,
4141
SafeSet,
42-
String,
4342
StringPrototypeCharCodeAt,
4443
StringPrototypeIndexOf,
4544
StringPrototypeSlice,
@@ -84,7 +83,6 @@ const { FSReqCallback } = binding;
8483
const{ toPathIfFileURL }=require('internal/url');
8584
const{
8685
customPromisifyArgs: kCustomPromisifyArgsSymbol,
87-
deprecate,
8886
kEmptyObject,
8987
promisify: {
9088
custom: kCustomPromisifiedSymbol,
@@ -123,7 +121,6 @@ const {
123121
validateRmOptionsSync,
124122
validateRmdirOptions,
125123
validateStringAfterArrayBufferView,
126-
validatePrimitiveStringAfterArrayBufferView,
127124
warnOnNonPortableTemplate
128125
}=require('internal/fs/utils');
129126
const{
@@ -171,11 +168,6 @@ const isWindows = process.platform === 'win32';
171168
constisOSX=process.platform==='darwin';
172169

173170

174-
constshowStringCoercionDeprecation=deprecate(
175-
()=>{},
176-
'Implicit coercion of objects with own toString property is deprecated.',
177-
'DEP0162'
178-
);
179171
functionshowTruncateDeprecation(){
180172
if(truncateWarn){
181173
process.emitWarning(
@@ -813,7 +805,7 @@ function readvSync(fd, buffers, position) {
813805
/**
814806
* Writes `buffer` to the specified `fd` (file descriptor).
815807
* @param {number} fd
816-
* @param {Buffer | TypedArray | DataView | string | object} buffer
808+
* @param {Buffer | TypedArray | DataView | string} buffer
817809
* @param {number | object} [offsetOrOptions]
818810
* @param {number} [length]
819811
* @param {number | null} [position]
@@ -861,9 +853,6 @@ function write(fd, buffer, offsetOrOptions, length, position, callback) {
861853
}
862854

863855
validateStringAfterArrayBufferView(buffer,'buffer');
864-
if(typeofbuffer!=='string'){
865-
showStringCoercionDeprecation();
866-
}
867856

868857
if(typeofposition!=='function'){
869858
if(typeofoffset==='function'){
@@ -875,7 +864,7 @@ function write(fd, buffer, offsetOrOptions, length, position, callback) {
875864
length='utf8';
876865
}
877866

878-
conststr=String(buffer);
867+
conststr=buffer;
879868
validateEncoding(str,length);
880869
callback=maybeCallback(position);
881870

@@ -926,7 +915,7 @@ function writeSync(fd, buffer, offsetOrOptions, length, position) {
926915
result=binding.writeBuffer(fd,buffer,offset,length,position,
927916
undefined,ctx);
928917
}else{
929-
validatePrimitiveStringAfterArrayBufferView(buffer,'buffer');
918+
validateStringAfterArrayBufferView(buffer,'buffer');
930919
validateEncoding(buffer,length);
931920

932921
if(offset===undefined)
@@ -2154,7 +2143,7 @@ function writeAll(fd, isUserFd, buffer, offset, length, signal, callback) {
21542143
/**
21552144
* Asynchronously writes data to the file.
21562145
* @param {string | Buffer | URL | number} path
2157-
* @param {string | Buffer | TypedArray | DataView | object} data
2146+
* @param {string | Buffer | TypedArray | DataView} data
21582147
* @param {{
21592148
* encoding?: string | null;
21602149
* mode?: number;
@@ -2171,10 +2160,7 @@ function writeFile(path, data, options, callback) {
21712160

21722161
if(!isArrayBufferView(data)){
21732162
validateStringAfterArrayBufferView(data,'data');
2174-
if(typeofdata!=='string'){
2175-
showStringCoercionDeprecation();
2176-
}
2177-
data=Buffer.from(String(data),options.encoding||'utf8');
2163+
data=Buffer.from(data,options.encoding||'utf8');
21782164
}
21792165

21802166
if(isFd(path)){
@@ -2201,7 +2187,7 @@ function writeFile(path, data, options, callback) {
22012187
/**
22022188
* Synchronously writes data to the file.
22032189
* @param {string | Buffer | URL | number} path
2204-
* @param {string | Buffer | TypedArray | DataView | object} data
2190+
* @param {string | Buffer | TypedArray | DataView} data
22052191
* @param {{
22062192
* encoding?: string | null;
22072193
* mode?: number;
@@ -2214,10 +2200,7 @@ function writeFileSync(path, data, options) {
22142200

22152201
if(!isArrayBufferView(data)){
22162202
validateStringAfterArrayBufferView(data,'data');
2217-
if(typeofdata!=='string'){
2218-
showStringCoercionDeprecation();
2219-
}
2220-
data=Buffer.from(String(data),options.encoding||'utf8');
2203+
data=Buffer.from(data,options.encoding||'utf8');
22212204
}
22222205

22232206
constflag=options.flag||'w';

‎lib/internal/fs/promises.js‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ const {
6666
validateOffsetLengthWrite,
6767
validateRmOptions,
6868
validateRmdirOptions,
69-
validatePrimitiveStringAfterArrayBufferView,
69+
validateStringAfterArrayBufferView,
7070
warnOnNonPortableTemplate,
7171
}=require('internal/fs/utils');
7272
const{ opendir }=require('internal/fs/dir');
@@ -608,7 +608,7 @@ async function write(handle, buffer, offsetOrOptions, length, position) {
608608
return{ bytesWritten, buffer };
609609
}
610610

611-
validatePrimitiveStringAfterArrayBufferView(buffer,'buffer');
611+
validateStringAfterArrayBufferView(buffer,'buffer');
612612
validateEncoding(buffer,length);
613613
constbytesWritten=(awaitbinding.writeString(handle.fd,buffer,offset,
614614
length,kUsePromises))||0;
@@ -838,7 +838,7 @@ async function writeFile(path, data, options) {
838838
constflag=options.flag||'w';
839839

840840
if(!isArrayBufferView(data)&&!isCustomIterable(data)){
841-
validatePrimitiveStringAfterArrayBufferView(data,'data');
841+
validateStringAfterArrayBufferView(data,'data');
842842
data=Buffer.from(data,options.encoding||'utf8');
843843
}
844844

‎lib/internal/fs/utils.js‎

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ const {
1414
MathMin,
1515
MathRound,
1616
ObjectIs,
17-
ObjectPrototypeHasOwnProperty,
1817
ObjectSetPrototypeOf,
1918
ReflectApply,
2019
ReflectOwnKeys,
@@ -874,27 +873,6 @@ const getValidMode = hideStackFrames((mode, type) => {
874873
});
875874

876875
constvalidateStringAfterArrayBufferView=hideStackFrames((buffer,name)=>{
877-
if(typeofbuffer==='string'){
878-
return;
879-
}
880-
881-
if(
882-
typeofbuffer==='object'&&
883-
buffer!==null&&
884-
typeofbuffer.toString==='function'&&
885-
ObjectPrototypeHasOwnProperty(buffer,'toString')
886-
){
887-
return;
888-
}
889-
890-
thrownewERR_INVALID_ARG_TYPE(
891-
name,
892-
['string','Buffer','TypedArray','DataView'],
893-
buffer
894-
);
895-
});
896-
897-
constvalidatePrimitiveStringAfterArrayBufferView=hideStackFrames((buffer,name)=>{
898876
if(typeofbuffer!=='string'){
899877
thrownewERR_INVALID_ARG_TYPE(
900878
name,
@@ -958,6 +936,5 @@ module.exports = {
958936
validateRmOptionsSync,
959937
validateRmdirOptions,
960938
validateStringAfterArrayBufferView,
961-
validatePrimitiveStringAfterArrayBufferView,
962939
warnOnNonPortableTemplate
963940
};

‎test/parallel/test-fs-write-file-sync.js‎

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -102,20 +102,20 @@ tmpdir.refresh();
102102
assert.strictEqual(content,'hello world!');
103103
}
104104

105-
// Test writeFileSync with an object with an own toString function
105+
// Test writeFileSync with an invalid input
106106
{
107-
// Runtime deprecated by DEP0162
108-
common.expectWarning('DeprecationWarning',
109-
'Implicit coercion of objects with own toString property is deprecated.',
110-
'DEP0162');
111-
constfile=path.join(tmpdir.path,'testWriteFileSyncStringify.txt');
112-
constdata={
113-
toString(){
114-
return'hello world!';
115-
}
116-
};
117-
118-
fs.writeFileSync(file,data,{encoding: 'utf8',flag: 'a'});
119-
constcontent=fs.readFileSync(file,{encoding: 'utf8'});
120-
assert.strictEqual(content,String(data));
107+
constfile=path.join(tmpdir.path,'testWriteFileSyncInvalid.txt');
108+
for(constdataof[
109+
false,5,{},[],null,undefined,true,5n,()=>{},Symbol(),newMap(),
110+
newString('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+
}
121121
}

‎test/parallel/test-fs-write.js‎

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ const fn = path.join(tmpdir.path, 'write.txt');
3333
constfn2=path.join(tmpdir.path,'write2.txt');
3434
constfn3=path.join(tmpdir.path,'write3.txt');
3535
constfn4=path.join(tmpdir.path,'write4.txt');
36-
constfn5=path.join(tmpdir.path,'write5.txt');
3736
constexpected='ümlaut.';
3837
constconstants=fs.constants;
3938

@@ -127,23 +126,6 @@ fs.open(fn3, 'w', 0o644, common.mustSucceed((fd) => {
127126
}));
128127

129128

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-
constdone=common.mustSucceed((written)=>{
137-
assert.strictEqual(written,Buffer.byteLength(expected));
138-
fs.closeSync(fd);
139-
});
140-
141-
constdata={
142-
toString(){returnexpected;}
143-
};
144-
fs.write(fd,data,done);
145-
}));
146-
147129
[false,'test',{},[],null,undefined].forEach((i)=>{
148130
assert.throws(
149131
()=>fs.write(i,common.mustNotCall()),
@@ -162,9 +144,12 @@ fs.open(fn4, 'w', 0o644, common.mustSucceed((fd) => {
162144
});
163145

164146
[
165-
false,5,{},[],null,undefined,
147+
false,5,{},[],null,undefined,true,5n,()=>{},Symbol(),newMap(),
166148
newString('notPrimitive'),
167149
{[Symbol.toPrimitive]: (hint)=>'amObject'},
150+
{toString(){return'amObject';}},
151+
Promise.resolve('amPromise'),
152+
common.mustNotCall(),
168153
].forEach((data)=>{
169154
assert.throws(
170155
()=>fs.write(1,data,common.mustNotCall()),
@@ -184,7 +169,7 @@ fs.open(fn4, 'w', 0o644, common.mustSucceed((fd) => {
184169

185170
{
186171
// Regression test for https://github.com/nodejs/node/issues/38168
187-
constfd=fs.openSync(fn5,'w');
172+
constfd=fs.openSync(fn4,'w');
188173

189174
assert.throws(
190175
()=>fs.writeSync(fd,'abc',0,'hex'),

0 commit comments

Comments
 (0)