• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2const common = require('../common');
3const assert = require('assert');
4
5const { Readable, Writable } = require('stream');
6
7const source = Readable({ read: () => {} });
8const dest1 = Writable({ write: () => {} });
9const dest2 = Writable({ write: () => {} });
10
11source.pipe(dest1);
12source.pipe(dest2);
13
14dest1.on('unpipe', common.mustCall());
15dest2.on('unpipe', common.mustCall());
16
17assert.strictEqual(source._readableState.pipes[0], dest1);
18assert.strictEqual(source._readableState.pipes[1], dest2);
19assert.strictEqual(source._readableState.pipes.length, 2);
20
21// Should be able to unpipe them in the reverse order that they were piped.
22
23source.unpipe(dest2);
24
25assert.strictEqual(source._readableState.pipes, dest1);
26assert.notStrictEqual(source._readableState.pipes, dest2);
27
28dest2.on('unpipe', common.mustNotCall());
29source.unpipe(dest2);
30
31source.unpipe(dest1);
32
33assert.strictEqual(source._readableState.pipes, null);
34
35{
36  // Test `cleanup()` if we unpipe all streams.
37  const source = Readable({ read: () => {} });
38  const dest1 = Writable({ write: () => {} });
39  const dest2 = Writable({ write: () => {} });
40
41  let destCount = 0;
42  const srcCheckEventNames = ['end', 'data'];
43  const destCheckEventNames = ['close', 'finish', 'drain', 'error', 'unpipe'];
44
45  const checkSrcCleanup = 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  function checkDestCleanup(dest) {
59    const currentDestId = ++destCount;
60    source.pipe(dest);
61
62    const unpipeChecker = 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}
88