@@ -1531,8 +1531,8 @@ describe('ReactInteractionTracing', () => {
15311531 'Loading...' ,
15321532 'Suspend [Sibling Text]' ,
15331533 '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} ])' ,
15361536 ] ) ;
15371537
15381538 root . render ( < App navigate = { true } showMarker = { true } /> ) ;
@@ -1679,8 +1679,8 @@ describe('ReactInteractionTracing', () => {
16791679 expect ( Scheduler ) . toFlushAndYield ( [
16801680 'Suspend [Page Two]' ,
16811681 '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} ])' ,
16841684 ] ) ;
16851685
16861686 await resolveText ( 'Page Two' ) ;
@@ -1698,6 +1698,273 @@ describe('ReactInteractionTracing', () => {
16981698 } ) ;
16991699 } ) ;
17001700
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+
17011968 // @gate enableTransitionTracing
17021969 it ( 'warns when marker name changes' , async ( ) => {
17031970 const transitionCallbacks = {
0 commit comments