Skip to content
Open
2 changes: 1 addition & 1 deletion src/js/node/fs.promises.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1614,7 +1614,7 @@ async function writeFileAsyncIterator(fdOrPath, iterable, optionsOrEncoding, fla
let signal: AbortSignal | null = null;
if (typeof optionsOrEncoding === "object") {
encoding = optionsOrEncoding?.encoding ?? (encoding || "utf8");
flag = optionsOrEncoding?.flag ?? (flag || "w");
flag = optionsOrEncoding?.flag || flag || "w";
mode = optionsOrEncoding?.mode ?? (mode || 0o666);
signal = optionsOrEncoding?.signal ?? null;
if (signal?.aborted) {
Expand Down
3 changes: 2 additions & 1 deletion src/runtime/node/node_fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4258,7 +4258,8 @@ pub(crate) mod args {
encoding = Encoding::assert(arg, ctx, encoding)?;
} else if arg.is_object() {
encoding = get_encoding(arg, ctx, encoding)?;
if let Some(flag_) = arg.get_truthy(ctx, "flag")? {
// Node: `options.flag || default` https://github.com/nodejs/node/blob/v26.3.0/lib/fs.js#L2343
if let Some(flag_) = arg.get(ctx, "flag")?.filter(|flag| flag.is_truthy()) {
flag = FileSystemFlags::from_js(ctx, flag_)?.unwrap_or(flag);
}
if let Some(mode_) = arg.get_truthy(ctx, "mode")? {
Expand Down
44 changes: 44 additions & 0 deletions test/js/node/fs/fs-promises-writeFile-async-iterator.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { expect, mock, test } from "bun:test";
import { readFileSync } from "fs";
import { writeFile } from "fs/promises";
import { tempDir } from "harness";
test("fs.promises.writeFile async iterator", async () => {
Expand Down Expand Up @@ -51,3 +52,46 @@ test("fs.promises.writeFile async iterator throws on invalid input", async () =>
expect(() => writeFile(String(dir), fn as any)).toThrow();
expect(fn[Symbol.asyncIterator]).not.toBeCalled();
});

// Node: `const flag = options.flag || 'w'`.
test("fs.promises.writeFile with iterable data takes a falsy flag as the default flag", async () => {
await using dir = tempDir("fs-promises-writeFile-falsy-flag", {});
const path = dir + "/file.txt";
const falsy: [string, any][] = [
["false", false],
["zero", 0],
["negative zero", -0],
["NaN", NaN],
["0n", 0n],
["empty string", ""],
["null", null],
["undefined", undefined],
];
const sources: [string, () => Iterable<string> | AsyncIterable<string>][] = [
["iterable", () => ["n", "e", "w"]],
[
"async iterable",
async function* () {
yield "n";
yield "e";
yield "w";
},
],
];

const results: Record<string, string> = {};
const expected: Record<string, string> = {};
for (const [kind, data] of sources) {
for (const [label, flag] of falsy) {
// Longer than "new": the default flag truncates.
await Bun.write(path, "old content");
const row = `${kind}, flag ${label}`;
results[row] = await writeFile(path, data(), { flag }).then(
() => readFileSync(path, "utf8"),
e => `${e.code}, the file holds ${readFileSync(path, "utf8")}`,
);
expected[row] = "new";
}
}
expect(results).toEqual(expected);
});
92 changes: 92 additions & 0 deletions test/js/node/fs/fs-write-flag-fixture.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading