index.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  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. 'use strict';
  22. var R = typeof Reflect === 'object' ? Reflect : null;
  23. var ReflectApply =
  24. R && typeof R.apply === 'function'
  25. ? R.apply
  26. : function ReflectApply(target, receiver, args) {
  27. return Function.prototype.apply.call(target, receiver, args);
  28. };
  29. var ReflectOwnKeys;
  30. if (R && typeof R.ownKeys === 'function') {
  31. ReflectOwnKeys = R.ownKeys;
  32. } else if (Object.getOwnPropertySymbols) {
  33. ReflectOwnKeys = function ReflectOwnKeys(target) {
  34. return Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target));
  35. };
  36. } else {
  37. ReflectOwnKeys = function ReflectOwnKeys(target) {
  38. return Object.getOwnPropertyNames(target);
  39. };
  40. }
  41. function ProcessEmitWarning(warning) {
  42. if (console && console.warn) console.warn(warning);
  43. }
  44. var NumberIsNaN =
  45. Number.isNaN ||
  46. function NumberIsNaN(value) {
  47. return value !== value;
  48. };
  49. function EventEmitter() {
  50. EventEmitter.init.call(this);
  51. }
  52. module.exports = EventEmitter;
  53. module.exports.once = once;
  54. // Backwards-compat with node 0.10.x
  55. EventEmitter.EventEmitter = EventEmitter;
  56. EventEmitter.prototype._events = undefined;
  57. EventEmitter.prototype._eventsCount = 0;
  58. EventEmitter.prototype._maxListeners = undefined;
  59. // By default EventEmitters will print a warning if more than 10 listeners are
  60. // added to it. This is a useful default which helps finding memory leaks.
  61. var defaultMaxListeners = 10;
  62. function checkListener(listener) {
  63. if (typeof listener !== 'function') {
  64. throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener);
  65. }
  66. }
  67. Object.defineProperty(EventEmitter, 'defaultMaxListeners', {
  68. enumerable: true,
  69. get: function () {
  70. return defaultMaxListeners;
  71. },
  72. set: function (arg) {
  73. if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) {
  74. throw new RangeError(
  75. 'The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received ' + arg + '.'
  76. );
  77. }
  78. defaultMaxListeners = arg;
  79. },
  80. });
  81. EventEmitter.init = function () {
  82. if (this._events === undefined || this._events === Object.getPrototypeOf(this)._events) {
  83. this._events = Object.create(null);
  84. this._eventsCount = 0;
  85. }
  86. this._maxListeners = this._maxListeners || undefined;
  87. };
  88. // Obviously not all Emitters should be limited to 10. This function allows
  89. // that to be increased. Set to zero for unlimited.
  90. EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {
  91. if (typeof n !== 'number' || n < 0 || NumberIsNaN(n)) {
  92. throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + n + '.');
  93. }
  94. this._maxListeners = n;
  95. return this;
  96. };
  97. function _getMaxListeners(that) {
  98. if (that._maxListeners === undefined) return EventEmitter.defaultMaxListeners;
  99. return that._maxListeners;
  100. }
  101. EventEmitter.prototype.getMaxListeners = function getMaxListeners() {
  102. return _getMaxListeners(this);
  103. };
  104. EventEmitter.prototype.emit = function emit(type) {
  105. var args = [];
  106. for (var i = 1; i < arguments.length; i++) args.push(arguments[i]);
  107. var doError = type === 'error';
  108. var events = this._events;
  109. if (events !== undefined) doError = doError && events.error === undefined;
  110. else if (!doError) return false;
  111. // If there is no 'error' event listener then throw.
  112. if (doError) {
  113. var er;
  114. if (args.length > 0) er = args[0];
  115. if (er instanceof Error) {
  116. // Note: The comments on the `throw` lines are intentional, they show
  117. // up in Node's output if this results in an unhandled exception.
  118. throw er; // Unhandled 'error' event
  119. }
  120. // At least give some kind of context to the user
  121. var err = new Error('Unhandled error.' + (er ? ' (' + er.message + ')' : ''));
  122. err.context = er;
  123. throw err; // Unhandled 'error' event
  124. }
  125. var handler = events[type];
  126. if (handler === undefined) return false;
  127. if (typeof handler === 'function') {
  128. ReflectApply(handler, this, args);
  129. } else {
  130. var len = handler.length;
  131. var listeners = arrayClone(handler, len);
  132. for (var i = 0; i < len; ++i) ReflectApply(listeners[i], this, args);
  133. }
  134. return true;
  135. };
  136. function _addListener(target, type, listener, prepend) {
  137. var m;
  138. var events;
  139. var existing;
  140. checkListener(listener);
  141. events = target._events;
  142. if (events === undefined) {
  143. events = target._events = Object.create(null);
  144. target._eventsCount = 0;
  145. } else {
  146. // To avoid recursion in the case that type === "newListener"! Before
  147. // adding it to the listeners, first emit "newListener".
  148. if (events.newListener !== undefined) {
  149. target.emit('newListener', type, listener.listener ? listener.listener : listener);
  150. // Re-assign `events` because a newListener handler could have caused the
  151. // this._events to be assigned to a new object
  152. events = target._events;
  153. }
  154. existing = events[type];
  155. }
  156. if (existing === undefined) {
  157. // Optimize the case of one listener. Don't need the extra array object.
  158. existing = events[type] = listener;
  159. ++target._eventsCount;
  160. } else {
  161. if (typeof existing === 'function') {
  162. // Adding the second element, need to change to array.
  163. existing = events[type] = prepend ? [listener, existing] : [existing, listener];
  164. // If we've already got an array, just append.
  165. } else if (prepend) {
  166. existing.unshift(listener);
  167. } else {
  168. existing.push(listener);
  169. }
  170. // Check for listener leak
  171. m = _getMaxListeners(target);
  172. if (m > 0 && existing.length > m && !existing.warned) {
  173. existing.warned = true;
  174. // No error code for this since it is a Warning
  175. // eslint-disable-next-line no-restricted-syntax
  176. var w = new Error(
  177. 'Possible EventEmitter memory leak detected. ' +
  178. existing.length +
  179. ' ' +
  180. String(type) +
  181. ' listeners ' +
  182. 'added. Use emitter.setMaxListeners() to ' +
  183. 'increase limit'
  184. );
  185. w.name = 'MaxListenersExceededWarning';
  186. w.emitter = target;
  187. w.type = type;
  188. w.count = existing.length;
  189. ProcessEmitWarning(w);
  190. }
  191. }
  192. return target;
  193. }
  194. EventEmitter.prototype.addListener = function addListener(type, listener) {
  195. return _addListener(this, type, listener, false);
  196. };
  197. EventEmitter.prototype.on = EventEmitter.prototype.addListener;
  198. EventEmitter.prototype.prependListener = function prependListener(type, listener) {
  199. return _addListener(this, type, listener, true);
  200. };
  201. function onceWrapper() {
  202. if (!this.fired) {
  203. this.target.removeListener(this.type, this.wrapFn);
  204. this.fired = true;
  205. if (arguments.length === 0) return this.listener.call(this.target);
  206. return this.listener.apply(this.target, arguments);
  207. }
  208. }
  209. function _onceWrap(target, type, listener) {
  210. var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener };
  211. var wrapped = onceWrapper.bind(state);
  212. wrapped.listener = listener;
  213. state.wrapFn = wrapped;
  214. return wrapped;
  215. }
  216. EventEmitter.prototype.once = function once(type, listener) {
  217. checkListener(listener);
  218. this.on(type, _onceWrap(this, type, listener));
  219. return this;
  220. };
  221. EventEmitter.prototype.prependOnceListener = function prependOnceListener(type, listener) {
  222. checkListener(listener);
  223. this.prependListener(type, _onceWrap(this, type, listener));
  224. return this;
  225. };
  226. // Emits a 'removeListener' event if and only if the listener was removed.
  227. EventEmitter.prototype.removeListener = function removeListener(type, listener) {
  228. var list, events, position, i, originalListener;
  229. checkListener(listener);
  230. events = this._events;
  231. if (events === undefined) return this;
  232. list = events[type];
  233. if (list === undefined) return this;
  234. if (list === listener || list.listener === listener) {
  235. if (--this._eventsCount === 0) this._events = Object.create(null);
  236. else {
  237. delete events[type];
  238. if (events.removeListener) this.emit('removeListener', type, list.listener || listener);
  239. }
  240. } else if (typeof list !== 'function') {
  241. position = -1;
  242. for (i = list.length - 1; i >= 0; i--) {
  243. if (list[i] === listener || list[i].listener === listener) {
  244. originalListener = list[i].listener;
  245. position = i;
  246. break;
  247. }
  248. }
  249. if (position < 0) return this;
  250. if (position === 0) list.shift();
  251. else {
  252. spliceOne(list, position);
  253. }
  254. if (list.length === 1) events[type] = list[0];
  255. if (events.removeListener !== undefined) this.emit('removeListener', type, originalListener || listener);
  256. }
  257. return this;
  258. };
  259. EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
  260. EventEmitter.prototype.removeAllListeners = function removeAllListeners(type) {
  261. var listeners, events, i;
  262. events = this._events;
  263. if (events === undefined) return this;
  264. // not listening for removeListener, no need to emit
  265. if (events.removeListener === undefined) {
  266. if (arguments.length === 0) {
  267. this._events = Object.create(null);
  268. this._eventsCount = 0;
  269. } else if (events[type] !== undefined) {
  270. if (--this._eventsCount === 0) this._events = Object.create(null);
  271. else delete events[type];
  272. }
  273. return this;
  274. }
  275. // emit removeListener for all listeners on all events
  276. if (arguments.length === 0) {
  277. var keys = Object.keys(events);
  278. var key;
  279. for (i = 0; i < keys.length; ++i) {
  280. key = keys[i];
  281. if (key === 'removeListener') continue;
  282. this.removeAllListeners(key);
  283. }
  284. this.removeAllListeners('removeListener');
  285. this._events = Object.create(null);
  286. this._eventsCount = 0;
  287. return this;
  288. }
  289. listeners = events[type];
  290. if (typeof listeners === 'function') {
  291. this.removeListener(type, listeners);
  292. } else if (listeners !== undefined) {
  293. // LIFO order
  294. for (i = listeners.length - 1; i >= 0; i--) {
  295. this.removeListener(type, listeners[i]);
  296. }
  297. }
  298. return this;
  299. };
  300. function _listeners(target, type, unwrap) {
  301. var events = target._events;
  302. if (events === undefined) return [];
  303. var evlistener = events[type];
  304. if (evlistener === undefined) return [];
  305. if (typeof evlistener === 'function') return unwrap ? [evlistener.listener || evlistener] : [evlistener];
  306. return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length);
  307. }
  308. EventEmitter.prototype.listeners = function listeners(type) {
  309. return _listeners(this, type, true);
  310. };
  311. EventEmitter.prototype.rawListeners = function rawListeners(type) {
  312. return _listeners(this, type, false);
  313. };
  314. EventEmitter.listenerCount = function (emitter, type) {
  315. if (typeof emitter.listenerCount === 'function') {
  316. return emitter.listenerCount(type);
  317. } else {
  318. return listenerCount.call(emitter, type);
  319. }
  320. };
  321. EventEmitter.prototype.listenerCount = listenerCount;
  322. function listenerCount(type) {
  323. var events = this._events;
  324. if (events !== undefined) {
  325. var evlistener = events[type];
  326. if (typeof evlistener === 'function') {
  327. return 1;
  328. } else if (evlistener !== undefined) {
  329. return evlistener.length;
  330. }
  331. }
  332. return 0;
  333. }
  334. EventEmitter.prototype.eventNames = function eventNames() {
  335. return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : [];
  336. };
  337. function arrayClone(arr, n) {
  338. var copy = new Array(n);
  339. for (var i = 0; i < n; ++i) copy[i] = arr[i];
  340. return copy;
  341. }
  342. function spliceOne(list, index) {
  343. for (; index + 1 < list.length; index++) list[index] = list[index + 1];
  344. list.pop();
  345. }
  346. function unwrapListeners(arr) {
  347. var ret = new Array(arr.length);
  348. for (var i = 0; i < ret.length; ++i) {
  349. ret[i] = arr[i].listener || arr[i];
  350. }
  351. return ret;
  352. }
  353. function once(emitter, name) {
  354. return new Promise(function (resolve, reject) {
  355. function errorListener(err) {
  356. emitter.removeListener(name, resolver);
  357. reject(err);
  358. }
  359. function resolver() {
  360. if (typeof emitter.removeListener === 'function') {
  361. emitter.removeListener('error', errorListener);
  362. }
  363. resolve([].slice.call(arguments));
  364. }
  365. eventTargetAgnosticAddListener(emitter, name, resolver, { once: true });
  366. if (name !== 'error') {
  367. addErrorHandlerIfEventEmitter(emitter, errorListener, { once: true });
  368. }
  369. });
  370. }
  371. function addErrorHandlerIfEventEmitter(emitter, handler, flags) {
  372. if (typeof emitter.on === 'function') {
  373. eventTargetAgnosticAddListener(emitter, 'error', handler, flags);
  374. }
  375. }
  376. function eventTargetAgnosticAddListener(emitter, name, listener, flags) {
  377. if (typeof emitter.on === 'function') {
  378. if (flags.once) {
  379. emitter.once(name, listener);
  380. } else {
  381. emitter.on(name, listener);
  382. }
  383. } else if (typeof emitter.addEventListener === 'function') {
  384. // EventTarget does not have `error` event semantics like Node
  385. // EventEmitters, we do not listen for `error` events here.
  386. emitter.addEventListener(name, function wrapListener(arg) {
  387. // IE does not have builtin `{ once: true }` support so we
  388. // have to do it manually.
  389. if (flags.once) {
  390. emitter.removeEventListener(name, wrapListener);
  391. }
  392. listener(arg);
  393. });
  394. } else {
  395. throw new TypeError('The "emitter" argument must be of type EventEmitter. Received type ' + typeof emitter);
  396. }
  397. }