/
githubmr
/
facebook-react
Обзор
Документация
Войти
/
githubmr
/
facebook-react
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
main
packages/react-server-dom-parcel/src/server/ReactFlightDOMServerBrowser.js
291 строка
8 KB
Jan Kassens
Update Flow to 0.279 (#34277)
25 авг 2025, 18:02
Не верифицирован
25 авг 2025, 18:02
df10309
Код
Авторство
О чём код?
/** * 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 { Request, ReactClientValue, } from 'react-server/src/ReactFlightServer'; import type {ReactFormState, Thenable} from 'shared/ReactTypes'; import { preloadModule, requireModule, resolveServerReference, type ServerManifest, type ServerReferenceId, } from '../client/ReactFlightClientConfigBundlerParcel'; import { createRequest, createPrerenderRequest, startWork, startFlowing, startFlowingDebug, stopFlowing, abort, resolveDebugMessage, closeDebugChannel, } from 'react-server/src/ReactFlightServer'; import { createResponse, close, getRoot, } from 'react-server/src/ReactFlightReplyServer'; import { decodeAction as decodeActionImpl, decodeFormState as decodeFormStateImpl, } from 'react-server/src/ReactFlightActionServer'; export { createClientReference, registerServerReference, } from '../ReactFlightParcelReferences'; import { createStringDecoder, readPartialStringChunk, readFinalStringChunk, } from 'react-client/src/ReactFlightClientStreamConfigWeb'; import type {TemporaryReferenceSet} from 'react-server/src/ReactFlightServerTemporaryReferences'; export {createTemporaryReferenceSet} from 'react-server/src/ReactFlightServerTemporaryReferences'; export type {TemporaryReferenceSet}; type Options = { debugChannel?: {readable?: ReadableStream, writable?: WritableStream, ...}, environmentName?: string | (() => string), filterStackFrame?: (url: string, functionName: string) => boolean, identifierPrefix?: string, signal?: AbortSignal, temporaryReferences?: TemporaryReferenceSet, onError?: (error: mixed) => void, onPostpone?: (reason: string) => void, }; function startReadingFromDebugChannelReadableStream( request: Request, stream: ReadableStream, ): void { const reader = stream.getReader(); const stringDecoder = createStringDecoder(); let stringBuffer = ''; function progress({ done, value, }: { done: boolean, value: ?any, ... }): void | Promise<void> { const buffer: Uint8Array = (value: any); stringBuffer += done ? readFinalStringChunk(stringDecoder, new Uint8Array(0)) : readPartialStringChunk(stringDecoder, buffer); const messages = stringBuffer.split('\n'); for (let i = 0; i < messages.length - 1; i++) { resolveDebugMessage(request, messages[i]); } stringBuffer = messages[messages.length - 1]; if (done) { closeDebugChannel(request); return; } return reader.read().then(progress).catch(error); } function error(e: any) { abort( request, new Error('Lost connection to the Debug Channel.', { cause: e, }), ); } reader.read().then(progress).catch(error); } export function renderToReadableStream( model: ReactClientValue, options?: Options, ): ReadableStream { const debugChannelReadable = __DEV__ && options && options.debugChannel ? options.debugChannel.readable : undefined; const debugChannelWritable = __DEV__ && options && options.debugChannel ? options.debugChannel.writable : undefined; const request = createRequest( model, null, 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, debugChannelReadable !== 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); } } if (debugChannelWritable !== undefined) { const debugStream = new ReadableStream( { type: 'bytes', pull: (controller): ?Promise<void> => { startFlowingDebug(request, controller); }, }, // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams. {highWaterMark: 0}, ); debugStream.pipeTo(debugChannelWritable); } if (debugChannelReadable !== undefined) { startReadingFromDebugChannelReadableStream(request, debugChannelReadable); } 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; } type StaticResult = { prelude: ReadableStream, }; export function prerender( model: ReactClientValue, options?: Options, ): Promise<StaticResult> { return new Promise((resolve, reject) => { const onFatalError = reject; function onAllReady() { const stream = new ReadableStream( { type: 'bytes', 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}, ); resolve({prelude: stream}); } const request = createPrerenderRequest( model, null, onAllReady, onFatalError, 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, false, ); if (options && options.signal) { const signal = options.signal; if (signal.aborted) { const reason = (signal: any).reason; abort(request, reason); } else { const listener = () => { const reason = (signal: any).reason; abort(request, reason); signal.removeEventListener('abort', listener); }; signal.addEventListener('abort', listener); } } startWork(request); }); } let serverManifest: ServerManifest = {}; export function registerServerActions(manifest: ServerManifest) { // This function is called by the bundler to register the manifest. serverManifest = manifest; } export function decodeReply<T>( body: string | FormData, options?: {temporaryReferences?: TemporaryReferenceSet}, ): Thenable<T> { if (typeof body === 'string') { const form = new FormData(); form.append('0', body); body = form; } const response = createResponse( serverManifest, '', options ? options.temporaryReferences : undefined, body, ); const root = getRoot<T>(response); close(response); return root; } export function decodeAction<T>(body: FormData): Promise<() => T> | null { return decodeActionImpl(body, serverManifest); } export function decodeFormState<S>( actionResult: S, body: FormData, ): Promise<ReactFormState<S, ServerReferenceId> | null> { return decodeFormStateImpl(actionResult, body, serverManifest); } export function loadServerAction<F: (...any[]) => any>(id: string): Promise<F> { const reference = resolveServerReference<any>(serverManifest, id); return Promise.resolve(reference) .then(() => preloadModule(reference)) .then(() => { const fn = requireModule(reference); if (typeof fn !== 'function') { throw new Error('Server actions must be functions'); } return fn; }); }