@@ -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,210 @@ describe('Profiler', () => {
24732473 onInteractionScheduledWorkCompleted ,
24742474 ) . toHaveBeenLastNotifiedOfInteraction ( interaction ) ;
24752475 } ) ;
2476+
2477+ it ( 'handles high-pri renderers between suspended and resolved (sync) trees' , async ( ) => {
2478+ let instance ;
2479+ class ClassComponent extends React . Component {
2480+ render ( ) {
2481+ instance = this ;
2482+ yieldForRenderer ( `ClassComponent [${ this . props . value } ]` ) ;
2483+ return this . props . value ;
2484+ }
2485+ }
2486+
2487+ const initialRenderInteraction = {
2488+ id : 0 ,
2489+ name : 'initial render' ,
2490+ timestamp : mockNow ( ) ,
2491+ } ;
2492+
2493+ const onRender = jest . fn ( ) ;
2494+ let renderer ;
2495+ SchedulerTracing . unstable_trace (
2496+ initialRenderInteraction . name ,
2497+ initialRenderInteraction . timestamp ,
2498+ ( ) => {
2499+ renderer = ReactTestRenderer . create (
2500+ < React . unstable_Profiler id = "app" onRender = { onRender } >
2501+ < React . Placeholder
2502+ delayMs = { 2000 }
2503+ fallback = { < Text text = "loading" /> } >
2504+ < AsyncText text = "loaded" ms = { 1000 } />
2505+ </ React . Placeholder >
2506+ < ClassComponent value = "initial" />
2507+ </ React . unstable_Profiler > ,
2508+ ) ;
2509+ } ,
2510+ ) ;
2511+ expect ( renderer . toJSON ( ) ) . toEqual ( [ 'loading' , 'initial' ] ) ;
2512+
2513+ expect ( onInteractionScheduledWorkCompleted ) . not . toHaveBeenCalled ( ) ;
2514+ expect ( onRender ) . toHaveBeenCalledTimes ( 2 ) ; // Sync null commit, placeholder commit
2515+ expect ( onRender . mock . calls [ 0 ] [ 6 ] ) . toMatchInteractions ( [
2516+ initialRenderInteraction ,
2517+ ] ) ;
2518+ onRender . mockClear ( ) ;
2519+
2520+ const highPriUpdateInteraction = {
2521+ id : 1 ,
2522+ name : 'hiPriUpdate' ,
2523+ timestamp : mockNow ( ) ,
2524+ } ;
2525+
2526+ const originalPromise = resourcePromise ;
2527+
2528+ renderer . unstable_flushSync ( ( ) => {
2529+ SchedulerTracing . unstable_trace (
2530+ highPriUpdateInteraction . name ,
2531+ highPriUpdateInteraction . timestamp ,
2532+ ( ) => {
2533+ renderer . update (
2534+ < React . unstable_Profiler id = "app" onRender = { onRender } >
2535+ < React . Placeholder
2536+ delayMs = { 2000 }
2537+ fallback = { < Text text = "loading" /> } >
2538+ < AsyncText text = "loaded" ms = { 1000 } />
2539+ </ React . Placeholder >
2540+ < ClassComponent value = "updated" />
2541+ </ React . unstable_Profiler > ,
2542+ ) ;
2543+ } ,
2544+ ) ;
2545+ } ) ;
2546+ expect ( renderer . toJSON ( ) ) . toEqual ( [ 'loading' , 'updated' ] ) ;
2547+
2548+ expect ( onRender ) . toHaveBeenCalledTimes ( 2 ) ; // Sync null commit, placeholder commit
2549+ expect ( onRender . mock . calls [ 0 ] [ 6 ] ) . toMatchInteractions ( [
2550+ initialRenderInteraction ,
2551+ highPriUpdateInteraction ,
2552+ ] ) ;
2553+ onRender . mockClear ( ) ;
2554+
2555+ expect ( onInteractionScheduledWorkCompleted ) . not . toHaveBeenCalled ( ) ;
2556+
2557+ advanceTimeBy ( 1000 ) ;
2558+ jest . advanceTimersByTime ( 1000 ) ;
2559+ await originalPromise ;
2560+ expect ( renderer . toJSON ( ) ) . toEqual ( [ 'loaded' , 'updated' ] ) ;
2561+
2562+ expect ( onRender ) . toHaveBeenCalledTimes ( 2 ) ;
2563+ expect ( onRender . mock . calls [ 0 ] [ 6 ] ) . toMatchInteractions ( [
2564+ initialRenderInteraction ,
2565+ highPriUpdateInteraction ,
2566+ ] ) ;
2567+
2568+ expect ( onInteractionScheduledWorkCompleted ) . toHaveBeenCalledTimes ( 2 ) ;
2569+ expect (
2570+ onInteractionScheduledWorkCompleted . mock . calls [ 0 ] [ 0 ] ,
2571+ ) . toMatchInteraction ( initialRenderInteraction ) ;
2572+ expect (
2573+ onInteractionScheduledWorkCompleted . mock . calls [ 1 ] [ 0 ] ,
2574+ ) . toMatchInteraction ( highPriUpdateInteraction ) ;
2575+ } ) ;
2576+
2577+ it ( 'handles high-pri renderers between suspended and resolved (async) trees' , async ( ) => {
2578+ let instance ;
2579+ class ClassComponent extends React . Component {
2580+ render ( ) {
2581+ instance = this ;
2582+ yieldForRenderer ( `ClassComponent [${ this . props . value } ]` ) ;
2583+ return this . props . value ;
2584+ }
2585+ }
2586+
2587+ const initialRenderInteraction = {
2588+ id : 0 ,
2589+ name : 'initial render' ,
2590+ timestamp : mockNow ( ) ,
2591+ } ;
2592+
2593+ const onRender = jest . fn ( ) ;
2594+ let renderer ;
2595+ SchedulerTracing . unstable_trace (
2596+ initialRenderInteraction . name ,
2597+ initialRenderInteraction . timestamp ,
2598+ ( ) => {
2599+ renderer = ReactTestRenderer . create (
2600+ < React . unstable_Profiler id = "app" onRender = { onRender } >
2601+ < React . Placeholder
2602+ delayMs = { 2000 }
2603+ fallback = { < Text text = "loading" /> } >
2604+ < AsyncText text = "loaded" ms = { 1000 } />
2605+ </ React . Placeholder >
2606+ < ClassComponent value = "initial" />
2607+ </ React . unstable_Profiler > ,
2608+ { unstable_isAsync : true } ,
2609+ ) ;
2610+ } ,
2611+ ) ;
2612+ expect ( renderer ) . toFlushAll ( [
2613+ 'Suspend [loaded]' ,
2614+ 'Text [loading]' ,
2615+ 'ClassComponent [initial]' ,
2616+ ] ) ;
2617+
2618+ expect ( onInteractionScheduledWorkCompleted ) . not . toHaveBeenCalled ( ) ;
2619+ expect ( onRender ) . not . toHaveBeenCalled ( ) ;
2620+
2621+ advanceTimeBy ( 500 ) ;
2622+ jest . advanceTimersByTime ( 500 ) ;
2623+
2624+ const highPriUpdateInteraction = {
2625+ id : 1 ,
2626+ name : 'hiPriUpdate' ,
2627+ timestamp : mockNow ( ) ,
2628+ } ;
2629+
2630+ const originalPromise = resourcePromise ;
2631+
2632+ renderer . unstable_flushSync ( ( ) => {
2633+ SchedulerTracing . unstable_trace (
2634+ highPriUpdateInteraction . name ,
2635+ highPriUpdateInteraction . timestamp ,
2636+ ( ) => {
2637+ renderer . update (
2638+ < React . unstable_Profiler id = "app" onRender = { onRender } >
2639+ < React . Placeholder
2640+ delayMs = { 2000 }
2641+ fallback = { < Text text = "loading" /> } >
2642+ < AsyncText text = "loaded" ms = { 1000 } />
2643+ </ React . Placeholder >
2644+ < ClassComponent value = "updated" />
2645+ </ React . unstable_Profiler > ,
2646+ ) ;
2647+ } ,
2648+ ) ;
2649+ } ) ;
2650+ expect ( renderer . toJSON ( ) ) . toEqual ( [ 'loading' , 'updated' ] ) ;
2651+
2652+ expect ( onRender ) . toHaveBeenCalledTimes ( 1 ) ;
2653+ expect ( onRender . mock . calls [ 0 ] [ 6 ] ) . toMatchInteractions ( [
2654+ highPriUpdateInteraction ,
2655+ ] ) ;
2656+ onRender . mockClear ( ) ;
2657+
2658+ expect ( onInteractionScheduledWorkCompleted ) . toHaveBeenCalledTimes ( 1 ) ;
2659+ expect (
2660+ onInteractionScheduledWorkCompleted ,
2661+ ) . toHaveBeenLastNotifiedOfInteraction ( highPriUpdateInteraction ) ;
2662+
2663+ advanceTimeBy ( 500 ) ;
2664+ jest . advanceTimersByTime ( 500 ) ;
2665+ await originalPromise ;
2666+ expect ( renderer ) . toFlushAll ( [ 'AsyncText [loaded]' ] ) ;
2667+ expect ( renderer . toJSON ( ) ) . toEqual ( [ 'loaded' , 'updated' ] ) ;
2668+
2669+ expect ( onRender ) . toHaveBeenCalledTimes ( 1 ) ;
2670+ expect ( onRender . mock . calls [ 0 ] [ 6 ] ) . toMatchInteractions ( [
2671+ initialRenderInteraction ,
2672+ highPriUpdateInteraction ,
2673+ ] ) ;
2674+
2675+ expect ( onInteractionScheduledWorkCompleted ) . toHaveBeenCalledTimes ( 2 ) ;
2676+ expect (
2677+ onInteractionScheduledWorkCompleted ,
2678+ ) . toHaveBeenLastNotifiedOfInteraction ( initialRenderInteraction ) ;
2679+ } ) ;
24762680 } ) ;
24772681 } ) ;
24782682} ) ;
0 commit comments