57 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			57 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
import EventEmitter from 'events';
 | 
						|
 | 
						|
export class SaferEmitter extends EventEmitter {
 | 
						|
    emit(type: string, ...args: unknown[]) {
 | 
						|
        let doError = type === 'error';
 | 
						|
 | 
						|
        let events = (this as any)._events;
 | 
						|
        if (events !== undefined) doError = doError && events.error === undefined;
 | 
						|
        else if (!doError) return false;
 | 
						|
 | 
						|
        // If there is no 'error' event listener then throw.
 | 
						|
        if (doError) {
 | 
						|
            let er;
 | 
						|
            if (args.length > 0) er = args[0];
 | 
						|
            if (er instanceof Error) {
 | 
						|
                // Note: The comments on the `throw` lines are intentional, they show
 | 
						|
                // up in Node's output if this results in an unhandled exception.
 | 
						|
                throw er; // Unhandled 'error' event
 | 
						|
            }
 | 
						|
            // At least give some kind of context to the user
 | 
						|
            let err = new Error('Unhandled error.' + (er ? ' (' + (er as any).message + ')' : ''));
 | 
						|
            (err as any).context = er;
 | 
						|
            throw err; // Unhandled 'error' event
 | 
						|
        }
 | 
						|
 | 
						|
        let handler = events[type];
 | 
						|
        if (handler === undefined) return false;
 | 
						|
        if (typeof handler === 'function') {
 | 
						|
            try {
 | 
						|
                Reflect.apply(handler, this, args);
 | 
						|
            } catch (error) {
 | 
						|
                events[type] = undefined;
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            let listeners = [...handler];
 | 
						|
 | 
						|
            listeners
 | 
						|
                .filter((e) => {
 | 
						|
                    try {
 | 
						|
                        e.call;
 | 
						|
                    } catch (error) {
 | 
						|
                        return false;
 | 
						|
                    }
 | 
						|
                    return true;
 | 
						|
                })
 | 
						|
                .forEach((listener) => {
 | 
						|
                    try {
 | 
						|
                        Reflect.apply(listener, this, args);
 | 
						|
                    } catch (error) {
 | 
						|
                        console.error(error);
 | 
						|
                    }
 | 
						|
                });
 | 
						|
        }
 | 
						|
        return true;
 | 
						|
    }
 | 
						|
}
 |