Skip to content

Commit

Permalink
Include the owner of a Server Component which must also be another Se…
Browse files Browse the repository at this point in the history
…rver Component
  • Loading branch information
sebmarkbage committed Apr 5, 2024
1 parent d290097 commit b44d302
Show file tree
Hide file tree
Showing 6 changed files with 25 additions and 11 deletions.
17 changes: 10 additions & 7 deletions packages/react-client/src/__tests__/ReactFlight-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ describe('ReactFlight', () => {
const rootModel = await ReactNoopFlightClient.read(transport);
const greeting = rootModel.greeting;
expect(greeting._debugInfo).toEqual(
__DEV__ ? [{name: 'Greeting', env: 'Server'}] : undefined,
__DEV__ ? [{name: 'Greeting', env: 'Server', owner: null}] : undefined,
);
ReactNoop.render(greeting);
});
Expand All @@ -241,7 +241,7 @@ describe('ReactFlight', () => {
await act(async () => {
const promise = ReactNoopFlightClient.read(transport);
expect(promise._debugInfo).toEqual(
__DEV__ ? [{name: 'Greeting', env: 'Server'}] : undefined,
__DEV__ ? [{name: 'Greeting', env: 'Server', owner: null}] : undefined,
);
ReactNoop.render(await promise);
});
Expand Down Expand Up @@ -2072,19 +2072,21 @@ describe('ReactFlight', () => {
await act(async () => {
const promise = ReactNoopFlightClient.read(transport);
expect(promise._debugInfo).toEqual(
__DEV__ ? [{name: 'ServerComponent', env: 'Server'}] : undefined,
__DEV__
? [{name: 'ServerComponent', env: 'Server', owner: null}]
: undefined,
);
const result = await promise;
const thirdPartyChildren = await result.props.children[1];
// We expect the debug info to be transferred from the inner stream to the outer.
expect(thirdPartyChildren[0]._debugInfo).toEqual(
__DEV__
? [{name: 'ThirdPartyComponent', env: 'third-party'}]
? [{name: 'ThirdPartyComponent', env: 'third-party', owner: null}]
: undefined,
);
expect(thirdPartyChildren[1]._debugInfo).toEqual(
__DEV__
? [{name: 'ThirdPartyLazyComponent', env: 'third-party'}]
? [{name: 'ThirdPartyLazyComponent', env: 'third-party', owner: null}]
: undefined,
);
ReactNoop.render(result);
Expand Down Expand Up @@ -2172,9 +2174,10 @@ describe('ReactFlight', () => {
// We've rendered down to the span.
expect(greeting.type).toBe('span');
if (__DEV__) {
const greetInfo = {name: 'Greeting', env: 'Server', owner: null};
expect(greeting._debugInfo).toEqual([
{name: 'Greeting', env: 'Server'},
{name: 'Container', env: 'Server'},
greetInfo,
{name: 'Container', env: 'Server', owner: greetInfo},
]);
// The owner that created the span was the outer server component.
// We expect the debug info to be referentially equal to the owner.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ describe('component stack', () => {
{
name: 'ServerComponent',
env: 'Server',
owner: null,
},
];
const Parent = () => ChildPromise;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ describe('ReactFlightDOMEdge', () => {
<ServerComponent recurse={20} />,
);
const serializedContent = await readResult(stream);
const expectedDebugInfoSize = __DEV__ ? 42 * 20 : 0;
const expectedDebugInfoSize = __DEV__ ? 64 * 20 : 0;
expect(serializedContent.length).toBeLessThan(150 + expectedDebugInfoSize);
});

Expand Down
13 changes: 11 additions & 2 deletions packages/react-server/src/ReactFlightServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,7 @@ function renderFunctionComponent<Props>(
key: null | string,
Component: (p: Props, arg: void) => any,
props: Props,
owner: null | ReactComponentInfo,
): ReactJSONValue {
// Reset the task's thenable state before continuing, so that if a later
// component suspends we can reuse the same task object. If the same
Expand Down Expand Up @@ -624,6 +625,7 @@ function renderFunctionComponent<Props>(
componentDebugInfo = {
name: componentName,
env: request.environmentName,
owner: owner,
};
// We outline this model eagerly so that we can refer to by reference as an owner.
// If we had a smarter way to dedupe we might not have to do this if there ends up
Expand Down Expand Up @@ -832,7 +834,7 @@ function renderElement(
return renderClientElement(task, type, key, props, owner);
}
// This is a Server Component.
return renderFunctionComponent(request, task, key, type, props);
return renderFunctionComponent(request, task, key, type, props, owner);
} else if (typeof type === 'string') {
// This is a host element. E.g. HTML.
return renderClientElement(task, type, key, props, owner);
Expand Down Expand Up @@ -878,7 +880,14 @@ function renderElement(
);
}
case REACT_FORWARD_REF_TYPE: {
return renderFunctionComponent(request, task, key, type.render, props);
return renderFunctionComponent(
request,
task,
key,
type.render,
props,
owner,
);
}
case REACT_MEMO_TYPE: {
return renderElement(request, task, type.type, key, ref, props, owner);
Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/__tests__/ReactFetch-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ describe('ReactFetch', () => {
const promise = render(Component);
expect(await promise).toMatchInlineSnapshot(`"GET world []"`);
expect(promise._debugInfo).toEqual(
__DEV__ ? [{name: 'Component', env: 'Server'}] : undefined,
__DEV__ ? [{name: 'Component', env: 'Server', owner: null}] : undefined,
);
expect(fetchCount).toBe(1);
});
Expand Down
1 change: 1 addition & 0 deletions packages/shared/ReactTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ export type Awaited<T> = T extends null | void
export type ReactComponentInfo = {
+name?: string,
+env?: string,
+owner?: null | ReactComponentInfo,
};

export type ReactAsyncInfo = {
Expand Down

0 comments on commit b44d302

Please sign in to comment.