Skip to content

Commit 18862e4

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 82363be commit 18862e4

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()`][].
@@ -896,6 +901,10 @@ the error raised if the file is not accessible.
896901
897902
<!-- YAML
898903
added: v10.0.0
904+
changes:
905+
- version: REPLACEME
906+
pr-url: https://github.com/nodejs/node/pull/50095
907+
description: The `flush` option is now supported.
899908
-->
900909
901910
* `path` {string|Buffer|URL|FileHandle} filename or {FileHandle}
@@ -904,6 +913,8 @@ added: v10.0.0
904913
* `encoding` {string|null} **Default:** `'utf8'`
905914
* `mode` {integer} **Default:** `0o666`
906915
* `flag` {string} See [support of file system `flags`][]. **Default:** `'a'`.
916+
* `flush` {boolean} If `true`, the underlying file descriptor is flushed
917+
prior to closing it. **Default:** `false`.
907918
* Returns: {Promise} Fulfills with `undefined` upon success.
908919
909920
Asynchronously append data to a file, creating the file if it does not yet
@@ -2052,6 +2063,9 @@ the user from reading or writing to it.
20522063
<!-- YAML
20532064
added: v0.6.7
20542065
changes:
2066+
- version: REPLACEME
2067+
pr-url: https://github.com/nodejs/node/pull/50095
2068+
description: The `flush` option is now supported.
20552069
- version: v18.0.0
20562070
pr-url: https://github.com/nodejs/node/pull/41678
20572071
description: Passing an invalid callback to the `callback` argument
@@ -2079,6 +2093,8 @@ changes:
20792093
* `encoding` {string|null} **Default:** `'utf8'`
20802094
* `mode` {integer} **Default:** `0o666`
20812095
* `flag` {string} See [support of file system `flags`][]. **Default:** `'a'`.
2096+
* `flush` {boolean} If `true`, the underlying file descriptor is flushed
2097+
prior to closing it. **Default:** `false`.
20822098
* `callback` {Function}
20832099
* `err` {Error}
20842100
@@ -5142,6 +5158,9 @@ try {
51425158
<!--YAML
51435159
added: v0.6.7
51445160
changes:
5161+
- version:REPLACEME
5162+
pr-url: https://github.com/nodejs/node/pull/50095
5163+
description: The `flush` option is now supported.
51455164
- version: v7.0.0
51465165
pr-url: https://github.com/nodejs/node/pull/7831
51475166
description: The passed `options` object will never be modified.
@@ -5156,6 +5175,8 @@ changes:
51565175
*`encoding` {string|null} **Default:**`'utf8'`
51575176
*`mode` {integer} **Default:**`0o666`
51585177
*`flag` {string} See [support of file system `flags`][]. **Default:**`'a'`.
5178+
*`flush` {boolean} If `true`, the underlying file descriptor is flushed
5179+
prior to closing it. **Default:**`false`.
51595180

51605181
Synchronously append data to a file, creating the file if it does not yet
51615182
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)