mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Defaults to true in browser builds, otherwise defaults to false. The assumption is that the server logs will already contain a log from the original Flight server. We currently always replay console logs but this leads to duplicates on the server by default when you use SSR, because the Flight Client on the server replays the logs. This can be nice since those logs gets badged. It can also be nice if they're running in separate servers but when they're logging to the same stream it's annoying. Which is really the typical set up so we should just make that the default but leave it configurable.
141 lines
3.4 KiB
JavaScript
141 lines
3.4 KiB
JavaScript
/**
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
* @flow
|
|
*/
|
|
|
|
import type {Thenable} from 'shared/ReactTypes.js';
|
|
|
|
import type {
|
|
Response as FlightResponse,
|
|
FindSourceMapURLCallback,
|
|
} from 'react-client/src/ReactFlightClient';
|
|
|
|
import type {ReactServerValue} from 'react-client/src/ReactFlightReplyClient';
|
|
|
|
import {
|
|
createResponse,
|
|
getRoot,
|
|
reportGlobalError,
|
|
processBinaryChunk,
|
|
close,
|
|
} from 'react-client/src/ReactFlightClient';
|
|
|
|
import {
|
|
processReply,
|
|
createServerReference,
|
|
} from 'react-client/src/ReactFlightReplyClient';
|
|
|
|
import type {TemporaryReferenceSet} from 'react-client/src/ReactFlightTemporaryReferences';
|
|
|
|
export {createTemporaryReferenceSet} from 'react-client/src/ReactFlightTemporaryReferences';
|
|
|
|
export type {TemporaryReferenceSet};
|
|
|
|
type CallServerCallback = <A, T>(string, args: A) => Promise<T>;
|
|
|
|
export type Options = {
|
|
callServer?: CallServerCallback,
|
|
temporaryReferences?: TemporaryReferenceSet,
|
|
findSourceMapURL?: FindSourceMapURLCallback,
|
|
replayConsoleLogs?: boolean,
|
|
};
|
|
|
|
function createResponseFromOptions(options: void | Options) {
|
|
return createResponse(
|
|
null,
|
|
null,
|
|
options && options.callServer ? options.callServer : undefined,
|
|
undefined, // encodeFormAction
|
|
undefined, // nonce
|
|
options && options.temporaryReferences
|
|
? options.temporaryReferences
|
|
: undefined,
|
|
__DEV__ && options && options.findSourceMapURL
|
|
? options.findSourceMapURL
|
|
: undefined,
|
|
__DEV__ ? (options ? options.replayConsoleLogs !== false : true) : false, // defaults to true
|
|
);
|
|
}
|
|
|
|
function startReadingFromStream(
|
|
response: FlightResponse,
|
|
stream: ReadableStream,
|
|
): void {
|
|
const reader = stream.getReader();
|
|
function progress({
|
|
done,
|
|
value,
|
|
}: {
|
|
done: boolean,
|
|
value: ?any,
|
|
...
|
|
}): void | Promise<void> {
|
|
if (done) {
|
|
close(response);
|
|
return;
|
|
}
|
|
const buffer: Uint8Array = (value: any);
|
|
processBinaryChunk(response, buffer);
|
|
return reader.read().then(progress).catch(error);
|
|
}
|
|
function error(e: any) {
|
|
reportGlobalError(response, e);
|
|
}
|
|
reader.read().then(progress).catch(error);
|
|
}
|
|
|
|
function createFromReadableStream<T>(
|
|
stream: ReadableStream,
|
|
options?: Options,
|
|
): Thenable<T> {
|
|
const response: FlightResponse = createResponseFromOptions(options);
|
|
startReadingFromStream(response, stream);
|
|
return getRoot(response);
|
|
}
|
|
|
|
function createFromFetch<T>(
|
|
promiseForResponse: Promise<Response>,
|
|
options?: Options,
|
|
): Thenable<T> {
|
|
const response: FlightResponse = createResponseFromOptions(options);
|
|
promiseForResponse.then(
|
|
function (r) {
|
|
startReadingFromStream(response, (r.body: any));
|
|
},
|
|
function (e) {
|
|
reportGlobalError(response, e);
|
|
},
|
|
);
|
|
return getRoot(response);
|
|
}
|
|
|
|
function encodeReply(
|
|
value: ReactServerValue,
|
|
options?: {temporaryReferences?: TemporaryReferenceSet},
|
|
): Promise<
|
|
string | URLSearchParams | FormData,
|
|
> /* We don't use URLSearchParams yet but maybe */ {
|
|
return new Promise((resolve, reject) => {
|
|
processReply(
|
|
value,
|
|
'',
|
|
options && options.temporaryReferences
|
|
? options.temporaryReferences
|
|
: undefined,
|
|
resolve,
|
|
reject,
|
|
);
|
|
});
|
|
}
|
|
|
|
export {
|
|
createFromFetch,
|
|
createFromReadableStream,
|
|
encodeReply,
|
|
createServerReference,
|
|
};
|