Skip to content

fix(rune): wait for texture images to finish loading before drawing - #892

Merged
martin-henz merged 2 commits into
masterfrom
fix/rune-texture-load-race
Aug 7, 2026
Merged

fix(rune): wait for texture images to finish loading before drawing#892
martin-henz merged 2 commits into
masterfrom
fix/rune-texture-load-race

Conversation

@martin-henz

Copy link
Copy Markdown
Member

Summary

  • rune.ts's loadTexture only awaited image load when the texture arrived as a raw URL string. When a rune is deserialized on the tab side (protocol.ts's deserializeRune), it constructs an HTMLImageElement, sets .src, and hands it back immediately without waiting for the fetch/decode to finish - loadTexture then took the typeof imageSource !== 'string' branch and uploaded that (possibly still-loading) image straight to WebGL, racing the actual download. Losing the race left the 1x1 placeholder pixel (opaque blue) as the visible texture instead of the real image.
  • Now loadTexture waits for image completion unconditionally, regardless of whether the image was just constructed from a URL or handed in already (maybe) loading.

Fixes #891

Test plan

  • Added src/bundles/rune/src/__tests__/rune.test.ts covering drawRunesToFrameBuffer: a texture image that's still loading is not uploaded until it fires onload; an already-loaded image uploads immediately; an already-errored image rejects. Verified the first two tests fail against the pre-fix code (confirms they catch the regression) and pass after the fix.
  • yarn buildtools test --project src/bundles/rune - all 51 tests pass
  • yarn buildtools tsc - clean
  • yarn eslint on changed files - clean

🤖 Generated with Claude Code

https://claude.ai/code/session_018mNjABo3YLgMJc1GS2DcpC

`deserializeRune` hands the draw path an HTMLImageElement whose
fetch/decode may still be in flight - `loadTexture` only waited for
load when the texture arrived as a raw URL string, so an
already-constructed-but-still-loading image (the normal path for
runes rendered in the tab) got uploaded to WebGL as-is, leaving the
1x1 placeholder pixel (opaque blue) as the visible texture. Wait for
image completion unconditionally instead.

Fixes #891

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018mNjABo3YLgMJc1GS2DcpC
@martin-henz

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

drawRunesToFrameBuffer now waits for image readiness before uploading textures to WebGL. Tests cover loading, already-loaded, and failed images with a mocked WebGL context.

Changes

Rune texture loading

Layer / File(s) Summary
Image readiness handling
src/bundles/rune/src/rune.ts
waitForImageToLoad resolves loaded images, waits for loading images, and rejects failed images. Texture sources now use this helper before WebGL upload.
Texture loading behavior tests
src/bundles/rune/src/__tests__/rune.test.ts
Tests verify delayed texture upload, immediate upload for loaded images, draw ordering, and rejection for failed images.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant drawRunesToFrameBuffer
  participant waitForImageToLoad
  participant HTMLImageElement
  participant WebGL

  drawRunesToFrameBuffer->>waitForImageToLoad: wait for texture readiness
  waitForImageToLoad->>HTMLImageElement: inspect readiness or wait for events
  HTMLImageElement-->>waitForImageToLoad: loaded image or load failure
  waitForImageToLoad-->>drawRunesToFrameBuffer: resolve or reject
  drawRunesToFrameBuffer->>WebGL: upload resolved texture
  drawRunesToFrameBuffer->>WebGL: draw textured geometry
Loading

Suggested reviewers: leeyi45

Poem

I’m a rabbit with a texture to load,
I wait for the image before the road.
No blue-screen leap, no hurried flight,
WebGL draws when the pixels are right.
Hop, hop—failed loads now signal clear!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly states that Rune texture images now wait for loading before drawing.
Description check ✅ Passed The description explains the bug, references issue #891, describes the fix, and lists reproducible tests and validation results.
Linked Issues check ✅ Passed The changes address issue #891 by waiting for texture images to finish loading before WebGL upload and drawing.
Out of Scope Changes check ✅ Passed The implementation and regression tests are directly related to the image-loading race described in issue #891.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/rune-texture-load-race

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/bundles/rune/src/rune.ts`:
- Around line 167-169: Update waitForImageToLoad() to register its load, abort,
and error callbacks with addEventListener instead of overwriting
HTMLImageElement handlers. Store the registered callbacks and remove all three
listeners when the promise settles, while preserving the existing resolve/reject
behavior for images supplied through Rune.of().
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c62c6233-8f5b-4ef8-b154-fd0d23e3fdf8

📥 Commits

Reviewing files that changed from the base of the PR and between 398b9e4 and f51af3f.

📒 Files selected for processing (2)
  • src/bundles/rune/src/__tests__/rune.test.ts
  • src/bundles/rune/src/rune.ts

Comment thread src/bundles/rune/src/rune.ts Outdated
waitForImageToLoad previously assigned image.onload/onerror/onabort
directly, which would clobber any handlers already attached to a
caller-supplied HTMLImageElement (Rune.of accepts one). Not currently
reachable since the only image producer (protocol.ts's imageFromUrl)
never attaches handlers before handing the image off, but the helper
is typed to accept any HTMLImageElement, so use
addEventListener/removeEventListener instead.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018mNjABo3YLgMJc1GS2DcpC
@martin-henz
martin-henz merged commit 006b7af into master Aug 7, 2026
12 checks passed
@martin-henz
martin-henz deleted the fix/rune-texture-load-race branch August 7, 2026 00:38
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.

runes: synchronous loading of images in from_url

1 participant