index.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. // Copyright Joyent, Inc. and other Node contributors.
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining a
  4. // copy of this software and associated documentation files (the
  5. // "Software"), to deal in the Software without restriction, including
  6. // without limitation the rights to use, copy, modify, merge, publish,
  7. // distribute, sublicense, and/or sell copies of the Software, and to permit
  8. // persons to whom the Software is furnished to do so, subject to the
  9. // following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included
  12. // in all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  15. // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  16. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  17. // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  18. // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  19. // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  20. // USE OR OTHER DEALINGS IN THE SOFTWARE.
  21. module.exports = Stream;
  22. var EE = require('events').EventEmitter;
  23. var inherits = require('inherits');
  24. inherits(Stream, EE);
  25. Stream.Readable = require('readable-stream/lib/_stream_readable.js');
  26. Stream.Writable = require('readable-stream/lib/_stream_writable.js');
  27. Stream.Duplex = require('readable-stream/lib/_stream_duplex.js');
  28. Stream.Transform = require('readable-stream/lib/_stream_transform.js');
  29. Stream.PassThrough = require('readable-stream/lib/_stream_passthrough.js');
  30. Stream.finished = require('readable-stream/lib/internal/streams/end-of-stream.js')
  31. Stream.pipeline = require('readable-stream/lib/internal/streams/pipeline.js')
  32. // Backwards-compat with node 0.4.x
  33. Stream.Stream = Stream;
  34. // old-style streams. Note that the pipe method (the only relevant
  35. // part of this class) is overridden in the Readable class.
  36. function Stream() {
  37. EE.call(this);
  38. }
  39. Stream.prototype.pipe = function(dest, options) {
  40. var source = this;
  41. function ondata(chunk) {
  42. if (dest.writable) {
  43. if (false === dest.write(chunk) && source.pause) {
  44. source.pause();
  45. }
  46. }
  47. }
  48. source.on('data', ondata);
  49. function ondrain() {
  50. if (source.readable && source.resume) {
  51. source.resume();
  52. }
  53. }
  54. dest.on('drain', ondrain);
  55. // If the 'end' option is not supplied, dest.end() will be called when
  56. // source gets the 'end' or 'close' events. Only dest.end() once.
  57. if (!dest._isStdio && (!options || options.end !== false)) {
  58. source.on('end', onend);
  59. source.on('close', onclose);
  60. }
  61. var didOnEnd = false;
  62. function onend() {
  63. if (didOnEnd) return;
  64. didOnEnd = true;
  65. dest.end();
  66. }
  67. function onclose() {
  68. if (didOnEnd) return;
  69. didOnEnd = true;
  70. if (typeof dest.destroy === 'function') dest.destroy();
  71. }
  72. // don't leave dangling pipes when there are errors.
  73. function onerror(er) {
  74. cleanup();
  75. if (EE.listenerCount(this, 'error') === 0) {
  76. throw er; // Unhandled stream error in pipe.
  77. }
  78. }
  79. source.on('error', onerror);
  80. dest.on('error', onerror);
  81. // remove all the event listeners that were added.
  82. function cleanup() {
  83. source.removeListener('data', ondata);
  84. dest.removeListener('drain', ondrain);
  85. source.removeListener('end', onend);
  86. source.removeListener('close', onclose);
  87. source.removeListener('error', onerror);
  88. dest.removeListener('error', onerror);
  89. source.removeListener('end', cleanup);
  90. source.removeListener('close', cleanup);
  91. dest.removeListener('close', cleanup);
  92. }
  93. source.on('end', cleanup);
  94. source.on('close', cleanup);
  95. dest.on('close', cleanup);
  96. dest.emit('pipe', source);
  97. // Allow for unix-like usage: A.pipe(B).pipe(C)
  98. return dest;
  99. };