Spaces:
Running
Running
/*! | |
* destroy | |
* Copyright(c) 2014 Jonathan Ong | |
* Copyright(c) 2015-2022 Douglas Christopher Wilson | |
* MIT Licensed | |
*/ | |
/** | |
* Module dependencies. | |
* @private | |
*/ | |
var EventEmitter = require('events').EventEmitter | |
var ReadStream = require('fs').ReadStream | |
var Stream = require('stream') | |
var Zlib = require('zlib') | |
/** | |
* Module exports. | |
* @public | |
*/ | |
module.exports = destroy | |
/** | |
* Destroy the given stream, and optionally suppress any future `error` events. | |
* | |
* @param {object} stream | |
* @param {boolean} suppress | |
* @public | |
*/ | |
function destroy (stream, suppress) { | |
if (isFsReadStream(stream)) { | |
destroyReadStream(stream) | |
} else if (isZlibStream(stream)) { | |
destroyZlibStream(stream) | |
} else if (hasDestroy(stream)) { | |
stream.destroy() | |
} | |
if (isEventEmitter(stream) && suppress) { | |
stream.removeAllListeners('error') | |
stream.addListener('error', noop) | |
} | |
return stream | |
} | |
/** | |
* Destroy a ReadStream. | |
* | |
* @param {object} stream | |
* @private | |
*/ | |
function destroyReadStream (stream) { | |
stream.destroy() | |
if (typeof stream.close === 'function') { | |
// node.js core bug work-around | |
stream.on('open', onOpenClose) | |
} | |
} | |
/** | |
* Close a Zlib stream. | |
* | |
* Zlib streams below Node.js 4.5.5 have a buggy implementation | |
* of .close() when zlib encountered an error. | |
* | |
* @param {object} stream | |
* @private | |
*/ | |
function closeZlibStream (stream) { | |
if (stream._hadError === true) { | |
var prop = stream._binding === null | |
? '_binding' | |
: '_handle' | |
stream[prop] = { | |
close: function () { this[prop] = null } | |
} | |
} | |
stream.close() | |
} | |
/** | |
* Destroy a Zlib stream. | |
* | |
* Zlib streams don't have a destroy function in Node.js 6. On top of that | |
* simply calling destroy on a zlib stream in Node.js 8+ will result in a | |
* memory leak. So until that is fixed, we need to call both close AND destroy. | |
* | |
* PR to fix memory leak: https://github.com/nodejs/node/pull/23734 | |
* | |
* In Node.js 6+8, it's important that destroy is called before close as the | |
* stream would otherwise emit the error 'zlib binding closed'. | |
* | |
* @param {object} stream | |
* @private | |
*/ | |
function destroyZlibStream (stream) { | |
if (typeof stream.destroy === 'function') { | |
// node.js core bug work-around | |
// istanbul ignore if: node.js 0.8 | |
if (stream._binding) { | |
// node.js < 0.10.0 | |
stream.destroy() | |
if (stream._processing) { | |
stream._needDrain = true | |
stream.once('drain', onDrainClearBinding) | |
} else { | |
stream._binding.clear() | |
} | |
} else if (stream._destroy && stream._destroy !== Stream.Transform.prototype._destroy) { | |
// node.js >= 12, ^11.1.0, ^10.15.1 | |
stream.destroy() | |
} else if (stream._destroy && typeof stream.close === 'function') { | |
// node.js 7, 8 | |
stream.destroyed = true | |
stream.close() | |
} else { | |
// fallback | |
// istanbul ignore next | |
stream.destroy() | |
} | |
} else if (typeof stream.close === 'function') { | |
// node.js < 8 fallback | |
closeZlibStream(stream) | |
} | |
} | |
/** | |
* Determine if stream has destroy. | |
* @private | |
*/ | |
function hasDestroy (stream) { | |
return stream instanceof Stream && | |
typeof stream.destroy === 'function' | |
} | |
/** | |
* Determine if val is EventEmitter. | |
* @private | |
*/ | |
function isEventEmitter (val) { | |
return val instanceof EventEmitter | |
} | |
/** | |
* Determine if stream is fs.ReadStream stream. | |
* @private | |
*/ | |
function isFsReadStream (stream) { | |
return stream instanceof ReadStream | |
} | |
/** | |
* Determine if stream is Zlib stream. | |
* @private | |
*/ | |
function isZlibStream (stream) { | |
return stream instanceof Zlib.Gzip || | |
stream instanceof Zlib.Gunzip || | |
stream instanceof Zlib.Deflate || | |
stream instanceof Zlib.DeflateRaw || | |
stream instanceof Zlib.Inflate || | |
stream instanceof Zlib.InflateRaw || | |
stream instanceof Zlib.Unzip | |
} | |
/** | |
* No-op function. | |
* @private | |
*/ | |
function noop () {} | |
/** | |
* On drain handler to clear binding. | |
* @private | |
*/ | |
// istanbul ignore next: node.js 0.8 | |
function onDrainClearBinding () { | |
this._binding.clear() | |
} | |
/** | |
* On open handler to close stream. | |
* @private | |
*/ | |
function onOpenClose () { | |
if (typeof this.fd === 'number') { | |
// actually close down the fd | |
this.close() | |
} | |
} | |