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