Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | 485x 485x 1299x 1299x 1299x 1299x 1299x 1299x 1262x 1255x 1255x 1255x 485x 3x 3x 3x 8x 8x 8x 8x 2409x 2409x 79x 65x 2409x 2409x 2407x 482x | import type { RuntimeEvent, RuntimeEventListener, Unsubscribe } from '../core/types';
/** Typed event emitter with deterministic delivery and cancellable events. @internal */
export interface TypedEventEmitter<TEvents extends object> {
/** Registers a listener and returns an idempotent unsubscribe function. */
on<TKey extends keyof TEvents>(
type: TKey,
listener: RuntimeEventListener<TEvents[TKey]>,
): Unsubscribe;
/** Removes a listener registered for the specified event. */
off<TKey extends keyof TEvents>(type: TKey, listener: RuntimeEventListener<TEvents[TKey]>): void;
/** Registers a listener for one delivery. */
once<TKey extends keyof TEvents>(
type: TKey,
listener: RuntimeEventListener<TEvents[TKey]>,
): Unsubscribe;
/** Delivers a typed payload and returns false when a listener cancelled it. */
emit<TKey extends keyof TEvents>(type: TKey, detail: TEvents[TKey]): boolean;
/** Removes every listener. */
clear(): void;
}
/**
* Creates an emitter whose listener snapshot is stable during each emission.
*
* @remarks Listener additions/removals during emission affect the next emission only.
* @internal
*/
export function createEventEmitter<TEvents extends object>(): TypedEventEmitter<TEvents> {
const listeners = new Map<keyof TEvents, Set<RuntimeEventListener<unknown>>>();
const on = <TKey extends keyof TEvents>(
type: TKey,
listener: RuntimeEventListener<TEvents[TKey]>,
): Unsubscribe => {
const bucket = listeners.get(type) ?? new Set<RuntimeEventListener<unknown>>();
listeners.set(type, bucket);
const genericListener = listener as RuntimeEventListener<unknown>;
bucket.add(genericListener);
let active = true;
return () => {
if (!active) return;
active = false;
bucket.delete(genericListener);
if (bucket.size === 0) listeners.delete(type);
};
};
return {
on,
off(type, listener) {
const bucket = listeners.get(type);
bucket?.delete(listener as RuntimeEventListener<unknown>);
if (bucket?.size === 0) listeners.delete(type);
},
once(type, listener) {
const unsubscribe: Unsubscribe = on(type, (event) => {
unsubscribe();
listener(event);
});
return unsubscribe;
},
emit(type, detail) {
let prevented = false;
const event: RuntimeEvent<TEvents[typeof type]> = {
detail,
get defaultPrevented() {
return prevented;
},
preventDefault() {
prevented = true;
},
};
const snapshot = [...(listeners.get(type) ?? [])];
for (const listener of snapshot) listener(event);
return !prevented;
},
clear() {
listeners.clear();
},
};
}
|