Skip to content

fix(mv): stop PIXI's BaseTexture from clobbering Bitmap's onload handler - #1058

Merged
take-cheeze merged 1 commit into
masterfrom
claude/mv-image-onload-bug
Aug 19, 2026
Merged

fix(mv): stop PIXI's BaseTexture from clobbering Bitmap's onload handler#1058
take-cheeze merged 1 commit into
masterfrom
claude/mv-image-onload-bug

Conversation

@take-cheeze

Copy link
Copy Markdown
Owner

Summary

  • The player never actually moved in any MV game ([MV-MOVE] ... moved=false on every probe, on both data/mv-sample and the downloaded data/Lunatic-Core bed) because Scene_Map never became active: the map tileset's Bitmap got permanently stuck at _loadingState: 'requesting'.
  • Root cause, found via an instance-level Object.defineProperty watchpoint on the tileset Image's onload (capturing a JS stack on every write): our Image shim (mruby-mvjs/src/mvcanvas.cxx) aliased addEventListener('load'/'error', cb) to the single onload/onerror property. Bitmap#_requestImage attaches its own completion handler that way, but PIXI's BaseTexture also assigns image.onload directly when wrapping an incomplete Image (to learn when it finishes loading) — on a real browser these are independent listener slots that both fire, but our shim let PIXI's later direct assignment silently discard MV's own handler.
  • Image now keeps addEventListener-registered listeners and the onload/onerror properties independent, firing both — matching the real DOM contract.
  • Also added a generation counter so a stale queued completion from a previous .src assignment can't land on a reused Image instance after a new owner has already re-armed it (MV pools and reuses Image objects via Bitmap._reuseImages).
  • Closed the CI assertion gap that let this go unnoticed: the MV movement smokes only checked the process exit code, unlike MZ's moved=true grep. Both MV movement-relevant smoke steps now assert it too.

Test plan

  • ./build/mruby/host/bin/mrbtest — 1818/1818 OK, 0 failures
  • bash scripts/mz_boot_check.bash — all MZ smokes pass (shared Image shim, unaffected)
  • Manual repro against data/mv-sample: [MV-MOVE] ... moved=true consistently across repeated runs
  • Manual repro against data/Lunatic-Core (real downloaded game): [MV-MOVE] ... moved=true
  • docs/TODO.md M5 write-up updated to reflect the fix (was ⚠️, now ); M5 milestone header flipped to
  • Changelog fragment added

Generated by Claude Code

The player never actually moved in any MV game: Scene_Map never became
active because the tileset Bitmap got permanently stuck at
_loadingState: 'requesting'. Root cause was the Image shim aliasing
addEventListener('load'/'error', ...) to the single onload/onerror
property slot. Bitmap#_requestImage attaches its own completion
handler that way, but PIXI's BaseTexture also assigns image.onload
directly when wrapping an incomplete Image -- on a real browser these
are independent listener slots that both fire, but our shim let
PIXI's later direct assignment silently discard MV's own handler.

Image now keeps addEventListener-registered listeners and the
onload/onerror properties independent, firing both. Also added a
generation counter so a stale queued completion from a previous .src
assignment can't land on a reused Image instance (MV pools and reuses
Image objects via Bitmap._reuseImages) after a new owner has already
re-armed it.

Verified against both data/mv-sample and the downloaded Lunatic-Core
bed: [MV-MOVE] now reports moved=true consistently. Added the missing
CI assertion (grep for moved=true, matching the MZ movement smoke)
to the two MV movement-relevant smoke steps so a regression here
fails CI directly instead of only being visible by reading logs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RmARb1uB2F9rXRg6tQsGgR
@take-cheeze
take-cheeze enabled auto-merge August 19, 2026 02:14
@github-actions github-actions Bot added component:graphics Rendering: bitmaps, tilemaps, sprites, windows, fonts component:runtime-js QuickJS host for MV/MZ: JS bindings, canvas, WebGL component:ci GitHub Actions workflows, caching, deploys component:docs README, /docs, ADRs, changelog fragments auto-merge Auto-merge is enabled; treat as already review-approved (see AGENTS.md) labels Aug 19, 2026
@take-cheeze
take-cheeze merged commit b0a3d69 into master Aug 19, 2026
12 checks passed
@take-cheeze
take-cheeze deleted the claude/mv-image-onload-bug branch August 19, 2026 02:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

auto-merge Auto-merge is enabled; treat as already review-approved (see AGENTS.md) component:ci GitHub Actions workflows, caching, deploys component:docs README, /docs, ADRs, changelog fragments component:graphics Rendering: bitmaps, tilemaps, sprites, windows, fonts component:runtime-js QuickJS host for MV/MZ: JS bindings, canvas, WebGL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants