Skip to content

Commit 35164fa

Browse files
cjihrigtargos
authored andcommitted
fs: add flush option to appendFile() functions
This commit adds documentation and tests for the 'flush' option of the fs.appendFile family of functions. Technically, support was indirectly added in #50009, but this makes it more official. Refs: #49886 Refs: #50009 PR-URL: #50095 Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
1 parent ffa9461 commit 35164fa

2 files changed

Lines changed: 135 additions & 0 deletions

File tree

‎doc/api/fs.md‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,9 @@ longer be used.
180180
<!-- YAML
181181
added: v10.0.0
182182
changes:
183+
- version: REPLACEME
184+
pr-url: https://github.com/nodejs/node/pull/50095
185+
description: The `flush` option is now supported.
183186
- version:
184187
- v15.14.0
185188
- v14.18.0
@@ -194,6 +197,8 @@ changes:
194197
*`data` {string|Buffer|TypedArray|DataView|AsyncIterable|Iterable|Stream}
195198
*`options` {Object|string}
196199
*`encoding` {string|null} **Default:**`'utf8'`
200+
*`flush` {boolean} If `true`, the underlying file descriptor is flushed
201+
prior to closing it. **Default:**`false`.
197202
* Returns: {Promise} Fulfills with `undefined` upon success.
198203

199204
Alias of [`filehandle.writeFile()`][].
@@ -878,6 +883,10 @@ the error raised if the file is not accessible.
878883
879884
<!-- YAML
880885
added: v10.0.0
886+
changes:
887+
- version: REPLACEME
888+
pr-url: https://github.com/nodejs/node/pull/50095
889+
description: The `flush` option is now supported.
881890
-->
882891
883892
* `path` {string|Buffer|URL|FileHandle} filename or {FileHandle}
@@ -886,6 +895,8 @@ added: v10.0.0
886895
* `encoding` {string|null} **Default:** `'utf8'`
887896
* `mode` {integer} **Default:** `0o666`
888897
* `flag` {string} See [support of file system `flags`][]. **Default:** `'a'`.
898+
* `flush` {boolean} If `true`, the underlying file descriptor is flushed
899+
prior to closing it. **Default:** `false`.
889900
* Returns: {Promise} Fulfills with `undefined` upon success.
890901
891902
Asynchronously append data to a file, creating the file if it does not yet
@@ -2028,6 +2039,9 @@ the user from reading or writing to it.
20282039
<!-- YAML
20292040
added: v0.6.7
20302041
changes:
2042+
- version: REPLACEME
2043+
pr-url: https://github.com/nodejs/node/pull/50095
2044+
description: The `flush` option is now supported.
20312045
- version: v18.0.0
20322046
pr-url: https://github.com/nodejs/node/pull/41678
20332047
description: Passing an invalid callback to the `callback` argument
@@ -2055,6 +2069,8 @@ changes:
20552069
* `encoding` {string|null} **Default:** `'utf8'`
20562070
* `mode` {integer} **Default:** `0o666`
20572071
* `flag` {string} See [support of file system `flags`][]. **Default:** `'a'`.
2072+
* `flush` {boolean} If `true`, the underlying file descriptor is flushed
2073+
prior to closing it. **Default:** `false`.
20582074
* `callback` {Function}
20592075
* `err` {Error}
20602076
@@ -5112,6 +5128,9 @@ try {
51125128
<!--YAML
51135129
added: v0.6.7
51145130
changes:
5131+
- version:REPLACEME
5132+
pr-url: https://github.com/nodejs/node/pull/50095
5133+
description: The `flush` option is now supported.
51155134
- version: v7.0.0
51165135
pr-url: https://github.com/nodejs/node/pull/7831
51175136
description: The passed `options` object will never be modified.
@@ -5126,6 +5145,8 @@ changes:
51265145
*`encoding` {string|null} **Default:**`'utf8'`
51275146
*`mode` {integer} **Default:**`0o666`
51285147
*`flag` {string} See [support of file system `flags`][]. **Default:**`'a'`.
5148+
*`flush` {boolean} If `true`, the underlying file descriptor is flushed
5149+
prior to closing it. **Default:**`false`.
51295150

51305151
Synchronously append data to a file, creating the file if it does not yet
51315152
exist. `data` can be a string or a {Buffer}.
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
'use strict';
2+
constcommon=require('../common');
3+
consttmpdir=require('../common/tmpdir');
4+
constassert=require('node:assert');
5+
constfs=require('node:fs');
6+
constfsp=require('node:fs/promises');
7+
consttest=require('node:test');
8+
constdata='foo';
9+
letcnt=0;
10+
11+
functionnextFile(){
12+
returntmpdir.resolve(`${cnt++}.out`);
13+
}
14+
15+
tmpdir.refresh();
16+
17+
test('synchronous version',async(t)=>{
18+
awaitt.test('validation',(t)=>{
19+
for(constvof['true','',0,1,[],{},Symbol()]){
20+
assert.throws(()=>{
21+
fs.appendFileSync(nextFile(),data,{flush: v});
22+
},{code: 'ERR_INVALID_ARG_TYPE'});
23+
}
24+
});
25+
26+
awaitt.test('performs flush',(t)=>{
27+
constspy=t.mock.method(fs,'fsyncSync');
28+
constfile=nextFile();
29+
fs.appendFileSync(file,data,{flush: true});
30+
constcalls=spy.mock.calls;
31+
assert.strictEqual(calls.length,1);
32+
assert.strictEqual(calls[0].result,undefined);
33+
assert.strictEqual(calls[0].error,undefined);
34+
assert.strictEqual(calls[0].arguments.length,1);
35+
assert.strictEqual(typeofcalls[0].arguments[0],'number');
36+
assert.strictEqual(fs.readFileSync(file,'utf8'),data);
37+
});
38+
39+
awaitt.test('does not perform flush',(t)=>{
40+
constspy=t.mock.method(fs,'fsyncSync');
41+
42+
for(constvof[undefined,null,false]){
43+
constfile=nextFile();
44+
fs.appendFileSync(file,data,{flush: v});
45+
assert.strictEqual(fs.readFileSync(file,'utf8'),data);
46+
}
47+
48+
assert.strictEqual(spy.mock.calls.length,0);
49+
});
50+
});
51+
52+
test('callback version',async(t)=>{
53+
awaitt.test('validation',(t)=>{
54+
for(constvof['true','',0,1,[],{},Symbol()]){
55+
assert.throws(()=>{
56+
fs.appendFileSync(nextFile(),data,{flush: v});
57+
},{code: 'ERR_INVALID_ARG_TYPE'});
58+
}
59+
});
60+
61+
awaitt.test('performs flush',(t,done)=>{
62+
constspy=t.mock.method(fs,'fsync');
63+
constfile=nextFile();
64+
fs.appendFile(file,data,{flush: true},common.mustSucceed(()=>{
65+
constcalls=spy.mock.calls;
66+
assert.strictEqual(calls.length,1);
67+
assert.strictEqual(calls[0].result,undefined);
68+
assert.strictEqual(calls[0].error,undefined);
69+
assert.strictEqual(calls[0].arguments.length,2);
70+
assert.strictEqual(typeofcalls[0].arguments[0],'number');
71+
assert.strictEqual(typeofcalls[0].arguments[1],'function');
72+
assert.strictEqual(fs.readFileSync(file,'utf8'),data);
73+
done();
74+
}));
75+
});
76+
77+
awaitt.test('does not perform flush',(t,done)=>{
78+
constvalues=[undefined,null,false];
79+
constspy=t.mock.method(fs,'fsync');
80+
letcnt=0;
81+
82+
for(constvofvalues){
83+
constfile=nextFile();
84+
85+
fs.appendFile(file,data,{flush: v},common.mustSucceed(()=>{
86+
assert.strictEqual(fs.readFileSync(file,'utf8'),data);
87+
cnt++;
88+
89+
if(cnt===values.length){
90+
assert.strictEqual(spy.mock.calls.length,0);
91+
done();
92+
}
93+
}));
94+
}
95+
});
96+
});
97+
98+
test('promise based version',async(t)=>{
99+
awaitt.test('validation',async(t)=>{
100+
for(constvof['true','',0,1,[],{},Symbol()]){
101+
awaitassert.rejects(()=>{
102+
returnfsp.appendFile(nextFile(),data,{flush: v});
103+
},{code: 'ERR_INVALID_ARG_TYPE'});
104+
}
105+
});
106+
107+
awaitt.test('success path',async(t)=>{
108+
for(constvof[undefined,null,false,true]){
109+
constfile=nextFile();
110+
awaitfsp.appendFile(file,data,{flush: v});
111+
assert.strictEqual(awaitfsp.readFile(file,'utf8'),data);
112+
}
113+
});
114+
});

0 commit comments

Comments
 (0)