mirror of
https://github.com/facebook/react.git
synced 2026-02-26 18:58:05 +00:00
Add aborting to the Flight Server. This encodes the reason as an "error" row that gets thrown client side. These are still exposed in prod which is a follow up we'll still have to do to encode them as digests instead. The error is encoded once and then referenced by each row that needs to be updated.
70 lines
1.7 KiB
JavaScript
70 lines
1.7 KiB
JavaScript
/**
|
|
* Copyright (c) Facebook, Inc. and its 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 {ReactModel} from 'react-server/src/ReactFlightServer';
|
|
import type {BundlerConfig} from './ReactFlightServerWebpackBundlerConfig';
|
|
import type {Writable} from 'stream';
|
|
import type {ServerContextJSONValue} from 'shared/ReactTypes';
|
|
|
|
import {
|
|
createRequest,
|
|
startWork,
|
|
startFlowing,
|
|
abort,
|
|
} from 'react-server/src/ReactFlightServer';
|
|
|
|
function createDrainHandler(destination, request) {
|
|
return () => startFlowing(request, destination);
|
|
}
|
|
|
|
type Options = {
|
|
onError?: (error: mixed) => void,
|
|
context?: Array<[string, ServerContextJSONValue]>,
|
|
identifierPrefix?: string,
|
|
};
|
|
|
|
type PipeableStream = {|
|
|
abort(reason: mixed): void,
|
|
pipe<T: Writable>(destination: T): T,
|
|
|};
|
|
|
|
function renderToPipeableStream(
|
|
model: ReactModel,
|
|
webpackMap: BundlerConfig,
|
|
options?: Options,
|
|
): PipeableStream {
|
|
const request = createRequest(
|
|
model,
|
|
webpackMap,
|
|
options ? options.onError : undefined,
|
|
options ? options.context : undefined,
|
|
options ? options.identifierPrefix : undefined,
|
|
);
|
|
let hasStartedFlowing = false;
|
|
startWork(request);
|
|
return {
|
|
pipe<T: Writable>(destination: T): T {
|
|
if (hasStartedFlowing) {
|
|
throw new Error(
|
|
'React currently only supports piping to one writable stream.',
|
|
);
|
|
}
|
|
hasStartedFlowing = true;
|
|
startFlowing(request, destination);
|
|
destination.on('drain', createDrainHandler(destination, request));
|
|
return destination;
|
|
},
|
|
abort(reason: mixed) {
|
|
abort(request, reason);
|
|
},
|
|
};
|
|
}
|
|
|
|
export {renderToPipeableStream};
|