From 8eee3b27e27066038bd649804b35928c9e0f3877 Mon Sep 17 00:00:00 2001 From: Simon <10131203+gaomeng1900@users.noreply.github.com> Date: Tue, 31 Mar 2026 19:59:57 +0800 Subject: [PATCH] feat(controller): fix `SimulatorMast` mem leak; add passthrough events --- .../page-controller/src/mask/SimulatorMask.ts | 35 ++++++++++++++++--- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/packages/page-controller/src/mask/SimulatorMask.ts b/packages/page-controller/src/mask/SimulatorMask.ts index eb13eb6..41cbdb4 100644 --- a/packages/page-controller/src/mask/SimulatorMask.ts +++ b/packages/page-controller/src/mask/SimulatorMask.ts @@ -5,7 +5,7 @@ import { isPageDark } from './checkDarkMode' import styles from './SimulatorMask.module.css' import cursorStyles from './cursor.module.css' -export class SimulatorMask { +export class SimulatorMask extends EventTarget { shown: boolean = false wrapper = document.createElement('div') motion: Motion | null = null @@ -19,6 +19,8 @@ export class SimulatorMask { #targetCursorY = 0 constructor() { + super() + this.wrapper.id = 'page-agent-runtime_simulator-mask' this.wrapper.className = styles.wrapper this.wrapper.setAttribute('data-browser-use-ignore', 'true') @@ -74,13 +76,34 @@ export class SimulatorMask { this.#moveCursorToTarget() - window.addEventListener('PageAgent::MovePointerTo', (event: Event) => { + // global events + // @note Mask should be isolated from the rest of the code. + // Global events are easier to manage and cleanup. + + const movePointerToListener = (event: Event) => { const { x, y } = (event as CustomEvent).detail this.setCursorPosition(x, y) - }) - - window.addEventListener('PageAgent::ClickPointer', (event: Event) => { + } + const clickPointerListener = () => { this.triggerClickAnimation() + } + const enablePassThroughListener = () => { + this.wrapper.style.pointerEvents = 'none' + } + const disablePassThroughListener = () => { + this.wrapper.style.pointerEvents = 'auto' + } + + window.addEventListener('PageAgent::MovePointerTo', movePointerToListener) + window.addEventListener('PageAgent::ClickPointer', clickPointerListener) + window.addEventListener('PageAgent::EnablePassThrough', enablePassThroughListener) + window.addEventListener('PageAgent::DisablePassThrough', disablePassThroughListener) + + this.addEventListener('dispose', () => { + window.removeEventListener('PageAgent::MovePointerTo', movePointerToListener) + window.removeEventListener('PageAgent::ClickPointer', clickPointerListener) + window.removeEventListener('PageAgent::EnablePassThrough', enablePassThroughListener) + window.removeEventListener('PageAgent::DisablePassThrough', disablePassThroughListener) }) } @@ -177,7 +200,9 @@ export class SimulatorMask { } dispose() { + console.log('dispose SimulatorMask') this.motion?.dispose() this.wrapper.remove() + this.dispatchEvent(new Event('dispose')) } }