Skip to content

Commit 175b4d4

Browse files
committed
streams: add stream.pipe
pipe is similar to pipeline however it supports stream composition. Refs: nodejs#32020
1 parent 4e17ffc commit 175b4d4

File tree

2 files changed

+107
-0
lines changed

2 files changed

+107
-0
lines changed

lib/internal/streams/pipelinify.js

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
'use strict';
2+
3+
const pipeline = require('internal/streams/pipeline');
4+
const Duplex = require('internal/streams/duplex');
5+
const { destroyer } = require('internal/streams/destroy');
6+
7+
module.exports = function pipe(...streams) {
8+
// TODO (ronag): Avoid double buffering.
9+
// Implement Writable/Readable/Duplex traits.
10+
// See, https://github.com/nodejs/node/pull/33515.
11+
12+
let ondrain;
13+
let onfinish;
14+
let onreadable;
15+
let onclose;
16+
let d;
17+
18+
const r = pipeline(streams, function(err) {
19+
if (onclose) {
20+
const cb = onclose;
21+
onclose = null;
22+
cb(err);
23+
} else {
24+
d.destroy(err);
25+
}
26+
});
27+
const w = streams[0];
28+
29+
const writable = w.writable;
30+
const readable = r.readable;
31+
const objectMode = w.readableObjectMode;
32+
33+
d = new Duplex({
34+
writable,
35+
readable,
36+
objectMode,
37+
highWaterMark: 1
38+
});
39+
40+
if (writable) {
41+
d._write = function(chunk, encoding, callback) {
42+
if (w.write(chunk, encoding)) {
43+
callback();
44+
} else {
45+
ondrain = callback;
46+
}
47+
};
48+
49+
d._final = function(callback) {
50+
w.end();
51+
onfinish = callback;
52+
};
53+
54+
d.on('drain', function() {
55+
if (ondrain) {
56+
const cb = ondrain;
57+
ondrain = null;
58+
cb();
59+
}
60+
});
61+
62+
d.on('finish', function() {
63+
if (onfinish) {
64+
const cb = onfinish;
65+
onfinish = null;
66+
cb();
67+
}
68+
});
69+
}
70+
71+
if (readable) {
72+
r.on('readable', function() {
73+
if (onreadable) {
74+
const cb = onreadable;
75+
onreadable = null;
76+
cb();
77+
}
78+
});
79+
80+
d._read = function() {
81+
while (true) {
82+
const buf = r.read();
83+
84+
if (buf === null) {
85+
onreadable = d._read;
86+
return;
87+
}
88+
89+
if (!d.push(buf)) {
90+
return;
91+
}
92+
}
93+
};
94+
}
95+
96+
d._destroy = function(err, callback) {
97+
onclose = callback;
98+
onreadable = null;
99+
ondrain = null;
100+
onfinish = null;
101+
destroyer(r, err);
102+
};
103+
104+
return d;
105+
};

lib/stream.js

+2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ const {
3030
} = require('internal/util');
3131

3232
const pipeline = require('internal/streams/pipeline');
33+
const pipelinify = require('internal/streams/pipelinify');
3334
const eos = require('internal/streams/end-of-stream');
3435
const internalBuffer = require('internal/buffer');
3536

@@ -42,6 +43,7 @@ Stream.Duplex = require('internal/streams/duplex');
4243
Stream.Transform = require('internal/streams/transform');
4344
Stream.PassThrough = require('internal/streams/passthrough');
4445
Stream.pipeline = pipeline;
46+
Stream.pipelinify = pipelinify;
4547
const { addAbortSignal } = require('internal/streams/add-abort-signal');
4648
Stream.addAbortSignal = addAbortSignal;
4749
Stream.finished = eos;

0 commit comments

Comments
 (0)