• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1"use strict";
2var __importDefault = (this && this.__importDefault) || function (mod) {
3    return (mod && mod.__esModule) ? mod : { "default": mod };
4};
5Object.defineProperty(exports, "__esModule", { value: true });
6exports.Minipass = exports.isWritable = exports.isReadable = exports.isStream = void 0;
7const proc = typeof process === 'object' && process
8    ? process
9    : {
10        stdout: null,
11        stderr: null,
12    };
13const events_1 = require("events");
14const stream_1 = __importDefault(require("stream"));
15const string_decoder_1 = require("string_decoder");
16/**
17 * Return true if the argument is a Minipass stream, Node stream, or something
18 * else that Minipass can interact with.
19 */
20const isStream = (s) => !!s &&
21    typeof s === 'object' &&
22    (s instanceof Minipass ||
23        s instanceof stream_1.default ||
24        (0, exports.isReadable)(s) ||
25        (0, exports.isWritable)(s));
26exports.isStream = isStream;
27/**
28 * Return true if the argument is a valid {@link Minipass.Readable}
29 */
30const isReadable = (s) => !!s &&
31    typeof s === 'object' &&
32    s instanceof events_1.EventEmitter &&
33    typeof s.pipe === 'function' &&
34    // node core Writable streams have a pipe() method, but it throws
35    s.pipe !== stream_1.default.Writable.prototype.pipe;
36exports.isReadable = isReadable;
37/**
38 * Return true if the argument is a valid {@link Minipass.Writable}
39 */
40const isWritable = (s) => !!s &&
41    typeof s === 'object' &&
42    s instanceof events_1.EventEmitter &&
43    typeof s.write === 'function' &&
44    typeof s.end === 'function';
45exports.isWritable = isWritable;
46const EOF = Symbol('EOF');
47const MAYBE_EMIT_END = Symbol('maybeEmitEnd');
48const EMITTED_END = Symbol('emittedEnd');
49const EMITTING_END = Symbol('emittingEnd');
50const EMITTED_ERROR = Symbol('emittedError');
51const CLOSED = Symbol('closed');
52const READ = Symbol('read');
53const FLUSH = Symbol('flush');
54const FLUSHCHUNK = Symbol('flushChunk');
55const ENCODING = Symbol('encoding');
56const DECODER = Symbol('decoder');
57const FLOWING = Symbol('flowing');
58const PAUSED = Symbol('paused');
59const RESUME = Symbol('resume');
60const BUFFER = Symbol('buffer');
61const PIPES = Symbol('pipes');
62const BUFFERLENGTH = Symbol('bufferLength');
63const BUFFERPUSH = Symbol('bufferPush');
64const BUFFERSHIFT = Symbol('bufferShift');
65const OBJECTMODE = Symbol('objectMode');
66// internal event when stream is destroyed
67const DESTROYED = Symbol('destroyed');
68// internal event when stream has an error
69const ERROR = Symbol('error');
70const EMITDATA = Symbol('emitData');
71const EMITEND = Symbol('emitEnd');
72const EMITEND2 = Symbol('emitEnd2');
73const ASYNC = Symbol('async');
74const ABORT = Symbol('abort');
75const ABORTED = Symbol('aborted');
76const SIGNAL = Symbol('signal');
77const DATALISTENERS = Symbol('dataListeners');
78const DISCARDED = Symbol('discarded');
79const defer = (fn) => Promise.resolve().then(fn);
80const nodefer = (fn) => fn();
81const isEndish = (ev) => ev === 'end' || ev === 'finish' || ev === 'prefinish';
82const isArrayBufferLike = (b) => b instanceof ArrayBuffer ||
83    (!!b &&
84        typeof b === 'object' &&
85        b.constructor &&
86        b.constructor.name === 'ArrayBuffer' &&
87        b.byteLength >= 0);
88const isArrayBufferView = (b) => !Buffer.isBuffer(b) && ArrayBuffer.isView(b);
89/**
90 * Internal class representing a pipe to a destination stream.
91 *
92 * @internal
93 */
94class Pipe {
95    src;
96    dest;
97    opts;
98    ondrain;
99    constructor(src, dest, opts) {
100        this.src = src;
101        this.dest = dest;
102        this.opts = opts;
103        this.ondrain = () => src[RESUME]();
104        this.dest.on('drain', this.ondrain);
105    }
106    unpipe() {
107        this.dest.removeListener('drain', this.ondrain);
108    }
109    // only here for the prototype
110    /* c8 ignore start */
111    proxyErrors(_er) { }
112    /* c8 ignore stop */
113    end() {
114        this.unpipe();
115        if (this.opts.end)
116            this.dest.end();
117    }
118}
119/**
120 * Internal class representing a pipe to a destination stream where
121 * errors are proxied.
122 *
123 * @internal
124 */
125class PipeProxyErrors extends Pipe {
126    unpipe() {
127        this.src.removeListener('error', this.proxyErrors);
128        super.unpipe();
129    }
130    constructor(src, dest, opts) {
131        super(src, dest, opts);
132        this.proxyErrors = er => dest.emit('error', er);
133        src.on('error', this.proxyErrors);
134    }
135}
136const isObjectModeOptions = (o) => !!o.objectMode;
137const isEncodingOptions = (o) => !o.objectMode && !!o.encoding && o.encoding !== 'buffer';
138/**
139 * Main export, the Minipass class
140 *
141 * `RType` is the type of data emitted, defaults to Buffer
142 *
143 * `WType` is the type of data to be written, if RType is buffer or string,
144 * then any {@link Minipass.ContiguousData} is allowed.
145 *
146 * `Events` is the set of event handler signatures that this object
147 * will emit, see {@link Minipass.Events}
148 */
149class Minipass extends events_1.EventEmitter {
150    [FLOWING] = false;
151    [PAUSED] = false;
152    [PIPES] = [];
153    [BUFFER] = [];
154    [OBJECTMODE];
155    [ENCODING];
156    [ASYNC];
157    [DECODER];
158    [EOF] = false;
159    [EMITTED_END] = false;
160    [EMITTING_END] = false;
161    [CLOSED] = false;
162    [EMITTED_ERROR] = null;
163    [BUFFERLENGTH] = 0;
164    [DESTROYED] = false;
165    [SIGNAL];
166    [ABORTED] = false;
167    [DATALISTENERS] = 0;
168    [DISCARDED] = false;
169    /**
170     * true if the stream can be written
171     */
172    writable = true;
173    /**
174     * true if the stream can be read
175     */
176    readable = true;
177    /**
178     * If `RType` is Buffer, then options do not need to be provided.
179     * Otherwise, an options object must be provided to specify either
180     * {@link Minipass.SharedOptions.objectMode} or
181     * {@link Minipass.SharedOptions.encoding}, as appropriate.
182     */
183    constructor(...args) {
184        const options = (args[0] ||
185            {});
186        super();
187        if (options.objectMode && typeof options.encoding === 'string') {
188            throw new TypeError('Encoding and objectMode may not be used together');
189        }
190        if (isObjectModeOptions(options)) {
191            this[OBJECTMODE] = true;
192            this[ENCODING] = null;
193        }
194        else if (isEncodingOptions(options)) {
195            this[ENCODING] = options.encoding;
196            this[OBJECTMODE] = false;
197        }
198        else {
199            this[OBJECTMODE] = false;
200            this[ENCODING] = null;
201        }
202        this[ASYNC] = !!options.async;
203        this[DECODER] = this[ENCODING]
204            ? new string_decoder_1.StringDecoder(this[ENCODING])
205            : null;
206        //@ts-ignore - private option for debugging and testing
207        if (options && options.debugExposeBuffer === true) {
208            Object.defineProperty(this, 'buffer', { get: () => this[BUFFER] });
209        }
210        //@ts-ignore - private option for debugging and testing
211        if (options && options.debugExposePipes === true) {
212            Object.defineProperty(this, 'pipes', { get: () => this[PIPES] });
213        }
214        const { signal } = options;
215        if (signal) {
216            this[SIGNAL] = signal;
217            if (signal.aborted) {
218                this[ABORT]();
219            }
220            else {
221                signal.addEventListener('abort', () => this[ABORT]());
222            }
223        }
224    }
225    /**
226     * The amount of data stored in the buffer waiting to be read.
227     *
228     * For Buffer strings, this will be the total byte length.
229     * For string encoding streams, this will be the string character length,
230     * according to JavaScript's `string.length` logic.
231     * For objectMode streams, this is a count of the items waiting to be
232     * emitted.
233     */
234    get bufferLength() {
235        return this[BUFFERLENGTH];
236    }
237    /**
238     * The `BufferEncoding` currently in use, or `null`
239     */
240    get encoding() {
241        return this[ENCODING];
242    }
243    /**
244     * @deprecated - This is a read only property
245     */
246    set encoding(_enc) {
247        throw new Error('Encoding must be set at instantiation time');
248    }
249    /**
250     * @deprecated - Encoding may only be set at instantiation time
251     */
252    setEncoding(_enc) {
253        throw new Error('Encoding must be set at instantiation time');
254    }
255    /**
256     * True if this is an objectMode stream
257     */
258    get objectMode() {
259        return this[OBJECTMODE];
260    }
261    /**
262     * @deprecated - This is a read-only property
263     */
264    set objectMode(_om) {
265        throw new Error('objectMode must be set at instantiation time');
266    }
267    /**
268     * true if this is an async stream
269     */
270    get ['async']() {
271        return this[ASYNC];
272    }
273    /**
274     * Set to true to make this stream async.
275     *
276     * Once set, it cannot be unset, as this would potentially cause incorrect
277     * behavior.  Ie, a sync stream can be made async, but an async stream
278     * cannot be safely made sync.
279     */
280    set ['async'](a) {
281        this[ASYNC] = this[ASYNC] || !!a;
282    }
283    // drop everything and get out of the flow completely
284    [ABORT]() {
285        this[ABORTED] = true;
286        this.emit('abort', this[SIGNAL]?.reason);
287        this.destroy(this[SIGNAL]?.reason);
288    }
289    /**
290     * True if the stream has been aborted.
291     */
292    get aborted() {
293        return this[ABORTED];
294    }
295    /**
296     * No-op setter. Stream aborted status is set via the AbortSignal provided
297     * in the constructor options.
298     */
299    set aborted(_) { }
300    write(chunk, encoding, cb) {
301        if (this[ABORTED])
302            return false;
303        if (this[EOF])
304            throw new Error('write after end');
305        if (this[DESTROYED]) {
306            this.emit('error', Object.assign(new Error('Cannot call write after a stream was destroyed'), { code: 'ERR_STREAM_DESTROYED' }));
307            return true;
308        }
309        if (typeof encoding === 'function') {
310            cb = encoding;
311            encoding = 'utf8';
312        }
313        if (!encoding)
314            encoding = 'utf8';
315        const fn = this[ASYNC] ? defer : nodefer;
316        // convert array buffers and typed array views into buffers
317        // at some point in the future, we may want to do the opposite!
318        // leave strings and buffers as-is
319        // anything is only allowed if in object mode, so throw
320        if (!this[OBJECTMODE] && !Buffer.isBuffer(chunk)) {
321            if (isArrayBufferView(chunk)) {
322                //@ts-ignore - sinful unsafe type changing
323                chunk = Buffer.from(chunk.buffer, chunk.byteOffset, chunk.byteLength);
324            }
325            else if (isArrayBufferLike(chunk)) {
326                //@ts-ignore - sinful unsafe type changing
327                chunk = Buffer.from(chunk);
328            }
329            else if (typeof chunk !== 'string') {
330                throw new Error('Non-contiguous data written to non-objectMode stream');
331            }
332        }
333        // handle object mode up front, since it's simpler
334        // this yields better performance, fewer checks later.
335        if (this[OBJECTMODE]) {
336            // maybe impossible?
337            /* c8 ignore start */
338            if (this[FLOWING] && this[BUFFERLENGTH] !== 0)
339                this[FLUSH](true);
340            /* c8 ignore stop */
341            if (this[FLOWING])
342                this.emit('data', chunk);
343            else
344                this[BUFFERPUSH](chunk);
345            if (this[BUFFERLENGTH] !== 0)
346                this.emit('readable');
347            if (cb)
348                fn(cb);
349            return this[FLOWING];
350        }
351        // at this point the chunk is a buffer or string
352        // don't buffer it up or send it to the decoder
353        if (!chunk.length) {
354            if (this[BUFFERLENGTH] !== 0)
355                this.emit('readable');
356            if (cb)
357                fn(cb);
358            return this[FLOWING];
359        }
360        // fast-path writing strings of same encoding to a stream with
361        // an empty buffer, skipping the buffer/decoder dance
362        if (typeof chunk === 'string' &&
363            // unless it is a string already ready for us to use
364            !(encoding === this[ENCODING] && !this[DECODER]?.lastNeed)) {
365            //@ts-ignore - sinful unsafe type change
366            chunk = Buffer.from(chunk, encoding);
367        }
368        if (Buffer.isBuffer(chunk) && this[ENCODING]) {
369            //@ts-ignore - sinful unsafe type change
370            chunk = this[DECODER].write(chunk);
371        }
372        // Note: flushing CAN potentially switch us into not-flowing mode
373        if (this[FLOWING] && this[BUFFERLENGTH] !== 0)
374            this[FLUSH](true);
375        if (this[FLOWING])
376            this.emit('data', chunk);
377        else
378            this[BUFFERPUSH](chunk);
379        if (this[BUFFERLENGTH] !== 0)
380            this.emit('readable');
381        if (cb)
382            fn(cb);
383        return this[FLOWING];
384    }
385    /**
386     * Low-level explicit read method.
387     *
388     * In objectMode, the argument is ignored, and one item is returned if
389     * available.
390     *
391     * `n` is the number of bytes (or in the case of encoding streams,
392     * characters) to consume. If `n` is not provided, then the entire buffer
393     * is returned, or `null` is returned if no data is available.
394     *
395     * If `n` is greater that the amount of data in the internal buffer,
396     * then `null` is returned.
397     */
398    read(n) {
399        if (this[DESTROYED])
400            return null;
401        this[DISCARDED] = false;
402        if (this[BUFFERLENGTH] === 0 ||
403            n === 0 ||
404            (n && n > this[BUFFERLENGTH])) {
405            this[MAYBE_EMIT_END]();
406            return null;
407        }
408        if (this[OBJECTMODE])
409            n = null;
410        if (this[BUFFER].length > 1 && !this[OBJECTMODE]) {
411            // not object mode, so if we have an encoding, then RType is string
412            // otherwise, must be Buffer
413            this[BUFFER] = [
414                (this[ENCODING]
415                    ? this[BUFFER].join('')
416                    : Buffer.concat(this[BUFFER], this[BUFFERLENGTH])),
417            ];
418        }
419        const ret = this[READ](n || null, this[BUFFER][0]);
420        this[MAYBE_EMIT_END]();
421        return ret;
422    }
423    [READ](n, chunk) {
424        if (this[OBJECTMODE])
425            this[BUFFERSHIFT]();
426        else {
427            const c = chunk;
428            if (n === c.length || n === null)
429                this[BUFFERSHIFT]();
430            else if (typeof c === 'string') {
431                this[BUFFER][0] = c.slice(n);
432                chunk = c.slice(0, n);
433                this[BUFFERLENGTH] -= n;
434            }
435            else {
436                this[BUFFER][0] = c.subarray(n);
437                chunk = c.subarray(0, n);
438                this[BUFFERLENGTH] -= n;
439            }
440        }
441        this.emit('data', chunk);
442        if (!this[BUFFER].length && !this[EOF])
443            this.emit('drain');
444        return chunk;
445    }
446    end(chunk, encoding, cb) {
447        if (typeof chunk === 'function') {
448            cb = chunk;
449            chunk = undefined;
450        }
451        if (typeof encoding === 'function') {
452            cb = encoding;
453            encoding = 'utf8';
454        }
455        if (chunk !== undefined)
456            this.write(chunk, encoding);
457        if (cb)
458            this.once('end', cb);
459        this[EOF] = true;
460        this.writable = false;
461        // if we haven't written anything, then go ahead and emit,
462        // even if we're not reading.
463        // we'll re-emit if a new 'end' listener is added anyway.
464        // This makes MP more suitable to write-only use cases.
465        if (this[FLOWING] || !this[PAUSED])
466            this[MAYBE_EMIT_END]();
467        return this;
468    }
469    // don't let the internal resume be overwritten
470    [RESUME]() {
471        if (this[DESTROYED])
472            return;
473        if (!this[DATALISTENERS] && !this[PIPES].length) {
474            this[DISCARDED] = true;
475        }
476        this[PAUSED] = false;
477        this[FLOWING] = true;
478        this.emit('resume');
479        if (this[BUFFER].length)
480            this[FLUSH]();
481        else if (this[EOF])
482            this[MAYBE_EMIT_END]();
483        else
484            this.emit('drain');
485    }
486    /**
487     * Resume the stream if it is currently in a paused state
488     *
489     * If called when there are no pipe destinations or `data` event listeners,
490     * this will place the stream in a "discarded" state, where all data will
491     * be thrown away. The discarded state is removed if a pipe destination or
492     * data handler is added, if pause() is called, or if any synchronous or
493     * asynchronous iteration is started.
494     */
495    resume() {
496        return this[RESUME]();
497    }
498    /**
499     * Pause the stream
500     */
501    pause() {
502        this[FLOWING] = false;
503        this[PAUSED] = true;
504        this[DISCARDED] = false;
505    }
506    /**
507     * true if the stream has been forcibly destroyed
508     */
509    get destroyed() {
510        return this[DESTROYED];
511    }
512    /**
513     * true if the stream is currently in a flowing state, meaning that
514     * any writes will be immediately emitted.
515     */
516    get flowing() {
517        return this[FLOWING];
518    }
519    /**
520     * true if the stream is currently in a paused state
521     */
522    get paused() {
523        return this[PAUSED];
524    }
525    [BUFFERPUSH](chunk) {
526        if (this[OBJECTMODE])
527            this[BUFFERLENGTH] += 1;
528        else
529            this[BUFFERLENGTH] += chunk.length;
530        this[BUFFER].push(chunk);
531    }
532    [BUFFERSHIFT]() {
533        if (this[OBJECTMODE])
534            this[BUFFERLENGTH] -= 1;
535        else
536            this[BUFFERLENGTH] -= this[BUFFER][0].length;
537        return this[BUFFER].shift();
538    }
539    [FLUSH](noDrain = false) {
540        do { } while (this[FLUSHCHUNK](this[BUFFERSHIFT]()) &&
541            this[BUFFER].length);
542        if (!noDrain && !this[BUFFER].length && !this[EOF])
543            this.emit('drain');
544    }
545    [FLUSHCHUNK](chunk) {
546        this.emit('data', chunk);
547        return this[FLOWING];
548    }
549    /**
550     * Pipe all data emitted by this stream into the destination provided.
551     *
552     * Triggers the flow of data.
553     */
554    pipe(dest, opts) {
555        if (this[DESTROYED])
556            return dest;
557        this[DISCARDED] = false;
558        const ended = this[EMITTED_END];
559        opts = opts || {};
560        if (dest === proc.stdout || dest === proc.stderr)
561            opts.end = false;
562        else
563            opts.end = opts.end !== false;
564        opts.proxyErrors = !!opts.proxyErrors;
565        // piping an ended stream ends immediately
566        if (ended) {
567            if (opts.end)
568                dest.end();
569        }
570        else {
571            // "as" here just ignores the WType, which pipes don't care about,
572            // since they're only consuming from us, and writing to the dest
573            this[PIPES].push(!opts.proxyErrors
574                ? new Pipe(this, dest, opts)
575                : new PipeProxyErrors(this, dest, opts));
576            if (this[ASYNC])
577                defer(() => this[RESUME]());
578            else
579                this[RESUME]();
580        }
581        return dest;
582    }
583    /**
584     * Fully unhook a piped destination stream.
585     *
586     * If the destination stream was the only consumer of this stream (ie,
587     * there are no other piped destinations or `'data'` event listeners)
588     * then the flow of data will stop until there is another consumer or
589     * {@link Minipass#resume} is explicitly called.
590     */
591    unpipe(dest) {
592        const p = this[PIPES].find(p => p.dest === dest);
593        if (p) {
594            if (this[PIPES].length === 1) {
595                if (this[FLOWING] && this[DATALISTENERS] === 0) {
596                    this[FLOWING] = false;
597                }
598                this[PIPES] = [];
599            }
600            else
601                this[PIPES].splice(this[PIPES].indexOf(p), 1);
602            p.unpipe();
603        }
604    }
605    /**
606     * Alias for {@link Minipass#on}
607     */
608    addListener(ev, handler) {
609        return this.on(ev, handler);
610    }
611    /**
612     * Mostly identical to `EventEmitter.on`, with the following
613     * behavior differences to prevent data loss and unnecessary hangs:
614     *
615     * - Adding a 'data' event handler will trigger the flow of data
616     *
617     * - Adding a 'readable' event handler when there is data waiting to be read
618     *   will cause 'readable' to be emitted immediately.
619     *
620     * - Adding an 'endish' event handler ('end', 'finish', etc.) which has
621     *   already passed will cause the event to be emitted immediately and all
622     *   handlers removed.
623     *
624     * - Adding an 'error' event handler after an error has been emitted will
625     *   cause the event to be re-emitted immediately with the error previously
626     *   raised.
627     */
628    on(ev, handler) {
629        const ret = super.on(ev, handler);
630        if (ev === 'data') {
631            this[DISCARDED] = false;
632            this[DATALISTENERS]++;
633            if (!this[PIPES].length && !this[FLOWING]) {
634                this[RESUME]();
635            }
636        }
637        else if (ev === 'readable' && this[BUFFERLENGTH] !== 0) {
638            super.emit('readable');
639        }
640        else if (isEndish(ev) && this[EMITTED_END]) {
641            super.emit(ev);
642            this.removeAllListeners(ev);
643        }
644        else if (ev === 'error' && this[EMITTED_ERROR]) {
645            const h = handler;
646            if (this[ASYNC])
647                defer(() => h.call(this, this[EMITTED_ERROR]));
648            else
649                h.call(this, this[EMITTED_ERROR]);
650        }
651        return ret;
652    }
653    /**
654     * Alias for {@link Minipass#off}
655     */
656    removeListener(ev, handler) {
657        return this.off(ev, handler);
658    }
659    /**
660     * Mostly identical to `EventEmitter.off`
661     *
662     * If a 'data' event handler is removed, and it was the last consumer
663     * (ie, there are no pipe destinations or other 'data' event listeners),
664     * then the flow of data will stop until there is another consumer or
665     * {@link Minipass#resume} is explicitly called.
666     */
667    off(ev, handler) {
668        const ret = super.off(ev, handler);
669        // if we previously had listeners, and now we don't, and we don't
670        // have any pipes, then stop the flow, unless it's been explicitly
671        // put in a discarded flowing state via stream.resume().
672        if (ev === 'data') {
673            this[DATALISTENERS] = this.listeners('data').length;
674            if (this[DATALISTENERS] === 0 &&
675                !this[DISCARDED] &&
676                !this[PIPES].length) {
677                this[FLOWING] = false;
678            }
679        }
680        return ret;
681    }
682    /**
683     * Mostly identical to `EventEmitter.removeAllListeners`
684     *
685     * If all 'data' event handlers are removed, and they were the last consumer
686     * (ie, there are no pipe destinations), then the flow of data will stop
687     * until there is another consumer or {@link Minipass#resume} is explicitly
688     * called.
689     */
690    removeAllListeners(ev) {
691        const ret = super.removeAllListeners(ev);
692        if (ev === 'data' || ev === undefined) {
693            this[DATALISTENERS] = 0;
694            if (!this[DISCARDED] && !this[PIPES].length) {
695                this[FLOWING] = false;
696            }
697        }
698        return ret;
699    }
700    /**
701     * true if the 'end' event has been emitted
702     */
703    get emittedEnd() {
704        return this[EMITTED_END];
705    }
706    [MAYBE_EMIT_END]() {
707        if (!this[EMITTING_END] &&
708            !this[EMITTED_END] &&
709            !this[DESTROYED] &&
710            this[BUFFER].length === 0 &&
711            this[EOF]) {
712            this[EMITTING_END] = true;
713            this.emit('end');
714            this.emit('prefinish');
715            this.emit('finish');
716            if (this[CLOSED])
717                this.emit('close');
718            this[EMITTING_END] = false;
719        }
720    }
721    /**
722     * Mostly identical to `EventEmitter.emit`, with the following
723     * behavior differences to prevent data loss and unnecessary hangs:
724     *
725     * If the stream has been destroyed, and the event is something other
726     * than 'close' or 'error', then `false` is returned and no handlers
727     * are called.
728     *
729     * If the event is 'end', and has already been emitted, then the event
730     * is ignored. If the stream is in a paused or non-flowing state, then
731     * the event will be deferred until data flow resumes. If the stream is
732     * async, then handlers will be called on the next tick rather than
733     * immediately.
734     *
735     * If the event is 'close', and 'end' has not yet been emitted, then
736     * the event will be deferred until after 'end' is emitted.
737     *
738     * If the event is 'error', and an AbortSignal was provided for the stream,
739     * and there are no listeners, then the event is ignored, matching the
740     * behavior of node core streams in the presense of an AbortSignal.
741     *
742     * If the event is 'finish' or 'prefinish', then all listeners will be
743     * removed after emitting the event, to prevent double-firing.
744     */
745    emit(ev, ...args) {
746        const data = args[0];
747        // error and close are only events allowed after calling destroy()
748        if (ev !== 'error' &&
749            ev !== 'close' &&
750            ev !== DESTROYED &&
751            this[DESTROYED]) {
752            return false;
753        }
754        else if (ev === 'data') {
755            return !this[OBJECTMODE] && !data
756                ? false
757                : this[ASYNC]
758                    ? (defer(() => this[EMITDATA](data)), true)
759                    : this[EMITDATA](data);
760        }
761        else if (ev === 'end') {
762            return this[EMITEND]();
763        }
764        else if (ev === 'close') {
765            this[CLOSED] = true;
766            // don't emit close before 'end' and 'finish'
767            if (!this[EMITTED_END] && !this[DESTROYED])
768                return false;
769            const ret = super.emit('close');
770            this.removeAllListeners('close');
771            return ret;
772        }
773        else if (ev === 'error') {
774            this[EMITTED_ERROR] = data;
775            super.emit(ERROR, data);
776            const ret = !this[SIGNAL] || this.listeners('error').length
777                ? super.emit('error', data)
778                : false;
779            this[MAYBE_EMIT_END]();
780            return ret;
781        }
782        else if (ev === 'resume') {
783            const ret = super.emit('resume');
784            this[MAYBE_EMIT_END]();
785            return ret;
786        }
787        else if (ev === 'finish' || ev === 'prefinish') {
788            const ret = super.emit(ev);
789            this.removeAllListeners(ev);
790            return ret;
791        }
792        // Some other unknown event
793        const ret = super.emit(ev, ...args);
794        this[MAYBE_EMIT_END]();
795        return ret;
796    }
797    [EMITDATA](data) {
798        for (const p of this[PIPES]) {
799            if (p.dest.write(data) === false)
800                this.pause();
801        }
802        const ret = this[DISCARDED] ? false : super.emit('data', data);
803        this[MAYBE_EMIT_END]();
804        return ret;
805    }
806    [EMITEND]() {
807        if (this[EMITTED_END])
808            return false;
809        this[EMITTED_END] = true;
810        this.readable = false;
811        return this[ASYNC]
812            ? (defer(() => this[EMITEND2]()), true)
813            : this[EMITEND2]();
814    }
815    [EMITEND2]() {
816        if (this[DECODER]) {
817            const data = this[DECODER].end();
818            if (data) {
819                for (const p of this[PIPES]) {
820                    p.dest.write(data);
821                }
822                if (!this[DISCARDED])
823                    super.emit('data', data);
824            }
825        }
826        for (const p of this[PIPES]) {
827            p.end();
828        }
829        const ret = super.emit('end');
830        this.removeAllListeners('end');
831        return ret;
832    }
833    /**
834     * Return a Promise that resolves to an array of all emitted data once
835     * the stream ends.
836     */
837    async collect() {
838        const buf = Object.assign([], {
839            dataLength: 0,
840        });
841        if (!this[OBJECTMODE])
842            buf.dataLength = 0;
843        // set the promise first, in case an error is raised
844        // by triggering the flow here.
845        const p = this.promise();
846        this.on('data', c => {
847            buf.push(c);
848            if (!this[OBJECTMODE])
849                buf.dataLength += c.length;
850        });
851        await p;
852        return buf;
853    }
854    /**
855     * Return a Promise that resolves to the concatenation of all emitted data
856     * once the stream ends.
857     *
858     * Not allowed on objectMode streams.
859     */
860    async concat() {
861        if (this[OBJECTMODE]) {
862            throw new Error('cannot concat in objectMode');
863        }
864        const buf = await this.collect();
865        return (this[ENCODING]
866            ? buf.join('')
867            : Buffer.concat(buf, buf.dataLength));
868    }
869    /**
870     * Return a void Promise that resolves once the stream ends.
871     */
872    async promise() {
873        return new Promise((resolve, reject) => {
874            this.on(DESTROYED, () => reject(new Error('stream destroyed')));
875            this.on('error', er => reject(er));
876            this.on('end', () => resolve());
877        });
878    }
879    /**
880     * Asynchronous `for await of` iteration.
881     *
882     * This will continue emitting all chunks until the stream terminates.
883     */
884    [Symbol.asyncIterator]() {
885        // set this up front, in case the consumer doesn't call next()
886        // right away.
887        this[DISCARDED] = false;
888        let stopped = false;
889        const stop = async () => {
890            this.pause();
891            stopped = true;
892            return { value: undefined, done: true };
893        };
894        const next = () => {
895            if (stopped)
896                return stop();
897            const res = this.read();
898            if (res !== null)
899                return Promise.resolve({ done: false, value: res });
900            if (this[EOF])
901                return stop();
902            let resolve;
903            let reject;
904            const onerr = (er) => {
905                this.off('data', ondata);
906                this.off('end', onend);
907                this.off(DESTROYED, ondestroy);
908                stop();
909                reject(er);
910            };
911            const ondata = (value) => {
912                this.off('error', onerr);
913                this.off('end', onend);
914                this.off(DESTROYED, ondestroy);
915                this.pause();
916                resolve({ value, done: !!this[EOF] });
917            };
918            const onend = () => {
919                this.off('error', onerr);
920                this.off('data', ondata);
921                this.off(DESTROYED, ondestroy);
922                stop();
923                resolve({ done: true, value: undefined });
924            };
925            const ondestroy = () => onerr(new Error('stream destroyed'));
926            return new Promise((res, rej) => {
927                reject = rej;
928                resolve = res;
929                this.once(DESTROYED, ondestroy);
930                this.once('error', onerr);
931                this.once('end', onend);
932                this.once('data', ondata);
933            });
934        };
935        return {
936            next,
937            throw: stop,
938            return: stop,
939            [Symbol.asyncIterator]() {
940                return this;
941            },
942        };
943    }
944    /**
945     * Synchronous `for of` iteration.
946     *
947     * The iteration will terminate when the internal buffer runs out, even
948     * if the stream has not yet terminated.
949     */
950    [Symbol.iterator]() {
951        // set this up front, in case the consumer doesn't call next()
952        // right away.
953        this[DISCARDED] = false;
954        let stopped = false;
955        const stop = () => {
956            this.pause();
957            this.off(ERROR, stop);
958            this.off(DESTROYED, stop);
959            this.off('end', stop);
960            stopped = true;
961            return { done: true, value: undefined };
962        };
963        const next = () => {
964            if (stopped)
965                return stop();
966            const value = this.read();
967            return value === null ? stop() : { done: false, value };
968        };
969        this.once('end', stop);
970        this.once(ERROR, stop);
971        this.once(DESTROYED, stop);
972        return {
973            next,
974            throw: stop,
975            return: stop,
976            [Symbol.iterator]() {
977                return this;
978            },
979        };
980    }
981    /**
982     * Destroy a stream, preventing it from being used for any further purpose.
983     *
984     * If the stream has a `close()` method, then it will be called on
985     * destruction.
986     *
987     * After destruction, any attempt to write data, read data, or emit most
988     * events will be ignored.
989     *
990     * If an error argument is provided, then it will be emitted in an
991     * 'error' event.
992     */
993    destroy(er) {
994        if (this[DESTROYED]) {
995            if (er)
996                this.emit('error', er);
997            else
998                this.emit(DESTROYED);
999            return this;
1000        }
1001        this[DESTROYED] = true;
1002        this[DISCARDED] = true;
1003        // throw away all buffered data, it's never coming out
1004        this[BUFFER].length = 0;
1005        this[BUFFERLENGTH] = 0;
1006        const wc = this;
1007        if (typeof wc.close === 'function' && !this[CLOSED])
1008            wc.close();
1009        if (er)
1010            this.emit('error', er);
1011        // if no error to emit, still reject pending promises
1012        else
1013            this.emit(DESTROYED);
1014        return this;
1015    }
1016    /**
1017     * Alias for {@link isStream}
1018     *
1019     * Former export location, maintained for backwards compatibility.
1020     *
1021     * @deprecated
1022     */
1023    static get isStream() {
1024        return exports.isStream;
1025    }
1026}
1027exports.Minipass = Minipass;
1028//# sourceMappingURL=index.js.map