• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Ported from https://github.com/mafintosh/end-of-stream with
2// permission from the author, Mathias Buus (@mafintosh).
3
4'use strict';
5
6var ERR_STREAM_PREMATURE_CLOSE = require('../../../errors').codes.ERR_STREAM_PREMATURE_CLOSE;
7function once(callback) {
8  var called = false;
9  return function () {
10    if (called) return;
11    called = true;
12    for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
13      args[_key] = arguments[_key];
14    }
15    callback.apply(this, args);
16  };
17}
18function noop() {}
19function isRequest(stream) {
20  return stream.setHeader && typeof stream.abort === 'function';
21}
22function eos(stream, opts, callback) {
23  if (typeof opts === 'function') return eos(stream, null, opts);
24  if (!opts) opts = {};
25  callback = once(callback || noop);
26  var readable = opts.readable || opts.readable !== false && stream.readable;
27  var writable = opts.writable || opts.writable !== false && stream.writable;
28  var onlegacyfinish = function onlegacyfinish() {
29    if (!stream.writable) onfinish();
30  };
31  var writableEnded = stream._writableState && stream._writableState.finished;
32  var onfinish = function onfinish() {
33    writable = false;
34    writableEnded = true;
35    if (!readable) callback.call(stream);
36  };
37  var readableEnded = stream._readableState && stream._readableState.endEmitted;
38  var onend = function onend() {
39    readable = false;
40    readableEnded = true;
41    if (!writable) callback.call(stream);
42  };
43  var onerror = function onerror(err) {
44    callback.call(stream, err);
45  };
46  var onclose = function onclose() {
47    var err;
48    if (readable && !readableEnded) {
49      if (!stream._readableState || !stream._readableState.ended) err = new ERR_STREAM_PREMATURE_CLOSE();
50      return callback.call(stream, err);
51    }
52    if (writable && !writableEnded) {
53      if (!stream._writableState || !stream._writableState.ended) err = new ERR_STREAM_PREMATURE_CLOSE();
54      return callback.call(stream, err);
55    }
56  };
57  var onrequest = function onrequest() {
58    stream.req.on('finish', onfinish);
59  };
60  if (isRequest(stream)) {
61    stream.on('complete', onfinish);
62    stream.on('abort', onclose);
63    if (stream.req) onrequest();else stream.on('request', onrequest);
64  } else if (writable && !stream._writableState) {
65    // legacy streams
66    stream.on('end', onlegacyfinish);
67    stream.on('close', onlegacyfinish);
68  }
69  stream.on('end', onend);
70  stream.on('finish', onfinish);
71  if (opts.error !== false) stream.on('error', onerror);
72  stream.on('close', onclose);
73  return function () {
74    stream.removeListener('complete', onfinish);
75    stream.removeListener('abort', onclose);
76    stream.removeListener('request', onrequest);
77    if (stream.req) stream.req.removeListener('finish', onfinish);
78    stream.removeListener('end', onlegacyfinish);
79    stream.removeListener('close', onlegacyfinish);
80    stream.removeListener('finish', onfinish);
81    stream.removeListener('end', onend);
82    stream.removeListener('error', onerror);
83    stream.removeListener('close', onclose);
84  };
85}
86module.exports = eos;