Subscribe on changes!

Async webcomponent inside another async webcomponent gives error

avatar
Mar 2nd 2024

Vue version

3.4.21

Link to minimal reproduction

https://play.vuejs.org/#eNqVVM1u2zAMfhVCF6dAamM/p84N0AYdsB26Yh12ElC4NpOqtSVDkpMGQd59lGTZSZcU200kP5If/7RlV22brjpkFyw3pRatBYO2a2dciqZV2sIWKlwIifPOWNXc1NigtNNeeWU2spwrQkrSwg4WWjWQUMCESy6zDH53CPdf53BXF5ulVp2soFJoQCoLa6VfYC3sE1QbWTSihJDTTMEoWBQvCMKmA5OHeaGrPkOaOcExp0TRft1Zq+SACGKP4bJU0ljwMS6P0p9MzuByBnfkLgymGo2qVzjxac/OYoA+yf+FCE4uCIXZb6RJQ5hJ0mzOS0qUxNYe9HsycDjp/OhTnHAf8+dZGDMNmASLTVsXFkkCyNtZ4Qajm6KGMpZ0kWduG8gcgsxuAyBIed/lgHAs/WtE9+0S0ogKffcPXfwcPZlIYI2P50eyDyVGAoMiz0ZbhLpWRiajdXhFPj3yrwhO7kPk2dAkNmVx697eC9hNi5ecWcPZ/u20Wq1cov3L+MJlr54kQsapJ/PkcDxvhlOJVSzI1HQ8Wc806PdYckk8x93/V6ZCPmN5eMJENG69kP3hBNhI/F3Oey0F2LocPspud6yQAfy2FmuIw0Is02ejJJWzdXjO3I6IGvWP1griyNkFeIuzFXWt1t+9zuoOp1FfPmH5ckT/bF6djrM7OlnUK+RssNlCL9EG8839Lb7SezA2qupqQr9j/Ok+gc5xDLBr+gOJ9h7Os/3mByHk8pe5ebVI+9kX5Yg65M7jOaPJuP/mVOkj3U/pZ+/H5Y66+LBC7WJSA8mQfvzAdn8APw8Paw==

Steps to reproduce

  • Create two vue components, like Card and Button
  • Make them async loading using defineAsyncComponent
  • Wrap them as a webcomponent using defineCustomElement
  • Define them using customElements.define
  • In the template put one inside the other `
  • Add another Button outside of the Card, observe the error: Uncaught (in promise): parent._instance is null

What is expected?

Components should be render independent of the existence of other components

What is actually happening?

Error is being thrown Uncaught (in promise): parent._instance is null

System Info

Not relevant, using the SFC Playground gives the same error

Any additional comments?

From my exploration, this can be solved by ensuring the component is loaded before trying to access the parent here. By adding this piece of code here: https://github.com/vuejs/core/blob/main/packages/runtime-dom/src/apiCustomElement.ts#L407

            const _def = parent._def as ComponentOptions;
            if (_def.__asyncLoader && !_def.__asyncResolved) {
              await _def.__asyncLoader();
            }