[Flight] Only use debug component info for parent stacks (#34431)

This commit is contained in:
Sebastian "Sebbie" Silbermann 2025-09-09 19:58:02 +02:00 committed by GitHub
parent a9410fb487
commit eec50b17b3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 123 additions and 18 deletions

View File

@ -1794,13 +1794,21 @@ function transferReferencedDebugInfo(
existingDebugInfo.push.apply(existingDebugInfo, referencedDebugInfo);
}
}
// We also add it to the initializing chunk since the resolution of that promise is
// also blocked by these. By adding it to both we can track it even if the array/element
// We also add the debug info to the initializing chunk since the resolution of that promise is
// also blocked by the referenced debug info. By adding it to both we can track it even if the array/element
// is extracted, or if the root is rendered as is.
if (parentChunk !== null) {
const parentDebugInfo = parentChunk._debugInfo;
// $FlowFixMe[method-unbinding]
parentDebugInfo.push.apply(parentDebugInfo, referencedDebugInfo);
for (let i = 0; i < referencedDebugInfo.length; ++i) {
const debugInfoEntry = referencedDebugInfo[i];
if (debugInfoEntry.name != null) {
(debugInfoEntry: ReactComponentInfo);
// We're not transferring Component info since we use Component info
// in Debug info to fill in gaps between Fibers for the parent stack.
} else {
parentDebugInfo.push(debugInfoEntry);
}
}
}
}
}

View File

@ -2960,13 +2960,6 @@ describe('ReactFlight', () => {
{
time: 16,
},
{
env: 'third-party',
key: null,
name: 'ThirdPartyAsyncIterableComponent',
props: {},
stack: ' in Object.<anonymous> (at **)',
},
{
time: 16,
},
@ -2995,13 +2988,6 @@ describe('ReactFlight', () => {
{
time: 19,
},
{
env: 'third-party',
key: null,
name: 'ThirdPartyAsyncIterableComponent',
props: {},
stack: ' in Object.<anonymous> (at **)',
},
{time: 19},
]
: undefined,
@ -3847,4 +3833,115 @@ describe('ReactFlight', () => {
expect(ReactNoop).toMatchRenderedOutput(<div>not using props</div>);
});
// @gate !__DEV__ || enableComponentPerformanceTrack
it('produces correct parent stacks', async () => {
function Container() {
return ReactServer.createElement('div', null);
}
function ContainerParent() {
return ReactServer.createElement(Container, null);
}
function App() {
return ReactServer.createElement(
'main',
null,
ReactServer.createElement(ContainerParent, null),
);
}
const transport = ReactNoopFlightServer.render({
root: ReactServer.createElement(App, null),
});
await act(async () => {
const {root} = await ReactNoopFlightClient.read(transport);
ReactNoop.render(root);
expect(root.type).toBe('main');
if (__DEV__) {
const div = root.props.children;
expect(getDebugInfo(div)).toEqual([
{
time: 14,
},
{
env: 'Server',
key: null,
name: 'ContainerParent',
owner: {
env: 'Server',
key: null,
name: 'App',
props: {},
stack: ' in Object.<anonymous> (at **)',
},
props: {},
stack: ' in App (at **)',
},
{
time: 15,
},
{
env: 'Server',
key: null,
name: 'Container',
owner: {
env: 'Server',
key: null,
name: 'ContainerParent',
owner: {
env: 'Server',
key: null,
name: 'App',
props: {},
stack: ' in Object.<anonymous> (at **)',
},
props: {},
stack: ' in App (at **)',
},
props: {},
stack: ' in ContainerParent (at **)',
},
{
time: 16,
},
]);
expect(getDebugInfo(root)).toEqual([
{
time: 12,
},
{
env: 'Server',
key: null,
name: 'App',
props: {},
stack: ' in Object.<anonymous> (at **)',
},
{
time: 13,
},
{
time: 14,
},
{
time: 15,
},
{
time: 16,
},
]);
} else {
expect(root._debugInfo).toBe(undefined);
expect(root._owner).toBe(undefined);
}
});
expect(ReactNoop).toMatchRenderedOutput(
<main>
<div />
</main>,
);
});
});