constructor(parentSignals) {
        this._signal = new AbortSignal();
        if (!parentSignals) {
            return;
        }
        // coerce parentSignals into an array
        if (!Array.isArray(parentSignals)) {
            // eslint-disable-next-line prefer-rest-params
            parentSignals = arguments;
        }
        for (const parentSignal of parentSignals) {
            // if the parent signal has already had abort() called,
            // then call abort on this signal as well.
            if (parentSignal.aborted) {
                this.abort();
            }
            else {
                // when the parent signal aborts, this signal should as well.
                parentSignal.addEventListener("abort", () => {
                    this.abort();
                });
            }
        }
    }
An AbortController provides an AbortSignal and the associated controls to signal
that an asynchronous operation should be aborted.

@example
Abort an operation when another event fires
```ts
const controller = new AbortController();
const signal = controller.signal;
doAsyncWork(signal);
button.addEventListener('click', () => controller.abort());
```

@example
Share aborter cross multiple operations in 30s
```ts
// Upload the same data to 2 different data centers at the same time,
// abort another when any of them is finished
const controller = AbortController.withTimeout(30 * 1000);
doAsyncWork(controller.signal).then(controller.abort);
doAsyncWork(controller.signal).then(controller.abort);
```

@example
Cascaded aborting
```ts
// All operations can't take more than 30 seconds
const aborter = Aborter.timeout(30 * 1000);

// Following 2 operations can't take more than 25 seconds
await doAsyncWork(aborter.withTimeout(25 * 1000));
await doAsyncWork(aborter.withTimeout(25 * 1000));
```