events.js 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977
  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. // Modified by the vm2 team to make this a standalone module to be loaded into the sandbox.
  22. 'use strict';
  23. const host = fromhost;
  24. const {
  25. Boolean,
  26. Error,
  27. String,
  28. Symbol
  29. } = globalThis;
  30. const ReflectApply = Reflect.apply;
  31. const ReflectOwnKeys = Reflect.ownKeys;
  32. const ErrorCaptureStackTrace = Error.captureStackTrace;
  33. const NumberIsNaN = Number.isNaN;
  34. const ObjectCreate = Object.create;
  35. const ObjectDefineProperty = Object.defineProperty;
  36. const ObjectDefineProperties = Object.defineProperties;
  37. const ObjectGetPrototypeOf = Object.getPrototypeOf;
  38. const SymbolFor = Symbol.for;
  39. function uncurryThis(func) {
  40. return (thiz, ...args) => ReflectApply(func, thiz, args);
  41. }
  42. const ArrayPrototypeIndexOf = uncurryThis(Array.prototype.indexOf);
  43. const ArrayPrototypeJoin = uncurryThis(Array.prototype.join);
  44. const ArrayPrototypeSlice = uncurryThis(Array.prototype.slice);
  45. const ArrayPrototypeSplice = uncurryThis(Array.prototype.splice);
  46. const ArrayPrototypeUnshift = uncurryThis(Array.prototype.unshift);
  47. const kRejection = SymbolFor('nodejs.rejection');
  48. function inspect(obj) {
  49. return typeof obj === 'symbol' ? obj.toString() : `${obj}`;
  50. }
  51. function spliceOne(list, index) {
  52. for (; index + 1 < list.length; index++)
  53. list[index] = list[index + 1];
  54. list.pop();
  55. }
  56. function assert(what, message) {
  57. if (!what) throw new Error(message);
  58. }
  59. function E(key, msg, Base) {
  60. return function NodeError(...args) {
  61. const error = new Base();
  62. const message = ReflectApply(msg, error, args);
  63. ObjectDefineProperties(error, {
  64. message: {
  65. value: message,
  66. enumerable: false,
  67. writable: true,
  68. configurable: true,
  69. },
  70. toString: {
  71. value() {
  72. return `${this.name} [${key}]: ${this.message}`;
  73. },
  74. enumerable: false,
  75. writable: true,
  76. configurable: true,
  77. },
  78. });
  79. error.code = key;
  80. return error;
  81. };
  82. }
  83. const ERR_INVALID_ARG_TYPE = E('ERR_INVALID_ARG_TYPE',
  84. (name, expected, actual) => {
  85. assert(typeof name === 'string', "'name' must be a string");
  86. if (!ArrayIsArray(expected)) {
  87. expected = [expected];
  88. }
  89. let msg = 'The ';
  90. if (StringPrototypeEndsWith(name, ' argument')) {
  91. // For cases like 'first argument'
  92. msg += `${name} `;
  93. } else {
  94. const type = StringPrototypeIncludes(name, '.') ? 'property' : 'argument';
  95. msg += `"${name}" ${type} `;
  96. }
  97. msg += 'must be ';
  98. const types = [];
  99. const instances = [];
  100. const other = [];
  101. for (const value of expected) {
  102. assert(typeof value === 'string',
  103. 'All expected entries have to be of type string');
  104. if (ArrayPrototypeIncludes(kTypes, value)) {
  105. ArrayPrototypePush(types, StringPrototypeToLowerCase(value));
  106. } else if (RegExpPrototypeTest(classRegExp, value)) {
  107. ArrayPrototypePush(instances, value);
  108. } else {
  109. assert(value !== 'object',
  110. 'The value "object" should be written as "Object"');
  111. ArrayPrototypePush(other, value);
  112. }
  113. }
  114. // Special handle `object` in case other instances are allowed to outline
  115. // the differences between each other.
  116. if (instances.length > 0) {
  117. const pos = ArrayPrototypeIndexOf(types, 'object');
  118. if (pos !== -1) {
  119. ArrayPrototypeSplice(types, pos, 1);
  120. ArrayPrototypePush(instances, 'Object');
  121. }
  122. }
  123. if (types.length > 0) {
  124. if (types.length > 2) {
  125. const last = ArrayPrototypePop(types);
  126. msg += `one of type ${ArrayPrototypeJoin(types, ', ')}, or ${last}`;
  127. } else if (types.length === 2) {
  128. msg += `one of type ${types[0]} or ${types[1]}`;
  129. } else {
  130. msg += `of type ${types[0]}`;
  131. }
  132. if (instances.length > 0 || other.length > 0)
  133. msg += ' or ';
  134. }
  135. if (instances.length > 0) {
  136. if (instances.length > 2) {
  137. const last = ArrayPrototypePop(instances);
  138. msg +=
  139. `an instance of ${ArrayPrototypeJoin(instances, ', ')}, or ${last}`;
  140. } else {
  141. msg += `an instance of ${instances[0]}`;
  142. if (instances.length === 2) {
  143. msg += ` or ${instances[1]}`;
  144. }
  145. }
  146. if (other.length > 0)
  147. msg += ' or ';
  148. }
  149. if (other.length > 0) {
  150. if (other.length > 2) {
  151. const last = ArrayPrototypePop(other);
  152. msg += `one of ${ArrayPrototypeJoin(other, ', ')}, or ${last}`;
  153. } else if (other.length === 2) {
  154. msg += `one of ${other[0]} or ${other[1]}`;
  155. } else {
  156. if (StringPrototypeToLowerCase(other[0]) !== other[0])
  157. msg += 'an ';
  158. msg += `${other[0]}`;
  159. }
  160. }
  161. if (actual == null) {
  162. msg += `. Received ${actual}`;
  163. } else if (typeof actual === 'function' && actual.name) {
  164. msg += `. Received function ${actual.name}`;
  165. } else if (typeof actual === 'object') {
  166. if (actual.constructor && actual.constructor.name) {
  167. msg += `. Received an instance of ${actual.constructor.name}`;
  168. } else {
  169. const inspected = inspect(actual, { depth: -1 });
  170. msg += `. Received ${inspected}`;
  171. }
  172. } else {
  173. let inspected = inspect(actual, { colors: false });
  174. if (inspected.length > 25)
  175. inspected = `${StringPrototypeSlice(inspected, 0, 25)}...`;
  176. msg += `. Received type ${typeof actual} (${inspected})`;
  177. }
  178. return msg;
  179. }, TypeError);
  180. const ERR_INVALID_THIS = E('ERR_INVALID_THIS', s => `Value of "this" must be of type ${s}`, TypeError);
  181. const ERR_OUT_OF_RANGE = E('ERR_OUT_OF_RANGE',
  182. (str, range, input, replaceDefaultBoolean = false) => {
  183. assert(range, 'Missing "range" argument');
  184. let msg = replaceDefaultBoolean ? str :
  185. `The value of "${str}" is out of range.`;
  186. const received = inspect(input);
  187. msg += ` It must be ${range}. Received ${received}`;
  188. return msg;
  189. }, RangeError);
  190. const ERR_UNHANDLED_ERROR = E('ERR_UNHANDLED_ERROR',
  191. err => {
  192. const msg = 'Unhandled error.';
  193. if (err === undefined) return msg;
  194. return `${msg} (${err})`;
  195. }, Error);
  196. function validateBoolean(value, name) {
  197. if (typeof value !== 'boolean')
  198. throw new ERR_INVALID_ARG_TYPE(name, 'boolean', value);
  199. }
  200. function validateFunction(value, name) {
  201. if (typeof value !== 'function')
  202. throw new ERR_INVALID_ARG_TYPE(name, 'Function', value);
  203. }
  204. function validateString(value, name) {
  205. if (typeof value !== 'string')
  206. throw new ERR_INVALID_ARG_TYPE(name, 'string', value);
  207. }
  208. function nc(cond, e) {
  209. return cond === undefined || cond === null ? e : cond;
  210. }
  211. function oc(base, key) {
  212. return base === undefined || base === null ? undefined : base[key];
  213. }
  214. const kCapture = Symbol('kCapture');
  215. const kErrorMonitor = host.kErrorMonitor || Symbol('events.errorMonitor');
  216. const kMaxEventTargetListeners = Symbol('events.maxEventTargetListeners');
  217. const kMaxEventTargetListenersWarned =
  218. Symbol('events.maxEventTargetListenersWarned');
  219. const kIsEventTarget = SymbolFor('nodejs.event_target');
  220. function isEventTarget(obj) {
  221. return oc(oc(obj, 'constructor'), kIsEventTarget);
  222. }
  223. /**
  224. * Creates a new `EventEmitter` instance.
  225. * @param {{ captureRejections?: boolean; }} [opts]
  226. * @constructs {EventEmitter}
  227. */
  228. function EventEmitter(opts) {
  229. EventEmitter.init.call(this, opts);
  230. }
  231. module.exports = EventEmitter;
  232. if (host.once) module.exports.once = host.once;
  233. if (host.on) module.exports.on = host.on;
  234. if (host.getEventListeners) module.exports.getEventListeners = host.getEventListeners;
  235. // Backwards-compat with node 0.10.x
  236. EventEmitter.EventEmitter = EventEmitter;
  237. EventEmitter.usingDomains = false;
  238. EventEmitter.captureRejectionSymbol = kRejection;
  239. ObjectDefineProperty(EventEmitter, 'captureRejections', {
  240. get() {
  241. return EventEmitter.prototype[kCapture];
  242. },
  243. set(value) {
  244. validateBoolean(value, 'EventEmitter.captureRejections');
  245. EventEmitter.prototype[kCapture] = value;
  246. },
  247. enumerable: true
  248. });
  249. if (host.EventEmitterReferencingAsyncResource) {
  250. const kAsyncResource = Symbol('kAsyncResource');
  251. const EventEmitterReferencingAsyncResource = host.EventEmitterReferencingAsyncResource;
  252. class EventEmitterAsyncResource extends EventEmitter {
  253. /**
  254. * @param {{
  255. * name?: string,
  256. * triggerAsyncId?: number,
  257. * requireManualDestroy?: boolean,
  258. * }} [options]
  259. */
  260. constructor(options = undefined) {
  261. let name;
  262. if (typeof options === 'string') {
  263. name = options;
  264. options = undefined;
  265. } else {
  266. if (new.target === EventEmitterAsyncResource) {
  267. validateString(oc(options, 'name'), 'options.name');
  268. }
  269. name = oc(options, 'name') || new.target.name;
  270. }
  271. super(options);
  272. this[kAsyncResource] =
  273. new EventEmitterReferencingAsyncResource(this, name, options);
  274. }
  275. /**
  276. * @param {symbol,string} event
  277. * @param {...any} args
  278. * @returns {boolean}
  279. */
  280. emit(event, ...args) {
  281. if (this[kAsyncResource] === undefined)
  282. throw new ERR_INVALID_THIS('EventEmitterAsyncResource');
  283. const { asyncResource } = this;
  284. ArrayPrototypeUnshift(args, super.emit, this, event);
  285. return ReflectApply(asyncResource.runInAsyncScope, asyncResource,
  286. args);
  287. }
  288. /**
  289. * @returns {void}
  290. */
  291. emitDestroy() {
  292. if (this[kAsyncResource] === undefined)
  293. throw new ERR_INVALID_THIS('EventEmitterAsyncResource');
  294. this.asyncResource.emitDestroy();
  295. }
  296. /**
  297. * @type {number}
  298. */
  299. get asyncId() {
  300. if (this[kAsyncResource] === undefined)
  301. throw new ERR_INVALID_THIS('EventEmitterAsyncResource');
  302. return this.asyncResource.asyncId();
  303. }
  304. /**
  305. * @type {number}
  306. */
  307. get triggerAsyncId() {
  308. if (this[kAsyncResource] === undefined)
  309. throw new ERR_INVALID_THIS('EventEmitterAsyncResource');
  310. return this.asyncResource.triggerAsyncId();
  311. }
  312. /**
  313. * @type {EventEmitterReferencingAsyncResource}
  314. */
  315. get asyncResource() {
  316. if (this[kAsyncResource] === undefined)
  317. throw new ERR_INVALID_THIS('EventEmitterAsyncResource');
  318. return this[kAsyncResource];
  319. }
  320. }
  321. EventEmitter.EventEmitterAsyncResource = EventEmitterAsyncResource;
  322. }
  323. EventEmitter.errorMonitor = kErrorMonitor;
  324. // The default for captureRejections is false
  325. ObjectDefineProperty(EventEmitter.prototype, kCapture, {
  326. value: false,
  327. writable: true,
  328. enumerable: false
  329. });
  330. EventEmitter.prototype._events = undefined;
  331. EventEmitter.prototype._eventsCount = 0;
  332. EventEmitter.prototype._maxListeners = undefined;
  333. // By default EventEmitters will print a warning if more than 10 listeners are
  334. // added to it. This is a useful default which helps finding memory leaks.
  335. let defaultMaxListeners = 10;
  336. function checkListener(listener) {
  337. validateFunction(listener, 'listener');
  338. }
  339. ObjectDefineProperty(EventEmitter, 'defaultMaxListeners', {
  340. enumerable: true,
  341. get: function() {
  342. return defaultMaxListeners;
  343. },
  344. set: function(arg) {
  345. if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) {
  346. throw new ERR_OUT_OF_RANGE('defaultMaxListeners',
  347. 'a non-negative number',
  348. arg);
  349. }
  350. defaultMaxListeners = arg;
  351. }
  352. });
  353. ObjectDefineProperties(EventEmitter, {
  354. kMaxEventTargetListeners: {
  355. value: kMaxEventTargetListeners,
  356. enumerable: false,
  357. configurable: false,
  358. writable: false,
  359. },
  360. kMaxEventTargetListenersWarned: {
  361. value: kMaxEventTargetListenersWarned,
  362. enumerable: false,
  363. configurable: false,
  364. writable: false,
  365. }
  366. });
  367. /**
  368. * Sets the max listeners.
  369. * @param {number} n
  370. * @param {EventTarget[] | EventEmitter[]} [eventTargets]
  371. * @returns {void}
  372. */
  373. EventEmitter.setMaxListeners =
  374. function(n = defaultMaxListeners, ...eventTargets) {
  375. if (typeof n !== 'number' || n < 0 || NumberIsNaN(n))
  376. throw new ERR_OUT_OF_RANGE('n', 'a non-negative number', n);
  377. if (eventTargets.length === 0) {
  378. defaultMaxListeners = n;
  379. } else {
  380. for (let i = 0; i < eventTargets.length; i++) {
  381. const target = eventTargets[i];
  382. if (isEventTarget(target)) {
  383. target[kMaxEventTargetListeners] = n;
  384. target[kMaxEventTargetListenersWarned] = false;
  385. } else if (typeof target.setMaxListeners === 'function') {
  386. target.setMaxListeners(n);
  387. } else {
  388. throw new ERR_INVALID_ARG_TYPE(
  389. 'eventTargets',
  390. ['EventEmitter', 'EventTarget'],
  391. target);
  392. }
  393. }
  394. }
  395. };
  396. // If you're updating this function definition, please also update any
  397. // re-definitions, such as the one in the Domain module (lib/domain.js).
  398. EventEmitter.init = function(opts) {
  399. if (this._events === undefined ||
  400. this._events === ObjectGetPrototypeOf(this)._events) {
  401. this._events = ObjectCreate(null);
  402. this._eventsCount = 0;
  403. }
  404. this._maxListeners = this._maxListeners || undefined;
  405. if (oc(opts, 'captureRejections')) {
  406. validateBoolean(opts.captureRejections, 'options.captureRejections');
  407. this[kCapture] = Boolean(opts.captureRejections);
  408. } else {
  409. // Assigning the kCapture property directly saves an expensive
  410. // prototype lookup in a very sensitive hot path.
  411. this[kCapture] = EventEmitter.prototype[kCapture];
  412. }
  413. };
  414. function addCatch(that, promise, type, args) {
  415. if (!that[kCapture]) {
  416. return;
  417. }
  418. // Handle Promises/A+ spec, then could be a getter
  419. // that throws on second use.
  420. try {
  421. const then = promise.then;
  422. if (typeof then === 'function') {
  423. then.call(promise, undefined, function(err) {
  424. // The callback is called with nextTick to avoid a follow-up
  425. // rejection from this promise.
  426. process.nextTick(emitUnhandledRejectionOrErr, that, err, type, args);
  427. });
  428. }
  429. } catch (err) {
  430. that.emit('error', err);
  431. }
  432. }
  433. function emitUnhandledRejectionOrErr(ee, err, type, args) {
  434. if (typeof ee[kRejection] === 'function') {
  435. ee[kRejection](err, type, ...args);
  436. } else {
  437. // We have to disable the capture rejections mechanism, otherwise
  438. // we might end up in an infinite loop.
  439. const prev = ee[kCapture];
  440. // If the error handler throws, it is not catchable and it
  441. // will end up in 'uncaughtException'. We restore the previous
  442. // value of kCapture in case the uncaughtException is present
  443. // and the exception is handled.
  444. try {
  445. ee[kCapture] = false;
  446. ee.emit('error', err);
  447. } finally {
  448. ee[kCapture] = prev;
  449. }
  450. }
  451. }
  452. /**
  453. * Increases the max listeners of the event emitter.
  454. * @param {number} n
  455. * @returns {EventEmitter}
  456. */
  457. EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {
  458. if (typeof n !== 'number' || n < 0 || NumberIsNaN(n)) {
  459. throw new ERR_OUT_OF_RANGE('n', 'a non-negative number', n);
  460. }
  461. this._maxListeners = n;
  462. return this;
  463. };
  464. function _getMaxListeners(that) {
  465. if (that._maxListeners === undefined)
  466. return EventEmitter.defaultMaxListeners;
  467. return that._maxListeners;
  468. }
  469. /**
  470. * Returns the current max listener value for the event emitter.
  471. * @returns {number}
  472. */
  473. EventEmitter.prototype.getMaxListeners = function getMaxListeners() {
  474. return _getMaxListeners(this);
  475. };
  476. /**
  477. * Synchronously calls each of the listeners registered
  478. * for the event.
  479. * @param {string | symbol} type
  480. * @param {...any} [args]
  481. * @returns {boolean}
  482. */
  483. EventEmitter.prototype.emit = function emit(type, ...args) {
  484. let doError = (type === 'error');
  485. const events = this._events;
  486. if (events !== undefined) {
  487. if (doError && events[kErrorMonitor] !== undefined)
  488. this.emit(kErrorMonitor, ...args);
  489. doError = (doError && events.error === undefined);
  490. } else if (!doError)
  491. return false;
  492. // If there is no 'error' event listener then throw.
  493. if (doError) {
  494. let er;
  495. if (args.length > 0)
  496. er = args[0];
  497. if (er instanceof Error) {
  498. try {
  499. const capture = {};
  500. ErrorCaptureStackTrace(capture, EventEmitter.prototype.emit);
  501. } catch (e) {}
  502. // Note: The comments on the `throw` lines are intentional, they show
  503. // up in Node's output if this results in an unhandled exception.
  504. throw er; // Unhandled 'error' event
  505. }
  506. let stringifiedEr;
  507. try {
  508. stringifiedEr = inspect(er);
  509. } catch (e) {
  510. stringifiedEr = er;
  511. }
  512. // At least give some kind of context to the user
  513. const err = new ERR_UNHANDLED_ERROR(stringifiedEr);
  514. err.context = er;
  515. throw err; // Unhandled 'error' event
  516. }
  517. const handler = events[type];
  518. if (handler === undefined)
  519. return false;
  520. if (typeof handler === 'function') {
  521. const result = handler.apply(this, args);
  522. // We check if result is undefined first because that
  523. // is the most common case so we do not pay any perf
  524. // penalty
  525. if (result !== undefined && result !== null) {
  526. addCatch(this, result, type, args);
  527. }
  528. } else {
  529. const len = handler.length;
  530. const listeners = arrayClone(handler);
  531. for (let i = 0; i < len; ++i) {
  532. const result = listeners[i].apply(this, args);
  533. // We check if result is undefined first because that
  534. // is the most common case so we do not pay any perf
  535. // penalty.
  536. // This code is duplicated because extracting it away
  537. // would make it non-inlineable.
  538. if (result !== undefined && result !== null) {
  539. addCatch(this, result, type, args);
  540. }
  541. }
  542. }
  543. return true;
  544. };
  545. function _addListener(target, type, listener, prepend) {
  546. let m;
  547. let events;
  548. let existing;
  549. checkListener(listener);
  550. events = target._events;
  551. if (events === undefined) {
  552. events = target._events = ObjectCreate(null);
  553. target._eventsCount = 0;
  554. } else {
  555. // To avoid recursion in the case that type === "newListener"! Before
  556. // adding it to the listeners, first emit "newListener".
  557. if (events.newListener !== undefined) {
  558. target.emit('newListener', type,
  559. nc(listener.listener, listener));
  560. // Re-assign `events` because a newListener handler could have caused the
  561. // this._events to be assigned to a new object
  562. events = target._events;
  563. }
  564. existing = events[type];
  565. }
  566. if (existing === undefined) {
  567. // Optimize the case of one listener. Don't need the extra array object.
  568. events[type] = listener;
  569. ++target._eventsCount;
  570. } else {
  571. if (typeof existing === 'function') {
  572. // Adding the second element, need to change to array.
  573. existing = events[type] =
  574. prepend ? [listener, existing] : [existing, listener];
  575. // If we've already got an array, just append.
  576. } else if (prepend) {
  577. existing.unshift(listener);
  578. } else {
  579. existing.push(listener);
  580. }
  581. // Check for listener leak
  582. m = _getMaxListeners(target);
  583. if (m > 0 && existing.length > m && !existing.warned) {
  584. existing.warned = true;
  585. // No error code for this since it is a Warning
  586. // eslint-disable-next-line no-restricted-syntax
  587. const w = new Error('Possible EventEmitter memory leak detected. ' +
  588. `${existing.length} ${String(type)} listeners ` +
  589. `added to ${inspect(target, { depth: -1 })}. Use ` +
  590. 'emitter.setMaxListeners() to increase limit');
  591. w.name = 'MaxListenersExceededWarning';
  592. w.emitter = target;
  593. w.type = type;
  594. w.count = existing.length;
  595. process.emitWarning(w);
  596. }
  597. }
  598. return target;
  599. }
  600. /**
  601. * Adds a listener to the event emitter.
  602. * @param {string | symbol} type
  603. * @param {Function} listener
  604. * @returns {EventEmitter}
  605. */
  606. EventEmitter.prototype.addListener = function addListener(type, listener) {
  607. return _addListener(this, type, listener, false);
  608. };
  609. EventEmitter.prototype.on = EventEmitter.prototype.addListener;
  610. /**
  611. * Adds the `listener` function to the beginning of
  612. * the listeners array.
  613. * @param {string | symbol} type
  614. * @param {Function} listener
  615. * @returns {EventEmitter}
  616. */
  617. EventEmitter.prototype.prependListener =
  618. function prependListener(type, listener) {
  619. return _addListener(this, type, listener, true);
  620. };
  621. function onceWrapper() {
  622. if (!this.fired) {
  623. this.target.removeListener(this.type, this.wrapFn);
  624. this.fired = true;
  625. if (arguments.length === 0)
  626. return this.listener.call(this.target);
  627. return this.listener.apply(this.target, arguments);
  628. }
  629. }
  630. function _onceWrap(target, type, listener) {
  631. const state = { fired: false, wrapFn: undefined, target, type, listener };
  632. const wrapped = onceWrapper.bind(state);
  633. wrapped.listener = listener;
  634. state.wrapFn = wrapped;
  635. return wrapped;
  636. }
  637. /**
  638. * Adds a one-time `listener` function to the event emitter.
  639. * @param {string | symbol} type
  640. * @param {Function} listener
  641. * @returns {EventEmitter}
  642. */
  643. EventEmitter.prototype.once = function once(type, listener) {
  644. checkListener(listener);
  645. this.on(type, _onceWrap(this, type, listener));
  646. return this;
  647. };
  648. /**
  649. * Adds a one-time `listener` function to the beginning of
  650. * the listeners array.
  651. * @param {string | symbol} type
  652. * @param {Function} listener
  653. * @returns {EventEmitter}
  654. */
  655. EventEmitter.prototype.prependOnceListener =
  656. function prependOnceListener(type, listener) {
  657. checkListener(listener);
  658. this.prependListener(type, _onceWrap(this, type, listener));
  659. return this;
  660. };
  661. /**
  662. * Removes the specified `listener` from the listeners array.
  663. * @param {string | symbol} type
  664. * @param {Function} listener
  665. * @returns {EventEmitter}
  666. */
  667. EventEmitter.prototype.removeListener =
  668. function removeListener(type, listener) {
  669. checkListener(listener);
  670. const events = this._events;
  671. if (events === undefined)
  672. return this;
  673. const list = events[type];
  674. if (list === undefined)
  675. return this;
  676. if (list === listener || list.listener === listener) {
  677. if (--this._eventsCount === 0)
  678. this._events = ObjectCreate(null);
  679. else {
  680. delete events[type];
  681. if (events.removeListener)
  682. this.emit('removeListener', type, list.listener || listener);
  683. }
  684. } else if (typeof list !== 'function') {
  685. let position = -1;
  686. for (let i = list.length - 1; i >= 0; i--) {
  687. if (list[i] === listener || list[i].listener === listener) {
  688. position = i;
  689. break;
  690. }
  691. }
  692. if (position < 0)
  693. return this;
  694. if (position === 0)
  695. list.shift();
  696. else {
  697. spliceOne(list, position);
  698. }
  699. if (list.length === 1)
  700. events[type] = list[0];
  701. if (events.removeListener !== undefined)
  702. this.emit('removeListener', type, listener);
  703. }
  704. return this;
  705. };
  706. EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
  707. /**
  708. * Removes all listeners from the event emitter. (Only
  709. * removes listeners for a specific event name if specified
  710. * as `type`).
  711. * @param {string | symbol} [type]
  712. * @returns {EventEmitter}
  713. */
  714. EventEmitter.prototype.removeAllListeners =
  715. function removeAllListeners(type) {
  716. const events = this._events;
  717. if (events === undefined)
  718. return this;
  719. // Not listening for removeListener, no need to emit
  720. if (events.removeListener === undefined) {
  721. if (arguments.length === 0) {
  722. this._events = ObjectCreate(null);
  723. this._eventsCount = 0;
  724. } else if (events[type] !== undefined) {
  725. if (--this._eventsCount === 0)
  726. this._events = ObjectCreate(null);
  727. else
  728. delete events[type];
  729. }
  730. return this;
  731. }
  732. // Emit removeListener for all listeners on all events
  733. if (arguments.length === 0) {
  734. for (const key of ReflectOwnKeys(events)) {
  735. if (key === 'removeListener') continue;
  736. this.removeAllListeners(key);
  737. }
  738. this.removeAllListeners('removeListener');
  739. this._events = ObjectCreate(null);
  740. this._eventsCount = 0;
  741. return this;
  742. }
  743. const listeners = events[type];
  744. if (typeof listeners === 'function') {
  745. this.removeListener(type, listeners);
  746. } else if (listeners !== undefined) {
  747. // LIFO order
  748. for (let i = listeners.length - 1; i >= 0; i--) {
  749. this.removeListener(type, listeners[i]);
  750. }
  751. }
  752. return this;
  753. };
  754. function _listeners(target, type, unwrap) {
  755. const events = target._events;
  756. if (events === undefined)
  757. return [];
  758. const evlistener = events[type];
  759. if (evlistener === undefined)
  760. return [];
  761. if (typeof evlistener === 'function')
  762. return unwrap ? [evlistener.listener || evlistener] : [evlistener];
  763. return unwrap ?
  764. unwrapListeners(evlistener) : arrayClone(evlistener);
  765. }
  766. /**
  767. * Returns a copy of the array of listeners for the event name
  768. * specified as `type`.
  769. * @param {string | symbol} type
  770. * @returns {Function[]}
  771. */
  772. EventEmitter.prototype.listeners = function listeners(type) {
  773. return _listeners(this, type, true);
  774. };
  775. /**
  776. * Returns a copy of the array of listeners and wrappers for
  777. * the event name specified as `type`.
  778. * @param {string | symbol} type
  779. * @returns {Function[]}
  780. */
  781. EventEmitter.prototype.rawListeners = function rawListeners(type) {
  782. return _listeners(this, type, false);
  783. };
  784. /**
  785. * Returns the number of listeners listening to the event name
  786. * specified as `type`.
  787. * @deprecated since v3.2.0
  788. * @param {EventEmitter} emitter
  789. * @param {string | symbol} type
  790. * @returns {number}
  791. */
  792. EventEmitter.listenerCount = function(emitter, type) {
  793. if (typeof emitter.listenerCount === 'function') {
  794. return emitter.listenerCount(type);
  795. }
  796. return emitter.listenerCount(type);
  797. };
  798. EventEmitter.prototype.listenerCount = listenerCount;
  799. /**
  800. * Returns the number of listeners listening to event name
  801. * specified as `type`.
  802. * @param {string | symbol} type
  803. * @returns {number}
  804. */
  805. function listenerCount(type) {
  806. const events = this._events;
  807. if (events !== undefined) {
  808. const evlistener = events[type];
  809. if (typeof evlistener === 'function') {
  810. return 1;
  811. } else if (evlistener !== undefined) {
  812. return evlistener.length;
  813. }
  814. }
  815. return 0;
  816. }
  817. /**
  818. * Returns an array listing the events for which
  819. * the emitter has registered listeners.
  820. * @returns {any[]}
  821. */
  822. EventEmitter.prototype.eventNames = function eventNames() {
  823. return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : [];
  824. };
  825. function arrayClone(arr) {
  826. // At least since V8 8.3, this implementation is faster than the previous
  827. // which always used a simple for-loop
  828. switch (arr.length) {
  829. case 2: return [arr[0], arr[1]];
  830. case 3: return [arr[0], arr[1], arr[2]];
  831. case 4: return [arr[0], arr[1], arr[2], arr[3]];
  832. case 5: return [arr[0], arr[1], arr[2], arr[3], arr[4]];
  833. case 6: return [arr[0], arr[1], arr[2], arr[3], arr[4], arr[5]];
  834. }
  835. return ArrayPrototypeSlice(arr);
  836. }
  837. function unwrapListeners(arr) {
  838. const ret = arrayClone(arr);
  839. for (let i = 0; i < ret.length; ++i) {
  840. const orig = ret[i].listener;
  841. if (typeof orig === 'function')
  842. ret[i] = orig;
  843. }
  844. return ret;
  845. }