"use strict";
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
});
module.exports = __toCommonJS(src_exports);
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 AsyncEventEmitter = class {
  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);
    }
    if (this._maxListeners > 0 && existing.length > this._maxListeners && !existing._hasWarnedAboutMaxListeners) {
      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");
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 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");
function handleMaybeAsync(emitter, result) {
  try {
    const fin = result.finally;
    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");
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  AbortError,
  AsyncEventEmitter
});
//# sourceMappingURL=index.js.map