From 97625272abe1fecc8ffba469795803ca8cfff9a7 Mon Sep 17 00:00:00 2001 From: Brian Vaughn <bvaughn@fb.com> Date: Thu, 1 Oct 2020 12:02:26 -0400 Subject: [PATCH] Debug tracing tests for CPU bound suspense (#19943) --- .../__tests__/DebugTracing-test.internal.js | 132 ++++++++++++++++-- .../forks/ReactFeatureFlags.www-dynamic.js | 2 +- 2 files changed, 121 insertions(+), 13 deletions(-) diff --git a/packages/react-reconciler/src/__tests__/DebugTracing-test.internal.js b/packages/react-reconciler/src/__tests__/DebugTracing-test.internal.js index 14960c36811c0..2df04c8c88544 100644 --- a/packages/react-reconciler/src/__tests__/DebugTracing-test.internal.js +++ b/packages/react-reconciler/src/__tests__/DebugTracing-test.internal.js @@ -96,6 +96,45 @@ describe('DebugTracing', () => { expect(logs).toEqual(['log: ⚛️ Example resolved']); }); + // @gate experimental && build === 'development' && enableDebugTracing + it('should log sync render with CPU suspense', () => { + function Example() { + console.log('<Example/>'); + return null; + } + + function Wrapper({children}) { + console.log('<Wrapper/>'); + return children; + } + + ReactTestRenderer.create( + <React.unstable_DebugTracingMode> + <Wrapper> + <React.Suspense fallback={null} unstable_expectedLoadTime={1}> + <Example /> + </React.Suspense> + </Wrapper> + </React.unstable_DebugTracingMode>, + ); + + expect(logs).toEqual([ + 'group: ⚛️ render (0b0000000000000000000000000000001)', + 'log: <Wrapper/>', + 'groupEnd: ⚛️ render (0b0000000000000000000000000000001)', + ]); + + logs.splice(0); + + expect(Scheduler).toFlushUntilNextPaint([]); + + expect(logs).toEqual([ + 'group: ⚛️ render (0b0000010000000000000000000000000)', + 'log: <Example/>', + 'groupEnd: ⚛️ render (0b0000010000000000000000000000000)', + ]); + }); + // @gate experimental && build === 'development' && enableDebugTracing it('should log concurrent render with suspense', async () => { const fakeSuspensePromise = Promise.resolve(true); @@ -130,6 +169,52 @@ describe('DebugTracing', () => { expect(logs).toEqual(['log: ⚛️ Example resolved']); }); + // @gate experimental && build === 'development' && enableDebugTracing + it('should log concurrent render with CPU suspense', () => { + function Example() { + console.log('<Example/>'); + return null; + } + + function Wrapper({children}) { + console.log('<Wrapper/>'); + return children; + } + + ReactTestRenderer.create( + <React.unstable_DebugTracingMode> + <Wrapper> + <React.Suspense fallback={null} unstable_expectedLoadTime={1}> + <Example /> + </React.Suspense> + </Wrapper> + </React.unstable_DebugTracingMode>, + {unstable_isConcurrent: true}, + ); + + expect(logs).toEqual([]); + + logs.splice(0); + + expect(Scheduler).toFlushUntilNextPaint([]); + + expect(logs).toEqual([ + 'group: ⚛️ render (0b0000000000000000000001000000000)', + 'log: <Wrapper/>', + 'groupEnd: ⚛️ render (0b0000000000000000000001000000000)', + ]); + + logs.splice(0); + + expect(Scheduler).toFlushUntilNextPaint([]); + + expect(logs).toEqual([ + 'group: ⚛️ render (0b0000010000000000000000000000000)', + 'log: <Example/>', + 'groupEnd: ⚛️ render (0b0000010000000000000000000000000)', + ]); + }); + // @gate experimental && build === 'development' && enableDebugTracing it('should log cascading class component updates', () => { class Example extends React.Component { @@ -191,12 +276,23 @@ describe('DebugTracing', () => { expect(Scheduler).toFlushUntilNextPaint([]); }).toErrorDev('Cannot update during an existing state transition'); - expect(logs).toEqual([ - 'group: ⚛️ render (0b0000000000000000000001000000000)', - 'log: ⚛️ Example updated state (0b0000000000000000000010000000000)', - 'log: ⚛️ Example updated state (0b0000000000000000000010000000000)', - 'groupEnd: ⚛️ render (0b0000000000000000000001000000000)', - ]); + gate(flags => { + if (flags.new) { + expect(logs).toEqual([ + 'group: ⚛️ render (0b0000000000000000000001000000000)', + 'log: ⚛️ Example updated state (0b0000000000000000000001000000000)', + 'log: ⚛️ Example updated state (0b0000000000000000000001000000000)', + 'groupEnd: ⚛️ render (0b0000000000000000000001000000000)', + ]); + } else { + expect(logs).toEqual([ + 'group: ⚛️ render (0b0000000000000000000001000000000)', + 'log: ⚛️ Example updated state (0b0000000000000000000010000000000)', + 'log: ⚛️ Example updated state (0b0000000000000000000010000000000)', + 'groupEnd: ⚛️ render (0b0000000000000000000001000000000)', + ]); + } + }); }); // @gate experimental && build === 'development' && enableDebugTracing @@ -274,12 +370,24 @@ describe('DebugTracing', () => { {unstable_isConcurrent: true}, ); }); - expect(logs).toEqual([ - 'group: ⚛️ render (0b0000000000000000000001000000000)', - 'log: ⚛️ Example updated state (0b0000000000000000000010000000000)', - 'log: ⚛️ Example updated state (0b0000000000000000000010000000000)', // debugRenderPhaseSideEffectsForStrictMode - 'groupEnd: ⚛️ render (0b0000000000000000000001000000000)', - ]); + + gate(flags => { + if (flags.new) { + expect(logs).toEqual([ + 'group: ⚛️ render (0b0000000000000000000001000000000)', + 'log: ⚛️ Example updated state (0b0000000000000000000001000000000)', + 'log: ⚛️ Example updated state (0b0000000000000000000001000000000)', // debugRenderPhaseSideEffectsForStrictMode + 'groupEnd: ⚛️ render (0b0000000000000000000001000000000)', + ]); + } else { + expect(logs).toEqual([ + 'group: ⚛️ render (0b0000000000000000000001000000000)', + 'log: ⚛️ Example updated state (0b0000000000000000000010000000000)', + 'log: ⚛️ Example updated state (0b0000000000000000000010000000000)', // debugRenderPhaseSideEffectsForStrictMode + 'groupEnd: ⚛️ render (0b0000000000000000000001000000000)', + ]); + } + }); }); // @gate experimental && build === 'development' && enableDebugTracing diff --git a/packages/shared/forks/ReactFeatureFlags.www-dynamic.js b/packages/shared/forks/ReactFeatureFlags.www-dynamic.js index aa3cf1a64a848..881a0e61010da 100644 --- a/packages/shared/forks/ReactFeatureFlags.www-dynamic.js +++ b/packages/shared/forks/ReactFeatureFlags.www-dynamic.js @@ -25,7 +25,7 @@ export const enableEagerRootListeners = !__VARIANT__; // It logs information to the console about React scheduling, rendering, and commit phases. // // NOTE: This feature will only work in DEV mode; all callsights are wrapped with __DEV__. -export const enableDebugTracing = false; +export const enableDebugTracing = __EXPERIMENTAL__; // This only has an effect in the new reconciler. But also, the new reconciler // is only enabled when __VARIANT__ is true. So this is set to the opposite of