From 217c82ea7cfeababdf50951b27a941b076c7d11e Mon Sep 17 00:00:00 2001 From: Yoshiya Hinosawa Date: Mon, 8 Apr 2024 12:47:34 +0900 Subject: [PATCH] fix(ext/node): out-of-order writes of fs.createWriteStream (#23244) This PR follows this fix (https://github.com/nodejs/node/pull/52005) in Node.js. Stream's construct callback happens one tick earlier by this change, and it prevents the reordering of the first few chunks in `node:stream.Writable` closes #20284 --- ext/node/polyfills/_stream.mjs | 5 +---- tests/unit_node/fs_test.ts | 35 ++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/ext/node/polyfills/_stream.mjs b/ext/node/polyfills/_stream.mjs index 6b772ac044..591f8bb512 100644 --- a/ext/node/polyfills/_stream.mjs +++ b/ext/node/polyfills/_stream.mjs @@ -1665,7 +1665,7 @@ var require_destroy = __commonJS({ } else if (err) { errorOrDestroy(stream, err, true); } else { - process.nextTick(emitConstructNT, stream); + stream.emit(kConstruct); } } try { @@ -1676,9 +1676,6 @@ var require_destroy = __commonJS({ nextTick(onConstruct, err); } } - function emitConstructNT(stream) { - stream.emit(kConstruct); - } function isRequest(stream) { return stream && stream.setHeader && typeof stream.abort === "function"; } diff --git a/tests/unit_node/fs_test.ts b/tests/unit_node/fs_test.ts index caa266ef2c..e62a246fad 100644 --- a/tests/unit_node/fs_test.ts +++ b/tests/unit_node/fs_test.ts @@ -5,6 +5,7 @@ import { join } from "node:path"; import { tmpdir } from "node:os"; import { constants, + createWriteStream, existsSync, mkdtempSync, promises, @@ -14,6 +15,7 @@ import { writeFileSync, } from "node:fs"; import { constants as fsPromiseConstants, cp } from "node:fs/promises"; +import process from "node:process"; import { pathToAbsoluteFileUrl } from "../unit/test_util.ts"; Deno.test( @@ -121,3 +123,36 @@ Deno.test( assert(dataRead === "Hello"); }, ); + +// TODO(kt3k): Delete this test case, and instead enable the compat case +// `test/parallel/test-fs-writestream-open-write.js`, when we update +// `tests/node_compat/runner/suite`. +Deno.test("[node/fs createWriteStream", async () => { + const { promise, resolve, reject } = Promise.withResolvers(); + const tempDir = await Deno.makeTempDir(); + const file = join(tempDir, "file.txt"); + try { + const w = createWriteStream(file); + + w.on("open", () => { + w.write("hello, "); + + process.nextTick(() => { + w.write("world"); + w.end(); + }); + }); + + w.on("close", async () => { + try { + assertEquals(await Deno.readTextFile(file), "hello, world"); + resolve(); + } catch (e) { + reject(e); + } + }); + await promise; + } finally { + await Deno.remove(tempDir, { recursive: true }); + } +});