Files
react/compiled/facebook-www/ReactFlightDOMServer-dev.modern.js
T
sebmarkbage b2392647b5 [Flight] Serialize deduped elements by direct reference even if they suspend (#28283)
In #28123 I switched these to be lazy references. However that creates a
lazy wrapper even if they're synchronously available. We try to as much
as possible preserve the original data structure in these cases.

E.g. here in the dev outlining I only use a lazy wrapper if it didn't
complete synchronously:
https://github.com/facebook/react/pull/28272/files#diff-d4c9c509922b3671d3ecce4e051df66dd5c3d38ff913c7a7fe94abc3ba2ed72eR638

Unfortunately we don't have a data structure that tracks the status of
each emitted row. We could store the task in the map but then they
couldn't be GC:ed as they complete. We could maybe store the status of
each element but seems so heavy.

For now I just went back to direct reference which might be an issue
since it can suspend something higher up when deduped.

DiffTrain build for [ba5e6a8329](https://github.com/facebook/react/commit/ba5e6a8329c7194a2c573c037a37f24ce45ee58f)
2024-02-08 23:50:18 +00:00

2605 lines
83 KiB
JavaScript

/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @noflow
* @nolint
* @preventMunge
* @preserve-invariant-messages
*/
"use strict";
if (__DEV__) {
(function () {
"use strict";
var ReactDOM = require("react-dom");
var React = require("react");
// eslint-disable-next-line no-unused-vars
// eslint-disable-next-line no-unused-vars
var requestedClientReferencesKeys = new Set();
var checkIsClientReference;
function setCheckIsClientReference(impl) {
checkIsClientReference = impl;
}
function registerClientReference(clientReference) {}
function isClientReference(reference) {
if (checkIsClientReference == null) {
throw new Error("Expected implementation for checkIsClientReference.");
}
return checkIsClientReference(reference);
}
function getClientReferenceKey(clientReference) {
var moduleId = clientReference.getModuleId();
requestedClientReferencesKeys.add(moduleId);
return clientReference.getModuleId();
}
function resolveClientReferenceMetadata(config, clientReference) {
return {
moduleId: clientReference.getModuleId(),
exportName: "default"
};
}
function registerServerReference(serverReference, id, exportName) {
throw new Error("registerServerReference: Not Implemented.");
}
function isServerReference(reference) {
throw new Error("isServerReference: Not Implemented.");
}
function getServerReferenceId(config, serverReference) {
throw new Error("getServerReferenceId: Not Implemented.");
}
function getRequestedClientReferencesKeys() {
return Array.from(requestedClientReferencesKeys);
}
function clearRequestedClientReferencesKeysSet() {
requestedClientReferencesKeys.clear();
}
// This refers to a WWW module.
var warningWWW = require("warning");
function error(format) {
{
{
for (
var _len2 = arguments.length,
args = new Array(_len2 > 1 ? _len2 - 1 : 0),
_key2 = 1;
_key2 < _len2;
_key2++
) {
args[_key2 - 1] = arguments[_key2];
}
printWarning("error", format, args);
}
}
}
function printWarning(level, format, args) {
{
var React = require("react");
var ReactSharedInternals =
React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; // Defensive in case this is fired before React is initialized.
if (ReactSharedInternals != null) {
var ReactDebugCurrentFrame =
ReactSharedInternals.ReactDebugCurrentFrame;
var stack = ReactDebugCurrentFrame.getStackAddendum();
if (stack !== "") {
format += "%s";
args.push(stack);
}
} // TODO: don't ignore level and pass it down somewhere too.
args.unshift(format);
args.unshift(false);
warningWWW.apply(null, args);
}
}
// Re-export dynamic flags from the www version.
require("ReactFeatureFlags");
function stringToChunk(content) {
return content;
}
var byteLengthImpl = null;
function setByteLengthOfChunkImplementation(impl) {
byteLengthImpl = impl;
}
function byteLengthOfChunk(chunk) {
if (byteLengthImpl == null) {
// eslint-disable-next-line react-internal/prod-error-codes
throw new Error(
"byteLengthOfChunk implementation is not configured. Please, provide the implementation via ReactFlightDOMServer.setConfig(...);"
);
}
return byteLengthImpl(chunk);
}
function scheduleWork(callback) {
callback();
}
function beginWriting(destination) {
destination.beginWriting();
}
function writeChunkAndReturn(destination, chunk) {
destination.write(chunk);
return true;
}
function completeWriting(destination) {
destination.completeWriting();
}
function flushBuffered(destination) {
destination.flushBuffered();
}
function close(destination) {
destination.close();
}
function closeWithError(destination, error) {
destination.onError(error);
destination.close();
}
function getServerReferenceBoundArguments(config, serverReference) {
throw new Error("getServerReferenceBoundArguments: Not Implemented.");
}
var ReactDOMSharedInternals =
ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
var ReactDOMFlightServerDispatcher = {
prefetchDNS: prefetchDNS,
preconnect: preconnect,
preload: preload,
preloadModule: preloadModule,
preinitStyle: preinitStyle,
preinitScript: preinitScript,
preinitModuleScript: preinitModuleScript
};
function prefetchDNS(href) {
{
if (typeof href === "string" && href) {
var request = resolveRequest();
if (request) {
var hints = getHints(request);
var key = "D|" + href;
if (hints.has(key)) {
// duplicate hint
return;
}
hints.add(key);
emitHint(request, "D", href);
}
}
}
}
function preconnect(href, crossOrigin) {
{
if (typeof href === "string") {
var request = resolveRequest();
if (request) {
var hints = getHints(request);
var key =
"C|" + (crossOrigin == null ? "null" : crossOrigin) + "|" + href;
if (hints.has(key)) {
// duplicate hint
return;
}
hints.add(key);
if (typeof crossOrigin === "string") {
emitHint(request, "C", [href, crossOrigin]);
} else {
emitHint(request, "C", href);
}
}
}
}
}
function preload(href, as, options) {
{
if (typeof href === "string") {
var request = resolveRequest();
if (request) {
var hints = getHints(request);
var key = "L";
if (as === "image" && options) {
key += getImagePreloadKey(
href,
options.imageSrcSet,
options.imageSizes
);
} else {
key += "[" + as + "]" + href;
}
if (hints.has(key)) {
// duplicate hint
return;
}
hints.add(key);
var trimmed = trimOptions(options);
if (trimmed) {
emitHint(request, "L", [href, as, trimmed]);
} else {
emitHint(request, "L", [href, as]);
}
}
}
}
}
function preloadModule(href, options) {
{
if (typeof href === "string") {
var request = resolveRequest();
if (request) {
var hints = getHints(request);
var key = "m|" + href;
if (hints.has(key)) {
// duplicate hint
return;
}
hints.add(key);
var trimmed = trimOptions(options);
if (trimmed) {
return emitHint(request, "m", [href, trimmed]);
} else {
return emitHint(request, "m", href);
}
}
}
}
}
function preinitStyle(href, precedence, options) {
{
if (typeof href === "string") {
var request = resolveRequest();
if (request) {
var hints = getHints(request);
var key = "S|" + href;
if (hints.has(key)) {
// duplicate hint
return;
}
hints.add(key);
var trimmed = trimOptions(options);
if (trimmed) {
return emitHint(request, "S", [
href,
typeof precedence === "string" ? precedence : 0,
trimmed
]);
} else if (typeof precedence === "string") {
return emitHint(request, "S", [href, precedence]);
} else {
return emitHint(request, "S", href);
}
}
}
}
}
function preinitScript(href, options) {
{
if (typeof href === "string") {
var request = resolveRequest();
if (request) {
var hints = getHints(request);
var key = "X|" + href;
if (hints.has(key)) {
// duplicate hint
return;
}
hints.add(key);
var trimmed = trimOptions(options);
if (trimmed) {
return emitHint(request, "X", [href, trimmed]);
} else {
return emitHint(request, "X", href);
}
}
}
}
}
function preinitModuleScript(href, options) {
{
if (typeof href === "string") {
var request = resolveRequest();
if (request) {
var hints = getHints(request);
var key = "M|" + href;
if (hints.has(key)) {
// duplicate hint
return;
}
hints.add(key);
var trimmed = trimOptions(options);
if (trimmed) {
return emitHint(request, "M", [href, trimmed]);
} else {
return emitHint(request, "M", href);
}
}
}
}
} // Flight normally encodes undefined as a special character however for directive option
// arguments we don't want to send unnecessary keys and bloat the payload so we create a
// trimmed object which omits any keys with null or undefined values.
// This is only typesafe because these option objects have entirely optional fields where
// null and undefined represent the same thing as no property.
function trimOptions(options) {
if (options == null) return null;
var hasProperties = false;
var trimmed = {};
for (var key in options) {
if (options[key] != null) {
hasProperties = true;
trimmed[key] = options[key];
}
}
return hasProperties ? trimmed : null;
}
function getImagePreloadKey(href, imageSrcSet, imageSizes) {
var uniquePart = "";
if (typeof imageSrcSet === "string" && imageSrcSet !== "") {
uniquePart += "[" + imageSrcSet + "]";
if (typeof imageSizes === "string") {
uniquePart += "[" + imageSizes + "]";
}
} else {
uniquePart += "[][]" + href;
}
return "[image]" + uniquePart;
}
var ReactDOMCurrentDispatcher = ReactDOMSharedInternals.Dispatcher;
function prepareHostDispatcher() {
ReactDOMCurrentDispatcher.current = ReactDOMFlightServerDispatcher;
} // Used to distinguish these contexts from ones used in other renderers.
// small, smaller than how we encode undefined, and is unambiguous. We could use
// a different tuple structure to encode this instead but this makes the runtime
// cost cheaper by eliminating a type checks in more positions.
// prettier-ignore
function createHints() {
return new Set();
}
// ATTENTION
// When adding new symbols to this file,
// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols'
// The Symbol used to tag the ReactElement-like types.
var REACT_ELEMENT_TYPE = Symbol.for("react.element");
var REACT_FRAGMENT_TYPE = Symbol.for("react.fragment");
var REACT_CONTEXT_TYPE = Symbol.for("react.context");
var REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref");
var REACT_SUSPENSE_TYPE = Symbol.for("react.suspense");
var REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list");
var REACT_MEMO_TYPE = Symbol.for("react.memo");
var REACT_LAZY_TYPE = Symbol.for("react.lazy");
var REACT_MEMO_CACHE_SENTINEL = Symbol.for("react.memo_cache_sentinel");
var MAYBE_ITERATOR_SYMBOL = Symbol.iterator;
var FAUX_ITERATOR_SYMBOL = "@@iterator";
function getIteratorFn(maybeIterable) {
if (maybeIterable === null || typeof maybeIterable !== "object") {
return null;
}
var maybeIterator =
(MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL]) ||
maybeIterable[FAUX_ITERATOR_SYMBOL];
if (typeof maybeIterator === "function") {
return maybeIterator;
}
return null;
}
// Corresponds to ReactFiberWakeable and ReactFizzWakeable modules. Generally,
// changes to one module should be reflected in the others.
// TODO: Rename this module and the corresponding Fiber one to "Thenable"
// instead of "Wakeable". Or some other more appropriate name.
// An error that is thrown (e.g. by `use`) to trigger Suspense. If we
// detect this is caught by userspace, we'll log a warning in development.
var SuspenseException = new Error(
"Suspense Exception: This is not a real error! It's an implementation " +
"detail of `use` to interrupt the current render. You must either " +
"rethrow it immediately, or move the `use` call outside of the " +
"`try/catch` block. Capturing without rethrowing will lead to " +
"unexpected behavior.\n\n" +
"To handle async errors, wrap your component in an error boundary, or " +
"call the promise's `.catch` method and pass the result to `use`"
);
function createThenableState() {
// The ThenableState is created the first time a component suspends. If it
// suspends again, we'll reuse the same state.
return [];
}
function noop() {}
function trackUsedThenable(thenableState, thenable, index) {
var previous = thenableState[index];
if (previous === undefined) {
thenableState.push(thenable);
} else {
if (previous !== thenable) {
// Reuse the previous thenable, and drop the new one. We can assume
// they represent the same value, because components are idempotent.
// Avoid an unhandled rejection errors for the Promises that we'll
// intentionally ignore.
thenable.then(noop, noop);
thenable = previous;
}
} // We use an expando to track the status and result of a thenable so that we
// can synchronously unwrap the value. Think of this as an extension of the
// Promise API, or a custom interface that is a superset of Thenable.
//
// If the thenable doesn't have a status, set it to "pending" and attach
// a listener that will update its status and result when it resolves.
switch (thenable.status) {
case "fulfilled": {
var fulfilledValue = thenable.value;
return fulfilledValue;
}
case "rejected": {
var rejectedError = thenable.reason;
throw rejectedError;
}
default: {
if (typeof thenable.status === "string");
else {
var pendingThenable = thenable;
pendingThenable.status = "pending";
pendingThenable.then(
function (fulfilledValue) {
if (thenable.status === "pending") {
var fulfilledThenable = thenable;
fulfilledThenable.status = "fulfilled";
fulfilledThenable.value = fulfilledValue;
}
},
function (error) {
if (thenable.status === "pending") {
var rejectedThenable = thenable;
rejectedThenable.status = "rejected";
rejectedThenable.reason = error;
}
}
); // Check one more time in case the thenable resolved synchronously
switch (thenable.status) {
case "fulfilled": {
var fulfilledThenable = thenable;
return fulfilledThenable.value;
}
case "rejected": {
var rejectedThenable = thenable;
throw rejectedThenable.reason;
}
}
} // Suspend.
//
// Throwing here is an implementation detail that allows us to unwind the
// call stack. But we shouldn't allow it to leak into userspace. Throw an
// opaque placeholder value instead of the actual thenable. If it doesn't
// get captured by the work loop, log a warning, because that means
// something in userspace must have caught it.
suspendedThenable = thenable;
throw SuspenseException;
}
}
} // This is used to track the actual thenable that suspended so it can be
// passed to the rest of the Suspense implementation — which, for historical
// reasons, expects to receive a thenable.
var suspendedThenable = null;
function getSuspendedThenable() {
// This is called right after `use` suspends by throwing an exception. `use`
// throws an opaque value instead of the thenable itself so that it can't be
// caught in userspace. Then the work loop accesses the actual thenable using
// this function.
if (suspendedThenable === null) {
throw new Error(
"Expected a suspended thenable. This is a bug in React. Please file " +
"an issue."
);
}
var thenable = suspendedThenable;
suspendedThenable = null;
return thenable;
}
var currentRequest$1 = null;
var thenableIndexCounter = 0;
var thenableState = null;
function prepareToUseHooksForRequest(request) {
currentRequest$1 = request;
}
function resetHooksForRequest() {
currentRequest$1 = null;
}
function prepareToUseHooksForComponent(prevThenableState) {
thenableIndexCounter = 0;
thenableState = prevThenableState;
}
function getThenableStateAfterSuspending() {
// If you use() to Suspend this should always exist but if you throw a Promise instead,
// which is not really supported anymore, it will be empty. We use the empty set as a
// marker to know if this was a replay of the same component or first attempt.
var state = thenableState || createThenableState();
thenableState = null;
return state;
}
var HooksDispatcher = {
useMemo: function (nextCreate) {
return nextCreate();
},
useCallback: function (callback) {
return callback;
},
useDebugValue: function () {},
useDeferredValue: unsupportedHook,
useTransition: unsupportedHook,
readContext: unsupportedContext,
useContext: unsupportedContext,
useReducer: unsupportedHook,
useRef: unsupportedHook,
useState: unsupportedHook,
useInsertionEffect: unsupportedHook,
useLayoutEffect: unsupportedHook,
useImperativeHandle: unsupportedHook,
useEffect: unsupportedHook,
useId: useId,
useSyncExternalStore: unsupportedHook,
useCacheRefresh: function () {
return unsupportedRefresh;
},
useMemoCache: function (size) {
var data = new Array(size);
for (var i = 0; i < size; i++) {
data[i] = REACT_MEMO_CACHE_SENTINEL;
}
return data;
},
use: use
};
function unsupportedHook() {
throw new Error("This Hook is not supported in Server Components.");
}
function unsupportedRefresh() {
throw new Error(
"Refreshing the cache is not supported in Server Components."
);
}
function unsupportedContext() {
throw new Error("Cannot read a Client Context from a Server Component.");
}
function useId() {
if (currentRequest$1 === null) {
throw new Error("useId can only be used while React is rendering");
}
var id = currentRequest$1.identifierCount++; // use 'S' for Flight components to distinguish from 'R' and 'r' in Fizz/Client
return (
":" + currentRequest$1.identifierPrefix + "S" + id.toString(32) + ":"
);
}
function use(usable) {
if (
(usable !== null && typeof usable === "object") ||
typeof usable === "function"
) {
// $FlowFixMe[method-unbinding]
if (typeof usable.then === "function") {
// This is a thenable.
var thenable = usable; // Track the position of the thenable within this fiber.
var index = thenableIndexCounter;
thenableIndexCounter += 1;
if (thenableState === null) {
thenableState = createThenableState();
}
return trackUsedThenable(thenableState, thenable, index);
} else if (usable.$$typeof === REACT_CONTEXT_TYPE) {
unsupportedContext();
}
}
if (isClientReference(usable)) {
if (
usable.value != null &&
usable.value.$$typeof === REACT_CONTEXT_TYPE
) {
// Show a more specific message since it's a common mistake.
throw new Error(
"Cannot read a Client Context from a Server Component."
);
} else {
throw new Error("Cannot use() an already resolved Client Reference.");
}
} else {
throw new Error( // eslint-disable-next-line react-internal/safe-string-coercion
"An unsupported type was passed to use(): " + String(usable)
);
}
}
function createSignal() {
return new AbortController().signal;
}
function resolveCache() {
var request = resolveRequest();
if (request) {
return getCache(request);
}
return new Map();
}
var DefaultCacheDispatcher = {
getCacheSignal: function () {
var cache = resolveCache();
var entry = cache.get(createSignal);
if (entry === undefined) {
entry = createSignal();
cache.set(createSignal, entry);
}
return entry;
},
getCacheForType: function (resourceType) {
var cache = resolveCache();
var entry = cache.get(resourceType);
if (entry === undefined) {
entry = resourceType(); // TODO: Warn if undefined?
cache.set(resourceType, entry);
}
return entry;
}
};
var isArrayImpl = Array.isArray; // eslint-disable-next-line no-redeclare
function isArray(a) {
return isArrayImpl(a);
}
var getPrototypeOf = Object.getPrototypeOf;
// in case they error.
var jsxPropsParents = new WeakMap();
var jsxChildrenParents = new WeakMap();
function isObjectPrototype(object) {
if (!object) {
return false;
}
var ObjectPrototype = Object.prototype;
if (object === ObjectPrototype) {
return true;
} // It might be an object from a different Realm which is
// still just a plain simple object.
if (getPrototypeOf(object)) {
return false;
}
var names = Object.getOwnPropertyNames(object);
for (var i = 0; i < names.length; i++) {
if (!(names[i] in ObjectPrototype)) {
return false;
}
}
return true;
}
function isSimpleObject(object) {
if (!isObjectPrototype(getPrototypeOf(object))) {
return false;
}
var names = Object.getOwnPropertyNames(object);
for (var i = 0; i < names.length; i++) {
var descriptor = Object.getOwnPropertyDescriptor(object, names[i]);
if (!descriptor) {
return false;
}
if (!descriptor.enumerable) {
if (
(names[i] === "key" || names[i] === "ref") &&
typeof descriptor.get === "function"
) {
// React adds key and ref getters to props objects to issue warnings.
// Those getters will not be transferred to the client, but that's ok,
// so we'll special case them.
continue;
}
return false;
}
}
return true;
}
function objectName(object) {
// $FlowFixMe[method-unbinding]
var name = Object.prototype.toString.call(object);
return name.replace(/^\[object (.*)\]$/, function (m, p0) {
return p0;
});
}
function describeKeyForErrorMessage(key) {
var encodedKey = JSON.stringify(key);
return '"' + key + '"' === encodedKey ? key : encodedKey;
}
function describeValueForErrorMessage(value) {
switch (typeof value) {
case "string": {
return JSON.stringify(
value.length <= 10 ? value : value.slice(0, 10) + "..."
);
}
case "object": {
if (isArray(value)) {
return "[...]";
}
var name = objectName(value);
if (name === "Object") {
return "{...}";
}
return name;
}
case "function":
return "function";
default:
// eslint-disable-next-line react-internal/safe-string-coercion
return String(value);
}
}
function describeElementType(type) {
if (typeof type === "string") {
return type;
}
switch (type) {
case REACT_SUSPENSE_TYPE:
return "Suspense";
case REACT_SUSPENSE_LIST_TYPE:
return "SuspenseList";
}
if (typeof type === "object") {
switch (type.$$typeof) {
case REACT_FORWARD_REF_TYPE:
return describeElementType(type.render);
case REACT_MEMO_TYPE:
return describeElementType(type.type);
case REACT_LAZY_TYPE: {
var lazyComponent = type;
var payload = lazyComponent._payload;
var init = lazyComponent._init;
try {
// Lazy may contain any component type so we recursively resolve it.
return describeElementType(init(payload));
} catch (x) {}
}
}
}
return "";
}
function describeObjectForErrorMessage(objectOrArray, expandedName) {
var objKind = objectName(objectOrArray);
if (objKind !== "Object" && objKind !== "Array") {
return objKind;
}
var str = "";
var start = -1;
var length = 0;
if (isArray(objectOrArray)) {
if (jsxChildrenParents.has(objectOrArray)) {
// Print JSX Children
var type = jsxChildrenParents.get(objectOrArray);
str = "<" + describeElementType(type) + ">";
var array = objectOrArray;
for (var i = 0; i < array.length; i++) {
var value = array[i];
var substr = void 0;
if (typeof value === "string") {
substr = value;
} else if (typeof value === "object" && value !== null) {
substr = "{" + describeObjectForErrorMessage(value) + "}";
} else {
substr = "{" + describeValueForErrorMessage(value) + "}";
}
if ("" + i === expandedName) {
start = str.length;
length = substr.length;
str += substr;
} else if (substr.length < 15 && str.length + substr.length < 40) {
str += substr;
} else {
str += "{...}";
}
}
str += "</" + describeElementType(type) + ">";
} else {
// Print Array
str = "[";
var _array = objectOrArray;
for (var _i = 0; _i < _array.length; _i++) {
if (_i > 0) {
str += ", ";
}
var _value = _array[_i];
var _substr = void 0;
if (typeof _value === "object" && _value !== null) {
_substr = describeObjectForErrorMessage(_value);
} else {
_substr = describeValueForErrorMessage(_value);
}
if ("" + _i === expandedName) {
start = str.length;
length = _substr.length;
str += _substr;
} else if (
_substr.length < 10 &&
str.length + _substr.length < 40
) {
str += _substr;
} else {
str += "...";
}
}
str += "]";
}
} else {
if (objectOrArray.$$typeof === REACT_ELEMENT_TYPE) {
str = "<" + describeElementType(objectOrArray.type) + "/>";
} else if (jsxPropsParents.has(objectOrArray)) {
// Print JSX
var _type = jsxPropsParents.get(objectOrArray);
str = "<" + (describeElementType(_type) || "...");
var object = objectOrArray;
var names = Object.keys(object);
for (var _i2 = 0; _i2 < names.length; _i2++) {
str += " ";
var name = names[_i2];
str += describeKeyForErrorMessage(name) + "=";
var _value2 = object[name];
var _substr2 = void 0;
if (
name === expandedName &&
typeof _value2 === "object" &&
_value2 !== null
) {
_substr2 = describeObjectForErrorMessage(_value2);
} else {
_substr2 = describeValueForErrorMessage(_value2);
}
if (typeof _value2 !== "string") {
_substr2 = "{" + _substr2 + "}";
}
if (name === expandedName) {
start = str.length;
length = _substr2.length;
str += _substr2;
} else if (
_substr2.length < 10 &&
str.length + _substr2.length < 40
) {
str += _substr2;
} else {
str += "...";
}
}
str += ">";
} else {
// Print Object
str = "{";
var _object = objectOrArray;
var _names = Object.keys(_object);
for (var _i3 = 0; _i3 < _names.length; _i3++) {
if (_i3 > 0) {
str += ", ";
}
var _name = _names[_i3];
str += describeKeyForErrorMessage(_name) + ": ";
var _value3 = _object[_name];
var _substr3 = void 0;
if (typeof _value3 === "object" && _value3 !== null) {
_substr3 = describeObjectForErrorMessage(_value3);
} else {
_substr3 = describeValueForErrorMessage(_value3);
}
if (_name === expandedName) {
start = str.length;
length = _substr3.length;
str += _substr3;
} else if (
_substr3.length < 10 &&
str.length + _substr3.length < 40
) {
str += _substr3;
} else {
str += "...";
}
}
str += "}";
}
}
if (expandedName === undefined) {
return str;
}
if (start > -1 && length > 0) {
var highlight = " ".repeat(start) + "^".repeat(length);
return "\n " + str + "\n " + highlight;
}
return "\n " + str;
}
var ReactSharedInternals =
React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
var ReactSharedServerInternals = // $FlowFixMe: It's defined in the one we resolve to.
React.__SECRET_SERVER_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
if (!ReactSharedServerInternals) {
throw new Error(
'The "react" package in this environment is not configured correctly. ' +
'The "react-server" condition must be enabled in any environment that ' +
"runs React Server Components."
);
}
var ObjectPrototype = Object.prototype;
var stringify = JSON.stringify; // Serializable values
// Thenable<ReactClientValue>
var PENDING = 0;
var COMPLETED = 1;
var ERRORED = 4;
var ReactCurrentCache = ReactSharedServerInternals.ReactCurrentCache;
var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher;
function defaultErrorHandler(error) {
console["error"](error); // Don't transform to our wrapper
}
function defaultPostponeHandler(reason) {
// Noop
}
var OPEN = 0;
var CLOSING = 1;
var CLOSED = 2;
function createRequest(
model,
bundlerConfig,
onError,
identifierPrefix,
onPostpone
) {
if (
ReactCurrentCache.current !== null &&
ReactCurrentCache.current !== DefaultCacheDispatcher
) {
throw new Error(
"Currently React only supports one RSC renderer at a time."
);
}
prepareHostDispatcher();
ReactCurrentCache.current = DefaultCacheDispatcher;
var abortSet = new Set();
var pingedTasks = [];
var cleanupQueue = [];
var hints = createHints();
var request = {
status: OPEN,
flushScheduled: false,
fatalError: null,
destination: null,
bundlerConfig: bundlerConfig,
cache: new Map(),
nextChunkId: 0,
pendingChunks: 0,
hints: hints,
abortableTasks: abortSet,
pingedTasks: pingedTasks,
completedImportChunks: [],
completedHintChunks: [],
completedRegularChunks: [],
completedErrorChunks: [],
writtenSymbols: new Map(),
writtenClientReferences: new Map(),
writtenServerReferences: new Map(),
writtenObjects: new WeakMap(),
identifierPrefix: identifierPrefix || "",
identifierCount: 1,
taintCleanupQueue: cleanupQueue,
onError: onError === undefined ? defaultErrorHandler : onError,
onPostpone:
onPostpone === undefined ? defaultPostponeHandler : onPostpone
};
var rootTask = createTask(request, model, null, false, abortSet);
pingedTasks.push(rootTask);
return request;
}
var currentRequest = null;
function resolveRequest() {
if (currentRequest) return currentRequest;
return null;
}
function serializeThenable(request, task, thenable) {
var newTask = createTask(
request,
null,
task.keyPath, // the server component sequence continues through Promise-as-a-child.
task.implicitSlot,
request.abortableTasks
);
switch (thenable.status) {
case "fulfilled": {
// We have the resolved value, we can go ahead and schedule it for serialization.
newTask.model = thenable.value;
pingTask(request, newTask);
return newTask.id;
}
case "rejected": {
var x = thenable.reason;
{
var digest = logRecoverableError(request, x);
emitErrorChunk(request, newTask.id, digest, x);
}
return newTask.id;
}
default: {
if (typeof thenable.status === "string") {
// Only instrument the thenable if the status if not defined. If
// it's defined, but an unknown value, assume it's been instrumented by
// some custom userspace implementation. We treat it as "pending".
break;
}
var pendingThenable = thenable;
pendingThenable.status = "pending";
pendingThenable.then(
function (fulfilledValue) {
if (thenable.status === "pending") {
var fulfilledThenable = thenable;
fulfilledThenable.status = "fulfilled";
fulfilledThenable.value = fulfilledValue;
}
},
function (error) {
if (thenable.status === "pending") {
var rejectedThenable = thenable;
rejectedThenable.status = "rejected";
rejectedThenable.reason = error;
}
}
);
break;
}
}
thenable.then(
function (value) {
newTask.model = value;
pingTask(request, newTask);
},
function (reason) {
{
newTask.status = ERRORED;
var _digest = logRecoverableError(request, reason);
emitErrorChunk(request, newTask.id, _digest, reason);
}
request.abortableTasks.delete(newTask);
if (request.destination !== null) {
flushCompletedChunks(request, request.destination);
}
}
);
return newTask.id;
}
function emitHint(request, code, model) {
emitHintChunk(request, code, model);
enqueueFlush(request);
}
function getHints(request) {
return request.hints;
}
function getCache(request) {
return request.cache;
}
function readThenable(thenable) {
if (thenable.status === "fulfilled") {
return thenable.value;
} else if (thenable.status === "rejected") {
throw thenable.reason;
}
throw thenable;
}
function createLazyWrapperAroundWakeable(wakeable) {
// This is a temporary fork of the `use` implementation until we accept
// promises everywhere.
var thenable = wakeable;
switch (thenable.status) {
case "fulfilled":
case "rejected":
break;
default: {
if (typeof thenable.status === "string") {
// Only instrument the thenable if the status if not defined. If
// it's defined, but an unknown value, assume it's been instrumented by
// some custom userspace implementation. We treat it as "pending".
break;
}
var pendingThenable = thenable;
pendingThenable.status = "pending";
pendingThenable.then(
function (fulfilledValue) {
if (thenable.status === "pending") {
var fulfilledThenable = thenable;
fulfilledThenable.status = "fulfilled";
fulfilledThenable.value = fulfilledValue;
}
},
function (error) {
if (thenable.status === "pending") {
var rejectedThenable = thenable;
rejectedThenable.status = "rejected";
rejectedThenable.reason = error;
}
}
);
break;
}
}
var lazyType = {
$$typeof: REACT_LAZY_TYPE,
_payload: thenable,
_init: readThenable
};
return lazyType;
}
function renderFunctionComponent(request, task, key, Component, props) {
// Reset the task's thenable state before continuing, so that if a later
// component suspends we can reuse the same task object. If the same
// component suspends again, the thenable state will be restored.
var prevThenableState = task.thenableState;
task.thenableState = null;
{
if (debugID === null) {
// We don't have a chunk to assign debug info. We need to outline this
// component to assign it an ID.
return outlineTask(request, task);
} else if (prevThenableState !== null);
else {
// This is a new component in the same task so we can emit more debug info.
var componentName = Component.displayName || Component.name || "";
request.pendingChunks++;
emitDebugChunk(request, debugID, {
name: componentName
});
}
}
prepareToUseHooksForComponent(prevThenableState); // The secondArg is always undefined in Server Components since refs error early.
var secondArg = undefined;
var result = Component(props, secondArg);
if (
typeof result === "object" &&
result !== null &&
typeof result.then === "function"
) {
// When the return value is in children position we can resolve it immediately,
// to its value without a wrapper if it's synchronously available.
var thenable = result;
if (thenable.status === "fulfilled") {
return thenable.value;
} // TODO: Once we accept Promises as children on the client, we can just return
// the thenable here.
result = createLazyWrapperAroundWakeable(result);
} // Track this element's key on the Server Component on the keyPath context..
var prevKeyPath = task.keyPath;
var prevImplicitSlot = task.implicitSlot;
if (key !== null) {
// Append the key to the path. Technically a null key should really add the child
// index. We don't do that to hold the payload small and implementation simple.
task.keyPath = prevKeyPath === null ? key : prevKeyPath + "," + key;
} else if (prevKeyPath === null) {
// This sequence of Server Components has no keys. This means that it was rendered
// in a slot that needs to assign an implicit key. Even if children below have
// explicit keys, they should not be used for the outer most key since it might
// collide with other slots in that set.
task.implicitSlot = true;
}
var json = renderModelDestructive(request, task, emptyRoot, "", result);
task.keyPath = prevKeyPath;
task.implicitSlot = prevImplicitSlot;
return json;
}
function renderFragment(request, task, children) {
if (task.keyPath !== null) {
// We have a Server Component that specifies a key but we're now splitting
// the tree using a fragment.
var fragment = [
REACT_ELEMENT_TYPE,
REACT_FRAGMENT_TYPE,
task.keyPath,
{
children: children
}
];
if (!task.implicitSlot) {
// If this was keyed inside a set. I.e. the outer Server Component was keyed
// then we need to handle reorders of the whole set. To do this we need to wrap
// this array in a keyed Fragment.
return fragment;
} // If the outer Server Component was implicit but then an inner one had a key
// we don't actually need to be able to move the whole set around. It'll always be
// in an implicit slot. The key only exists to be able to reset the state of the
// children. We could achieve the same effect by passing on the keyPath to the next
// set of components inside the fragment. This would also allow a keyless fragment
// reconcile against a single child.
// Unfortunately because of JSON.stringify, we can't call the recursive loop for
// each child within this context because we can't return a set with already resolved
// values. E.g. a string would get double encoded. Returning would pop the context.
// So instead, we wrap it with an unkeyed fragment and inner keyed fragment.
return [fragment];
} // Since we're yielding here, that implicitly resets the keyPath context on the
// way up. Which is what we want since we've consumed it. If this changes to
// be recursive serialization, we need to reset the keyPath and implicitSlot,
// before recursing here.
return children;
}
function renderClientElement(task, type, key, props) {
// the keys of any Server Components which are not serialized.
var keyPath = task.keyPath;
if (key === null) {
key = keyPath;
} else if (keyPath !== null) {
key = keyPath + "," + key;
}
var element = [REACT_ELEMENT_TYPE, type, key, props];
if (task.implicitSlot && key !== null) {
// The root Server Component had no key so it was in an implicit slot.
// If we had a key lower, it would end up in that slot with an explicit key.
// We wrap the element in a fragment to give it an implicit key slot with
// an inner explicit key.
return [element];
} // Since we're yielding here, that implicitly resets the keyPath context on the
// way up. Which is what we want since we've consumed it. If this changes to
// be recursive serialization, we need to reset the keyPath and implicitSlot,
// before recursing here. We also need to reset it once we render into an array
// or anything else too which we also get implicitly.
return element;
} // The chunk ID we're currently rendering that we can assign debug data to.
var debugID = null;
function outlineTask(request, task) {
var newTask = createTask(
request,
task.model, // the currently rendering element
task.keyPath, // unlike outlineModel this one carries along context
task.implicitSlot,
request.abortableTasks
);
retryTask(request, newTask);
if (newTask.status === COMPLETED) {
// We completed synchronously so we can refer to this by reference. This
// makes it behaves the same as prod during deserialization.
return serializeByValueID(newTask.id);
} // This didn't complete synchronously so it wouldn't have even if we didn't
// outline it, so this would reduce to a lazy reference even in prod.
return serializeLazyID(newTask.id);
}
function renderElement(request, task, type, key, ref, props) {
if (ref !== null && ref !== undefined) {
// When the ref moves to the regular props object this will implicitly
// throw for functions. We could probably relax it to a DEV warning for other
// cases.
throw new Error(
"Refs cannot be used in Server Components, nor passed to Client Components."
);
}
{
jsxPropsParents.set(props, type);
if (typeof props.children === "object" && props.children !== null) {
jsxChildrenParents.set(props.children, type);
}
}
if (typeof type === "function") {
if (isClientReference(type)) {
// This is a reference to a Client Component.
return renderClientElement(task, type, key, props);
} // This is a Server Component.
return renderFunctionComponent(request, task, key, type, props);
} else if (typeof type === "string") {
// This is a host element. E.g. HTML.
return renderClientElement(task, type, key, props);
} else if (typeof type === "symbol") {
if (type === REACT_FRAGMENT_TYPE && key === null) {
// For key-less fragments, we add a small optimization to avoid serializing
// it as a wrapper.
var prevImplicitSlot = task.implicitSlot;
if (task.keyPath === null) {
task.implicitSlot = true;
}
var json = renderModelDestructive(
request,
task,
emptyRoot,
"",
props.children
);
task.implicitSlot = prevImplicitSlot;
return json;
} // This might be a built-in React component. We'll let the client decide.
// Any built-in works as long as its props are serializable.
return renderClientElement(task, type, key, props);
} else if (type != null && typeof type === "object") {
if (isClientReference(type)) {
// This is a reference to a Client Component.
return renderClientElement(task, type, key, props);
}
switch (type.$$typeof) {
case REACT_LAZY_TYPE: {
var payload = type._payload;
var init = type._init;
var wrappedType = init(payload);
return renderElement(request, task, wrappedType, key, ref, props);
}
case REACT_FORWARD_REF_TYPE: {
return renderFunctionComponent(
request,
task,
key,
type.render,
props
);
}
case REACT_MEMO_TYPE: {
return renderElement(request, task, type.type, key, ref, props);
}
}
}
throw new Error(
"Unsupported Server Component type: " +
describeValueForErrorMessage(type)
);
}
function pingTask(request, task) {
var pingedTasks = request.pingedTasks;
pingedTasks.push(task);
if (pingedTasks.length === 1) {
request.flushScheduled = request.destination !== null;
scheduleWork(function () {
return performWork(request);
});
}
}
function createTask(request, model, keyPath, implicitSlot, abortSet) {
request.pendingChunks++;
var id = request.nextChunkId++;
if (typeof model === "object" && model !== null) {
// If we're about to write this into a new task we can assign it an ID early so that
// any other references can refer to the value we're about to write.
if (keyPath !== null || implicitSlot);
else {
request.writtenObjects.set(model, id);
}
}
var task = {
id: id,
status: PENDING,
model: model,
keyPath: keyPath,
implicitSlot: implicitSlot,
ping: function () {
return pingTask(request, task);
},
toJSON: function (parentPropertyName, value) {
var parent = this; // Make sure that `parent[parentPropertyName]` wasn't JSONified before `value` was passed to us
{
// $FlowFixMe[incompatible-use]
var originalValue = parent[parentPropertyName];
if (
typeof originalValue === "object" &&
originalValue !== value &&
!(originalValue instanceof Date)
) {
if (objectName(originalValue) !== "Object") {
var jsxParentType = jsxChildrenParents.get(parent);
if (typeof jsxParentType === "string") {
error(
"%s objects cannot be rendered as text children. Try formatting it using toString().%s",
objectName(originalValue),
describeObjectForErrorMessage(parent, parentPropertyName)
);
} else {
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 {
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
};
abortSet.add(task);
return task;
}
function serializeByValueID(id) {
return "$" + id.toString(16);
}
function serializeLazyID(id) {
return "$L" + id.toString(16);
}
function serializePromiseID(id) {
return "$@" + id.toString(16);
}
function serializeServerReferenceID(id) {
return "$F" + id.toString(16);
}
function serializeSymbolReference(name) {
return "$S" + name;
}
function serializeNumber(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() {
return "$undefined";
}
function serializeDateFromDateJSON(dateJSON) {
// JSON.stringify automatically calls Date.prototype.toJSON which calls toISOString.
// We need only tack on a $D prefix.
return "$D" + dateJSON;
}
function serializeBigInt(n) {
return "$n" + n.toString(10);
}
function serializeRowHeader(tag, id) {
return id.toString(16) + ":" + tag;
}
function encodeReferenceChunk(request, id, reference) {
var json = stringify(reference);
var row = id.toString(16) + ":" + json + "\n";
return stringToChunk(row);
}
function serializeClientReference(
request,
parent,
parentPropertyName,
clientReference
) {
var clientReferenceKey = getClientReferenceKey(clientReference);
var writtenClientReferences = request.writtenClientReferences;
var existingId = writtenClientReferences.get(clientReferenceKey);
if (existingId !== undefined) {
if (parent[0] === REACT_ELEMENT_TYPE && parentPropertyName === "1") {
// If we're encoding the "type" of an element, we can refer
// to that by a lazy reference instead of directly since React
// knows how to deal with lazy values. This lets us suspend
// on this component rather than its parent until the code has
// loaded.
return serializeLazyID(existingId);
}
return serializeByValueID(existingId);
}
try {
var clientReferenceMetadata = resolveClientReferenceMetadata(
request.bundlerConfig,
clientReference
);
request.pendingChunks++;
var importId = request.nextChunkId++;
emitImportChunk(request, importId, clientReferenceMetadata);
writtenClientReferences.set(clientReferenceKey, importId);
if (parent[0] === REACT_ELEMENT_TYPE && parentPropertyName === "1") {
// If we're encoding the "type" of an element, we can refer
// to that by a lazy reference instead of directly since React
// knows how to deal with lazy values. This lets us suspend
// on this component rather than its parent until the code has
// loaded.
return serializeLazyID(importId);
}
return serializeByValueID(importId);
} catch (x) {
request.pendingChunks++;
var errorId = request.nextChunkId++;
var digest = logRecoverableError(request, x);
emitErrorChunk(request, errorId, digest, x);
return serializeByValueID(errorId);
}
}
function outlineModel(request, value) {
var newTask = createTask(
request,
value,
null, // The way we use outlining is for reusing an object.
false, // It makes no sense for that use case to be contextual.
request.abortableTasks
);
retryTask(request, newTask);
return newTask.id;
}
function serializeServerReference(request, serverReference) {
var writtenServerReferences = request.writtenServerReferences;
var existingId = writtenServerReferences.get(serverReference);
if (existingId !== undefined) {
return serializeServerReferenceID(existingId);
}
var bound = getServerReferenceBoundArguments();
var serverReferenceMetadata = {
id: getServerReferenceId(),
bound: bound ? Promise.resolve(bound) : null
};
var metadataId = outlineModel(request, serverReferenceMetadata);
writtenServerReferences.set(serverReference, metadataId);
return serializeServerReferenceID(metadataId);
}
function serializeLargeTextString(request, text) {
request.pendingChunks += 2;
var textId = request.nextChunkId++;
var textChunk = stringToChunk(text);
var binaryLength = byteLengthOfChunk(textChunk);
var row = textId.toString(16) + ":T" + binaryLength.toString(16) + ",";
var headerChunk = stringToChunk(row);
request.completedRegularChunks.push(headerChunk, textChunk);
return serializeByValueID(textId);
}
function serializeMap(request, map) {
var entries = Array.from(map);
for (var i = 0; i < entries.length; i++) {
var key = entries[i][0];
if (typeof key === "object" && key !== null) {
var writtenObjects = request.writtenObjects;
var existingId = writtenObjects.get(key);
if (existingId === undefined) {
// Mark all object keys as seen so that they're always outlined.
writtenObjects.set(key, -1);
}
}
}
var id = outlineModel(request, entries);
return "$Q" + id.toString(16);
}
function serializeSet(request, set) {
var entries = Array.from(set);
for (var i = 0; i < entries.length; i++) {
var key = entries[i];
if (typeof key === "object" && key !== null) {
var writtenObjects = request.writtenObjects;
var existingId = writtenObjects.get(key);
if (existingId === undefined) {
// Mark all object keys as seen so that they're always outlined.
writtenObjects.set(key, -1);
}
}
}
var id = outlineModel(request, entries);
return "$W" + id.toString(16);
}
function escapeStringValue(value) {
if (value[0] === "$") {
// We need to escape $ prefixed strings since we use those to encode
// references to IDs and as special symbol values.
return "$" + value;
} else {
return value;
}
}
var modelRoot = false;
function renderModel(request, task, parent, key, value) {
var prevKeyPath = task.keyPath;
var prevImplicitSlot = task.implicitSlot;
try {
return renderModelDestructive(request, task, parent, key, value);
} catch (thrownValue) {
var x =
thrownValue === SuspenseException // This is a special type of exception used for Suspense. For historical
? // reasons, the rest of the Suspense implementation expects the thrown
// value to be a thenable, because before `use` existed that was the
// (unstable) API for suspending. This implementation detail can change
// later, once we deprecate the old API in favor of `use`.
getSuspendedThenable()
: thrownValue; // If the suspended/errored value was an element or lazy it can be reduced
// to a lazy reference, so that it doesn't error the parent.
var model = task.model;
var wasReactNode =
typeof model === "object" &&
model !== null &&
(model.$$typeof === REACT_ELEMENT_TYPE ||
model.$$typeof === REACT_LAZY_TYPE);
if (typeof x === "object" && x !== null) {
// $FlowFixMe[method-unbinding]
if (typeof x.then === "function") {
// Something suspended, we'll need to create a new task and resolve it later.
var newTask = createTask(
request,
task.model,
task.keyPath,
task.implicitSlot,
request.abortableTasks
);
var ping = newTask.ping;
x.then(ping, ping);
newTask.thenableState = getThenableStateAfterSuspending(); // Restore the context. We assume that this will be restored by the inner
// functions in case nothing throws so we don't use "finally" here.
task.keyPath = prevKeyPath;
task.implicitSlot = prevImplicitSlot;
if (wasReactNode) {
return serializeLazyID(newTask.id);
}
return serializeByValueID(newTask.id);
}
} // Restore the context. We assume that this will be restored by the inner
// functions in case nothing throws so we don't use "finally" here.
task.keyPath = prevKeyPath;
task.implicitSlot = prevImplicitSlot;
if (wasReactNode) {
// Something errored. We'll still send everything we have up until this point.
// We'll replace this element with a lazy reference that throws on the client
// once it gets rendered.
request.pendingChunks++;
var errorId = request.nextChunkId++;
var digest = logRecoverableError(request, x);
emitErrorChunk(request, errorId, digest, x);
return serializeLazyID(errorId);
} // Something errored but it was not in a React Node. There's no need to serialize
// it by value because it'll just error the whole parent row anyway so we can
// just stop any siblings and error the whole parent row.
throw x;
}
}
function renderModelDestructive(
request,
task,
parent,
parentPropertyName,
value
) {
// Set the currently rendering model
task.model = value; // Special Symbol, that's very common.
if (value === REACT_ELEMENT_TYPE) {
return "$";
}
if (value === null) {
return null;
}
if (typeof value === "object") {
switch (value.$$typeof) {
case REACT_ELEMENT_TYPE: {
var _writtenObjects = request.writtenObjects;
var _existingId = _writtenObjects.get(value);
if (_existingId !== undefined) {
if (task.keyPath !== null || task.implicitSlot);
else if (modelRoot === value) {
// This is the ID we're currently emitting so we need to write it
// once but if we discover it again, we refer to it by id.
modelRoot = null;
} else if (_existingId === -1) {
// Seen but not yet outlined.
// TODO: If we throw here we can treat this as suspending which causes an outline
// but that is able to reuse the same task if we're already in one but then that
// will be a lazy future value rather than guaranteed to exist but maybe that's good.
var newId = outlineModel(request, value);
return serializeByValueID(newId);
} else {
// We've already emitted this as an outlined object, so we can refer to that by its
// existing ID. TODO: We should use a lazy reference since, unlike plain objects,
// elements might suspend so it might not have emitted yet even if we have the ID for
// it. However, this creates an extra wrapper when it's not needed. We should really
// detect whether this already was emitted and synchronously available. In that
// case we can refer to it synchronously and only make it lazy otherwise.
// We currently don't have a data structure that lets us see that though.
return serializeByValueID(_existingId);
}
} else {
// This is the first time we've seen this object. We may never see it again
// so we'll inline it. Mark it as seen. If we see it again, we'll outline.
_writtenObjects.set(value, -1);
}
var element = value; // Attempt to render the Server Component.
return renderElement(
request,
task,
element.type, // $FlowFixMe[incompatible-call] the key of an element is null | string
element.key,
element.ref,
element.props
);
}
case REACT_LAZY_TYPE: {
var payload = value._payload;
var init = value._init;
var resolvedModel = init(payload);
return renderModelDestructive(
request,
task,
emptyRoot,
"",
resolvedModel
);
}
}
if (isClientReference(value)) {
return serializeClientReference(
request,
parent,
parentPropertyName,
value
);
}
var writtenObjects = request.writtenObjects;
var existingId = writtenObjects.get(value); // $FlowFixMe[method-unbinding]
if (typeof value.then === "function") {
if (existingId !== undefined) {
if (task.keyPath !== null || task.implicitSlot) {
// If we're in some kind of context we can't reuse the result of this render or
// previous renders of this element. We only reuse Promises if they're not wrapped
// by another Server Component.
var _promiseId = serializeThenable(request, task, value);
return serializePromiseID(_promiseId);
} else if (modelRoot === value) {
// This is the ID we're currently emitting so we need to write it
// once but if we discover it again, we refer to it by id.
modelRoot = null;
} else {
// We've seen this promise before, so we can just refer to the same result.
return serializePromiseID(existingId);
}
} // We assume that any object with a .then property is a "Thenable" type,
// or a Promise type. Either of which can be represented by a Promise.
var promiseId = serializeThenable(request, task, value);
writtenObjects.set(value, promiseId);
return serializePromiseID(promiseId);
}
if (existingId !== undefined) {
if (modelRoot === value) {
// This is the ID we're currently emitting so we need to write it
// once but if we discover it again, we refer to it by id.
modelRoot = null;
} else if (existingId === -1) {
// Seen but not yet outlined.
var _newId = outlineModel(request, value);
return serializeByValueID(_newId);
} else {
// We've already emitted this as an outlined object, so we can
// just refer to that by its existing ID.
return serializeByValueID(existingId);
}
} else {
// This is the first time we've seen this object. We may never see it again
// so we'll inline it. Mark it as seen. If we see it again, we'll outline.
writtenObjects.set(value, -1);
}
if (isArray(value)) {
return renderFragment(request, task, value);
}
if (value instanceof Map) {
return serializeMap(request, value);
}
if (value instanceof Set) {
return serializeSet(request, value);
}
var iteratorFn = getIteratorFn(value);
if (iteratorFn) {
return renderFragment(request, task, Array.from(value));
} // Verify that this is a simple plain object.
var 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."
);
}
{
if (objectName(value) !== "Object") {
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)) {
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) {
var symbols = Object.getOwnPropertySymbols(value);
if (symbols.length > 0) {
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)
);
}
}
} // $FlowFixMe[incompatible-return]
return value;
}
if (typeof value === "string") {
if (value[value.length - 1] === "Z") {
// Possibly a Date, whose toJSON automatically calls toISOString
// $FlowFixMe[incompatible-use]
var originalValue = parent[parentPropertyName];
if (originalValue instanceof Date) {
return serializeDateFromDateJSON(value);
}
}
if (value.length >= 1024) {
// For large strings, we encode them outside the JSON payload so that we
// don't have to double encode and double parse the strings. This can also
// be more compact in case the string has a lot of escaped characters.
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
);
}
if (isServerReference()) {
return serializeServerReference(request, value);
}
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 {
throw new Error(
"Functions cannot be passed directly to Client Components " +
'unless you explicitly expose it by marking it with "use server".' +
describeObjectForErrorMessage(parent, parentPropertyName)
);
}
}
if (typeof value === "symbol") {
var writtenSymbols = request.writtenSymbols;
var _existingId2 = writtenSymbols.get(value);
if (_existingId2 !== undefined) {
return serializeByValueID(_existingId2);
} // $FlowFixMe[incompatible-type] `description` might be undefined
var name = 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++;
var symbolId = request.nextChunkId++;
emitSymbolChunk(request, symbolId, name);
writtenSymbols.set(value, symbolId);
return serializeByValueID(symbolId);
}
if (typeof value === "bigint") {
return serializeBigInt(value);
}
throw new Error(
"Type " +
typeof value +
" is not supported in Client Component props." +
describeObjectForErrorMessage(parent, parentPropertyName)
);
}
function logRecoverableError(request, error) {
var onError = request.onError;
var errorDigest = onError(error);
if (errorDigest != null && typeof errorDigest !== "string") {
// eslint-disable-next-line react-internal/prod-error-codes
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, error) {
if (request.destination !== null) {
request.status = CLOSED;
closeWithError(request.destination, error);
} else {
request.status = CLOSING;
request.fatalError = error;
}
}
function emitErrorChunk(request, id, digest, error) {
var errorInfo;
{
var message;
var stack = "";
try {
if (error instanceof Error) {
// eslint-disable-next-line react-internal/safe-string-coercion
message = String(error.message); // eslint-disable-next-line react-internal/safe-string-coercion
stack = String(error.stack);
} else {
message = "Error: " + error;
}
} catch (x) {
message =
"An error occurred but serializing the error message failed.";
}
errorInfo = {
digest: digest,
message: message,
stack: stack
};
}
var row = serializeRowHeader("E", id) + stringify(errorInfo) + "\n";
var processedChunk = stringToChunk(row);
request.completedErrorChunks.push(processedChunk);
}
function emitImportChunk(request, id, clientReferenceMetadata) {
// $FlowFixMe[incompatible-type] stringify can return null
var json = stringify(clientReferenceMetadata);
var row = serializeRowHeader("I", id) + json + "\n";
var processedChunk = stringToChunk(row);
request.completedImportChunks.push(processedChunk);
}
function emitHintChunk(request, code, model) {
var json = stringify(model);
var id = request.nextChunkId++;
var row = serializeRowHeader("H" + code, id) + json + "\n";
var processedChunk = stringToChunk(row);
request.completedHintChunks.push(processedChunk);
}
function emitSymbolChunk(request, id, name) {
var symbolReference = serializeSymbolReference(name);
var processedChunk = encodeReferenceChunk(request, id, symbolReference);
request.completedImportChunks.push(processedChunk);
}
function emitModelChunk(request, id, json) {
var row = id.toString(16) + ":" + json + "\n";
var processedChunk = stringToChunk(row);
request.completedRegularChunks.push(processedChunk);
}
function emitDebugChunk(request, id, debugInfo) {
var json = stringify(debugInfo);
var row = serializeRowHeader("D", id) + json + "\n";
var processedChunk = stringToChunk(row);
request.completedRegularChunks.push(processedChunk);
}
var emptyRoot = {};
function retryTask(request, task) {
if (task.status !== PENDING) {
// We completed this by other means before we had a chance to retry it.
return;
}
var prevDebugID = debugID;
try {
// Track the root so we know that we have to emit this object even though it
// already has an ID. This is needed because we might see this object twice
// in the same toJSON if it is cyclic.
modelRoot = task.model;
if (true) {
// Track the ID of the current task so we can assign debug info to this id.
debugID = task.id;
} // We call the destructive form that mutates this task. That way if something
// suspends again, we can reuse the same task instead of spawning a new one.
var resolvedModel = renderModelDestructive(
request,
task,
emptyRoot,
"",
task.model
);
if (true) {
// We're now past rendering this task and future renders will spawn new tasks for their
// debug info.
debugID = null;
} // Track the root again for the resolved object.
modelRoot = resolvedModel; // The keyPath resets at any terminal child node.
task.keyPath = null;
task.implicitSlot = false;
var json;
if (typeof resolvedModel === "object" && resolvedModel !== null) {
// Object might contain unresolved values like additional elements.
// This is simulating what the JSON loop would do if this was part of it.
// $FlowFixMe[incompatible-type] stringify can return null for undefined but we never do
json = stringify(resolvedModel, task.toJSON);
} else {
// If the value is a string, it means it's a terminal value and we already escaped it
// We don't need to escape it again so it's not passed the toJSON replacer.
// $FlowFixMe[incompatible-type] stringify can return null for undefined but we never do
json = stringify(resolvedModel);
}
emitModelChunk(request, task.id, json);
request.abortableTasks.delete(task);
task.status = COMPLETED;
} catch (thrownValue) {
var x =
thrownValue === SuspenseException // This is a special type of exception used for Suspense. For historical
? // reasons, the rest of the Suspense implementation expects the thrown
// value to be a thenable, because before `use` existed that was the
// (unstable) API for suspending. This implementation detail can change
// later, once we deprecate the old API in favor of `use`.
getSuspendedThenable()
: thrownValue;
if (typeof x === "object" && x !== null) {
// $FlowFixMe[method-unbinding]
if (typeof x.then === "function") {
// Something suspended again, let's pick it back up later.
var ping = task.ping;
x.then(ping, ping);
task.thenableState = getThenableStateAfterSuspending();
return;
}
}
request.abortableTasks.delete(task);
task.status = ERRORED;
var digest = logRecoverableError(request, x);
emitErrorChunk(request, task.id, digest, x);
} finally {
{
debugID = prevDebugID;
}
}
}
function performWork(request) {
var prevDispatcher = ReactCurrentDispatcher.current;
ReactCurrentDispatcher.current = HooksDispatcher;
var prevRequest = currentRequest;
currentRequest = request;
prepareToUseHooksForRequest(request);
try {
var pingedTasks = request.pingedTasks;
request.pingedTasks = [];
for (var i = 0; i < pingedTasks.length; i++) {
var task = pingedTasks[i];
retryTask(request, task);
}
if (request.destination !== null) {
flushCompletedChunks(request, request.destination);
}
} catch (error) {
logRecoverableError(request, error);
fatalError(request, error);
} finally {
ReactCurrentDispatcher.current = prevDispatcher;
resetHooksForRequest();
currentRequest = prevRequest;
}
}
function flushCompletedChunks(request, destination) {
beginWriting(destination);
try {
// We emit module chunks first in the stream so that
// they can be preloaded as early as possible.
var importsChunks = request.completedImportChunks;
var i = 0;
for (; i < importsChunks.length; i++) {
request.pendingChunks--;
var chunk = importsChunks[i];
var keepWriting = writeChunkAndReturn(destination, chunk);
if (!keepWriting) {
request.destination = null;
i++;
break;
}
}
importsChunks.splice(0, i); // Next comes hints.
var hintChunks = request.completedHintChunks;
i = 0;
for (; i < hintChunks.length; i++) {
var _chunk = hintChunks[i];
var _keepWriting = writeChunkAndReturn(destination, _chunk);
if (!_keepWriting) {
request.destination = null;
i++;
break;
}
}
hintChunks.splice(0, i); // Next comes model data.
var regularChunks = request.completedRegularChunks;
i = 0;
for (; i < regularChunks.length; i++) {
request.pendingChunks--;
var _chunk2 = regularChunks[i];
var _keepWriting2 = writeChunkAndReturn(destination, _chunk2);
if (!_keepWriting2) {
request.destination = null;
i++;
break;
}
}
regularChunks.splice(0, i); // Finally, errors are sent. The idea is that it's ok to delay
// any error messages and prioritize display of other parts of
// the page.
var errorChunks = request.completedErrorChunks;
i = 0;
for (; i < errorChunks.length; i++) {
request.pendingChunks--;
var _chunk3 = errorChunks[i];
var _keepWriting3 = writeChunkAndReturn(destination, _chunk3);
if (!_keepWriting3) {
request.destination = null;
i++;
break;
}
}
errorChunks.splice(0, i);
} finally {
request.flushScheduled = false;
completeWriting(destination);
}
flushBuffered(destination);
if (request.pendingChunks === 0) {
close(destination);
}
}
function startWork(request) {
request.flushScheduled = request.destination !== null;
{
scheduleWork(function () {
return performWork(request);
});
}
}
function enqueueFlush(request) {
if (
request.flushScheduled === false && // If there are pinged tasks we are going to flush anyway after work completes
request.pingedTasks.length === 0 && // If there is no destination there is nothing we can flush to. A flush will
// happen when we start flowing again
request.destination !== null
) {
var destination = request.destination;
request.flushScheduled = true;
scheduleWork(function () {
return flushCompletedChunks(request, destination);
});
}
}
function startFlowing(request, destination) {
if (request.status === CLOSING) {
request.status = CLOSED;
closeWithError(destination, request.fatalError);
return;
}
if (request.status === CLOSED) {
return;
}
if (request.destination !== null) {
// We're already flowing.
return;
}
request.destination = destination;
try {
flushCompletedChunks(request, destination);
} catch (error) {
logRecoverableError(request, error);
fatalError(request, error);
}
}
function renderToDestination(destination, model, options) {
if (!configured) {
throw new Error(
"Please make sure to call `setConfig(...)` before calling `renderToDestination`."
);
}
var request = createRequest(
model,
null,
options ? options.onError : undefined
);
startWork(request);
startFlowing(request, destination);
}
var configured = false;
function setConfig(config) {
setByteLengthOfChunkImplementation(config.byteLength);
setCheckIsClientReference(config.isClientReference);
configured = true;
}
exports.clearRequestedClientReferencesKeysSet =
clearRequestedClientReferencesKeysSet;
exports.getRequestedClientReferencesKeys = getRequestedClientReferencesKeys;
exports.registerClientReference = registerClientReference;
exports.registerServerReference = registerServerReference;
exports.renderToDestination = renderToDestination;
exports.setCheckIsClientReference = setCheckIsClientReference;
exports.setConfig = setConfig;
})();
}