diff --git a/lib/stream/consumers.js b/lib/stream/consumers.js index ffe6e531205..4566eff6a30 100644 --- a/lib/stream/consumers.js +++ b/lib/stream/consumers.js @@ -63,6 +63,9 @@ async function text(stream) { else str += dec.decode(chunk, { stream: true }); } + // Flush the streaming TextDecoder so that any pending + // incomplete multibyte characters are handled. + str += dec.decode(undefined, { stream: false }); return str; } diff --git a/test/parallel/test-stream-consumers.js b/test/parallel/test-stream-consumers.js index 8f6a9deb1c2..1a3b6ce0020 100644 --- a/test/parallel/test-stream-consumers.js +++ b/test/parallel/test-stream-consumers.js @@ -232,3 +232,17 @@ const kArrayBuffer = stream.write({}); stream.end({}); } + +{ + const stream = new TransformStream(); + text(stream.readable).then(common.mustCall((str) => { + // Incomplete utf8 character is flushed as a replacement char + assert.strictEqual(str.charCodeAt(0), 0xfffd); + })); + const writer = stream.writable.getWriter(); + Promise.all([ + writer.write(new Uint8Array([0xe2])), + writer.write(new Uint8Array([0x82])), + writer.close(), + ]).then(common.mustCall()); +}