| /*! | 
|  * destroy | 
|  * Copyright(c) 2014 Jonathan Ong | 
|  * Copyright(c) 2015-2022 Douglas Christopher Wilson | 
|  * MIT Licensed | 
|  */ | 
|   | 
| 'use strict' | 
|   | 
| /** | 
|  * 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() | 
|   } | 
| } |