diff options
Diffstat (limited to 'remote/test/puppeteer/packages/puppeteer-core/src/util/decorators.ts')
-rw-r--r-- | remote/test/puppeteer/packages/puppeteer-core/src/util/decorators.ts | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/remote/test/puppeteer/packages/puppeteer-core/src/util/decorators.ts b/remote/test/puppeteer/packages/puppeteer-core/src/util/decorators.ts index af21c5fe29..c4dc3b6c0d 100644 --- a/remote/test/puppeteer/packages/puppeteer-core/src/util/decorators.ts +++ b/remote/test/puppeteer/packages/puppeteer-core/src/util/decorators.ts @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +import type {EventType} from '../common/EventEmitter.js'; +import type {EventEmitter} from '../common/EventEmitter.js'; import type {Disposed, Moveable} from '../common/types.js'; import {asyncDisposeSymbol, disposeSymbol} from './disposable.js'; @@ -138,3 +140,67 @@ export function guarded<T extends object>( }; }; } + +const bubbleHandlers = new WeakMap<object, Map<any, any>>(); + +/** + * Event emitter fields marked with `bubble` will have their events bubble up + * the field owner. + */ +// The type is too complicated to type. +// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types +export function bubble<T extends EventType[]>(events?: T) { + return <This extends EventEmitter<any>, Value extends EventEmitter<any>>( + {set, get}: ClassAccessorDecoratorTarget<This, Value>, + context: ClassAccessorDecoratorContext<This, Value> + ): ClassAccessorDecoratorResult<This, Value> => { + context.addInitializer(function () { + const handlers = bubbleHandlers.get(this) ?? new Map(); + if (handlers.has(events)) { + return; + } + + const handler = + events !== undefined + ? (type: EventType, event: unknown) => { + if (events.includes(type)) { + this.emit(type, event); + } + } + : (type: EventType, event: unknown) => { + this.emit(type, event); + }; + + handlers.set(events, handler); + bubbleHandlers.set(this, handlers); + }); + return { + set(emitter) { + const handler = bubbleHandlers.get(this)!.get(events)!; + + // In case we are re-setting. + const oldEmitter = get.call(this); + if (oldEmitter !== undefined) { + oldEmitter.off('*', handler); + } + + if (emitter === undefined) { + return; + } + emitter.on('*', handler); + set.call(this, emitter); + }, + // @ts-expect-error -- TypeScript incorrectly types init to require a + // return. + init(emitter) { + if (emitter === undefined) { + return; + } + const handler = bubbleHandlers.get(this)!.get(events)!; + + emitter.on('*', handler); + return emitter; + }, + }; + }; +} |