UNPKG

@virtualstate/app-history

Version:

Native JavaScript [app-history](https://github.com/WICG/app-history) implementation

54 lines (45 loc) 2.07 kB
import { Event } from "./event" import { isSignalEvent, isSignalHandled } from "./signal-event" import { AbortError } from "../app-history-errors" import {EventTargetListenersMatch, EventTargetListenersThis} from "./event-target-options" import { EventTargetListeners } from "./event-target-listeners" export interface SyncEventTarget extends EventTargetListeners { new (thisValue?: unknown): SyncEventTarget; dispatchEvent(event: Event): void | Promise<void> } export class SyncEventTarget extends EventTargetListeners implements SyncEventTarget { readonly [EventTargetListenersThis]: unknown constructor(thisValue: unknown = undefined) { super(); this[EventTargetListenersThis] = thisValue } dispatchEvent(event: Event) { const listeners = this[EventTargetListenersMatch]?.(event.type) ?? []; // Don't even dispatch an aborted event if (isSignalEvent(event) && event.signal.aborted) { throw new AbortError(); } for (let index = 0; index < listeners.length; index += 1) { const descriptor = listeners[index]; // Remove the listener before invoking the callback // This ensures that inside of the callback causes no more additional event triggers to this // listener if (descriptor.once) { // by passing the descriptor as the options, we get an internal redirect // that forces an instance level object equals, meaning // we will only remove _this_ descriptor! this.removeEventListener(descriptor.type, descriptor.callback, descriptor); } try { descriptor.callback.call(this[EventTargetListenersThis] ?? this, event); } catch (error) { if (!isSignalHandled(event, error)) { throw error; } } if (isSignalEvent(event) && event.signal.aborted) { throw new AbortError(); } } } }