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