char/avril

(wip) why'd you have to go and make things so complicaaaaated?

git clone https://git.t4t.associates/char/avril

Charlotte Somport web extension to typescript44fe2c6

main
26.4 KiB958 linesraw
1import {
2  Array,
3  ArrayPrototypePush as push,
4  Error,
5  ErrorGetStack,
6  Map,
7  MapPrototypeDelete as mapDelete,
8  MapPrototypeGet as mapGet,
9  MapPrototypeSet as mapSet,
10  NumberIsFinite as isFinite,
11  ObjectCreate,
12  ObjectDefineProperty as define,
13  ObjectSetPrototypeOf,
14  ReflectApply as apply,
15  ReflectConstruct as construct,
16  TypeError,
17  uncurryThis,
18  WeakMap,
19  WeakMapPrototypeGet as get,
20  WeakMapPrototypeSet as set,
21} from "ext:core/primordials";
22import {
23  array,
24  dictionary,
25  required,
26  state,
27  string,
28  usv,
29} from "ext:web/idl.js";
30import { op_timer_now as now } from "ext:core/ops";
31import { enqueueMicrotask } from "ext:core/microtasks";
32import { isPromise } from "ext:core/event_hooks";
33import { scheduleTimeout } from "ext:timers/timers.js";
34import {
35  registerSerializable,
36  registerUncloneable,
37  registerWire,
38} from "./serialization.js";
39
40interface EventState {
41  type: string;
42  bubbles: boolean;
43  cancelable: boolean;
44  composed: boolean;
45  target: EventTarget | null;
46  phase: number;
47  dispatching: boolean;
48  stopped: boolean;
49  immediate: boolean;
50  prevented: boolean;
51  passive: boolean;
52  trusted: boolean;
53  time: number;
54}
55interface ExceptionState {
56  message: string;
57  name: string;
58}
59interface Listener {
60  type: string;
61  callback: EventListener;
62  capture: boolean;
63  once: boolean;
64  passive: boolean;
65  active: boolean;
66}
67export type EventListener = ((this: EventTarget, event: Event) => unknown) | {
68  handleEvent(event: Event): unknown;
69};
70interface SignalState {
71  aborted: boolean;
72  reason: unknown;
73  algorithms: (() => void)[];
74  handler: ((event: Event) => unknown) | null;
75  handlerListener?: ((event: Event) => void) | null;
76}
77const events = new WeakMap<object, EventState>(),
78  customEvents = new WeakMap<object, { detail: unknown }>(),
79  errorEvents = new WeakMap<
80    object,
81    {
82      message: string;
83      filename: string;
84      lineno: number;
85      colno: number;
86      error: unknown;
87    }
88  >(),
89  rejectionEvents = new WeakMap<
90    object,
91    { promise: Promise<unknown>; reason: unknown }
92  >(),
93  targets = new WeakMap<object, Listener[]>(),
94  listenerObservers = new WeakMap<object, (target: object) => void>(),
95  signals = new WeakMap<object, SignalState>(),
96  controllers = new WeakMap<object, AbortSignal>(),
97  exceptions = new WeakMap<object, ExceptionState>();
98registerUncloneable(events);
99registerUncloneable(customEvents);
100registerUncloneable(errorEvents);
101registerUncloneable(rejectionEvents);
102registerUncloneable(targets);
103registerUncloneable(signals);
104registerUncloneable(controllers);
105const secret = ObjectCreate(null), trunc = Math.trunc, floor = Math.floor;
106function trustedGetter(this: object): boolean {
107  return state(events, this).trusted;
108}
109const WeakRef = globalThis.WeakRef,
110  deref = uncurryThis(WeakRef.prototype.deref);
111const slice: <T>(array: readonly T[], start?: number, end?: number) => T[] =
112  uncurryThis(Array.prototype.slice);
113let globalTarget: object | undefined, reporting = false;
114const pendingReports = new Map<unknown, number>();
115function report(error: unknown): void {
116  reportErrorValue(error);
117}
118class DOMException extends Error {
119  // @ts-expect-error Reflect.construct preserves the native Error prototype without a guest-replaceable super().
120  constructor(message: unknown = "", name: unknown = "Error") {
121    const convertedMessage = string(message), convertedName = string(name);
122    const self = construct(Error, [convertedMessage], new.target) as {
123      message?: unknown;
124    };
125    delete self.message;
126    set(exceptions, self, { message: convertedMessage, name: convertedName });
127    return self as DOMException;
128  }
129  get name() {
130    return state(exceptions, this).name;
131  }
132  get message() {
133    return state(exceptions, this).message;
134  }
135  get code() {
136    switch (state(exceptions, this).name) {
137      case "IndexSizeError":
138        return 1;
139      case "HierarchyRequestError":
140        return 3;
141      case "WrongDocumentError":
142        return 4;
143      case "InvalidCharacterError":
144        return 5;
145      case "NoModificationAllowedError":
146        return 7;
147      case "NotFoundError":
148        return 8;
149      case "NotSupportedError":
150        return 9;
151      case "InUseAttributeError":
152        return 10;
153      case "InvalidStateError":
154        return 11;
155      case "SyntaxError":
156        return 12;
157      case "InvalidModificationError":
158        return 13;
159      case "NamespaceError":
160        return 14;
161      case "InvalidAccessError":
162        return 15;
163      case "TypeMismatchError":
164        return 17;
165      case "SecurityError":
166        return 18;
167      case "NetworkError":
168        return 19;
169      case "AbortError":
170        return 20;
171      case "URLMismatchError":
172        return 21;
173      case "QuotaExceededError":
174        return 22;
175      case "TimeoutError":
176        return 23;
177      case "InvalidNodeTypeError":
178        return 24;
179      case "DataCloneError":
180        return 25;
181      default:
182        return 0;
183    }
184  }
185}
186for (
187  const [name, value] of [
188    ["INDEX_SIZE_ERR", 1],
189    ["DOMSTRING_SIZE_ERR", 2],
190    ["HIERARCHY_REQUEST_ERR", 3],
191    ["WRONG_DOCUMENT_ERR", 4],
192    ["INVALID_CHARACTER_ERR", 5],
193    ["NO_DATA_ALLOWED_ERR", 6],
194    ["NO_MODIFICATION_ALLOWED_ERR", 7],
195    ["NOT_FOUND_ERR", 8],
196    ["NOT_SUPPORTED_ERR", 9],
197    ["INUSE_ATTRIBUTE_ERR", 10],
198    ["INVALID_STATE_ERR", 11],
199    ["SYNTAX_ERR", 12],
200    ["INVALID_MODIFICATION_ERR", 13],
201    ["NAMESPACE_ERR", 14],
202    ["INVALID_ACCESS_ERR", 15],
203    ["VALIDATION_ERR", 16],
204    ["TYPE_MISMATCH_ERR", 17],
205    ["SECURITY_ERR", 18],
206    ["NETWORK_ERR", 19],
207    ["ABORT_ERR", 20],
208    ["URL_MISMATCH_ERR", 21],
209    ["QUOTA_EXCEEDED_ERR", 22],
210    ["TIMEOUT_ERR", 23],
211    ["INVALID_NODE_TYPE_ERR", 24],
212    ["DATA_CLONE_ERR", 25],
213  ]
214) {
215  define(DOMException, name, { value, enumerable: true });
216  define(DOMException.prototype, name, { value, enumerable: true });
217}
218function createException(
219  data: ExceptionState,
220  stack: unknown = undefined,
221): DOMException {
222  // Construct native Error data without a guest-replaceable dynamic super() call.
223  const result = construct(Error, [data.message], DOMException) as {
224    message?: unknown;
225  };
226  delete result.message;
227  if (typeof stack === "string") {
228    define(result, "stack", {
229      value: stack,
230      writable: true,
231      configurable: true,
232    });
233  }
234  set(exceptions, result, data);
235  return result as DOMException;
236}
237function dataCloneError(message: string): DOMException {
238  return createException({ message, name: "DataCloneError" });
239}
240registerSerializable(
241  exceptions,
242  (data: ExceptionState, source: object) =>
243    createException(data, ErrorGetStack(source)),
244);
245registerWire({
246  name: "DOMException",
247  states: exceptions,
248  encode: (data) => data,
249  decode: (data: unknown) => createException(data as ExceptionState),
250});
251class Event {
252  constructor(type: unknown, init: unknown = {}) {
253    if (arguments.length === 0) throw new TypeError("Event requires a type");
254    type = string(type);
255    const options = dictionary(init);
256    set(events, this, {
257      type: type as string,
258      bubbles: !!options.bubbles,
259      cancelable: !!options.cancelable,
260      composed: !!options.composed,
261      target: null,
262      phase: 0,
263      dispatching: false,
264      stopped: false,
265      immediate: false,
266      prevented: false,
267      passive: false,
268      trusted: false,
269      time: floor(now(null) * 10) / 10,
270    });
271    define(this, "isTrusted", {
272      get: trustedGetter,
273      enumerable: true,
274    });
275  }
276  get type() {
277    return state(events, this).type;
278  }
279  get bubbles() {
280    return state(events, this).bubbles;
281  }
282  get cancelable() {
283    return state(events, this).cancelable;
284  }
285  get composed() {
286    return state(events, this).composed;
287  }
288  get target() {
289    return state(events, this).target;
290  }
291  get srcElement() {
292    return state(events, this).target;
293  }
294  get currentTarget() {
295    const s = state(events, this);
296    return s.dispatching ? s.target : null;
297  }
298  get eventPhase() {
299    return state(events, this).phase;
300  }
301  get timeStamp() {
302    return state(events, this).time;
303  }
304  get defaultPrevented() {
305    return state(events, this).prevented;
306  }
307  get cancelBubble() {
308    return state(events, this).stopped;
309  }
310  set cancelBubble(value) {
311    if (value) state(events, this).stopped = true;
312  }
313  get returnValue() {
314    return !state(events, this).prevented;
315  }
316  set returnValue(value) {
317    const s = state(events, this);
318    if (!value && s.cancelable && !s.passive) s.prevented = true;
319  }
320  preventDefault() {
321    const s = state(events, this);
322    if (s.cancelable && !s.passive) s.prevented = true;
323  }
324  stopPropagation() {
325    state(events, this).stopped = true;
326  }
327  stopImmediatePropagation() {
328    const s = state(events, this);
329    s.stopped = s.immediate = true;
330  }
331  composedPath() {
332    const s = state(events, this);
333    return s.dispatching ? [s.target] : [];
334  }
335  initEvent(
336    type: unknown,
337    bubbles: unknown = false,
338    cancelable: unknown = false,
339  ) {
340    required(arguments.length, 1);
341    type = string(type);
342    bubbles = !!bubbles;
343    cancelable = !!cancelable;
344    const s = state(events, this);
345    if (s.dispatching) return;
346    s.type = type as string;
347    s.bubbles = bubbles as boolean;
348    s.cancelable = cancelable as boolean;
349    s.composed = false;
350    s.target = null;
351    s.phase = 0;
352    s.trusted = false;
353    s.stopped = s.immediate = s.prevented = false;
354  }
355}
356for (
357  const [name, value] of [
358    ["NONE", 0],
359    ["CAPTURING_PHASE", 1],
360    ["AT_TARGET", 2],
361    ["BUBBLING_PHASE", 3],
362  ]
363) {
364  define(Event, name, { value, enumerable: true });
365  define(Event.prototype, name, { value, enumerable: true });
366}
367class CustomEvent extends Event {
368  // @ts-expect-error Reflect.construct preserves new.target without a guest-replaceable super().
369  constructor(type: unknown, init: unknown = {}) {
370    required(arguments.length, 1);
371    type = string(type);
372    const options = dictionary(init);
373    const self = construct(Event, [type, options], new.target);
374    const detail = options.detail;
375    set(customEvents, self, {
376      detail: detail === undefined ? null : detail,
377    });
378    return self as CustomEvent;
379  }
380  get detail() {
381    return state(customEvents, this).detail;
382  }
383}
384class ErrorEvent extends Event {
385  // @ts-expect-error Reflect.construct preserves new.target without a guest-replaceable super().
386  constructor(type: unknown, init: unknown = {}) {
387    required(arguments.length, 1);
388    type = string(type);
389    const options = dictionary(init);
390    const self = construct(Event, [type, options], new.target);
391    const message = options.message,
392      filename = options.filename,
393      error = options.error,
394      lineno = options.lineno,
395      colno = options.colno;
396    set(errorEvents, self, {
397      message: message === undefined ? "" : string(message),
398      filename: filename === undefined ? "" : string(filename),
399      lineno: lineno === undefined ? 0 : +(lineno as number) >>> 0,
400      colno: colno === undefined ? 0 : +(colno as number) >>> 0,
401      error: error === undefined ? null : error,
402    });
403    return self as ErrorEvent;
404  }
405  get message() {
406    return state(errorEvents, this).message;
407  }
408  get filename() {
409    return state(errorEvents, this).filename;
410  }
411  get lineno() {
412    return state(errorEvents, this).lineno;
413  }
414  get colno() {
415    return state(errorEvents, this).colno;
416  }
417  get error() {
418    return state(errorEvents, this).error;
419  }
420}
421class PromiseRejectionEvent extends Event {
422  // @ts-expect-error Reflect.construct preserves new.target without a guest-replaceable super().
423  constructor(type: unknown, init: unknown = {}) {
424    required(arguments.length, 1);
425    type = string(type);
426    const options = dictionary(init);
427    const self = construct(Event, [type, options], new.target);
428    const promise = options.promise;
429    if (!isPromise(promise)) {
430      throw new TypeError("Expected a Promise");
431    }
432    set(rejectionEvents, self, {
433      promise,
434      reason: options.reason,
435    });
436    return self as PromiseRejectionEvent;
437  }
438  get promise() {
439    return state(rejectionEvents, this).promise;
440  }
441  get reason() {
442    return state(rejectionEvents, this).reason;
443  }
444}
445function dispatchEvent(
446  target: object,
447  event: Event,
448  trusted: boolean,
449): boolean {
450  const list = state(targets, target), s = state(events, event);
451  if (s.dispatching || !s.type) {
452    throw new DOMException(
453      "Event is already dispatching or uninitialized",
454      "InvalidStateError",
455    );
456  }
457  s.trusted = trusted;
458  s.dispatching = true;
459  s.target = target as EventTarget;
460  s.phase = 2;
461  s.stopped = s.immediate = false;
462  const snapshot = slice(list);
463  for (let i = 0; i < snapshot.length; i++) {
464    const l = snapshot[i];
465    if (!l.active || l.type !== s.type) continue;
466    if (l.once) {
467      l.active = false;
468      listenersChanged(target);
469    }
470    s.passive = l.passive;
471    try {
472      if (typeof l.callback === "function") {
473        apply(l.callback, target, [event]);
474      } else l.callback.handleEvent(event);
475    } catch (error) {
476      report(error);
477    }
478    if (s.immediate) break;
479  }
480  s.passive = false;
481  s.dispatching = false;
482  s.phase = 0;
483  return !s.prevented;
484}
485class EventTarget {
486  constructor() {
487    set(targets, this, array());
488  }
489  addEventListener(
490    type: unknown,
491    callback: EventListener | null | undefined,
492    options?: unknown,
493  ): void;
494  addEventListener(
495    type: unknown,
496    callback: unknown,
497    options: unknown = {},
498  ): void {
499    required(arguments.length, 2);
500    const list = state(targets, this);
501    type = string(type);
502    if (callback === null || callback === undefined) return;
503    if (typeof callback !== "function" && typeof callback !== "object") {
504      throw new TypeError("Invalid event listener");
505    }
506    const capture = typeof options === "boolean"
507      ? options
508      : !!(options as Record<PropertyKey, unknown> | null | undefined)?.capture;
509    for (let i = 0; i < list.length; i++) {
510      if (
511        list[i].active && list[i].type === type &&
512        list[i].callback === callback && list[i].capture === capture
513      ) return;
514    }
515    const signal = typeof options === "object"
516      ? (options as Record<PropertyKey, unknown> | null)?.signal as
517        | AbortSignal
518        | undefined
519      : undefined;
520    if (signal !== undefined && state(signals, signal).aborted) return;
521    const listener = {
522      type: type as string,
523      callback: callback as EventListener,
524      capture,
525      once: !!(options as Record<PropertyKey, unknown> | null | undefined)
526        ?.once,
527      passive: !!(options as Record<PropertyKey, unknown> | null | undefined)
528        ?.passive,
529      active: true,
530    };
531    push(list, listener);
532    if (signal !== undefined) {
533      const weakTarget = new WeakRef(this),
534        weakListener = new WeakRef(listener);
535      addAbort(signal, () => {
536        const current = deref(weakListener), target = deref(weakTarget);
537        if (current) current.active = false;
538        if (target) listenersChanged(target);
539      });
540    }
541    listenersChanged(this);
542  }
543  removeEventListener(
544    type: unknown,
545    callback: EventListener | null | undefined,
546    options?: unknown,
547  ): void;
548  removeEventListener(
549    type: unknown,
550    callback: unknown,
551    options: unknown = {},
552  ): void {
553    required(arguments.length, 2);
554    const list = state(targets, this);
555    type = string(type);
556    const capture = typeof options === "boolean"
557      ? options
558      : !!(options as Record<PropertyKey, unknown> | null | undefined)?.capture;
559    for (let i = 0; i < list.length; i++) {
560      if (
561        list[i].type === type && list[i].callback === callback &&
562        list[i].capture === capture
563      ) list[i].active = false;
564    }
565    listenersChanged(this);
566  }
567  dispatchEvent(event: Event): boolean {
568    required(arguments.length, 1);
569    return dispatchEvent(this, event, false);
570  }
571}
572type CapturedListenerMethod = (
573  target: unknown,
574  type: unknown,
575  callback: EventListener | null | undefined,
576  options?: unknown,
577) => void;
578const addListener = uncurryThis(
579    EventTarget.prototype.addEventListener,
580  ) as CapturedListenerMethod,
581  removeListener = uncurryThis(
582    EventTarget.prototype.removeEventListener,
583  ) as CapturedListenerMethod;
584const dispatch = (target: unknown, event: Event): boolean =>
585  dispatchEvent(target as object, event, true);
586function listenersChanged(target: object): void {
587  const list = state(targets, target);
588  let kept = 0;
589  for (let i = 0; i < list.length; i++) {
590    if (list[i].active) list[kept++] = list[i];
591  }
592  list.length = kept;
593  const observer = get(listenerObservers, target);
594  if (observer) observer(target);
595}
596function observeListeners(
597  target: object,
598  observer: (target: object) => void,
599): void {
600  state(targets, target);
601  set(listenerObservers, target, observer);
602  observer(target);
603}
604function hasListener(target: object, type: string): boolean {
605  const list = state(targets, target);
606  for (let i = 0; i < list.length; i++) {
607    if (list[i].active && list[i].type === type) return true;
608  }
609  return false;
610}
611const isDispatching = (event: Event): boolean =>
612  state(events, event).dispatching;
613const preventDefault = uncurryThis(Event.prototype.preventDefault);
614const globalHandlers = ObjectCreate(null) as Record<string, Function | null>,
615  globalListeners = ObjectCreate(null) as Record<string, EventListener | null>;
616function installGlobalEventTarget(target: object): void {
617  globalTarget = target;
618  ObjectSetPrototypeOf(target, EventTarget.prototype);
619  set(targets, target, array());
620  const methods: Record<string, (...args: never[]) => unknown> = {
621    addEventListener(
622      type: unknown,
623      callback: unknown,
624      options: unknown = undefined,
625    ) {
626      required(arguments.length, 2);
627      return addListener(
628        this ?? target,
629        type,
630        callback as EventListener | null,
631        options,
632      );
633    },
634    removeEventListener(
635      type: unknown,
636      callback: unknown,
637      options: unknown = undefined,
638    ) {
639      required(arguments.length, 2);
640      return removeListener(
641        this ?? target,
642        type,
643        callback as EventListener | null,
644        options,
645      );
646    },
647    dispatchEvent(event: Event) {
648      required(arguments.length, 1);
649      return dispatchEvent(this ?? target, event, false);
650    },
651  };
652  for (
653    const name of ["addEventListener", "removeEventListener", "dispatchEvent"]
654  ) {
655    define(target, name, {
656      value: methods[name],
657      writable: true,
658      enumerable: true,
659      configurable: true,
660    });
661  }
662  for (
663    const [name, type] of [
664      ["onerror", "error"],
665      ["onunhandledrejection", "unhandledrejection"],
666      ["onrejectionhandled", "rejectionhandled"],
667    ]
668  ) {
669    define(target, name, {
670      get: () => globalHandlers[name] ?? null,
671      set: (handler) => setGlobalHandler(name, type, handler),
672      enumerable: true,
673      configurable: true,
674    });
675  }
676}
677function setGlobalHandler(name: string, type: string, handler: unknown): void {
678  handler = typeof handler === "function" ? handler : null;
679  if (!handler) {
680    const listener = globalListeners[name];
681    if (listener) removeListener(globalTarget!, type, listener);
682    delete globalHandlers[name];
683    delete globalListeners[name];
684    return;
685  }
686  globalHandlers[name] = handler as Function;
687  if (globalListeners[name]) return;
688  const listener = (event: Event) => {
689    const handler = globalHandlers[name];
690    if (!handler) return;
691    const result = type === "error"
692      ? apply(handler as (...args: never[]) => unknown, globalTarget!, [
693        (event as ErrorEvent).message,
694        (event as ErrorEvent).filename,
695        (event as ErrorEvent).lineno,
696        (event as ErrorEvent).colno,
697        (event as ErrorEvent).error,
698      ])
699      : apply(handler as (...args: never[]) => unknown, globalTarget!, [event]);
700    if (type === "error" ? result === true : result === false) {
701      const s = state(events, event);
702      if (s.cancelable && !s.passive) s.prevented = true;
703    }
704  };
705  globalListeners[name] = listener;
706  addListener(globalTarget!, type, listener);
707}
708function exceptionMessage(error: unknown): string {
709  if (
710    error !== null && (typeof error === "object" || typeof error === "function")
711  ) {
712    try {
713      const message = (error as Record<PropertyKey, unknown>).message;
714      if (message !== undefined) return usv(message);
715    } catch (error) {
716      void error;
717    }
718  }
719  try {
720    return usv(error);
721  } catch {
722    return "";
723  }
724}
725function dispatchError(
726  error: unknown,
727  filename = "",
728  lineno = 0,
729  colno = 0,
730): boolean {
731  if (reporting || !globalTarget) return false;
732  reporting = true;
733  try {
734    const event = new ErrorEvent("error", {
735      cancelable: true,
736      message: exceptionMessage(error),
737      filename,
738      lineno,
739      colno,
740      error,
741    });
742    state(errorEvents, event).error = error;
743    dispatch(globalTarget, event);
744    return state(events, event).prevented;
745  } catch {
746    return false;
747  } finally {
748    reporting = false;
749  }
750}
751function reportException(
752  error: unknown,
753  filename = "",
754  lineno = 0,
755  colno = 0,
756): boolean {
757  const count = mapGet(pendingReports, error);
758  if (count !== undefined) {
759    if (count === 1) mapDelete(pendingReports, error);
760    else mapSet(pendingReports, error, count - 1);
761    return false;
762  }
763  return dispatchError(error, filename, lineno, colno);
764}
765function reportErrorValue(error: unknown): void {
766  if (!reporting && dispatchError(error)) return;
767  mapSet(pendingReports, error, (mapGet(pendingReports, error) ?? 0) + 1);
768  enqueueMicrotask(() => {
769    throw error;
770  });
771}
772function reportUnhandledRejection(
773  promise: Promise<unknown>,
774  reason: unknown,
775): boolean {
776  const event = new PromiseRejectionEvent("unhandledrejection", {
777    cancelable: true,
778    promise,
779    reason,
780  });
781  dispatch(globalTarget!, event);
782  return state(events, event).prevented;
783}
784function reportRejectionHandled(
785  promise: Promise<unknown>,
786  reason: unknown,
787): void {
788  dispatch(
789    globalTarget!,
790    new PromiseRejectionEvent("rejectionhandled", { promise, reason }),
791  );
792}
793function addAbort(signal: unknown, callback: () => void): () => void {
794  push(state(signals, signal).algorithms, callback);
795  return () => {
796    const current = state(signals, signal),
797      algorithms = current.algorithms,
798      remaining = array<() => void>();
799    for (let i = 0; i < algorithms.length; i++) {
800      if (algorithms[i] !== callback) push(remaining, algorithms[i]);
801    }
802    current.algorithms = remaining;
803  };
804}
805function abort(signal: unknown, reason?: unknown): void {
806  const s = state(signals, signal);
807  if (s.aborted) return;
808  s.aborted = true;
809  s.reason = reason === undefined
810    ? new DOMException("The operation was aborted", "AbortError")
811    : reason;
812  const algorithms = s.algorithms;
813  s.algorithms = array<() => void>();
814  for (let i = 0; i < algorithms.length; i++) algorithms[i]();
815  dispatch(signal, new Event("abort"));
816}
817class AbortSignal extends EventTarget {
818  // @ts-expect-error Reflect.construct preserves new.target without a guest-replaceable super().
819  constructor(key: unknown) {
820    if (key !== secret) throw new TypeError("Illegal constructor");
821    const self = construct(EventTarget, [], new.target) as AbortSignal;
822    set(signals, self, {
823      aborted: false,
824      reason: undefined,
825      handler: null,
826      algorithms: array<() => void>(),
827    });
828    return self as AbortSignal;
829  }
830  get aborted() {
831    return state(signals, this).aborted;
832  }
833  get reason() {
834    return state(signals, this).reason;
835  }
836  get onabort() {
837    return state(signals, this).handler;
838  }
839  set onabort(value) {
840    const s = state(signals, this);
841    value = typeof value === "function" ? value : null;
842    if (!s.handler && value) {
843      s.handlerListener = (event) => {
844        if (s.handler) apply(s.handler, this, [event]);
845      };
846      addListener(this, "abort", s.handlerListener!);
847    } else if (s.handler && !value) {
848      removeListener(this, "abort", s.handlerListener!);
849    }
850    s.handler = value;
851  }
852  throwIfAborted() {
853    const s = state(signals, this);
854    if (s.aborted) throw s.reason;
855  }
856  static abort(reason?: unknown): AbortSignal {
857    const signal = new AbortSignal(secret);
858    abort(signal, reason);
859    return signal;
860  }
861  static any(sequence: unknown): AbortSignal {
862    if (
863      sequence === null ||
864      (typeof sequence !== "object" && typeof sequence !== "function")
865    ) throw new TypeError("Expected a sequence of AbortSignals");
866    const list = array<AbortSignal>();
867    for (const signal of sequence as Iterable<unknown>) {
868      state(signals, signal);
869      push(list, signal as AbortSignal);
870    }
871    const result = new AbortSignal(secret);
872    for (let i = 0; i < list.length; i++) {
873      if (state(signals, list[i]).aborted) {
874        abort(result, state(signals, list[i]).reason);
875        return result;
876      }
877    }
878    const weak = new WeakRef(result);
879    for (let i = 0; i < list.length; i++) {
880      addAbort(list[i], () => {
881        const follower = deref(weak);
882        if (follower) abort(follower, state(signals, list[i]).reason);
883      });
884    }
885    return result;
886  }
887  static timeout(milliseconds: unknown): AbortSignal {
888    required(arguments.length, 1);
889    const number = +(milliseconds as number), delay = trunc(number);
890    if (!isFinite(number) || delay < 0 || delay >= 2 ** 64) {
891      throw new TypeError("milliseconds is outside the accepted range");
892    }
893    const signal = new AbortSignal(secret);
894    scheduleTimeout(() => {
895      abort(
896        signal,
897        createException({
898          message: "The operation timed out",
899          name: "TimeoutError",
900        }),
901      );
902    }, delay);
903    return signal;
904  }
905}
906class AbortController {
907  constructor() {
908    set(controllers, this, new AbortSignal(secret));
909  }
910  get signal() {
911    return state(controllers, this);
912  }
913  abort(reason?: unknown): void {
914    abort(state(controllers, this), reason);
915  }
916}
917function followSignal(signal: unknown): AbortSignal {
918  const source = state(signals, signal), result = new AbortSignal(secret);
919  if (source.aborted) abort(result, source.reason);
920  else {
921    const weak = new WeakRef(result);
922    addAbort(signal, () => {
923      const follower = deref(weak);
924      if (follower) abort(follower, source.reason);
925    });
926  }
927  return result;
928}
929
930export {
931  abort,
932  AbortController,
933  AbortSignal,
934  addAbort,
935  addListener,
936  createException,
937  CustomEvent,
938  dataCloneError,
939  dispatch,
940  DOMException,
941  ErrorEvent,
942  Event,
943  EventTarget,
944  followSignal,
945  hasListener,
946  installGlobalEventTarget,
947  isDispatching,
948  observeListeners,
949  preventDefault,
950  PromiseRejectionEvent,
951  removeListener,
952  reportErrorValue,
953  reportException,
954  reportRejectionHandled,
955  reportUnhandledRejection,
956  secret,
957  signals,
958};