Skip to content

Commit edef89b

Browse files
watildeaduh95
authored andcommitted
stream: fix dropped first chunk in Utf8Stream buffer mode
Signed-off-by: Daijiro Wachi <daijiro.wachi@gmail.com> PR-URL: #63833 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Mattias Buelens <mattias@buelens.com>
1 parent e26f183 commit edef89b

2 files changed

Lines changed: 73 additions & 1 deletion

File tree

‎lib/internal/streams/fast-utf8-stream.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -818,7 +818,7 @@ class Utf8Stream extends EventEmitter {
818818
bufs.length===0||
819819
lens[lens.length-1]+data.length>this.#maxWrite
820820
){
821-
ArrayPrototypePush(bufs,[]);
821+
ArrayPrototypePush(bufs,[data]);
822822
ArrayPrototypePush(lens,data.length);
823823
}else{
824824
ArrayPrototypePush(bufs[bufs.length-1],data);
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
'use strict';
2+
3+
// Regression test for buffer content mode: the first buffer of every
4+
// batch used to be dropped, corrupting the output and eventually
5+
// crashing in mergeBuf(). Refs: https://github.com/nodejs/node/pull/58897
6+
7+
constcommon=require('../common');
8+
consttmpdir=require('../common/tmpdir');
9+
constassert=require('node:assert');
10+
const{
11+
readFile,
12+
Utf8Stream,
13+
}=require('node:fs');
14+
const{ join }=require('node:path');
15+
16+
tmpdir.refresh();
17+
letfileCounter=0;
18+
19+
functiongetTempFile(){
20+
returnjoin(tmpdir.path,`fastutf8stream-${process.pid}-${Date.now()}-${fileCounter++}.log`);
21+
}
22+
23+
runTests(false);
24+
runTests(true);
25+
26+
functionrunTests(sync){
27+
{
28+
// A single buffer write must end up in the file.
29+
constdest=getTempFile();
30+
conststream=newUtf8Stream({ dest, sync,contentMode: 'buffer'});
31+
32+
stream.on('ready',common.mustCall(()=>{
33+
assert.ok(stream.write(Buffer.from('hello world\n')));
34+
stream.end();
35+
36+
stream.on('finish',common.mustCall(()=>{
37+
readFile(dest,'utf8',common.mustSucceed((data)=>{
38+
assert.strictEqual(data,'hello world\n');
39+
}));
40+
}));
41+
}));
42+
}
43+
44+
{
45+
// Writes that exceed maxWrite start a new batch; data must survive
46+
// the batch boundary and be written in order.
47+
constdest=getTempFile();
48+
conststream=newUtf8Stream({
49+
dest,
50+
sync,
51+
contentMode: 'buffer',
52+
minLength: 60,
53+
maxWrite: 64,
54+
});
55+
56+
stream.on('ready',common.mustCall(()=>{
57+
stream.write(Buffer.from('a'.repeat(40)));
58+
stream.write(Buffer.from('b'.repeat(40)));
59+
stream.write(Buffer.from('c'.repeat(40)));
60+
stream.end();
61+
62+
stream.on('finish',common.mustCall(()=>{
63+
readFile(dest,'utf8',common.mustSucceed((data)=>{
64+
assert.strictEqual(
65+
data,
66+
'a'.repeat(40)+'b'.repeat(40)+'c'.repeat(40),
67+
);
68+
}));
69+
}));
70+
}));
71+
}
72+
}

0 commit comments

Comments
 (0)