SkillBarHUD icon load callback mounts a mesh after dispose #1083

Closed
opened 2026-08-13 13:53:36 +00:00 by spikerj · 1 comment
Owner

Where: projects/spikersoft/src/app/_components/_games/dungeon-crawler/hud/skill-bar-hud.ts — loadIcon() TextureLoader callback → addIconMesh().

What: Icon loads are async and uncancelled. If dispose() (or setSlots/resize → clearGroup()) runs before the callback, addIconMesh still group.add(mesh) and pushes onto iconSprites. The disposed HUD grows a stray textured quad; a rebuild can also get icons at the previous slot positions.

Repro (unit): stub TextureLoader.load to defer onLoad, setSlots([{icon:'/x.png'}]), dispose(), then fire the callback → group.children.length === 1.

Expected: ignore the callback if disposed / generation changed, or abort in-flight loads on clearGroup/dispose.

Found by Wave 8 a2 coverage tests.

**Where:** `projects/spikersoft/src/app/_components/_games/dungeon-crawler/hud/skill-bar-hud.ts` — `loadIcon()` TextureLoader callback → `addIconMesh()`. **What:** Icon loads are async and uncancelled. If `dispose()` (or `setSlots`/`resize` → `clearGroup()`) runs before the callback, `addIconMesh` still `group.add(mesh)` and pushes onto `iconSprites`. The disposed HUD grows a stray textured quad; a rebuild can also get icons at the *previous* slot positions. **Repro (unit):** stub `TextureLoader.load` to defer `onLoad`, `setSlots([{icon:'/x.png'}])`, `dispose()`, then fire the callback → `group.children.length === 1`. **Expected:** ignore the callback if disposed / generation changed, or abort in-flight loads on `clearGroup`/`dispose`. Found by Wave 8 a2 coverage tests.
Author
Owner

Fixed in spikersoft-angular PR #823 (a0f0ccd9). Closing.

Fixed in `spikersoft-angular` [PR #823](https://git.spikersoft.com/spikerj/spikersoft-angular/pulls/823) (`a0f0ccd9`). Closing.
Sign in to join this conversation.