From 0d67cc065157b2b98843cd1e2578b0969765c54b Mon Sep 17 00:00:00 2001 From: Brooke Date: Sat, 14 Dec 2024 17:32:58 +0000 Subject: [PATCH 1/6] Fix `commong` typo in multiple children error message (#31777) --- packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js | 2 +- packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js b/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js index fe2e713d8a3ba..9883ba4454df4 100644 --- a/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js +++ b/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js @@ -3080,7 +3080,7 @@ function pushTitle( console.error( 'React expects the `children` prop of <title> tags to be a string, number, bigint, or object with a novel `toString` method but found an Array with length %s instead.' + ' Browsers treat all child Nodes of <title> tags as Text content and React expects to be able to convert `children` of <title> tags to a single string value' + - ' which is why Arrays of length greater than 1 are not supported. When using JSX it can be commong to combine text nodes and value nodes.' + + ' which is why Arrays of length greater than 1 are not supported. When using JSX it can be common to combine text nodes and value nodes.' + ' For example: <title>hello {nameOfUser}. While not immediately apparent, `children` in this case is an Array with length 2. If your `children` prop' + ' is using this form try rewriting it using a template string: {`hello ${nameOfUser}`}.', children.length, diff --git a/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js b/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js index 9c91be1225015..9dcd4c6945884 100644 --- a/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js @@ -5928,7 +5928,7 @@ describe('ReactDOMFizzServer', () => { pipe(writable); }); }).toErrorDev([ - 'React expects the `children` prop of tags to be a string, number, bigint, or object with a novel `toString` method but found an Array with length 2 instead. Browsers treat all child Nodes of <title> tags as Text content and React expects to be able to convert `children` of <title> tags to a single string value which is why Arrays of length greater than 1 are not supported. When using JSX it can be commong to combine text nodes and value nodes. For example: <title>hello {nameOfUser}. While not immediately apparent, `children` in this case is an Array with length 2. If your `children` prop is using this form try rewriting it using a template string: {`hello ${nameOfUser}`}.', + 'React expects the `children` prop of tags to be a string, number, bigint, or object with a novel `toString` method but found an Array with length 2 instead. Browsers treat all child Nodes of <title> tags as Text content and React expects to be able to convert `children` of <title> tags to a single string value which is why Arrays of length greater than 1 are not supported. When using JSX it can be common to combine text nodes and value nodes. For example: <title>hello {nameOfUser}. While not immediately apparent, `children` in this case is an Array with length 2. If your `children` prop is using this form try rewriting it using a template string: {`hello ${nameOfUser}`}.', ]); expect(getVisibleChildren(document.head)).toEqual(); From 9e2c233139e62ea2f50bfa8986de02044e895c65 Mon Sep 17 00:00:00 2001 From: Ricky <rickhanlonii@gmail.com> Date: Sat, 14 Dec 2024 13:05:17 -0500 Subject: [PATCH 2/6] [flags] Delete enableSuspenseAvoidThisFallbackFizz (#31779) We're not shipping `enableSuspenseAvoidThisFallback` and the fizz flag is already off so we can delete it. --- .../src/server/ReactFizzConfigDOM.js | 12 -- .../src/server/ReactFizzConfigDOMLegacy.js | 2 - .../src/__tests__/ReactDOMFizzServer-test.js | 145 ------------------ .../react-markup/src/ReactFizzConfigMarkup.js | 2 - packages/react-server/src/ReactFizzServer.js | 34 +--- .../src/forks/ReactFizzConfig.custom.js | 4 - packages/shared/ReactFeatureFlags.js | 2 - .../forks/ReactFeatureFlags.native-fb.js | 1 - .../forks/ReactFeatureFlags.native-oss.js | 1 - .../forks/ReactFeatureFlags.test-renderer.js | 1 - ...actFeatureFlags.test-renderer.native-fb.js | 1 - .../ReactFeatureFlags.test-renderer.www.js | 1 - .../shared/forks/ReactFeatureFlags.www.js | 1 - 13 files changed, 1 insertion(+), 206 deletions(-) diff --git a/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js b/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js index 9883ba4454df4..04aaf0c2ac706 100644 --- a/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js +++ b/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js @@ -3886,18 +3886,6 @@ const clientRenderedSuspenseBoundaryError1D = const clientRenderedSuspenseBoundaryError2 = stringToPrecomputedChunk('></template>'); -export function pushStartCompletedSuspenseBoundary( - target: Array<Chunk | PrecomputedChunk>, -) { - target.push(startCompletedSuspenseBoundary); -} - -export function pushEndCompletedSuspenseBoundary( - target: Array<Chunk | PrecomputedChunk>, -) { - target.push(endSuspenseBoundary); -} - export function writeStartCompletedSuspenseBoundary( destination: Destination, renderState: RenderState, diff --git a/packages/react-dom-bindings/src/server/ReactFizzConfigDOMLegacy.js b/packages/react-dom-bindings/src/server/ReactFizzConfigDOMLegacy.js index 725ee666f52af..e4cd9ca93d99e 100644 --- a/packages/react-dom-bindings/src/server/ReactFizzConfigDOMLegacy.js +++ b/packages/react-dom-bindings/src/server/ReactFizzConfigDOMLegacy.js @@ -142,8 +142,6 @@ export { makeId, pushStartInstance, pushEndInstance, - pushStartCompletedSuspenseBoundary, - pushEndCompletedSuspenseBoundary, pushFormStateMarkerIsMatching, pushFormStateMarkerIsNotMatching, writeStartSegment, diff --git a/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js b/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js index 9dcd4c6945884..777f067a183e8 100644 --- a/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js @@ -2211,151 +2211,6 @@ describe('ReactDOMFizzServer', () => { expect(getVisibleChildren(container)).toEqual(<div>Hello</div>); }); - // @gate enableSuspenseAvoidThisFallbackFizz - it('should respect unstable_avoidThisFallback', async () => { - const resolved = { - 0: false, - 1: false, - }; - const promiseRes = {}; - const promises = { - 0: new Promise(res => { - promiseRes[0] = () => { - resolved[0] = true; - res(); - }; - }), - 1: new Promise(res => { - promiseRes[1] = () => { - resolved[1] = true; - res(); - }; - }), - }; - - const InnerComponent = ({isClient, depth}) => { - if (isClient) { - // Resuspend after re-rendering on client to check that fallback shows on client - throw new Promise(() => {}); - } - if (!resolved[depth]) { - throw promises[depth]; - } - return ( - <div> - <Text text={`resolved ${depth}`} /> - </div> - ); - }; - - function App({isClient}) { - return ( - <div> - <Text text="Non Suspense Content" /> - <Suspense - fallback={ - <span> - <Text text="Avoided Fallback" /> - </span> - } - unstable_avoidThisFallback={true}> - <InnerComponent isClient={isClient} depth={0} /> - <div> - <Suspense fallback={<Text text="Fallback" />}> - <Suspense - fallback={ - <span> - <Text text="Avoided Fallback2" /> - </span> - } - unstable_avoidThisFallback={true}> - <InnerComponent isClient={isClient} depth={1} /> - </Suspense> - </Suspense> - </div> - </Suspense> - </div> - ); - } - - await jest.runAllTimers(); - - await act(() => { - const {pipe} = renderToPipeableStream(<App isClient={false} />); - pipe(writable); - }); - - // Nothing is output since root has a suspense with avoidedThisFallback that hasn't resolved - expect(getVisibleChildren(container)).toEqual(undefined); - expect(container.innerHTML).not.toContain('Avoided Fallback'); - - // resolve first suspense component with avoidThisFallback - await act(() => { - promiseRes[0](); - }); - - expect(getVisibleChildren(container)).toEqual( - <div> - Non Suspense Content - <div>resolved 0</div> - <div>Fallback</div> - </div>, - ); - - expect(container.innerHTML).not.toContain('Avoided Fallback2'); - - await act(() => { - promiseRes[1](); - }); - - expect(getVisibleChildren(container)).toEqual( - <div> - Non Suspense Content - <div>resolved 0</div> - <div> - <div>resolved 1</div> - </div> - </div>, - ); - - let root; - await act(async () => { - root = ReactDOMClient.hydrateRoot(container, <App isClient={false} />); - await waitForAll([]); - await jest.runAllTimers(); - }); - - // No change after hydration - expect(getVisibleChildren(container)).toEqual( - <div> - Non Suspense Content - <div>resolved 0</div> - <div> - <div>resolved 1</div> - </div> - </div>, - ); - - await act(async () => { - // Trigger update by changing isClient to true - root.render(<App isClient={true} />); - await waitForAll([]); - await jest.runAllTimers(); - }); - - // Now that we've resuspended at the root we show the root fallback - expect(getVisibleChildren(container)).toEqual( - <div> - Non Suspense Content - <div style="display: none;">resolved 0</div> - <div style="display: none;"> - <div>resolved 1</div> - </div> - <span>Avoided Fallback</span> - </div>, - ); - }); - it('calls getServerSnapshot instead of getSnapshot', async () => { const ref = React.createRef(); diff --git a/packages/react-markup/src/ReactFizzConfigMarkup.js b/packages/react-markup/src/ReactFizzConfigMarkup.js index 6b43d0bad39a7..048e54933930d 100644 --- a/packages/react-markup/src/ReactFizzConfigMarkup.js +++ b/packages/react-markup/src/ReactFizzConfigMarkup.js @@ -49,8 +49,6 @@ export { getChildFormatContext, makeId, pushEndInstance, - pushStartCompletedSuspenseBoundary, - pushEndCompletedSuspenseBoundary, pushFormStateMarkerIsMatching, pushFormStateMarkerIsNotMatching, writeStartSegment, diff --git a/packages/react-server/src/ReactFizzServer.js b/packages/react-server/src/ReactFizzServer.js index f245861ba0012..ad6721ec60796 100644 --- a/packages/react-server/src/ReactFizzServer.js +++ b/packages/react-server/src/ReactFizzServer.js @@ -65,8 +65,6 @@ import { pushTextInstance, pushStartInstance, pushEndInstance, - pushStartCompletedSuspenseBoundary, - pushEndCompletedSuspenseBoundary, pushSegmentFinale, getChildFormatContext, writeHoistables, @@ -155,7 +153,6 @@ import { disableLegacyContext, disableLegacyContextForFunctionComponents, enableScopeAPI, - enableSuspenseAvoidThisFallbackFizz, enableCache, enablePostpone, enableHalt, @@ -1490,28 +1487,6 @@ function replaySuspenseBoundary( request.pingedTasks.push(suspendedFallbackTask); } -function renderBackupSuspenseBoundary( - request: Request, - task: Task, - keyPath: KeyNode, - props: Object, -) { - const content = props.children; - const segment = task.blockedSegment; - const prevKeyPath = task.keyPath; - task.keyPath = keyPath; - if (segment === null) { - // Replay - renderNode(request, task, content, -1); - } else { - // Render - pushStartCompletedSuspenseBoundary(segment.chunks); - renderNode(request, task, content, -1); - pushEndCompletedSuspenseBoundary(segment.chunks); - } - task.keyPath = prevKeyPath; -} - function renderHostElement( request: Request, task: Task, @@ -2194,14 +2169,7 @@ function renderElement( throw new Error('ReactDOMServer does not yet support scope components.'); } case REACT_SUSPENSE_TYPE: { - if ( - enableSuspenseAvoidThisFallbackFizz && - props.unstable_avoidThisFallback === true - ) { - renderBackupSuspenseBoundary(request, task, keyPath, props); - } else { - renderSuspenseBoundary(request, task, keyPath, props); - } + renderSuspenseBoundary(request, task, keyPath, props); return; } } diff --git a/packages/react-server/src/forks/ReactFizzConfig.custom.js b/packages/react-server/src/forks/ReactFizzConfig.custom.js index 02ce1e4e2afee..be14f349aa286 100644 --- a/packages/react-server/src/forks/ReactFizzConfig.custom.js +++ b/packages/react-server/src/forks/ReactFizzConfig.custom.js @@ -51,10 +51,6 @@ export const makeId = $$$config.makeId; export const pushTextInstance = $$$config.pushTextInstance; export const pushStartInstance = $$$config.pushStartInstance; export const pushEndInstance = $$$config.pushEndInstance; -export const pushStartCompletedSuspenseBoundary = - $$$config.pushStartCompletedSuspenseBoundary; -export const pushEndCompletedSuspenseBoundary = - $$$config.pushEndCompletedSuspenseBoundary; export const pushSegmentFinale = $$$config.pushSegmentFinale; export const pushFormStateMarkerIsMatching = $$$config.pushFormStateMarkerIsMatching; diff --git a/packages/shared/ReactFeatureFlags.js b/packages/shared/ReactFeatureFlags.js index 212afaabc4216..f28d123e61e5b 100644 --- a/packages/shared/ReactFeatureFlags.js +++ b/packages/shared/ReactFeatureFlags.js @@ -108,8 +108,6 @@ export const enableLegacyHidden = false; // Enables unstable_avoidThisFallback feature in Fiber export const enableSuspenseAvoidThisFallback = false; -// Enables unstable_avoidThisFallback feature in Fizz -export const enableSuspenseAvoidThisFallbackFizz = false; export const enableCPUSuspense = __EXPERIMENTAL__; diff --git a/packages/shared/forks/ReactFeatureFlags.native-fb.js b/packages/shared/forks/ReactFeatureFlags.native-fb.js index 7493a34494d82..4d89fa091061a 100644 --- a/packages/shared/forks/ReactFeatureFlags.native-fb.js +++ b/packages/shared/forks/ReactFeatureFlags.native-fb.js @@ -73,7 +73,6 @@ export const enableComponentPerformanceTrack = false; export const enableScopeAPI = false; export const enableServerComponentLogs = true; export const enableSuspenseAvoidThisFallback = false; -export const enableSuspenseAvoidThisFallbackFizz = false; export const enableSuspenseCallback = true; export const enableTaint = true; export const enableTransitionTracing = false; diff --git a/packages/shared/forks/ReactFeatureFlags.native-oss.js b/packages/shared/forks/ReactFeatureFlags.native-oss.js index e034a723d7574..0407f01910b75 100644 --- a/packages/shared/forks/ReactFeatureFlags.native-oss.js +++ b/packages/shared/forks/ReactFeatureFlags.native-oss.js @@ -63,7 +63,6 @@ export const enableScopeAPI = false; export const enableServerComponentLogs = true; export const enableShallowPropDiffing = false; export const enableSuspenseAvoidThisFallback = false; -export const enableSuspenseAvoidThisFallbackFizz = false; export const enableSuspenseCallback = false; export const enableTaint = true; export const enableTransitionTracing = false; diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.js index fe518f955e949..b83cb9a99fc3d 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.js @@ -33,7 +33,6 @@ export const enableSuspenseCallback = false; export const enableTrustedTypesIntegration = false; export const disableTextareaChildren = false; export const enableSuspenseAvoidThisFallback = false; -export const enableSuspenseAvoidThisFallbackFizz = false; export const enableCPUSuspense = false; export const enableNoCloningMemoCache = false; export const enableUseEffectEventHook = false; diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js index 0b0da8b8cb326..115117685aeb4 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js @@ -57,7 +57,6 @@ export const enableScopeAPI = false; export const enableServerComponentLogs = true; export const enableShallowPropDiffing = false; export const enableSuspenseAvoidThisFallback = false; -export const enableSuspenseAvoidThisFallbackFizz = false; export const enableSuspenseCallback = false; export const enableTaint = true; export const enableTransitionTracing = false; diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js index 63f76b4a3a7c4..cad15eecc8c11 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js @@ -35,7 +35,6 @@ export const disableLegacyContextForFunctionComponents = false; export const enableTrustedTypesIntegration = false; export const disableTextareaChildren = false; export const enableSuspenseAvoidThisFallback = true; -export const enableSuspenseAvoidThisFallbackFizz = false; export const enableCPUSuspense = false; export const enableNoCloningMemoCache = false; export const enableUseEffectEventHook = false; diff --git a/packages/shared/forks/ReactFeatureFlags.www.js b/packages/shared/forks/ReactFeatureFlags.www.js index f54c73a4647d4..eea2ba4230f50 100644 --- a/packages/shared/forks/ReactFeatureFlags.www.js +++ b/packages/shared/forks/ReactFeatureFlags.www.js @@ -51,7 +51,6 @@ export const enableUpdaterTracking = __PROFILE__; export const enableFabricCompleteRootInCommitPhase = false; export const enableSuspenseAvoidThisFallback = true; -export const enableSuspenseAvoidThisFallbackFizz = false; export const enableCPUSuspense = true; export const enableUseEffectEventHook = true; From d1dd7feabc63bf8ca61e9b3f4d78245a29ebbe9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Markb=C3=A5ge?= <sebastian@calyptus.eu> Date: Sat, 14 Dec 2024 13:46:21 -0500 Subject: [PATCH 3/6] [Fiber] Schedule client renders using non-hydration lane (#31776) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Related to #31752. When hydrating, we have two different ways of handling a Suspense boundary that the server has already given up on and decided to client render. If we have already hydrated the parent and then later this happens, then we'll use the retry lane like any ping. If we discover that it was already in client-render mode when we discover the Suspense boundary for the first time, then schedule a default lane to let us first finish the current render and then upgrade the priority to sync to try to client render this boundary as soon as possible since we're holding back content. We used to use the `DefaultHydrationLane` for this but this is not really a Hydration. It's actually a client render. If we get any other updates flowing in from above at the same time we might as well do them in the same pass instead of two passes. So this should be considered more like any update. This also means that visually the client render pass now gets painted as a render instead of a hydration. This show the flow of a shell being hydrated at the default priority, then a Suspense boundary being discovered and hydrated at Idle and then an inner boundary being discovered as client rendered which gets upgraded to default. <img width="1363" alt="Screenshot 2024-12-14 at 12 13 57 AM" src="https://github.com/user-attachments/assets/a141133e-4856-4f38-a11f-f26bd00b6245" /> --- packages/react-reconciler/src/ReactFiberBeginWork.js | 12 +++++------- packages/shared/ReactFeatureFlags.js | 4 ++-- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.js b/packages/react-reconciler/src/ReactFiberBeginWork.js index 119129d506c09..0ae0e668d22ac 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.js @@ -111,6 +111,7 @@ import { disableLegacyMode, disableDefaultPropsExceptForClasses, enableOwnerStacks, + enableHydrationLaneScheduling, } from 'shared/ReactFeatureFlags'; import isArray from 'shared/isArray'; import shallowEqual from 'shared/shallowEqual'; @@ -146,6 +147,7 @@ import { NoLane, NoLanes, OffscreenLane, + DefaultLane, DefaultHydrationLane, SomeRetryLane, includesSomeLane, @@ -2646,14 +2648,10 @@ function mountDehydratedSuspenseComponent( // have timed out. In theory we could render it in this pass but it would have the // wrong priority associated with it and will prevent hydration of parent path. // Instead, we'll leave work left on it to render it in a separate commit. - - // TODO This time should be the time at which the server rendered response that is - // a parent to this boundary was displayed. However, since we currently don't have - // a protocol to transfer that time, we'll just estimate it by using the current - // time. This will mean that Suspense timeouts are slightly shifted to later than - // they should be. // Schedule a normal pri update to render this content. - workInProgress.lanes = laneToLanes(DefaultHydrationLane); + workInProgress.lanes = laneToLanes( + enableHydrationLaneScheduling ? DefaultLane : DefaultHydrationLane, + ); } else { // We'll continue hydrating the rest at offscreen priority since we'll already // be showing the right content coming from the server, it is no rush. diff --git a/packages/shared/ReactFeatureFlags.js b/packages/shared/ReactFeatureFlags.js index f28d123e61e5b..afac564cad28a 100644 --- a/packages/shared/ReactFeatureFlags.js +++ b/packages/shared/ReactFeatureFlags.js @@ -22,6 +22,8 @@ // when it rolls out to prod. We should remove these as soon as possible. // ----------------------------------------------------------------------------- +export const enableHydrationLaneScheduling = true; + // ----------------------------------------------------------------------------- // Land or remove (moderate effort) // @@ -111,8 +113,6 @@ export const enableSuspenseAvoidThisFallback = false; export const enableCPUSuspense = __EXPERIMENTAL__; -export const enableHydrationLaneScheduling = true; - // Test this at Meta before enabling. export const enableNoCloningMemoCache = false; From c32780eeb4c44e138d09a35da841926f512d3b07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Markb=C3=A5ge?= <sebastian@calyptus.eu> Date: Sat, 14 Dec 2024 13:49:47 -0500 Subject: [PATCH 4/6] [Fiber] Highlight hydration and offscreen render phases (#31752) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This highlights the render phase as the tertiary color (green) when we're render a hydration lane or offscreen lane. I call the "Render" phase "Hydrated" instead in this case. For the offscreen case we don't currently have a differentiation between hydrated or activity. I just called that "Prepared". Even for the hydration case where there's no discovered client rendered boundaries it's more like it's preparing for an interaction rather than blocking one. Where as for the other lanes the hydration might block something. <img width="1173" alt="Screenshot 2024-12-12 at 11 23 14 PM" src="https://github.com/user-attachments/assets/49ab1508-840f-4188-a085-18fe94b14187" /> In a follow up I'd like to color the components in the Components tree green if they were hydrated but not the ones that was actually client rendered e.g. due to a mismatch or forced client rendering so you can tell the difference. Unfortunately, the current signals we have for this get reset earlier in the commit phase than when we log these. Another thing is that a failed hydration should probably be colored red even though it ends up committing successfully. I.e. a recoverable error. --- .../react-reconciler/src/ReactFiberLane.js | 12 ++++ .../src/ReactFiberPerformanceTrack.js | 70 ++++++++++++++++--- .../src/ReactFiberWorkLoop.js | 29 ++++++-- 3 files changed, 94 insertions(+), 17 deletions(-) diff --git a/packages/react-reconciler/src/ReactFiberLane.js b/packages/react-reconciler/src/ReactFiberLane.js index ee3a0a3df2b60..4c96207bd6696 100644 --- a/packages/react-reconciler/src/ReactFiberLane.js +++ b/packages/react-reconciler/src/ReactFiberLane.js @@ -621,6 +621,18 @@ export function includesTransitionLane(lanes: Lanes): boolean { return (lanes & TransitionLanes) !== NoLanes; } +export function includesOnlyHydrationLanes(lanes: Lanes): boolean { + return (lanes & HydrationLanes) === lanes; +} + +export function includesOnlyOffscreenLanes(lanes: Lanes): boolean { + return (lanes & OffscreenLane) === lanes; +} + +export function includesOnlyHydrationOrOffscreenLanes(lanes: Lanes): boolean { + return (lanes & (HydrationLanes | OffscreenLane)) === lanes; +} + export function includesBlockingLane(lanes: Lanes): boolean { const SyncDefaultLanes = InputContinuousHydrationLane | diff --git a/packages/react-reconciler/src/ReactFiberPerformanceTrack.js b/packages/react-reconciler/src/ReactFiberPerformanceTrack.js index 56470bb0e55d6..7e9e246d8beb2 100644 --- a/packages/react-reconciler/src/ReactFiberPerformanceTrack.js +++ b/packages/react-reconciler/src/ReactFiberPerformanceTrack.js @@ -9,9 +9,16 @@ import type {Fiber} from './ReactInternalTypes'; +import type {Lanes} from './ReactFiberLane'; + import getComponentNameFromFiber from './getComponentNameFromFiber'; -import {getGroupNameOfHighestPriorityLane} from './ReactFiberLane'; +import { + getGroupNameOfHighestPriorityLane, + includesOnlyHydrationLanes, + includesOnlyOffscreenLanes, + includesOnlyHydrationOrOffscreenLanes, +} from './ReactFiberLane'; import {enableProfilerTimer} from 'shared/ReactFeatureFlags'; @@ -51,7 +58,7 @@ const reusableLaneOptions = { }, }; -export function setCurrentTrackFromLanes(lanes: number): void { +export function setCurrentTrackFromLanes(lanes: Lanes): void { reusableLaneDevToolDetails.track = getGroupNameOfHighestPriorityLane(lanes); } @@ -223,6 +230,7 @@ export function logBlockingStart( eventType: null | string, eventIsRepeat: boolean, renderStartTime: number, + lanes: Lanes, ): void { if (supportsUserTiming) { reusableLaneDevToolDetails.track = 'Blocking'; @@ -240,7 +248,11 @@ export function logBlockingStart( } if (updateTime > 0) { // Log the time from when we called setState until we started rendering. - reusableLaneDevToolDetails.color = 'primary-light'; + reusableLaneDevToolDetails.color = includesOnlyHydrationOrOffscreenLanes( + lanes, + ) + ? 'tertiary-light' + : 'primary-light'; reusableLaneOptions.start = updateTime; reusableLaneOptions.end = renderStartTime; performance.measure('Blocked', reusableLaneOptions); @@ -292,33 +304,65 @@ export function logTransitionStart( } } -export function logRenderPhase(startTime: number, endTime: number): void { +export function logRenderPhase( + startTime: number, + endTime: number, + lanes: Lanes, +): void { if (supportsUserTiming) { - reusableLaneDevToolDetails.color = 'primary-dark'; + reusableLaneDevToolDetails.color = includesOnlyHydrationOrOffscreenLanes( + lanes, + ) + ? 'tertiary-dark' + : 'primary-dark'; reusableLaneOptions.start = startTime; reusableLaneOptions.end = endTime; - performance.measure('Render', reusableLaneOptions); + performance.measure( + includesOnlyOffscreenLanes(lanes) + ? 'Prepared' + : includesOnlyHydrationLanes(lanes) + ? 'Hydrated' + : 'Render', + reusableLaneOptions, + ); } } export function logInterruptedRenderPhase( startTime: number, endTime: number, + lanes: Lanes, ): void { if (supportsUserTiming) { - reusableLaneDevToolDetails.color = 'primary-dark'; + reusableLaneDevToolDetails.color = includesOnlyHydrationOrOffscreenLanes( + lanes, + ) + ? 'tertiary-dark' + : 'primary-dark'; reusableLaneOptions.start = startTime; reusableLaneOptions.end = endTime; - performance.measure('Interrupted Render', reusableLaneOptions); + performance.measure( + includesOnlyOffscreenLanes(lanes) + ? 'Prewarm' + : includesOnlyHydrationLanes(lanes) + ? 'Interrupted Hydration' + : 'Interrupted Render', + reusableLaneOptions, + ); } } export function logSuspendedRenderPhase( startTime: number, endTime: number, + lanes: Lanes, ): void { if (supportsUserTiming) { - reusableLaneDevToolDetails.color = 'primary-dark'; + reusableLaneDevToolDetails.color = includesOnlyHydrationOrOffscreenLanes( + lanes, + ) + ? 'tertiary-dark' + : 'primary-dark'; reusableLaneOptions.start = startTime; reusableLaneOptions.end = endTime; performance.measure('Prewarm', reusableLaneOptions); @@ -328,10 +372,15 @@ export function logSuspendedRenderPhase( export function logSuspendedWithDelayPhase( startTime: number, endTime: number, + lanes: Lanes, ): void { // This means the render was suspended and cannot commit until it gets unblocked. if (supportsUserTiming) { - reusableLaneDevToolDetails.color = 'primary-dark'; + reusableLaneDevToolDetails.color = includesOnlyHydrationOrOffscreenLanes( + lanes, + ) + ? 'tertiary-dark' + : 'primary-dark'; reusableLaneOptions.start = startTime; reusableLaneOptions.end = endTime; performance.measure('Suspended', reusableLaneOptions); @@ -341,6 +390,7 @@ export function logSuspendedWithDelayPhase( export function logErroredRenderPhase( startTime: number, endTime: number, + lanes: Lanes, ): void { if (supportsUserTiming) { reusableLaneDevToolDetails.color = 'error'; diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.js b/packages/react-reconciler/src/ReactFiberWorkLoop.js index f812d16c9c65a..dd637d687da4f 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.js @@ -1035,7 +1035,7 @@ export function performWorkOnRoot( if (errorRetryLanes !== NoLanes) { if (enableProfilerTimer && enableComponentPerformanceTrack) { setCurrentTrackFromLanes(lanes); - logErroredRenderPhase(renderStartTime, renderEndTime); + logErroredRenderPhase(renderStartTime, renderEndTime, lanes); finalizeRender(lanes, renderEndTime); } lanes = errorRetryLanes; @@ -1066,7 +1066,7 @@ export function performWorkOnRoot( if (exitStatus === RootFatalErrored) { if (enableProfilerTimer && enableComponentPerformanceTrack) { setCurrentTrackFromLanes(lanes); - logErroredRenderPhase(renderStartTime, renderEndTime); + logErroredRenderPhase(renderStartTime, renderEndTime, lanes); finalizeRender(lanes, renderEndTime); } prepareFreshStack(root, NoLanes); @@ -1207,7 +1207,7 @@ function finishConcurrentRender( // until we receive more data. if (enableProfilerTimer && enableComponentPerformanceTrack) { setCurrentTrackFromLanes(lanes); - logSuspendedRenderPhase(renderStartTime, renderEndTime); + logSuspendedRenderPhase(renderStartTime, renderEndTime, lanes); finalizeRender(lanes, renderEndTime); trackSuspendedTime(lanes, renderEndTime); } @@ -1757,9 +1757,17 @@ function prepareFreshStack(root: FiberRoot, lanes: Lanes): Fiber { // then this is considered a prewarm and not an interrupted render because // we couldn't have shown anything anyway so it's not a bad thing that we // got interrupted. - logSuspendedRenderPhase(previousRenderStartTime, renderStartTime); + logSuspendedRenderPhase( + previousRenderStartTime, + renderStartTime, + lanes, + ); } else { - logInterruptedRenderPhase(previousRenderStartTime, renderStartTime); + logInterruptedRenderPhase( + previousRenderStartTime, + renderStartTime, + lanes, + ); } finalizeRender(workInProgressRootRenderLanes, renderStartTime); } @@ -1783,6 +1791,7 @@ function prepareFreshStack(root: FiberRoot, lanes: Lanes): Fiber { : clampedUpdateTime >= 0 ? clampedUpdateTime : renderStartTime, + lanes, ); } logBlockingStart( @@ -1791,6 +1800,7 @@ function prepareFreshStack(root: FiberRoot, lanes: Lanes): Fiber { blockingEventType, blockingEventIsRepeat, renderStartTime, + lanes, ); clearBlockingTimers(); } @@ -1817,6 +1827,7 @@ function prepareFreshStack(root: FiberRoot, lanes: Lanes): Fiber { : clampedUpdateTime >= 0 ? clampedUpdateTime : renderStartTime, + lanes, ); } logTransitionStart( @@ -3202,9 +3213,13 @@ function commitRootImpl( // Log the previous render phase once we commit. I.e. we weren't interrupted. setCurrentTrackFromLanes(lanes); if (exitStatus === RootErrored) { - logErroredRenderPhase(completedRenderStartTime, completedRenderEndTime); + logErroredRenderPhase( + completedRenderStartTime, + completedRenderEndTime, + lanes, + ); } else { - logRenderPhase(completedRenderStartTime, completedRenderEndTime); + logRenderPhase(completedRenderStartTime, completedRenderEndTime, lanes); } } From c80b336d23aa472b5e5910268138ac0447d6ae19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Markb=C3=A5ge?= <sebastian@calyptus.eu> Date: Sat, 14 Dec 2024 16:17:06 -0500 Subject: [PATCH 5/6] Implement requestPaint in the actual scheduler (#31784) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When implementing passive effects we did a pretty massive oversight. While the passive effect is scheduled into its own scheduler task, the scheduler doesn't always yield to the browser if it has time left. That means that if you have a fast commit phase, it might try to squeeze in the passive effects in the same frame but those then might end being very heavy. We had `requestPaint()` for this but that was only implemented for the `isInputPending` experiment. It wasn't thought we needed it for the regular scheduler because it yields "every frame" anyway - but it doesn't yield every task. While the `isInputPending` experiment showed that it wasn't actually any significant impact, and it was better to keep shorter yield time anyway. Which is why we deleted the code. Whatever small win it did see in some cases might have been actually due to this issue rather than anything to do with `isInputPending` at all. As you can see in https://github.com/facebook/react/pull/31782 we do have this implemented in the mock scheduler and a lot of behavior that we assert assumes that this works. So this just implements yielding after `requestPaint` is called. Before: <img width="1023" alt="Screenshot 2024-12-14 at 3 40 24 PM" src="https://github.com/user-attachments/assets/d60f4bb2-c8f8-4f91-a402-9ac25b278450" /> After: <img width="1108" alt="Screenshot 2024-12-14 at 3 41 25 PM" src="https://github.com/user-attachments/assets/170cdb90-a049-436f-9501-be3fb9bc04ca" /> Notice how in after the native task is split into two. It might not always actually paint and the native scheduler might make the same mistake and think it has enough time left but it's at least less likely to. We do have another way to do this. When we yield a continuation we also yield to the native browser. This is to enable the Suspense Optimization (currently disabled) to work. We could do the same for passive effects and, in fact, I have a branch that does but because that requires a lot more tests to be fixed it's a lot more invasive of a change. The nice thing about this approach is that this is not even running in tests at all and the tests we do have assert that this is the behavior already. 😬 --- packages/scheduler/src/__tests__/Scheduler-test.js | 4 ++-- packages/scheduler/src/forks/Scheduler.js | 11 ++++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/scheduler/src/__tests__/Scheduler-test.js b/packages/scheduler/src/__tests__/Scheduler-test.js index 5af59a24a24f5..9e0813e461e61 100644 --- a/packages/scheduler/src/__tests__/Scheduler-test.js +++ b/packages/scheduler/src/__tests__/Scheduler-test.js @@ -183,7 +183,7 @@ describe('SchedulerBrowser', () => { it('task with continuation', () => { scheduleCallback(NormalPriority, () => { runtime.log('Task'); - // Request paint so that we yield at the end of the frame interval + // Request paint so that we yield immediately requestPaint(); while (!Scheduler.unstable_shouldYield()) { runtime.advanceTime(1); @@ -199,7 +199,7 @@ describe('SchedulerBrowser', () => { runtime.assertLog([ 'Message Event', 'Task', - gate(flags => (flags.www ? 'Yield at 10ms' : 'Yield at 5ms')), + 'Yield at 0ms', 'Post Message', ]); diff --git a/packages/scheduler/src/forks/Scheduler.js b/packages/scheduler/src/forks/Scheduler.js index a785bec95320c..0e85e0a99b7b0 100644 --- a/packages/scheduler/src/forks/Scheduler.js +++ b/packages/scheduler/src/forks/Scheduler.js @@ -93,6 +93,8 @@ var isPerformingWork = false; var isHostCallbackScheduled = false; var isHostTimeoutScheduled = false; +var needsPaint = false; + // Capture local references to native APIs, in case a polyfill overrides them. const localSetTimeout = typeof setTimeout === 'function' ? setTimeout : null; const localClearTimeout = @@ -456,6 +458,10 @@ let frameInterval = frameYieldMs; let startTime = -1; function shouldYieldToHost(): boolean { + if (needsPaint) { + // Yield now. + return true; + } const timeElapsed = getCurrentTime() - startTime; if (timeElapsed < frameInterval) { // The main thread has only been blocked for a really short amount of time; @@ -466,7 +472,9 @@ function shouldYieldToHost(): boolean { return true; } -function requestPaint() {} +function requestPaint() { + needsPaint = true; +} function forceFrameRate(fps: number) { if (fps < 0 || fps > 125) { @@ -486,6 +494,7 @@ function forceFrameRate(fps: number) { } const performWorkUntilDeadline = () => { + needsPaint = false; if (isMessageLoopRunning) { const currentTime = getCurrentTime(); // Keep track of the start time so we can measure how long the main thread From 2d320563f35ad75419983f166431055b4e7ed9f6 Mon Sep 17 00:00:00 2001 From: Ricky <rickhanlonii@gmail.com> Date: Sun, 15 Dec 2024 12:16:10 -0500 Subject: [PATCH 6/6] [flags] Delete enableDebugTracing (#31780) This is unused, even in the one builds that uses it, and we don't plan on landing it in this form. --- .../ReactDOMServerIntegrationModes-test.js | 50 -- packages/react-reconciler/src/DebugTracing.js | 231 --------- packages/react-reconciler/src/ReactFiber.js | 10 - .../src/ReactFiberClassComponent.js | 36 +- .../react-reconciler/src/ReactFiberHooks.js | 12 - .../react-reconciler/src/ReactFiberThrow.js | 13 +- .../src/ReactFiberWorkLoop.js | 75 --- .../react-reconciler/src/ReactTypeOfMode.js | 4 +- .../__tests__/DebugTracing-test.internal.js | 440 ------------------ packages/react-server/src/ReactFizzServer.js | 2 - packages/react/index.development.js | 1 - .../react/index.experimental.development.js | 1 - packages/react/index.experimental.js | 1 - packages/react/index.fb.js | 1 - packages/react/index.js | 1 - packages/react/src/ReactClient.js | 2 - .../ReactServer.experimental.development.js | 2 - .../react/src/ReactServer.experimental.js | 2 - packages/shared/ReactFeatureFlags.js | 5 - packages/shared/ReactSymbols.js | 3 - .../forks/ReactFeatureFlags.native-fb.js | 1 - .../forks/ReactFeatureFlags.native-oss.js | 1 - .../forks/ReactFeatureFlags.test-renderer.js | 1 - ...actFeatureFlags.test-renderer.native-fb.js | 1 - .../ReactFeatureFlags.test-renderer.www.js | 1 - .../forks/ReactFeatureFlags.www-dynamic.js | 6 - .../shared/forks/ReactFeatureFlags.www.js | 1 - packages/shared/isValidElementType.js | 3 - 28 files changed, 4 insertions(+), 903 deletions(-) delete mode 100644 packages/react-reconciler/src/DebugTracing.js delete mode 100644 packages/react-reconciler/src/__tests__/DebugTracing-test.internal.js diff --git a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationModes-test.js b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationModes-test.js index 9dbac22704d17..5770bd1e20c9f 100644 --- a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationModes-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationModes-test.js @@ -37,56 +37,6 @@ describe('ReactDOMServerIntegration', () => { resetModules(); }); - // Test pragmas don't support itRenders abstraction - if ( - __EXPERIMENTAL__ && - require('shared/ReactFeatureFlags').enableDebugTracing - ) { - describe('React.unstable_DebugTracingMode', () => { - beforeEach(() => { - spyOnDevAndProd(console, 'log'); - }); - - itRenders('with one child', async render => { - const e = await render( - <React.unstable_DebugTracingMode> - <div>text1</div> - </React.unstable_DebugTracingMode>, - ); - const parent = e.parentNode; - expect(parent.childNodes[0].tagName).toBe('DIV'); - }); - - itRenders('mode with several children', async render => { - const Header = props => { - return <p>header</p>; - }; - const Footer = props => { - return ( - <React.unstable_DebugTracingMode> - <h2>footer</h2> - <h3>about</h3> - </React.unstable_DebugTracingMode> - ); - }; - const e = await render( - <React.unstable_DebugTracingMode> - <div>text1</div> - <span>text2</span> - <Header /> - <Footer /> - </React.unstable_DebugTracingMode>, - ); - const parent = e.parentNode; - expect(parent.childNodes[0].tagName).toBe('DIV'); - expect(parent.childNodes[1].tagName).toBe('SPAN'); - expect(parent.childNodes[2].tagName).toBe('P'); - expect(parent.childNodes[3].tagName).toBe('H2'); - expect(parent.childNodes[4].tagName).toBe('H3'); - }); - }); - } - describe('React.StrictMode', () => { itRenders('a strict mode with one child', async render => { const e = await render( diff --git a/packages/react-reconciler/src/DebugTracing.js b/packages/react-reconciler/src/DebugTracing.js deleted file mode 100644 index 16606748be696..0000000000000 --- a/packages/react-reconciler/src/DebugTracing.js +++ /dev/null @@ -1,231 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -import type {Lane, Lanes} from './ReactFiberLane'; -import type {Wakeable} from 'shared/ReactTypes'; - -import {enableDebugTracing} from 'shared/ReactFeatureFlags'; - -const nativeConsole: Object = console; -let nativeConsoleLog: null | Function = null; - -const pendingGroupArgs: Array<any> = []; -let printedGroupIndex: number = -1; - -function formatLanes(laneOrLanes: Lane | Lanes): string { - return '0b' + (laneOrLanes: any).toString(2).padStart(31, '0'); -} - -function group(...groupArgs: Array<string>): void { - pendingGroupArgs.push(groupArgs); - - if (nativeConsoleLog === null) { - nativeConsoleLog = nativeConsole.log; - nativeConsole.log = log; - } -} - -function groupEnd(): void { - pendingGroupArgs.pop(); - while (printedGroupIndex >= pendingGroupArgs.length) { - nativeConsole.groupEnd(); - printedGroupIndex--; - } - - if (pendingGroupArgs.length === 0) { - nativeConsole.log = nativeConsoleLog; - nativeConsoleLog = null; - } -} - -function log(...logArgs: Array<mixed>): void { - if (printedGroupIndex < pendingGroupArgs.length - 1) { - for (let i = printedGroupIndex + 1; i < pendingGroupArgs.length; i++) { - const groupArgs = pendingGroupArgs[i]; - nativeConsole.group(...groupArgs); - } - printedGroupIndex = pendingGroupArgs.length - 1; - } - if (typeof nativeConsoleLog === 'function') { - nativeConsoleLog(...logArgs); - } else { - nativeConsole.log(...logArgs); - } -} - -const REACT_LOGO_STYLE = - 'background-color: #20232a; color: #61dafb; padding: 0 2px;'; - -export function logCommitStarted(lanes: Lanes): void { - if (__DEV__) { - if (enableDebugTracing) { - group( - `%c⚛%c commit%c (${formatLanes(lanes)})`, - REACT_LOGO_STYLE, - '', - 'font-weight: normal;', - ); - } - } -} - -export function logCommitStopped(): void { - if (__DEV__) { - if (enableDebugTracing) { - groupEnd(); - } - } -} - -const PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map; -// $FlowFixMe[incompatible-type]: Flow cannot handle polymorphic WeakMaps -const wakeableIDs: WeakMap<Wakeable, number> = new PossiblyWeakMap(); -let wakeableID: number = 0; -function getWakeableID(wakeable: Wakeable): number { - if (!wakeableIDs.has(wakeable)) { - wakeableIDs.set(wakeable, wakeableID++); - } - return ((wakeableIDs.get(wakeable): any): number); -} - -export function logComponentSuspended( - componentName: string, - wakeable: Wakeable, -): void { - if (__DEV__) { - if (enableDebugTracing) { - const id = getWakeableID(wakeable); - const display = (wakeable: any).displayName || wakeable; - log( - `%c⚛%c ${componentName} suspended`, - REACT_LOGO_STYLE, - 'color: #80366d; font-weight: bold;', - id, - display, - ); - wakeable.then( - () => { - log( - `%c⚛%c ${componentName} resolved`, - REACT_LOGO_STYLE, - 'color: #80366d; font-weight: bold;', - id, - display, - ); - }, - () => { - log( - `%c⚛%c ${componentName} rejected`, - REACT_LOGO_STYLE, - 'color: #80366d; font-weight: bold;', - id, - display, - ); - }, - ); - } - } -} - -export function logLayoutEffectsStarted(lanes: Lanes): void { - if (__DEV__) { - if (enableDebugTracing) { - group( - `%c⚛%c layout effects%c (${formatLanes(lanes)})`, - REACT_LOGO_STYLE, - '', - 'font-weight: normal;', - ); - } - } -} - -export function logLayoutEffectsStopped(): void { - if (__DEV__) { - if (enableDebugTracing) { - groupEnd(); - } - } -} - -export function logPassiveEffectsStarted(lanes: Lanes): void { - if (__DEV__) { - if (enableDebugTracing) { - group( - `%c⚛%c passive effects%c (${formatLanes(lanes)})`, - REACT_LOGO_STYLE, - '', - 'font-weight: normal;', - ); - } - } -} - -export function logPassiveEffectsStopped(): void { - if (__DEV__) { - if (enableDebugTracing) { - groupEnd(); - } - } -} - -export function logRenderStarted(lanes: Lanes): void { - if (__DEV__) { - if (enableDebugTracing) { - group( - `%c⚛%c render%c (${formatLanes(lanes)})`, - REACT_LOGO_STYLE, - '', - 'font-weight: normal;', - ); - } - } -} - -export function logRenderStopped(): void { - if (__DEV__) { - if (enableDebugTracing) { - groupEnd(); - } - } -} - -export function logForceUpdateScheduled( - componentName: string, - lane: Lane, -): void { - if (__DEV__) { - if (enableDebugTracing) { - log( - `%c⚛%c ${componentName} forced update %c(${formatLanes(lane)})`, - REACT_LOGO_STYLE, - 'color: #db2e1f; font-weight: bold;', - '', - ); - } - } -} - -export function logStateUpdateScheduled( - componentName: string, - lane: Lane, - payloadOrAction: any, -): void { - if (__DEV__) { - if (enableDebugTracing) { - log( - `%c⚛%c ${componentName} updated state %c(${formatLanes(lane)})`, - REACT_LOGO_STYLE, - 'color: #01a252; font-weight: bold;', - '', - payloadOrAction, - ); - } - } -} diff --git a/packages/react-reconciler/src/ReactFiber.js b/packages/react-reconciler/src/ReactFiber.js index 29a8931038c8d..42f347f4ba956 100644 --- a/packages/react-reconciler/src/ReactFiber.js +++ b/packages/react-reconciler/src/ReactFiber.js @@ -32,7 +32,6 @@ import { enableScopeAPI, enableLegacyHidden, enableTransitionTracing, - enableDebugTracing, enableDO_NOT_USE_disableStrictPassiveEffect, enableRenderableContext, disableLegacyMode, @@ -80,7 +79,6 @@ import {NoLanes} from './ReactFiberLane'; import { NoMode, ConcurrentMode, - DebugTracingMode, ProfileMode, StrictLegacyMode, StrictEffectsMode, @@ -89,7 +87,6 @@ import { import { REACT_FORWARD_REF_TYPE, REACT_FRAGMENT_TYPE, - REACT_DEBUG_TRACING_MODE_TYPE, REACT_STRICT_MODE_TYPE, REACT_PROFILER_TYPE, REACT_PROVIDER_TYPE, @@ -630,13 +627,6 @@ export function createFiberFromTypeAndProps( return createFiberFromTracingMarker(pendingProps, mode, lanes, key); } // Fall through - case REACT_DEBUG_TRACING_MODE_TYPE: - if (enableDebugTracing) { - fiberTag = Mode; - mode |= DebugTracingMode; - break; - } - // Fall through default: { if (typeof type === 'object' && type !== null) { switch (type.$$typeof) { diff --git a/packages/react-reconciler/src/ReactFiberClassComponent.js b/packages/react-reconciler/src/ReactFiberClassComponent.js index c32525702e944..f5d5c96a2a93c 100644 --- a/packages/react-reconciler/src/ReactFiberClassComponent.js +++ b/packages/react-reconciler/src/ReactFiberClassComponent.js @@ -20,7 +20,6 @@ import { import { debugRenderPhaseSideEffectsForStrictMode, disableLegacyContext, - enableDebugTracing, enableSchedulingProfiler, enableLazyContextPropagation, disableDefaultPropsExceptForClasses, @@ -35,12 +34,7 @@ import assign from 'shared/assign'; import isArray from 'shared/isArray'; import {REACT_CONTEXT_TYPE, REACT_CONSUMER_TYPE} from 'shared/ReactSymbols'; -import { - DebugTracingMode, - NoMode, - StrictLegacyMode, - StrictEffectsMode, -} from './ReactTypeOfMode'; +import {NoMode, StrictLegacyMode, StrictEffectsMode} from './ReactTypeOfMode'; import { enqueueUpdate, @@ -65,7 +59,6 @@ import { } from './ReactFiberContext'; import {readContext, checkIfContextChanged} from './ReactFiberNewContext'; import {requestUpdateLane, scheduleUpdateOnFiber} from './ReactFiberWorkLoop'; -import {logForceUpdateScheduled, logStateUpdateScheduled} from './DebugTracing'; import { markForceUpdateScheduled, markStateUpdateScheduled, @@ -199,15 +192,6 @@ const classComponentUpdater = { entangleTransitions(root, fiber, lane); } - if (__DEV__) { - if (enableDebugTracing) { - if (fiber.mode & DebugTracingMode) { - const name = getComponentNameFromFiber(fiber) || 'Unknown'; - logStateUpdateScheduled(name, lane, payload); - } - } - } - if (enableSchedulingProfiler) { markStateUpdateScheduled(fiber, lane); } @@ -234,15 +218,6 @@ const classComponentUpdater = { entangleTransitions(root, fiber, lane); } - if (__DEV__) { - if (enableDebugTracing) { - if (fiber.mode & DebugTracingMode) { - const name = getComponentNameFromFiber(fiber) || 'Unknown'; - logStateUpdateScheduled(name, lane, payload); - } - } - } - if (enableSchedulingProfiler) { markStateUpdateScheduled(fiber, lane); } @@ -269,15 +244,6 @@ const classComponentUpdater = { entangleTransitions(root, fiber, lane); } - if (__DEV__) { - if (enableDebugTracing) { - if (fiber.mode & DebugTracingMode) { - const name = getComponentNameFromFiber(fiber) || 'Unknown'; - logForceUpdateScheduled(name, lane); - } - } - } - if (enableSchedulingProfiler) { markForceUpdateScheduled(fiber, lane); } diff --git a/packages/react-reconciler/src/ReactFiberHooks.js b/packages/react-reconciler/src/ReactFiberHooks.js index d2df61063f687..11851d213b0fb 100644 --- a/packages/react-reconciler/src/ReactFiberHooks.js +++ b/packages/react-reconciler/src/ReactFiberHooks.js @@ -35,7 +35,6 @@ import { } from './ReactFiberConfig'; import ReactSharedInternals from 'shared/ReactSharedInternals'; import { - enableDebugTracing, enableSchedulingProfiler, enableCache, enableLazyContextPropagation, @@ -56,7 +55,6 @@ import { import { NoMode, ConcurrentMode, - DebugTracingMode, StrictEffectsMode, StrictLegacyMode, NoStrictPassiveEffectsMode, @@ -125,7 +123,6 @@ import { getIsHydrating, tryToClaimNextHydratableFormMarkerInstance, } from './ReactFiberHydrationContext'; -import {logStateUpdateScheduled} from './DebugTracing'; import { markStateUpdateScheduled, setIsStrictModeForDevtools, @@ -3928,15 +3925,6 @@ function entangleTransitionUpdate<S, A>( } function markUpdateInDevTools<A>(fiber: Fiber, lane: Lane, action: A): void { - if (__DEV__) { - if (enableDebugTracing) { - if (fiber.mode & DebugTracingMode) { - const name = getComponentNameFromFiber(fiber) || 'Unknown'; - logStateUpdateScheduled(name, lane, action); - } - } - } - if (enableSchedulingProfiler) { markStateUpdateScheduled(fiber, lane); } diff --git a/packages/react-reconciler/src/ReactFiberThrow.js b/packages/react-reconciler/src/ReactFiberThrow.js index e901486c1d448..a4bdb84e6c4e7 100644 --- a/packages/react-reconciler/src/ReactFiberThrow.js +++ b/packages/react-reconciler/src/ReactFiberThrow.js @@ -37,9 +37,8 @@ import { ForceClientRender, ScheduleRetry, } from './ReactFiberFlags'; -import {NoMode, ConcurrentMode, DebugTracingMode} from './ReactTypeOfMode'; +import {NoMode, ConcurrentMode} from './ReactTypeOfMode'; import { - enableDebugTracing, enableLazyContextPropagation, enableUpdaterTracking, enablePostpone, @@ -70,7 +69,6 @@ import { } from './ReactFiberWorkLoop'; import {propagateParentContextChangesToDeferredTree} from './ReactFiberNewContext'; import {logUncaughtError, logCaughtError} from './ReactFiberErrorLogger'; -import {logComponentSuspended} from './DebugTracing'; import {isDevToolsPresent} from './ReactFiberDevToolsHook'; import { SyncLane, @@ -399,15 +397,6 @@ function throwException( } } - if (__DEV__) { - if (enableDebugTracing) { - if (sourceFiber.mode & DebugTracingMode) { - const name = getComponentNameFromFiber(sourceFiber) || 'Unknown'; - logComponentSuspended(name, wakeable); - } - } - } - // Mark the nearest Suspense boundary to switch to rendering a fallback. const suspenseBoundary = getSuspenseHandler(); if (suspenseBoundary !== null) { diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.js b/packages/react-reconciler/src/ReactFiberWorkLoop.js index dd637d687da4f..f2fc387d7e27c 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.js @@ -29,7 +29,6 @@ import { enableProfilerTimer, enableProfilerCommitHooks, enableProfilerNestedUpdatePhase, - enableDebugTracing, enableSchedulingProfiler, enableUpdaterTracking, enableCache, @@ -55,16 +54,6 @@ import { NormalPriority as NormalSchedulerPriority, IdlePriority as IdleSchedulerPriority, } from './Scheduler'; -import { - logCommitStarted, - logCommitStopped, - logLayoutEffectsStarted, - logLayoutEffectsStopped, - logPassiveEffectsStarted, - logPassiveEffectsStopped, - logRenderStarted, - logRenderStopped, -} from './DebugTracing'; import { logBlockingStart, logTransitionStart, @@ -2260,12 +2249,6 @@ function renderRootSync( prepareFreshStack(root, lanes); } - if (__DEV__) { - if (enableDebugTracing) { - logRenderStarted(lanes); - } - } - if (enableSchedulingProfiler) { markRenderStarted(lanes); } @@ -2360,12 +2343,6 @@ function renderRootSync( popDispatcher(prevDispatcher); popAsyncDispatcher(prevAsyncDispatcher); - if (__DEV__) { - if (enableDebugTracing) { - logRenderStopped(); - } - } - if (enableSchedulingProfiler) { markRenderStopped(); } @@ -2433,12 +2410,6 @@ function renderRootConcurrent(root: FiberRoot, lanes: Lanes) { workInProgressRootIsPrerendering = checkIfRootIsPrerendering(root, lanes); } - if (__DEV__) { - if (enableDebugTracing) { - logRenderStarted(lanes); - } - } - if (enableSchedulingProfiler) { markRenderStarted(lanes); } @@ -2651,12 +2622,6 @@ function renderRootConcurrent(root: FiberRoot, lanes: Lanes) { popAsyncDispatcher(prevAsyncDispatcher); executionContext = prevExecutionContext; - if (__DEV__) { - if (enableDebugTracing) { - logRenderStopped(); - } - } - // Check if the tree has completed. if (workInProgress !== null) { // Still work remaining. @@ -3223,27 +3188,14 @@ function commitRootImpl( } } - if (__DEV__) { - if (enableDebugTracing) { - logCommitStarted(lanes); - } - } - if (enableSchedulingProfiler) { markCommitStarted(lanes); } if (finishedWork === null) { - if (__DEV__) { - if (enableDebugTracing) { - logCommitStopped(); - } - } - if (enableSchedulingProfiler) { markCommitStopped(); } - return null; } else { if (__DEV__) { @@ -3409,21 +3361,10 @@ function commitRootImpl( // The next phase is the layout phase, where we call effects that read // the host tree after it's been mutated. The idiomatic use case for this is // layout, but class component lifecycles also fire here for legacy reasons. - if (__DEV__) { - if (enableDebugTracing) { - logLayoutEffectsStarted(lanes); - } - } if (enableSchedulingProfiler) { markLayoutEffectsStarted(lanes); } commitLayoutEffects(finishedWork, root, lanes); - if (__DEV__) { - if (enableDebugTracing) { - logLayoutEffectsStopped(); - } - } - if (enableSchedulingProfiler) { markLayoutEffectsStopped(); } @@ -3589,12 +3530,6 @@ function commitRootImpl( // If layout work was scheduled, flush it now. flushSyncWorkOnAllRoots(); - if (__DEV__) { - if (enableDebugTracing) { - logCommitStopped(); - } - } - if (enableSchedulingProfiler) { markCommitStopped(); } @@ -3735,10 +3670,6 @@ function flushPassiveEffectsImpl(wasDelayedCommit: void | boolean) { if (__DEV__) { isFlushingPassiveEffects = true; didScheduleUpdateDuringPassiveEffects = false; - - if (enableDebugTracing) { - logPassiveEffectsStarted(lanes); - } } let passiveEffectStartTime = 0; @@ -3767,12 +3698,6 @@ function flushPassiveEffectsImpl(wasDelayedCommit: void | boolean) { pendingPassiveEffectsRenderEndTime, ); - if (__DEV__) { - if (enableDebugTracing) { - logPassiveEffectsStopped(); - } - } - if (enableSchedulingProfiler) { markPassiveEffectsStopped(); } diff --git a/packages/react-reconciler/src/ReactTypeOfMode.js b/packages/react-reconciler/src/ReactTypeOfMode.js index 7542c8eff528c..fd67d9979f8bb 100644 --- a/packages/react-reconciler/src/ReactTypeOfMode.js +++ b/packages/react-reconciler/src/ReactTypeOfMode.js @@ -12,8 +12,8 @@ export type TypeOfMode = number; export const NoMode = /* */ 0b0000000; // TODO: Remove ConcurrentMode by reading from the root tag instead export const ConcurrentMode = /* */ 0b0000001; -export const ProfileMode = /* */ 0b0000010; -export const DebugTracingMode = /* */ 0b0000100; +export const ProfileMode = /* */ 0b0000010; +//export const DebugTracingMode = /* */ 0b0000100; // Removed export const StrictLegacyMode = /* */ 0b0001000; export const StrictEffectsMode = /* */ 0b0010000; export const NoStrictPassiveEffectsMode = /* */ 0b1000000; diff --git a/packages/react-reconciler/src/__tests__/DebugTracing-test.internal.js b/packages/react-reconciler/src/__tests__/DebugTracing-test.internal.js deleted file mode 100644 index ba0451c4c5f0b..0000000000000 --- a/packages/react-reconciler/src/__tests__/DebugTracing-test.internal.js +++ /dev/null @@ -1,440 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @emails react-core - */ - -'use strict'; - -describe('DebugTracing', () => { - let React; - let ReactNoop; - let waitForPaint; - let waitForAll; - let act; - - let logs; - - const SYNC_LANE_STRING = '0b0000000000000000000000000000010'; - const DEFAULT_LANE_STRING = '0b0000000000000000000000000100000'; - const RETRY_LANE_STRING = '0b0000000010000000000000000000000'; - - global.IS_REACT_ACT_ENVIRONMENT = true; - - beforeEach(() => { - jest.resetModules(); - - React = require('react'); - ReactNoop = require('react-noop-renderer'); - const InternalTestUtils = require('internal-test-utils'); - waitForPaint = InternalTestUtils.waitForPaint; - waitForAll = InternalTestUtils.waitForAll; - act = InternalTestUtils.act; - - logs = []; - - const groups = []; - - spyOnDevAndProd(console, 'log').mockImplementation(message => { - logs.push(`log: ${message.replace(/%c/g, '')}`); - }); - spyOnDevAndProd(console, 'group').mockImplementation(message => { - logs.push(`group: ${message.replace(/%c/g, '')}`); - groups.push(message); - }); - spyOnDevAndProd(console, 'groupEnd').mockImplementation(() => { - const message = groups.pop(); - logs.push(`groupEnd: ${message.replace(/%c/g, '')}`); - }); - }); - - // @gate enableDebugTracing - it('should not log anything for sync render without suspends or state updates', async () => { - await act(() => { - ReactNoop.render( - <React.unstable_DebugTracingMode> - <div /> - </React.unstable_DebugTracingMode>, - ); - }); - - expect(logs).toEqual([]); - }); - - // @gate experimental && enableDebugTracing - it('should not log anything for concurrent render without suspends or state updates', async () => { - await act(() => - ReactNoop.render( - <React.unstable_DebugTracingMode> - <div /> - </React.unstable_DebugTracingMode>, - ), - ); - expect(logs).toEqual([]); - }); - - // @gate experimental && build === 'development' && enableDebugTracing && !disableLegacyMode - it('should log sync render with suspense, legacy', async () => { - let resolveFakeSuspensePromise; - let didResolve = false; - const fakeSuspensePromise = new Promise(resolve => { - resolveFakeSuspensePromise = () => { - didResolve = true; - resolve(); - }; - }); - - function Example() { - if (!didResolve) { - throw fakeSuspensePromise; - } - return null; - } - - ReactNoop.renderLegacySyncRoot( - <React.unstable_DebugTracingMode> - <React.Suspense fallback={null}> - <Example /> - </React.Suspense> - </React.unstable_DebugTracingMode>, - ); - - expect(logs).toEqual([ - `group: ⚛ render (${SYNC_LANE_STRING})`, - 'log: ⚛ Example suspended', - `groupEnd: ⚛ render (${SYNC_LANE_STRING})`, - ]); - - logs.splice(0); - - resolveFakeSuspensePromise(); - await waitForAll([]); - - expect(logs).toEqual(['log: ⚛ Example resolved']); - }); - - // @gate experimental && build === 'development' && enableDebugTracing && enableCPUSuspense && !disableLegacyMode - it('should log sync render with CPU suspense, legacy', async () => { - function Example() { - console.log('<Example/>'); - return null; - } - - function Wrapper({children}) { - console.log('<Wrapper/>'); - return children; - } - - ReactNoop.renderLegacySyncRoot( - <React.unstable_DebugTracingMode> - <Wrapper> - <React.Suspense fallback={null} unstable_expectedLoadTime={1}> - <Example /> - </React.Suspense> - </Wrapper> - </React.unstable_DebugTracingMode>, - ); - - expect(logs).toEqual([ - `group: ⚛ render (${SYNC_LANE_STRING})`, - 'log: <Wrapper/>', - `groupEnd: ⚛ render (${SYNC_LANE_STRING})`, - ]); - - logs.splice(0); - - await waitForPaint([]); - - expect(logs).toEqual([ - `group: ⚛ render (${RETRY_LANE_STRING})`, - 'log: <Example/>', - `groupEnd: ⚛ render (${RETRY_LANE_STRING})`, - ]); - }); - - // @gate experimental && build === 'development' && enableDebugTracing - it('should log concurrent render with suspense', async () => { - let isResolved = false; - let resolveFakeSuspensePromise; - const fakeSuspensePromise = new Promise(resolve => { - resolveFakeSuspensePromise = () => { - resolve(); - isResolved = true; - }; - }); - - function Example() { - if (!isResolved) { - throw fakeSuspensePromise; - } - return null; - } - - await act(() => - ReactNoop.render( - <React.unstable_DebugTracingMode> - <React.Suspense fallback={null}> - <Example /> - </React.Suspense> - </React.unstable_DebugTracingMode>, - ), - ); - - expect(logs).toEqual([ - `group: ⚛ render (${DEFAULT_LANE_STRING})`, - 'log: ⚛ Example suspended', - `groupEnd: ⚛ render (${DEFAULT_LANE_STRING})`, - - ...(gate('enableSiblingPrerendering') - ? [ - `group: ⚛ render (${RETRY_LANE_STRING})`, - 'log: ⚛ Example suspended', - `groupEnd: ⚛ render (${RETRY_LANE_STRING})`, - ] - : []), - ]); - - logs.splice(0); - - await act(async () => await resolveFakeSuspensePromise()); - expect(logs).toEqual([ - 'log: ⚛ Example resolved', - - ...(gate('enableSiblingPrerendering') - ? ['log: ⚛ Example resolved'] - : []), - ]); - }); - - // @gate experimental && build === 'development' && enableDebugTracing && enableCPUSuspense - it('should log concurrent render with CPU suspense', async () => { - function Example() { - console.log('<Example/>'); - return null; - } - - function Wrapper({children}) { - console.log('<Wrapper/>'); - return children; - } - - await act(() => - ReactNoop.render( - <React.unstable_DebugTracingMode> - <Wrapper> - <React.Suspense fallback={null} unstable_expectedLoadTime={1}> - <Example /> - </React.Suspense> - </Wrapper> - </React.unstable_DebugTracingMode>, - ), - ); - - expect(logs).toEqual([ - `group: ⚛ render (${DEFAULT_LANE_STRING})`, - 'log: <Wrapper/>', - `groupEnd: ⚛ render (${DEFAULT_LANE_STRING})`, - `group: ⚛ render (${RETRY_LANE_STRING})`, - 'log: <Example/>', - `groupEnd: ⚛ render (${RETRY_LANE_STRING})`, - ]); - }); - - // @gate experimental && build === 'development' && enableDebugTracing - it('should log cascading class component updates', async () => { - class Example extends React.Component { - state = {didMount: false}; - componentDidMount() { - this.setState({didMount: true}); - } - render() { - return null; - } - } - - await act(() => - ReactNoop.render( - <React.unstable_DebugTracingMode> - <Example /> - </React.unstable_DebugTracingMode>, - ), - ); - - expect(logs).toEqual([ - `group: ⚛ commit (${DEFAULT_LANE_STRING})`, - `group: ⚛ layout effects (${DEFAULT_LANE_STRING})`, - `log: ⚛ Example updated state (${SYNC_LANE_STRING})`, - `groupEnd: ⚛ layout effects (${DEFAULT_LANE_STRING})`, - `groupEnd: ⚛ commit (${DEFAULT_LANE_STRING})`, - ]); - }); - - // @gate experimental && build === 'development' && enableDebugTracing - it('should log render phase state updates for class component', async () => { - class Example extends React.Component { - state = {didRender: false}; - render() { - if (this.state.didRender === false) { - this.setState({didRender: true}); - } - return null; - } - } - - await expect(async () => { - await act(() => { - ReactNoop.render( - <React.unstable_DebugTracingMode> - <Example /> - </React.unstable_DebugTracingMode>, - ); - }); - }).toErrorDev( - 'Cannot update during an existing state transition (such as within `render`). Render methods should be a pure function of props and state.', - ); - - expect(logs).toEqual([ - `group: ⚛ render (${DEFAULT_LANE_STRING})`, - `log: ⚛ Example updated state (${DEFAULT_LANE_STRING})`, - `groupEnd: ⚛ render (${DEFAULT_LANE_STRING})`, - ]); - }); - - // @gate experimental && build === 'development' && enableDebugTracing - it('should log cascading layout updates', async () => { - function Example() { - const [didMount, setDidMount] = React.useState(false); - React.useLayoutEffect(() => { - setDidMount(true); - }, []); - return didMount; - } - - await act(() => - ReactNoop.render( - <React.unstable_DebugTracingMode> - <Example /> - </React.unstable_DebugTracingMode>, - ), - ); - - expect(logs).toEqual([ - `group: ⚛ commit (${DEFAULT_LANE_STRING})`, - `group: ⚛ layout effects (${DEFAULT_LANE_STRING})`, - `log: ⚛ Example updated state (${SYNC_LANE_STRING})`, - `groupEnd: ⚛ layout effects (${DEFAULT_LANE_STRING})`, - `groupEnd: ⚛ commit (${DEFAULT_LANE_STRING})`, - ]); - }); - - // @gate experimental && build === 'development' && enableDebugTracing - it('should log cascading passive updates', async () => { - function Example() { - const [didMount, setDidMount] = React.useState(false); - React.useEffect(() => { - setDidMount(true); - }, []); - return didMount; - } - - await act(() => { - ReactNoop.render( - <React.unstable_DebugTracingMode> - <Example /> - </React.unstable_DebugTracingMode>, - ); - }); - expect(logs).toEqual([ - `group: ⚛ passive effects (${DEFAULT_LANE_STRING})`, - `log: ⚛ Example updated state (${DEFAULT_LANE_STRING})`, - `groupEnd: ⚛ passive effects (${DEFAULT_LANE_STRING})`, - ]); - }); - - // @gate experimental && build === 'development' && enableDebugTracing - it('should log render phase updates', async () => { - function Example() { - const [didRender, setDidRender] = React.useState(false); - if (!didRender) { - setDidRender(true); - } - return didRender; - } - - await act(() => { - ReactNoop.render( - <React.unstable_DebugTracingMode> - <Example /> - </React.unstable_DebugTracingMode>, - ); - }); - - expect(logs).toEqual([ - `group: ⚛ render (${DEFAULT_LANE_STRING})`, - `log: ⚛ Example updated state (${DEFAULT_LANE_STRING})`, - `groupEnd: ⚛ render (${DEFAULT_LANE_STRING})`, - ]); - }); - - // @gate experimental && build === 'development' && enableDebugTracing - it('should log when user code logs', async () => { - function Example() { - console.log('Hello from user code'); - return null; - } - - await act(() => - ReactNoop.render( - <React.unstable_DebugTracingMode> - <Example /> - </React.unstable_DebugTracingMode>, - ), - ); - - expect(logs).toEqual([ - `group: ⚛ render (${DEFAULT_LANE_STRING})`, - 'log: Hello from user code', - `groupEnd: ⚛ render (${DEFAULT_LANE_STRING})`, - ]); - }); - - // @gate experimental && enableDebugTracing - it('should not log anything outside of a unstable_DebugTracingMode subtree', async () => { - function ExampleThatCascades() { - const [didMount, setDidMount] = React.useState(false); - React.useLayoutEffect(() => { - setDidMount(true); - }, []); - return didMount; - } - - const fakeSuspensePromise = {then() {}}; - - function ExampleThatSuspends() { - throw fakeSuspensePromise; - } - - function Example() { - return null; - } - - await act(() => - ReactNoop.render( - <React.Fragment> - <ExampleThatCascades /> - <React.Suspense fallback={null}> - <ExampleThatSuspends /> - </React.Suspense> - <React.unstable_DebugTracingMode> - <Example /> - </React.unstable_DebugTracingMode> - </React.Fragment>, - ), - ); - - expect(logs).toEqual([]); - }); -}); diff --git a/packages/react-server/src/ReactFizzServer.js b/packages/react-server/src/ReactFizzServer.js index ad6721ec60796..f18b624a11b9c 100644 --- a/packages/react-server/src/ReactFizzServer.js +++ b/packages/react-server/src/ReactFizzServer.js @@ -134,7 +134,6 @@ import { REACT_LAZY_TYPE, REACT_SUSPENSE_TYPE, REACT_LEGACY_HIDDEN_TYPE, - REACT_DEBUG_TRACING_MODE_TYPE, REACT_STRICT_MODE_TYPE, REACT_PROFILER_TYPE, REACT_SUSPENSE_LIST_TYPE, @@ -2136,7 +2135,6 @@ function renderElement( // www build. As a migration step, we could add a special prop to Offscreen // that simulates the old behavior (no hiding, no change to effects). case REACT_LEGACY_HIDDEN_TYPE: - case REACT_DEBUG_TRACING_MODE_TYPE: case REACT_STRICT_MODE_TYPE: case REACT_PROFILER_TYPE: case REACT_FRAGMENT_TYPE: { diff --git a/packages/react/index.development.js b/packages/react/index.development.js index 8472789ba36cd..809e940f070ba 100644 --- a/packages/react/index.development.js +++ b/packages/react/index.development.js @@ -45,7 +45,6 @@ export { memo, cache, startTransition, - unstable_DebugTracingMode, unstable_LegacyHidden, unstable_Activity, unstable_Scope, diff --git a/packages/react/index.experimental.development.js b/packages/react/index.experimental.development.js index d41774e1feedc..cc753cd9c5ed8 100644 --- a/packages/react/index.experimental.development.js +++ b/packages/react/index.experimental.development.js @@ -28,7 +28,6 @@ export { memo, cache, startTransition, - unstable_DebugTracingMode, unstable_Activity, unstable_postpone, unstable_getCacheForType, diff --git a/packages/react/index.experimental.js b/packages/react/index.experimental.js index ae98e3b91f19c..ab97c58caa5d2 100644 --- a/packages/react/index.experimental.js +++ b/packages/react/index.experimental.js @@ -28,7 +28,6 @@ export { memo, cache, startTransition, - unstable_DebugTracingMode, unstable_Activity, unstable_postpone, unstable_getCacheForType, diff --git a/packages/react/index.fb.js b/packages/react/index.fb.js index 4764281481dbb..8cded91b9854d 100644 --- a/packages/react/index.fb.js +++ b/packages/react/index.fb.js @@ -33,7 +33,6 @@ export { StrictMode, Suspense, unstable_Activity, - unstable_DebugTracingMode, unstable_getCacheForType, unstable_LegacyHidden, unstable_Scope, diff --git a/packages/react/index.js b/packages/react/index.js index 2edb0a2c1de09..3e087509ccb06 100644 --- a/packages/react/index.js +++ b/packages/react/index.js @@ -46,7 +46,6 @@ export { memo, cache, startTransition, - unstable_DebugTracingMode, unstable_LegacyHidden, unstable_Activity, unstable_Scope, diff --git a/packages/react/src/ReactClient.js b/packages/react/src/ReactClient.js index 478d9e026aae8..90ce18b133a34 100644 --- a/packages/react/src/ReactClient.js +++ b/packages/react/src/ReactClient.js @@ -10,7 +10,6 @@ import ReactVersion from 'shared/ReactVersion'; import { REACT_FRAGMENT_TYPE, - REACT_DEBUG_TRACING_MODE_TYPE, REACT_PROFILER_TYPE, REACT_STRICT_MODE_TYPE, REACT_SUSPENSE_TYPE, @@ -105,7 +104,6 @@ export { REACT_FRAGMENT_TYPE as Fragment, REACT_PROFILER_TYPE as Profiler, REACT_STRICT_MODE_TYPE as StrictMode, - REACT_DEBUG_TRACING_MODE_TYPE as unstable_DebugTracingMode, REACT_SUSPENSE_TYPE as Suspense, createElement, cloneElement, diff --git a/packages/react/src/ReactServer.experimental.development.js b/packages/react/src/ReactServer.experimental.development.js index ccf423d79ecc7..82aff0d615fb4 100644 --- a/packages/react/src/ReactServer.experimental.development.js +++ b/packages/react/src/ReactServer.experimental.development.js @@ -15,7 +15,6 @@ import { REACT_PROFILER_TYPE, REACT_STRICT_MODE_TYPE, REACT_SUSPENSE_TYPE, - REACT_DEBUG_TRACING_MODE_TYPE, } from 'shared/ReactSymbols'; import { cloneElement, @@ -71,7 +70,6 @@ export { memo, cache, startTransition, - REACT_DEBUG_TRACING_MODE_TYPE as unstable_DebugTracingMode, REACT_SUSPENSE_TYPE as unstable_SuspenseList, getCacheForType as unstable_getCacheForType, postpone as unstable_postpone, diff --git a/packages/react/src/ReactServer.experimental.js b/packages/react/src/ReactServer.experimental.js index 97b548f82d6b6..e77e249930e21 100644 --- a/packages/react/src/ReactServer.experimental.js +++ b/packages/react/src/ReactServer.experimental.js @@ -15,7 +15,6 @@ import { REACT_PROFILER_TYPE, REACT_STRICT_MODE_TYPE, REACT_SUSPENSE_TYPE, - REACT_DEBUG_TRACING_MODE_TYPE, } from 'shared/ReactSymbols'; import { cloneElement, @@ -70,7 +69,6 @@ export { memo, cache, startTransition, - REACT_DEBUG_TRACING_MODE_TYPE as unstable_DebugTracingMode, REACT_SUSPENSE_TYPE as unstable_SuspenseList, getCacheForType as unstable_getCacheForType, postpone as unstable_postpone, diff --git a/packages/shared/ReactFeatureFlags.js b/packages/shared/ReactFeatureFlags.js index afac564cad28a..5a1220d7f24c9 100644 --- a/packages/shared/ReactFeatureFlags.js +++ b/packages/shared/ReactFeatureFlags.js @@ -267,11 +267,6 @@ export const enableProfilerCommitHooks = __PROFILE__; // Phase param passed to onRender callback differentiates between an "update" and a "cascading-update". export const enableProfilerNestedUpdatePhase = __PROFILE__; -// Adds verbose console logging for e.g. state updates, suspense, and work loop -// stuff. Intended to enable React core members to more easily debug scheduling -// issues in DEV builds. -export const enableDebugTracing = false; - export const enableAsyncDebugInfo = __EXPERIMENTAL__; // Track which Fiber(s) schedule render work. diff --git a/packages/shared/ReactSymbols.js b/packages/shared/ReactSymbols.js index 002870896f00f..0d1208b21af0c 100644 --- a/packages/shared/ReactSymbols.js +++ b/packages/shared/ReactSymbols.js @@ -33,9 +33,6 @@ export const REACT_SUSPENSE_LIST_TYPE: symbol = Symbol.for( export const REACT_MEMO_TYPE: symbol = Symbol.for('react.memo'); export const REACT_LAZY_TYPE: symbol = Symbol.for('react.lazy'); export const REACT_SCOPE_TYPE: symbol = Symbol.for('react.scope'); -export const REACT_DEBUG_TRACING_MODE_TYPE: symbol = Symbol.for( - 'react.debug_trace_mode', -); export const REACT_OFFSCREEN_TYPE: symbol = Symbol.for('react.offscreen'); export const REACT_LEGACY_HIDDEN_TYPE: symbol = Symbol.for( 'react.legacy_hidden', diff --git a/packages/shared/forks/ReactFeatureFlags.native-fb.js b/packages/shared/forks/ReactFeatureFlags.native-fb.js index 4d89fa091061a..0a9d33675daaf 100644 --- a/packages/shared/forks/ReactFeatureFlags.native-fb.js +++ b/packages/shared/forks/ReactFeatureFlags.native-fb.js @@ -47,7 +47,6 @@ export const enableAsyncIterableChildren = false; export const enableCache = true; export const enableCPUSuspense = true; export const enableCreateEventHandleAPI = false; -export const enableDebugTracing = false; export const enableDeferRootSchedulingToMicrotask = true; export const enableDO_NOT_USE_disableStrictPassiveEffect = false; export const enableMoveBefore = true; diff --git a/packages/shared/forks/ReactFeatureFlags.native-oss.js b/packages/shared/forks/ReactFeatureFlags.native-oss.js index 0407f01910b75..52b9a67f77135 100644 --- a/packages/shared/forks/ReactFeatureFlags.native-oss.js +++ b/packages/shared/forks/ReactFeatureFlags.native-oss.js @@ -34,7 +34,6 @@ export const enableAsyncIterableChildren = false; export const enableCache = true; export const enableCPUSuspense = false; export const enableCreateEventHandleAPI = false; -export const enableDebugTracing = false; export const enableDeferRootSchedulingToMicrotask = true; export const enableDO_NOT_USE_disableStrictPassiveEffect = false; export const enableFabricCompleteRootInCommitPhase = false; diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.js index b83cb9a99fc3d..201d659f657d6 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.js @@ -11,7 +11,6 @@ import typeof * as FeatureFlagsType from 'shared/ReactFeatureFlags'; import typeof * as ExportsType from './ReactFeatureFlags.test-renderer'; export const debugRenderPhaseSideEffectsForStrictMode = false; -export const enableDebugTracing = false; export const enableAsyncDebugInfo = false; export const enableSchedulingProfiler = false; export const enableProfilerTimer = __PROFILE__; diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js index 115117685aeb4..1b311a3ecfe66 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js @@ -26,7 +26,6 @@ export const enableAsyncIterableChildren = false; export const enableCache = true; export const enableCPUSuspense = true; export const enableCreateEventHandleAPI = false; -export const enableDebugTracing = false; export const enableDeferRootSchedulingToMicrotask = true; export const enableDO_NOT_USE_disableStrictPassiveEffect = false; export const enableMoveBefore = false; diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js index cad15eecc8c11..b74d89a4b9cdb 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js @@ -11,7 +11,6 @@ import typeof * as FeatureFlagsType from 'shared/ReactFeatureFlags'; import typeof * as ExportsType from './ReactFeatureFlags.test-renderer.www'; export const debugRenderPhaseSideEffectsForStrictMode = false; -export const enableDebugTracing = false; export const enableAsyncDebugInfo = false; export const enableSchedulingProfiler = false; export const enableProfilerTimer = __PROFILE__; diff --git a/packages/shared/forks/ReactFeatureFlags.www-dynamic.js b/packages/shared/forks/ReactFeatureFlags.www-dynamic.js index 7c28c76fb1392..69da420d0422c 100644 --- a/packages/shared/forks/ReactFeatureFlags.www-dynamic.js +++ b/packages/shared/forks/ReactFeatureFlags.www-dynamic.js @@ -32,12 +32,6 @@ export const retryLaneExpirationMs = 5000; export const syncLaneExpirationMs = 250; export const transitionLaneExpirationMs = 5000; -// Enable this flag to help with concurrent mode debugging. -// It logs information to the console about React scheduling, rendering, and commit phases. -// -// NOTE: This feature will only work in DEV mode; all callsites are wrapped with __DEV__. -export const enableDebugTracing = __EXPERIMENTAL__; - export const enableSchedulingProfiler = __VARIANT__; export const enableInfiniteRenderLoopDetection = __VARIANT__; diff --git a/packages/shared/forks/ReactFeatureFlags.www.js b/packages/shared/forks/ReactFeatureFlags.www.js index eea2ba4230f50..e9ec691f0817a 100644 --- a/packages/shared/forks/ReactFeatureFlags.www.js +++ b/packages/shared/forks/ReactFeatureFlags.www.js @@ -19,7 +19,6 @@ export const { disableDefaultPropsExceptForClasses, disableLegacyContextForFunctionComponents, disableSchedulerTimeoutInWorkLoop, - enableDebugTracing, enableDeferRootSchedulingToMicrotask, enableDO_NOT_USE_disableStrictPassiveEffect, enableHiddenSubtreeInsertionEffectCleanup, diff --git a/packages/shared/isValidElementType.js b/packages/shared/isValidElementType.js index 6d5397be33e70..346992b118865 100644 --- a/packages/shared/isValidElementType.js +++ b/packages/shared/isValidElementType.js @@ -14,7 +14,6 @@ import { REACT_FORWARD_REF_TYPE, REACT_FRAGMENT_TYPE, REACT_PROFILER_TYPE, - REACT_DEBUG_TRACING_MODE_TYPE, REACT_STRICT_MODE_TYPE, REACT_SUSPENSE_TYPE, REACT_SUSPENSE_LIST_TYPE, @@ -28,7 +27,6 @@ import { import { enableScopeAPI, enableTransitionTracing, - enableDebugTracing, enableLegacyHidden, enableRenderableContext, } from './ReactFeatureFlags'; @@ -46,7 +44,6 @@ export default function isValidElementType(type: mixed): boolean { if ( type === REACT_FRAGMENT_TYPE || type === REACT_PROFILER_TYPE || - (enableDebugTracing && type === REACT_DEBUG_TRACING_MODE_TYPE) || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE ||