Skip to content

fix(mask): dispose 后 requestAnimationFrame 循环未停止导致内存泄漏#418

Merged
gaomeng1900 merged 2 commits intoalibaba:mainfrom
lgy2020:fix/simulator-mask-raf-leak
Apr 13, 2026
Merged

fix(mask): dispose 后 requestAnimationFrame 循环未停止导致内存泄漏#418
gaomeng1900 merged 2 commits intoalibaba:mainfrom
lgy2020:fix/simulator-mask-raf-leak

Conversation

@lgy2020
Copy link
Copy Markdown
Contributor

@lgy2020 lgy2020 commented Apr 8, 2026

What

修复 SimulatorMask 组件中
equestAnimationFrame 动画循环在 dispose() 调用后不会停止的资源泄漏问题。

Type

  • Bug fix

问题描述

#moveCursorToTarget() 方法通过
equestAnimationFrame 递归调用自身,为 AI 光标创建持续的动画循环。但 dispose() 方法仅移除了 DOM 包装元素,没有停止这个动画循环,导致:

  • CPU 浪费:dispose 后 rAF 回调仍以 ~60fps 频率持续执行,对已从 DOM 移除的 cursor 元素做无用计算
  • 资源泄漏:每个 SimulatorMask 实例创建的动画循环在页面生命周期内无法回收
  • 控制台噪声:对已移除 DOM 节点的 style 赋值可能产生浏览器警告

修复方案

添加 #disposed 布尔标志位:

  1. 在 #moveCursorToTarget() 入口检查,已 dispose 则直接 return 退出递归
  2. 在 dispose() 最开头设为 rue,确保下一次 rAF 回调立即停止

Changes

  • 新增 #disposed 字段(默认 alse)
  • #moveCursorToTarget() 入口增加 if (this.#disposed) return 守卫
  • dispose() 中在其他清理操作之前设置 his.#disposed = true

Testing

  • Tested in modern browsers
  • No console errors

Requirements / 要求

  • 我已阅读并遵守行为准则和贡献指南
  • 此 PR 非 bot 或 AI 自主生成,我已亲自编写并充分审查了每一处变更

@gaomeng1900 麻烦 review 一下,感谢!

lgy2020 and others added 2 commits April 8, 2026 18:53
…ry leak

The #moveCursorToTarget() method recursively schedules itself via
requestAnimationFrame, creating a continuous animation loop for the
AI cursor. However, dispose() only removes the DOM wrapper element
without stopping this loop, causing:

- CPU waste: rAF callback continues executing every frame (~60fps)
  after the mask is disposed, performing unnecessary calculations
  on a detached cursor element.
- Resource leak: Each SimulatorMask instance creates an unrecoverable
  animation loop that persists for the lifetime of the page.
- Console noise: style assignments to removed DOM nodes may produce
  browser warnings.

Fix: Add a #disposed boolean flag, checked at the top of
#moveCursorToTarget() to short-circuit the recursion. Set the flag
to true in dispose() before removing DOM elements.

Changes:
- Add #disposed field (default false)
- Guard #moveCursorToTarget() with early return when #disposed
- Set #disposed = true in dispose() before cleanup
@gaomeng1900
Copy link
Copy Markdown
Collaborator

LGTM

@gaomeng1900 gaomeng1900 merged commit a1b7684 into alibaba:main Apr 13, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants