Skip to content

Commit f6bb096

Browse files
fs: honor flush option in writeFileSync utf8 fast path
The C++ utf8 fast path added in 4466dee does not perform an fsync, but the gate routing writeFileSync through it did not consult the flush option added in e01c1d7. As a result writeFileSync(path, data, { encoding: 'utf8', flush: true }) wrote without flushing, while the same call without an explicit encoding flushed correctly. Skip the fast path when flush is requested. appendFileSync delegates to writeFileSync and was affected the same way. Extend the existing flush tests with the explicit-utf8-encoding case for both; the new cases fail without this change. Signed-off-by: Sam Attard <sattard@anthropic.com>
1 parent 141a504 commit f6bb096

3 files changed

Lines changed: 30 additions & 2 deletions

File tree

lib/fs.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2844,8 +2844,10 @@ function writeFileSync(path, data, options) {
28442844

28452845
const flag = options.flag || 'w';
28462846

2847-
// C++ fast path for string data and UTF8 encoding
2848-
if (typeof data === 'string' && (options.encoding === 'utf8' || options.encoding === 'utf-8')) {
2847+
// C++ fast path for string data and UTF8 encoding. The fast path does
2848+
// not perform an fsync, so it cannot be used when flush is requested.
2849+
if (typeof data === 'string' && !flush &&
2850+
(options.encoding === 'utf8' || options.encoding === 'utf-8')) {
28492851
if (!isInt32(path)) {
28502852
path = getValidatedPath(path);
28512853
}

test/parallel/test-fs-append-file-flush.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,19 @@ test('synchronous version', async (t) => {
4747

4848
assert.strictEqual(spy.mock.calls.length, 0);
4949
});
50+
51+
await t.test('performs flush with explicit utf8 encoding', (t) => {
52+
// Refs: the C++ utf8 fast path must not skip the flush.
53+
const spy = t.mock.method(fs, 'fsyncSync');
54+
55+
for (const encoding of ['utf8', 'utf-8']) {
56+
const file = nextFile();
57+
fs.appendFileSync(file, data, { encoding, flush: true });
58+
assert.strictEqual(fs.readFileSync(file, 'utf8'), data);
59+
}
60+
61+
assert.strictEqual(spy.mock.calls.length, 2);
62+
});
5063
});
5164

5265
test('callback version', async (t) => {

test/parallel/test-fs-write-file-flush.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,19 @@ test('synchronous version', async (t) => {
4747

4848
assert.strictEqual(spy.mock.calls.length, 0);
4949
});
50+
51+
await t.test('performs flush with explicit utf8 encoding', (t) => {
52+
// Refs: the C++ utf8 fast path must not skip the flush.
53+
const spy = t.mock.method(fs, 'fsyncSync');
54+
55+
for (const encoding of ['utf8', 'utf-8']) {
56+
const file = nextFile();
57+
fs.writeFileSync(file, data, { encoding, flush: true });
58+
assert.strictEqual(fs.readFileSync(file, 'utf8'), data);
59+
}
60+
61+
assert.strictEqual(spy.mock.calls.length, 2);
62+
});
5063
});
5164

5265
test('callback version', async (t) => {

0 commit comments

Comments
 (0)