// Copyright Joyent, Inc. and other Node contributors.1//2// Permission is hereby granted, free of charge, to any person obtaining a3// copy of this software and associated documentation files (the4// "Software"), to deal in the Software without restriction, including5// without limitation the rights to use, copy, modify, merge, publish,6// distribute, sublicense, and/or sell copies of the Software, and to permit7// persons to whom the Software is furnished to do so, subject to the8// following conditions:9//10// The above copyright notice and this permission notice shall be included11// in all copies or substantial portions of the Software.12//13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS14// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF15// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN16// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,17// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR18// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE19// USE OR OTHER DEALINGS IN THE SOFTWARE.2021module.exports = Stream;2223var EE = require('events').EventEmitter;24var inherits = require('inherits');2526inherits(Stream, EE);27Stream.Readable = require('readable-stream/readable.js');28Stream.Writable = require('readable-stream/writable.js');29Stream.Duplex = require('readable-stream/duplex.js');30Stream.Transform = require('readable-stream/transform.js');31Stream.PassThrough = require('readable-stream/passthrough.js');3233// Backwards-compat with node 0.4.x34Stream.Stream = Stream;35363738// old-style streams. Note that the pipe method (the only relevant39// part of this class) is overridden in the Readable class.4041function Stream() {42EE.call(this);43}4445Stream.prototype.pipe = function(dest, options) {46var source = this;4748function ondata(chunk) {49if (dest.writable) {50if (false === dest.write(chunk) && source.pause) {51source.pause();52}53}54}5556source.on('data', ondata);5758function ondrain() {59if (source.readable && source.resume) {60source.resume();61}62}6364dest.on('drain', ondrain);6566// If the 'end' option is not supplied, dest.end() will be called when67// source gets the 'end' or 'close' events. Only dest.end() once.68if (!dest._isStdio && (!options || options.end !== false)) {69source.on('end', onend);70source.on('close', onclose);71}7273var didOnEnd = false;74function onend() {75if (didOnEnd) return;76didOnEnd = true;7778dest.end();79}808182function onclose() {83if (didOnEnd) return;84didOnEnd = true;8586if (typeof dest.destroy === 'function') dest.destroy();87}8889// don't leave dangling pipes when there are errors.90function onerror(er) {91cleanup();92if (EE.listenerCount(this, 'error') === 0) {93throw er; // Unhandled stream error in pipe.94}95}9697source.on('error', onerror);98dest.on('error', onerror);99100// remove all the event listeners that were added.101function cleanup() {102source.removeListener('data', ondata);103dest.removeListener('drain', ondrain);104105source.removeListener('end', onend);106source.removeListener('close', onclose);107108source.removeListener('error', onerror);109dest.removeListener('error', onerror);110111source.removeListener('end', cleanup);112source.removeListener('close', cleanup);113114dest.removeListener('close', cleanup);115}116117source.on('end', cleanup);118source.on('close', cleanup);119120dest.on('close', cleanup);121122dest.emit('pipe', source);123124// Allow for unix-like usage: A.pipe(B).pipe(C)125return dest;126};127128129