mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-22 01:29:04 +01:00
Merge pull request #157171 from mjbvz/able-rooster
Try using AbortController for disposable dom listeners
This commit is contained in:
@@ -29,40 +29,20 @@ export function isInDOM(node: Node | null): boolean {
|
||||
return node?.isConnected ?? false;
|
||||
}
|
||||
|
||||
class DomListener implements IDisposable {
|
||||
|
||||
private _handler: (e: any) => void;
|
||||
private _node: EventTarget;
|
||||
private readonly _type: string;
|
||||
private readonly _options: boolean | AddEventListenerOptions;
|
||||
|
||||
constructor(node: EventTarget, type: string, handler: (e: any) => void, options?: boolean | AddEventListenerOptions) {
|
||||
this._node = node;
|
||||
this._type = type;
|
||||
this._handler = handler;
|
||||
this._options = (options || false);
|
||||
this._node.addEventListener(this._type, this._handler, this._options);
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
if (!this._handler) {
|
||||
// Already disposed
|
||||
return;
|
||||
}
|
||||
|
||||
this._node.removeEventListener(this._type, this._handler, this._options);
|
||||
|
||||
// Prevent leakers from holding on to the dom or handler func
|
||||
this._node = null!;
|
||||
this._handler = null!;
|
||||
}
|
||||
}
|
||||
|
||||
export function addDisposableListener<K extends keyof GlobalEventHandlersEventMap>(node: EventTarget, type: K, handler: (event: GlobalEventHandlersEventMap[K]) => void, useCapture?: boolean): IDisposable;
|
||||
export function addDisposableListener(node: EventTarget, type: string, handler: (event: any) => void, useCapture?: boolean): IDisposable;
|
||||
export function addDisposableListener(node: EventTarget, type: string, handler: (event: any) => void, options: AddEventListenerOptions): IDisposable;
|
||||
export function addDisposableListener<K extends keyof GlobalEventHandlersEventMap>(node: EventTarget, type: K, handler: (event: GlobalEventHandlersEventMap[K]) => void, useCaptureOrOptions?: boolean | AddEventListenerOptions): IDisposable;
|
||||
export function addDisposableListener(node: EventTarget, type: string, handler: (event: any) => void, useCaptureOrOptions?: boolean | AddEventListenerOptions): IDisposable;
|
||||
export function addDisposableListener(node: EventTarget, type: string, handler: (event: any) => void, useCaptureOrOptions?: boolean | AddEventListenerOptions): IDisposable {
|
||||
return new DomListener(node, type, handler, useCaptureOrOptions);
|
||||
let controller: AbortController | undefined = new AbortController();
|
||||
|
||||
const opts: AddEventListenerOptions = typeof useCaptureOrOptions === 'boolean'
|
||||
? { capture: useCaptureOrOptions, signal: controller.signal }
|
||||
: { signal: controller.signal, ...(useCaptureOrOptions ?? {}) };
|
||||
|
||||
node.addEventListener(type, handler, opts);
|
||||
return toDisposable(() => {
|
||||
controller?.abort();
|
||||
controller = undefined;
|
||||
});
|
||||
}
|
||||
|
||||
export interface IAddStandardDisposableListenerSignature {
|
||||
@@ -122,18 +102,16 @@ export function addDisposableGenericMouseUpListener(node: EventTarget, handler:
|
||||
}
|
||||
|
||||
export function createEventEmitter<K extends keyof HTMLElementEventMap>(target: HTMLElement, type: K, options?: boolean | AddEventListenerOptions): event.Emitter<HTMLElementEventMap[K]> {
|
||||
let domListener: DomListener | null = null;
|
||||
let domListener: IDisposable | undefined = undefined;
|
||||
const handler = (e: HTMLElementEventMap[K]) => result.fire(e);
|
||||
const onFirstListenerAdd = () => {
|
||||
if (!domListener) {
|
||||
domListener = new DomListener(target, type, handler, options);
|
||||
domListener = addDisposableListener(target, type, handler, options);
|
||||
}
|
||||
};
|
||||
const onLastListenerRemove = () => {
|
||||
if (domListener) {
|
||||
domListener.dispose();
|
||||
domListener = null;
|
||||
}
|
||||
domListener?.dispose();
|
||||
domListener = undefined;
|
||||
};
|
||||
const result = new event.Emitter<HTMLElementEventMap[K]>({ onFirstListenerAdd, onLastListenerRemove });
|
||||
return result;
|
||||
|
||||
Reference in New Issue
Block a user