mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
c17a27ef49
This PR adds a new FB-specific configuration of Flight. We also need to bundle a version of ReactSharedSubset that will be used for running Flight on the server. This initial implementation does not support server actions yet. The FB-Flight still uses the text protocol on the server (the flag `enableBinaryFlight` is set to false). It looks like we need some changes in Hermes to properly support this binary format.
92 lines
2.2 KiB
JavaScript
92 lines
2.2 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 {enableBinaryFlight} from 'shared/ReactFeatureFlags';
|
|
import type {Thenable} from 'shared/ReactTypes';
|
|
import type {Response as FlightResponse} from 'react-client/src/ReactFlightClient';
|
|
|
|
import {
|
|
createResponse,
|
|
getRoot,
|
|
reportGlobalError,
|
|
processBinaryChunk,
|
|
close,
|
|
} from 'react-client/src/ReactFlightClient';
|
|
|
|
import type {SSRModuleMap} from './ReactFlightClientConfigFBBundler';
|
|
|
|
type Options = {
|
|
moduleMap: SSRModuleMap,
|
|
};
|
|
|
|
function createResponseFromOptions(options: void | Options) {
|
|
const moduleMap = options && options.moduleMap;
|
|
if (moduleMap == null) {
|
|
throw new Error('Expected `moduleMap` to be defined.');
|
|
}
|
|
|
|
return createResponse(moduleMap, null, undefined, undefined);
|
|
}
|
|
|
|
function processChunk(response: FlightResponse, chunk: string | Uint8Array) {
|
|
if (enableBinaryFlight) {
|
|
if (typeof chunk === 'string') {
|
|
throw new Error(
|
|
'`enableBinaryFlight` flag is enabled, expected a Uint8Array as input, got string.',
|
|
);
|
|
}
|
|
}
|
|
const buffer = typeof chunk !== 'string' ? chunk : encodeString(chunk);
|
|
|
|
processBinaryChunk(response, buffer);
|
|
}
|
|
|
|
function encodeString(string: string) {
|
|
const textEncoder = new TextEncoder();
|
|
return textEncoder.encode(string);
|
|
}
|
|
|
|
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);
|
|
processChunk(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);
|
|
}
|
|
|
|
export {createFromReadableStream};
|