Skip to content

Fix a-assets image onload crash from loop-variable closure#5809

Open
vincentfretin wants to merge 1 commit intoaframevr:masterfrom
vincentfretin:fix-assets-img
Open

Fix a-assets image onload crash from loop-variable closure#5809
vincentfretin wants to merge 1 commit intoaframevr:masterfrom
vincentfretin:fix-assets-img

Conversation

@vincentfretin
Copy link
Copy Markdown
Contributor

Summary

  • Fixes TypeError: Cannot read properties of undefined (reading 'getAttribute') at a-assets.js:68 when an <img> in <a-assets> finishes loading asynchronously.
  • Regression introduced in 835aac4 (Set the image cache when img is loaded #5778), which moved THREE.Cache.add into the imgEl.onload handler. Before that commit the cache call ran synchronously inside the Promise executor, so the current-iteration imgEl / imgEls[i] were still in scope and there was no crash — but the cache was populated before the image actually finished loading, which is what Set the image cache when img is loaded #5778 correctly set out to fix.
  • Once the call was moved into onload, the callback closed over the shared outer var i / var imgEl. Because var is function-scoped, by the time the handler fired i had already advanced past the end of the images loop (typically to mediaEls.length), so imgEls[i] was undefined and .getAttribute('src') threw.
  • Note: using imgEls[i] would also be semantically off when fixUpMediaElement clones the element, since imgEls[i] is then the pre-clone element that has been detached from the DOM. That part alone wouldn't crash — detached elements still respond to getAttribute — and the src string happens to match the clone's, so the cache key would still be correct. The actual crash is purely the closure/indexing bug above.
  • Fix: bind the current imgEl to a local var el inside the Promise executor and use it in both the .complete and onload branches.

Test plan

  • Added caches image loaded asynchronously alongside media element in tests/core/a-assets.test.js. It uses a cache-busted src (so imgEl.complete is false and the onload path is taken) plus a sibling <audio> element, which reliably reproduces the crash before the fix.
  • Verified the new test fails on master with the exact TypeError from the bug report, and passes with the fix applied.
  • Full a-assets test suite passes (29 tests).

The image onload handler closed over the shared outer loop variables,
so by the time it fired imgEls[i] was undefined (or a stale element
already removed by fixUpMediaElement), causing
"Cannot read properties of undefined (reading 'getAttribute')".
Bind the current img to a local inside the Promise executor.
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.

1 participant