mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
4b62400765
This lets you customize the filter, for example allowing node_modules or filter out additional functions that you don't want to include when sending the stack to the client. Notably this doesn't filter out Server Components out of the parent stack. Those are just like a view of the tree by name. Not virtual stack frames.
125 lines
3.3 KiB
JavaScript
125 lines
3.3 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 {ReactClientValue} from 'react-server/src/ReactFlightServer';
|
|
import type {Thenable} from 'shared/ReactTypes';
|
|
import type {ClientManifest} from './ReactFlightServerConfigWebpackBundler';
|
|
import type {ServerManifest} from 'react-client/src/ReactFlightClientConfig';
|
|
|
|
import {
|
|
createRequest,
|
|
startWork,
|
|
startFlowing,
|
|
stopFlowing,
|
|
abort,
|
|
} from 'react-server/src/ReactFlightServer';
|
|
|
|
import {
|
|
createResponse,
|
|
close,
|
|
getRoot,
|
|
} from 'react-server/src/ReactFlightReplyServer';
|
|
|
|
import {
|
|
decodeAction,
|
|
decodeFormState,
|
|
} from 'react-server/src/ReactFlightActionServer';
|
|
|
|
export {
|
|
registerServerReference,
|
|
registerClientReference,
|
|
createClientModuleProxy,
|
|
} from './ReactFlightWebpackReferences';
|
|
|
|
import type {TemporaryReferenceSet} from 'react-server/src/ReactFlightServerTemporaryReferences';
|
|
|
|
export {createTemporaryReferenceSet} from 'react-server/src/ReactFlightServerTemporaryReferences';
|
|
|
|
export type {TemporaryReferenceSet};
|
|
|
|
type Options = {
|
|
environmentName?: string | (() => string),
|
|
filterStackFrame?: (url: string, functionName: string) => boolean,
|
|
identifierPrefix?: string,
|
|
signal?: AbortSignal,
|
|
temporaryReferences?: TemporaryReferenceSet,
|
|
onError?: (error: mixed) => void,
|
|
onPostpone?: (reason: string) => void,
|
|
};
|
|
|
|
function renderToReadableStream(
|
|
model: ReactClientValue,
|
|
webpackMap: ClientManifest,
|
|
options?: Options,
|
|
): ReadableStream {
|
|
const request = createRequest(
|
|
model,
|
|
webpackMap,
|
|
options ? options.onError : undefined,
|
|
options ? options.identifierPrefix : undefined,
|
|
options ? options.onPostpone : undefined,
|
|
options ? options.temporaryReferences : undefined,
|
|
__DEV__ && options ? options.environmentName : undefined,
|
|
__DEV__ && options ? options.filterStackFrame : undefined,
|
|
);
|
|
if (options && options.signal) {
|
|
const signal = options.signal;
|
|
if (signal.aborted) {
|
|
abort(request, (signal: any).reason);
|
|
} else {
|
|
const listener = () => {
|
|
abort(request, (signal: any).reason);
|
|
signal.removeEventListener('abort', listener);
|
|
};
|
|
signal.addEventListener('abort', listener);
|
|
}
|
|
}
|
|
const stream = new ReadableStream(
|
|
{
|
|
type: 'bytes',
|
|
start: (controller): ?Promise<void> => {
|
|
startWork(request);
|
|
},
|
|
pull: (controller): ?Promise<void> => {
|
|
startFlowing(request, controller);
|
|
},
|
|
cancel: (reason): ?Promise<void> => {
|
|
stopFlowing(request);
|
|
abort(request, reason);
|
|
},
|
|
},
|
|
// $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.
|
|
{highWaterMark: 0},
|
|
);
|
|
return stream;
|
|
}
|
|
|
|
function decodeReply<T>(
|
|
body: string | FormData,
|
|
webpackMap: ServerManifest,
|
|
options?: {temporaryReferences?: TemporaryReferenceSet},
|
|
): Thenable<T> {
|
|
if (typeof body === 'string') {
|
|
const form = new FormData();
|
|
form.append('0', body);
|
|
body = form;
|
|
}
|
|
const response = createResponse(
|
|
webpackMap,
|
|
'',
|
|
options ? options.temporaryReferences : undefined,
|
|
body,
|
|
);
|
|
const root = getRoot<T>(response);
|
|
close(response);
|
|
return root;
|
|
}
|
|
|
|
export {renderToReadableStream, decodeReply, decodeAction, decodeFormState};
|