@@ -1641,6 +1641,141 @@ describe('Suspense', () => {
1641
1641
expect ( serializeInner ( root ) ) . toBe ( expected )
1642
1642
} )
1643
1643
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
+
1644
1779
// #6416
1645
1780
test ( 'KeepAlive with Suspense' , async ( ) => {
1646
1781
const Async = defineAsyncComponent ( {
0 commit comments