@@ -2729,6 +2729,91 @@ describe('Profiler', () => {
27292729 onInteractionScheduledWorkCompleted . mock . calls [ 1 ] [ 0 ] ,
27302730 ) . toMatchInteraction ( highPriUpdateInteraction ) ;
27312731 } ) ;
2732+
2733+ it ( 'does not trace Promises flagged with __reactDoNotTraceInteractions' , async ( ) => {
2734+ loadModulesForTracing ( { useNoopRenderer : true } ) ;
2735+
2736+ const interaction = {
2737+ id : 0 ,
2738+ name : 'initial render' ,
2739+ timestamp : Scheduler . unstable_now ( ) ,
2740+ } ;
2741+
2742+ AsyncText = ( { ms, text} ) => {
2743+ try {
2744+ TextResource . read ( [ text , ms ] ) ;
2745+ Scheduler . unstable_yieldValue ( `AsyncText [${ text } ]` ) ;
2746+ return text ;
2747+ } catch ( promise ) {
2748+ promise . __reactDoNotTraceInteractions = true ;
2749+
2750+ if ( typeof promise . then === 'function' ) {
2751+ Scheduler . unstable_yieldValue ( `Suspend [${ text } ]` ) ;
2752+ } else {
2753+ Scheduler . unstable_yieldValue ( `Error [${ text } ]` ) ;
2754+ }
2755+ throw promise ;
2756+ }
2757+ } ;
2758+
2759+ const onRender = jest . fn ( ) ;
2760+ SchedulerTracing . unstable_trace (
2761+ interaction . name ,
2762+ Scheduler . unstable_now ( ) ,
2763+ ( ) => {
2764+ ReactNoop . render (
2765+ < React . Profiler id = "test-profiler" onRender = { onRender } >
2766+ < React . Suspense fallback = { < Text text = "Loading..." /> } >
2767+ < AsyncText text = "Async" ms = { 20000 } />
2768+ </ React . Suspense >
2769+ < Text text = "Sync" />
2770+ </ React . Profiler > ,
2771+ ) ;
2772+ } ,
2773+ ) ;
2774+
2775+ expect ( onInteractionTraced ) . toHaveBeenCalledTimes ( 1 ) ;
2776+ expect ( onInteractionTraced ) . toHaveBeenLastNotifiedOfInteraction (
2777+ interaction ,
2778+ ) ;
2779+ expect ( onInteractionScheduledWorkCompleted ) . not . toHaveBeenCalled ( ) ;
2780+ expect ( getWorkForReactThreads ( onWorkStarted ) ) . toHaveLength ( 0 ) ;
2781+ expect ( getWorkForReactThreads ( onWorkStopped ) ) . toHaveLength ( 0 ) ;
2782+
2783+ expect ( Scheduler ) . toFlushAndYield ( [
2784+ 'Suspend [Async]' ,
2785+ 'Text [Loading...]' ,
2786+ 'Text [Sync]' ,
2787+ ] ) ;
2788+ // Should have committed the placeholder.
2789+ expect ( ReactNoop . getChildrenAsJSX ( ) ) . toEqual ( 'Loading...Sync' ) ;
2790+ expect ( onRender ) . toHaveBeenCalledTimes ( 1 ) ;
2791+
2792+ let call = onRender . mock . calls [ 0 ] ;
2793+ expect ( call [ 0 ] ) . toEqual ( 'test-profiler' ) ;
2794+ expect ( call [ 6 ] ) . toMatchInteractions (
2795+ ReactFeatureFlags . enableSchedulerTracing ? [ interaction ] : [ ] ,
2796+ ) ;
2797+
2798+ // The interaction is now complete.
2799+ expect ( onInteractionTraced ) . toHaveBeenCalledTimes ( 1 ) ;
2800+ expect ( onInteractionScheduledWorkCompleted ) . toHaveBeenCalledTimes ( 1 ) ;
2801+ expect (
2802+ onInteractionScheduledWorkCompleted ,
2803+ ) . toHaveBeenLastNotifiedOfInteraction ( interaction ) ;
2804+
2805+ // Once the promise resolves, we render the suspended view
2806+ await awaitableAdvanceTimers ( 20000 ) ;
2807+ expect ( Scheduler ) . toHaveYielded ( [ 'Promise resolved [Async]' ] ) ;
2808+ expect ( Scheduler ) . toFlushAndYield ( [ 'AsyncText [Async]' ] ) ;
2809+ expect ( ReactNoop . getChildrenAsJSX ( ) ) . toEqual ( 'AsyncSync' ) ;
2810+ expect ( onRender ) . toHaveBeenCalledTimes ( 2 ) ;
2811+
2812+ // No interactions should be associated with this update.
2813+ call = onRender . mock . calls [ 1 ] ;
2814+ expect ( call [ 0 ] ) . toEqual ( 'test-profiler' ) ;
2815+ expect ( call [ 6 ] ) . toMatchInteractions ( [ ] ) ;
2816+ } ) ;
27322817 } ) ;
27332818 } ) ;
27342819} ) ;
0 commit comments