import getComponentNameFromType from 'shared/getComponentNameFromType';
import ReactSharedInternals from 'shared/ReactSharedInternals';
import hasOwnProperty from 'shared/hasOwnProperty';
import assign from 'shared/assign';
import {
getIteratorFn,
REACT_ELEMENT_TYPE,
REACT_FRAGMENT_TYPE,
} from 'shared/ReactSymbols';
import {checkKeyStringCoercion} from 'shared/CheckStringCoercion';
import isValidElementType from 'shared/isValidElementType';
import isArray from 'shared/isArray';
import {describeUnknownElementTypeFrameInDEV} from 'shared/ReactComponentStackFrame';
import {enableRefAsProp, disableStringRefs} from 'shared/ReactFeatureFlags';
const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;
const ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;
const REACT_CLIENT_REFERENCE = Symbol.for('react.client.reference');
let specialPropKeyWarningShown;
let specialPropRefWarningShown;
let didWarnAboutStringRefs;
let didWarnAboutElementRef;
if (__DEV__) {
didWarnAboutStringRefs = {};
didWarnAboutElementRef = {};
}
function hasValidRef(config) {
if (__DEV__) {
if (hasOwnProperty.call(config, 'ref')) {
const getter = Object.getOwnPropertyDescriptor(config, 'ref').get;
if (getter && getter.isReactWarning) {
return false;
}
}
}
return config.ref !== undefined;
}
function hasValidKey(config) {
if (__DEV__) {
if (hasOwnProperty.call(config, 'key')) {
const getter = Object.getOwnPropertyDescriptor(config, 'key').get;
if (getter && getter.isReactWarning) {
return false;
}
}
}
return config.key !== undefined;
}
function warnIfStringRefCannotBeAutoConverted(config, self) {
if (__DEV__) {
if (
!disableStringRefs &&
typeof config.ref === 'string' &&
ReactCurrentOwner.current &&
self &&
ReactCurrentOwner.current.stateNode !== self
) {
const componentName = getComponentNameFromType(
ReactCurrentOwner.current.type,
);
if (!didWarnAboutStringRefs[componentName]) {
console.error(
'Component "%s" contains the string ref "%s". ' +
'Support for string refs will be removed in a future major release. ' +
'This case cannot be automatically converted to an arrow function. ' +
'We ask you to manually fix this case by using useRef() or createRef() instead. ' +
'Learn more about using refs safely here: ' +
'https://react.dev/link/strict-mode-string-ref',
getComponentNameFromType(ReactCurrentOwner.current.type),
config.ref,
);
didWarnAboutStringRefs[componentName] = true;
}
}
}
}
function defineKeyPropWarningGetter(props, displayName) {
if (__DEV__) {
const warnAboutAccessingKey = function () {
if (!specialPropKeyWarningShown) {
specialPropKeyWarningShown = true;
console.error(
'%s: `key` is not a prop. Trying to access it will result ' +
'in `undefined` being returned. If you need to access the same ' +
'value within the child component, you should pass it as a different ' +
'prop. (https://react.dev/link/special-props)',
displayName,
);
}
};
warnAboutAccessingKey.isReactWarning = true;
Object.defineProperty(props, 'key', {
get: warnAboutAccessingKey,
configurable: true,
});
}
}
function defineRefPropWarningGetter(props, displayName) {
if (!enableRefAsProp) {
if (__DEV__) {
const warnAboutAccessingRef = function () {
if (!specialPropRefWarningShown) {
specialPropRefWarningShown = true;
console.error(
'%s: `ref` is not a prop. Trying to access it will result ' +
'in `undefined` being returned. If you need to access the same ' +
'value within the child component, you should pass it as a different ' +
'prop. (https://react.dev/link/special-props)',
displayName,
);
}
};
warnAboutAccessingRef.isReactWarning = true;
Object.defineProperty(props, 'ref', {
get: warnAboutAccessingRef,
configurable: true,
});
}
}
}
function elementRefGetterWithDeprecationWarning() {
if (__DEV__) {
const componentName = getComponentNameFromType(this.type);
if (!didWarnAboutElementRef[componentName]) {
didWarnAboutElementRef[componentName] = true;
console.error(
'Accessing element.ref was removed in React 19. ref is now a ' +
'regular prop. It will be removed from the JSX Element ' +
'type in a future release.',
);
}
const refProp = this.props.ref;
return refProp !== undefined ? refProp : null;
}
}
function ReactElement(type, key, _ref, self, source, owner, props) {
let ref;
if (enableRefAsProp) {
const refProp = props.ref;
ref = refProp !== undefined ? refProp : null;
} else {
ref = _ref;
}
let element;
if (__DEV__ && enableRefAsProp) {
element = {
$$typeof: REACT_ELEMENT_TYPE,
type,
key,
props,
_owner: owner,
};
if (ref !== null) {
Object.defineProperty(element, 'ref', {
enumerable: false,
get: elementRefGetterWithDeprecationWarning,
});
} else {
Object.defineProperty(element, 'ref', {
enumerable: false,
value: null,
});
}
} else {
element = {
$$typeof: REACT_ELEMENT_TYPE,
type,
key,
ref,
props,
_owner: owner,
};
}
if (__DEV__) {
element._store = {};
Object.defineProperty(element._store, 'validated', {
configurable: false,
enumerable: false,
writable: true,
value: false,
});
Object.defineProperty(element, '_debugInfo', {
configurable: false,
enumerable: false,
writable: true,
value: null,
});
if (Object.freeze) {
Object.freeze(element.props);
Object.freeze(element);
}
}
return element;
}
export function jsxProd(type, config, maybeKey) {
let propName;
const props = {};
let key = null;
let ref = null;
if (maybeKey !== undefined) {
if (__DEV__) {
checkKeyStringCoercion(maybeKey);
}
key = '' + maybeKey;
}
if (hasValidKey(config)) {
if (__DEV__) {
checkKeyStringCoercion(config.key);
}
key = '' + config.key;
}
if (hasValidRef(config)) {
if (!enableRefAsProp) {
ref = config.ref;
}
}
for (propName in config) {
if (
hasOwnProperty.call(config, propName) &&
propName !== 'key' &&
(enableRefAsProp || propName !== 'ref')
) {
props[propName] = config[propName];
}
}
if (type && type.defaultProps) {
const defaultProps = type.defaultProps;
for (propName in defaultProps) {
if (props[propName] === undefined) {
props[propName] = defaultProps[propName];
}
}
}
return ReactElement(
type,
key,
ref,
undefined,
undefined,
ReactCurrentOwner.current,
props,
);
}
export function jsxProdSignatureRunningInDevWithDynamicChildren(
type,
config,
maybeKey,
source,
self,
) {
if (__DEV__) {
const isStaticChildren = false;
return jsxDEV(type, config, maybeKey, isStaticChildren, source, self);
}
}
export function jsxProdSignatureRunningInDevWithStaticChildren(
type,
config,
maybeKey,
source,
self,
) {
if (__DEV__) {
const isStaticChildren = true;
return jsxDEV(type, config, maybeKey, isStaticChildren, source, self);
}
}
const didWarnAboutKeySpread = {};
export function jsxDEV(type, config, maybeKey, isStaticChildren, source, self) {
if (__DEV__) {
if (!isValidElementType(type)) {
let info = '';
if (
type === undefined ||
(typeof type === 'object' &&
type !== null &&
Object.keys(type).length === 0)
) {
info +=
' You likely forgot to export your component from the file ' +
"it's defined in, or you might have mixed up default and named imports.";
}
let typeString;
if (type === null) {
typeString = 'null';
} else if (isArray(type)) {
typeString = 'array';
} else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) {
typeString = `<${getComponentNameFromType(type.type) || 'Unknown'} />`;
info =
' Did you accidentally export a JSX literal instead of a component?';
} else {
typeString = typeof type;
}
console.error(
'React.jsx: type is invalid -- expected a string (for ' +
'built-in components) or a class/function (for composite ' +
'components) but got: %s.%s',
typeString,
info,
);
} else {
const children = config.children;
if (children !== undefined) {
if (isStaticChildren) {
if (isArray(children)) {
for (let i = 0; i < children.length; i++) {
validateChildKeys(children[i], type);
}
if (Object.freeze) {
Object.freeze(children);
}
} else {
console.error(
'React.jsx: Static children should always be an array. ' +
'You are likely explicitly calling React.jsxs or React.jsxDEV. ' +
'Use the Babel transform instead.',
);
}
} else {
validateChildKeys(children, type);
}
}
}
if (hasOwnProperty.call(config, 'key')) {
const componentName = getComponentNameFromType(type);
const keys = Object.keys(config).filter(k => k !== 'key');
const beforeExample =
keys.length > 0
? '{key: someKey, ' + keys.join(': ..., ') + ': ...}'
: '{key: someKey}';
if (!didWarnAboutKeySpread[componentName + beforeExample]) {
const afterExample =
keys.length > 0 ? '{' + keys.join(': ..., ') + ': ...}' : '{}';
console.error(
'A props object containing a "key" prop is being spread into JSX:\n' +
' let props = %s;\n' +
' <%s {...props} />\n' +
'React keys must be passed directly to JSX without using spread:\n' +
' let props = %s;\n' +
' <%s key={someKey} {...props} />',
beforeExample,
componentName,
afterExample,
componentName,
);
didWarnAboutKeySpread[componentName + beforeExample] = true;
}
}
let propName;
const props = {};
let key = null;
let ref = null;
if (maybeKey !== undefined) {
if (__DEV__) {
checkKeyStringCoercion(maybeKey);
}
key = '' + maybeKey;
}
if (hasValidKey(config)) {
if (__DEV__) {
checkKeyStringCoercion(config.key);
}
key = '' + config.key;
}
if (hasValidRef(config)) {
if (!enableRefAsProp) {
ref = config.ref;
}
if (!disableStringRefs) {
warnIfStringRefCannotBeAutoConverted(config, self);
}
}
for (propName in config) {
if (
hasOwnProperty.call(config, propName) &&
propName !== 'key' &&
(enableRefAsProp || propName !== 'ref')
) {
props[propName] = config[propName];
}
}
if (type && type.defaultProps) {
const defaultProps = type.defaultProps;
for (propName in defaultProps) {
if (props[propName] === undefined) {
props[propName] = defaultProps[propName];
}
}
}
if (key || (!enableRefAsProp && ref)) {
const displayName =
typeof type === 'function'
? type.displayName || type.name || 'Unknown'
: type;
if (key) {
defineKeyPropWarningGetter(props, displayName);
}
if (!enableRefAsProp && ref) {
defineRefPropWarningGetter(props, displayName);
}
}
const element = ReactElement(
type,
key,
ref,
self,
source,
ReactCurrentOwner.current,
props,
);
if (type === REACT_FRAGMENT_TYPE) {
validateFragmentProps(element);
}
return element;
}
}
export function createElement(type, config, children) {
if (__DEV__) {
if (!isValidElementType(type)) {
let info = '';
if (
type === undefined ||
(typeof type === 'object' &&
type !== null &&
Object.keys(type).length === 0)
) {
info +=
' You likely forgot to export your component from the file ' +
"it's defined in, or you might have mixed up default and named imports.";
}
let typeString;
if (type === null) {
typeString = 'null';
} else if (isArray(type)) {
typeString = 'array';
} else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) {
typeString = `<${getComponentNameFromType(type.type) || 'Unknown'} />`;
info =
' Did you accidentally export a JSX literal instead of a component?';
} else {
typeString = typeof type;
}
console.error(
'React.createElement: type is invalid -- expected a string (for ' +
'built-in components) or a class/function (for composite ' +
'components) but got: %s.%s',
typeString,
info,
);
} else {
for (let i = 2; i < arguments.length; i++) {
validateChildKeys(arguments[i], type);
}
}
}
let propName;
const props = {};
let key = null;
let ref = null;
if (config != null) {
if (hasValidRef(config)) {
if (!enableRefAsProp) {
ref = config.ref;
}
if (__DEV__ && !disableStringRefs) {
warnIfStringRefCannotBeAutoConverted(config, config.__self);
}
}
if (hasValidKey(config)) {
if (__DEV__) {
checkKeyStringCoercion(config.key);
}
key = '' + config.key;
}
for (propName in config) {
if (
hasOwnProperty.call(config, propName) &&
propName !== 'key' &&
(enableRefAsProp || propName !== 'ref') &&
propName !== '__self' &&
propName !== '__source'
) {
props[propName] = config[propName];
}
}
}
const childrenLength = arguments.length - 2;
if (childrenLength === 1) {
props.children = children;
} else if (childrenLength > 1) {
const childArray = Array(childrenLength);
for (let i = 0; i < childrenLength; i++) {
childArray[i] = arguments[i + 2];
}
if (__DEV__) {
if (Object.freeze) {
Object.freeze(childArray);
}
}
props.children = childArray;
}
if (type && type.defaultProps) {
const defaultProps = type.defaultProps;
for (propName in defaultProps) {
if (props[propName] === undefined) {
props[propName] = defaultProps[propName];
}
}
}
if (__DEV__) {
if (key || (!enableRefAsProp && ref)) {
const displayName =
typeof type === 'function'
? type.displayName || type.name || 'Unknown'
: type;
if (key) {
defineKeyPropWarningGetter(props, displayName);
}
if (!enableRefAsProp && ref) {
defineRefPropWarningGetter(props, displayName);
}
}
}
const element = ReactElement(
type,
key,
ref,
undefined,
undefined,
ReactCurrentOwner.current,
props,
);
if (type === REACT_FRAGMENT_TYPE) {
validateFragmentProps(element);
}
return element;
}
let didWarnAboutDeprecatedCreateFactory = false;
export function createFactory(type) {
const factory = createElement.bind(null, type);
factory.type = type;
if (__DEV__) {
if (!didWarnAboutDeprecatedCreateFactory) {
didWarnAboutDeprecatedCreateFactory = true;
console.warn(
'React.createFactory() is deprecated and will be removed in ' +
'a future major release. Consider using JSX ' +
'or use React.createElement() directly instead.',
);
}
Object.defineProperty(factory, 'type', {
enumerable: false,
get: function () {
console.warn(
'Factory.type is deprecated. Access the class directly ' +
'before passing it to createFactory.',
);
Object.defineProperty(this, 'type', {
value: type,
});
return type;
},
});
}
return factory;
}
export function cloneAndReplaceKey(oldElement, newKey) {
return ReactElement(
oldElement.type,
newKey,
enableRefAsProp ? null : oldElement.ref,
undefined,
undefined,
oldElement._owner,
oldElement.props,
);
}
export function cloneElement(element, config, children) {
if (element === null || element === undefined) {
throw new Error(
`The argument must be a React element, but you passed ${element}.`,
);
}
let propName;
const props = assign({}, element.props);
let key = element.key;
let ref = enableRefAsProp ? null : element.ref;
let owner = element._owner;
if (config != null) {
if (hasValidRef(config)) {
if (!enableRefAsProp) {
ref = config.ref;
}
owner = ReactCurrentOwner.current;
}
if (hasValidKey(config)) {
if (__DEV__) {
checkKeyStringCoercion(config.key);
}
key = '' + config.key;
}
let defaultProps;
if (element.type && element.type.defaultProps) {
defaultProps = element.type.defaultProps;
}
for (propName in config) {
if (
hasOwnProperty.call(config, propName) &&
propName !== 'key' &&
(enableRefAsProp || propName !== 'ref') &&
propName !== '__self' &&
propName !== '__source' &&
!(enableRefAsProp && propName === 'ref' && config.ref === undefined)
) {
if (config[propName] === undefined && defaultProps !== undefined) {
props[propName] = defaultProps[propName];
} else {
props[propName] = config[propName];
}
}
}
}
const childrenLength = arguments.length - 2;
if (childrenLength === 1) {
props.children = children;
} else if (childrenLength > 1) {
const childArray = Array(childrenLength);
for (let i = 0; i < childrenLength; i++) {
childArray[i] = arguments[i + 2];
}
props.children = childArray;
}
const clonedElement = ReactElement(
element.type,
key,
ref,
undefined,
undefined,
owner,
props,
);
for (let i = 2; i < arguments.length; i++) {
validateChildKeys(arguments[i], clonedElement.type);
}
return clonedElement;
}
function getDeclarationErrorAddendum() {
if (__DEV__) {
if (ReactCurrentOwner.current) {
const name = getComponentNameFromType(ReactCurrentOwner.current.type);
if (name) {
return '\n\nCheck the render method of `' + name + '`.';
}
}
return '';
}
}
function validateChildKeys(node, parentType) {
if (__DEV__) {
if (typeof node !== 'object' || !node) {
return;
}
if (node.$$typeof === REACT_CLIENT_REFERENCE) {
} else if (isArray(node)) {
for (let i = 0; i < node.length; i++) {
const child = node[i];
if (isValidElement(child)) {
validateExplicitKey(child, parentType);
}
}
} else if (isValidElement(node)) {
if (node._store) {
node._store.validated = true;
}
} else {
const iteratorFn = getIteratorFn(node);
if (typeof iteratorFn === 'function') {
if (iteratorFn !== node.entries) {
const iterator = iteratorFn.call(node);
let step;
while (!(step = iterator.next()).done) {
if (isValidElement(step.value)) {
validateExplicitKey(step.value, parentType);
}
}
}
}
}
}
}
export function isValidElement(object) {
return (
typeof object === 'object' &&
object !== null &&
object.$$typeof === REACT_ELEMENT_TYPE
);
}
const ownerHasKeyUseWarning = {};
function validateExplicitKey(element, parentType) {
if (__DEV__) {
if (!element._store || element._store.validated || element.key != null) {
return;
}
element._store.validated = true;
const currentComponentErrorInfo = getCurrentComponentErrorInfo(parentType);
if (ownerHasKeyUseWarning[currentComponentErrorInfo]) {
return;
}
ownerHasKeyUseWarning[currentComponentErrorInfo] = true;
let childOwner = '';
if (
element &&
element._owner &&
element._owner !== ReactCurrentOwner.current
) {
childOwner = ` It was passed a child from ${getComponentNameFromType(
element._owner.type,
)}.`;
}
setCurrentlyValidatingElement(element);
console.error(
'Each child in a list should have a unique "key" prop.' +
'%s%s See https://react.dev/link/warning-keys for more information.',
currentComponentErrorInfo,
childOwner,
);
setCurrentlyValidatingElement(null);
}
}
function setCurrentlyValidatingElement(element) {
if (__DEV__) {
if (element) {
const owner = element._owner;
const stack = describeUnknownElementTypeFrameInDEV(
element.type,
owner ? owner.type : null,
);
ReactDebugCurrentFrame.setExtraStackFrame(stack);
} else {
ReactDebugCurrentFrame.setExtraStackFrame(null);
}
}
}
function getCurrentComponentErrorInfo(parentType) {
if (__DEV__) {
let info = getDeclarationErrorAddendum();
if (!info) {
const parentName = getComponentNameFromType(parentType);
if (parentName) {
info = `\n\nCheck the top-level render call using <${parentName}>.`;
}
}
return info;
}
}
function validateFragmentProps(fragment) {
if (__DEV__) {
const keys = Object.keys(fragment.props);
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
if (key !== 'children' && key !== 'key') {
setCurrentlyValidatingElement(fragment);
console.error(
'Invalid prop `%s` supplied to `React.Fragment`. ' +
'React.Fragment can only have `key` and `children` props.',
key,
);
setCurrentlyValidatingElement(null);
break;
}
}
if (!enableRefAsProp && fragment.ref !== null) {
setCurrentlyValidatingElement(fragment);
console.error('Invalid attribute `ref` supplied to `React.Fragment`.');
setCurrentlyValidatingElement(null);
}
}
}