Skip to content

Commit

Permalink
Split out ServerReferenceMetadata into Id and Bound Arguments (#26351)
Browse files Browse the repository at this point in the history
This is just moving some stuff around and renaming things.

This tuple is opaque to the Flight implementation and we should probably
encode it separately as a single string instead of a model object.

The term "Metadata" isn't the same as when used for ClientReferences so
it's not really the right term anyway.

I also made it optional since a bound function with no arguments bound
is technically different than a raw instance of that function (it's a
clone).

I also renamed the type ReactModel to ReactClientValue. This is the
generic serializable type for something that can pass through the
serializable boundary from server to client. There will be another one
for client to server.

I also filled in missing classes and ensure the serializable sub-types
are explicit. E.g. Array and Thenable.
  • Loading branch information
sebmarkbage authored Mar 9, 2023
1 parent 62cd5af commit 2b003a5
Show file tree
Hide file tree
Showing 24 changed files with 179 additions and 122 deletions.
11 changes: 7 additions & 4 deletions packages/react-client/src/ReactFlightClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import type {
ClientReferenceMetadata,
UninitializedModel,
Response,
BundlerConfig,
SSRManifest,
} from './ReactFlightClientHostConfig';

import {
Expand Down Expand Up @@ -149,7 +149,7 @@ Chunk.prototype.then = function <T>(
};

export type ResponseBase = {
_bundlerConfig: BundlerConfig,
_bundlerConfig: SSRManifest,
_callServer: CallServerCallback,
_chunks: Map<number, SomeChunk<any>>,
...
Expand Down Expand Up @@ -473,13 +473,16 @@ function createModelReject<T>(chunk: SomeChunk<T>): (error: mixed) => void {

function createServerReferenceProxy<A: Iterable<any>, T>(
response: Response,
metaData: {id: any, bound: Thenable<Array<any>>},
metaData: {id: any, bound: null | Thenable<Array<any>>},
): (...A) => Promise<T> {
const callServer = response._callServer;
const proxy = function (): Promise<T> {
// $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));
Expand Down Expand Up @@ -608,7 +611,7 @@ function missingCall() {
}

export function createResponse(
bundlerConfig: BundlerConfig,
bundlerConfig: SSRManifest,
callServer: void | CallServerCallback,
): ResponseBase {
const chunks: Map<number, SomeChunk<any>> = new Map();
Expand Down
4 changes: 2 additions & 2 deletions packages/react-client/src/ReactFlightClientStream.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<T> = mixed; // eslint-disable-line no-unused-vars
export const resolveClientReference = $$$hostConfig.resolveClientReference;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<T> = mixed; // eslint-disable-line no-unused-vars
export const resolveClientReference: any = null;
Expand Down
4 changes: 2 additions & 2 deletions packages/react-noop-renderer/src/ReactNoopFlightServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<T>(
bundlerConfig: BundlerConfig,
bundlerConfig: SSRManifest,
metadata: ClientReferenceMetadata,
): ClientReference<T> {
return resolveClientReferenceImpl(metadata);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand All @@ -25,9 +25,9 @@ type Options = {
};

function render(
model: ReactModel,
model: ReactClientValue,
destination: Destination,
config: BundlerConfig,
config: ClientManifest,
options?: Options,
): void {
const request = createRequest(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -23,7 +26,7 @@ export type ServerReferenceId = {};

import type {
Destination,
BundlerConfig,
BundlerConfig as ClientManifest,
ClientReferenceMetadata,
} from 'ReactFlightDOMRelayServerIntegration';

Expand All @@ -37,7 +40,7 @@ import {

export type {
Destination,
BundlerConfig,
BundlerConfig as ClientManifest,
ClientReferenceMetadata,
} from 'ReactFlightDOMRelayServerIntegration';

Expand All @@ -60,16 +63,23 @@ export function getClientReferenceKey(
}

export function resolveClientReferenceMetadata<T>(
config: BundlerConfig,
config: ClientManifest,
resource: ClientReference<T>,
): ClientReferenceMetadata {
return resolveClientReferenceMetadataImpl(config, resource);
}

export function resolveServerReferenceMetadata<T>(
config: BundlerConfig,
export function getServerReferenceId<T>(
config: ClientManifest,
resource: ServerReference<T>,
): ServerReferenceId {
throw new Error('Not implemented.');
}

export function getServerReferenceBoundArguments<T>(
config: ClientManifest,
resource: ServerReference<T>,
): {id: ServerReferenceId, bound: Promise<Array<any>>} {
): Array<ReactClientValue> {
throw new Error('Not implemented.');
}

Expand Down Expand Up @@ -125,9 +135,9 @@ export function processErrorChunkDev(

function convertModelToJSON(
request: Request,
parent: {+[key: string]: ReactModel} | $ReadOnlyArray<ReactModel>,
parent: {+[key: string]: ReactClientValue} | $ReadOnlyArray<ReactClientValue>,
key: string,
model: ReactModel,
model: ReactClientValue,
): JSONValue {
const json = resolveModelToJSON(request, parent, key, model);
if (typeof json === 'object' && json !== null) {
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,12 @@ import type {
RejectedThenable,
} from 'shared/ReactTypes';

export type WebpackSSRMap = {
export type SSRManifest = {
[clientId: string]: {
[clientExportName: string]: ClientReference<any>,
},
};

export type BundlerConfig = WebpackSSRMap;

export opaque type ClientReferenceMetadata = {
id: string,
chunks: Array<string>,
Expand All @@ -34,7 +32,7 @@ export opaque type ClientReference<T> = {
};

export function resolveClientReference<T>(
bundlerConfig: BundlerConfig,
bundlerConfig: SSRManifest,
metadata: ClientReferenceMetadata,
): ClientReference<T> {
const resolvedModuleData = bundlerConfig[metadata.id][metadata.name];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<string>,
Expand All @@ -32,7 +30,7 @@ export opaque type ClientReferenceMetadata = {
export opaque type ClientReference<T> = ClientReferenceMetadata;

export function resolveClientReference<T>(
bundlerConfig: BundlerConfig,
bundlerConfig: SSRManifest,
metadata: ClientReferenceMetadata,
): ClientReference<T> {
if (bundlerConfig) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -30,7 +30,7 @@ function noServerCall() {
}

export type Options = {
moduleMap?: BundlerConfig,
moduleMap?: SSRManifest,
};

function createResponseFromOptions(options: void | Options) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand All @@ -34,7 +34,7 @@ function noServerCall() {

function createFromNodeStream<T>(
stream: Readable,
moduleMap: $NonMaybeType<BundlerConfig>,
moduleMap: $NonMaybeType<SSRManifest>,
): Thenable<T> {
const response: Response = createResponse(moduleMap, noServerCall);
stream.on('data', chunk => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -26,8 +26,8 @@ type Options = {
};

function renderToReadableStream(
model: ReactModel,
webpackMap: BundlerConfig,
model: ReactClientValue,
webpackMap: ClientManifest,
options?: Options,
): ReadableStream {
const request = createRequest(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -26,8 +26,8 @@ type Options = {
};

function renderToReadableStream(
model: ReactModel,
webpackMap: BundlerConfig,
model: ReactClientValue,
webpackMap: ClientManifest,
options?: Options,
): ReadableStream {
const request = createRequest(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand All @@ -36,8 +39,8 @@ type PipeableStream = {
};

function renderToPipeableStream(
model: ReactModel,
webpackMap: BundlerConfig,
model: ReactClientValue,
webpackMap: ClientManifest,
options?: Options,
): PipeableStream {
const request = createRequest(
Expand Down
Loading

0 comments on commit 2b003a5

Please sign in to comment.