react-server-dom-webpack
Version:
React Server Components bindings for DOM using Webpack. This is intended to be integrated into meta-frameworks. It is not intended to be imported directly.
1,671 lines (1,390 loc) • 95.4 kB
JavaScript
/**
* @license React
* react-server-dom-webpack-server.browser.production.min.js
*
* 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.
*/
'use strict';
var ReactDOM = require('react-dom');
var React = require('react');
// -----------------------------------------------------------------------------
const enablePostpone = false;
function scheduleWork(callback) {
callback();
}
const VIEW_SIZE = 512;
let currentView = null;
let writtenBytes = 0;
function beginWriting(destination) {
currentView = new Uint8Array(VIEW_SIZE);
writtenBytes = 0;
}
function writeChunk(destination, chunk) {
if (chunk.byteLength === 0) {
return;
}
if (chunk.byteLength > VIEW_SIZE) {
// one that is cached by the streaming renderer. We will enqueu
// it directly and expect it is not re-used
if (writtenBytes > 0) {
destination.enqueue(new Uint8Array(currentView.buffer, 0, writtenBytes));
currentView = new Uint8Array(VIEW_SIZE);
writtenBytes = 0;
}
destination.enqueue(chunk);
return;
}
let bytesToWrite = chunk;
const allowableBytes = currentView.length - writtenBytes;
if (allowableBytes < bytesToWrite.byteLength) {
// this chunk would overflow the current view. We enqueue a full view
// and start a new view with the remaining chunk
if (allowableBytes === 0) {
// the current view is already full, send it
destination.enqueue(currentView);
} else {
// fill up the current view and apply the remaining chunk bytes
// to a new view.
currentView.set(bytesToWrite.subarray(0, allowableBytes), writtenBytes); // writtenBytes += allowableBytes; // this can be skipped because we are going to immediately reset the view
destination.enqueue(currentView);
bytesToWrite = bytesToWrite.subarray(allowableBytes);
}
currentView = new Uint8Array(VIEW_SIZE);
writtenBytes = 0;
}
currentView.set(bytesToWrite, writtenBytes);
writtenBytes += bytesToWrite.byteLength;
}
function writeChunkAndReturn(destination, chunk) {
writeChunk(destination, chunk); // in web streams there is no backpressure so we can alwas write more
return true;
}
function completeWriting(destination) {
if (currentView && writtenBytes > 0) {
destination.enqueue(new Uint8Array(currentView.buffer, 0, writtenBytes));
currentView = null;
writtenBytes = 0;
}
}
function close$1(destination) {
destination.close();
}
const textEncoder = new TextEncoder();
function stringToChunk(content) {
return textEncoder.encode(content);
}
function byteLengthOfChunk(chunk) {
return chunk.byteLength;
}
function closeWithError(destination, error) {
// $FlowFixMe[method-unbinding]
if (typeof destination.error === 'function') {
// $FlowFixMe[incompatible-call]: This is an Error object or the destination accepts other types.
destination.error(error);
} else {
// Earlier implementations doesn't support this method. In that environment you're
// supposed to throw from a promise returned but we don't return a promise in our
// approach. We could fork this implementation but this is environment is an edge
// case to begin with. It's even less common to run this in an older environment.
// Even then, this is not where errors are supposed to happen and they get reported
// to a global callback in addition to this anyway. So it's fine just to close this.
destination.close();
}
}
// eslint-disable-next-line no-unused-vars
const CLIENT_REFERENCE_TAG = Symbol.for('react.client.reference');
const SERVER_REFERENCE_TAG = Symbol.for('react.server.reference');
function isClientReference(reference) {
return reference.$$typeof === CLIENT_REFERENCE_TAG;
}
function isServerReference(reference) {
return reference.$$typeof === SERVER_REFERENCE_TAG;
}
function registerClientReference(proxyImplementation, id, exportName) {
return registerClientReferenceImpl(proxyImplementation, id + '#' + exportName, false);
}
function registerClientReferenceImpl(proxyImplementation, id, async) {
return Object.defineProperties(proxyImplementation, {
$$typeof: {
value: CLIENT_REFERENCE_TAG
},
$$id: {
value: id
},
$$async: {
value: async
}
});
} // $FlowFixMe[method-unbinding]
const FunctionBind = Function.prototype.bind; // $FlowFixMe[method-unbinding]
const ArraySlice = Array.prototype.slice;
function bind() {
// $FlowFixMe[unsupported-syntax]
const newFn = FunctionBind.apply(this, arguments);
if (this.$$typeof === SERVER_REFERENCE_TAG) {
const args = ArraySlice.call(arguments, 1);
return Object.defineProperties(newFn, {
$$typeof: {
value: SERVER_REFERENCE_TAG
},
$$id: {
value: this.$$id
},
$$bound: {
value: this.$$bound ? this.$$bound.concat(args) : args
},
bind: {
value: bind
}
});
}
return newFn;
}
function registerServerReference(reference, id, exportName) {
return Object.defineProperties(reference, {
$$typeof: {
value: SERVER_REFERENCE_TAG
},
$$id: {
value: exportName === null ? id : id + '#' + exportName
},
$$bound: {
value: null
},
bind: {
value: bind
}
});
}
const PROMISE_PROTOTYPE = Promise.prototype;
const deepProxyHandlers = {
get: function (target, name, receiver) {
switch (name) {
// These names are read by the Flight runtime if you end up using the exports object.
case '$$typeof':
// These names are a little too common. We should probably have a way to
// have the Flight runtime extract the inner target instead.
return target.$$typeof;
case '$$id':
return target.$$id;
case '$$async':
return target.$$async;
case 'name':
return target.name;
case 'displayName':
return undefined;
// We need to special case this because createElement reads it if we pass this
// reference.
case 'defaultProps':
return undefined;
// Avoid this attempting to be serialized.
case 'toJSON':
return undefined;
case Symbol.toPrimitive:
// $FlowFixMe[prop-missing]
return Object.prototype[Symbol.toPrimitive];
case 'Provider':
throw new Error("Cannot render a Client Context Provider on the Server. " + "Instead, you can export a Client Component wrapper " + "that itself renders a Client Context Provider.");
} // eslint-disable-next-line react-internal/safe-string-coercion
const expression = String(target.name) + '.' + String(name);
throw new Error("Cannot access " + expression + " on the server. " + 'You cannot dot into a client module from a server component. ' + 'You can only pass the imported name through.');
},
set: function () {
throw new Error('Cannot assign to a client module from a server module.');
}
};
function getReference(target, name) {
switch (name) {
// These names are read by the Flight runtime if you end up using the exports object.
case '$$typeof':
return target.$$typeof;
case '$$id':
return target.$$id;
case '$$async':
return target.$$async;
case 'name':
return target.name;
// We need to special case this because createElement reads it if we pass this
// reference.
case 'defaultProps':
return undefined;
// Avoid this attempting to be serialized.
case 'toJSON':
return undefined;
case Symbol.toPrimitive:
// $FlowFixMe[prop-missing]
return Object.prototype[Symbol.toPrimitive];
case '__esModule':
// Something is conditionally checking which export to use. We'll pretend to be
// an ESM compat module but then we'll check again on the client.
const moduleId = target.$$id;
target.default = registerClientReferenceImpl(function () {
throw new Error("Attempted to call the default export of " + moduleId + " from the server " + "but it's on the client. It's not possible to invoke a client function from " + "the server, it can only be rendered as a Component or passed to props of a " + "Client Component.");
}, target.$$id + '#', target.$$async);
return true;
case 'then':
if (target.then) {
// Use a cached value
return target.then;
}
if (!target.$$async) {
// If this module is expected to return a Promise (such as an AsyncModule) then
// we should resolve that with a client reference that unwraps the Promise on
// the client.
const clientReference = registerClientReferenceImpl({}, target.$$id, true);
const proxy = new Proxy(clientReference, proxyHandlers); // Treat this as a resolved Promise for React's use()
target.status = 'fulfilled';
target.value = proxy;
const then = target.then = registerClientReferenceImpl(function then(resolve, reject) {
// Expose to React.
return Promise.resolve(resolve(proxy));
}, // If this is not used as a Promise but is treated as a reference to a `.then`
// export then we should treat it as a reference to that name.
target.$$id + '#then', false);
return then;
} else {
// Since typeof .then === 'function' is a feature test we'd continue recursing
// indefinitely if we return a function. Instead, we return an object reference
// if we check further.
return undefined;
}
}
let cachedReference = target[name];
if (!cachedReference) {
const reference = registerClientReferenceImpl(function () {
throw new Error( // eslint-disable-next-line react-internal/safe-string-coercion
"Attempted to call " + String(name) + "() from the server but " + String(name) + " is on the client. " + "It's not possible to invoke a client function from the server, it can " + "only be rendered as a Component or passed to props of a Client Component.");
}, target.$$id + '#' + name, target.$$async);
Object.defineProperty(reference, 'name', {
value: name
});
cachedReference = target[name] = new Proxy(reference, deepProxyHandlers);
}
return cachedReference;
}
const proxyHandlers = {
get: function (target, name, receiver) {
return getReference(target, name);
},
getOwnPropertyDescriptor: function (target, name) {
let descriptor = Object.getOwnPropertyDescriptor(target, name);
if (!descriptor) {
descriptor = {
value: getReference(target, name),
writable: false,
configurable: false,
enumerable: false
};
Object.defineProperty(target, name, descriptor);
}
return descriptor;
},
getPrototypeOf(target) {
// Pretend to be a Promise in case anyone asks.
return PROMISE_PROTOTYPE;
},
set: function () {
throw new Error('Cannot assign to a client module from a server module.');
}
};
function createClientModuleProxy(moduleId) {
const clientReference = registerClientReferenceImpl({}, // Represents the whole Module object instead of a particular import.
moduleId, false);
return new Proxy(clientReference, proxyHandlers);
}
function getClientReferenceKey(reference) {
return reference.$$async ? reference.$$id + '#async' : reference.$$id;
}
function resolveClientReferenceMetadata(config, clientReference) {
const modulePath = clientReference.$$id;
let name = '';
let resolvedModuleData = config[modulePath];
if (resolvedModuleData) {
// The potentially aliased name.
name = resolvedModuleData.name;
} else {
// We didn't find this specific export name but we might have the * export
// which contains this name as well.
// TODO: It's unfortunate that we now have to parse this string. We should
// probably go back to encoding path and name separately on the client reference.
const idx = modulePath.lastIndexOf('#');
if (idx !== -1) {
name = modulePath.slice(idx + 1);
resolvedModuleData = config[modulePath.slice(0, idx)];
}
if (!resolvedModuleData) {
throw new Error('Could not find the module "' + modulePath + '" in the React Client Manifest. ' + 'This is probably a bug in the React Server Components bundler.');
}
}
if (clientReference.$$async === true) {
return [resolvedModuleData.id, resolvedModuleData.chunks, name, 1];
} else {
return [resolvedModuleData.id, resolvedModuleData.chunks, name];
}
}
function getServerReferenceId(config, serverReference) {
return serverReference.$$id;
}
function getServerReferenceBoundArguments(config, serverReference) {
return serverReference.$$bound;
}
const ReactDOMSharedInternals = ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
const ReactDOMFlightServerDispatcher = {
prefetchDNS,
preconnect,
preload,
preloadModule: preloadModule$1,
preinitStyle,
preinitScript,
preinitModuleScript
};
function prefetchDNS(href) {
{
if (typeof href === 'string' && href) {
const request = resolveRequest();
if (request) {
const hints = getHints(request);
const 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') {
const request = resolveRequest();
if (request) {
const hints = getHints(request);
const 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') {
const request = resolveRequest();
if (request) {
const hints = getHints(request);
let 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);
const trimmed = trimOptions(options);
if (trimmed) {
emitHint(request, 'L', [href, as, trimmed]);
} else {
emitHint(request, 'L', [href, as]);
}
}
}
}
}
function preloadModule$1(href, options) {
{
if (typeof href === 'string') {
const request = resolveRequest();
if (request) {
const hints = getHints(request);
const key = 'm|' + href;
if (hints.has(key)) {
// duplicate hint
return;
}
hints.add(key);
const 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') {
const request = resolveRequest();
if (request) {
const hints = getHints(request);
const key = 'S|' + href;
if (hints.has(key)) {
// duplicate hint
return;
}
hints.add(key);
const 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') {
const request = resolveRequest();
if (request) {
const hints = getHints(request);
const key = 'X|' + href;
if (hints.has(key)) {
// duplicate hint
return;
}
hints.add(key);
const 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') {
const request = resolveRequest();
if (request) {
const hints = getHints(request);
const key = 'M|' + href;
if (hints.has(key)) {
// duplicate hint
return;
}
hints.add(key);
const 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;
let hasProperties = false;
const trimmed = {};
for (const key in options) {
if (options[key] != null) {
hasProperties = true;
trimmed[key] = options[key];
}
}
return hasProperties ? trimmed : null;
}
function getImagePreloadKey(href, imageSrcSet, imageSizes) {
let uniquePart = '';
if (typeof imageSrcSet === 'string' && imageSrcSet !== '') {
uniquePart += '[' + imageSrcSet + ']';
if (typeof imageSizes === 'string') {
uniquePart += '[' + imageSizes + ']';
}
} else {
uniquePart += '[][]' + href;
}
return "[image]" + uniquePart;
}
const 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.
const REACT_ELEMENT_TYPE = Symbol.for('react.element');
const REACT_FRAGMENT_TYPE = Symbol.for('react.fragment');
const REACT_CONTEXT_TYPE = Symbol.for('react.context');
const REACT_FORWARD_REF_TYPE = Symbol.for('react.forward_ref');
const REACT_SUSPENSE_TYPE = Symbol.for('react.suspense');
const REACT_SUSPENSE_LIST_TYPE = Symbol.for('react.suspense_list');
const REACT_MEMO_TYPE = Symbol.for('react.memo');
const REACT_LAZY_TYPE = Symbol.for('react.lazy');
const REACT_MEMO_CACHE_SENTINEL = Symbol.for('react.memo_cache_sentinel');
const REACT_POSTPONE_TYPE = Symbol.for('react.postpone');
const MAYBE_ITERATOR_SYMBOL = Symbol.iterator;
const FAUX_ITERATOR_SYMBOL = '@@iterator';
function getIteratorFn(maybeIterable) {
if (maybeIterable === null || typeof maybeIterable !== 'object') {
return null;
}
const 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.
const 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) {
const 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':
{
const fulfilledValue = thenable.value;
return fulfilledValue;
}
case 'rejected':
{
const rejectedError = thenable.reason;
throw rejectedError;
}
default:
{
if (typeof thenable.status === 'string') ; else {
const pendingThenable = thenable;
pendingThenable.status = 'pending';
pendingThenable.then(fulfilledValue => {
if (thenable.status === 'pending') {
const fulfilledThenable = thenable;
fulfilledThenable.status = 'fulfilled';
fulfilledThenable.value = fulfilledValue;
}
}, error => {
if (thenable.status === 'pending') {
const rejectedThenable = thenable;
rejectedThenable.status = 'rejected';
rejectedThenable.reason = error;
}
}); // Check one more time in case the thenable resolved synchronously
switch (thenable.status) {
case 'fulfilled':
{
const fulfilledThenable = thenable;
return fulfilledThenable.value;
}
case 'rejected':
{
const 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.
let 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.');
}
const thenable = suspendedThenable;
suspendedThenable = null;
return thenable;
}
let currentRequest$1 = null;
let thenableIndexCounter = 0;
let 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.
const state = thenableState || createThenableState();
thenableState = null;
return state;
}
const HooksDispatcher = {
useMemo(nextCreate) {
return nextCreate();
},
useCallback(callback) {
return callback;
},
useDebugValue() {},
useDeferredValue: unsupportedHook,
useTransition: unsupportedHook,
readContext: unsupportedContext,
useContext: unsupportedContext,
useReducer: unsupportedHook,
useRef: unsupportedHook,
useState: unsupportedHook,
useInsertionEffect: unsupportedHook,
useLayoutEffect: unsupportedHook,
useImperativeHandle: unsupportedHook,
useEffect: unsupportedHook,
useId,
useSyncExternalStore: unsupportedHook,
useCacheRefresh() {
return unsupportedRefresh;
},
useMemoCache(size) {
const data = new Array(size);
for (let i = 0; i < size; i++) {
data[i] = REACT_MEMO_CACHE_SENTINEL;
}
return data;
},
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');
}
const 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.
const thenable = usable; // Track the position of the thenable within this fiber.
const 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() {
const request = resolveRequest();
if (request) {
return getCache(request);
}
return new Map();
}
const DefaultCacheDispatcher = {
getCacheSignal() {
const cache = resolveCache();
let entry = cache.get(createSignal);
if (entry === undefined) {
entry = createSignal();
cache.set(createSignal, entry);
}
return entry;
},
getCacheForType(resourceType) {
const cache = resolveCache();
let entry = cache.get(resourceType);
if (entry === undefined) {
entry = resourceType(); // TODO: Warn if undefined?
cache.set(resourceType, entry);
}
return entry;
}
};
const isArrayImpl = Array.isArray; // eslint-disable-next-line no-redeclare
function isArray(a) {
return isArrayImpl(a);
}
const getPrototypeOf = Object.getPrototypeOf;
function objectName(object) {
// $FlowFixMe[method-unbinding]
const name = Object.prototype.toString.call(object);
return name.replace(/^\[object (.*)\]$/, function (m, p0) {
return p0;
});
}
function describeKeyForErrorMessage(key) {
const 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 '[...]';
}
const 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:
{
const lazyComponent = type;
const payload = lazyComponent._payload;
const 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) {
const objKind = objectName(objectOrArray);
if (objKind !== 'Object' && objKind !== 'Array') {
return objKind;
}
let str = '';
let start = -1;
let length = 0;
if (isArray(objectOrArray)) {
{
// Print Array
str = '[';
const array = objectOrArray;
for (let i = 0; i < array.length; i++) {
if (i > 0) {
str += ', ';
}
const value = array[i];
let substr;
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 {
// Print Object
str = '{';
const object = objectOrArray;
const names = Object.keys(object);
for (let i = 0; i < names.length; i++) {
if (i > 0) {
str += ', ';
}
const name = names[i];
str += describeKeyForErrorMessage(name) + ': ';
const value = object[name];
let substr;
if (typeof value === 'object' && value !== null) {
substr = describeObjectForErrorMessage(value);
} else {
substr = describeValueForErrorMessage(value);
}
if (name === expandedName) {
start = str.length;
length = substr.length;
str += substr;
} else if (substr.length < 10 && str.length + substr.length < 40) {
str += substr;
} else {
str += '...';
}
}
str += '}';
}
}
if (expandedName === undefined) {
return str;
}
if (start > -1 && length > 0) {
const highlight = ' '.repeat(start) + '^'.repeat(length);
return '\n ' + str + '\n ' + highlight;
}
return '\n ' + str;
}
const ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
const 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.');
}
const ObjectPrototype = Object.prototype;
const stringify = JSON.stringify; // Serializable values
// Thenable<ReactClientValue>
const PENDING$1 = 0;
const COMPLETED = 1;
const ABORTED = 3;
const ERRORED$1 = 4;
const ReactCurrentCache = ReactSharedServerInternals.ReactCurrentCache;
const ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher;
function defaultErrorHandler(error) {
console['error'](error); // Don't transform to our wrapper
}
function defaultPostponeHandler(reason) {// Noop
}
const OPEN = 0;
const CLOSING = 1;
const CLOSED = 2;
function createRequest(model, bundlerConfig, onError, identifierPrefix, onPostpone, environmentName) {
if (ReactCurrentCache.current !== null && ReactCurrentCache.current !== DefaultCacheDispatcher) {
throw new Error('Currently React only supports one RSC renderer at a time.');
}
prepareHostDispatcher();
ReactCurrentCache.current = DefaultCacheDispatcher;
const abortSet = new Set();
const pingedTasks = [];
const cleanupQueue = [];
const hints = createHints();
const request = {
status: OPEN,
flushScheduled: false,
fatalError: null,
destination: null,
bundlerConfig,
cache: new Map(),
nextChunkId: 0,
pendingChunks: 0,
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
};
const rootTask = createTask(request, model, null, false, abortSet);
pingedTasks.push(rootTask);
return request;
}
let currentRequest = null;
function resolveRequest() {
if (currentRequest) return currentRequest;
return null;
}
function serializeThenable(request, task, thenable) {
const 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':
{
const x = thenable.reason;
{
const digest = logRecoverableError(request, x);
emitErrorChunk(request, newTask.id, digest);
}
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;
}
const pendingThenable = thenable;
pendingThenable.status = 'pending';
pendingThenable.then(fulfilledValue => {
if (thenable.status === 'pending') {
const fulfilledThenable = thenable;
fulfilledThenable.status = 'fulfilled';
fulfilledThenable.value = fulfilledValue;
}
}, error => {
if (thenable.status === 'pending') {
const rejectedThenable = thenable;
rejectedThenable.status = 'rejected';
rejectedThenable.reason = error;
}
});
break;
}
}
thenable.then(value => {
newTask.model = value;
pingTask(request, newTask);
}, reason => {
{
newTask.status = ERRORED$1;
const digest = logRecoverableError(request, reason);
emitErrorChunk(request, newTask.id, digest);
}
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.
const 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;
}
const pendingThenable = thenable;
pendingThenable.status = 'pending';
pendingThenable.then(fulfilledValue => {
if (thenable.status === 'pending') {
const fulfilledThenable = thenable;
fulfilledThenable.status = 'fulfilled';
fulfilledThenable.value = fulfilledValue;
}
}, error => {
if (thenable.status === 'pending') {
const rejectedThenable = thenable;
rejectedThenable.status = 'rejected';
rejectedThenable.reason = error;
}
});
break;
}
}
const 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.
const prevThenableState = task.thenableState;
task.thenableState = null;
prepareToUseHooksForComponent(prevThenableState); // The secondArg is always undefined in Server Components since refs error early.
const secondArg = undefined;
let 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.
const 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..
const prevKeyPath = task.keyPath;
const 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;
}
const json = renderModelDestructive(request, task, emptyRoot, '', result);
task.keyPath = prevKeyPath;
task.implicitSlot = prevImplicitSlot;
return json;
}
function renderFragment(request, task, children) {
{
return children;
}
}
function renderClientElement(task, type, key, props) {
{
return [REACT_ELEMENT_TYPE, type, key, props];
} // We prepend the terminal client element that actually gets serialized with
} // The chunk ID we're currently rendering that we can assign debug data to.
let debugID = null;
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.');
}
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.
const prevImplicitSlot = task.implicitSlot;
if (task.keyPath === null) {
task.implicitSlot = true;
}
const 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:
{
const payload = type._payload;
const init = type._init;
const 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) {
const pingedTasks = request.pingedTasks;
pingedTasks.push(task);
if (pingedTasks.length === 1) {
request.flushScheduled = request.destination !== null;
scheduleWork(() => performWork(request));
}
}
function createTask(request, model, keyPath, implicitSlot, abortSet) {
request.pendingChunks++;
const 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.
{
request.writtenObjects.set(model, id);
}
}
const task = {
id,
status: PENDING$1,
model,
keyPath,
implicitSlot,
ping: () => pingTask(request, task),
toJSON: function (parentPropertyName, value) {
const parent = this; // Make sure that `parent[parentPropertyName]` wasn't JSONified before `value` was passed to us
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) {
const json = stringify(reference);
const row = id.toString(16) + ':' + json + '\n';
return stringToChunk(row);
}
function serializeClientReference(request, parent, parentPropertyName, clientReference) {
const clientReferenceKey = getClientReferenceKey(clientReference);
const writtenClientReferences = request.writtenClientReferences;
const 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 {
const 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') {
// 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++;
const errorId = request.nextChunkId++;
const digest = logRecoverableError(request, x);
emitErrorChunk(request, errorId, digest);
return serializeByValueID(errorId);
}
}
function outlineModel(request, value) {
const 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) {
const writtenServerReferences = request.writtenServerReferences;
const existingId = writtenServerReferences.get(serverReference);
if (existingId !== undefined) {
return serializeServerReferenceID(existingId);
}
const bound = getServerReferenceBoundArguments(request.bundlerConfig, serverReference);
const serverReferenceMetadata = {
id: getServerReferenceId(request.bundlerConfig, serverReference),
bound: bound ? Promise.resolve(bound) : null
};
const metadataId = outlineModel(request, serverReferenceMetadata);
writtenServerReferences.set(serverReference, metadataId);
return serializeServerReferenceID(metadataId);
}
function serializeLargeTextString(request, text) {
request.pendingChunks += 2;
const textId = request.nextChunkId++;
const textChunk = stringToChunk(text);
const binaryLength = byteLengthOfChunk(textChunk);
const row = textId.toString(16) + ':T' + binaryLength.toString(16) + ',';
const headerChunk = stringToChunk(row);
request.completedRegularChunks.push(headerChunk, textChunk);
return serializeByValueID(textId);
}
function serializeMap(request, map) {
const entries = Array.from(map);
for (l