index.js 33 KB

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