EngineStatusHUD.dispose leaks unstored row-label Text objects #1098

Closed
opened 2026-08-13 14:22:50 +00:00 by spikerj · 1 comment
Owner

While covering EngineStatusHUD leftover (Wave 8 a1 tick 3, tests only).

What happens: dispose() only walks the named Text/Mesh fields (titleText, value texts, bar fills). Row captions created in createThrottleRow / createStatRow / createHeatRow / createBoostRow (THROTTLE, HEALTH, HEAT, BOOST) are group.added but never stored, so they are not removed or dispose()d.

rebuildUI() does walk every group.children entry, so a resize is clean; a HUD teardown via dispose() is not.

User-visible: leaving a space-game session (or toggling the engine HUD off) leaks four troika Text meshes + their glyph resources per HUD instance. Repeating play/exit grows GPU memory.

Fix: either store the label refs and dispose them with the others, or walk group.children the same way rebuildUI does (and null the named fields so a second dispose() is a no-op).

Repro (jsdom, mocked troika): after new EngineStatusHUD().dispose(), group.children.length === 4 (the unstored labels).

File: projects/spikersoft/src/app/_components/_games/space-game/hud/engine-status-hud.ts

While covering `EngineStatusHUD` leftover (Wave 8 a1 tick 3, tests only). **What happens:** `dispose()` only walks the *named* Text/Mesh fields (`titleText`, value texts, bar fills). Row captions created in `createThrottleRow` / `createStatRow` / `createHeatRow` / `createBoostRow` (`THROTTLE`, `HEALTH`, `HEAT`, `BOOST`) are `group.add`ed but never stored, so they are not removed or `dispose()`d. `rebuildUI()` *does* walk every `group.children` entry, so a resize is clean; a HUD teardown via `dispose()` is not. **User-visible:** leaving a space-game session (or toggling the engine HUD off) leaks four troika Text meshes + their glyph resources per HUD instance. Repeating play/exit grows GPU memory. **Fix:** either store the label refs and dispose them with the others, or walk `group.children` the same way `rebuildUI` does (and null the named fields so a second `dispose()` is a no-op). **Repro (jsdom, mocked troika):** after `new EngineStatusHUD().dispose()`, `group.children.length === 4` (the unstored labels). File: `projects/spikersoft/src/app/_components/_games/space-game/hud/engine-status-hud.ts`
Author
Owner

Resolved in spikersoft-angular PR #819 (merged to master). EngineStatusHUD.dispose disposes unstored row-label Texts. Closing.

Resolved in spikersoft-angular [PR #819](https://git.spikersoft.com/spikerj/spikersoft-angular/pulls/819) (merged to `master`). EngineStatusHUD.dispose disposes unstored row-label Texts. Closing.
Sign in to join this conversation.