diff --git a/packages/react-client/src/ReactFlightClient.js b/packages/react-client/src/ReactFlightClient.js index aa864b6895b46..fe5532de5c339 100644 --- a/packages/react-client/src/ReactFlightClient.js +++ b/packages/react-client/src/ReactFlightClient.js @@ -15,7 +15,7 @@ import type { ClientReferenceMetadata, UninitializedModel, Response, - BundlerConfig, + SSRManifest, } from './ReactFlightClientHostConfig'; import { @@ -149,7 +149,7 @@ Chunk.prototype.then = function ( }; export type ResponseBase = { - _bundlerConfig: BundlerConfig, + _bundlerConfig: SSRManifest, _callServer: CallServerCallback, _chunks: Map>, ... @@ -473,13 +473,16 @@ function createModelReject(chunk: SomeChunk): (error: mixed) => void { function createServerReferenceProxy, T>( response: Response, - metaData: {id: any, bound: Thenable>}, + metaData: {id: any, bound: null | Thenable>}, ): (...A) => Promise { const callServer = response._callServer; const proxy = function (): Promise { // $FlowFixMe[method-unbinding] const args = Array.prototype.slice.call(arguments); const p = metaData.bound; + if (!p) { + return callServer(metaData.id, args); + } if (p.status === INITIALIZED) { const bound = p.value; return callServer(metaData.id, bound.concat(args)); @@ -608,7 +611,7 @@ function missingCall() { } export function createResponse( - bundlerConfig: BundlerConfig, + bundlerConfig: SSRManifest, callServer: void | CallServerCallback, ): ResponseBase { const chunks: Map> = new Map(); diff --git a/packages/react-client/src/ReactFlightClientStream.js b/packages/react-client/src/ReactFlightClientStream.js index 16178c5d8075e..56772ec4a42b3 100644 --- a/packages/react-client/src/ReactFlightClientStream.js +++ b/packages/react-client/src/ReactFlightClientStream.js @@ -9,7 +9,7 @@ import type {CallServerCallback} from './ReactFlightClient'; import type {Response} from './ReactFlightClientHostConfigStream'; -import type {BundlerConfig} from './ReactFlightClientHostConfig'; +import type {SSRManifest} from './ReactFlightClientHostConfig'; import { resolveModule, @@ -121,7 +121,7 @@ function createFromJSONCallback(response: Response) { } export function createResponse( - bundlerConfig: BundlerConfig, + bundlerConfig: SSRManifest, callServer: void | CallServerCallback, ): Response { // NOTE: CHECK THE COMPILER OUTPUT EACH TIME YOU CHANGE THIS. diff --git a/packages/react-client/src/forks/ReactFlightClientHostConfig.custom.js b/packages/react-client/src/forks/ReactFlightClientHostConfig.custom.js index 8262bd7f165d3..3300d3bbca0c7 100644 --- a/packages/react-client/src/forks/ReactFlightClientHostConfig.custom.js +++ b/packages/react-client/src/forks/ReactFlightClientHostConfig.custom.js @@ -26,7 +26,7 @@ declare var $$$hostConfig: any; export type Response = any; -export opaque type BundlerConfig = mixed; +export opaque type SSRManifest = mixed; export opaque type ClientReferenceMetadata = mixed; export opaque type ClientReference = mixed; // eslint-disable-line no-unused-vars export const resolveClientReference = $$$hostConfig.resolveClientReference; diff --git a/packages/react-client/src/forks/ReactFlightClientHostConfig.dom-bun.js b/packages/react-client/src/forks/ReactFlightClientHostConfig.dom-bun.js index 4bcb94fc76962..8f240e36e6a2f 100644 --- a/packages/react-client/src/forks/ReactFlightClientHostConfig.dom-bun.js +++ b/packages/react-client/src/forks/ReactFlightClientHostConfig.dom-bun.js @@ -11,7 +11,7 @@ export * from 'react-client/src/ReactFlightClientHostConfigBrowser'; export * from 'react-client/src/ReactFlightClientHostConfigStream'; export type Response = any; -export opaque type BundlerConfig = mixed; +export opaque type SSRManifest = mixed; export opaque type ClientReferenceMetadata = mixed; export opaque type ClientReference = mixed; // eslint-disable-line no-unused-vars export const resolveClientReference: any = null; diff --git a/packages/react-noop-renderer/src/ReactNoopFlightServer.js b/packages/react-noop-renderer/src/ReactNoopFlightServer.js index da0ec35a8b026..52794a6221c3f 100644 --- a/packages/react-noop-renderer/src/ReactNoopFlightServer.js +++ b/packages/react-noop-renderer/src/ReactNoopFlightServer.js @@ -14,7 +14,7 @@ * environment. */ -import type {ReactModel} from 'react-server/src/ReactFlightServer'; +import type {ReactClientValue} from 'react-server/src/ReactFlightServer'; import type {ServerContextJSONValue} from 'shared/ReactTypes'; import {saveModule} from 'react-noop-renderer/flight-modules'; @@ -71,7 +71,7 @@ type Options = { identifierPrefix?: string, }; -function render(model: ReactModel, options?: Options): Destination { +function render(model: ReactClientValue, options?: Options): Destination { const destination: Destination = []; const bundlerConfig = undefined; const request = ReactNoopFlightServer.createRequest( diff --git a/packages/react-server-dom-relay/src/ReactFlightDOMRelayClientHostConfig.js b/packages/react-server-dom-relay/src/ReactFlightDOMRelayClientHostConfig.js index 81b954687423b..1bf240428f5f0 100644 --- a/packages/react-server-dom-relay/src/ReactFlightDOMRelayClientHostConfig.js +++ b/packages/react-server-dom-relay/src/ReactFlightDOMRelayClientHostConfig.js @@ -31,14 +31,14 @@ import isArray from 'shared/isArray'; export type {ClientReferenceMetadata} from 'ReactFlightDOMRelayClientIntegration'; -export type BundlerConfig = null; +export type SSRManifest = null; export type UninitializedModel = JSONValue; export type Response = ResponseBase; export function resolveClientReference( - bundlerConfig: BundlerConfig, + bundlerConfig: SSRManifest, metadata: ClientReferenceMetadata, ): ClientReference { return resolveClientReferenceImpl(metadata); diff --git a/packages/react-server-dom-relay/src/ReactFlightDOMRelayServer.js b/packages/react-server-dom-relay/src/ReactFlightDOMRelayServer.js index d76133d4182c6..7ecd37cca3c69 100644 --- a/packages/react-server-dom-relay/src/ReactFlightDOMRelayServer.js +++ b/packages/react-server-dom-relay/src/ReactFlightDOMRelayServer.js @@ -7,9 +7,9 @@ * @flow */ -import type {ReactModel} from 'react-server/src/ReactFlightServer'; +import type {ReactClientValue} from 'react-server/src/ReactFlightServer'; import type { - BundlerConfig, + ClientManifest, Destination, } from './ReactFlightDOMRelayServerHostConfig'; @@ -25,9 +25,9 @@ type Options = { }; function render( - model: ReactModel, + model: ReactClientValue, destination: Destination, - config: BundlerConfig, + config: ClientManifest, options?: Options, ): void { const request = createRequest( diff --git a/packages/react-server-dom-relay/src/ReactFlightDOMRelayServerHostConfig.js b/packages/react-server-dom-relay/src/ReactFlightDOMRelayServerHostConfig.js index 5d71f6e3c68e6..0910af6a01e1c 100644 --- a/packages/react-server-dom-relay/src/ReactFlightDOMRelayServerHostConfig.js +++ b/packages/react-server-dom-relay/src/ReactFlightDOMRelayServerHostConfig.js @@ -9,7 +9,10 @@ import type {RowEncoding, JSONValue} from './ReactFlightDOMRelayProtocol'; -import type {Request, ReactModel} from 'react-server/src/ReactFlightServer'; +import type { + Request, + ReactClientValue, +} from 'react-server/src/ReactFlightServer'; import type {JSResourceReference} from 'JSResourceReference'; import JSResourceReferenceImpl from 'JSResourceReferenceImpl'; @@ -23,7 +26,7 @@ export type ServerReferenceId = {}; import type { Destination, - BundlerConfig, + BundlerConfig as ClientManifest, ClientReferenceMetadata, } from 'ReactFlightDOMRelayServerIntegration'; @@ -37,7 +40,7 @@ import { export type { Destination, - BundlerConfig, + BundlerConfig as ClientManifest, ClientReferenceMetadata, } from 'ReactFlightDOMRelayServerIntegration'; @@ -60,16 +63,23 @@ export function getClientReferenceKey( } export function resolveClientReferenceMetadata( - config: BundlerConfig, + config: ClientManifest, resource: ClientReference, ): ClientReferenceMetadata { return resolveClientReferenceMetadataImpl(config, resource); } -export function resolveServerReferenceMetadata( - config: BundlerConfig, +export function getServerReferenceId( + config: ClientManifest, + resource: ServerReference, +): ServerReferenceId { + throw new Error('Not implemented.'); +} + +export function getServerReferenceBoundArguments( + config: ClientManifest, resource: ServerReference, -): {id: ServerReferenceId, bound: Promise>} { +): Array { throw new Error('Not implemented.'); } @@ -125,9 +135,9 @@ export function processErrorChunkDev( function convertModelToJSON( request: Request, - parent: {+[key: string]: ReactModel} | $ReadOnlyArray, + parent: {+[key: string]: ReactClientValue} | $ReadOnlyArray, key: string, - model: ReactModel, + model: ReactClientValue, ): JSONValue { const json = resolveModelToJSON(request, parent, key, model); if (typeof json === 'object' && json !== null) { @@ -160,7 +170,7 @@ function convertModelToJSON( export function processModelChunk( request: Request, id: number, - model: ReactModel, + model: ReactClientValue, ): Chunk { // $FlowFixMe no good way to define an empty exact object const json = convertModelToJSON(request, {}, '', model); diff --git a/packages/react-server-dom-webpack/src/ReactFlightClientNodeBundlerConfig.js b/packages/react-server-dom-webpack/src/ReactFlightClientNodeBundlerConfig.js index a7de70225c6d6..d7bc2e2897bd4 100644 --- a/packages/react-server-dom-webpack/src/ReactFlightClientNodeBundlerConfig.js +++ b/packages/react-server-dom-webpack/src/ReactFlightClientNodeBundlerConfig.js @@ -13,14 +13,12 @@ import type { RejectedThenable, } from 'shared/ReactTypes'; -export type WebpackSSRMap = { +export type SSRManifest = { [clientId: string]: { [clientExportName: string]: ClientReference, }, }; -export type BundlerConfig = WebpackSSRMap; - export opaque type ClientReferenceMetadata = { id: string, chunks: Array, @@ -34,7 +32,7 @@ export opaque type ClientReference = { }; export function resolveClientReference( - bundlerConfig: BundlerConfig, + bundlerConfig: SSRManifest, metadata: ClientReferenceMetadata, ): ClientReference { const resolvedModuleData = bundlerConfig[metadata.id][metadata.name]; diff --git a/packages/react-server-dom-webpack/src/ReactFlightClientWebpackBundlerConfig.js b/packages/react-server-dom-webpack/src/ReactFlightClientWebpackBundlerConfig.js index 739f0160ecb82..739546cb378f3 100644 --- a/packages/react-server-dom-webpack/src/ReactFlightClientWebpackBundlerConfig.js +++ b/packages/react-server-dom-webpack/src/ReactFlightClientWebpackBundlerConfig.js @@ -13,14 +13,12 @@ import type { RejectedThenable, } from 'shared/ReactTypes'; -export type WebpackSSRMap = { +export type SSRManifest = null | { [clientId: string]: { [clientExportName: string]: ClientReferenceMetadata, }, }; -export type BundlerConfig = null | WebpackSSRMap; - export opaque type ClientReferenceMetadata = { id: string, chunks: Array, @@ -32,7 +30,7 @@ export opaque type ClientReferenceMetadata = { export opaque type ClientReference = ClientReferenceMetadata; export function resolveClientReference( - bundlerConfig: BundlerConfig, + bundlerConfig: SSRManifest, metadata: ClientReferenceMetadata, ): ClientReference { if (bundlerConfig) { diff --git a/packages/react-server-dom-webpack/src/ReactFlightDOMClientEdge.js b/packages/react-server-dom-webpack/src/ReactFlightDOMClientEdge.js index 24dd5699beb45..7eb7b50655654 100644 --- a/packages/react-server-dom-webpack/src/ReactFlightDOMClientEdge.js +++ b/packages/react-server-dom-webpack/src/ReactFlightDOMClientEdge.js @@ -11,7 +11,7 @@ import type {Thenable} from 'shared/ReactTypes.js'; import type {Response as FlightResponse} from 'react-client/src/ReactFlightClientStream'; -import type {BundlerConfig} from './ReactFlightClientWebpackBundlerConfig'; +import type {SSRManifest} from './ReactFlightClientWebpackBundlerConfig'; import { createResponse, @@ -30,7 +30,7 @@ function noServerCall() { } export type Options = { - moduleMap?: BundlerConfig, + moduleMap?: SSRManifest, }; function createResponseFromOptions(options: void | Options) { diff --git a/packages/react-server-dom-webpack/src/ReactFlightDOMClientNode.js b/packages/react-server-dom-webpack/src/ReactFlightDOMClientNode.js index 532ee43b81e19..09502a7bf5479 100644 --- a/packages/react-server-dom-webpack/src/ReactFlightDOMClientNode.js +++ b/packages/react-server-dom-webpack/src/ReactFlightDOMClientNode.js @@ -11,7 +11,7 @@ import type {Thenable} from 'shared/ReactTypes.js'; import type {Response} from 'react-client/src/ReactFlightClientStream'; -import type {BundlerConfig} from 'react-client/src/ReactFlightClientHostConfig'; +import type {SSRManifest} from 'react-client/src/ReactFlightClientHostConfig'; import type {Readable} from 'stream'; @@ -34,7 +34,7 @@ function noServerCall() { function createFromNodeStream( stream: Readable, - moduleMap: $NonMaybeType, + moduleMap: $NonMaybeType, ): Thenable { const response: Response = createResponse(moduleMap, noServerCall); stream.on('data', chunk => { diff --git a/packages/react-server-dom-webpack/src/ReactFlightDOMServerBrowser.js b/packages/react-server-dom-webpack/src/ReactFlightDOMServerBrowser.js index be2343121e2a0..76eb5da99d159 100644 --- a/packages/react-server-dom-webpack/src/ReactFlightDOMServerBrowser.js +++ b/packages/react-server-dom-webpack/src/ReactFlightDOMServerBrowser.js @@ -7,9 +7,9 @@ * @flow */ -import type {ReactModel} from 'react-server/src/ReactFlightServer'; +import type {ReactClientValue} from 'react-server/src/ReactFlightServer'; import type {ServerContextJSONValue} from 'shared/ReactTypes'; -import type {BundlerConfig} from './ReactFlightServerWebpackBundlerConfig'; +import type {ClientManifest} from './ReactFlightServerWebpackBundlerConfig'; import { createRequest, @@ -26,8 +26,8 @@ type Options = { }; function renderToReadableStream( - model: ReactModel, - webpackMap: BundlerConfig, + model: ReactClientValue, + webpackMap: ClientManifest, options?: Options, ): ReadableStream { const request = createRequest( diff --git a/packages/react-server-dom-webpack/src/ReactFlightDOMServerEdge.js b/packages/react-server-dom-webpack/src/ReactFlightDOMServerEdge.js index be2343121e2a0..76eb5da99d159 100644 --- a/packages/react-server-dom-webpack/src/ReactFlightDOMServerEdge.js +++ b/packages/react-server-dom-webpack/src/ReactFlightDOMServerEdge.js @@ -7,9 +7,9 @@ * @flow */ -import type {ReactModel} from 'react-server/src/ReactFlightServer'; +import type {ReactClientValue} from 'react-server/src/ReactFlightServer'; import type {ServerContextJSONValue} from 'shared/ReactTypes'; -import type {BundlerConfig} from './ReactFlightServerWebpackBundlerConfig'; +import type {ClientManifest} from './ReactFlightServerWebpackBundlerConfig'; import { createRequest, @@ -26,8 +26,8 @@ type Options = { }; function renderToReadableStream( - model: ReactModel, - webpackMap: BundlerConfig, + model: ReactClientValue, + webpackMap: ClientManifest, options?: Options, ): ReadableStream { const request = createRequest( diff --git a/packages/react-server-dom-webpack/src/ReactFlightDOMServerNode.js b/packages/react-server-dom-webpack/src/ReactFlightDOMServerNode.js index 82ff956c99d72..16a38a33a1673 100644 --- a/packages/react-server-dom-webpack/src/ReactFlightDOMServerNode.js +++ b/packages/react-server-dom-webpack/src/ReactFlightDOMServerNode.js @@ -7,9 +7,12 @@ * @flow */ -import type {Request, ReactModel} from 'react-server/src/ReactFlightServer'; +import type { + Request, + ReactClientValue, +} from 'react-server/src/ReactFlightServer'; import type {Destination} from 'react-server/src/ReactServerStreamConfigNode'; -import type {BundlerConfig} from './ReactFlightServerWebpackBundlerConfig'; +import type {ClientManifest} from './ReactFlightServerWebpackBundlerConfig'; import type {Writable} from 'stream'; import type {ServerContextJSONValue} from 'shared/ReactTypes'; @@ -36,8 +39,8 @@ type PipeableStream = { }; function renderToPipeableStream( - model: ReactModel, - webpackMap: BundlerConfig, + model: ReactClientValue, + webpackMap: ClientManifest, options?: Options, ): PipeableStream { const request = createRequest( diff --git a/packages/react-server-dom-webpack/src/ReactFlightServerWebpackBundlerConfig.js b/packages/react-server-dom-webpack/src/ReactFlightServerWebpackBundlerConfig.js index 29d41e7f4ad98..444f2c0b2a150 100644 --- a/packages/react-server-dom-webpack/src/ReactFlightServerWebpackBundlerConfig.js +++ b/packages/react-server-dom-webpack/src/ReactFlightServerWebpackBundlerConfig.js @@ -7,18 +7,16 @@ * @flow */ -import type {ReactModel} from 'react-server/src/ReactFlightServer'; +import type {ReactClientValue} from 'react-server/src/ReactFlightServer'; -type WebpackMap = { +export type ClientManifest = { [id: string]: ClientReferenceMetadata, }; -export type BundlerConfig = WebpackMap; - export type ServerReference = T & { $$typeof: symbol, $$id: string, - $$bound: Array, + $$bound: null | Array, }; export type ServerReferenceId = string; @@ -57,7 +55,7 @@ export function isServerReference(reference: Object): boolean { } export function resolveClientReferenceMetadata( - config: BundlerConfig, + config: ClientManifest, clientReference: ClientReference, ): ClientReferenceMetadata { const resolvedModuleData = config[clientReference.$$id]; @@ -73,12 +71,16 @@ export function resolveClientReferenceMetadata( } } -export function resolveServerReferenceMetadata( - config: BundlerConfig, +export function getServerReferenceId( + config: ClientManifest, + serverReference: ServerReference, +): ServerReferenceId { + return serverReference.$$id; +} + +export function getServerReferenceBoundArguments( + config: ClientManifest, serverReference: ServerReference, -): {id: ServerReferenceId, bound: Promise>} { - return { - id: serverReference.$$id, - bound: Promise.resolve(serverReference.$$bound), - }; +): null | Array { + return serverReference.$$bound; } diff --git a/packages/react-server-dom-webpack/src/ReactFlightWebpackNodeLoader.js b/packages/react-server-dom-webpack/src/ReactFlightWebpackNodeLoader.js index 5885cc98e65c6..dae810af0a765 100644 --- a/packages/react-server-dom-webpack/src/ReactFlightWebpackNodeLoader.js +++ b/packages/react-server-dom-webpack/src/ReactFlightWebpackNodeLoader.js @@ -188,7 +188,7 @@ function transformServerModule( newSrc += 'Object.defineProperties(' + local + ',{'; newSrc += '$$typeof: {value: Symbol.for("react.server.reference")},'; newSrc += '$$id: {value: ' + JSON.stringify(url + '#' + exported) + '},'; - newSrc += '$$bound: { value: [] }'; + newSrc += '$$bound: { value: null }'; newSrc += '});\n'; }); return newSrc; diff --git a/packages/react-server-dom-webpack/src/ReactFlightWebpackNodeRegister.js b/packages/react-server-dom-webpack/src/ReactFlightWebpackNodeRegister.js index be666af6fc369..fb7cbfd271968 100644 --- a/packages/react-server-dom-webpack/src/ReactFlightWebpackNodeRegister.js +++ b/packages/react-server-dom-webpack/src/ReactFlightWebpackNodeRegister.js @@ -30,7 +30,7 @@ module.exports = function register() { const args = Array.prototype.slice.call(arguments, 1); newFn.$$typeof = SERVER_REFERENCE; newFn.$$id = this.$$id; - newFn.$$bound = this.$$bound.concat(args); + newFn.$$bound = this.$$bound ? this.$$bound.concat(args) : args; } return newFn; }: any); @@ -289,7 +289,7 @@ module.exports = function register() { $$typeof: {value: SERVER_REFERENCE}, // Represents the whole Module object instead of a particular import. $$id: {value: moduleId}, - $$bound: {value: []}, + $$bound: {value: null}, }); } else { const keys = Object.keys(exports); @@ -300,7 +300,7 @@ module.exports = function register() { Object.defineProperties((value: any), { $$typeof: {value: SERVER_REFERENCE}, $$id: {value: moduleId + '#' + key}, - $$bound: {value: []}, + $$bound: {value: null}, }); } } diff --git a/packages/react-server-native-relay/src/ReactFlightNativeRelayClientHostConfig.js b/packages/react-server-native-relay/src/ReactFlightNativeRelayClientHostConfig.js index cc85a7976e03f..8e7c18d31a3a9 100644 --- a/packages/react-server-native-relay/src/ReactFlightNativeRelayClientHostConfig.js +++ b/packages/react-server-native-relay/src/ReactFlightNativeRelayClientHostConfig.js @@ -31,14 +31,14 @@ import isArray from 'shared/isArray'; export type {ClientReferenceMetadata} from 'ReactFlightNativeRelayClientIntegration'; -export type BundlerConfig = null; +export type SSRManifest = null; export type UninitializedModel = JSONValue; export type Response = ResponseBase; export function resolveClientReference( - bundlerConfig: BundlerConfig, + bundlerConfig: SSRManifest, metadata: ClientReferenceMetadata, ): ClientReference { return resolveClientReferenceImpl(metadata); diff --git a/packages/react-server-native-relay/src/ReactFlightNativeRelayServer.js b/packages/react-server-native-relay/src/ReactFlightNativeRelayServer.js index 4f059abd897d1..5e049368f72f2 100644 --- a/packages/react-server-native-relay/src/ReactFlightNativeRelayServer.js +++ b/packages/react-server-native-relay/src/ReactFlightNativeRelayServer.js @@ -7,9 +7,9 @@ * @flow */ -import type {ReactModel} from 'react-server/src/ReactFlightServer'; +import type {ReactClientValue} from 'react-server/src/ReactFlightServer'; import type { - BundlerConfig, + ClientManifest, Destination, } from './ReactFlightNativeRelayServerHostConfig'; @@ -20,9 +20,9 @@ import { } from 'react-server/src/ReactFlightServer'; function render( - model: ReactModel, + model: ReactClientValue, destination: Destination, - config: BundlerConfig, + config: ClientManifest, ): void { const request = createRequest(model, config); startWork(request); diff --git a/packages/react-server-native-relay/src/ReactFlightNativeRelayServerHostConfig.js b/packages/react-server-native-relay/src/ReactFlightNativeRelayServerHostConfig.js index 703afb6e7ebc5..05f53e2049460 100644 --- a/packages/react-server-native-relay/src/ReactFlightNativeRelayServerHostConfig.js +++ b/packages/react-server-native-relay/src/ReactFlightNativeRelayServerHostConfig.js @@ -8,7 +8,10 @@ */ import type {RowEncoding, JSONValue} from './ReactFlightNativeRelayProtocol'; -import type {Request, ReactModel} from 'react-server/src/ReactFlightServer'; +import type { + Request, + ReactClientValue, +} from 'react-server/src/ReactFlightServer'; import hasOwnProperty from 'shared/hasOwnProperty'; import isArray from 'shared/isArray'; import type {JSResourceReference} from 'JSResourceReference'; @@ -20,7 +23,7 @@ export type ServerReferenceId = {}; import type { Destination, - BundlerConfig, + BundlerConfig as ClientManifest, ClientReferenceMetadata, } from 'ReactFlightNativeRelayServerIntegration'; @@ -34,7 +37,7 @@ import { export type { Destination, - BundlerConfig, + BundlerConfig as ClientManifest, ClientReferenceMetadata, } from 'ReactFlightNativeRelayServerIntegration'; @@ -57,16 +60,23 @@ export function getClientReferenceKey( } export function resolveClientReferenceMetadata( - config: BundlerConfig, + config: ClientManifest, resource: ClientReference, ): ClientReferenceMetadata { return resolveClientReferenceMetadataImpl(config, resource); } -export function resolveServerReferenceMetadata( - config: BundlerConfig, +export function getServerReferenceId( + config: ClientManifest, + resource: ServerReference, +): ServerReferenceId { + throw new Error('Not implemented.'); +} + +export function getServerReferenceBoundArguments( + config: ClientManifest, resource: ServerReference, -): {id: ServerReferenceId, bound: Promise>} { +): Array { throw new Error('Not implemented.'); } @@ -121,9 +131,9 @@ export function processErrorChunkDev( function convertModelToJSON( request: Request, - parent: {+[key: string]: ReactModel} | $ReadOnlyArray, + parent: {+[key: string]: ReactClientValue} | $ReadOnlyArray, key: string, - model: ReactModel, + model: ReactClientValue, ): JSONValue { const json = resolveModelToJSON(request, parent, key, model); if (typeof json === 'object' && json !== null) { @@ -155,7 +165,7 @@ function convertModelToJSON( export function processModelChunk( request: Request, id: number, - model: ReactModel, + model: ReactClientValue, ): Chunk { // $FlowFixMe no good way to define an empty exact object const json = convertModelToJSON(request, {}, '', model); diff --git a/packages/react-server/src/ReactFlightServer.js b/packages/react-server/src/ReactFlightServer.js index 17e1c7aca83c5..2f82e024b67fb 100644 --- a/packages/react-server/src/ReactFlightServer.js +++ b/packages/react-server/src/ReactFlightServer.js @@ -10,7 +10,7 @@ import type { Destination, Chunk, - BundlerConfig, + ClientManifest, ClientReferenceMetadata, ClientReference, ClientReferenceKey, @@ -27,6 +27,7 @@ import type { PendingThenable, FulfilledThenable, RejectedThenable, + ReactServerContext, } from 'shared/ReactTypes'; import type {LazyComponent} from 'react/src/ReactLazy'; @@ -44,7 +45,8 @@ import { processErrorChunkDev, processReferenceChunk, resolveClientReferenceMetadata, - resolveServerReferenceMetadata, + getServerReferenceId, + getServerReferenceBoundArguments, getClientReferenceKey, isClientReference, isServerReference, @@ -95,21 +97,32 @@ type ReactJSONValue = | number | null | $ReadOnlyArray - | ReactModelObject; - -export type ReactModel = - | React$Element - | LazyComponent + | ReactClientObject; + +// Serializable values +export type ReactClientValue = + // Server Elements and Lazy Components are unwrapped on the Server + | React$Element> + | LazyComponent + // References are passed by their value + | ClientReference + | ServerReference + // The rest are passed as is. Sub-types can be passed in but lose their + // subtype, so the receiver can only accept once of these. + | React$Element + | React$Element & any> + | ReactServerContext | string | boolean | number | symbol | null - | Iterable - | ReactModelObject - | Promise; + | Iterable + | Array + | ReactClientObject + | Promise; // Thenable -type ReactModelObject = {+[key: string]: ReactModel}; +type ReactClientObject = {+[key: string]: ReactClientValue}; const PENDING = 0; const COMPLETED = 1; @@ -119,7 +132,7 @@ const ERRORED = 4; type Task = { id: number, status: 0 | 1 | 3 | 4, - model: ReactModel, + model: ReactClientValue, ping: () => void, context: ContextSnapshot, thenableState: ThenableState | null, @@ -129,7 +142,7 @@ export type Request = { status: 0 | 1 | 2, fatalError: mixed, destination: null | Destination, - bundlerConfig: BundlerConfig, + bundlerConfig: ClientManifest, cache: Map, nextChunkId: number, pendingChunks: number, @@ -145,7 +158,7 @@ export type Request = { identifierPrefix: string, identifierCount: number, onError: (error: mixed) => ?string, - toJSON: (key: string, value: ReactModel) => ReactJSONValue, + toJSON: (key: string, value: ReactClientValue) => ReactJSONValue, }; const ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher; @@ -161,8 +174,8 @@ const CLOSING = 1; const CLOSED = 2; export function createRequest( - model: ReactModel, - bundlerConfig: BundlerConfig, + model: ReactClientValue, + bundlerConfig: ClientManifest, onError: void | ((error: mixed) => ?string), context?: Array<[string, ServerContextJSONValue]>, identifierPrefix?: string, @@ -200,7 +213,7 @@ export function createRequest( identifierCount: 1, onError: onError === undefined ? defaultErrorHandler : onError, // $FlowFixMe[missing-this-annot] - toJSON: function (key: string, value: ReactModel): ReactJSONValue { + toJSON: function (key: string, value: ReactClientValue): ReactJSONValue { return resolveModelToJSON(request, this, key, value); }, }; @@ -364,7 +377,7 @@ function attemptResolveElement( ref: mixed, props: any, prevThenableState: ThenableState | null, -): ReactModel { +): ReactClientValue { if (ref !== null && ref !== undefined) { // When the ref moves to the regular props object this will implicitly // throw for functions. We could probably relax it to a DEV warning for other @@ -492,7 +505,7 @@ function pingTask(request: Request, task: Task): void { function createTask( request: Request, - model: ReactModel, + model: ReactClientValue, context: ContextSnapshot, abortSet: Set, ): Task { @@ -535,7 +548,9 @@ function serializeProviderReference(name: string): string { function serializeClientReference( request: Request, - parent: {+[key: string | number]: ReactModel} | $ReadOnlyArray, + parent: + | {+[key: string | number]: ReactClientValue} + | $ReadOnlyArray, key: string, clientReference: ClientReference, ): string { @@ -586,7 +601,9 @@ function serializeClientReference( function serializeServerReference( request: Request, - parent: {+[key: string | number]: ReactModel} | $ReadOnlyArray, + parent: + | {+[key: string | number]: ReactClientValue} + | $ReadOnlyArray, key: string, serverReference: ServerReference, ): string { @@ -595,10 +612,18 @@ function serializeServerReference( if (existingId !== undefined) { return serializeServerReferenceID(existingId); } + + const bound: null | Array = getServerReferenceBoundArguments( + request.bundlerConfig, + serverReference, + ); const serverReferenceMetadata: { id: ServerReferenceId, - bound: Promise>, - } = resolveServerReferenceMetadata(request.bundlerConfig, serverReference); + bound: null | Promise>, + } = { + id: getServerReferenceId(request.bundlerConfig, serverReference), + bound: bound ? Promise.resolve(bound) : null, + }; request.pendingChunks++; const metadataId = request.nextChunkId++; // We assume that this object doesn't suspend. @@ -683,7 +708,7 @@ function describeKeyForErrorMessage(key: string): string { return '"' + key + '"' === encodedKey ? key : encodedKey; } -function describeValueForErrorMessage(value: ReactModel): string { +function describeValueForErrorMessage(value: ReactClientValue): string { switch (typeof value) { case 'string': { return JSON.stringify( @@ -740,8 +765,8 @@ function describeElementType(type: any): string { function describeObjectForErrorMessage( objectOrArray: - | {+[key: string | number]: ReactModel, ...} - | $ReadOnlyArray, + | {+[key: string | number]: ReactClientValue, ...} + | $ReadOnlyArray, expandedName?: string, ): string { const objKind = objectName(objectOrArray); @@ -756,7 +781,7 @@ function describeObjectForErrorMessage( // Print JSX Children const type = jsxChildrenParents.get(objectOrArray); str = '<' + describeElementType(type) + '>'; - const array: $ReadOnlyArray = objectOrArray; + const array: $ReadOnlyArray = objectOrArray; for (let i = 0; i < array.length; i++) { const value = array[i]; let substr; @@ -782,7 +807,7 @@ function describeObjectForErrorMessage( } else { // Print Array str = '['; - const array: $ReadOnlyArray = objectOrArray; + const array: $ReadOnlyArray = objectOrArray; for (let i = 0; i < array.length; i++) { if (i > 0) { str += ', '; @@ -814,7 +839,8 @@ function describeObjectForErrorMessage( // Print JSX const type = jsxPropsParents.get(objectOrArray); str = '<' + (describeElementType(type) || '...'); - const object: {+[key: string | number]: ReactModel, ...} = objectOrArray; + const object: {+[key: string | number]: ReactClientValue, ...} = + objectOrArray; const names = Object.keys(object); for (let i = 0; i < names.length; i++) { str += ' '; @@ -849,7 +875,8 @@ function describeObjectForErrorMessage( } else { // Print Object str = '{'; - const object: {+[key: string | number]: ReactModel, ...} = objectOrArray; + const object: {+[key: string | number]: ReactClientValue, ...} = + objectOrArray; const names = Object.keys(object); for (let i = 0; i < names.length; i++) { if (i > 0) { @@ -893,9 +920,11 @@ let isInsideContextValue = false; export function resolveModelToJSON( request: Request, - parent: {+[key: string | number]: ReactModel} | $ReadOnlyArray, + parent: + | {+[key: string | number]: ReactClientValue} + | $ReadOnlyArray, key: string, - value: ReactModel, + value: ReactClientValue, ): ReactJSONValue { if (__DEV__) { // $FlowFixMe @@ -938,7 +967,7 @@ export function resolveModelToJSON( if ( parent[0] === REACT_ELEMENT_TYPE && parent[1] && - parent[1].$$typeof === REACT_PROVIDER_TYPE && + (parent[1]: any).$$typeof === REACT_PROVIDER_TYPE && key === '3' ) { insideContextProps = value; diff --git a/packages/react-server/src/ReactFlightServerBundlerConfigCustom.js b/packages/react-server/src/ReactFlightServerBundlerConfigCustom.js index edd34138db99d..b8254bb51d3cd 100644 --- a/packages/react-server/src/ReactFlightServerBundlerConfigCustom.js +++ b/packages/react-server/src/ReactFlightServerBundlerConfigCustom.js @@ -9,7 +9,7 @@ declare var $$$hostConfig: any; -export opaque type BundlerConfig = mixed; +export opaque type ClientManifest = mixed; export opaque type ClientReference = mixed; // eslint-disable-line no-unused-vars export opaque type ServerReference = mixed; // eslint-disable-line no-unused-vars export opaque type ClientReferenceMetadata: any = mixed; @@ -20,5 +20,6 @@ export const isServerReference = $$$hostConfig.isServerReference; export const getClientReferenceKey = $$$hostConfig.getClientReferenceKey; export const resolveClientReferenceMetadata = $$$hostConfig.resolveClientReferenceMetadata; -export const resolveServerReferenceMetadata = - $$$hostConfig.resolveServerReferenceMetadata; +export const getServerReferenceId = $$$hostConfig.getServerReferenceId; +export const getServerReferenceBoundArguments = + $$$hostConfig.getServerReferenceBoundArguments; diff --git a/packages/react-server/src/ReactFlightServerConfigStream.js b/packages/react-server/src/ReactFlightServerConfigStream.js index 43a7f75c80681..4377a313b374a 100644 --- a/packages/react-server/src/ReactFlightServerConfigStream.js +++ b/packages/react-server/src/ReactFlightServerConfigStream.js @@ -64,7 +64,10 @@ ByteSize // TODO: Implement HTMLData, BlobData and URLData. -import type {Request, ReactModel} from 'react-server/src/ReactFlightServer'; +import type { + Request, + ReactClientValue, +} from 'react-server/src/ReactFlightServer'; import {stringToChunk} from './ReactServerStreamConfig'; @@ -124,7 +127,7 @@ export function processErrorChunkDev( export function processModelChunk( request: Request, id: number, - model: ReactModel, + model: ReactClientValue, ): Chunk { // $FlowFixMe[incompatible-type] stringify can return null const json: string = stringify(model, request.toJSON); @@ -145,7 +148,7 @@ export function processReferenceChunk( export function processImportChunk( request: Request, id: number, - clientReferenceMetadata: ReactModel, + clientReferenceMetadata: ReactClientValue, ): Chunk { // $FlowFixMe[incompatible-type] stringify can return null const json: string = stringify(clientReferenceMetadata);