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