Skip to content

Commit 27532f4

Browse files
陈刚MylesBorins
authored andcommitted
stream: cleanup() when unpiping all streams.
This PR makes sure the object emitted as the 'unpipe' event in the destination stream is not shared between destination, as it would be muted. Refs: #12746 PR-URL: #18266 Reviewed-By: Luigi Pinca <[email protected]> Reviewed-By: Anatoli Papirovski <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]> Reviewed-By: Anna Henningsen <[email protected]>
1 parent a13fbdd commit 27532f4

File tree

2 files changed

+55
-1
lines changed

2 files changed

+55
-1
lines changed

‎lib/_stream_readable.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -754,7 +754,7 @@ Readable.prototype.unpipe = function(dest){
754754
state.flowing=false;
755755

756756
for(vari=0;i<len;i++)
757-
dests[i].emit('unpipe',this,unpipeInfo);
757+
dests[i].emit('unpipe',this,{hasUnpiped: false});
758758
returnthis;
759759
}
760760

‎test/parallel/test-stream-pipe-unpipe-streams.js‎

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,57 @@ source.unpipe(dest2);
3131
source.unpipe(dest1);
3232

3333
assert.strictEqual(source._readableState.pipes,null);
34+
35+
{
36+
// test `cleanup()` if we unpipe all streams.
37+
constsource=Readable({read: ()=>{}});
38+
constdest1=Writable({write: ()=>{}});
39+
constdest2=Writable({write: ()=>{}});
40+
41+
letdestCount=0;
42+
constsrcCheckEventNames=['end','data'];
43+
constdestCheckEventNames=['close','finish','drain','error','unpipe'];
44+
45+
constcheckSrcCleanup=common.mustCall(()=>{
46+
assert.strictEqual(source._readableState.pipes,null);
47+
assert.strictEqual(source._readableState.pipesCount,0);
48+
assert.strictEqual(source._readableState.flowing,false);
49+
50+
srcCheckEventNames.forEach((eventName)=>{
51+
assert.strictEqual(
52+
source.listenerCount(eventName),0,
53+
`source's '${eventName}' event listeners not removed`
54+
);
55+
});
56+
});
57+
58+
functioncheckDestCleanup(dest){
59+
constcurrentDestId=++destCount;
60+
source.pipe(dest);
61+
62+
constunpipeChecker=common.mustCall(()=>{
63+
assert.deepStrictEqual(
64+
dest.listeners('unpipe'),[unpipeChecker],
65+
`destination{${currentDestId}} should have a 'unpipe' event `+
66+
'listener which is `unpipeChecker`'
67+
);
68+
dest.removeListener('unpipe',unpipeChecker);
69+
destCheckEventNames.forEach((eventName)=>{
70+
assert.strictEqual(
71+
dest.listenerCount(eventName),0,
72+
`destination{${currentDestId}}'s '${eventName}' event `+
73+
'listeners not removed'
74+
);
75+
});
76+
77+
if(--destCount===0)
78+
checkSrcCleanup();
79+
});
80+
81+
dest.on('unpipe',unpipeChecker);
82+
}
83+
84+
checkDestCleanup(dest1);
85+
checkDestCleanup(dest2);
86+
source.unpipe();
87+
}

0 commit comments

Comments
(0)