diff --git a/build/lib/layersChecker.js b/build/lib/layersChecker.js index 2580ebe4e3a..29bc918be45 100644 --- a/build/lib/layersChecker.js +++ b/build/lib/layersChecker.js @@ -51,6 +51,7 @@ const CORE_TYPES = [ 'BigInt64Array', 'btoa', 'atob', + 'AbortController', 'AbortSignal', 'MessageChannel', 'MessagePort', diff --git a/build/lib/layersChecker.ts b/build/lib/layersChecker.ts index 7e93c1413b0..a6f71473867 100644 --- a/build/lib/layersChecker.ts +++ b/build/lib/layersChecker.ts @@ -52,6 +52,7 @@ const CORE_TYPES = [ 'BigInt64Array', 'btoa', 'atob', + 'AbortController', 'AbortSignal', 'MessageChannel', 'MessagePort', diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts index 1ff6fda0127..3ddc0d543ba 100644 --- a/src/vs/base/browser/dom.ts +++ b/src/vs/base/browser/dom.ts @@ -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(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(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(target: HTMLElement, type: K, options?: boolean | AddEventListenerOptions): event.Emitter { - 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({ onFirstListenerAdd, onLastListenerRemove }); return result;