diff --git a/lib/internal/webstreams/adapters.js b/lib/internal/webstreams/adapters.js index 7650831da837f7..9fad01dee03c6c 100644 --- a/lib/internal/webstreams/adapters.js +++ b/lib/internal/webstreams/adapters.js @@ -215,6 +215,9 @@ function newWritableStreamFromStreamWritable(streamWritable) { write(chunk) { if (streamWritable.writableNeedDrain || !streamWritable.write(chunk)) { backpressurePromise = PromiseWithResolvers(); + if (!streamWritable.writableNeedDrain) { + backpressurePromise.resolve(); + } return SafePromisePrototypeFinally( backpressurePromise.promise, () => { backpressurePromise = undefined; diff --git a/test/parallel/test-whatwg-webstreams-adapters-to-writablestream.js b/test/parallel/test-whatwg-webstreams-adapters-to-writablestream.js index 1527610c513333..730e9491b5835e 100644 --- a/test/parallel/test-whatwg-webstreams-adapters-to-writablestream.js +++ b/test/parallel/test-whatwg-webstreams-adapters-to-writablestream.js @@ -165,3 +165,26 @@ class TestWritable extends Writable { const writer = writableStream.getWriter(); writer.closed.then(common.mustCall()); } + +{ + // Test that the stream doesn't hang when the underlying Writable + // emits 'drain' synchronously during write(). + // Fixes: https://github.com/nodejs/node/issues/61145 + const writable = new Writable({ + write(chunk, encoding, callback) { + callback(); + }, + }); + + // Force synchronous 'drain' emission during write() + // to simulate a stream that doesn't have Node.js's built-in kSync protection. + writable.write = function(chunk) { + this.emit('drain'); + return false; + }; + + const writableStream = newWritableStreamFromStreamWritable(writable); + const writer = writableStream.getWriter(); + writer.write(new Uint8Array([1, 2, 3])).then(common.mustCall()); + writer.write(new Uint8Array([4, 5, 6])).then(common.mustCall()); +}