Lazily freeze in case anything in the currently initializing chunk is blocked (#29139)

Fixed #29129.

---------

Co-authored-by: Hendrik Liebau <[email protected]>
This commit is contained in:
Sebastian Markbåge
2024-05-17 13:58:42 -04:00
committed by GitHub
co-authored by Hendrik Liebau
parent 93c934277f
commit 4255ba11ef
3 changed files with 60 additions and 1 deletions
+6 -1
View File
@@ -641,7 +641,12 @@ function createElement(
}
// TODO: We should be freezing the element but currently, we might write into
// _debugInfo later. We could move it into _store which remains mutable.
Object.freeze(element.props);
if (initializingChunkBlockedModel !== null) {
const freeze = Object.freeze.bind(Object, element.props);
initializingChunk.then(freeze, freeze);
} else {
Object.freeze(element.props);
}
}
return element;
}
@@ -198,6 +198,55 @@ describe('ReactFlightDOMBrowser', () => {
});
});
it('should resolve client components (with async chunks) when referenced in props', async () => {
let resolveClientComponentChunk;
const ClientOuter = clientExports(function ClientOuter({
Component,
children,
}) {
return <Component>{children}</Component>;
});
const ClientInner = clientExports(
function ClientInner({children}) {
return <span>{children}</span>;
},
'42',
'/test.js',
new Promise(resolve => (resolveClientComponentChunk = resolve)),
);
function Server() {
return <ClientOuter Component={ClientInner}>Hello, World!</ClientOuter>;
}
const stream = ReactServerDOMServer.renderToReadableStream(
<Server />,
webpackMap,
);
function ClientRoot({response}) {
return use(response);
}
const response = ReactServerDOMClient.createFromReadableStream(stream);
const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);
await act(() => {
root.render(<ClientRoot response={response} />);
});
expect(container.innerHTML).toBe('');
await act(() => {
resolveClientComponentChunk();
});
expect(container.innerHTML).toBe('<span>Hello, World!</span>');
});
it('should progressively reveal server components', async () => {
let reportedErrors = [];
@@ -69,10 +69,15 @@ exports.clientExports = function clientExports(
moduleExports,
chunkId,
chunkFilename,
blockOnChunk,
) {
const chunks = [];
if (chunkId) {
chunks.push(chunkId, chunkFilename);
if (blockOnChunk) {
webpackChunkMap[chunkId] = blockOnChunk;
}
}
const idx = '' + webpackModuleIdx++;
webpackClientModules[idx] = moduleExports;