@@ -1531,8 +1531,8 @@ describe('ReactInteractionTracing', () => {
1531
1531
'Loading...' ,
1532
1532
'Suspend [Sibling Text]' ,
1533
1533
'Sibling Loading...' ,
1534
- 'onMarkerIncomplete(transition one, marker one, 1000, [{endTime: 3000, name: marker one, type: marker}])' ,
1535
- 'onMarkerIncomplete(transition one, parent, 1000, [{endTime: 3000, name: marker one, type: marker}])' ,
1534
+ 'onMarkerIncomplete(transition one, marker one, 1000, [{endTime: 3000, name: marker one, type: marker}, {endTime: 3000, name: suspense page, type: suspense} ])' ,
1535
+ 'onMarkerIncomplete(transition one, parent, 1000, [{endTime: 3000, name: marker one, type: marker}, {endTime: 3000, name: suspense page, type: suspense} ])' ,
1536
1536
] ) ;
1537
1537
1538
1538
root . render ( < App navigate = { true } showMarker = { true } /> ) ;
@@ -1679,8 +1679,8 @@ describe('ReactInteractionTracing', () => {
1679
1679
expect ( Scheduler ) . toFlushAndYield ( [
1680
1680
'Suspend [Page Two]' ,
1681
1681
'Loading Two...' ,
1682
- 'onMarkerIncomplete(transition, one, 1000, [{endTime: 3000, name: one, type: marker}])' ,
1683
- 'onMarkerIncomplete(transition, parent, 1000, [{endTime: 3000, name: one, type: marker}])' ,
1682
+ 'onMarkerIncomplete(transition, one, 1000, [{endTime: 3000, name: one, type: marker}, {endTime: 3000, name: suspense one, type: suspense} ])' ,
1683
+ 'onMarkerIncomplete(transition, parent, 1000, [{endTime: 3000, name: one, type: marker}, {endTime: 3000, name: suspense one, type: suspense} ])' ,
1684
1684
] ) ;
1685
1685
1686
1686
await resolveText ( 'Page Two' ) ;
@@ -1698,6 +1698,273 @@ describe('ReactInteractionTracing', () => {
1698
1698
} ) ;
1699
1699
} ) ;
1700
1700
1701
+ it ( 'Suspense boundary added by the transition is deleted' , async ( ) => {
1702
+ const transitionCallbacks = {
1703
+ onTransitionStart : ( name , startTime ) => {
1704
+ Scheduler . unstable_yieldValue (
1705
+ `onTransitionStart(${ name } , ${ startTime } )` ,
1706
+ ) ;
1707
+ } ,
1708
+ onTransitionProgress : ( name , startTime , endTime , pending ) => {
1709
+ const suspenseNames = pending . map ( p => p . name || '<null>' ) . join ( ', ' ) ;
1710
+ Scheduler . unstable_yieldValue (
1711
+ `onTransitionProgress(${ name } , ${ startTime } , ${ endTime } , [${ suspenseNames } ])` ,
1712
+ ) ;
1713
+ } ,
1714
+ onTransitionComplete : ( name , startTime , endTime ) => {
1715
+ Scheduler . unstable_yieldValue (
1716
+ `onTransitionComplete(${ name } , ${ startTime } , ${ endTime } )` ,
1717
+ ) ;
1718
+ } ,
1719
+ onMarkerProgress : (
1720
+ transitioName ,
1721
+ markerName ,
1722
+ startTime ,
1723
+ currentTime ,
1724
+ pending ,
1725
+ ) => {
1726
+ const suspenseNames = pending . map ( p => p . name || '<null>' ) . join ( ', ' ) ;
1727
+ Scheduler . unstable_yieldValue (
1728
+ `onMarkerProgress(${ transitioName } , ${ markerName } , ${ startTime } , ${ currentTime } , [${ suspenseNames } ])` ,
1729
+ ) ;
1730
+ } ,
1731
+ onMarkerIncomplete : (
1732
+ transitionName ,
1733
+ markerName ,
1734
+ startTime ,
1735
+ deletions ,
1736
+ ) => {
1737
+ Scheduler . unstable_yieldValue (
1738
+ `onMarkerIncomplete(${ transitionName } , ${ markerName } , ${ startTime } , [${ stringifyDeletions (
1739
+ deletions ,
1740
+ ) } ])`,
1741
+ ) ;
1742
+ } ,
1743
+ onMarkerComplete : ( transitioName , markerName , startTime , endTime ) => {
1744
+ Scheduler . unstable_yieldValue (
1745
+ `onMarkerComplete(${ transitioName } , ${ markerName } , ${ startTime } , ${ endTime } )` ,
1746
+ ) ;
1747
+ } ,
1748
+ } ;
1749
+
1750
+ function App ( { navigate, deleteOne} ) {
1751
+ return (
1752
+ < div >
1753
+ { navigate ? (
1754
+ < React . unstable_TracingMarker name = "parent" >
1755
+ < React . unstable_TracingMarker name = "one" >
1756
+ { ! deleteOne ? (
1757
+ < Suspense
1758
+ unstable_name = "suspense one"
1759
+ fallback = { < Text text = "Loading One..." /> } >
1760
+ < AsyncText text = "Page One" />
1761
+ < React . unstable_TracingMarker name = "page one" />
1762
+ < Suspense
1763
+ unstable_name = "suspense child"
1764
+ fallback = { < Text text = "Loading Child..." /> } >
1765
+ < React . unstable_TracingMarker name = "child" />
1766
+ < AsyncText text = "Child" />
1767
+ </ Suspense >
1768
+ </ Suspense >
1769
+ ) : null }
1770
+ </ React . unstable_TracingMarker >
1771
+ < React . unstable_TracingMarker name = "two" >
1772
+ < Suspense
1773
+ unstable_name = "suspense two"
1774
+ fallback = { < Text text = "Loading Two..." /> } >
1775
+ < AsyncText text = "Page Two" />
1776
+ </ Suspense >
1777
+ </ React . unstable_TracingMarker >
1778
+ </ React . unstable_TracingMarker >
1779
+ ) : (
1780
+ < Text text = "Page One" />
1781
+ ) }
1782
+ </ div >
1783
+ ) ;
1784
+ }
1785
+ const root = ReactNoop . createRoot ( {
1786
+ unstable_transitionCallbacks : transitionCallbacks ,
1787
+ } ) ;
1788
+ await act ( async ( ) => {
1789
+ root . render ( < App navigate = { false } deleteOne = { false } /> ) ;
1790
+
1791
+ ReactNoop . expire ( 1000 ) ;
1792
+ await advanceTimers ( 1000 ) ;
1793
+ expect ( Scheduler ) . toFlushAndYield ( [ 'Page One' ] ) ;
1794
+
1795
+ startTransition (
1796
+ ( ) => root . render ( < App navigate = { true } deleteOne = { false } /> ) ,
1797
+ {
1798
+ name : 'transition' ,
1799
+ } ,
1800
+ ) ;
1801
+ ReactNoop . expire ( 1000 ) ;
1802
+ await advanceTimers ( 1000 ) ;
1803
+ expect ( Scheduler ) . toFlushAndYield ( [
1804
+ 'Suspend [Page One]' ,
1805
+ 'Suspend [Child]' ,
1806
+ 'Loading Child...' ,
1807
+ 'Loading One...' ,
1808
+ 'Suspend [Page Two]' ,
1809
+ 'Loading Two...' ,
1810
+ 'onTransitionStart(transition, 1000)' ,
1811
+ 'onMarkerProgress(transition, parent, 1000, 2000, [suspense one, suspense two])' ,
1812
+ 'onMarkerProgress(transition, one, 1000, 2000, [suspense one])' ,
1813
+ 'onMarkerProgress(transition, two, 1000, 2000, [suspense two])' ,
1814
+ 'onTransitionProgress(transition, 1000, 2000, [suspense one, suspense two])' ,
1815
+ ] ) ;
1816
+
1817
+ await resolveText ( 'Page One' ) ;
1818
+ ReactNoop . expire ( 1000 ) ;
1819
+ await advanceTimers ( 1000 ) ;
1820
+ expect ( Scheduler ) . toFlushAndYield ( [
1821
+ 'Page One' ,
1822
+ 'Suspend [Child]' ,
1823
+ 'Loading Child...' ,
1824
+ 'onMarkerProgress(transition, parent, 1000, 3000, [suspense two, suspense child])' ,
1825
+ 'onMarkerProgress(transition, one, 1000, 3000, [suspense child])' ,
1826
+ 'onMarkerComplete(transition, page one, 1000, 3000)' ,
1827
+ 'onTransitionProgress(transition, 1000, 3000, [suspense two, suspense child])' ,
1828
+ ] ) ;
1829
+
1830
+ root . render ( < App navigate = { true } deleteOne = { true } /> ) ;
1831
+ ReactNoop . expire ( 1000 ) ;
1832
+ await advanceTimers ( 1000 ) ;
1833
+ expect ( Scheduler ) . toFlushAndYield ( [
1834
+ 'Suspend [Page Two]' ,
1835
+ 'Loading Two...' ,
1836
+ // "suspense one" has unsuspended so shouldn't be included
1837
+ // tracing marker "page one" has completed so shouldn't be included
1838
+ // all children of "suspense child" haven't yet been rendered so shouldn't be included
1839
+ 'onMarkerIncomplete(transition, parent, 1000, [{endTime: 4000, name: suspense child, type: suspense}])' ,
1840
+ 'onMarkerIncomplete(transition, one, 1000, [{endTime: 4000, name: suspense child, type: suspense}])' ,
1841
+ ] ) ;
1842
+
1843
+ await resolveText ( 'Page Two' ) ;
1844
+ ReactNoop . expire ( 1000 ) ;
1845
+ await advanceTimers ( 1000 ) ;
1846
+ expect ( Scheduler ) . toFlushAndYield ( [
1847
+ 'Page Two' ,
1848
+ 'onMarkerProgress(transition, parent, 1000, 5000, [])' ,
1849
+ 'onMarkerProgress(transition, two, 1000, 5000, [])' ,
1850
+ 'onMarkerComplete(transition, two, 1000, 5000)' ,
1851
+ 'onTransitionProgress(transition, 1000, 5000, [])' ,
1852
+ ] ) ;
1853
+ } ) ;
1854
+ } ) ;
1855
+
1856
+ it ( 'Suspense boundary not added by the transition is deleted ' , async ( ) => {
1857
+ const transitionCallbacks = {
1858
+ onTransitionStart : ( name , startTime ) => {
1859
+ Scheduler . unstable_yieldValue (
1860
+ `onTransitionStart(${ name } , ${ startTime } )` ,
1861
+ ) ;
1862
+ } ,
1863
+ onTransitionProgress : ( name , startTime , endTime , pending ) => {
1864
+ const suspenseNames = pending . map ( p => p . name || '<null>' ) . join ( ', ' ) ;
1865
+ Scheduler . unstable_yieldValue (
1866
+ `onTransitionProgress(${ name } , ${ startTime } , ${ endTime } , [${ suspenseNames } ])` ,
1867
+ ) ;
1868
+ } ,
1869
+ onTransitionComplete : ( name , startTime , endTime ) => {
1870
+ Scheduler . unstable_yieldValue (
1871
+ `onTransitionComplete(${ name } , ${ startTime } , ${ endTime } )` ,
1872
+ ) ;
1873
+ } ,
1874
+ onMarkerProgress : (
1875
+ transitioName ,
1876
+ markerName ,
1877
+ startTime ,
1878
+ currentTime ,
1879
+ pending ,
1880
+ ) => {
1881
+ const suspenseNames = pending . map ( p => p . name || '<null>' ) . join ( ', ' ) ;
1882
+ Scheduler . unstable_yieldValue (
1883
+ `onMarkerProgress(${ transitioName } , ${ markerName } , ${ startTime } , ${ currentTime } , [${ suspenseNames } ])` ,
1884
+ ) ;
1885
+ } ,
1886
+ onMarkerIncomplete : (
1887
+ transitionName ,
1888
+ markerName ,
1889
+ startTime ,
1890
+ deletions ,
1891
+ ) => {
1892
+ Scheduler . unstable_yieldValue (
1893
+ `onMarkerIncomplete(${ transitionName } , ${ markerName } , ${ startTime } , [${ stringifyDeletions (
1894
+ deletions ,
1895
+ ) } ])`,
1896
+ ) ;
1897
+ } ,
1898
+ onMarkerComplete : ( transitioName , markerName , startTime , endTime ) => {
1899
+ Scheduler . unstable_yieldValue (
1900
+ `onMarkerComplete(${ transitioName } , ${ markerName } , ${ startTime } , ${ endTime } )` ,
1901
+ ) ;
1902
+ } ,
1903
+ } ;
1904
+
1905
+ function App ( { show} ) {
1906
+ return (
1907
+ < React . unstable_TracingMarker name = "parent" >
1908
+ { show ? (
1909
+ < Suspense unstable_name = "appended child" >
1910
+ < AsyncText text = "Appended child" />
1911
+ </ Suspense >
1912
+ ) : null }
1913
+ < Suspense unstable_name = "child" >
1914
+ < AsyncText text = "Child" />
1915
+ </ Suspense >
1916
+ </ React . unstable_TracingMarker >
1917
+ ) ;
1918
+ }
1919
+
1920
+ const root = ReactNoop . createRoot ( {
1921
+ unstable_transitionCallbacks : transitionCallbacks ,
1922
+ } ) ;
1923
+ await act ( async ( ) => {
1924
+ startTransition ( ( ) => root . render ( < App show = { false } /> ) , {
1925
+ name : 'transition' ,
1926
+ } ) ;
1927
+ ReactNoop . expire ( 1000 ) ;
1928
+ await advanceTimers ( 1000 ) ;
1929
+
1930
+ expect ( Scheduler ) . toFlushAndYield ( [
1931
+ 'Suspend [Child]' ,
1932
+ 'onTransitionStart(transition, 0)' ,
1933
+ 'onMarkerProgress(transition, parent, 0, 1000, [child])' ,
1934
+ 'onTransitionProgress(transition, 0, 1000, [child])' ,
1935
+ ] ) ;
1936
+
1937
+ root . render ( < App show = { true } /> ) ;
1938
+ ReactNoop . expire ( 1000 ) ;
1939
+ await advanceTimers ( 1000 ) ;
1940
+ // This appended child isn't part of the transition so we
1941
+ // don't call any callback
1942
+ expect ( Scheduler ) . toFlushAndYield ( [
1943
+ 'Suspend [Appended child]' ,
1944
+ 'Suspend [Child]' ,
1945
+ ] ) ;
1946
+
1947
+ // This deleted child isn't part of the transition so we
1948
+ // don't call any callbacks
1949
+ root . render ( < App show = { false } /> ) ;
1950
+ ReactNoop . expire ( 1000 ) ;
1951
+ await advanceTimers ( 1000 ) ;
1952
+ expect ( Scheduler ) . toFlushAndYield ( [ 'Suspend [Child]' ] ) ;
1953
+
1954
+ await resolveText ( 'Child' ) ;
1955
+ ReactNoop . expire ( 1000 ) ;
1956
+ await advanceTimers ( 1000 ) ;
1957
+
1958
+ expect ( Scheduler ) . toFlushAndYield ( [
1959
+ 'Child' ,
1960
+ 'onMarkerProgress(transition, parent, 0, 4000, [])' ,
1961
+ 'onMarkerComplete(transition, parent, 0, 4000)' ,
1962
+ 'onTransitionProgress(transition, 0, 4000, [])' ,
1963
+ 'onTransitionComplete(transition, 0, 4000)' ,
1964
+ ] ) ;
1965
+ } ) ;
1966
+ } ) ;
1967
+
1701
1968
// @gate enableTransitionTracing
1702
1969
it ( 'warns when marker name changes' , async ( ) => {
1703
1970
const transitionCallbacks = {
0 commit comments