diff --git a/.eslintrc.js b/.eslintrc.js index 941c2e3b23..2d0e4abe71 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -492,7 +492,6 @@ module.exports = { ReadableStreamController: 'readonly', RequestInfo: 'readonly', RequestOptions: 'readonly', - ResponseState: 'readonly', StoreAsGlobal: 'readonly', symbol: 'readonly', SyntheticEvent: 'readonly', diff --git a/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js b/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js index a30a9af90a..4a3c2d157d 100644 --- a/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js +++ b/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js @@ -50,7 +50,7 @@ import { } from 'react-server/src/ReactServerStreamConfig'; import { resolveRequest, - getResources, + getResumableState, flushResources, } from 'react-server/src/ReactFizzServer'; @@ -117,27 +117,24 @@ const SentClientRenderFunction /* */ = 0b00100; const SentStyleInsertionFunction /* */ = 0b01000; const SentFormReplayingRuntime /* */ = 0b10000; -// Per response, global state that is not contextual to the rendering subtree. -export type ResponseState = { - bootstrapChunks: Array, +// Per request, global state that is not contextual to the rendering subtree. +// This cannot be resumed and therefore should only contain things that are +// temporary working state or are never used in the prerender pass. +export type RenderState = { + // These can be recreated from resumable state. placeholderPrefix: PrecomputedChunk, segmentPrefix: PrecomputedChunk, boundaryPrefix: string, - idPrefix: string, - nextSuspenseID: number, - streamingFormat: StreamingFormat, - // state for script streaming format, unused if using external runtime / data + // inline script streaming format, unused if using external runtime / data startInlineScript: PrecomputedChunk, - instructions: InstructionState, - // state for data streaming format - externalRuntimeScript: null | ExternalRuntimeScript, + // the preamble must always flush before resuming, so all these chunks must + // be null or empty when resuming. - // preamble and postamble chunks and state + // preamble chunks htmlChunks: null | Array, headChunks: null | Array, - hasBody: boolean, // Hoistable chunks charsetChunks: Array, @@ -145,6 +142,9 @@ export type ResponseState = { preloadChunks: Array, hoistableChunks: Array, + // Module-global-like reference for current boundary resources + boundaryResources: ?BoundaryResources, + // Module-global-like reference for flushing/hoisting state of style resources // We need to track whether the current request has flushed any style resources // without sending an instruction to hoist them. we do that here @@ -155,6 +155,43 @@ export type ResponseState = { ... }; +// Per response, global state that is not contextual to the rendering subtree. +// This is resumable and therefore should be serializable. +export type ResumableState = { + // external runtime script chunks + externalRuntimeScript: null | ExternalRuntimeScript, // TODO: Move to a serializable format + bootstrapChunks: Array, // TODO: Move to a serializable format. + idPrefix: string, + nextSuspenseID: number, + streamingFormat: StreamingFormat, + + // state for script streaming format, unused if using external runtime / data + instructions: InstructionState, + + // postamble state + hasBody: boolean, + hasHtml: boolean, + + // Resources + + // Request local cache + preloadsMap: Map, + preconnectsMap: Map, + stylesMap: Map, + scriptsMap: Map, + + // Flushing queues for Resource dependencies + preconnects: Set, + fontPreloads: Set, + highImagePreloads: Set, + // usedImagePreloads: Set, + precedences: Map>, + stylePrecedences: Map, + bootstrapScripts: Set, + scripts: Set, + bulkPreloads: Set, +}; + const dataElementQuotedEnd = stringToPrecomputedChunk('">'); const startInlineScript = stringToPrecomputedChunk('