Skip to content
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/_stream_readable.js
Original file line number Diff line number Diff line change
Expand Up @@ -759,7 +759,7 @@ Readable.prototype.unpipe = function(dest) {
state.flowing = false;

for (var i = 0; i < len; i++)
dests[i].emit('unpipe', this, unpipeInfo);
dests[i].emit('unpipe', this, { hasUnpiped: false });
return this;
}

Expand Down
54 changes: 54 additions & 0 deletions test/parallel/test-stream-pipe-unpipe-streams.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,57 @@ source.unpipe(dest2);
source.unpipe(dest1);

assert.strictEqual(source._readableState.pipes, null);

{
// test `cleanup()` if we unpipe all streams.
const source = Readable({ read: () => {} });
const dest1 = Writable({ write: () => {} });
const dest2 = Writable({ write: () => {} });

let destCount = 0;
const srcCheckEventNames = ['end', 'data'];
const destCheckEventNames = ['close', 'finish', 'drain', 'error', 'unpipe'];

const checkSrcCleanup = common.mustCall(() => {
assert.strictEqual(source._readableState.pipes, null);
assert.strictEqual(source._readableState.pipesCount, 0);
assert.strictEqual(source._readableState.flowing, false);

srcCheckEventNames.forEach((eventName) => {
assert.strictEqual(
source.listenerCount(eventName), 0,
`source's '${eventName}' event listeners don't be cleaned up`

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: replace "don't be cleaned up" with "not removed", same below.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok~

);
});
});

function checkDestCleanup(dest) {
const currentDestId = ++destCount;
source.pipe(dest);

const unpipeChecker = common.mustCall(() => {
assert.strictEqual(
dest.listenerCount('unpipe'), 1,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I'd simplify this as

assert.deepStrictEqual(dest.listeners('unpipe'), [unpipeChecker]);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok~

`destination{${currentDestId}} should have a 'unpipe' event ` +
'listener which is `unpipeChecker`'
);
dest.removeListener('unpipe', unpipeChecker);
destCheckEventNames.forEach((eventName) => {
assert.strictEqual(
dest.listenerCount(eventName), 0,
`destination{${currentDestId}}'s '${eventName}' event ` +
"listeners don't be cleaned up"
);
});

if (--destCount === 0)
checkSrcCleanup();
});

dest.on('unpipe', unpipeChecker);
}

checkDestCleanup(dest1);
checkDestCleanup(dest2);
source.unpipe();
}