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;