Repository: facebook/react
File: packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js (JavaScript)

Code before:
    const container = document.createElement('div');
    const root = ReactDOMClient.createRoot(container);

    await act(() => {
      root.render(<ClientRoot response={response} />);
    });

    const expectedHtml =
      '<svg id="1"><path></path></svg><svg id="2"><path></path></svg>';

    expect(container.innerHTML).toBe(expectedHtml);

    // Render a second time:

    // Assigning the path elements to variables in module scope (here simulated
    // with the test's function scope), and rendering a second time, prevents
    // the owner of the path elements (i.e. Svg1/Svg2) to be deduped. The owner
    // of the path in Svg1 is fully inlined. The owner of the owner of the path
    // in Svg2 is Server, which is deduped and replaced with a reference to the
    // owner of the owner of the path in Svg1. This nested owner is actually
    // Server from the previous render pass, which is kinda broken and libaries
    // probably shouldn't generate code like this. This reference can only be
    // resolved properly if owners are specifically handled when resolving
    // outlined models.

    stream = await serverAct(() =>
      ReactServerDOMServer.renderToReadableStream(<Server />, webpackMap),
    );

    response = ReactServerDOMClient.createFromReadableStream(stream);

    await act(() => {
      root.render(<ClientRoot response={response} />);
    });

    expect(container.innerHTML).toBe(expectedHtml);
  });

  it('should progressively reveal server components', async () => {
    let reportedErrors = [];

    // Client Components

    class ErrorBoundary extends React.Component {
      state = {hasError: false, error: null};
      static getDerivedStateFromError(error) {
        return {
          hasError: true,
          error,
        };
      }

Review comment (suggestion):
The first render pass yields:

```
1:{"name":"Server","env":"Server","key":null,"owner":null}
0:D"$1"
3:{"name":"Svg1","env":"Server","key":null,"owner":"$1"}
2:D"$3"
2:["$","svg",null,{"id":"1","children":[["$","path",null,{},"$3"],["$","path",null,{},"$3"]]},"$3"]
5:{"name":"Svg2","env":"Server","key":null,"owner":"$1"}
4:D"$5"
4:["$","svg",null,{"id":"2","children":["$","path",null,{},"$5"]},"$5"]
0:["$2","$4"]
```

Notice how the owners are fully deduped to their own chunks.

The second render pass yields:

```
1:{"name":"Server","env":"Server","key":null,"owner":null}
0:D"$1"
3:{"name":"Svg1","env":"Server","key":null,"owner":"$1"}
2:D"$3"
2:["$","svg",null,{"id":"1","children":[["$","path",null,{},{"name":"Svg1","env":"Server","key":null,"owner":{"name":"Server","env":"Server","key":null,"owner":null}}],["$","path",null,{},"$2:props:children:0:_owner"]]},"$3"]
5:{"name":"Svg2","env":"Server","key":null,"owner":"$1"}
4:D"$5"
4:["$","svg",null,{"id":"2","children":["$","path",null,{},{"name":"Svg2","env":"Server","key":null,"owner":"$2:props:children:0:_owner:owner"}]},"$5"]
0:["$2","$4"]
```

Notice the `$2:props:children:0:_owner:owner` reference that can now be revolved with the provided fix. Before, the reference was `$2:props:children:0:4:owner` and could not be resolved, leading to the error: `TypeError: Cannot read properties of undefined (reading '$$typeof')` in `getOutlinedModel`.

Code after:

    let response = ReactServerDOMClient.createFromReadableStream(stream);
    const container = document.createElement('div');
    const root = ReactDOMClient.createRoot(container);

    await act(() => {
      root.render(<ClientRoot response={response} />);
    });

    const expectedHtml =
      '<svg id="1"><path></path><path></path></svg><svg id="2"><path></path></svg>';

    expect(container.innerHTML).toBe(expectedHtml);

    // Render a second time:

    // Assigning the path elements to variables in module scope (here simulated
    // with the test's function scope), and rendering a second time, prevents
    // the owner of the path elements (i.e. Svg1/Svg2) to be deduped. The owner
    // of the path in Svg1 is fully inlined. The owner of the owner of the path
    // in Svg2 is Server, which is deduped and replaced with a reference to the
    // owner of the owner of the path in Svg1. This nested owner is actually
    // Server from the previous render pass, which is kinda broken and libraries
    // probably shouldn't generate code like this. This reference can only be
    // resolved properly if owners are specifically handled when resolving
    // outlined models.

    stream = await serverAct(() =>
      ReactServerDOMServer.renderToReadableStream(<Server />, webpackMap),
    );

    response = ReactServerDOMClient.createFromReadableStream(stream);

    await act(() => {
      root.render(<ClientRoot response={response} />);
    });

    expect(container.innerHTML).toBe(expectedHtml);

    if (__DEV__) {
      const resolvedPath1b = await response.value[0].props.children[1]._payload;

      expect(resolvedPath1b._owner).toEqual(
        expect.objectContaining({
          name: 'Svg1',
          env: 'Server',
          key: null,
          owner: expect.objectContaining({
            name: 'Server',
            env: 'Server',
            key: null,