PointerEventReceiver memory leak
Steps to Reproduce
- Instantiate and start an engine in any configuration.
- Add and initialize any scene that removes the default
PointerSystem(e.g.this.world.remove(this.world.get(PointerSystem))). - Move, click, or scroll your mouse.
The culprit of the issue is a combination of these two pieces of code:
-
PointerEventReceiverappends pointer events to internal arrays that are cleared via an external call of its clear method. -
PointerSystemis currently responsible for the external call to the receiver's clear method: https://github.com/excaliburjs/Excalibur/blob/main/src/engine/Input/PointerSystem.ts#L163.
Expected Result
When removing the default PointerSystem, the engine or scene do not allocate or retain memory related to pointer events.
Actual Result
For every native pointer event:
- Two event listener handlers are invoked (one for the engine and one for the scene).
- Two references per pointer event are retained indefinitely (one by the by the engine's
PointerEventReceiverand one by the scene'sPointerEventReceiver).
Environment
- browsers and versions: Chrome 131.0.6778.265
- operating system: MacOS
- Excalibur versions: 0.30.3
- The memory leak does not depend on the environment.
Current Workaround
Detach both input receivers when initializing the scene that removes the default pointer system:
public override onInitialize(): void {
this.world.remove(this.world.get(PointerSystem));
this.input.pointers.detach();
this.engine.input.pointers.detach();
}
Potential Quick Fix
Normally, the PointerSystem calls clear() on both input receivers at the end of its update loop. Alternatively (or additionally), clear() could be called by the pointer event receiver itself as the first step to its update().
Potential Robust Fix
The quick fix is not ideal because it still incurs superfluous allocation and execution. Rather than having the engine and scene manage pointer event listeners, the pointer system itself should manage the listeners. This way the system can remove the listeners when deactivated, disabled, disposed, and/or removed.
@blakearoberts Thanks for the bug! Definitely an issue...
I do agree that perhaps pointer management should wholly be contained within the PointerSystem. It definitely feels right.
The current state is a vestige of Excalibur's evolution over time to an ECS based engine.
This issue hasn't had any recent activity lately and is being marked as stale automatically.