import type {Chunk, BinaryChunk, Destination} from './ReactServerStreamConfig';
import type {Postpone} from 'react/src/ReactPostpone';
import type {TemporaryReferenceSet} from './ReactFlightServerTemporaryReferences';
import {
enableBinaryFlight,
enablePostpone,
enableHalt,
enableTaint,
enableRefAsProp,
enableServerComponentLogs,
enableOwnerStacks,
} from 'shared/ReactFeatureFlags';
import {enableFlightReadableStream} from 'shared/ReactFeatureFlags';
import {
scheduleWork,
scheduleMicrotask,
flushBuffered,
beginWriting,
writeChunkAndReturn,
stringToChunk,
typedArrayToBinaryChunk,
byteLengthOfChunk,
byteLengthOfBinaryChunk,
completeWriting,
close,
closeWithError,
} from './ReactServerStreamConfig';
export type {Destination, Chunk} from './ReactServerStreamConfig';
import type {
ClientManifest,
ClientReferenceMetadata,
ClientReference,
ClientReferenceKey,
ServerReference,
ServerReferenceId,
Hints,
HintCode,
HintModel,
} from './ReactFlightServerConfig';
import type {ThenableState} from './ReactFlightThenable';
import type {
Wakeable,
Thenable,
PendingThenable,
FulfilledThenable,
RejectedThenable,
ReactDebugInfo,
ReactComponentInfo,
ReactAsyncInfo,
ReactStackTrace,
ReactCallSite,
} from 'shared/ReactTypes';
import type {ReactElement} from 'shared/ReactElementType';
import type {LazyComponent} from 'react/src/ReactLazy';
import {
resolveClientReferenceMetadata,
getServerReferenceId,
getServerReferenceBoundArguments,
getServerReferenceLocation,
getClientReferenceKey,
isClientReference,
isServerReference,
supportsRequestStorage,
requestStorage,
createHints,
initAsyncDebugInfo,
parseStackTrace,
supportsComponentStorage,
componentStorage,
} from './ReactFlightServerConfig';
import {
resolveTemporaryReference,
isOpaqueTemporaryReference,
} from './ReactFlightServerTemporaryReferences';
import {
HooksDispatcher,
prepareToUseHooksForRequest,
prepareToUseHooksForComponent,
getThenableStateAfterSuspending,
resetHooksForRequest,
} from './ReactFlightHooks';
import {DefaultAsyncDispatcher} from './flight/ReactFlightAsyncDispatcher';
import {resolveOwner, setCurrentOwner} from './flight/ReactFlightCurrentOwner';
import {getOwnerStackByComponentInfoInDev} from 'shared/ReactComponentInfoStack';
import {
callComponentInDEV,
callLazyInitInDEV,
callIteratorInDEV,
} from './ReactFlightCallUserSpace';
import {
getIteratorFn,
REACT_ELEMENT_TYPE,
REACT_LEGACY_ELEMENT_TYPE,
REACT_FORWARD_REF_TYPE,
REACT_FRAGMENT_TYPE,
REACT_LAZY_TYPE,
REACT_MEMO_TYPE,
REACT_POSTPONE_TYPE,
ASYNC_ITERATOR,
} from 'shared/ReactSymbols';
import {
describeObjectForErrorMessage,
isSimpleObject,
jsxPropsParents,
jsxChildrenParents,
objectName,
} from 'shared/ReactSerializationErrors';
import ReactSharedInternals from './ReactSharedInternalsServer';
import isArray from 'shared/isArray';
import getPrototypeOf from 'shared/getPrototypeOf';
import binaryToComparableString from 'shared/binaryToComparableString';
import {SuspenseException, getSuspendedThenable} from './ReactFlightThenable';
function defaultFilterStackFrame(
filename: string,
functionName: string,
): boolean {
return (
filename !== '' &&
!filename.startsWith('node:') &&
!filename.includes('node_modules')
);
}
function filterStackTrace(
request: Request,
error: Error,
skipFrames: number,
): ReactStackTrace {
const filterStackFrame = request.filterStackFrame;
const stack = parseStackTrace(error, skipFrames);
for (let i = 0; i < stack.length; i++) {
const callsite = stack[i];
const functionName = callsite[0];
let url = callsite[1];
if (url.startsWith('rsc://React/')) {
const envIdx = url.indexOf('/', 12);
const suffixIdx = url.lastIndexOf('?');
if (envIdx > -1 && suffixIdx > -1) {
url = callsite[1] = url.slice(envIdx + 1, suffixIdx);
}
}
if (!filterStackFrame(url, functionName)) {
stack.splice(i, 1);
i--;
}
}
return stack;
}
initAsyncDebugInfo();
function patchConsole(consoleInst: typeof console, methodName: string) {
const descriptor = Object.getOwnPropertyDescriptor(consoleInst, methodName);
if (
descriptor &&
(descriptor.configurable || descriptor.writable) &&
typeof descriptor.value === 'function'
) {
const originalMethod = descriptor.value;
const originalName = Object.getOwnPropertyDescriptor(
originalMethod,
'name',
);
const wrapperMethod = function (this: typeof console) {
const request = resolveRequest();
if (methodName === 'assert' && arguments[0]) {
} else if (request !== null) {
const stack = filterStackTrace(
request,
new Error('react-stack-top-frame'),
1,
);
request.pendingChunks++;
const id = request.nextChunkId++;
const owner: null | ReactComponentInfo = resolveOwner();
emitConsoleChunk(request, id, methodName, owner, stack, arguments);
}
return originalMethod.apply(this, arguments);
};
if (originalName) {
Object.defineProperty(
wrapperMethod,
'name',
originalName,
);
}
Object.defineProperty(consoleInst, methodName, {
value: wrapperMethod,
});
}
}
if (
enableServerComponentLogs &&
__DEV__ &&
typeof console === 'object' &&
console !== null
) {
patchConsole(console, 'assert');
patchConsole(console, 'debug');
patchConsole(console, 'dir');
patchConsole(console, 'dirxml');
patchConsole(console, 'error');
patchConsole(console, 'group');
patchConsole(console, 'groupCollapsed');
patchConsole(console, 'groupEnd');
patchConsole(console, 'info');
patchConsole(console, 'log');
patchConsole(console, 'table');
patchConsole(console, 'trace');
patchConsole(console, 'warn');
}
function getCurrentStackInDEV(): string {
if (__DEV__) {
if (enableOwnerStacks) {
const owner: null | ReactComponentInfo = resolveOwner();
if (owner === null) {
return '';
}
return getOwnerStackByComponentInfoInDev(owner);
}
return '';
}
return '';
}
const ObjectPrototype = Object.prototype;
type JSONValue =
| string
| boolean
| number
| null
| {+[key: string]: JSONValue}
| $ReadOnlyArray<JSONValue>;
const stringify = JSON.stringify;
type ReactJSONValue =
| string
| boolean
| number
| null
| $ReadOnlyArray<ReactClientValue>
| ReactClientObject;
export type ReactClientValue =
| React$Element<React$AbstractComponent<any, any>>
| LazyComponent<ReactClientValue, any>
| ClientReference<any>
| ServerReference<any>
| React$Element<string>
| React$Element<ClientReference<any> & any>
| ReactComponentInfo
| string
| boolean
| number
| symbol
| null
| void
| bigint
| ReadableStream
| $AsyncIterable<ReactClientValue, ReactClientValue, void>
| $AsyncIterator<ReactClientValue, ReactClientValue, void>
| Iterable<ReactClientValue>
| Iterator<ReactClientValue>
| Array<ReactClientValue>
| Map<ReactClientValue, ReactClientValue>
| Set<ReactClientValue>
| FormData
| $ArrayBufferView
| ArrayBuffer
| Date
| ReactClientObject
| Promise<ReactClientValue>;
type ReactClientObject = {+[key: string]: ReactClientValue};
const PENDING = 0;
const COMPLETED = 1;
const ABORTED = 3;
const ERRORED = 4;
const RENDERING = 5;
type Task = {
id: number,
status: 0 | 1 | 3 | 4 | 5,
model: ReactClientValue,
ping: () => void,
toJSON: (key: string, value: ReactClientValue) => ReactJSONValue,
keyPath: null | string,
implicitSlot: boolean,
thenableState: ThenableState | null,
environmentName: string,
debugOwner: null | ReactComponentInfo,
debugStack: null | Error,
debugTask: null | ConsoleTask,
};
interface Reference {}
const OPENING = 10;
const OPEN = 11;
const ABORTING = 12;
const CLOSING = 13;
const CLOSED = 14;
const RENDER = 20;
const PRERENDER = 21;
export type Request = {
status: 10 | 11 | 12 | 13 | 14,
type: 20 | 21,
flushScheduled: boolean,
fatalError: mixed,
destination: null | Destination,
bundlerConfig: ClientManifest,
cache: Map<Function, mixed>,
nextChunkId: number,
pendingChunks: number,
hints: Hints,
abortListeners: Set<(reason: mixed) => void>,
abortableTasks: Set<Task>,
pingedTasks: Array<Task>,
completedImportChunks: Array<Chunk>,
completedHintChunks: Array<Chunk>,
completedRegularChunks: Array<Chunk | BinaryChunk>,
completedErrorChunks: Array<Chunk>,
writtenSymbols: Map<symbol, number>,
writtenClientReferences: Map<ClientReferenceKey, number>,
writtenServerReferences: Map<ServerReference<any>, number>,
writtenObjects: WeakMap<Reference, string>,
temporaryReferences: void | TemporaryReferenceSet,
identifierPrefix: string,
identifierCount: number,
taintCleanupQueue: Array<string | bigint>,
onError: (error: mixed) => ?string,
onPostpone: (reason: string) => void,
onAllReady: () => void,
onFatalError: mixed => void,
environmentName: () => string,
filterStackFrame: (url: string, functionName: string) => boolean,
didWarnForKey: null | WeakSet<ReactComponentInfo>,
};
const {
TaintRegistryObjects,
TaintRegistryValues,
TaintRegistryByteLengths,
TaintRegistryPendingRequests,
} = ReactSharedInternals;
function throwTaintViolation(message: string) {
throw new Error(message);
}
function cleanupTaintQueue(request: Request): void {
const cleanupQueue = request.taintCleanupQueue;
TaintRegistryPendingRequests.delete(cleanupQueue);
for (let i = 0; i < cleanupQueue.length; i++) {
const entryValue = cleanupQueue[i];
const entry = TaintRegistryValues.get(entryValue);
if (entry !== undefined) {
if (entry.count === 1) {
TaintRegistryValues.delete(entryValue);
} else {
entry.count--;
}
}
}
cleanupQueue.length = 0;
}
function defaultErrorHandler(error: mixed) {
console['error'](error);
}
function defaultPostponeHandler(reason: string) {
}
function RequestInstance(
this: $FlowFixMe,
type: 20 | 21,
model: ReactClientValue,
bundlerConfig: ClientManifest,
onError: void | ((error: mixed) => ?string),
identifierPrefix?: string,
onPostpone: void | ((reason: string) => void),
temporaryReferences: void | TemporaryReferenceSet,
environmentName: void | string | (() => string),
filterStackFrame: void | ((url: string, functionName: string) => boolean),
onAllReady: () => void,
onFatalError: (error: mixed) => void,
) {
if (
ReactSharedInternals.A !== null &&
ReactSharedInternals.A !== DefaultAsyncDispatcher
) {
throw new Error(
'Currently React only supports one RSC renderer at a time.',
);
}
ReactSharedInternals.A = DefaultAsyncDispatcher;
if (__DEV__) {
ReactSharedInternals.getCurrentStack = getCurrentStackInDEV;
}
const abortSet: Set<Task> = new Set();
const pingedTasks: Array<Task> = [];
const cleanupQueue: Array<string | bigint> = [];
if (enableTaint) {
TaintRegistryPendingRequests.add(cleanupQueue);
}
const hints = createHints();
this.type = type;
this.status = OPENING;
this.flushScheduled = false;
this.fatalError = null;
this.destination = null;
this.bundlerConfig = bundlerConfig;
this.cache = new Map();
this.nextChunkId = 0;
this.pendingChunks = 0;
this.hints = hints;
this.abortListeners = new Set();
this.abortableTasks = abortSet;
this.pingedTasks = pingedTasks;
this.completedImportChunks = ([]: Array<Chunk>);
this.completedHintChunks = ([]: Array<Chunk>);
this.completedRegularChunks = ([]: Array<Chunk | BinaryChunk>);
this.completedErrorChunks = ([]: Array<Chunk>);
this.writtenSymbols = new Map();
this.writtenClientReferences = new Map();
this.writtenServerReferences = new Map();
this.writtenObjects = new WeakMap();
this.temporaryReferences = temporaryReferences;
this.identifierPrefix = identifierPrefix || '';
this.identifierCount = 1;
this.taintCleanupQueue = cleanupQueue;
this.onError = onError === undefined ? defaultErrorHandler : onError;
this.onPostpone =
onPostpone === undefined ? defaultPostponeHandler : onPostpone;
this.onAllReady = onAllReady;
this.onFatalError = onFatalError;
if (__DEV__) {
this.environmentName =
environmentName === undefined
? () => 'Server'
: typeof environmentName !== 'function'
? () => environmentName
: environmentName;
this.filterStackFrame =
filterStackFrame === undefined
? defaultFilterStackFrame
: filterStackFrame;
this.didWarnForKey = null;
}
const rootTask = createTask(
this,
model,
null,
false,
abortSet,
null,
null,
null,
);
pingedTasks.push(rootTask);
}
function noop() {}
export function createRequest(
model: ReactClientValue,
bundlerConfig: ClientManifest,
onError: void | ((error: mixed) => ?string),
identifierPrefix?: string,
onPostpone: void | ((reason: string) => void),
temporaryReferences: void | TemporaryReferenceSet,
environmentName: void | string | (() => string),
filterStackFrame: void | ((url: string, functionName: string) => boolean),
): Request {
return new RequestInstance(
RENDER,
model,
bundlerConfig,
onError,
identifierPrefix,
onPostpone,
temporaryReferences,
environmentName,
filterStackFrame,
noop,
noop,
);
}
export function createPrerenderRequest(
model: ReactClientValue,
bundlerConfig: ClientManifest,
onAllReady: () => void,
onFatalError: () => void,
onError: void | ((error: mixed) => ?string),
identifierPrefix?: string,
onPostpone: void | ((reason: string) => void),
temporaryReferences: void | TemporaryReferenceSet,
environmentName: void | string | (() => string),
filterStackFrame: void | ((url: string, functionName: string) => boolean),
): Request {
return new RequestInstance(
PRERENDER,
model,
bundlerConfig,
onError,
identifierPrefix,
onPostpone,
temporaryReferences,
environmentName,
filterStackFrame,
onAllReady,
onFatalError,
);
}
let currentRequest: null | Request = null;
export function resolveRequest(): null | Request {
if (currentRequest) return currentRequest;
if (supportsRequestStorage) {
const store = requestStorage.getStore();
if (store) return store;
}
return null;
}
function serializeThenable(
request: Request,
task: Task,
thenable: Thenable<any>,
): number {
const newTask = createTask(
request,
null,
task.keyPath,
task.implicitSlot,
request.abortableTasks,
__DEV__ ? task.debugOwner : null,
__DEV__ && enableOwnerStacks ? task.debugStack : null,
__DEV__ && enableOwnerStacks ? task.debugTask : null,
);
if (__DEV__) {
const debugInfo: ?ReactDebugInfo = (thenable: any)._debugInfo;
if (debugInfo) {
forwardDebugInfo(request, newTask.id, debugInfo);
}
}
switch (thenable.status) {
case 'fulfilled': {
newTask.model = thenable.value;
pingTask(request, newTask);
return newTask.id;
}
case 'rejected': {
const x = thenable.reason;
if (
enablePostpone &&
typeof x === 'object' &&
x !== null &&
(x: any).$$typeof === REACT_POSTPONE_TYPE
) {
const postponeInstance: Postpone = (x: any);
logPostpone(request, postponeInstance.message, newTask);
emitPostponeChunk(request, newTask.id, postponeInstance);
} else {
const digest = logRecoverableError(request, x, null);
emitErrorChunk(request, newTask.id, digest, x);
}
newTask.status = ERRORED;
request.abortableTasks.delete(newTask);
return newTask.id;
}
default: {
if (request.status === ABORTING) {
request.abortableTasks.delete(newTask);
newTask.status = ABORTED;
if (enableHalt && request.type === PRERENDER) {
request.pendingChunks--;
} else {
const errorId: number = (request.fatalError: any);
const model = stringify(serializeByValueID(errorId));
emitModelChunk(request, newTask.id, model);
}
return newTask.id;
}
if (typeof thenable.status === 'string') {
break;
}
const pendingThenable: PendingThenable<mixed> = (thenable: any);
pendingThenable.status = 'pending';
pendingThenable.then(
fulfilledValue => {
if (thenable.status === 'pending') {
const fulfilledThenable: FulfilledThenable<mixed> = (thenable: any);
fulfilledThenable.status = 'fulfilled';
fulfilledThenable.value = fulfilledValue;
}
},
(error: mixed) => {
if (thenable.status === 'pending') {
const rejectedThenable: RejectedThenable<mixed> = (thenable: any);
rejectedThenable.status = 'rejected';
rejectedThenable.reason = error;
}
},
);
break;
}
}
thenable.then(
value => {
newTask.model = value;
pingTask(request, newTask);
},
reason => {
if (
enablePostpone &&
typeof reason === 'object' &&
reason !== null &&
(reason: any).$$typeof === REACT_POSTPONE_TYPE
) {
const postponeInstance: Postpone = (reason: any);
logPostpone(request, postponeInstance.message, newTask);
emitPostponeChunk(request, newTask.id, postponeInstance);
} else {
const digest = logRecoverableError(request, reason, newTask);
emitErrorChunk(request, newTask.id, digest, reason);
}
newTask.status = ERRORED;
request.abortableTasks.delete(newTask);
enqueueFlush(request);
},
);
return newTask.id;
}
function serializeReadableStream(
request: Request,
task: Task,
stream: ReadableStream,
): string {
let supportsBYOB: void | boolean = stream.supportsBYOB;
if (supportsBYOB === undefined) {
try {
stream.getReader({mode: 'byob'}).releaseLock();
supportsBYOB = true;
} catch (x) {
supportsBYOB = false;
}
}
const reader = stream.getReader();
const streamTask = createTask(
request,
task.model,
task.keyPath,
task.implicitSlot,
request.abortableTasks,
__DEV__ ? task.debugOwner : null,
__DEV__ && enableOwnerStacks ? task.debugStack : null,
__DEV__ && enableOwnerStacks ? task.debugTask : null,
);
request.abortableTasks.delete(streamTask);
request.pendingChunks++;
const startStreamRow =
streamTask.id.toString(16) + ':' + (supportsBYOB ? 'r' : 'R') + '\n';
request.completedRegularChunks.push(stringToChunk(startStreamRow));
let aborted = false;
function progress(entry: {done: boolean, value: ReactClientValue, ...}) {
if (aborted) {
return;
}
if (entry.done) {
request.abortListeners.delete(abortStream);
const endStreamRow = streamTask.id.toString(16) + ':C\n';
request.completedRegularChunks.push(stringToChunk(endStreamRow));
enqueueFlush(request);
aborted = true;
} else {
try {
streamTask.model = entry.value;
request.pendingChunks++;
tryStreamTask(request, streamTask);
enqueueFlush(request);
reader.read().then(progress, error);
} catch (x) {
error(x);
}
}
}
function error(reason: mixed) {
if (aborted) {
return;
}
aborted = true;
request.abortListeners.delete(abortStream);
const digest = logRecoverableError(request, reason, streamTask);
emitErrorChunk(request, streamTask.id, digest, reason);
enqueueFlush(request);
reader.cancel(reason).then(error, error);
}
function abortStream(reason: mixed) {
if (aborted) {
return;
}
aborted = true;
request.abortListeners.delete(abortStream);
if (
enablePostpone &&
typeof reason === 'object' &&
reason !== null &&
(reason: any).$$typeof === REACT_POSTPONE_TYPE
) {
const postponeInstance: Postpone = (reason: any);
logPostpone(request, postponeInstance.message, streamTask);
if (enableHalt && request.type === PRERENDER) {
request.pendingChunks--;
} else {
emitPostponeChunk(request, streamTask.id, postponeInstance);
enqueueFlush(request);
}
} else {
const digest = logRecoverableError(request, reason, streamTask);
if (enableHalt && request.type === PRERENDER) {
request.pendingChunks--;
} else {
emitErrorChunk(request, streamTask.id, digest, reason);
enqueueFlush(request);
}
}
reader.cancel(reason).then(error, error);
}
request.abortListeners.add(abortStream);
reader.read().then(progress, error);
return serializeByValueID(streamTask.id);
}
function serializeAsyncIterable(
request: Request,
task: Task,
iterable: $AsyncIterable<ReactClientValue, ReactClientValue, void>,
iterator: $AsyncIterator<ReactClientValue, ReactClientValue, void>,
): string {
const isIterator = iterable === iterator;
const streamTask = createTask(
request,
task.model,
task.keyPath,
task.implicitSlot,
request.abortableTasks,
__DEV__ ? task.debugOwner : null,
__DEV__ && enableOwnerStacks ? task.debugStack : null,
__DEV__ && enableOwnerStacks ? task.debugTask : null,
);
request.abortableTasks.delete(streamTask);
request.pendingChunks++;
const startStreamRow =
streamTask.id.toString(16) + ':' + (isIterator ? 'x' : 'X') + '\n';
request.completedRegularChunks.push(stringToChunk(startStreamRow));
if (__DEV__) {
const debugInfo: ?ReactDebugInfo = (iterable: any)._debugInfo;
if (debugInfo) {
forwardDebugInfo(request, streamTask.id, debugInfo);
}
}
let aborted = false;
function progress(
entry:
| {done: false, +value: ReactClientValue, ...}
| {done: true, +value: ReactClientValue, ...},
) {
if (aborted) {
return;
}
if (entry.done) {
request.abortListeners.delete(abortIterable);
let endStreamRow;
if (entry.value === undefined) {
endStreamRow = streamTask.id.toString(16) + ':C\n';
} else {
try {
const chunkId = outlineModel(request, entry.value);
endStreamRow =
streamTask.id.toString(16) +
':C' +
stringify(serializeByValueID(chunkId)) +
'\n';
} catch (x) {
error(x);
return;
}
}
request.completedRegularChunks.push(stringToChunk(endStreamRow));
enqueueFlush(request);
aborted = true;
} else {
try {
streamTask.model = entry.value;
request.pendingChunks++;
tryStreamTask(request, streamTask);
enqueueFlush(request);
if (__DEV__) {
callIteratorInDEV(iterator, progress, error);
} else {
iterator.next().then(progress, error);
}
} catch (x) {
error(x);
return;
}
}
}
function error(reason: mixed) {
if (aborted) {
return;
}
aborted = true;
request.abortListeners.delete(abortIterable);
const digest = logRecoverableError(request, reason, streamTask);
emitErrorChunk(request, streamTask.id, digest, reason);
enqueueFlush(request);
if (typeof (iterator: any).throw === 'function') {
iterator.throw(reason).then(error, error);
}
}
function abortIterable(reason: mixed) {
if (aborted) {
return;
}
aborted = true;
request.abortListeners.delete(abortIterable);
if (
enablePostpone &&
typeof reason === 'object' &&
reason !== null &&
(reason: any).$$typeof === REACT_POSTPONE_TYPE
) {
const postponeInstance: Postpone = (reason: any);
logPostpone(request, postponeInstance.message, streamTask);
if (enableHalt && request.type === PRERENDER) {
request.pendingChunks--;
} else {
emitPostponeChunk(request, streamTask.id, postponeInstance);
enqueueFlush(request);
}
} else {
const digest = logRecoverableError(request, reason, streamTask);
if (enableHalt && request.type === PRERENDER) {
request.pendingChunks--;
} else {
emitErrorChunk(request, streamTask.id, digest, reason);
enqueueFlush(request);
}
}
if (typeof (iterator: any).throw === 'function') {
iterator.throw(reason).then(error, error);
}
}
request.abortListeners.add(abortIterable);
if (__DEV__) {
callIteratorInDEV(iterator, progress, error);
} else {
iterator.next().then(progress, error);
}
return serializeByValueID(streamTask.id);
}
export function emitHint<Code: HintCode>(
request: Request,
code: Code,
model: HintModel<Code>,
): void {
emitHintChunk(request, code, model);
enqueueFlush(request);
}
export function getHints(request: Request): Hints {
return request.hints;
}
export function getCache(request: Request): Map<Function, mixed> {
return request.cache;
}
function readThenable<T>(thenable: Thenable<T>): T {
if (thenable.status === 'fulfilled') {
return thenable.value;
} else if (thenable.status === 'rejected') {
throw thenable.reason;
}
throw thenable;
}
function createLazyWrapperAroundWakeable(wakeable: Wakeable) {
const thenable: Thenable<mixed> = (wakeable: any);
switch (thenable.status) {
case 'fulfilled':
case 'rejected':
break;
default: {
if (typeof thenable.status === 'string') {
break;
}
const pendingThenable: PendingThenable<mixed> = (thenable: any);
pendingThenable.status = 'pending';
pendingThenable.then(
fulfilledValue => {
if (thenable.status === 'pending') {
const fulfilledThenable: FulfilledThenable<mixed> = (thenable: any);
fulfilledThenable.status = 'fulfilled';
fulfilledThenable.value = fulfilledValue;
}
},
(error: mixed) => {
if (thenable.status === 'pending') {
const rejectedThenable: RejectedThenable<mixed> = (thenable: any);
rejectedThenable.status = 'rejected';
rejectedThenable.reason = error;
}
},
);
break;
}
}
const lazyType: LazyComponent<any, Thenable<any>> = {
$$typeof: REACT_LAZY_TYPE,
_payload: thenable,
_init: readThenable,
};
if (__DEV__) {
lazyType._debugInfo = (thenable: any)._debugInfo || [];
}
return lazyType;
}
function callWithDebugContextInDEV<A, T>(
request: Request,
task: Task,
callback: A => T,
arg: A,
): T {
const componentDebugInfo: ReactComponentInfo = {
name: '',
env: task.environmentName,
key: null,
owner: task.debugOwner,
};
if (enableOwnerStacks) {
componentDebugInfo.stack =
task.debugStack === null
? null
: filterStackTrace(request, task.debugStack, 1);
componentDebugInfo.debugStack = task.debugStack;
componentDebugInfo.debugTask = task.debugTask;
}
const debugTask = task.debugTask;
setCurrentOwner(componentDebugInfo);
try {
if (enableOwnerStacks && debugTask) {
return debugTask.run(callback.bind(null, arg));
}
return callback(arg);
} finally {
setCurrentOwner(null);
}
}
const voidHandler = () => {};
function renderFunctionComponent<Props>(
request: Request,
task: Task,
key: null | string,
Component: (p: Props, arg: void) => any,
props: Props,
validated: number,
): ReactJSONValue {
const prevThenableState = task.thenableState;
task.thenableState = null;
let result;
let componentDebugInfo: ReactComponentInfo;
if (__DEV__) {
if (debugID === null) {
return outlineTask(request, task);
} else if (prevThenableState !== null) {
componentDebugInfo = (prevThenableState: any)._componentDebugInfo;
} else {
const componentDebugID = debugID;
const componentName =
(Component: any).displayName || Component.name || '';
const componentEnv = (0, request.environmentName)();
request.pendingChunks++;
componentDebugInfo = ({
name: componentName,
env: componentEnv,
key: key,
owner: task.debugOwner,
}: ReactComponentInfo);
if (enableOwnerStacks) {
componentDebugInfo.stack =
task.debugStack === null
? null
: filterStackTrace(request, task.debugStack, 1);
componentDebugInfo.props = props;
componentDebugInfo.debugStack = task.debugStack;
componentDebugInfo.debugTask = task.debugTask;
} else {
componentDebugInfo.props = props;
}
outlineComponentInfo(request, componentDebugInfo);
emitDebugChunk(request, componentDebugID, componentDebugInfo);
task.environmentName = componentEnv;
if (enableOwnerStacks && validated === 2) {
warnForMissingKey(request, key, componentDebugInfo, task.debugTask);
}
}
prepareToUseHooksForComponent(prevThenableState, componentDebugInfo);
if (supportsComponentStorage) {
if (enableOwnerStacks && task.debugTask) {
result = task.debugTask.run(
componentStorage.run.bind(
componentStorage,
componentDebugInfo,
callComponentInDEV,
Component,
props,
componentDebugInfo,
),
);
} else {
result = componentStorage.run(
componentDebugInfo,
callComponentInDEV,
Component,
props,
componentDebugInfo,
);
}
} else {
if (enableOwnerStacks && task.debugTask) {
result = task.debugTask.run(
callComponentInDEV.bind(null, Component, props, componentDebugInfo),
);
} else {
result = callComponentInDEV(Component, props, componentDebugInfo);
}
}
} else {
prepareToUseHooksForComponent(prevThenableState, null);
const secondArg = undefined;
result = Component(props, secondArg);
}
if (request.status === ABORTING) {
if (
typeof result === 'object' &&
result !== null &&
typeof result.then === 'function' &&
!isClientReference(result)
) {
result.then(voidHandler, voidHandler);
}
throw null;
}
if (
typeof result === 'object' &&
result !== null &&
!isClientReference(result)
) {
if (typeof result.then === 'function') {
const thenable: Thenable<any> = result;
if (__DEV__) {
thenable.then(resolvedValue => {
if (
typeof resolvedValue === 'object' &&
resolvedValue !== null &&
resolvedValue.$$typeof === REACT_ELEMENT_TYPE
) {
resolvedValue._store.validated = 1;
}
}, voidHandler);
}
if (thenable.status === 'fulfilled') {
return thenable.value;
}
result = createLazyWrapperAroundWakeable(result);
}
const iteratorFn = getIteratorFn(result);
if (iteratorFn) {
const iterableChild = result;
result = {
[Symbol.iterator]: function () {
const iterator = iteratorFn.call(iterableChild);
if (__DEV__) {
if (iterator === iterableChild) {
const isGeneratorComponent =
Object.prototype.toString.call(Component) ===
'[object GeneratorFunction]' &&
Object.prototype.toString.call(iterableChild) ===
'[object Generator]';
if (!isGeneratorComponent) {
callWithDebugContextInDEV(request, task, () => {
console.error(
'Returning an Iterator from a Server Component is not supported ' +
'since it cannot be looped over more than once. ',
);
});
}
}
}
return (iterator: any);
},
};
if (__DEV__) {
(result: any)._debugInfo = iterableChild._debugInfo;
}
} else if (
enableFlightReadableStream &&
typeof (result: any)[ASYNC_ITERATOR] === 'function' &&
(typeof ReadableStream !== 'function' ||
!(result instanceof ReadableStream))
) {
const iterableChild = result;
result = {
[ASYNC_ITERATOR]: function () {
const iterator = (iterableChild: any)[ASYNC_ITERATOR]();
if (__DEV__) {
if (iterator === iterableChild) {
const isGeneratorComponent =
Object.prototype.toString.call(Component) ===
'[object AsyncGeneratorFunction]' &&
Object.prototype.toString.call(iterableChild) ===
'[object AsyncGenerator]';
if (!isGeneratorComponent) {
callWithDebugContextInDEV(request, task, () => {
console.error(
'Returning an AsyncIterator from a Server Component is not supported ' +
'since it cannot be looped over more than once. ',
);
});
}
}
}
return iterator;
},
};
if (__DEV__) {
(result: any)._debugInfo = iterableChild._debugInfo;
}
} else if (__DEV__ && (result: any).$$typeof === REACT_ELEMENT_TYPE) {
(result: any)._store.validated = 1;
}
}
const prevKeyPath = task.keyPath;
const prevImplicitSlot = task.implicitSlot;
if (key !== null) {
task.keyPath = prevKeyPath === null ? key : prevKeyPath + ',' + key;
} else if (prevKeyPath === null) {
task.implicitSlot = true;
}
const json = renderModelDestructive(request, task, emptyRoot, '', result);
task.keyPath = prevKeyPath;
task.implicitSlot = prevImplicitSlot;
return json;
}
function warnForMissingKey(
request: Request,
key: null | string,
componentDebugInfo: ReactComponentInfo,
debugTask: null | ConsoleTask,
): void {
if (__DEV__) {
let didWarnForKey = request.didWarnForKey;
if (didWarnForKey == null) {
didWarnForKey = request.didWarnForKey = new WeakSet();
}
const parentOwner = componentDebugInfo.owner;
if (parentOwner != null) {
if (didWarnForKey.has(parentOwner)) {
return;
}
didWarnForKey.add(parentOwner);
}
const logKeyError = () => {
console.error(
'Each child in a list should have a unique "key" prop.' +
'%s%s See https://react.dev/link/warning-keys for more information.',
'',
'',
);
};
if (supportsComponentStorage) {
if (enableOwnerStacks && debugTask) {
debugTask.run(
componentStorage.run.bind(
componentStorage,
componentDebugInfo,
callComponentInDEV,
logKeyError,
null,
componentDebugInfo,
),
);
} else {
componentStorage.run(
componentDebugInfo,
callComponentInDEV,
logKeyError,
null,
componentDebugInfo,
);
}
} else {
if (enableOwnerStacks && debugTask) {
debugTask.run(
callComponentInDEV.bind(null, logKeyError, null, componentDebugInfo),
);
} else {
callComponentInDEV(logKeyError, null, componentDebugInfo);
}
}
}
}
function renderFragment(
request: Request,
task: Task,
children: $ReadOnlyArray<ReactClientValue>,
): ReactJSONValue {
if (__DEV__) {
for (let i = 0; i < children.length; i++) {
const child = children[i];
if (
child !== null &&
typeof child === 'object' &&
child.$$typeof === REACT_ELEMENT_TYPE
) {
const element: ReactElement = (child: any);
if (element.key === null && !element._store.validated) {
element._store.validated = 2;
}
}
}
}
if (task.keyPath !== null) {
const fragment = __DEV__
? enableOwnerStacks
? [
REACT_ELEMENT_TYPE,
REACT_FRAGMENT_TYPE,
task.keyPath,
{children},
null,
null,
0,
]
: [
REACT_ELEMENT_TYPE,
REACT_FRAGMENT_TYPE,
task.keyPath,
{children},
null,
]
: [REACT_ELEMENT_TYPE, REACT_FRAGMENT_TYPE, task.keyPath, {children}];
if (!task.implicitSlot) {
return fragment;
}
return [fragment];
}
if (__DEV__) {
const debugInfo: ?ReactDebugInfo = (children: any)._debugInfo;
if (debugInfo) {
if (debugID === null) {
return outlineTask(request, task);
} else {
forwardDebugInfo(request, debugID, debugInfo);
}
children = Array.from(children);
}
}
return children;
}
function renderAsyncFragment(
request: Request,
task: Task,
children: $AsyncIterable<ReactClientValue, ReactClientValue, void>,
getAsyncIterator: () => $AsyncIterator<any, any, any>,
): ReactJSONValue {
if (task.keyPath !== null) {
const fragment = __DEV__
? enableOwnerStacks
? [
REACT_ELEMENT_TYPE,
REACT_FRAGMENT_TYPE,
task.keyPath,
{children},
null,
null,
0,
]
: [
REACT_ELEMENT_TYPE,
REACT_FRAGMENT_TYPE,
task.keyPath,
{children},
null,
]
: [REACT_ELEMENT_TYPE, REACT_FRAGMENT_TYPE, task.keyPath, {children}];
if (!task.implicitSlot) {
return fragment;
}
return [fragment];
}
const asyncIterator = getAsyncIterator.call(children);
return serializeAsyncIterable(request, task, children, asyncIterator);
}
function renderClientElement(
request: Request,
task: Task,
type: any,
key: null | string,
props: any,
validated: number,
): ReactJSONValue {
const keyPath = task.keyPath;
if (key === null) {
key = keyPath;
} else if (keyPath !== null) {
key = keyPath + ',' + key;
}
if (__DEV__) {
if (task.debugOwner !== null) {
outlineComponentInfo(request, task.debugOwner);
}
}
const element = __DEV__
? enableOwnerStacks
? [
REACT_ELEMENT_TYPE,
type,
key,
props,
task.debugOwner,
task.debugStack === null
? null
: filterStackTrace(request, task.debugStack, 1),
validated,
]
: [REACT_ELEMENT_TYPE, type, key, props, task.debugOwner]
: [REACT_ELEMENT_TYPE, type, key, props];
if (task.implicitSlot && key !== null) {
return [element];
}
return element;
}
let debugID: null | number = null;
function outlineTask(request: Request, task: Task): ReactJSONValue {
const newTask = createTask(
request,
task.model,
task.keyPath,
task.implicitSlot,
request.abortableTasks,
__DEV__ ? task.debugOwner : null,
__DEV__ && enableOwnerStacks ? task.debugStack : null,
__DEV__ && enableOwnerStacks ? task.debugTask : null,
);
retryTask(request, newTask);
if (newTask.status === COMPLETED) {
return serializeByValueID(newTask.id);
}
return serializeLazyID(newTask.id);
}
function outlineHaltedTask(
request: Request,
task: Task,
allowLazy: boolean,
): ReactJSONValue {
const taskId = request.nextChunkId++;
if (allowLazy) {
return serializeLazyID(taskId);
} else {
return serializeByValueID(taskId);
}
}
function renderElement(
request: Request,
task: Task,
type: any,
key: null | string,
ref: mixed,
props: any,
validated: number,
): ReactJSONValue {
if (ref !== null && ref !== undefined) {
throw new Error(
'Refs cannot be used in Server Components, nor passed to Client Components.',
);
}
if (__DEV__) {
jsxPropsParents.set(props, type);
if (typeof props.children === 'object' && props.children !== null) {
jsxChildrenParents.set(props.children, type);
}
}
if (
typeof type === 'function' &&
!isClientReference(type) &&
!isOpaqueTemporaryReference(type)
) {
return renderFunctionComponent(request, task, key, type, props, validated);
} else if (type === REACT_FRAGMENT_TYPE && key === null) {
if (__DEV__ && enableOwnerStacks && validated === 2) {
const componentDebugInfo: ReactComponentInfo = {
name: 'Fragment',
env: (0, request.environmentName)(),
key: key,
owner: task.debugOwner,
stack:
task.debugStack === null
? null
: filterStackTrace(request, task.debugStack, 1),
props: props,
debugStack: task.debugStack,
debugTask: task.debugTask,
};
warnForMissingKey(request, key, componentDebugInfo, task.debugTask);
}
const prevImplicitSlot = task.implicitSlot;
if (task.keyPath === null) {
task.implicitSlot = true;
}
const json = renderModelDestructive(
request,
task,
emptyRoot,
'',
props.children,
);
task.implicitSlot = prevImplicitSlot;
return json;
} else if (
type != null &&
typeof type === 'object' &&
!isClientReference(type)
) {
switch (type.$$typeof) {
case REACT_LAZY_TYPE: {
let wrappedType;
if (__DEV__) {
wrappedType = callLazyInitInDEV(type);
} else {
const payload = type._payload;
const init = type._init;
wrappedType = init(payload);
}
if (request.status === ABORTING) {
throw null;
}
return renderElement(
request,
task,
wrappedType,
key,
ref,
props,
validated,
);
}
case REACT_FORWARD_REF_TYPE: {
return renderFunctionComponent(
request,
task,
key,
type.render,
props,
validated,
);
}
case REACT_MEMO_TYPE: {
return renderElement(
request,
task,
type.type,
key,
ref,
props,
validated,
);
}
case REACT_ELEMENT_TYPE: {
if (__DEV__) {
type._store.validated = 1;
}
}
}
}
return renderClientElement(request, task, type, key, props, validated);
}
function pingTask(request: Request, task: Task): void {
const pingedTasks = request.pingedTasks;
pingedTasks.push(task);
if (pingedTasks.length === 1) {
request.flushScheduled = request.destination !== null;
if (request.type === PRERENDER || request.status === OPENING) {
scheduleMicrotask(() => performWork(request));
} else {
scheduleWork(() => performWork(request));
}
}
}
function createTask(
request: Request,
model: ReactClientValue,
keyPath: null | string,
implicitSlot: boolean,
abortSet: Set<Task>,
debugOwner: null | ReactComponentInfo,
debugStack: null | Error,
debugTask: null | ConsoleTask,
): Task {
request.pendingChunks++;
const id = request.nextChunkId++;
if (typeof model === 'object' && model !== null) {
if (keyPath !== null || implicitSlot) {
} else {
request.writtenObjects.set(model, serializeByValueID(id));
}
}
const task: Task = (({
id,
status: PENDING,
model,
keyPath,
implicitSlot,
ping: () => pingTask(request, task),
toJSON: function (
this:
| {+[key: string | number]: ReactClientValue}
| $ReadOnlyArray<ReactClientValue>,
parentPropertyName: string,
value: ReactClientValue,
): ReactJSONValue {
const parent = this;
if (__DEV__) {
const originalValue = parent[parentPropertyName];
if (
typeof originalValue === 'object' &&
originalValue !== value &&
!(originalValue instanceof Date)
) {
callWithDebugContextInDEV(request, task, () => {
if (objectName(originalValue) !== 'Object') {
const jsxParentType = jsxChildrenParents.get(parent);
if (typeof jsxParentType === 'string') {
console.error(
'%s objects cannot be rendered as text children. Try formatting it using toString().%s',
objectName(originalValue),
describeObjectForErrorMessage(parent, parentPropertyName),
);
} else {
console.error(
'Only plain objects can be passed to Client Components from Server Components. ' +
'%s objects are not supported.%s',
objectName(originalValue),
describeObjectForErrorMessage(parent, parentPropertyName),
);
}
} else {
console.error(
'Only plain objects can be passed to Client Components from Server Components. ' +
'Objects with toJSON methods are not supported. Convert it manually ' +
'to a simple value before passing it to props.%s',
describeObjectForErrorMessage(parent, parentPropertyName),
);
}
});
}
}
return renderModel(request, task, parent, parentPropertyName, value);
},
thenableState: null,
}: Omit<
Task,
'environmentName' | 'debugOwner' | 'debugStack' | 'debugTask',
>): any);
if (__DEV__) {
task.environmentName = request.environmentName();
task.debugOwner = debugOwner;
if (enableOwnerStacks) {
task.debugStack = debugStack;
task.debugTask = debugTask;
}
}
abortSet.add(task);
return task;
}
function serializeByValueID(id: number): string {
return '$' + id.toString(16);
}
function serializeLazyID(id: number): string {
return '$L' + id.toString(16);
}
function serializeInfinitePromise(): string {
return '$@';
}
function serializePromiseID(id: number): string {
return '$@' + id.toString(16);
}
function serializeServerReferenceID(id: number): string {
return '$F' + id.toString(16);
}
function serializeSymbolReference(name: string): string {
return '$S' + name;
}
function serializeLimitedObject(): string {
return '$Y';
}
function serializeNumber(number: number): string | number {
if (Number.isFinite(number)) {
if (number === 0 && 1 / number === -Infinity) {
return '$-0';
} else {
return number;
}
} else {
if (number === Infinity) {
return '$Infinity';
} else if (number === -Infinity) {
return '$-Infinity';
} else {
return '$NaN';
}
}
}
function serializeUndefined(): string {
return '$undefined';
}
function serializeDateFromDateJSON(dateJSON: string): string {
return '$D' + dateJSON;
}
function serializeBigInt(n: bigint): string {
return '$n' + n.toString(10);
}
function serializeRowHeader(tag: string, id: number) {
return id.toString(16) + ':' + tag;
}
function encodeReferenceChunk(
request: Request,
id: number,
reference: string,
): Chunk {
const json = stringify(reference);
const row = id.toString(16) + ':' + json + '\n';
return stringToChunk(row);
}
function serializeClientReference(
request: Request,
parent:
| {+[propertyName: string | number]: ReactClientValue}
| $ReadOnlyArray<ReactClientValue>,
parentPropertyName: string,
clientReference: ClientReference<any>,
): string {
const clientReferenceKey: ClientReferenceKey =
getClientReferenceKey(clientReference);
const writtenClientReferences = request.writtenClientReferences;
const existingId = writtenClientReferences.get(clientReferenceKey);
if (existingId !== undefined) {
if (parent[0] === REACT_ELEMENT_TYPE && parentPropertyName === '1') {
return serializeLazyID(existingId);
}
return serializeByValueID(existingId);
}
try {
const clientReferenceMetadata: ClientReferenceMetadata =
resolveClientReferenceMetadata(request.bundlerConfig, clientReference);
request.pendingChunks++;
const importId = request.nextChunkId++;
emitImportChunk(request, importId, clientReferenceMetadata);
writtenClientReferences.set(clientReferenceKey, importId);
if (parent[0] === REACT_ELEMENT_TYPE && parentPropertyName === '1') {
return serializeLazyID(importId);
}
return serializeByValueID(importId);
} catch (x) {
request.pendingChunks++;
const errorId = request.nextChunkId++;
const digest = logRecoverableError(request, x, null);
emitErrorChunk(request, errorId, digest, x);
return serializeByValueID(errorId);
}
}
function outlineModel(request: Request, value: ReactClientValue): number {
const newTask = createTask(
request,
value,
null,
false,
request.abortableTasks,
null,
null,
null,
);
retryTask(request, newTask);
return newTask.id;
}
function serializeServerReference(
request: Request,
serverReference: ServerReference<any>,
): string {
const writtenServerReferences = request.writtenServerReferences;
const existingId = writtenServerReferences.get(serverReference);
if (existingId !== undefined) {
return serializeServerReferenceID(existingId);
}
const boundArgs: null | Array<any> = getServerReferenceBoundArguments(
request.bundlerConfig,
serverReference,
);
const bound = boundArgs === null ? null : Promise.resolve(boundArgs);
const id = getServerReferenceId(request.bundlerConfig, serverReference);
let location: null | ReactCallSite = null;
if (__DEV__) {
const error = getServerReferenceLocation(
request.bundlerConfig,
serverReference,
);
if (error) {
const frames = parseStackTrace(error, 1);
if (frames.length > 0) {
location = frames[0];
}
}
}
const serverReferenceMetadata: {
id: ServerReferenceId,
bound: null | Promise<Array<any>>,
name?: string,
env?: string,
location?: ReactCallSite,
} =
__DEV__ && location !== null
? {
id,
bound,
name:
typeof serverReference === 'function' ? serverReference.name : '',
env: (0, request.environmentName)(),
location,
}
: {
id,
bound,
};
const metadataId = outlineModel(request, serverReferenceMetadata);
writtenServerReferences.set(serverReference, metadataId);
return serializeServerReferenceID(metadataId);
}
function serializeTemporaryReference(
request: Request,
reference: string,
): string {
return '$T' + reference;
}
function serializeLargeTextString(request: Request, text: string): string {
request.pendingChunks++;
const textId = request.nextChunkId++;
emitTextChunk(request, textId, text);
return serializeByValueID(textId);
}
function serializeMap(
request: Request,
map: Map<ReactClientValue, ReactClientValue>,
): string {
const entries = Array.from(map);
const id = outlineModel(request, entries);
return '$Q' + id.toString(16);
}
function serializeFormData(request: Request, formData: FormData): string {
const entries = Array.from(formData.entries());
const id = outlineModel(request, (entries: any));
return '$K' + id.toString(16);
}
function serializeSet(request: Request, set: Set<ReactClientValue>): string {
const entries = Array.from(set);
const id = outlineModel(request, entries);
return '$W' + id.toString(16);
}
function serializeConsoleMap(
request: Request,
counter: {objectLimit: number},
map: Map<ReactClientValue, ReactClientValue>,
): string {
const entries = Array.from(map);
const id = outlineConsoleValue(request, counter, entries);
return '$Q' + id.toString(16);
}
function serializeConsoleSet(
request: Request,
counter: {objectLimit: number},
set: Set<ReactClientValue>,
): string {
const entries = Array.from(set);
const id = outlineConsoleValue(request, counter, entries);
return '$W' + id.toString(16);
}
function serializeIterator(
request: Request,
iterator: Iterator<ReactClientValue>,
): string {
const id = outlineModel(request, Array.from(iterator));
return '$i' + id.toString(16);
}
function serializeTypedArray(
request: Request,
tag: string,
typedArray: $ArrayBufferView,
): string {
request.pendingChunks++;
const bufferId = request.nextChunkId++;
emitTypedArrayChunk(request, bufferId, tag, typedArray);
return serializeByValueID(bufferId);
}
function serializeBlob(request: Request, blob: Blob): string {
const model: Array<string | Uint8Array> = [blob.type];
const newTask = createTask(
request,
model,
null,
false,
request.abortableTasks,
null,
null,
null,
);
const reader = blob.stream().getReader();
let aborted = false;
function progress(
entry: {done: false, value: Uint8Array} | {done: true, value: void},
): Promise<void> | void {
if (aborted) {
return;
}
if (entry.done) {
request.abortListeners.delete(abortBlob);
aborted = true;
pingTask(request, newTask);
return;
}
model.push(entry.value);
return reader.read().then(progress).catch(error);
}
function error(reason: mixed) {
if (aborted) {
return;
}
aborted = true;
request.abortListeners.delete(abortBlob);
const digest = logRecoverableError(request, reason, newTask);
emitErrorChunk(request, newTask.id, digest, reason);
enqueueFlush(request);
reader.cancel(reason).then(error, error);
}
function abortBlob(reason: mixed) {
if (aborted) {
return;
}
aborted = true;
request.abortListeners.delete(abortBlob);
if (
enablePostpone &&
typeof reason === 'object' &&
reason !== null &&
(reason: any).$$typeof === REACT_POSTPONE_TYPE
) {
const postponeInstance: Postpone = (reason: any);
logPostpone(request, postponeInstance.message, newTask);
if (enableHalt && request.type === PRERENDER) {
request.pendingChunks--;
} else {
emitPostponeChunk(request, newTask.id, postponeInstance);
enqueueFlush(request);
}
} else {
const digest = logRecoverableError(request, reason, newTask);
if (enableHalt && request.type === PRERENDER) {
request.pendingChunks--;
} else {
emitErrorChunk(request, newTask.id, digest, reason);
enqueueFlush(request);
}
}
reader.cancel(reason).then(error, error);
}
request.abortListeners.add(abortBlob);
reader.read().then(progress).catch(error);
return '$B' + newTask.id.toString(16);
}
function escapeStringValue(value: string): string {
if (value[0] === '$') {
return '$' + value;
} else {
return value;
}
}
let modelRoot: null | ReactClientValue = false;
function renderModel(
request: Request,
task: Task,
parent:
| {+[key: string | number]: ReactClientValue}
| $ReadOnlyArray<ReactClientValue>,
key: string,
value: ReactClientValue,
): ReactJSONValue {
const prevKeyPath = task.keyPath;
const prevImplicitSlot = task.implicitSlot;
try {
return renderModelDestructive(request, task, parent, key, value);
} catch (thrownValue) {
const model = task.model;
const wasReactNode =
typeof model === 'object' &&
model !== null &&
((model: any).$$typeof === REACT_ELEMENT_TYPE ||
(model: any).$$typeof === REACT_LAZY_TYPE);
if (request.status === ABORTING) {
task.status = ABORTED;
if (enableHalt && request.type === PRERENDER) {
return outlineHaltedTask(request, task, wasReactNode);
}
const errorId = (request.fatalError: any);
if (wasReactNode) {
return serializeLazyID(errorId);
}
return serializeByValueID(errorId);
}
const x =
thrownValue === SuspenseException
?
getSuspendedThenable()
: thrownValue;
if (typeof x === 'object' && x !== null) {
if (typeof x.then === 'function') {
const newTask = createTask(
request,
task.model,
task.keyPath,
task.implicitSlot,
request.abortableTasks,
__DEV__ ? task.debugOwner : null,
__DEV__ && enableOwnerStacks ? task.debugStack : null,
__DEV__ && enableOwnerStacks ? task.debugTask : null,
);
const ping = newTask.ping;
(x: any).then(ping, ping);
newTask.thenableState = getThenableStateAfterSuspending();
task.keyPath = prevKeyPath;
task.implicitSlot = prevImplicitSlot;
if (wasReactNode) {
return serializeLazyID(newTask.id);
}
return serializeByValueID(newTask.id);
} else if (enablePostpone && x.$$typeof === REACT_POSTPONE_TYPE) {
const postponeInstance: Postpone = (x: any);
request.pendingChunks++;
const postponeId = request.nextChunkId++;
logPostpone(request, postponeInstance.message, task);
emitPostponeChunk(request, postponeId, postponeInstance);
task.keyPath = prevKeyPath;
task.implicitSlot = prevImplicitSlot;
if (wasReactNode) {
return serializeLazyID(postponeId);
}
return serializeByValueID(postponeId);
}
}
task.keyPath = prevKeyPath;
task.implicitSlot = prevImplicitSlot;
request.pendingChunks++;
const errorId = request.nextChunkId++;
const digest = logRecoverableError(request, x, task);
emitErrorChunk(request, errorId, digest, x);
if (wasReactNode) {
return serializeLazyID(errorId);
}
return serializeByValueID(errorId);
}
}
function renderModelDestructive(
request: Request,
task: Task,
parent:
| {+[propertyName: string | number]: ReactClientValue}
| $ReadOnlyArray<ReactClientValue>,
parentPropertyName: string,
value: ReactClientValue,
): ReactJSONValue {
task.model = value;
if (value === REACT_ELEMENT_TYPE) {
return '$';
}
if (value === null) {
return null;
}
if (typeof value === 'object') {
switch ((value: any).$$typeof) {
case REACT_ELEMENT_TYPE: {
let elementReference = null;
const writtenObjects = request.writtenObjects;
if (task.keyPath !== null || task.implicitSlot) {
} else {
const existingReference = writtenObjects.get(value);
if (existingReference !== undefined) {
if (modelRoot === value) {
modelRoot = null;
} else {
return existingReference;
}
} else if (parentPropertyName.indexOf(':') === -1) {
const parentReference = writtenObjects.get(parent);
if (parentReference !== undefined) {
elementReference = parentReference + ':' + parentPropertyName;
writtenObjects.set(value, elementReference);
}
}
}
const element: ReactElement = (value: any);
if (__DEV__) {
const debugInfo: ?ReactDebugInfo = (value: any)._debugInfo;
if (debugInfo) {
if (debugID === null) {
return outlineTask(request, task);
} else {
forwardDebugInfo(request, debugID, debugInfo);
}
}
}
const props = element.props;
let ref;
if (enableRefAsProp) {
const refProp = props.ref;
ref = refProp !== undefined ? refProp : null;
} else {
ref = element.ref;
}
if (__DEV__) {
task.debugOwner = element._owner;
if (enableOwnerStacks) {
task.debugStack = element._debugStack;
task.debugTask = element._debugTask;
}
}
const newChild = renderElement(
request,
task,
element.type,
element.key,
ref,
props,
__DEV__ && enableOwnerStacks ? element._store.validated : 0,
);
if (
typeof newChild === 'object' &&
newChild !== null &&
elementReference !== null
) {
if (!writtenObjects.has(newChild)) {
writtenObjects.set(newChild, elementReference);
}
}
return newChild;
}
case REACT_LAZY_TYPE: {
task.thenableState = null;
const lazy: LazyComponent<any, any> = (value: any);
let resolvedModel;
if (__DEV__) {
resolvedModel = callLazyInitInDEV(lazy);
} else {
const payload = lazy._payload;
const init = lazy._init;
resolvedModel = init(payload);
}
if (request.status === ABORTING) {
throw null;
}
if (__DEV__) {
const debugInfo: ?ReactDebugInfo = lazy._debugInfo;
if (debugInfo) {
if (debugID === null) {
return outlineTask(request, task);
} else {
forwardDebugInfo(request, debugID, debugInfo);
}
}
}
return renderModelDestructive(
request,
task,
emptyRoot,
'',
resolvedModel,
);
}
case REACT_LEGACY_ELEMENT_TYPE: {
throw new Error(
'A React Element from an older version of React was rendered. ' +
'This is not supported. It can happen if:\n' +
'- Multiple copies of the "react" package is used.\n' +
'- A library pre-bundled an old copy of "react" or "react/jsx-runtime".\n' +
'- A compiler tries to "inline" JSX instead of using the runtime.',
);
}
}
if (isClientReference(value)) {
return serializeClientReference(
request,
parent,
parentPropertyName,
(value: any),
);
}
if (request.temporaryReferences !== undefined) {
const tempRef = resolveTemporaryReference(
request.temporaryReferences,
value,
);
if (tempRef !== undefined) {
return serializeTemporaryReference(request, tempRef);
}
}
if (enableTaint) {
const tainted = TaintRegistryObjects.get(value);
if (tainted !== undefined) {
throwTaintViolation(tainted);
}
}
const writtenObjects = request.writtenObjects;
const existingReference = writtenObjects.get(value);
if (typeof value.then === 'function') {
if (existingReference !== undefined) {
if (task.keyPath !== null || task.implicitSlot) {
const promiseId = serializeThenable(request, task, (value: any));
return serializePromiseID(promiseId);
} else if (modelRoot === value) {
modelRoot = null;
} else {
return existingReference;
}
}
const promiseId = serializeThenable(request, task, (value: any));
const promiseReference = serializePromiseID(promiseId);
writtenObjects.set(value, promiseReference);
return promiseReference;
}
if (existingReference !== undefined) {
if (modelRoot === value) {
modelRoot = null;
} else {
return existingReference;
}
} else if (parentPropertyName.indexOf(':') === -1) {
const parentReference = writtenObjects.get(parent);
if (parentReference !== undefined) {
let propertyName = parentPropertyName;
if (isArray(parent) && parent[0] === REACT_ELEMENT_TYPE) {
switch (parentPropertyName) {
case '1':
propertyName = 'type';
break;
case '2':
propertyName = 'key';
break;
case '3':
propertyName = 'props';
break;
case '4':
propertyName = '_owner';
break;
}
}
writtenObjects.set(value, parentReference + ':' + propertyName);
}
}
if (isArray(value)) {
return renderFragment(request, task, value);
}
if (value instanceof Map) {
return serializeMap(request, value);
}
if (value instanceof Set) {
return serializeSet(request, value);
}
if (typeof FormData === 'function' && value instanceof FormData) {
return serializeFormData(request, value);
}
if (value instanceof Error) {
return serializeErrorValue(request, value);
}
if (enableBinaryFlight) {
if (value instanceof ArrayBuffer) {
return serializeTypedArray(request, 'A', new Uint8Array(value));
}
if (value instanceof Int8Array) {
return serializeTypedArray(request, 'O', value);
}
if (value instanceof Uint8Array) {
return serializeTypedArray(request, 'o', value);
}
if (value instanceof Uint8ClampedArray) {
return serializeTypedArray(request, 'U', value);
}
if (value instanceof Int16Array) {
return serializeTypedArray(request, 'S', value);
}
if (value instanceof Uint16Array) {
return serializeTypedArray(request, 's', value);
}
if (value instanceof Int32Array) {
return serializeTypedArray(request, 'L', value);
}
if (value instanceof Uint32Array) {
return serializeTypedArray(request, 'l', value);
}
if (value instanceof Float32Array) {
return serializeTypedArray(request, 'G', value);
}
if (value instanceof Float64Array) {
return serializeTypedArray(request, 'g', value);
}
if (value instanceof BigInt64Array) {
return serializeTypedArray(request, 'M', value);
}
if (value instanceof BigUint64Array) {
return serializeTypedArray(request, 'm', value);
}
if (value instanceof DataView) {
return serializeTypedArray(request, 'V', value);
}
if (typeof Blob === 'function' && value instanceof Blob) {
return serializeBlob(request, value);
}
}
const iteratorFn = getIteratorFn(value);
if (iteratorFn) {
const iterator = iteratorFn.call(value);
if (iterator === value) {
return serializeIterator(request, (iterator: any));
}
return renderFragment(request, task, Array.from((iterator: any)));
}
if (enableFlightReadableStream) {
if (
typeof ReadableStream === 'function' &&
value instanceof ReadableStream
) {
return serializeReadableStream(request, task, value);
}
const getAsyncIterator: void | (() => $AsyncIterator<any, any, any>) =
(value: any)[ASYNC_ITERATOR];
if (typeof getAsyncIterator === 'function') {
return renderAsyncFragment(
request,
task,
(value: any),
getAsyncIterator,
);
}
}
const proto = getPrototypeOf(value);
if (
proto !== ObjectPrototype &&
(proto === null || getPrototypeOf(proto) !== null)
) {
throw new Error(
'Only plain objects, and a few built-ins, can be passed to Client Components ' +
'from Server Components. Classes or null prototypes are not supported.' +
describeObjectForErrorMessage(parent, parentPropertyName),
);
}
if (__DEV__) {
if (objectName(value) !== 'Object') {
callWithDebugContextInDEV(request, task, () => {
console.error(
'Only plain objects can be passed to Client Components from Server Components. ' +
'%s objects are not supported.%s',
objectName(value),
describeObjectForErrorMessage(parent, parentPropertyName),
);
});
} else if (!isSimpleObject(value)) {
callWithDebugContextInDEV(request, task, () => {
console.error(
'Only plain objects can be passed to Client Components from Server Components. ' +
'Classes or other objects with methods are not supported.%s',
describeObjectForErrorMessage(parent, parentPropertyName),
);
});
} else if (Object.getOwnPropertySymbols) {
const symbols = Object.getOwnPropertySymbols(value);
if (symbols.length > 0) {
callWithDebugContextInDEV(request, task, () => {
console.error(
'Only plain objects can be passed to Client Components from Server Components. ' +
'Objects with symbol properties like %s are not supported.%s',
symbols[0].description,
describeObjectForErrorMessage(parent, parentPropertyName),
);
});
}
}
}
return value;
}
if (typeof value === 'string') {
if (enableTaint) {
const tainted = TaintRegistryValues.get(value);
if (tainted !== undefined) {
throwTaintViolation(tainted.message);
}
}
if (value[value.length - 1] === 'Z') {
const originalValue = parent[parentPropertyName];
if (originalValue instanceof Date) {
return serializeDateFromDateJSON(value);
}
}
if (value.length >= 1024 && byteLengthOfChunk !== null) {
return serializeLargeTextString(request, value);
}
return escapeStringValue(value);
}
if (typeof value === 'boolean') {
return value;
}
if (typeof value === 'number') {
return serializeNumber(value);
}
if (typeof value === 'undefined') {
return serializeUndefined();
}
if (typeof value === 'function') {
if (isClientReference(value)) {
return serializeClientReference(
request,
parent,
parentPropertyName,
(value: any),
);
}
if (isServerReference(value)) {
return serializeServerReference(request, (value: any));
}
if (request.temporaryReferences !== undefined) {
const tempRef = resolveTemporaryReference(
request.temporaryReferences,
value,
);
if (tempRef !== undefined) {
return serializeTemporaryReference(request, tempRef);
}
}
if (enableTaint) {
const tainted = TaintRegistryObjects.get(value);
if (tainted !== undefined) {
throwTaintViolation(tainted);
}
}
if (isOpaqueTemporaryReference(value)) {
throw new Error(
'Could not reference an opaque temporary reference. ' +
'This is likely due to misconfiguring the temporaryReferences options ' +
'on the server.',
);
} else if (/^on[A-Z]/.test(parentPropertyName)) {
throw new Error(
'Event handlers cannot be passed to Client Component props.' +
describeObjectForErrorMessage(parent, parentPropertyName) +
'\nIf you need interactivity, consider converting part of this to a Client Component.',
);
} else if (
__DEV__ &&
(jsxChildrenParents.has(parent) ||
(jsxPropsParents.has(parent) && parentPropertyName === 'children'))
) {
const componentName = value.displayName || value.name || 'Component';
throw new Error(
'Functions are not valid as a child of Client Components. This may happen if ' +
'you return ' +
componentName +
' instead of <' +
componentName +
' /> from render. ' +
'Or maybe you meant to call this function rather than return it.' +
describeObjectForErrorMessage(parent, parentPropertyName),
);
} else {
throw new Error(
'Functions cannot be passed directly to Client Components ' +
'unless you explicitly expose it by marking it with "use server". ' +
'Or maybe you meant to call this function rather than return it.' +
describeObjectForErrorMessage(parent, parentPropertyName),
);
}
}
if (typeof value === 'symbol') {
const writtenSymbols = request.writtenSymbols;
const existingId = writtenSymbols.get(value);
if (existingId !== undefined) {
return serializeByValueID(existingId);
}
const name: string = value.description;
if (Symbol.for(name) !== value) {
throw new Error(
'Only global symbols received from Symbol.for(...) can be passed to Client Components. ' +
`The symbol Symbol.for(${
// $FlowFixMe[incompatible-type] `description` might be undefined
value.description
}) cannot be found among global symbols.` +
describeObjectForErrorMessage(parent, parentPropertyName),
);
}
request.pendingChunks++;
const symbolId = request.nextChunkId++;
emitSymbolChunk(request, symbolId, name);
writtenSymbols.set(value, symbolId);
return serializeByValueID(symbolId);
}
if (typeof value === 'bigint') {
if (enableTaint) {
const tainted = TaintRegistryValues.get(value);
if (tainted !== undefined) {
throwTaintViolation(tainted.message);
}
}
return serializeBigInt(value);
}
throw new Error(
`Type ${typeof value} is not supported in Client Component props.` +
describeObjectForErrorMessage(parent, parentPropertyName),
);
}
function logPostpone(
request: Request,
reason: string,
task: Task | null,
): void {
const prevRequest = currentRequest;
currentRequest = null;
try {
const onPostpone = request.onPostpone;
if (__DEV__ && task !== null) {
if (supportsRequestStorage) {
requestStorage.run(
undefined,
callWithDebugContextInDEV,
request,
task,
onPostpone,
reason,
);
} else {
callWithDebugContextInDEV(request, task, onPostpone, reason);
}
} else if (supportsRequestStorage) {
requestStorage.run(undefined, onPostpone, reason);
} else {
onPostpone(reason);
}
} finally {
currentRequest = prevRequest;
}
}
function logRecoverableError(
request: Request,
error: mixed,
task: Task | null,
): string {
const prevRequest = currentRequest;
currentRequest = null;
let errorDigest;
try {
const onError = request.onError;
if (__DEV__ && task !== null) {
if (supportsRequestStorage) {
errorDigest = requestStorage.run(
undefined,
callWithDebugContextInDEV,
request,
task,
onError,
error,
);
} else {
errorDigest = callWithDebugContextInDEV(request, task, onError, error);
}
} else if (supportsRequestStorage) {
errorDigest = requestStorage.run(undefined, onError, error);
} else {
errorDigest = onError(error);
}
} finally {
currentRequest = prevRequest;
}
if (errorDigest != null && typeof errorDigest !== 'string') {
throw new Error(
`onError returned something with a type other than "string". onError should return a string and may return null or undefined but must not return anything else. It received something of type "${typeof errorDigest}" instead`,
);
}
return errorDigest || '';
}
function fatalError(request: Request, error: mixed): void {
const onFatalError = request.onFatalError;
onFatalError(error);
if (enableTaint) {
cleanupTaintQueue(request);
}
if (request.destination !== null) {
request.status = CLOSED;
closeWithError(request.destination, error);
} else {
request.status = CLOSING;
request.fatalError = error;
}
}
function emitPostponeChunk(
request: Request,
id: number,
postponeInstance: Postpone,
): void {
let row;
if (__DEV__) {
let reason = '';
let stack: ReactStackTrace;
const env = request.environmentName();
try {
reason = String(postponeInstance.message);
stack = filterStackTrace(request, postponeInstance, 0);
} catch (x) {
stack = [];
}
row = serializeRowHeader('P', id) + stringify({reason, stack, env}) + '\n';
} else {
row = serializeRowHeader('P', id) + '\n';
}
const processedChunk = stringToChunk(row);
request.completedErrorChunks.push(processedChunk);
}
function serializeErrorValue(request: Request, error: Error): string {
if (__DEV__) {
let message;
let stack: ReactStackTrace;
let env = (0, request.environmentName)();
try {
message = String(error.message);
stack = filterStackTrace(request, error, 0);
const errorEnv = (error: any).environmentName;
if (typeof errorEnv === 'string') {
env = errorEnv;
}
} catch (x) {
message = 'An error occurred but serializing the error message failed.';
stack = [];
}
const errorInfo = {message, stack, env};
const id = outlineModel(request, errorInfo);
return '$Z' + id.toString(16);
} else {
return '$Z';
}
}
function emitErrorChunk(
request: Request,
id: number,
digest: string,
error: mixed,
): void {
let errorInfo: any;
if (__DEV__) {
let message;
let stack: ReactStackTrace;
let env = (0, request.environmentName)();
try {
if (error instanceof Error) {
message = String(error.message);
stack = filterStackTrace(request, error, 0);
const errorEnv = (error: any).environmentName;
if (typeof errorEnv === 'string') {
env = errorEnv;
}
} else if (typeof error === 'object' && error !== null) {
message = describeObjectForErrorMessage(error);
stack = [];
} else {
message = String(error);
stack = [];
}
} catch (x) {
message = 'An error occurred but serializing the error message failed.';
stack = [];
}
errorInfo = {digest, message, stack, env};
} else {
errorInfo = {digest};
}
const row = serializeRowHeader('E', id) + stringify(errorInfo) + '\n';
const processedChunk = stringToChunk(row);
request.completedErrorChunks.push(processedChunk);
}
function emitImportChunk(
request: Request,
id: number,
clientReferenceMetadata: ClientReferenceMetadata,
): void {
const json: string = stringify(clientReferenceMetadata);
const row = serializeRowHeader('I', id) + json + '\n';
const processedChunk = stringToChunk(row);
request.completedImportChunks.push(processedChunk);
}
function emitHintChunk<Code: HintCode>(
request: Request,
code: Code,
model: HintModel<Code>,
): void {
const json: string = stringify(model);
const id = request.nextChunkId++;
const row = serializeRowHeader('H' + code, id) + json + '\n';
const processedChunk = stringToChunk(row);
request.completedHintChunks.push(processedChunk);
}
function emitSymbolChunk(request: Request, id: number, name: string): void {
const symbolReference = serializeSymbolReference(name);
const processedChunk = encodeReferenceChunk(request, id, symbolReference);
request.completedImportChunks.push(processedChunk);
}
function emitModelChunk(request: Request, id: number, json: string): void {
const row = id.toString(16) + ':' + json + '\n';
const processedChunk = stringToChunk(row);
request.completedRegularChunks.push(processedChunk);
}
function emitDebugChunk(
request: Request,
id: number,
debugInfo: ReactComponentInfo | ReactAsyncInfo,
): void {
if (!__DEV__) {
throw new Error(
'emitDebugChunk should never be called in production mode. This is a bug in React.',
);
}
const counter = {objectLimit: 500};
function replacer(
this:
| {+[key: string | number]: ReactClientValue}
| $ReadOnlyArray<ReactClientValue>,
parentPropertyName: string,
value: ReactClientValue,
): ReactJSONValue {
return renderConsoleValue(
request,
counter,
this,
parentPropertyName,
value,
);
}
const json: string = stringify(debugInfo, replacer);
const row = serializeRowHeader('D', id) + json + '\n';
const processedChunk = stringToChunk(row);
request.completedRegularChunks.push(processedChunk);
}
function outlineComponentInfo(
request: Request,
componentInfo: ReactComponentInfo,
): void {
if (!__DEV__) {
throw new Error(
'outlineComponentInfo should never be called in production mode. This is a bug in React.',
);
}
if (request.writtenObjects.has(componentInfo)) {
return;
}
if (componentInfo.owner != null) {
outlineComponentInfo(request, componentInfo.owner);
}
let objectLimit = 10;
if (componentInfo.stack != null) {
objectLimit += componentInfo.stack.length;
}
const counter = {objectLimit};
const componentDebugInfo: Omit<
ReactComponentInfo,
'debugTask' | 'debugStack',
> = {
name: componentInfo.name,
env: componentInfo.env,
key: componentInfo.key,
owner: componentInfo.owner,
};
if (enableOwnerStacks) {
componentDebugInfo.stack = componentInfo.stack;
}
componentDebugInfo.props = componentInfo.props;
const id = outlineConsoleValue(request, counter, componentDebugInfo);
request.writtenObjects.set(componentInfo, serializeByValueID(id));
}
function emitTypedArrayChunk(
request: Request,
id: number,
tag: string,
typedArray: $ArrayBufferView,
): void {
if (enableTaint) {
if (TaintRegistryByteLengths.has(typedArray.byteLength)) {
const tainted = TaintRegistryValues.get(
binaryToComparableString(typedArray),
);
if (tainted !== undefined) {
throwTaintViolation(tainted.message);
}
}
}
request.pendingChunks++;
const binaryChunk = typedArrayToBinaryChunk(typedArray);
const binaryLength = byteLengthOfBinaryChunk(binaryChunk);
const row = id.toString(16) + ':' + tag + binaryLength.toString(16) + ',';
const headerChunk = stringToChunk(row);
request.completedRegularChunks.push(headerChunk, binaryChunk);
}
function emitTextChunk(request: Request, id: number, text: string): void {
if (byteLengthOfChunk === null) {
throw new Error(
'Existence of byteLengthOfChunk should have already been checked. This is a bug in React.',
);
}
request.pendingChunks++;
const textChunk = stringToChunk(text);
const binaryLength = byteLengthOfChunk(textChunk);
const row = id.toString(16) + ':T' + binaryLength.toString(16) + ',';
const headerChunk = stringToChunk(row);
request.completedRegularChunks.push(headerChunk, textChunk);
}
function serializeEval(source: string): string {
if (!__DEV__) {
throw new Error(
'serializeEval should never be called in production mode. This is a bug in React.',
);
}
return '$E' + source;
}
function renderConsoleValue(
request: Request,
counter: {objectLimit: number},
parent:
| {+[propertyName: string | number]: ReactClientValue}
| $ReadOnlyArray<ReactClientValue>,
parentPropertyName: string,
value: ReactClientValue,
): ReactJSONValue {
const originalValue = parent[parentPropertyName];
if (
typeof originalValue === 'object' &&
originalValue !== value &&
!(originalValue instanceof Date)
) {
}
if (value === null) {
return null;
}
if (typeof value === 'object') {
if (isClientReference(value)) {
return serializeClientReference(
request,
parent,
parentPropertyName,
(value: any),
);
}
if (request.temporaryReferences !== undefined) {
const tempRef = resolveTemporaryReference(
request.temporaryReferences,
value,
);
if (tempRef !== undefined) {
return serializeTemporaryReference(request, tempRef);
}
}
const writtenObjects = request.writtenObjects;
const existingReference = writtenObjects.get(value);
if (existingReference !== undefined) {
return existingReference;
}
if (counter.objectLimit <= 0) {
return serializeLimitedObject();
}
counter.objectLimit--;
switch ((value: any).$$typeof) {
case REACT_ELEMENT_TYPE: {
const element: ReactElement = (value: any);
if (element._owner != null) {
outlineComponentInfo(request, element._owner);
}
if (enableOwnerStacks) {
let debugStack: null | ReactStackTrace = null;
if (element._debugStack != null) {
debugStack = filterStackTrace(request, element._debugStack, 1);
const stackId = outlineConsoleValue(
request,
{objectLimit: debugStack.length + 2},
debugStack,
);
request.writtenObjects.set(debugStack, serializeByValueID(stackId));
}
return [
REACT_ELEMENT_TYPE,
element.type,
element.key,
element.props,
element._owner,
debugStack,
element._store.validated,
];
}
return [
REACT_ELEMENT_TYPE,
element.type,
element.key,
element.props,
element._owner,
];
}
}
if (typeof value.then === 'function') {
const thenable: Thenable<any> = (value: any);
switch (thenable.status) {
case 'fulfilled': {
return serializePromiseID(
outlineConsoleValue(request, counter, thenable.value),
);
}
case 'rejected': {
const x = thenable.reason;
request.pendingChunks++;
const errorId = request.nextChunkId++;
if (
enablePostpone &&
typeof x === 'object' &&
x !== null &&
(x: any).$$typeof === REACT_POSTPONE_TYPE
) {
const postponeInstance: Postpone = (x: any);
emitPostponeChunk(request, errorId, postponeInstance);
} else {
const digest = '';
emitErrorChunk(request, errorId, digest, x);
}
return serializePromiseID(errorId);
}
}
return serializeInfinitePromise();
}
if (isArray(value)) {
return value;
}
if (value instanceof Map) {
return serializeConsoleMap(request, counter, value);
}
if (value instanceof Set) {
return serializeConsoleSet(request, counter, value);
}
if (typeof FormData === 'function' && value instanceof FormData) {
return serializeFormData(request, value);
}
if (value instanceof Error) {
return serializeErrorValue(request, value);
}
if (enableBinaryFlight) {
if (value instanceof ArrayBuffer) {
return serializeTypedArray(request, 'A', new Uint8Array(value));
}
if (value instanceof Int8Array) {
return serializeTypedArray(request, 'O', value);
}
if (value instanceof Uint8Array) {
return serializeTypedArray(request, 'o', value);
}
if (value instanceof Uint8ClampedArray) {
return serializeTypedArray(request, 'U', value);
}
if (value instanceof Int16Array) {
return serializeTypedArray(request, 'S', value);
}
if (value instanceof Uint16Array) {
return serializeTypedArray(request, 's', value);
}
if (value instanceof Int32Array) {
return serializeTypedArray(request, 'L', value);
}
if (value instanceof Uint32Array) {
return serializeTypedArray(request, 'l', value);
}
if (value instanceof Float32Array) {
return serializeTypedArray(request, 'G', value);
}
if (value instanceof Float64Array) {
return serializeTypedArray(request, 'g', value);
}
if (value instanceof BigInt64Array) {
return serializeTypedArray(request, 'M', value);
}
if (value instanceof BigUint64Array) {
return serializeTypedArray(request, 'm', value);
}
if (value instanceof DataView) {
return serializeTypedArray(request, 'V', value);
}
if (typeof Blob === 'function' && value instanceof Blob) {
return serializeBlob(request, value);
}
}
const iteratorFn = getIteratorFn(value);
if (iteratorFn) {
return Array.from((value: any));
}
return value;
}
if (typeof value === 'string') {
if (value[value.length - 1] === 'Z') {
if (originalValue instanceof Date) {
return serializeDateFromDateJSON(value);
}
}
if (value.length >= 1024) {
return serializeLargeTextString(request, value);
}
return escapeStringValue(value);
}
if (typeof value === 'boolean') {
return value;
}
if (typeof value === 'number') {
return serializeNumber(value);
}
if (typeof value === 'undefined') {
return serializeUndefined();
}
if (typeof value === 'function') {
if (isClientReference(value)) {
return serializeClientReference(
request,
parent,
parentPropertyName,
(value: any),
);
}
if (request.temporaryReferences !== undefined) {
const tempRef = resolveTemporaryReference(
request.temporaryReferences,
value,
);
if (tempRef !== undefined) {
return serializeTemporaryReference(request, tempRef);
}
}
return serializeEval('(' + Function.prototype.toString.call(value) + ')');
}
if (typeof value === 'symbol') {
const writtenSymbols = request.writtenSymbols;
const existingId = writtenSymbols.get(value);
if (existingId !== undefined) {
return serializeByValueID(existingId);
}
const name: string = value.description;
request.pendingChunks++;
const symbolId = request.nextChunkId++;
emitSymbolChunk(request, symbolId, name);
return serializeByValueID(symbolId);
}
if (typeof value === 'bigint') {
return serializeBigInt(value);
}
return 'unknown type ' + typeof value;
}
function outlineConsoleValue(
request: Request,
counter: {objectLimit: number},
model: ReactClientValue,
): number {
if (!__DEV__) {
throw new Error(
'outlineConsoleValue should never be called in production mode. This is a bug in React.',
);
}
function replacer(
this:
| {+[key: string | number]: ReactClientValue}
| $ReadOnlyArray<ReactClientValue>,
parentPropertyName: string,
value: ReactClientValue,
): ReactJSONValue {
try {
return renderConsoleValue(
request,
counter,
this,
parentPropertyName,
value,
);
} catch (x) {
return (
'Unknown Value: React could not send it from the server.\n' + x.message
);
}
}
const json: string = stringify(model, replacer);
request.pendingChunks++;
const id = request.nextChunkId++;
const row = id.toString(16) + ':' + json + '\n';
const processedChunk = stringToChunk(row);
request.completedRegularChunks.push(processedChunk);
return id;
}
function emitConsoleChunk(
request: Request,
id: number,
methodName: string,
owner: null | ReactComponentInfo,
stackTrace: ReactStackTrace,
args: Array<any>,
): void {
if (!__DEV__) {
throw new Error(
'emitConsoleChunk should never be called in production mode. This is a bug in React.',
);
}
const counter = {objectLimit: 500};
function replacer(
this:
| {+[key: string | number]: ReactClientValue}
| $ReadOnlyArray<ReactClientValue>,
parentPropertyName: string,
value: ReactClientValue,
): ReactJSONValue {
try {
return renderConsoleValue(
request,
counter,
this,
parentPropertyName,
value,
);
} catch (x) {
return (
'Unknown Value: React could not send it from the server.\n' + x.message
);
}
}
if (owner != null) {
outlineComponentInfo(request, owner);
}
const env = (0, request.environmentName)();
const payload = [methodName, stackTrace, owner, env];
payload.push.apply(payload, args);
const json: string = stringify(payload, replacer);
const row = serializeRowHeader('W', id) + json + '\n';
const processedChunk = stringToChunk(row);
request.completedRegularChunks.push(processedChunk);
}
function forwardDebugInfo(
request: Request,
id: number,
debugInfo: ReactDebugInfo,
) {
for (let i = 0; i < debugInfo.length; i++) {
request.pendingChunks++;
if (typeof debugInfo[i].name === 'string') {
outlineComponentInfo(request, (debugInfo[i]: any));
}
emitDebugChunk(request, id, debugInfo[i]);
}
}
function emitChunk(
request: Request,
task: Task,
value: ReactClientValue,
): void {
const id = task.id;
if (typeof value === 'string' && byteLengthOfChunk !== null) {
if (enableTaint) {
const tainted = TaintRegistryValues.get(value);
if (tainted !== undefined) {
throwTaintViolation(tainted.message);
}
}
emitTextChunk(request, id, value);
return;
}
if (enableBinaryFlight) {
if (value instanceof ArrayBuffer) {
emitTypedArrayChunk(request, id, 'A', new Uint8Array(value));
return;
}
if (value instanceof Int8Array) {
emitTypedArrayChunk(request, id, 'O', value);
return;
}
if (value instanceof Uint8Array) {
emitTypedArrayChunk(request, id, 'o', value);
return;
}
if (value instanceof Uint8ClampedArray) {
emitTypedArrayChunk(request, id, 'U', value);
return;
}
if (value instanceof Int16Array) {
emitTypedArrayChunk(request, id, 'S', value);
return;
}
if (value instanceof Uint16Array) {
emitTypedArrayChunk(request, id, 's', value);
return;
}
if (value instanceof Int32Array) {
emitTypedArrayChunk(request, id, 'L', value);
return;
}
if (value instanceof Uint32Array) {
emitTypedArrayChunk(request, id, 'l', value);
return;
}
if (value instanceof Float32Array) {
emitTypedArrayChunk(request, id, 'G', value);
return;
}
if (value instanceof Float64Array) {
emitTypedArrayChunk(request, id, 'g', value);
return;
}
if (value instanceof BigInt64Array) {
emitTypedArrayChunk(request, id, 'M', value);
return;
}
if (value instanceof BigUint64Array) {
emitTypedArrayChunk(request, id, 'm', value);
return;
}
if (value instanceof DataView) {
emitTypedArrayChunk(request, id, 'V', value);
return;
}
}
const json: string = stringify(value, task.toJSON);
emitModelChunk(request, task.id, json);
}
const emptyRoot = {};
function retryTask(request: Request, task: Task): void {
if (task.status !== PENDING) {
return;
}
const prevDebugID = debugID;
task.status = RENDERING;
try {
modelRoot = task.model;
if (__DEV__) {
debugID = task.id;
}
const resolvedModel = renderModelDestructive(
request,
task,
emptyRoot,
'',
task.model,
);
if (__DEV__) {
debugID = null;
}
modelRoot = resolvedModel;
task.keyPath = null;
task.implicitSlot = false;
if (typeof resolvedModel === 'object' && resolvedModel !== null) {
request.writtenObjects.set(resolvedModel, serializeByValueID(task.id));
if (__DEV__) {
const currentEnv = (0, request.environmentName)();
if (currentEnv !== task.environmentName) {
request.pendingChunks++;
emitDebugChunk(request, task.id, {env: currentEnv});
}
}
emitChunk(request, task, resolvedModel);
} else {
const json: string = stringify(resolvedModel);
if (__DEV__) {
const currentEnv = (0, request.environmentName)();
if (currentEnv !== task.environmentName) {
request.pendingChunks++;
emitDebugChunk(request, task.id, {env: currentEnv});
}
}
emitModelChunk(request, task.id, json);
}
request.abortableTasks.delete(task);
task.status = COMPLETED;
} catch (thrownValue) {
if (request.status === ABORTING) {
request.abortableTasks.delete(task);
task.status = ABORTED;
if (enableHalt && request.type === PRERENDER) {
request.pendingChunks--;
} else {
const errorId: number = (request.fatalError: any);
const model = stringify(serializeByValueID(errorId));
emitModelChunk(request, task.id, model);
}
return;
}
const x =
thrownValue === SuspenseException
?
getSuspendedThenable()
: thrownValue;
if (typeof x === 'object' && x !== null) {
if (typeof x.then === 'function') {
task.status = PENDING;
task.thenableState = getThenableStateAfterSuspending();
const ping = task.ping;
x.then(ping, ping);
return;
} else if (enablePostpone && x.$$typeof === REACT_POSTPONE_TYPE) {
request.abortableTasks.delete(task);
task.status = ERRORED;
const postponeInstance: Postpone = (x: any);
logPostpone(request, postponeInstance.message, task);
emitPostponeChunk(request, task.id, postponeInstance);
return;
}
}
request.abortableTasks.delete(task);
task.status = ERRORED;
const digest = logRecoverableError(request, x, task);
emitErrorChunk(request, task.id, digest, x);
} finally {
if (__DEV__) {
debugID = prevDebugID;
}
}
}
function tryStreamTask(request: Request, task: Task): void {
const prevDebugID = debugID;
if (__DEV__) {
debugID = null;
}
try {
emitChunk(request, task, task.model);
} finally {
if (__DEV__) {
debugID = prevDebugID;
}
}
}
function performWork(request: Request): void {
const prevDispatcher = ReactSharedInternals.H;
ReactSharedInternals.H = HooksDispatcher;
const prevRequest = currentRequest;
currentRequest = request;
prepareToUseHooksForRequest(request);
const hadAbortableTasks = request.abortableTasks.size > 0;
try {
const pingedTasks = request.pingedTasks;
request.pingedTasks = [];
for (let i = 0; i < pingedTasks.length; i++) {
const task = pingedTasks[i];
retryTask(request, task);
}
if (request.destination !== null) {
flushCompletedChunks(request, request.destination);
}
if (hadAbortableTasks && request.abortableTasks.size === 0) {
const onAllReady = request.onAllReady;
onAllReady();
}
} catch (error) {
logRecoverableError(request, error, null);
fatalError(request, error);
} finally {
ReactSharedInternals.H = prevDispatcher;
resetHooksForRequest();
currentRequest = prevRequest;
}
}
function abortTask(task: Task, request: Request, errorId: number): void {
if (task.status === RENDERING) {
return;
}
task.status = ABORTED;
const ref = serializeByValueID(errorId);
const processedChunk = encodeReferenceChunk(request, task.id, ref);
request.completedErrorChunks.push(processedChunk);
}
function haltTask(task: Task, request: Request): void {
if (task.status === RENDERING) {
return;
}
task.status = ABORTED;
request.pendingChunks--;
}
function flushCompletedChunks(
request: Request,
destination: Destination,
): void {
beginWriting(destination);
try {
const importsChunks = request.completedImportChunks;
let i = 0;
for (; i < importsChunks.length; i++) {
request.pendingChunks--;
const chunk = importsChunks[i];
const keepWriting: boolean = writeChunkAndReturn(destination, chunk);
if (!keepWriting) {
request.destination = null;
i++;
break;
}
}
importsChunks.splice(0, i);
const hintChunks = request.completedHintChunks;
i = 0;
for (; i < hintChunks.length; i++) {
const chunk = hintChunks[i];
const keepWriting: boolean = writeChunkAndReturn(destination, chunk);
if (!keepWriting) {
request.destination = null;
i++;
break;
}
}
hintChunks.splice(0, i);
const regularChunks = request.completedRegularChunks;
i = 0;
for (; i < regularChunks.length; i++) {
request.pendingChunks--;
const chunk = regularChunks[i];
const keepWriting: boolean = writeChunkAndReturn(destination, chunk);
if (!keepWriting) {
request.destination = null;
i++;
break;
}
}
regularChunks.splice(0, i);
const errorChunks = request.completedErrorChunks;
i = 0;
for (; i < errorChunks.length; i++) {
request.pendingChunks--;
const chunk = errorChunks[i];
const keepWriting: boolean = writeChunkAndReturn(destination, chunk);
if (!keepWriting) {
request.destination = null;
i++;
break;
}
}
errorChunks.splice(0, i);
} finally {
request.flushScheduled = false;
completeWriting(destination);
}
flushBuffered(destination);
if (request.pendingChunks === 0) {
if (enableTaint) {
cleanupTaintQueue(request);
}
request.status = CLOSED;
close(destination);
request.destination = null;
}
}
export function startWork(request: Request): void {
request.flushScheduled = request.destination !== null;
if (supportsRequestStorage) {
scheduleMicrotask(() => {
requestStorage.run(request, performWork, request);
});
} else {
scheduleMicrotask(() => performWork(request));
}
scheduleWork(() => {
if (request.status === OPENING) {
request.status = OPEN;
}
});
}
function enqueueFlush(request: Request): void {
if (
request.flushScheduled === false &&
request.pingedTasks.length === 0 &&
request.destination !== null
) {
request.flushScheduled = true;
scheduleWork(() => {
request.flushScheduled = false;
const destination = request.destination;
if (destination) {
flushCompletedChunks(request, destination);
}
});
}
}
export function startFlowing(request: Request, destination: Destination): void {
if (request.status === CLOSING) {
request.status = CLOSED;
closeWithError(destination, request.fatalError);
return;
}
if (request.status === CLOSED) {
return;
}
if (request.destination !== null) {
return;
}
request.destination = destination;
try {
flushCompletedChunks(request, destination);
} catch (error) {
logRecoverableError(request, error, null);
fatalError(request, error);
}
}
export function stopFlowing(request: Request): void {
request.destination = null;
}
export function abort(request: Request, reason: mixed): void {
try {
if (request.status <= OPEN) {
request.status = ABORTING;
}
const abortableTasks = request.abortableTasks;
if (abortableTasks.size > 0) {
if (
enablePostpone &&
typeof reason === 'object' &&
reason !== null &&
(reason: any).$$typeof === REACT_POSTPONE_TYPE
) {
const postponeInstance: Postpone = (reason: any);
logPostpone(request, postponeInstance.message, null);
if (enableHalt && request.type === PRERENDER) {
abortableTasks.forEach(task => haltTask(task, request));
abortableTasks.clear();
} else {
const errorId = request.nextChunkId++;
request.fatalError = errorId;
request.pendingChunks++;
emitPostponeChunk(request, errorId, postponeInstance);
abortableTasks.forEach(task => abortTask(task, request, errorId));
abortableTasks.clear();
}
} else {
const error =
reason === undefined
? new Error(
'The render was aborted by the server without a reason.',
)
: typeof reason === 'object' &&
reason !== null &&
typeof reason.then === 'function'
? new Error(
'The render was aborted by the server with a promise.',
)
: reason;
const digest = logRecoverableError(request, error, null);
if (enableHalt && request.type === PRERENDER) {
abortableTasks.forEach(task => haltTask(task, request));
abortableTasks.clear();
} else {
const errorId = request.nextChunkId++;
request.fatalError = errorId;
request.pendingChunks++;
emitErrorChunk(request, errorId, digest, error);
abortableTasks.forEach(task => abortTask(task, request, errorId));
abortableTasks.clear();
}
}
const onAllReady = request.onAllReady;
onAllReady();
}
const abortListeners = request.abortListeners;
if (abortListeners.size > 0) {
let error;
if (
enablePostpone &&
typeof reason === 'object' &&
reason !== null &&
(reason: any).$$typeof === REACT_POSTPONE_TYPE
) {
error = new Error('The render was aborted due to being postponed.');
} else {
error =
reason === undefined
? new Error(
'The render was aborted by the server without a reason.',
)
: typeof reason === 'object' &&
reason !== null &&
typeof reason.then === 'function'
? new Error(
'The render was aborted by the server with a promise.',
)
: reason;
}
abortListeners.forEach(callback => callback(error));
abortListeners.clear();
}
if (request.destination !== null) {
flushCompletedChunks(request, request.destination);
}
} catch (error) {
logRecoverableError(request, error, null);
fatalError(request, error);
}
}