123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977 |
- // Copyright Joyent, Inc. and other Node contributors.
- //
- // Permission is hereby granted, free of charge, to any person obtaining a
- // copy of this software and associated documentation files (the
- // "Software"), to deal in the Software without restriction, including
- // without limitation the rights to use, copy, modify, merge, publish,
- // distribute, sublicense, and/or sell copies of the Software, and to permit
- // persons to whom the Software is furnished to do so, subject to the
- // following conditions:
- //
- // The above copyright notice and this permission notice shall be included
- // in all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
- // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
- // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- // USE OR OTHER DEALINGS IN THE SOFTWARE.
- // Modified by the vm2 team to make this a standalone module to be loaded into the sandbox.
- 'use strict';
- const host = fromhost;
- const {
- Boolean,
- Error,
- String,
- Symbol
- } = globalThis;
- const ReflectApply = Reflect.apply;
- const ReflectOwnKeys = Reflect.ownKeys;
- const ErrorCaptureStackTrace = Error.captureStackTrace;
- const NumberIsNaN = Number.isNaN;
- const ObjectCreate = Object.create;
- const ObjectDefineProperty = Object.defineProperty;
- const ObjectDefineProperties = Object.defineProperties;
- const ObjectGetPrototypeOf = Object.getPrototypeOf;
- const SymbolFor = Symbol.for;
- function uncurryThis(func) {
- return (thiz, ...args) => ReflectApply(func, thiz, args);
- }
- const ArrayPrototypeIndexOf = uncurryThis(Array.prototype.indexOf);
- const ArrayPrototypeJoin = uncurryThis(Array.prototype.join);
- const ArrayPrototypeSlice = uncurryThis(Array.prototype.slice);
- const ArrayPrototypeSplice = uncurryThis(Array.prototype.splice);
- const ArrayPrototypeUnshift = uncurryThis(Array.prototype.unshift);
- const kRejection = SymbolFor('nodejs.rejection');
- function inspect(obj) {
- return typeof obj === 'symbol' ? obj.toString() : `${obj}`;
- }
- function spliceOne(list, index) {
- for (; index + 1 < list.length; index++)
- list[index] = list[index + 1];
- list.pop();
- }
- function assert(what, message) {
- if (!what) throw new Error(message);
- }
- function E(key, msg, Base) {
- return function NodeError(...args) {
- const error = new Base();
- const message = ReflectApply(msg, error, args);
- ObjectDefineProperties(error, {
- message: {
- value: message,
- enumerable: false,
- writable: true,
- configurable: true,
- },
- toString: {
- value() {
- return `${this.name} [${key}]: ${this.message}`;
- },
- enumerable: false,
- writable: true,
- configurable: true,
- },
- });
- error.code = key;
- return error;
- };
- }
- const ERR_INVALID_ARG_TYPE = E('ERR_INVALID_ARG_TYPE',
- (name, expected, actual) => {
- assert(typeof name === 'string', "'name' must be a string");
- if (!ArrayIsArray(expected)) {
- expected = [expected];
- }
- let msg = 'The ';
- if (StringPrototypeEndsWith(name, ' argument')) {
- // For cases like 'first argument'
- msg += `${name} `;
- } else {
- const type = StringPrototypeIncludes(name, '.') ? 'property' : 'argument';
- msg += `"${name}" ${type} `;
- }
- msg += 'must be ';
- const types = [];
- const instances = [];
- const other = [];
- for (const value of expected) {
- assert(typeof value === 'string',
- 'All expected entries have to be of type string');
- if (ArrayPrototypeIncludes(kTypes, value)) {
- ArrayPrototypePush(types, StringPrototypeToLowerCase(value));
- } else if (RegExpPrototypeTest(classRegExp, value)) {
- ArrayPrototypePush(instances, value);
- } else {
- assert(value !== 'object',
- 'The value "object" should be written as "Object"');
- ArrayPrototypePush(other, value);
- }
- }
- // Special handle `object` in case other instances are allowed to outline
- // the differences between each other.
- if (instances.length > 0) {
- const pos = ArrayPrototypeIndexOf(types, 'object');
- if (pos !== -1) {
- ArrayPrototypeSplice(types, pos, 1);
- ArrayPrototypePush(instances, 'Object');
- }
- }
- if (types.length > 0) {
- if (types.length > 2) {
- const last = ArrayPrototypePop(types);
- msg += `one of type ${ArrayPrototypeJoin(types, ', ')}, or ${last}`;
- } else if (types.length === 2) {
- msg += `one of type ${types[0]} or ${types[1]}`;
- } else {
- msg += `of type ${types[0]}`;
- }
- if (instances.length > 0 || other.length > 0)
- msg += ' or ';
- }
- if (instances.length > 0) {
- if (instances.length > 2) {
- const last = ArrayPrototypePop(instances);
- msg +=
- `an instance of ${ArrayPrototypeJoin(instances, ', ')}, or ${last}`;
- } else {
- msg += `an instance of ${instances[0]}`;
- if (instances.length === 2) {
- msg += ` or ${instances[1]}`;
- }
- }
- if (other.length > 0)
- msg += ' or ';
- }
- if (other.length > 0) {
- if (other.length > 2) {
- const last = ArrayPrototypePop(other);
- msg += `one of ${ArrayPrototypeJoin(other, ', ')}, or ${last}`;
- } else if (other.length === 2) {
- msg += `one of ${other[0]} or ${other[1]}`;
- } else {
- if (StringPrototypeToLowerCase(other[0]) !== other[0])
- msg += 'an ';
- msg += `${other[0]}`;
- }
- }
- if (actual == null) {
- msg += `. Received ${actual}`;
- } else if (typeof actual === 'function' && actual.name) {
- msg += `. Received function ${actual.name}`;
- } else if (typeof actual === 'object') {
- if (actual.constructor && actual.constructor.name) {
- msg += `. Received an instance of ${actual.constructor.name}`;
- } else {
- const inspected = inspect(actual, { depth: -1 });
- msg += `. Received ${inspected}`;
- }
- } else {
- let inspected = inspect(actual, { colors: false });
- if (inspected.length > 25)
- inspected = `${StringPrototypeSlice(inspected, 0, 25)}...`;
- msg += `. Received type ${typeof actual} (${inspected})`;
- }
- return msg;
- }, TypeError);
- const ERR_INVALID_THIS = E('ERR_INVALID_THIS', s => `Value of "this" must be of type ${s}`, TypeError);
- const ERR_OUT_OF_RANGE = E('ERR_OUT_OF_RANGE',
- (str, range, input, replaceDefaultBoolean = false) => {
- assert(range, 'Missing "range" argument');
- let msg = replaceDefaultBoolean ? str :
- `The value of "${str}" is out of range.`;
- const received = inspect(input);
- msg += ` It must be ${range}. Received ${received}`;
- return msg;
- }, RangeError);
- const ERR_UNHANDLED_ERROR = E('ERR_UNHANDLED_ERROR',
- err => {
- const msg = 'Unhandled error.';
- if (err === undefined) return msg;
- return `${msg} (${err})`;
- }, Error);
- function validateBoolean(value, name) {
- if (typeof value !== 'boolean')
- throw new ERR_INVALID_ARG_TYPE(name, 'boolean', value);
- }
- function validateFunction(value, name) {
- if (typeof value !== 'function')
- throw new ERR_INVALID_ARG_TYPE(name, 'Function', value);
- }
- function validateString(value, name) {
- if (typeof value !== 'string')
- throw new ERR_INVALID_ARG_TYPE(name, 'string', value);
- }
- function nc(cond, e) {
- return cond === undefined || cond === null ? e : cond;
- }
- function oc(base, key) {
- return base === undefined || base === null ? undefined : base[key];
- }
- const kCapture = Symbol('kCapture');
- const kErrorMonitor = host.kErrorMonitor || Symbol('events.errorMonitor');
- const kMaxEventTargetListeners = Symbol('events.maxEventTargetListeners');
- const kMaxEventTargetListenersWarned =
- Symbol('events.maxEventTargetListenersWarned');
- const kIsEventTarget = SymbolFor('nodejs.event_target');
- function isEventTarget(obj) {
- return oc(oc(obj, 'constructor'), kIsEventTarget);
- }
- /**
- * Creates a new `EventEmitter` instance.
- * @param {{ captureRejections?: boolean; }} [opts]
- * @constructs {EventEmitter}
- */
- function EventEmitter(opts) {
- EventEmitter.init.call(this, opts);
- }
- module.exports = EventEmitter;
- if (host.once) module.exports.once = host.once;
- if (host.on) module.exports.on = host.on;
- if (host.getEventListeners) module.exports.getEventListeners = host.getEventListeners;
- // Backwards-compat with node 0.10.x
- EventEmitter.EventEmitter = EventEmitter;
- EventEmitter.usingDomains = false;
- EventEmitter.captureRejectionSymbol = kRejection;
- ObjectDefineProperty(EventEmitter, 'captureRejections', {
- get() {
- return EventEmitter.prototype[kCapture];
- },
- set(value) {
- validateBoolean(value, 'EventEmitter.captureRejections');
- EventEmitter.prototype[kCapture] = value;
- },
- enumerable: true
- });
- if (host.EventEmitterReferencingAsyncResource) {
- const kAsyncResource = Symbol('kAsyncResource');
- const EventEmitterReferencingAsyncResource = host.EventEmitterReferencingAsyncResource;
- class EventEmitterAsyncResource extends EventEmitter {
- /**
- * @param {{
- * name?: string,
- * triggerAsyncId?: number,
- * requireManualDestroy?: boolean,
- * }} [options]
- */
- constructor(options = undefined) {
- let name;
- if (typeof options === 'string') {
- name = options;
- options = undefined;
- } else {
- if (new.target === EventEmitterAsyncResource) {
- validateString(oc(options, 'name'), 'options.name');
- }
- name = oc(options, 'name') || new.target.name;
- }
- super(options);
- this[kAsyncResource] =
- new EventEmitterReferencingAsyncResource(this, name, options);
- }
- /**
- * @param {symbol,string} event
- * @param {...any} args
- * @returns {boolean}
- */
- emit(event, ...args) {
- if (this[kAsyncResource] === undefined)
- throw new ERR_INVALID_THIS('EventEmitterAsyncResource');
- const { asyncResource } = this;
- ArrayPrototypeUnshift(args, super.emit, this, event);
- return ReflectApply(asyncResource.runInAsyncScope, asyncResource,
- args);
- }
- /**
- * @returns {void}
- */
- emitDestroy() {
- if (this[kAsyncResource] === undefined)
- throw new ERR_INVALID_THIS('EventEmitterAsyncResource');
- this.asyncResource.emitDestroy();
- }
- /**
- * @type {number}
- */
- get asyncId() {
- if (this[kAsyncResource] === undefined)
- throw new ERR_INVALID_THIS('EventEmitterAsyncResource');
- return this.asyncResource.asyncId();
- }
- /**
- * @type {number}
- */
- get triggerAsyncId() {
- if (this[kAsyncResource] === undefined)
- throw new ERR_INVALID_THIS('EventEmitterAsyncResource');
- return this.asyncResource.triggerAsyncId();
- }
- /**
- * @type {EventEmitterReferencingAsyncResource}
- */
- get asyncResource() {
- if (this[kAsyncResource] === undefined)
- throw new ERR_INVALID_THIS('EventEmitterAsyncResource');
- return this[kAsyncResource];
- }
- }
- EventEmitter.EventEmitterAsyncResource = EventEmitterAsyncResource;
- }
- EventEmitter.errorMonitor = kErrorMonitor;
- // The default for captureRejections is false
- ObjectDefineProperty(EventEmitter.prototype, kCapture, {
- value: false,
- writable: true,
- enumerable: false
- });
- EventEmitter.prototype._events = undefined;
- EventEmitter.prototype._eventsCount = 0;
- EventEmitter.prototype._maxListeners = undefined;
- // By default EventEmitters will print a warning if more than 10 listeners are
- // added to it. This is a useful default which helps finding memory leaks.
- let defaultMaxListeners = 10;
- function checkListener(listener) {
- validateFunction(listener, 'listener');
- }
- ObjectDefineProperty(EventEmitter, 'defaultMaxListeners', {
- enumerable: true,
- get: function() {
- return defaultMaxListeners;
- },
- set: function(arg) {
- if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) {
- throw new ERR_OUT_OF_RANGE('defaultMaxListeners',
- 'a non-negative number',
- arg);
- }
- defaultMaxListeners = arg;
- }
- });
- ObjectDefineProperties(EventEmitter, {
- kMaxEventTargetListeners: {
- value: kMaxEventTargetListeners,
- enumerable: false,
- configurable: false,
- writable: false,
- },
- kMaxEventTargetListenersWarned: {
- value: kMaxEventTargetListenersWarned,
- enumerable: false,
- configurable: false,
- writable: false,
- }
- });
- /**
- * Sets the max listeners.
- * @param {number} n
- * @param {EventTarget[] | EventEmitter[]} [eventTargets]
- * @returns {void}
- */
- EventEmitter.setMaxListeners =
- function(n = defaultMaxListeners, ...eventTargets) {
- if (typeof n !== 'number' || n < 0 || NumberIsNaN(n))
- throw new ERR_OUT_OF_RANGE('n', 'a non-negative number', n);
- if (eventTargets.length === 0) {
- defaultMaxListeners = n;
- } else {
- for (let i = 0; i < eventTargets.length; i++) {
- const target = eventTargets[i];
- if (isEventTarget(target)) {
- target[kMaxEventTargetListeners] = n;
- target[kMaxEventTargetListenersWarned] = false;
- } else if (typeof target.setMaxListeners === 'function') {
- target.setMaxListeners(n);
- } else {
- throw new ERR_INVALID_ARG_TYPE(
- 'eventTargets',
- ['EventEmitter', 'EventTarget'],
- target);
- }
- }
- }
- };
- // If you're updating this function definition, please also update any
- // re-definitions, such as the one in the Domain module (lib/domain.js).
- EventEmitter.init = function(opts) {
- if (this._events === undefined ||
- this._events === ObjectGetPrototypeOf(this)._events) {
- this._events = ObjectCreate(null);
- this._eventsCount = 0;
- }
- this._maxListeners = this._maxListeners || undefined;
- if (oc(opts, 'captureRejections')) {
- validateBoolean(opts.captureRejections, 'options.captureRejections');
- this[kCapture] = Boolean(opts.captureRejections);
- } else {
- // Assigning the kCapture property directly saves an expensive
- // prototype lookup in a very sensitive hot path.
- this[kCapture] = EventEmitter.prototype[kCapture];
- }
- };
- function addCatch(that, promise, type, args) {
- if (!that[kCapture]) {
- return;
- }
- // Handle Promises/A+ spec, then could be a getter
- // that throws on second use.
- try {
- const then = promise.then;
- if (typeof then === 'function') {
- then.call(promise, undefined, function(err) {
- // The callback is called with nextTick to avoid a follow-up
- // rejection from this promise.
- process.nextTick(emitUnhandledRejectionOrErr, that, err, type, args);
- });
- }
- } catch (err) {
- that.emit('error', err);
- }
- }
- function emitUnhandledRejectionOrErr(ee, err, type, args) {
- if (typeof ee[kRejection] === 'function') {
- ee[kRejection](err, type, ...args);
- } else {
- // We have to disable the capture rejections mechanism, otherwise
- // we might end up in an infinite loop.
- const prev = ee[kCapture];
- // If the error handler throws, it is not catchable and it
- // will end up in 'uncaughtException'. We restore the previous
- // value of kCapture in case the uncaughtException is present
- // and the exception is handled.
- try {
- ee[kCapture] = false;
- ee.emit('error', err);
- } finally {
- ee[kCapture] = prev;
- }
- }
- }
- /**
- * Increases the max listeners of the event emitter.
- * @param {number} n
- * @returns {EventEmitter}
- */
- EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {
- if (typeof n !== 'number' || n < 0 || NumberIsNaN(n)) {
- throw new ERR_OUT_OF_RANGE('n', 'a non-negative number', n);
- }
- this._maxListeners = n;
- return this;
- };
- function _getMaxListeners(that) {
- if (that._maxListeners === undefined)
- return EventEmitter.defaultMaxListeners;
- return that._maxListeners;
- }
- /**
- * Returns the current max listener value for the event emitter.
- * @returns {number}
- */
- EventEmitter.prototype.getMaxListeners = function getMaxListeners() {
- return _getMaxListeners(this);
- };
- /**
- * Synchronously calls each of the listeners registered
- * for the event.
- * @param {string | symbol} type
- * @param {...any} [args]
- * @returns {boolean}
- */
- EventEmitter.prototype.emit = function emit(type, ...args) {
- let doError = (type === 'error');
- const events = this._events;
- if (events !== undefined) {
- if (doError && events[kErrorMonitor] !== undefined)
- this.emit(kErrorMonitor, ...args);
- doError = (doError && events.error === undefined);
- } else if (!doError)
- return false;
- // If there is no 'error' event listener then throw.
- if (doError) {
- let er;
- if (args.length > 0)
- er = args[0];
- if (er instanceof Error) {
- try {
- const capture = {};
- ErrorCaptureStackTrace(capture, EventEmitter.prototype.emit);
- } catch (e) {}
- // Note: The comments on the `throw` lines are intentional, they show
- // up in Node's output if this results in an unhandled exception.
- throw er; // Unhandled 'error' event
- }
- let stringifiedEr;
- try {
- stringifiedEr = inspect(er);
- } catch (e) {
- stringifiedEr = er;
- }
- // At least give some kind of context to the user
- const err = new ERR_UNHANDLED_ERROR(stringifiedEr);
- err.context = er;
- throw err; // Unhandled 'error' event
- }
- const handler = events[type];
- if (handler === undefined)
- return false;
- if (typeof handler === 'function') {
- const result = handler.apply(this, args);
- // We check if result is undefined first because that
- // is the most common case so we do not pay any perf
- // penalty
- if (result !== undefined && result !== null) {
- addCatch(this, result, type, args);
- }
- } else {
- const len = handler.length;
- const listeners = arrayClone(handler);
- for (let i = 0; i < len; ++i) {
- const result = listeners[i].apply(this, args);
- // We check if result is undefined first because that
- // is the most common case so we do not pay any perf
- // penalty.
- // This code is duplicated because extracting it away
- // would make it non-inlineable.
- if (result !== undefined && result !== null) {
- addCatch(this, result, type, args);
- }
- }
- }
- return true;
- };
- function _addListener(target, type, listener, prepend) {
- let m;
- let events;
- let existing;
- checkListener(listener);
- events = target._events;
- if (events === undefined) {
- events = target._events = ObjectCreate(null);
- target._eventsCount = 0;
- } else {
- // To avoid recursion in the case that type === "newListener"! Before
- // adding it to the listeners, first emit "newListener".
- if (events.newListener !== undefined) {
- target.emit('newListener', type,
- nc(listener.listener, listener));
- // Re-assign `events` because a newListener handler could have caused the
- // this._events to be assigned to a new object
- events = target._events;
- }
- existing = events[type];
- }
- if (existing === undefined) {
- // Optimize the case of one listener. Don't need the extra array object.
- events[type] = listener;
- ++target._eventsCount;
- } else {
- if (typeof existing === 'function') {
- // Adding the second element, need to change to array.
- existing = events[type] =
- prepend ? [listener, existing] : [existing, listener];
- // If we've already got an array, just append.
- } else if (prepend) {
- existing.unshift(listener);
- } else {
- existing.push(listener);
- }
- // Check for listener leak
- m = _getMaxListeners(target);
- if (m > 0 && existing.length > m && !existing.warned) {
- existing.warned = true;
- // No error code for this since it is a Warning
- // eslint-disable-next-line no-restricted-syntax
- const w = new Error('Possible EventEmitter memory leak detected. ' +
- `${existing.length} ${String(type)} listeners ` +
- `added to ${inspect(target, { depth: -1 })}. Use ` +
- 'emitter.setMaxListeners() to increase limit');
- w.name = 'MaxListenersExceededWarning';
- w.emitter = target;
- w.type = type;
- w.count = existing.length;
- process.emitWarning(w);
- }
- }
- return target;
- }
- /**
- * Adds a listener to the event emitter.
- * @param {string | symbol} type
- * @param {Function} listener
- * @returns {EventEmitter}
- */
- EventEmitter.prototype.addListener = function addListener(type, listener) {
- return _addListener(this, type, listener, false);
- };
- EventEmitter.prototype.on = EventEmitter.prototype.addListener;
- /**
- * Adds the `listener` function to the beginning of
- * the listeners array.
- * @param {string | symbol} type
- * @param {Function} listener
- * @returns {EventEmitter}
- */
- EventEmitter.prototype.prependListener =
- function prependListener(type, listener) {
- return _addListener(this, type, listener, true);
- };
- function onceWrapper() {
- if (!this.fired) {
- this.target.removeListener(this.type, this.wrapFn);
- this.fired = true;
- if (arguments.length === 0)
- return this.listener.call(this.target);
- return this.listener.apply(this.target, arguments);
- }
- }
- function _onceWrap(target, type, listener) {
- const state = { fired: false, wrapFn: undefined, target, type, listener };
- const wrapped = onceWrapper.bind(state);
- wrapped.listener = listener;
- state.wrapFn = wrapped;
- return wrapped;
- }
- /**
- * Adds a one-time `listener` function to the event emitter.
- * @param {string | symbol} type
- * @param {Function} listener
- * @returns {EventEmitter}
- */
- EventEmitter.prototype.once = function once(type, listener) {
- checkListener(listener);
- this.on(type, _onceWrap(this, type, listener));
- return this;
- };
- /**
- * Adds a one-time `listener` function to the beginning of
- * the listeners array.
- * @param {string | symbol} type
- * @param {Function} listener
- * @returns {EventEmitter}
- */
- EventEmitter.prototype.prependOnceListener =
- function prependOnceListener(type, listener) {
- checkListener(listener);
- this.prependListener(type, _onceWrap(this, type, listener));
- return this;
- };
- /**
- * Removes the specified `listener` from the listeners array.
- * @param {string | symbol} type
- * @param {Function} listener
- * @returns {EventEmitter}
- */
- EventEmitter.prototype.removeListener =
- function removeListener(type, listener) {
- checkListener(listener);
- const events = this._events;
- if (events === undefined)
- return this;
- const list = events[type];
- if (list === undefined)
- return this;
- if (list === listener || list.listener === listener) {
- if (--this._eventsCount === 0)
- this._events = ObjectCreate(null);
- else {
- delete events[type];
- if (events.removeListener)
- this.emit('removeListener', type, list.listener || listener);
- }
- } else if (typeof list !== 'function') {
- let position = -1;
- for (let i = list.length - 1; i >= 0; i--) {
- if (list[i] === listener || list[i].listener === listener) {
- position = i;
- break;
- }
- }
- if (position < 0)
- return this;
- if (position === 0)
- list.shift();
- else {
- spliceOne(list, position);
- }
- if (list.length === 1)
- events[type] = list[0];
- if (events.removeListener !== undefined)
- this.emit('removeListener', type, listener);
- }
- return this;
- };
- EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
- /**
- * Removes all listeners from the event emitter. (Only
- * removes listeners for a specific event name if specified
- * as `type`).
- * @param {string | symbol} [type]
- * @returns {EventEmitter}
- */
- EventEmitter.prototype.removeAllListeners =
- function removeAllListeners(type) {
- const events = this._events;
- if (events === undefined)
- return this;
- // Not listening for removeListener, no need to emit
- if (events.removeListener === undefined) {
- if (arguments.length === 0) {
- this._events = ObjectCreate(null);
- this._eventsCount = 0;
- } else if (events[type] !== undefined) {
- if (--this._eventsCount === 0)
- this._events = ObjectCreate(null);
- else
- delete events[type];
- }
- return this;
- }
- // Emit removeListener for all listeners on all events
- if (arguments.length === 0) {
- for (const key of ReflectOwnKeys(events)) {
- if (key === 'removeListener') continue;
- this.removeAllListeners(key);
- }
- this.removeAllListeners('removeListener');
- this._events = ObjectCreate(null);
- this._eventsCount = 0;
- return this;
- }
- const listeners = events[type];
- if (typeof listeners === 'function') {
- this.removeListener(type, listeners);
- } else if (listeners !== undefined) {
- // LIFO order
- for (let i = listeners.length - 1; i >= 0; i--) {
- this.removeListener(type, listeners[i]);
- }
- }
- return this;
- };
- function _listeners(target, type, unwrap) {
- const events = target._events;
- if (events === undefined)
- return [];
- const evlistener = events[type];
- if (evlistener === undefined)
- return [];
- if (typeof evlistener === 'function')
- return unwrap ? [evlistener.listener || evlistener] : [evlistener];
- return unwrap ?
- unwrapListeners(evlistener) : arrayClone(evlistener);
- }
- /**
- * Returns a copy of the array of listeners for the event name
- * specified as `type`.
- * @param {string | symbol} type
- * @returns {Function[]}
- */
- EventEmitter.prototype.listeners = function listeners(type) {
- return _listeners(this, type, true);
- };
- /**
- * Returns a copy of the array of listeners and wrappers for
- * the event name specified as `type`.
- * @param {string | symbol} type
- * @returns {Function[]}
- */
- EventEmitter.prototype.rawListeners = function rawListeners(type) {
- return _listeners(this, type, false);
- };
- /**
- * Returns the number of listeners listening to the event name
- * specified as `type`.
- * @deprecated since v3.2.0
- * @param {EventEmitter} emitter
- * @param {string | symbol} type
- * @returns {number}
- */
- EventEmitter.listenerCount = function(emitter, type) {
- if (typeof emitter.listenerCount === 'function') {
- return emitter.listenerCount(type);
- }
- return emitter.listenerCount(type);
- };
- EventEmitter.prototype.listenerCount = listenerCount;
- /**
- * Returns the number of listeners listening to event name
- * specified as `type`.
- * @param {string | symbol} type
- * @returns {number}
- */
- function listenerCount(type) {
- const events = this._events;
- if (events !== undefined) {
- const evlistener = events[type];
- if (typeof evlistener === 'function') {
- return 1;
- } else if (evlistener !== undefined) {
- return evlistener.length;
- }
- }
- return 0;
- }
- /**
- * Returns an array listing the events for which
- * the emitter has registered listeners.
- * @returns {any[]}
- */
- EventEmitter.prototype.eventNames = function eventNames() {
- return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : [];
- };
- function arrayClone(arr) {
- // At least since V8 8.3, this implementation is faster than the previous
- // which always used a simple for-loop
- switch (arr.length) {
- case 2: return [arr[0], arr[1]];
- case 3: return [arr[0], arr[1], arr[2]];
- case 4: return [arr[0], arr[1], arr[2], arr[3]];
- case 5: return [arr[0], arr[1], arr[2], arr[3], arr[4]];
- case 6: return [arr[0], arr[1], arr[2], arr[3], arr[4], arr[5]];
- }
- return ArrayPrototypeSlice(arr);
- }
- function unwrapListeners(arr) {
- const ret = arrayClone(arr);
- for (let i = 0; i < ret.length; ++i) {
- const orig = ret[i].listener;
- if (typeof orig === 'function')
- ret[i] = orig;
- }
- return ret;
- }
|