@@ -1641,6 +1641,141 @@ describe('Suspense', () => {
16411641 expect ( serializeInner ( root ) ) . toBe ( expected )
16421642 } )
16431643
1644+ //#8678
1645+ test ( 'nested suspense (child suspense update before parent suspense resolve)' , async ( ) => {
1646+ const calls : string [ ] = [ ]
1647+
1648+ const InnerA = defineAsyncComponent (
1649+ {
1650+ setup : ( ) => {
1651+ calls . push ( 'innerA created' )
1652+ onMounted ( ( ) => {
1653+ calls . push ( 'innerA mounted' )
1654+ } )
1655+ return ( ) => h ( 'div' , 'innerA' )
1656+ } ,
1657+ } ,
1658+ 10 ,
1659+ )
1660+
1661+ const InnerB = defineAsyncComponent (
1662+ {
1663+ setup : ( ) => {
1664+ calls . push ( 'innerB created' )
1665+ onMounted ( ( ) => {
1666+ calls . push ( 'innerB mounted' )
1667+ } )
1668+ return ( ) => h ( 'div' , 'innerB' )
1669+ } ,
1670+ } ,
1671+ 10 ,
1672+ )
1673+
1674+ const OuterA = defineAsyncComponent (
1675+ {
1676+ setup : ( _ , { slots } : any ) => {
1677+ calls . push ( 'outerA created' )
1678+ onMounted ( ( ) => {
1679+ calls . push ( 'outerA mounted' )
1680+ } )
1681+ return ( ) =>
1682+ h ( Fragment , null , [ h ( 'div' , 'outerA' ) , slots . default ?.( ) ] )
1683+ } ,
1684+ } ,
1685+ 5 ,
1686+ )
1687+
1688+ const OuterB = defineAsyncComponent (
1689+ {
1690+ setup : ( _ , { slots } : any ) => {
1691+ calls . push ( 'outerB created' )
1692+ onMounted ( ( ) => {
1693+ calls . push ( 'outerB mounted' )
1694+ } )
1695+ return ( ) =>
1696+ h ( Fragment , null , [ h ( 'div' , 'outerB' ) , slots . default ?.( ) ] )
1697+ } ,
1698+ } ,
1699+ 5 ,
1700+ )
1701+
1702+ const outerToggle = ref ( false )
1703+ const innerToggle = ref ( false )
1704+
1705+ /**
1706+ * <Suspense>
1707+ * <component :is="outerToggle ? outerB : outerA">
1708+ * <Suspense>
1709+ * <component :is="innerToggle ? innerB : innerA" />
1710+ * </Suspense>
1711+ * </component>
1712+ * </Suspense>
1713+ */
1714+ const Comp = {
1715+ setup ( ) {
1716+ return ( ) =>
1717+ h ( Suspense , null , {
1718+ default : [
1719+ h ( outerToggle . value ? OuterB : OuterA , null , {
1720+ default : ( ) =>
1721+ h ( Suspense , null , {
1722+ default : h ( innerToggle . value ? InnerB : InnerA ) ,
1723+ } ) ,
1724+ } ) ,
1725+ ] ,
1726+ fallback : h ( 'div' , 'fallback outer' ) ,
1727+ } )
1728+ } ,
1729+ }
1730+
1731+ const root = nodeOps . createElement ( 'div' )
1732+ render ( h ( Comp ) , root )
1733+ expect ( serializeInner ( root ) ) . toBe ( `<div>fallback outer</div>` )
1734+
1735+ // mount outer component
1736+ await Promise . all ( deps )
1737+ await nextTick ( )
1738+
1739+ expect ( serializeInner ( root ) ) . toBe ( `<div>outerA</div><!---->` )
1740+ expect ( calls ) . toEqual ( [ `outerA created` , `outerA mounted` ] )
1741+
1742+ // mount inner component
1743+ await Promise . all ( deps )
1744+ await nextTick ( )
1745+ expect ( serializeInner ( root ) ) . toBe ( `<div>outerA</div><div>innerA</div>` )
1746+
1747+ expect ( calls ) . toEqual ( [
1748+ 'outerA created' ,
1749+ 'outerA mounted' ,
1750+ 'innerA created' ,
1751+ 'innerA mounted' ,
1752+ ] )
1753+
1754+ calls . length = 0
1755+ deps . length = 0
1756+
1757+ // toggle both outer and inner components
1758+ outerToggle . value = true
1759+ innerToggle . value = true
1760+ await nextTick ( )
1761+
1762+ await Promise . all ( deps )
1763+ await nextTick ( )
1764+ expect ( serializeInner ( root ) ) . toBe ( `<div>outerB</div><!---->` )
1765+
1766+ await Promise . all ( deps )
1767+ await nextTick ( )
1768+ expect ( serializeInner ( root ) ) . toBe ( `<div>outerB</div><div>innerB</div>` )
1769+
1770+ // innerB only mount once
1771+ expect ( calls ) . toEqual ( [
1772+ 'outerB created' ,
1773+ 'outerB mounted' ,
1774+ 'innerB created' ,
1775+ 'innerB mounted' ,
1776+ ] )
1777+ } )
1778+
16441779 // #6416
16451780 test ( 'KeepAlive with Suspense' , async ( ) => {
16461781 const Async = defineAsyncComponent ( {
0 commit comments