Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
84 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { describe, expect, jest, test } from '@jest/globals'; | ||
|
||
import { EventEmitter } from './EventEmitter'; | ||
|
||
describe('EventEmitter', () => { | ||
test('fire', () => { | ||
const emitter = new EventEmitter<string>(); | ||
const listener = jest.fn(); | ||
const listener2 = jest.fn(); | ||
emitter.event(listener); | ||
emitter.event(listener2); | ||
emitter.fire('foo'); | ||
expect(listener).toHaveBeenCalledWith('foo'); | ||
expect(listener2).toHaveBeenCalledWith('foo'); | ||
}); | ||
|
||
test('dispose', () => { | ||
const emitter = new EventEmitter<string>(); | ||
const listener = jest.fn(); | ||
const disposable = emitter.event(listener); | ||
emitter.fire('foo'); | ||
disposable.dispose(); | ||
emitter.fire('bar'); | ||
expect(listener).toHaveBeenCalledWith('foo'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
/* eslint-disable @typescript-eslint/no-explicit-any */ | ||
// eslint-disable-next-line node/no-missing-import | ||
import type * as vscode from 'vscode'; | ||
|
||
type Disposable = vscode.Disposable; | ||
|
||
type Listener<T> = (e: T) => any; | ||
|
||
export class EventEmitter<T> implements vscode.EventEmitter<T> { | ||
readonly #listeners = new Set<Listener<T>>(); | ||
|
||
/** | ||
* The event listeners can subscribe to. | ||
*/ | ||
event(listener: (e: T) => any, thisArgs?: any, disposables?: Disposable[]): Disposable { | ||
const fn = thisArgs ? listener.bind(thisArgs) : listener; | ||
this.#listeners.add(fn); | ||
const disposable = { | ||
dispose: () => { | ||
this.#listeners.delete(fn); | ||
}, | ||
}; | ||
|
||
if (disposables) { | ||
disposables.push(disposable); | ||
} | ||
|
||
return disposable; | ||
} | ||
|
||
/** | ||
* Notify all subscribers of the {@link EventEmitter.event event}. Failure | ||
* of one or more listener will not fail this function call. | ||
* | ||
* @param data The event object. | ||
*/ | ||
fire(data: T): void { | ||
for (const listener of this.#listeners) { | ||
try { | ||
listener(data); | ||
} catch { | ||
// ignore | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Dispose this object and free resources. | ||
*/ | ||
dispose(): void { | ||
this.#listeners.clear(); | ||
} | ||
|
||
constructor() {} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters