@@ -2210,6 +2210,118 @@ describe('defineCustomElement', () => {
22102210 expect ( barVal ) . toBe ( 'bar' )
22112211 } )
22122212
2213+ test ( 'nested async custom elements should mount ancestor-first' , async ( ) => {
2214+ const mounted : string [ ] = [ ]
2215+ const OuterComp = defineComponent ( {
2216+ setup ( ) {
2217+ provide ( 'foo' , 'foo' )
2218+ } ,
2219+ mounted ( ) {
2220+ mounted . push ( 'outer' )
2221+ } ,
2222+ render ( ) {
2223+ return h ( 'slot' )
2224+ } ,
2225+ } )
2226+ const MiddleComp = defineComponent ( {
2227+ setup ( ) {
2228+ provide ( 'bar' , 'bar' )
2229+ } ,
2230+ mounted ( ) {
2231+ mounted . push ( 'middle' )
2232+ } ,
2233+ render ( ) {
2234+ return h ( 'slot' )
2235+ } ,
2236+ } )
2237+ const InnerComp = defineComponent ( {
2238+ setup ( ) {
2239+ const foo = inject ( 'foo' )
2240+ const bar = inject ( 'bar' )
2241+ return ( ) => h ( 'div' , `${ foo } /${ bar } ` )
2242+ } ,
2243+ mounted ( ) {
2244+ mounted . push ( 'inner' )
2245+ } ,
2246+ } )
2247+ let resolveOuter ! : ( comp : typeof OuterComp ) => void
2248+ let resolveMiddle ! : ( comp : typeof MiddleComp ) => void
2249+ let resolveInner ! : ( comp : typeof InnerComp ) => void
2250+ const outerReady = new Promise < typeof OuterComp > ( resolve => {
2251+ resolveOuter = resolve
2252+ } )
2253+ const middleReady = new Promise < typeof MiddleComp > ( resolve => {
2254+ resolveMiddle = resolve
2255+ } )
2256+ const innerReady = new Promise < typeof InnerComp > ( resolve => {
2257+ resolveInner = resolve
2258+ } )
2259+
2260+ const Outer = defineCustomElement ( defineAsyncComponent ( ( ) => outerReady ) )
2261+ const Middle = defineCustomElement ( defineAsyncComponent ( ( ) => middleReady ) )
2262+ const Inner = defineCustomElement ( defineAsyncComponent ( ( ) => innerReady ) )
2263+
2264+ customElements . define ( 'async-chain-outer' , Outer )
2265+ customElements . define ( 'async-chain-middle' , Middle )
2266+ customElements . define ( 'async-chain-inner' , Inner )
2267+ container . innerHTML =
2268+ `<async-chain-outer>` +
2269+ `<async-chain-middle>` +
2270+ `<async-chain-inner></async-chain-inner>` +
2271+ `</async-chain-middle>` +
2272+ `</async-chain-outer>`
2273+
2274+ resolveInner ( InnerComp )
2275+ resolveOuter ( OuterComp )
2276+ await new Promise ( resolve => setTimeout ( resolve ) )
2277+ resolveMiddle ( MiddleComp )
2278+ await new Promise ( resolve => setTimeout ( resolve ) )
2279+
2280+ const inner = container . querySelector ( 'async-chain-inner' ) as VueElement
2281+ expect ( mounted ) . toEqual ( [ 'outer' , 'middle' , 'inner' ] )
2282+ expect ( inner . shadowRoot ! . innerHTML ) . toBe ( '<div>foo/bar</div>' )
2283+ } )
2284+
2285+ test ( 'should not resolve nested custom element after disconnect' , async ( ) => {
2286+ const mounted = vi . fn ( )
2287+ const ParentComp = defineComponent ( {
2288+ render ( ) {
2289+ return h ( 'slot' )
2290+ } ,
2291+ } )
2292+ let resolveParent ! : ( comp : typeof ParentComp ) => void
2293+ const parentReady = new Promise < typeof ParentComp > ( resolve => {
2294+ resolveParent = resolve
2295+ } )
2296+ const Parent = defineCustomElement ( defineAsyncComponent ( ( ) => parentReady ) )
2297+ const Child = defineCustomElement ( {
2298+ mounted,
2299+ render ( ) {
2300+ return h ( 'div' , 'child' )
2301+ } ,
2302+ } )
2303+
2304+ customElements . define ( 'async-disconnect-parent' , Parent )
2305+ customElements . define ( 'async-disconnect-child' , Child )
2306+ container . innerHTML =
2307+ `<async-disconnect-parent>` +
2308+ `<async-disconnect-child></async-disconnect-child>` +
2309+ `</async-disconnect-parent>`
2310+
2311+ const parent = container . firstChild as VueElement
2312+ const child = parent . firstChild as VueElement
2313+ child . remove ( )
2314+ resolveParent ( ParentComp )
2315+ await new Promise ( resolve => setTimeout ( resolve ) )
2316+
2317+ expect ( mounted ) . not . toHaveBeenCalled ( )
2318+ expect ( child . shadowRoot ! . innerHTML ) . toBe ( '' )
2319+
2320+ parent . appendChild ( child )
2321+ expect ( mounted ) . toHaveBeenCalledOnce ( )
2322+ expect ( child . shadowRoot ! . innerHTML ) . toBe ( '<div>child</div>' )
2323+ } )
2324+
22132325 describe ( 'configureApp' , ( ) => {
22142326 test ( 'should work' , ( ) => {
22152327 const E = defineCustomElement (
0 commit comments