Skip to content

fix: defer xrlayers/xrlayerscene init until XR8 is ready, fix HTML issues#1

Open
tkada wants to merge 1 commit into8thwall:mainfrom
tkada:fix/xr8-init-timing
Open

fix: defer xrlayers/xrlayerscene init until XR8 is ready, fix HTML issues#1
tkada wants to merge 1 commit into8thwall:mainfrom
tkada:fix/xr8-init-timing

Conversation

@tkada
Copy link
Copy Markdown

@tkada tkada commented Apr 4, 2026

Summary

  • Fix ReferenceError: XR8 is not defined in xrlayers.init() and xrlayerscene.init()
  • Move sky-recenter from an inline <script> in index.html to src/app.js (bundled via bundle.js) to prevent duplicate component registration errors
  • Fix malformed closing tag </sky-scene></a-entity>

Root Cause

xr.js is loaded with async="true" and internally uses an async Promise chain. The critical execution order inside xr.js is:

1. yield Promise.all(...)   ← async: loads WASM and other resources
2. window.AFRAME && n()    ← sync: registers A-Frame components → triggers init() immediately
3. window.XR8 = I          ← XR8 global is set HERE (after step 2)

xrlayerscene.init() calls XR8.LayersController.configure(...) and xrlayers.init() calls XR8.GlTextureRenderer.create(...) directly. Since these init() calls are triggered at step 2 — before window.XR8 is assigned at step 3 — the result is:

Uncaught (in promise) ReferenceError: XR8 is not defined
    at n.init (xr.js:43:219643)

Fix

src/app.js wraps AFRAME.registerComponent (executed via bundle.js, which loads synchronously before the async xr.js) to intercept the registration of xrlayers and xrlayerscene. Their init() functions are deferred until the xrloaded event, which is dispatched by xr.js immediately after window.XR8 = I is set.

;(function patchXR8DependentComponents () {
  const _reg = AFRAME.registerComponent.bind(AFRAME)
  AFRAME.registerComponent = function (name, def) {
    if ((name === 'xrlayers' || name === 'xrlayerscene') && typeof def.init === 'function') {
      const origInit = def.init
      def.init = function () {
        const self = this
        const run = () => origInit.call(self)
        window.XR8 ? run() : window.addEventListener('xrloaded', run, { once: true })
      }
    }
    return _reg(name, def)
  }
})()

Test plan

  • No ReferenceError: XR8 is not defined in the browser console
  • Loading screen completes and AR scene is visible with sky effects
  • sky-recenter component works correctly (no duplicate registration error)

Made with Cursor

…sues

xr.js (async) sets window.XR8 AFTER registering A-Frame components:
  1. yield Promise.all(...)  - async WASM load
  2. window.AFRAME && n()   - registers components, triggers init() immediately
  3. window.XR8 = I         - XR8 global set here (too late)

Because xrlayers.init() and xrlayerscene.init() reference XR8 directly,
they throw "ReferenceError: XR8 is not defined" at step 2.

Changes:
- Add src/app.js: wrap AFRAME.registerComponent to defer init() of
  xrlayers and xrlayerscene until the "xrloaded" event fires
- Move sky-recenter component from inline <script> in index.html to app.js
  (loaded via bundle.js) to avoid duplicate registration errors
- Fix malformed closing tag </sky-scene> -> </a-entity>

Made-with: Cursor
@cmbartschat
Copy link
Copy Markdown
Contributor

Hi there, I didn't see this pull request until now.

I fixed the build error.

Can you give a little more information about how to reproduce the load order issue?

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.

2 participants