diff --git a/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js b/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js index e8f9295d92983..fea9c74959402 100644 --- a/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js +++ b/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js @@ -245,6 +245,13 @@ export type ResumableState = { nextFormID: number, streamingFormat: StreamingFormat, + // We carry the bootstrap intializers in resumable state in case we postpone in the shell + // of a prerender. On resume we will reinitialize the bootstrap scripts if necessary. + // If we end up flushing the bootstrap scripts we void these on the resumable state + bootstrapScriptContent?: string | void, + bootstrapScripts?: $ReadOnlyArray | void, + bootstrapModules?: $ReadOnlyArray | void, + // state for script streaming format, unused if using external runtime / data instructions: InstructionState, @@ -349,9 +356,6 @@ const DEFAULT_HEADERS_CAPACITY_IN_UTF16_CODE_UNITS = 2000; export function createRenderState( resumableState: ResumableState, nonce: string | void, - bootstrapScriptContent: string | void, - bootstrapScripts: $ReadOnlyArray | void, - bootstrapModules: $ReadOnlyArray | void, externalRuntimeConfig: string | BootstrapScriptDescriptor | void, importMap: ImportMap | void, onHeaders: void | ((headers: HeadersDescriptor) => void), @@ -367,6 +371,8 @@ export function createRenderState( const bootstrapChunks: Array = []; let externalRuntimeScript: null | ExternalRuntimeScript = null; + const {bootstrapScriptContent, bootstrapScripts, bootstrapModules} = + resumableState; if (bootstrapScriptContent !== undefined) { bootstrapChunks.push( inlineScriptWithNonce, @@ -612,9 +618,6 @@ export function resumeRenderState( return createRenderState( resumableState, nonce, - // These should have already been flushed in the prerender. - undefined, - undefined, undefined, undefined, undefined, @@ -625,6 +628,9 @@ export function resumeRenderState( export function createResumableState( identifierPrefix: string | void, externalRuntimeConfig: string | BootstrapScriptDescriptor | void, + bootstrapScriptContent: string | void, + bootstrapScripts: $ReadOnlyArray | void, + bootstrapModules: $ReadOnlyArray | void, ): ResumableState { const idPrefix = identifierPrefix === undefined ? '' : identifierPrefix; @@ -638,6 +644,9 @@ export function createResumableState( idPrefix: idPrefix, nextFormID: 0, streamingFormat, + bootstrapScriptContent, + bootstrapScripts, + bootstrapModules, instructions: NothingSent, hasBody: false, hasHtml: false, @@ -3714,7 +3723,11 @@ export function pushEndInstance( function writeBootstrap( destination: Destination, renderState: RenderState, + resumableState: ResumableState, ): boolean { + resumableState.bootstrapScriptContent = undefined; + resumableState.bootstrapScripts = undefined; + resumableState.bootstrapModules = undefined; const bootstrapChunks = renderState.bootstrapChunks; let i = 0; for (; i < bootstrapChunks.length - 1; i++) { @@ -3731,8 +3744,9 @@ function writeBootstrap( export function writeCompletedRoot( destination: Destination, renderState: RenderState, + resumableState: ResumableState, ): boolean { - return writeBootstrap(destination, renderState); + return writeBootstrap(destination, renderState, resumableState); } // Structural Nodes @@ -4197,7 +4211,7 @@ export function writeCompletedBoundaryInstruction( } else { writeMore = writeChunkAndReturn(destination, completeBoundaryDataEnd); } - return writeBootstrap(destination, renderState) && writeMore; + return writeBootstrap(destination, renderState, resumableState) && writeMore; } const clientRenderScript1Full = stringToPrecomputedChunk( diff --git a/packages/react-dom-bindings/src/server/ReactFizzConfigDOMLegacy.js b/packages/react-dom-bindings/src/server/ReactFizzConfigDOMLegacy.js index 72b8b1e07a759..60cdcc2d96433 100644 --- a/packages/react-dom-bindings/src/server/ReactFizzConfigDOMLegacy.js +++ b/packages/react-dom-bindings/src/server/ReactFizzConfigDOMLegacy.js @@ -92,8 +92,6 @@ export function createRenderState( undefined, undefined, undefined, - undefined, - undefined, ); return { // Keep this in sync with ReactFizzConfigDOM diff --git a/packages/react-dom/src/server/ReactDOMFizzServerBrowser.js b/packages/react-dom/src/server/ReactDOMFizzServerBrowser.js index 14acfcb739b23..e1dc396782265 100644 --- a/packages/react-dom/src/server/ReactDOMFizzServerBrowser.js +++ b/packages/react-dom/src/server/ReactDOMFizzServerBrowser.js @@ -114,6 +114,9 @@ function renderToReadableStream( const resumableState = createResumableState( options ? options.identifierPrefix : undefined, options ? options.unstable_externalRuntimeSrc : undefined, + options ? options.bootstrapScriptContent : undefined, + options ? options.bootstrapScripts : undefined, + options ? options.bootstrapModules : undefined, ); const request = createRequest( children, @@ -121,9 +124,6 @@ function renderToReadableStream( createRenderState( resumableState, options ? options.nonce : undefined, - options ? options.bootstrapScriptContent : undefined, - options ? options.bootstrapScripts : undefined, - options ? options.bootstrapModules : undefined, options ? options.unstable_externalRuntimeSrc : undefined, options ? options.importMap : undefined, onHeadersImpl, diff --git a/packages/react-dom/src/server/ReactDOMFizzServerBun.js b/packages/react-dom/src/server/ReactDOMFizzServerBun.js index e125a142c3037..309eb2b8d9d5b 100644 --- a/packages/react-dom/src/server/ReactDOMFizzServerBun.js +++ b/packages/react-dom/src/server/ReactDOMFizzServerBun.js @@ -104,6 +104,9 @@ function renderToReadableStream( const resumableState = createResumableState( options ? options.identifierPrefix : undefined, options ? options.unstable_externalRuntimeSrc : undefined, + options ? options.bootstrapScriptContent : undefined, + options ? options.bootstrapScripts : undefined, + options ? options.bootstrapModules : undefined, ); const request = createRequest( children, @@ -111,9 +114,6 @@ function renderToReadableStream( createRenderState( resumableState, options ? options.nonce : undefined, - options ? options.bootstrapScriptContent : undefined, - options ? options.bootstrapScripts : undefined, - options ? options.bootstrapModules : undefined, options ? options.unstable_externalRuntimeSrc : undefined, options ? options.importMap : undefined, onHeadersImpl, diff --git a/packages/react-dom/src/server/ReactDOMFizzServerEdge.js b/packages/react-dom/src/server/ReactDOMFizzServerEdge.js index 14acfcb739b23..e1dc396782265 100644 --- a/packages/react-dom/src/server/ReactDOMFizzServerEdge.js +++ b/packages/react-dom/src/server/ReactDOMFizzServerEdge.js @@ -114,6 +114,9 @@ function renderToReadableStream( const resumableState = createResumableState( options ? options.identifierPrefix : undefined, options ? options.unstable_externalRuntimeSrc : undefined, + options ? options.bootstrapScriptContent : undefined, + options ? options.bootstrapScripts : undefined, + options ? options.bootstrapModules : undefined, ); const request = createRequest( children, @@ -121,9 +124,6 @@ function renderToReadableStream( createRenderState( resumableState, options ? options.nonce : undefined, - options ? options.bootstrapScriptContent : undefined, - options ? options.bootstrapScripts : undefined, - options ? options.bootstrapModules : undefined, options ? options.unstable_externalRuntimeSrc : undefined, options ? options.importMap : undefined, onHeadersImpl, diff --git a/packages/react-dom/src/server/ReactDOMFizzServerNode.js b/packages/react-dom/src/server/ReactDOMFizzServerNode.js index ca280be5edd7e..a37bea02c8aea 100644 --- a/packages/react-dom/src/server/ReactDOMFizzServerNode.js +++ b/packages/react-dom/src/server/ReactDOMFizzServerNode.js @@ -88,6 +88,9 @@ function createRequestImpl(children: ReactNodeList, options: void | Options) { const resumableState = createResumableState( options ? options.identifierPrefix : undefined, options ? options.unstable_externalRuntimeSrc : undefined, + options ? options.bootstrapScriptContent : undefined, + options ? options.bootstrapScripts : undefined, + options ? options.bootstrapModules : undefined, ); return createRequest( children, @@ -95,9 +98,6 @@ function createRequestImpl(children: ReactNodeList, options: void | Options) { createRenderState( resumableState, options ? options.nonce : undefined, - options ? options.bootstrapScriptContent : undefined, - options ? options.bootstrapScripts : undefined, - options ? options.bootstrapModules : undefined, options ? options.unstable_externalRuntimeSrc : undefined, options ? options.importMap : undefined, options ? options.onHeaders : undefined, diff --git a/packages/react-dom/src/server/ReactDOMFizzStaticBrowser.js b/packages/react-dom/src/server/ReactDOMFizzStaticBrowser.js index 52e0b120c7200..7b5200d6183d7 100644 --- a/packages/react-dom/src/server/ReactDOMFizzStaticBrowser.js +++ b/packages/react-dom/src/server/ReactDOMFizzStaticBrowser.js @@ -94,6 +94,9 @@ function prerender( const resources = createResumableState( options ? options.identifierPrefix : undefined, options ? options.unstable_externalRuntimeSrc : undefined, + options ? options.bootstrapScriptContent : undefined, + options ? options.bootstrapScripts : undefined, + options ? options.bootstrapModules : undefined, ); const request = createPrerenderRequest( children, @@ -101,9 +104,6 @@ function prerender( createRenderState( resources, undefined, // nonce is not compatible with prerendered bootstrap scripts - options ? options.bootstrapScriptContent : undefined, - options ? options.bootstrapScripts : undefined, - options ? options.bootstrapModules : undefined, options ? options.unstable_externalRuntimeSrc : undefined, options ? options.importMap : undefined, onHeadersImpl, diff --git a/packages/react-dom/src/server/ReactDOMFizzStaticEdge.js b/packages/react-dom/src/server/ReactDOMFizzStaticEdge.js index 0cef058935bb9..3cac30b1d9ac0 100644 --- a/packages/react-dom/src/server/ReactDOMFizzStaticEdge.js +++ b/packages/react-dom/src/server/ReactDOMFizzStaticEdge.js @@ -93,6 +93,9 @@ function prerender( const resources = createResumableState( options ? options.identifierPrefix : undefined, options ? options.unstable_externalRuntimeSrc : undefined, + options ? options.bootstrapScriptContent : undefined, + options ? options.bootstrapScripts : undefined, + options ? options.bootstrapModules : undefined, ); const request = createPrerenderRequest( children, @@ -100,9 +103,6 @@ function prerender( createRenderState( resources, undefined, // nonce is not compatible with prerendered bootstrap scripts - options ? options.bootstrapScriptContent : undefined, - options ? options.bootstrapScripts : undefined, - options ? options.bootstrapModules : undefined, options ? options.unstable_externalRuntimeSrc : undefined, options ? options.importMap : undefined, onHeadersImpl, diff --git a/packages/react-dom/src/server/ReactDOMFizzStaticNode.js b/packages/react-dom/src/server/ReactDOMFizzStaticNode.js index 604dbdccc4fc6..938749cb6afe0 100644 --- a/packages/react-dom/src/server/ReactDOMFizzStaticNode.js +++ b/packages/react-dom/src/server/ReactDOMFizzStaticNode.js @@ -94,6 +94,9 @@ function prerenderToNodeStream( const resumableState = createResumableState( options ? options.identifierPrefix : undefined, options ? options.unstable_externalRuntimeSrc : undefined, + options ? options.bootstrapScriptContent : undefined, + options ? options.bootstrapScripts : undefined, + options ? options.bootstrapModules : undefined, ); const request = createPrerenderRequest( children, @@ -101,9 +104,6 @@ function prerenderToNodeStream( createRenderState( resumableState, undefined, // nonce is not compatible with prerendered bootstrap scripts - options ? options.bootstrapScriptContent : undefined, - options ? options.bootstrapScripts : undefined, - options ? options.bootstrapModules : undefined, options ? options.unstable_externalRuntimeSrc : undefined, options ? options.importMap : undefined, options ? options.onHeaders : undefined, diff --git a/packages/react-server-dom-fb/src/ReactDOMServerFB.js b/packages/react-server-dom-fb/src/ReactDOMServerFB.js index 8e4fcbfb04a48..b610a00566caa 100644 --- a/packages/react-server-dom-fb/src/ReactDOMServerFB.js +++ b/packages/react-server-dom-fb/src/ReactDOMServerFB.js @@ -53,6 +53,9 @@ function renderToStream(children: ReactNodeList, options: Options): Stream { const resumableState = createResumableState( options ? options.identifierPrefix : undefined, options ? options.unstable_externalRuntimeSrc : undefined, + options ? options.bootstrapScriptContent : undefined, + options ? options.bootstrapScripts : undefined, + options ? options.bootstrapModules : undefined, ); const request = createRequest( children, @@ -60,9 +63,6 @@ function renderToStream(children: ReactNodeList, options: Options): Stream { createRenderState( resumableState, undefined, - options ? options.bootstrapScriptContent : undefined, - options ? options.bootstrapScripts : undefined, - options ? options.bootstrapModules : undefined, options ? options.unstable_externalRuntimeSrc : undefined, ), createRootFormatContext(undefined), diff --git a/packages/react-server/src/ReactFizzServer.js b/packages/react-server/src/ReactFizzServer.js index 80cfb68c760a3..4c458afd0e2b4 100644 --- a/packages/react-server/src/ReactFizzServer.js +++ b/packages/react-server/src/ReactFizzServer.js @@ -3968,7 +3968,11 @@ function flushCompletedQueues( flushSegment(request, destination, completedRootSegment); request.completedRootSegment = null; - writeCompletedRoot(destination, request.renderState); + writeCompletedRoot( + destination, + request.renderState, + request.resumableState, + ); } else { // We haven't flushed the root yet so we don't need to check any other branches further down return;