"use strict";
var AsyncEventEmitter = (() => {
  var __defProp = Object.defineProperty;
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
  var __getOwnPropNames = Object.getOwnPropertyNames;
  var __hasOwnProp = Object.prototype.hasOwnProperty;
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
  var __export = (target, all) => {
    for (var name in all)
      __defProp(target, name, { get: all[name], enumerable: true });
  };
  var __copyProps = (to, from, except, desc) => {
    if (from && typeof from === "object" || typeof from === "function") {
      for (let key of __getOwnPropNames(from))
        if (!__hasOwnProp.call(to, key) && key !== except)
          __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
    }
    return to;
  };
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

  // src/index.ts
  var src_exports = {};
  __export(src_exports, {
    AbortError: () => AbortError,
    AsyncEventEmitter: () => AsyncEventEmitter
  });
  function validateListener(input) {
    if (typeof input !== "function") {
      throw new TypeError(`The listener argument must be a function. Received ${typeof input}`);
    }
  }
  __name(validateListener, "validateListener");
  function validateAbortSignal(input) {
    if (input && !(input instanceof AbortSignal)) {
      throw new TypeError(`The signal option must be an AbortSignal. Received ${input}`);
    }
  }
  __name(validateAbortSignal, "validateAbortSignal");
  function spliceOne(list, index) {
    for (; index + 1 < list.length; index++) {
      list[index] = list[index + 1];
    }
    list.pop();
  }
  __name(spliceOne, "spliceOne");
  function arrayClone(arr) {
    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 arr.slice();
  }
  __name(arrayClone, "arrayClone");
  function identicalSequenceRange(a, b) {
    for (let i = 0; i < a.length - 3; i++) {
      const pos = b.indexOf(a[i]);
      if (pos !== -1) {
        const rest = b.length - pos;
        if (rest > 3) {
          let len = 1;
          const maxLen = Math.min(a.length - i, rest);
          while (maxLen > len && a[i + len] === b[pos + len]) {
            len++;
          }
          if (len > 3) {
            return [len, i];
          }
        }
      }
    }
    return [0, 0];
  }
  __name(identicalSequenceRange, "identicalSequenceRange");
  function enhanceStackTrace(err, own) {
    let ctorInfo = "";
    try {
      const { name } = this.constructor;
      if (name !== "AsyncEventEmitter") ctorInfo = ` on ${name} instance`;
    } catch {
    }
    const sep = `
Emitted 'error' event${ctorInfo} at:
`;
    const errStack = err.stack.split("\n").slice(1);
    const ownStack = own.stack.split("\n").slice(1);
    const { 0: len, 1: off } = identicalSequenceRange(ownStack, errStack);
    if (len > 0) {
      ownStack.splice(off + 1, len - 2, "    [... lines matching original stack trace ...]");
    }
    return err.stack + sep + ownStack.join("\n");
  }
  __name(enhanceStackTrace, "enhanceStackTrace");
  var brandSymbol = Symbol.for("async-event-emitter.ts-brand");
  brandSymbol;
  var _AsyncEventEmitter = class _AsyncEventEmitter {
    constructor() {
      this._events = {
        __proto__: null
      };
      this._eventCount = 0;
      this._maxListeners = 10;
      this._internalPromiseMap = /* @__PURE__ */ new Map();
      this._wrapperId = 0n;
    }
    addListener(eventName, listener) {
      validateListener(listener);
      const wrapped = this._wrapListener(eventName, listener, false);
      this._addListener(eventName, wrapped, false);
      return this;
    }
    on(eventName, listener) {
      return this.addListener(eventName, listener);
    }
    once(eventName, listener) {
      validateListener(listener);
      const wrapped = this._wrapListener(eventName, listener, true);
      this._addListener(eventName, wrapped, false);
      return this;
    }
    removeListener(eventName, listener) {
      validateListener(listener);
      const events = this._events;
      const eventList = events[eventName];
      if (eventList === void 0) {
        return this;
      }
      if (eventList === listener || eventList.listener === listener) {
        if (--this._eventCount === 0) {
          this._events = { __proto__: null };
        } else {
          delete events[eventName];
          if (events.removeListener) {
            this.emit(
              "removeListener",
              eventName,
              eventList.listener ?? eventList
            );
          }
        }
      } else if (typeof eventList !== "function") {
        let position = -1;
        for (let i = eventList.length - 1; i >= 0; i--) {
          if (eventList[i] === listener || eventList[i].listener === listener) {
            position = i;
            break;
          }
        }
        if (position < 0) {
          return this;
        }
        if (position === 0) {
          eventList.shift();
        } else {
          spliceOne(eventList, position);
        }
        if (eventList.length === 0) {
          delete events[eventName];
          --this._eventCount;
        }
        if (events.removeListener !== void 0) {
          this.emit("removeListener", eventName, listener);
        }
      }
      return this;
    }
    off(eventName, listener) {
      return this.removeListener(eventName, listener);
    }
    removeAllListeners(event) {
      const events = this._events;
      if (events.removeListener === void 0) {
        if (!event) {
          this._events = { __proto__: null };
          this._eventCount = 0;
        } else if (events[event] !== void 0) {
          if (--this._eventCount === 0) {
            this._events = { __proto__: null };
          } else {
            delete events[event];
          }
        }
        return this;
      }
      if (!event) {
        for (const key of Reflect.ownKeys(events)) {
          if (key === "removeListener") {
            continue;
          }
          this.removeAllListeners(key);
        }
        this.removeAllListeners("removeListener");
        this._events = { __proto__: null };
        this._eventCount = 0;
        return this;
      }
      const listeners = events[event];
      if (typeof listeners === "function") {
        this.removeListener(event, listeners);
      } else if (listeners !== void 0) {
        for (let i = listeners.length - 1; i >= 0; i--) {
          this.removeListener(event, listeners[i]);
        }
      }
      return this;
    }
    setMaxListeners(n) {
      if (typeof n !== "number" || n < 0 || Number.isNaN(n)) {
        throw new RangeError(`Expected to get a non-negative number for "setMaxListeners", got ${n} instead`);
      }
      this._maxListeners = n;
      return this;
    }
    getMaxListeners() {
      return this._maxListeners;
    }
    listeners(eventName) {
      const eventList = this._events[eventName];
      if (eventList === void 0) {
        return [];
      }
      if (typeof eventList === "function") {
        return [eventList.listener ?? eventList];
      }
      const ret = arrayClone(eventList);
      for (let i = 0; i < ret.length; ++i) {
        const orig = ret[i].listener;
        if (typeof orig === "function") {
          ret[i] = orig;
        }
      }
      return ret;
    }
    rawListeners(eventName) {
      const eventList = this._events[eventName];
      if (eventList === void 0) {
        return [];
      }
      if (typeof eventList === "function") {
        return [eventList];
      }
      return arrayClone(eventList);
    }
    emit(eventName, ...args) {
      let doError = eventName === "error";
      const events = this._events;
      if (events !== void 0) {
        doError = doError && events.error === void 0;
      } else if (!doError) {
        return false;
      }
      if (doError) {
        let er;
        if (args.length > 0) {
          er = args[0];
        }
        if (er instanceof Error) {
          try {
            const capture = {};
            Error.captureStackTrace(capture, _AsyncEventEmitter.prototype.emit);
            Object.defineProperty(er, "stack", {
              value: enhanceStackTrace.call(this, er, capture),
              configurable: true
            });
          } catch {
          }
          throw er; // Unhandled 'error' event
        }
        const stringifiedError = String(er);
        const err = new Error(`Unhandled 'error' event emitted, received ${stringifiedError}`);
        err.context = er;
        throw err; // Unhandled 'error' event
      }
      const handlers = events[eventName];
      if (handlers === void 0) {
        return false;
      }
      if (typeof handlers === "function") {
        const result = handlers.apply(this, args);
        if (result !== void 0 && result !== null) {
          handleMaybeAsync(this, result);
        }
      } else {
        const len = handlers.length;
        const listeners = arrayClone(handlers);
        for (let i = 0; i < len; ++i) {
          const result = listeners[i].apply(this, args);
          if (result !== void 0 && result !== null) {
            handleMaybeAsync(this, result);
          }
        }
      }
      return true;
    }
    listenerCount(eventName) {
      const events = this._events;
      if (events === void 0) {
        return 0;
      }
      const eventListeners = events[eventName];
      if (typeof eventListeners === "function") {
        return 1;
      }
      return eventListeners?.length ?? 0;
    }
    prependListener(eventName, listener) {
      validateListener(listener);
      const wrapped = this._wrapListener(eventName, listener, false);
      this._addListener(eventName, wrapped, true);
      return this;
    }
    prependOnceListener(eventName, listener) {
      validateListener(listener);
      const wrapped = this._wrapListener(eventName, listener, true);
      this._addListener(eventName, wrapped, true);
      return this;
    }
    eventNames() {
      return this._eventCount > 0 ? Reflect.ownKeys(this._events) : [];
    }
    async waitForAllListenersToComplete() {
      const promises = [...this._internalPromiseMap.values()];
      if (promises.length === 0) {
        return false;
      }
      await Promise.all(promises);
      return true;
    }
    _addListener(eventName, wrappedListener, prepend) {
      if (this._events.newListener !== void 0) {
        this.emit(
          "newListener",
          eventName,
          wrappedListener.listener ?? wrappedListener
        );
      }
      let existing = this._events[eventName];
      if (existing === void 0) {
        existing = this._events[eventName] = wrappedListener;
        ++this._eventCount;
      } else if (typeof existing === "function") {
        existing = this._events[eventName] = prepend ? [wrappedListener, existing] : [existing, wrappedListener];
      } else if (prepend) {
        existing.unshift(wrappedListener);
      } else {
        existing.push(wrappedListener);
      }
      const existingWarnedAboutMaxListeners = Reflect.get(existing, "_hasWarnedAboutMaxListeners");
      if (this._maxListeners > 0 && existing.length > this._maxListeners && !existingWarnedAboutMaxListeners) {
        Reflect.set(existing, "_hasWarnedAboutMaxListeners", true);
        const warningMessage = [
          `Possible AsyncEventEmitter memory leak detected. ${existing.length} ${String(
            eventName
          )} listeners added to ${this.constructor.name}.`,
          `Use emitter.setMaxListeners() to increase the limit.`
        ].join(" ");
        console.warn(warningMessage);
      }
    }
    _wrapListener(eventName, listener, once) {
      if (!once) {
        return listener;
      }
      const state = {
        fired: false,
        wrapFn: void 0,
        eventEmitter: this,
        eventName,
        listener
      };
      const aliased = onceWrapper;
      const wrapped = aliased.bind(state);
      wrapped.listener = listener;
      state.wrapFn = wrapped;
      return wrapped;
    }
    static listenerCount(emitter, eventName) {
      return emitter.listenerCount(eventName);
    }
    static async once(emitter, eventName, options = {}) {
      const signal = options?.signal;
      validateAbortSignal(signal);
      if (signal?.aborted) {
        throw new AbortError(void 0, { cause: getReason(signal) });
      }
      return new Promise((resolve, reject) => {
        const errorListener = /* @__PURE__ */ __name((err) => {
          emitter.removeListener(eventName, resolver);
          if (signal) {
            eventTargetAgnosticRemoveListener(emitter, eventName, abortListener);
          }
          reject(err);
        }, "errorListener");
        const resolver = /* @__PURE__ */ __name((...args) => {
          emitter.removeListener("error", errorListener);
          if (signal) {
            eventTargetAgnosticRemoveListener(signal, "abort", abortListener);
          }
          resolve(args);
        }, "resolver");
        emitter.once(eventName, resolver);
        if (eventName !== "error") {
          emitter.once("error", errorListener);
        }
        const abortListener = /* @__PURE__ */ __name(() => {
          eventTargetAgnosticRemoveListener(emitter, eventName, resolver);
          eventTargetAgnosticRemoveListener(emitter, "error", errorListener);
          reject(new AbortError(void 0, { cause: getReason(signal) }));
        }, "abortListener");
        if (signal) {
          eventTargetAgnosticAddListener(signal, "abort", abortListener, { once: true });
        }
      });
    }
    static on(emitter, eventName, options = {}) {
      const signal = options?.signal;
      validateAbortSignal(signal);
      if (signal?.aborted) {
        throw new AbortError(void 0, { cause: getReason(signal) });
      }
      const unconsumedEvents = [];
      const unconsumedPromises = [];
      let error = null;
      let finished = false;
      const abortListener = /* @__PURE__ */ __name(() => {
        errorHandler(new AbortError(void 0, { cause: getReason(signal) }));
      }, "abortListener");
      const eventHandler = /* @__PURE__ */ __name((...args) => {
        const promise = unconsumedPromises.shift();
        if (promise) {
          promise.resolve(createIterResult(args, false));
        } else {
          unconsumedEvents.push(args);
        }
      }, "eventHandler");
      const errorHandler = /* @__PURE__ */ __name((err) => {
        finished = true;
        const toError = unconsumedPromises.shift();
        if (toError) {
          toError.reject(err);
        } else {
          error = err;
        }
        void iterator.return();
      }, "errorHandler");
      const iterator = Object.setPrototypeOf(
        {
          next() {
            const value = unconsumedEvents.shift();
            if (value) {
              return Promise.resolve(createIterResult(value, false));
            }
            if (error) {
              const p = Promise.reject(error);
              error = null;
              return p;
            }
            if (finished) {
              return Promise.resolve(createIterResult(void 0, true));
            }
            return new Promise((resolve, reject) => {
              unconsumedPromises.push({ resolve, reject });
            });
          },
          return() {
            emitter.off(eventName, eventHandler);
            emitter.off("error", errorHandler);
            if (signal) {
              eventTargetAgnosticRemoveListener(signal, "abort", abortListener);
            }
            finished = true;
            const doneResult = createIterResult(void 0, true);
            for (const promise of unconsumedPromises) {
              promise.resolve(doneResult);
            }
            return Promise.resolve(doneResult);
          },
          throw(err) {
            if (!err || !(err instanceof Error)) {
              throw new TypeError(
                `Expected Error instance to be thrown in AsyncEventEmitter.AsyncIterator. Got ${err}`
              );
            }
            error = err;
            emitter.off(eventName, eventHandler);
            emitter.off("error", errorHandler);
          },
          [Symbol.asyncIterator]() {
            return this;
          }
        },
        AsyncIteratorPrototype
      );
      emitter.on(eventName, eventHandler);
      if (eventName !== "error") {
        emitter.on("error", errorHandler);
      }
      if (signal) {
        eventTargetAgnosticAddListener(signal, "abort", abortListener);
      }
      return iterator;
    }
  };
  __name(_AsyncEventEmitter, "AsyncEventEmitter");
  var AsyncEventEmitter = _AsyncEventEmitter;
  function onceWrapper() {
    if (!this.fired) {
      this.eventEmitter.removeListener(this.eventName, this.wrapFn);
      this.fired = true;
      if (arguments.length === 0) {
        return this.listener.call(this.eventEmitter);
      }
      return this.listener.apply(this.eventEmitter, arguments);
    }
  }
  __name(onceWrapper, "onceWrapper");
  function getReason(signal) {
    return signal?.reason;
  }
  __name(getReason, "getReason");
  function eventTargetAgnosticRemoveListener(emitter, name, listener, flags) {
    if (typeof emitter.off === "function") {
      emitter.off(name, listener);
    } else if (typeof emitter.removeEventListener === "function") {
      emitter.removeEventListener(name, listener, flags);
    }
  }
  __name(eventTargetAgnosticRemoveListener, "eventTargetAgnosticRemoveListener");
  function eventTargetAgnosticAddListener(emitter, name, listener, flags) {
    if (typeof emitter.on === "function") {
      if (flags?.once) {
        emitter.once(name, listener);
      } else {
        emitter.on(name, listener);
      }
    } else if (typeof emitter.addEventListener === "function") {
      emitter.addEventListener(name, listener, flags);
    }
  }
  __name(eventTargetAgnosticAddListener, "eventTargetAgnosticAddListener");
  var AsyncIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf(async function* () {
  }).prototype);
  function createIterResult(value, done) {
    return { value, done };
  }
  __name(createIterResult, "createIterResult");
  var _AbortError = class _AbortError extends Error {
    constructor(message = "The operation was aborted", options = void 0) {
      if (options !== void 0 && typeof options !== "object") {
        throw new TypeError(`Failed to create AbortError: options is not an object or undefined`);
      }
      super(message, options);
      this.code = "ABORT_ERR";
      this.name = "AbortError";
    }
  };
  __name(_AbortError, "AbortError");
  var AbortError = _AbortError;
  function handleMaybeAsync(emitter, result) {
    try {
      const the = result.then;
      const fin = result.finally;
      if (typeof the === "function") {
        the.call(result, void 0, (error) => {
          setTimeout(() => {
            emitter.emit("error", error);
          }, 0);
        });
      }
      if (typeof fin === "function") {
        const promiseId = String(++emitter["_wrapperId"]);
        emitter["_internalPromiseMap"].set(promiseId, result);
        fin.call(result, /* @__PURE__ */ __name(function final() {
          emitter["_internalPromiseMap"].delete(promiseId);
        }, "final"));
      }
    } catch (err) {
      emitter.emit("error", err);
    }
  }
  __name(handleMaybeAsync, "handleMaybeAsync");
  return __toCommonJS(src_exports);
})();
//# sourceMappingURL=index.global.js.map