• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright Joyent, Inc. and other Node contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a
4// copy of this software and associated documentation files (the
5// "Software"), to deal in the Software without restriction, including
6// without limitation the rights to use, copy, modify, merge, publish,
7// distribute, sublicense, and/or sell copies of the Software, and to permit
8// persons to whom the Software is furnished to do so, subject to the
9// following conditions:
10//
11// The above copyright notice and this permission notice shall be included
12// in all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20// USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22'use strict';
23
24const {
25  ArrayPrototypeJoin,
26  ArrayPrototypeShift,
27  ArrayPrototypeSlice,
28  ArrayPrototypeSplice,
29  ArrayPrototypeUnshift,
30  Boolean,
31  Error,
32  ErrorCaptureStackTrace,
33  FunctionPrototypeBind,
34  FunctionPrototypeCall,
35  NumberIsNaN,
36  ObjectCreate,
37  ObjectDefineProperty,
38  ObjectDefineProperties,
39  ObjectGetPrototypeOf,
40  ObjectSetPrototypeOf,
41  Promise,
42  PromiseReject,
43  PromiseResolve,
44  ReflectApply,
45  ReflectOwnKeys,
46  String,
47  StringPrototypeSplit,
48  Symbol,
49  SymbolFor,
50  SymbolAsyncIterator,
51  SymbolDispose,
52} = primordials;
53const kRejection = SymbolFor('nodejs.rejection');
54
55const { kEmptyObject } = require('internal/util');
56
57const {
58  inspect,
59  identicalSequenceRange,
60} = require('internal/util/inspect');
61
62let spliceOne;
63let kResistStopPropagation;
64
65const {
66  AbortError,
67  kEnhanceStackBeforeInspector,
68  codes: {
69    ERR_INVALID_ARG_TYPE,
70    ERR_INVALID_THIS,
71    ERR_OUT_OF_RANGE,
72    ERR_UNHANDLED_ERROR,
73  },
74  genericNodeError,
75} = require('internal/errors');
76
77const {
78  validateAbortSignal,
79  validateBoolean,
80  validateFunction,
81  validateString,
82} = require('internal/validators');
83
84const kCapture = Symbol('kCapture');
85const kErrorMonitor = Symbol('events.errorMonitor');
86const kMaxEventTargetListeners = Symbol('events.maxEventTargetListeners');
87const kMaxEventTargetListenersWarned =
88  Symbol('events.maxEventTargetListenersWarned');
89
90let EventEmitterAsyncResource;
91// The EventEmitterAsyncResource has to be initialized lazily because event.js
92// is loaded so early in the bootstrap process, before async_hooks is available.
93//
94// This implementation was adapted straight from addaleax's
95// eventemitter-asyncresource MIT-licensed userland module.
96// https://github.com/addaleax/eventemitter-asyncresource
97function lazyEventEmitterAsyncResource() {
98  if (EventEmitterAsyncResource === undefined) {
99    const {
100      AsyncResource,
101    } = require('async_hooks');
102
103    const kEventEmitter = Symbol('kEventEmitter');
104    const kAsyncResource = Symbol('kAsyncResource');
105    class EventEmitterReferencingAsyncResource extends AsyncResource {
106      /**
107       * @param {EventEmitter} ee
108       * @param {string} [type]
109       * @param {{
110       *   triggerAsyncId?: number,
111       *   requireManualDestroy?: boolean,
112       * }} [options]
113       */
114      constructor(ee, type, options) {
115        super(type, options);
116        this[kEventEmitter] = ee;
117      }
118
119      /**
120       * @type {EventEmitter}
121       */
122      get eventEmitter() {
123        if (this[kEventEmitter] === undefined)
124          throw new ERR_INVALID_THIS('EventEmitterReferencingAsyncResource');
125        return this[kEventEmitter];
126      }
127    }
128
129    EventEmitterAsyncResource =
130      class EventEmitterAsyncResource extends EventEmitter {
131        /**
132         * @param {{
133         *   name?: string,
134         *   triggerAsyncId?: number,
135         *   requireManualDestroy?: boolean,
136         * }} [options]
137         */
138        constructor(options = undefined) {
139          let name;
140          if (typeof options === 'string') {
141            name = options;
142            options = undefined;
143          } else {
144            if (new.target === EventEmitterAsyncResource) {
145              validateString(options?.name, 'options.name');
146            }
147            name = options?.name || new.target.name;
148          }
149          super(options);
150
151          this[kAsyncResource] =
152            new EventEmitterReferencingAsyncResource(this, name, options);
153        }
154
155        /**
156         * @param {symbol,string} event
157         * @param  {...any} args
158         * @returns {boolean}
159         */
160        emit(event, ...args) {
161          if (this[kAsyncResource] === undefined)
162            throw new ERR_INVALID_THIS('EventEmitterAsyncResource');
163          const { asyncResource } = this;
164          ArrayPrototypeUnshift(args, super.emit, this, event);
165          return ReflectApply(asyncResource.runInAsyncScope, asyncResource,
166                              args);
167        }
168
169        /**
170         * @returns {void}
171         */
172        emitDestroy() {
173          if (this[kAsyncResource] === undefined)
174            throw new ERR_INVALID_THIS('EventEmitterAsyncResource');
175          this.asyncResource.emitDestroy();
176        }
177
178        /**
179         * @type {number}
180         */
181        get asyncId() {
182          if (this[kAsyncResource] === undefined)
183            throw new ERR_INVALID_THIS('EventEmitterAsyncResource');
184          return this.asyncResource.asyncId();
185        }
186
187        /**
188         * @type {number}
189         */
190        get triggerAsyncId() {
191          if (this[kAsyncResource] === undefined)
192            throw new ERR_INVALID_THIS('EventEmitterAsyncResource');
193          return this.asyncResource.triggerAsyncId();
194        }
195
196        /**
197         * @type {EventEmitterReferencingAsyncResource}
198         */
199        get asyncResource() {
200          if (this[kAsyncResource] === undefined)
201            throw new ERR_INVALID_THIS('EventEmitterAsyncResource');
202          return this[kAsyncResource];
203        }
204      };
205  }
206  return EventEmitterAsyncResource;
207}
208
209/**
210 * Creates a new `EventEmitter` instance.
211 * @param {{ captureRejections?: boolean; }} [opts]
212 * @constructs {EventEmitter}
213 */
214function EventEmitter(opts) {
215  EventEmitter.init.call(this, opts);
216}
217module.exports = EventEmitter;
218module.exports.addAbortListener = addAbortListener;
219module.exports.once = once;
220module.exports.on = on;
221module.exports.getEventListeners = getEventListeners;
222module.exports.getMaxListeners = getMaxListeners;
223// Backwards-compat with node 0.10.x
224EventEmitter.EventEmitter = EventEmitter;
225
226EventEmitter.usingDomains = false;
227
228EventEmitter.captureRejectionSymbol = kRejection;
229ObjectDefineProperty(EventEmitter, 'captureRejections', {
230  __proto__: null,
231  get() {
232    return EventEmitter.prototype[kCapture];
233  },
234  set(value) {
235    validateBoolean(value, 'EventEmitter.captureRejections');
236
237    EventEmitter.prototype[kCapture] = value;
238  },
239  enumerable: true,
240});
241
242ObjectDefineProperty(EventEmitter, 'EventEmitterAsyncResource', {
243  __proto__: null,
244  enumerable: true,
245  get: lazyEventEmitterAsyncResource,
246  set: undefined,
247  configurable: true,
248});
249
250EventEmitter.errorMonitor = kErrorMonitor;
251
252// The default for captureRejections is false
253ObjectDefineProperty(EventEmitter.prototype, kCapture, {
254  __proto__: null,
255  value: false,
256  writable: true,
257  enumerable: false,
258});
259
260EventEmitter.prototype._events = undefined;
261EventEmitter.prototype._eventsCount = 0;
262EventEmitter.prototype._maxListeners = undefined;
263
264// By default EventEmitters will print a warning if more than 10 listeners are
265// added to it. This is a useful default which helps finding memory leaks.
266let defaultMaxListeners = 10;
267let isEventTarget;
268
269function checkListener(listener) {
270  validateFunction(listener, 'listener');
271}
272
273ObjectDefineProperty(EventEmitter, 'defaultMaxListeners', {
274  __proto__: null,
275  enumerable: true,
276  get: function() {
277    return defaultMaxListeners;
278  },
279  set: function(arg) {
280    if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) {
281      throw new ERR_OUT_OF_RANGE('defaultMaxListeners',
282                                 'a non-negative number',
283                                 arg);
284    }
285    defaultMaxListeners = arg;
286  },
287});
288
289ObjectDefineProperties(EventEmitter, {
290  kMaxEventTargetListeners: {
291    __proto__: null,
292    value: kMaxEventTargetListeners,
293    enumerable: false,
294    configurable: false,
295    writable: false,
296  },
297  kMaxEventTargetListenersWarned: {
298    __proto__: null,
299    value: kMaxEventTargetListenersWarned,
300    enumerable: false,
301    configurable: false,
302    writable: false,
303  },
304});
305
306/**
307 * Sets the max listeners.
308 * @param {number} n
309 * @param {EventTarget[] | EventEmitter[]} [eventTargets]
310 * @returns {void}
311 */
312EventEmitter.setMaxListeners =
313  function(n = defaultMaxListeners, ...eventTargets) {
314    if (typeof n !== 'number' || n < 0 || NumberIsNaN(n))
315      throw new ERR_OUT_OF_RANGE('n', 'a non-negative number', n);
316    if (eventTargets.length === 0) {
317      defaultMaxListeners = n;
318    } else {
319      if (isEventTarget === undefined)
320        isEventTarget = require('internal/event_target').isEventTarget;
321
322      for (let i = 0; i < eventTargets.length; i++) {
323        const target = eventTargets[i];
324        if (isEventTarget(target)) {
325          target[kMaxEventTargetListeners] = n;
326          target[kMaxEventTargetListenersWarned] = false;
327        } else if (typeof target.setMaxListeners === 'function') {
328          target.setMaxListeners(n);
329        } else {
330          throw new ERR_INVALID_ARG_TYPE(
331            'eventTargets',
332            ['EventEmitter', 'EventTarget'],
333            target);
334        }
335      }
336    }
337  };
338
339// If you're updating this function definition, please also update any
340// re-definitions, such as the one in the Domain module (lib/domain.js).
341EventEmitter.init = function(opts) {
342
343  if (this._events === undefined ||
344      this._events === ObjectGetPrototypeOf(this)._events) {
345    this._events = ObjectCreate(null);
346    this._eventsCount = 0;
347  }
348
349  this._maxListeners = this._maxListeners || undefined;
350
351
352  if (opts?.captureRejections) {
353    validateBoolean(opts.captureRejections, 'options.captureRejections');
354    this[kCapture] = Boolean(opts.captureRejections);
355  } else {
356    // Assigning the kCapture property directly saves an expensive
357    // prototype lookup in a very sensitive hot path.
358    this[kCapture] = EventEmitter.prototype[kCapture];
359  }
360};
361
362function addCatch(that, promise, type, args) {
363  if (!that[kCapture]) {
364    return;
365  }
366
367  // Handle Promises/A+ spec, then could be a getter
368  // that throws on second use.
369  try {
370    const then = promise.then;
371
372    if (typeof then === 'function') {
373      then.call(promise, undefined, function(err) {
374        // The callback is called with nextTick to avoid a follow-up
375        // rejection from this promise.
376        process.nextTick(emitUnhandledRejectionOrErr, that, err, type, args);
377      });
378    }
379  } catch (err) {
380    that.emit('error', err);
381  }
382}
383
384function emitUnhandledRejectionOrErr(ee, err, type, args) {
385  if (typeof ee[kRejection] === 'function') {
386    ee[kRejection](err, type, ...args);
387  } else {
388    // We have to disable the capture rejections mechanism, otherwise
389    // we might end up in an infinite loop.
390    const prev = ee[kCapture];
391
392    // If the error handler throws, it is not catchable and it
393    // will end up in 'uncaughtException'. We restore the previous
394    // value of kCapture in case the uncaughtException is present
395    // and the exception is handled.
396    try {
397      ee[kCapture] = false;
398      ee.emit('error', err);
399    } finally {
400      ee[kCapture] = prev;
401    }
402  }
403}
404
405/**
406 * Increases the max listeners of the event emitter.
407 * @param {number} n
408 * @returns {EventEmitter}
409 */
410EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {
411  if (typeof n !== 'number' || n < 0 || NumberIsNaN(n)) {
412    throw new ERR_OUT_OF_RANGE('n', 'a non-negative number', n);
413  }
414  this._maxListeners = n;
415  return this;
416};
417
418function _getMaxListeners(that) {
419  if (that._maxListeners === undefined)
420    return EventEmitter.defaultMaxListeners;
421  return that._maxListeners;
422}
423
424/**
425 * Returns the current max listener value for the event emitter.
426 * @returns {number}
427 */
428EventEmitter.prototype.getMaxListeners = function getMaxListeners() {
429  return _getMaxListeners(this);
430};
431
432function enhanceStackTrace(err, own) {
433  let ctorInfo = '';
434  try {
435    const { name } = this.constructor;
436    if (name !== 'EventEmitter')
437      ctorInfo = ` on ${name} instance`;
438  } catch {
439    // Continue regardless of error.
440  }
441  const sep = `\nEmitted 'error' event${ctorInfo} at:\n`;
442
443  const errStack = ArrayPrototypeSlice(
444    StringPrototypeSplit(err.stack, '\n'), 1);
445  const ownStack = ArrayPrototypeSlice(
446    StringPrototypeSplit(own.stack, '\n'), 1);
447
448  const { len, offset } = identicalSequenceRange(ownStack, errStack);
449  if (len > 0) {
450    ArrayPrototypeSplice(ownStack, offset + 1, len - 2,
451                         '    [... lines matching original stack trace ...]');
452  }
453
454  return err.stack + sep + ArrayPrototypeJoin(ownStack, '\n');
455}
456
457/**
458 * Synchronously calls each of the listeners registered
459 * for the event.
460 * @param {string | symbol} type
461 * @param {...any} [args]
462 * @returns {boolean}
463 */
464EventEmitter.prototype.emit = function emit(type, ...args) {
465  let doError = (type === 'error');
466
467  const events = this._events;
468  if (events !== undefined) {
469    if (doError && events[kErrorMonitor] !== undefined)
470      this.emit(kErrorMonitor, ...args);
471    doError = (doError && events.error === undefined);
472  } else if (!doError)
473    return false;
474
475  // If there is no 'error' event listener then throw.
476  if (doError) {
477    let er;
478    if (args.length > 0)
479      er = args[0];
480    if (er instanceof Error) {
481      try {
482        const capture = {};
483        ErrorCaptureStackTrace(capture, EventEmitter.prototype.emit);
484        ObjectDefineProperty(er, kEnhanceStackBeforeInspector, {
485          __proto__: null,
486          value: FunctionPrototypeBind(enhanceStackTrace, this, er, capture),
487          configurable: true,
488        });
489      } catch {
490        // Continue regardless of error.
491      }
492
493      // Note: The comments on the `throw` lines are intentional, they show
494      // up in Node's output if this results in an unhandled exception.
495      throw er; // Unhandled 'error' event
496    }
497
498    let stringifiedEr;
499    try {
500      stringifiedEr = inspect(er);
501    } catch {
502      stringifiedEr = er;
503    }
504
505    // At least give some kind of context to the user
506    const err = new ERR_UNHANDLED_ERROR(stringifiedEr);
507    err.context = er;
508    throw err; // Unhandled 'error' event
509  }
510
511  const handler = events[type];
512
513  if (handler === undefined)
514    return false;
515
516  if (typeof handler === 'function') {
517    const result = handler.apply(this, args);
518
519    // We check if result is undefined first because that
520    // is the most common case so we do not pay any perf
521    // penalty
522    if (result !== undefined && result !== null) {
523      addCatch(this, result, type, args);
524    }
525  } else {
526    const len = handler.length;
527    const listeners = arrayClone(handler);
528    for (let i = 0; i < len; ++i) {
529      const result = listeners[i].apply(this, args);
530
531      // We check if result is undefined first because that
532      // is the most common case so we do not pay any perf
533      // penalty.
534      // This code is duplicated because extracting it away
535      // would make it non-inlineable.
536      if (result !== undefined && result !== null) {
537        addCatch(this, result, type, args);
538      }
539    }
540  }
541
542  return true;
543};
544
545function _addListener(target, type, listener, prepend) {
546  let m;
547  let events;
548  let existing;
549
550  checkListener(listener);
551
552  events = target._events;
553  if (events === undefined) {
554    events = target._events = ObjectCreate(null);
555    target._eventsCount = 0;
556  } else {
557    // To avoid recursion in the case that type === "newListener"! Before
558    // adding it to the listeners, first emit "newListener".
559    if (events.newListener !== undefined) {
560      target.emit('newListener', type,
561                  listener.listener ?? listener);
562
563      // Re-assign `events` because a newListener handler could have caused the
564      // this._events to be assigned to a new object
565      events = target._events;
566    }
567    existing = events[type];
568  }
569
570  if (existing === undefined) {
571    // Optimize the case of one listener. Don't need the extra array object.
572    events[type] = listener;
573    ++target._eventsCount;
574  } else {
575    if (typeof existing === 'function') {
576      // Adding the second element, need to change to array.
577      existing = events[type] =
578        prepend ? [listener, existing] : [existing, listener];
579      // If we've already got an array, just append.
580    } else if (prepend) {
581      existing.unshift(listener);
582    } else {
583      existing.push(listener);
584    }
585
586    // Check for listener leak
587    m = _getMaxListeners(target);
588    if (m > 0 && existing.length > m && !existing.warned) {
589      existing.warned = true;
590      // No error code for this since it is a Warning
591      const w = genericNodeError(
592        `Possible EventEmitter memory leak detected. ${existing.length} ${String(type)} listeners ` +
593        `added to ${inspect(target, { depth: -1 })}. Use emitter.setMaxListeners() to increase limit`,
594        { name: 'MaxListenersExceededWarning', emitter: target, type: type, count: existing.length });
595      process.emitWarning(w);
596    }
597  }
598
599  return target;
600}
601
602/**
603 * Adds a listener to the event emitter.
604 * @param {string | symbol} type
605 * @param {Function} listener
606 * @returns {EventEmitter}
607 */
608EventEmitter.prototype.addListener = function addListener(type, listener) {
609  return _addListener(this, type, listener, false);
610};
611
612EventEmitter.prototype.on = EventEmitter.prototype.addListener;
613
614/**
615 * Adds the `listener` function to the beginning of
616 * the listeners array.
617 * @param {string | symbol} type
618 * @param {Function} listener
619 * @returns {EventEmitter}
620 */
621EventEmitter.prototype.prependListener =
622    function prependListener(type, listener) {
623      return _addListener(this, type, listener, true);
624    };
625
626function onceWrapper() {
627  if (!this.fired) {
628    this.target.removeListener(this.type, this.wrapFn);
629    this.fired = true;
630    if (arguments.length === 0)
631      return this.listener.call(this.target);
632    return this.listener.apply(this.target, arguments);
633  }
634}
635
636function _onceWrap(target, type, listener) {
637  const state = { fired: false, wrapFn: undefined, target, type, listener };
638  const wrapped = onceWrapper.bind(state);
639  wrapped.listener = listener;
640  state.wrapFn = wrapped;
641  return wrapped;
642}
643
644/**
645 * Adds a one-time `listener` function to the event emitter.
646 * @param {string | symbol} type
647 * @param {Function} listener
648 * @returns {EventEmitter}
649 */
650EventEmitter.prototype.once = function once(type, listener) {
651  checkListener(listener);
652
653  this.on(type, _onceWrap(this, type, listener));
654  return this;
655};
656
657/**
658 * Adds a one-time `listener` function to the beginning of
659 * the listeners array.
660 * @param {string | symbol} type
661 * @param {Function} listener
662 * @returns {EventEmitter}
663 */
664EventEmitter.prototype.prependOnceListener =
665    function prependOnceListener(type, listener) {
666      checkListener(listener);
667
668      this.prependListener(type, _onceWrap(this, type, listener));
669      return this;
670    };
671
672/**
673 * Removes the specified `listener` from the listeners array.
674 * @param {string | symbol} type
675 * @param {Function} listener
676 * @returns {EventEmitter}
677 */
678EventEmitter.prototype.removeListener =
679    function removeListener(type, listener) {
680      checkListener(listener);
681
682      const events = this._events;
683      if (events === undefined)
684        return this;
685
686      const list = events[type];
687      if (list === undefined)
688        return this;
689
690      if (list === listener || list.listener === listener) {
691        if (--this._eventsCount === 0)
692          this._events = ObjectCreate(null);
693        else {
694          delete events[type];
695          if (events.removeListener)
696            this.emit('removeListener', type, list.listener || listener);
697        }
698      } else if (typeof list !== 'function') {
699        let position = -1;
700
701        for (let i = list.length - 1; i >= 0; i--) {
702          if (list[i] === listener || list[i].listener === listener) {
703            position = i;
704            break;
705          }
706        }
707
708        if (position < 0)
709          return this;
710
711        if (position === 0)
712          list.shift();
713        else {
714          if (spliceOne === undefined)
715            spliceOne = require('internal/util').spliceOne;
716          spliceOne(list, position);
717        }
718
719        if (list.length === 1)
720          events[type] = list[0];
721
722        if (events.removeListener !== undefined)
723          this.emit('removeListener', type, listener);
724      }
725
726      return this;
727    };
728
729EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
730
731/**
732 * Removes all listeners from the event emitter. (Only
733 * removes listeners for a specific event name if specified
734 * as `type`).
735 * @param {string | symbol} [type]
736 * @returns {EventEmitter}
737 */
738EventEmitter.prototype.removeAllListeners =
739    function removeAllListeners(type) {
740      const events = this._events;
741      if (events === undefined)
742        return this;
743
744      // Not listening for removeListener, no need to emit
745      if (events.removeListener === undefined) {
746        if (arguments.length === 0) {
747          this._events = ObjectCreate(null);
748          this._eventsCount = 0;
749        } else if (events[type] !== undefined) {
750          if (--this._eventsCount === 0)
751            this._events = ObjectCreate(null);
752          else
753            delete events[type];
754        }
755        return this;
756      }
757
758      // Emit removeListener for all listeners on all events
759      if (arguments.length === 0) {
760        for (const key of ReflectOwnKeys(events)) {
761          if (key === 'removeListener') continue;
762          this.removeAllListeners(key);
763        }
764        this.removeAllListeners('removeListener');
765        this._events = ObjectCreate(null);
766        this._eventsCount = 0;
767        return this;
768      }
769
770      const listeners = events[type];
771
772      if (typeof listeners === 'function') {
773        this.removeListener(type, listeners);
774      } else if (listeners !== undefined) {
775        // LIFO order
776        for (let i = listeners.length - 1; i >= 0; i--) {
777          this.removeListener(type, listeners[i]);
778        }
779      }
780
781      return this;
782    };
783
784function _listeners(target, type, unwrap) {
785  const events = target._events;
786
787  if (events === undefined)
788    return [];
789
790  const evlistener = events[type];
791  if (evlistener === undefined)
792    return [];
793
794  if (typeof evlistener === 'function')
795    return unwrap ? [evlistener.listener || evlistener] : [evlistener];
796
797  return unwrap ?
798    unwrapListeners(evlistener) : arrayClone(evlistener);
799}
800
801/**
802 * Returns a copy of the array of listeners for the event name
803 * specified as `type`.
804 * @param {string | symbol} type
805 * @returns {Function[]}
806 */
807EventEmitter.prototype.listeners = function listeners(type) {
808  return _listeners(this, type, true);
809};
810
811/**
812 * Returns a copy of the array of listeners and wrappers for
813 * the event name specified as `type`.
814 * @param {string | symbol} type
815 * @returns {Function[]}
816 */
817EventEmitter.prototype.rawListeners = function rawListeners(type) {
818  return _listeners(this, type, false);
819};
820
821/**
822 * Returns the number of listeners listening to the event name
823 * specified as `type`.
824 * @deprecated since v3.2.0
825 * @param {EventEmitter} emitter
826 * @param {string | symbol} type
827 * @returns {number}
828 */
829EventEmitter.listenerCount = function(emitter, type) {
830  if (typeof emitter.listenerCount === 'function') {
831    return emitter.listenerCount(type);
832  }
833  return FunctionPrototypeCall(listenerCount, emitter, type);
834};
835
836EventEmitter.prototype.listenerCount = listenerCount;
837
838/**
839 * Returns the number of listeners listening to event name
840 * specified as `type`.
841 * @param {string | symbol} type
842 * @param {Function} listener
843 * @returns {number}
844 */
845function listenerCount(type, listener) {
846  const events = this._events;
847
848  if (events !== undefined) {
849    const evlistener = events[type];
850
851    if (typeof evlistener === 'function') {
852      if (listener != null) {
853        return listener === evlistener || listener === evlistener.listener ? 1 : 0;
854      }
855
856      return 1;
857    } else if (evlistener !== undefined) {
858      if (listener != null) {
859        let matching = 0;
860
861        for (let i = 0, l = evlistener.length; i < l; i++) {
862          if (evlistener[i] === listener || evlistener[i].listener === listener) {
863            matching++;
864          }
865        }
866
867        return matching;
868      }
869
870      return evlistener.length;
871    }
872  }
873
874  return 0;
875}
876
877/**
878 * Returns an array listing the events for which
879 * the emitter has registered listeners.
880 * @returns {any[]}
881 */
882EventEmitter.prototype.eventNames = function eventNames() {
883  return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : [];
884};
885
886function arrayClone(arr) {
887  // At least since V8 8.3, this implementation is faster than the previous
888  // which always used a simple for-loop
889  switch (arr.length) {
890    case 2: return [arr[0], arr[1]];
891    case 3: return [arr[0], arr[1], arr[2]];
892    case 4: return [arr[0], arr[1], arr[2], arr[3]];
893    case 5: return [arr[0], arr[1], arr[2], arr[3], arr[4]];
894    case 6: return [arr[0], arr[1], arr[2], arr[3], arr[4], arr[5]];
895  }
896  return ArrayPrototypeSlice(arr);
897}
898
899function unwrapListeners(arr) {
900  const ret = arrayClone(arr);
901  for (let i = 0; i < ret.length; ++i) {
902    const orig = ret[i].listener;
903    if (typeof orig === 'function')
904      ret[i] = orig;
905  }
906  return ret;
907}
908
909/**
910 * Returns a copy of the array of listeners for the event name
911 * specified as `type`.
912 * @param {EventEmitter | EventTarget} emitterOrTarget
913 * @param {string | symbol} type
914 * @returns {Function[]}
915 */
916function getEventListeners(emitterOrTarget, type) {
917  // First check if EventEmitter
918  if (typeof emitterOrTarget.listeners === 'function') {
919    return emitterOrTarget.listeners(type);
920  }
921  // Require event target lazily to avoid always loading it
922  const { isEventTarget, kEvents } = require('internal/event_target');
923  if (isEventTarget(emitterOrTarget)) {
924    const root = emitterOrTarget[kEvents].get(type);
925    const listeners = [];
926    let handler = root?.next;
927    while (handler?.listener !== undefined) {
928      const listener = handler.listener?.deref ?
929        handler.listener.deref() : handler.listener;
930      listeners.push(listener);
931      handler = handler.next;
932    }
933    return listeners;
934  }
935  throw new ERR_INVALID_ARG_TYPE('emitter',
936                                 ['EventEmitter', 'EventTarget'],
937                                 emitterOrTarget);
938}
939
940/**
941 * Returns the max listeners set.
942 * @param {EventEmitter | EventTarget} emitterOrTarget
943 * @returns {number}
944 */
945function getMaxListeners(emitterOrTarget) {
946  if (typeof emitterOrTarget?.getMaxListeners === 'function') {
947    return _getMaxListeners(emitterOrTarget);
948  } else if (emitterOrTarget?.[kMaxEventTargetListeners]) {
949    return emitterOrTarget[kMaxEventTargetListeners];
950  }
951
952  throw new ERR_INVALID_ARG_TYPE('emitter',
953                                 ['EventEmitter', 'EventTarget'],
954                                 emitterOrTarget);
955}
956
957/**
958 * Creates a `Promise` that is fulfilled when the emitter
959 * emits the given event.
960 * @param {EventEmitter} emitter
961 * @param {string} name
962 * @param {{ signal: AbortSignal; }} [options]
963 * @returns {Promise}
964 */
965async function once(emitter, name, options = kEmptyObject) {
966  const signal = options?.signal;
967  validateAbortSignal(signal, 'options.signal');
968  if (signal?.aborted)
969    throw new AbortError(undefined, { cause: signal?.reason });
970  return new Promise((resolve, reject) => {
971    const errorListener = (err) => {
972      emitter.removeListener(name, resolver);
973      if (signal != null) {
974        eventTargetAgnosticRemoveListener(signal, 'abort', abortListener);
975      }
976      reject(err);
977    };
978    const resolver = (...args) => {
979      if (typeof emitter.removeListener === 'function') {
980        emitter.removeListener('error', errorListener);
981      }
982      if (signal != null) {
983        eventTargetAgnosticRemoveListener(signal, 'abort', abortListener);
984      }
985      resolve(args);
986    };
987
988    kResistStopPropagation ??= require('internal/event_target').kResistStopPropagation;
989    const opts = { __proto__: null, once: true, [kResistStopPropagation]: true };
990    eventTargetAgnosticAddListener(emitter, name, resolver, opts);
991    if (name !== 'error' && typeof emitter.once === 'function') {
992      // EventTarget does not have `error` event semantics like Node
993      // EventEmitters, we listen to `error` events only on EventEmitters.
994      emitter.once('error', errorListener);
995    }
996    function abortListener() {
997      eventTargetAgnosticRemoveListener(emitter, name, resolver);
998      eventTargetAgnosticRemoveListener(emitter, 'error', errorListener);
999      reject(new AbortError(undefined, { cause: signal?.reason }));
1000    }
1001    if (signal != null) {
1002      eventTargetAgnosticAddListener(
1003        signal, 'abort', abortListener, { __proto__: null, once: true, [kResistStopPropagation]: true });
1004    }
1005  });
1006}
1007
1008const AsyncIteratorPrototype = ObjectGetPrototypeOf(
1009  ObjectGetPrototypeOf(async function* () {}).prototype);
1010
1011function createIterResult(value, done) {
1012  return { value, done };
1013}
1014
1015function eventTargetAgnosticRemoveListener(emitter, name, listener, flags) {
1016  if (typeof emitter.removeListener === 'function') {
1017    emitter.removeListener(name, listener);
1018  } else if (typeof emitter.removeEventListener === 'function') {
1019    emitter.removeEventListener(name, listener, flags);
1020  } else {
1021    throw new ERR_INVALID_ARG_TYPE('emitter', 'EventEmitter', emitter);
1022  }
1023}
1024
1025function eventTargetAgnosticAddListener(emitter, name, listener, flags) {
1026  if (typeof emitter.on === 'function') {
1027    if (flags?.once) {
1028      emitter.once(name, listener);
1029    } else {
1030      emitter.on(name, listener);
1031    }
1032  } else if (typeof emitter.addEventListener === 'function') {
1033    emitter.addEventListener(name, listener, flags);
1034  } else {
1035    throw new ERR_INVALID_ARG_TYPE('emitter', 'EventEmitter', emitter);
1036  }
1037}
1038
1039/**
1040 * Returns an `AsyncIterator` that iterates `event` events.
1041 * @param {EventEmitter} emitter
1042 * @param {string | symbol} event
1043 * @param {{ signal: AbortSignal; }} [options]
1044 * @returns {AsyncIterator}
1045 */
1046function on(emitter, event, options = kEmptyObject) {
1047  const signal = options?.signal;
1048  validateAbortSignal(signal, 'options.signal');
1049  if (signal?.aborted)
1050    throw new AbortError(undefined, { cause: signal?.reason });
1051
1052  const unconsumedEvents = [];
1053  const unconsumedPromises = [];
1054  let error = null;
1055  let finished = false;
1056
1057  const iterator = ObjectSetPrototypeOf({
1058    next() {
1059      // First, we consume all unread events
1060      const value = unconsumedEvents.shift();
1061      if (value) {
1062        return PromiseResolve(createIterResult(value, false));
1063      }
1064
1065      // Then we error, if an error happened
1066      // This happens one time if at all, because after 'error'
1067      // we stop listening
1068      if (error) {
1069        const p = PromiseReject(error);
1070        // Only the first element errors
1071        error = null;
1072        return p;
1073      }
1074
1075      // If the iterator is finished, resolve to done
1076      if (finished) {
1077        return PromiseResolve(createIterResult(undefined, true));
1078      }
1079
1080      // Wait until an event happens
1081      return new Promise(function(resolve, reject) {
1082        unconsumedPromises.push({ resolve, reject });
1083      });
1084    },
1085
1086    return() {
1087      eventTargetAgnosticRemoveListener(emitter, event, eventHandler);
1088      eventTargetAgnosticRemoveListener(emitter, 'error', errorHandler);
1089
1090      if (signal) {
1091        eventTargetAgnosticRemoveListener(
1092          signal,
1093          'abort',
1094          abortListener,
1095          { once: true });
1096      }
1097
1098      finished = true;
1099
1100      for (const promise of unconsumedPromises) {
1101        promise.resolve(createIterResult(undefined, true));
1102      }
1103
1104      return PromiseResolve(createIterResult(undefined, true));
1105    },
1106
1107    throw(err) {
1108      if (!err || !(err instanceof Error)) {
1109        throw new ERR_INVALID_ARG_TYPE('EventEmitter.AsyncIterator',
1110                                       'Error', err);
1111      }
1112      error = err;
1113      eventTargetAgnosticRemoveListener(emitter, event, eventHandler);
1114      eventTargetAgnosticRemoveListener(emitter, 'error', errorHandler);
1115    },
1116
1117    [SymbolAsyncIterator]() {
1118      return this;
1119    },
1120  }, AsyncIteratorPrototype);
1121
1122  eventTargetAgnosticAddListener(emitter, event, eventHandler);
1123  if (event !== 'error' && typeof emitter.on === 'function') {
1124    emitter.on('error', errorHandler);
1125  }
1126
1127  if (signal) {
1128    kResistStopPropagation ??= require('internal/event_target').kResistStopPropagation;
1129    eventTargetAgnosticAddListener(
1130      signal,
1131      'abort',
1132      abortListener,
1133      { __proto__: null, once: true, [kResistStopPropagation]: true });
1134  }
1135
1136  function abortListener() {
1137    errorHandler(new AbortError(undefined, { cause: signal?.reason }));
1138  }
1139
1140  function eventHandler(...args) {
1141    const promise = ArrayPrototypeShift(unconsumedPromises);
1142    if (promise) {
1143      promise.resolve(createIterResult(args, false));
1144    } else {
1145      unconsumedEvents.push(args);
1146    }
1147  }
1148
1149  function errorHandler(err) {
1150    finished = true;
1151
1152    const toError = ArrayPrototypeShift(unconsumedPromises);
1153
1154    if (toError) {
1155      toError.reject(err);
1156    } else {
1157      // The next time we call next()
1158      error = err;
1159    }
1160
1161    iterator.return();
1162  }
1163  return iterator;
1164}
1165
1166let queueMicrotask;
1167
1168function addAbortListener(signal, listener) {
1169  if (signal === undefined) {
1170    throw new ERR_INVALID_ARG_TYPE('signal', 'AbortSignal', signal);
1171  }
1172  validateAbortSignal(signal, 'signal');
1173  validateFunction(listener, 'listener');
1174
1175  let removeEventListener;
1176  if (signal.aborted) {
1177    queueMicrotask ??= require('internal/process/task_queues').queueMicrotask;
1178    queueMicrotask(() => listener());
1179  } else {
1180    kResistStopPropagation ??= require('internal/event_target').kResistStopPropagation;
1181    // TODO(atlowChemi) add { subscription: true } and return directly
1182    signal.addEventListener('abort', listener, { __proto__: null, once: true, [kResistStopPropagation]: true });
1183    removeEventListener = () => {
1184      signal.removeEventListener('abort', listener);
1185    };
1186  }
1187  return {
1188    __proto__: null,
1189    [SymbolDispose]() {
1190      removeEventListener?.();
1191    },
1192  };
1193}
1194