@@ -2198,9 +2198,9 @@ describe('Profiler', () => {
21982198 return text ;
21992199 } catch ( promise ) {
22002200 if ( typeof promise . then === 'function' ) {
2201- yieldForRenderer ( `Suspend! [${ text } ]` ) ;
2201+ yieldForRenderer ( `Suspend [${ text } ]` ) ;
22022202 } else {
2203- yieldForRenderer ( `Error! [${ text } ]` ) ;
2203+ yieldForRenderer ( `Error [${ text } ]` ) ;
22042204 }
22052205 throw promise ;
22062206 }
@@ -2242,7 +2242,7 @@ describe('Profiler', () => {
22422242 expect ( getWorkForReactThreads ( onWorkStopped ) ) . toHaveLength ( 0 ) ;
22432243
22442244 expect ( ReactNoop . flush ( ) ) . toEqual ( [
2245- 'Suspend! [Async]' ,
2245+ 'Suspend [Async]' ,
22462246 'Text [Loading...]' ,
22472247 'Text [Sync]' ,
22482248 ] ) ;
@@ -2422,7 +2422,7 @@ describe('Profiler', () => {
24222422 advanceTimeBy ( 1500 ) ;
24232423 await awaitableAdvanceTimers ( 1500 ) ;
24242424
2425- expect ( renderer ) . toFlushAll ( [ 'Suspend! [loaded]' , 'Text [loading]' ] ) ;
2425+ expect ( renderer ) . toFlushAll ( [ 'Suspend [loaded]' , 'Text [loading]' ] ) ;
24262426 expect ( onInteractionScheduledWorkCompleted ) . not . toHaveBeenCalled ( ) ;
24272427
24282428 advanceTimeBy ( 2500 ) ;
@@ -2473,6 +2473,192 @@ describe('Profiler', () => {
24732473 onInteractionScheduledWorkCompleted ,
24742474 ) . toHaveBeenLastNotifiedOfInteraction ( interaction ) ;
24752475 } ) ;
2476+
2477+ it ( 'handles high-pri renderers between suspended and resolved (sync) trees' , async ( ) => {
2478+ const initialRenderInteraction = {
2479+ id : 0 ,
2480+ name : 'initial render' ,
2481+ timestamp : mockNow ( ) ,
2482+ } ;
2483+
2484+ const onRender = jest . fn ( ) ;
2485+ let renderer ;
2486+ SchedulerTracing . unstable_trace (
2487+ initialRenderInteraction . name ,
2488+ initialRenderInteraction . timestamp ,
2489+ ( ) => {
2490+ renderer = ReactTestRenderer . create (
2491+ < React . unstable_Profiler id = "app" onRender = { onRender } >
2492+ < React . Placeholder
2493+ delayMs = { 2000 }
2494+ fallback = { < Text text = "loading" /> } >
2495+ < AsyncText text = "loaded" ms = { 1000 } />
2496+ </ React . Placeholder >
2497+ < Text text = "initial" />
2498+ </ React . unstable_Profiler > ,
2499+ ) ;
2500+ } ,
2501+ ) ;
2502+ expect ( renderer . toJSON ( ) ) . toEqual ( [ 'loading' , 'initial' ] ) ;
2503+
2504+ expect ( onInteractionScheduledWorkCompleted ) . not . toHaveBeenCalled ( ) ;
2505+ expect ( onRender ) . toHaveBeenCalledTimes ( 2 ) ; // Sync null commit, placeholder commit
2506+ expect ( onRender . mock . calls [ 0 ] [ 6 ] ) . toMatchInteractions ( [
2507+ initialRenderInteraction ,
2508+ ] ) ;
2509+ onRender . mockClear ( ) ;
2510+
2511+ const highPriUpdateInteraction = {
2512+ id : 1 ,
2513+ name : 'hiPriUpdate' ,
2514+ timestamp : mockNow ( ) ,
2515+ } ;
2516+
2517+ const originalPromise = resourcePromise ;
2518+
2519+ renderer . unstable_flushSync ( ( ) => {
2520+ SchedulerTracing . unstable_trace (
2521+ highPriUpdateInteraction . name ,
2522+ highPriUpdateInteraction . timestamp ,
2523+ ( ) => {
2524+ renderer . update (
2525+ < React . unstable_Profiler id = "app" onRender = { onRender } >
2526+ < React . Placeholder
2527+ delayMs = { 2000 }
2528+ fallback = { < Text text = "loading" /> } >
2529+ < AsyncText text = "loaded" ms = { 1000 } />
2530+ </ React . Placeholder >
2531+ < Text text = "updated" />
2532+ </ React . unstable_Profiler > ,
2533+ ) ;
2534+ } ,
2535+ ) ;
2536+ } ) ;
2537+ expect ( renderer . toJSON ( ) ) . toEqual ( [ 'loading' , 'updated' ] ) ;
2538+
2539+ expect ( onRender ) . toHaveBeenCalledTimes ( 2 ) ; // Sync null commit, placeholder commit
2540+ expect ( onRender . mock . calls [ 0 ] [ 6 ] ) . toMatchInteractions ( [
2541+ initialRenderInteraction ,
2542+ highPriUpdateInteraction ,
2543+ ] ) ;
2544+ onRender . mockClear ( ) ;
2545+
2546+ expect ( onInteractionScheduledWorkCompleted ) . not . toHaveBeenCalled ( ) ;
2547+
2548+ advanceTimeBy ( 1000 ) ;
2549+ jest . advanceTimersByTime ( 1000 ) ;
2550+ await originalPromise ;
2551+ expect ( renderer . toJSON ( ) ) . toEqual ( [ 'loaded' , 'updated' ] ) ;
2552+
2553+ expect ( onRender ) . toHaveBeenCalledTimes ( 2 ) ;
2554+ expect ( onRender . mock . calls [ 0 ] [ 6 ] ) . toMatchInteractions ( [
2555+ initialRenderInteraction ,
2556+ highPriUpdateInteraction ,
2557+ ] ) ;
2558+
2559+ expect ( onInteractionScheduledWorkCompleted ) . toHaveBeenCalledTimes ( 2 ) ;
2560+ expect (
2561+ onInteractionScheduledWorkCompleted . mock . calls [ 0 ] [ 0 ] ,
2562+ ) . toMatchInteraction ( initialRenderInteraction ) ;
2563+ expect (
2564+ onInteractionScheduledWorkCompleted . mock . calls [ 1 ] [ 0 ] ,
2565+ ) . toMatchInteraction ( highPriUpdateInteraction ) ;
2566+ } ) ;
2567+
2568+ it ( 'handles high-pri renderers between suspended and resolved (async) trees' , async ( ) => {
2569+ const initialRenderInteraction = {
2570+ id : 0 ,
2571+ name : 'initial render' ,
2572+ timestamp : mockNow ( ) ,
2573+ } ;
2574+
2575+ const onRender = jest . fn ( ) ;
2576+ let renderer ;
2577+ SchedulerTracing . unstable_trace (
2578+ initialRenderInteraction . name ,
2579+ initialRenderInteraction . timestamp ,
2580+ ( ) => {
2581+ renderer = ReactTestRenderer . create (
2582+ < React . unstable_Profiler id = "app" onRender = { onRender } >
2583+ < React . Placeholder
2584+ delayMs = { 2000 }
2585+ fallback = { < Text text = "loading" /> } >
2586+ < AsyncText text = "loaded" ms = { 1000 } />
2587+ </ React . Placeholder >
2588+ < Text text = "initial" />
2589+ </ React . unstable_Profiler > ,
2590+ { unstable_isAsync : true } ,
2591+ ) ;
2592+ } ,
2593+ ) ;
2594+ expect ( renderer ) . toFlushAll ( [
2595+ 'Suspend [loaded]' ,
2596+ 'Text [loading]' ,
2597+ 'Text [initial]' ,
2598+ ] ) ;
2599+
2600+ expect ( onInteractionScheduledWorkCompleted ) . not . toHaveBeenCalled ( ) ;
2601+ expect ( onRender ) . not . toHaveBeenCalled ( ) ;
2602+
2603+ advanceTimeBy ( 500 ) ;
2604+ jest . advanceTimersByTime ( 500 ) ;
2605+
2606+ const highPriUpdateInteraction = {
2607+ id : 1 ,
2608+ name : 'hiPriUpdate' ,
2609+ timestamp : mockNow ( ) ,
2610+ } ;
2611+
2612+ const originalPromise = resourcePromise ;
2613+
2614+ renderer . unstable_flushSync ( ( ) => {
2615+ SchedulerTracing . unstable_trace (
2616+ highPriUpdateInteraction . name ,
2617+ highPriUpdateInteraction . timestamp ,
2618+ ( ) => {
2619+ renderer . update (
2620+ < React . unstable_Profiler id = "app" onRender = { onRender } >
2621+ < React . Placeholder
2622+ delayMs = { 2000 }
2623+ fallback = { < Text text = "loading" /> } >
2624+ < AsyncText text = "loaded" ms = { 1000 } />
2625+ </ React . Placeholder >
2626+ < Text text = "updated" />
2627+ </ React . unstable_Profiler > ,
2628+ ) ;
2629+ } ,
2630+ ) ;
2631+ } ) ;
2632+ expect ( renderer . toJSON ( ) ) . toEqual ( [ 'loading' , 'updated' ] ) ;
2633+
2634+ expect ( onRender ) . toHaveBeenCalledTimes ( 1 ) ;
2635+ expect ( onRender . mock . calls [ 0 ] [ 6 ] ) . toMatchInteractions ( [
2636+ highPriUpdateInteraction ,
2637+ ] ) ;
2638+ onRender . mockClear ( ) ;
2639+
2640+ expect ( onInteractionScheduledWorkCompleted ) . toHaveBeenCalledTimes ( 1 ) ;
2641+ expect (
2642+ onInteractionScheduledWorkCompleted ,
2643+ ) . toHaveBeenLastNotifiedOfInteraction ( highPriUpdateInteraction ) ;
2644+
2645+ advanceTimeBy ( 500 ) ;
2646+ jest . advanceTimersByTime ( 500 ) ;
2647+ await originalPromise ;
2648+ expect ( renderer ) . toFlushAll ( [ 'AsyncText [loaded]' ] ) ;
2649+ expect ( renderer . toJSON ( ) ) . toEqual ( [ 'loaded' , 'updated' ] ) ;
2650+
2651+ expect ( onRender ) . toHaveBeenCalledTimes ( 1 ) ;
2652+ expect ( onRender . mock . calls [ 0 ] [ 6 ] ) . toMatchInteractions ( [
2653+ initialRenderInteraction ,
2654+ highPriUpdateInteraction ,
2655+ ] ) ;
2656+
2657+ expect ( onInteractionScheduledWorkCompleted ) . toHaveBeenCalledTimes ( 2 ) ;
2658+ expect (
2659+ onInteractionScheduledWorkCompleted ,
2660+ ) . toHaveBeenLastNotifiedOfInteraction ( initialRenderInteraction ) ;
2661+ } ) ;
24762662 } ) ;
24772663 } ) ;
24782664} ) ;
0 commit comments