Use strict equality (===) to prevent type coercion bugs
if (type === REACT_FRAGMENT_TYPE) {
1/**2 * Copyright (c) Meta Platforms, Inc. and affiliates.3 *4 * This source code is licensed under the MIT license found in the5 * LICENSE file in the root directory of this source tree.6 */78import getComponentNameFromType from 'shared/getComponentNameFromType';9import ReactSharedInternals from 'shared/ReactSharedInternals';10import hasOwnProperty from 'shared/hasOwnProperty';11import assign from 'shared/assign';12import {13 REACT_ELEMENT_TYPE,14 REACT_FRAGMENT_TYPE,15 REACT_LAZY_TYPE,16 REACT_OPTIMISTIC_KEY,17} from 'shared/ReactSymbols';18import {checkKeyStringCoercion} from 'shared/CheckStringCoercion';19import isArray from 'shared/isArray';20import {ownerStackLimit, enableOptimisticKey} from 'shared/ReactFeatureFlags';2122const createTask =23 // eslint-disable-next-line react-internal/no-production-logging24 __DEV__ && console.createTask25 ? // eslint-disable-next-line react-internal/no-production-logging26 console.createTask27 : () => null;2829function getTaskName(type) {30 if (type === REACT_FRAGMENT_TYPE) {31 return '<>';32 }33 if (34 typeof type === 'object' &&35 type !== null &&36 type.$$typeof === REACT_LAZY_TYPE37 ) {38 // We don't want to eagerly initialize the initializer in DEV mode so we can't39 // call it to extract the type so we don't know the type of this component.40 return '<...>';41 }42 try {43 const name = getComponentNameFromType(type);44 return name ? '<' + name + '>' : '<...>';45 } catch (x) {46 return '<...>';47 }48}4950function getOwner() {51 if (__DEV__) {52 const dispatcher = ReactSharedInternals.A;53 if (dispatcher === null) {54 return null;55 }56 return dispatcher.getOwner();57 }58 return null;59}6061// v8 (Chromium, Node.js) defaults to 1062// SpiderMonkey (Firefox) does not support Error.stackTraceLimit63// JSC (Safari) defaults to 10064// The lower the limit, the more likely we'll not reach react_stack_bottom_frame65// The higher the limit, the slower Error() is when not inspecting with a debugger.66// When inspecting with a debugger, Error.stackTraceLimit has no impact on Error() performance (in v8).67const ownerStackTraceLimit = 10;6869/** @noinline */70function UnknownOwner() {71 /** @noinline */72 return (() => Error('react-stack-top-frame'))();73}74const createFakeCallStack = {75 react_stack_bottom_frame: function (callStackForError) {76 return callStackForError();77 },78};7980let specialPropKeyWarningShown;81let didWarnAboutElementRef;82let didWarnAboutOldJSXRuntime;83let unknownOwnerDebugStack;84let unknownOwnerDebugTask;8586if (__DEV__) {87 didWarnAboutElementRef = {};8889 // We use this technique to trick minifiers to preserve the function name.90 unknownOwnerDebugStack = createFakeCallStack.react_stack_bottom_frame.bind(91 createFakeCallStack,92 UnknownOwner,93 )();94 unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));95}9697function hasValidRef(config) {98 if (__DEV__) {99 if (hasOwnProperty.call(config, 'ref')) {100 const getter = Object.getOwnPropertyDescriptor(config, 'ref').get;101 if (getter && getter.isReactWarning) {102 return false;103 }104 }105 }106 return config.ref !== undefined;107}108109function hasValidKey(config) {110 if (__DEV__) {111 if (hasOwnProperty.call(config, 'key')) {112 const getter = Object.getOwnPropertyDescriptor(config, 'key').get;113 if (getter && getter.isReactWarning) {114 return false;115 }116 }117 }118 return config.key !== undefined;119}120121function defineKeyPropWarningGetter(props, displayName) {122 if (__DEV__) {123 const warnAboutAccessingKey = function () {124 if (!specialPropKeyWarningShown) {125 specialPropKeyWarningShown = true;126 console.error(127 '%s: `key` is not a prop. Trying to access it will result ' +128 'in `undefined` being returned. If you need to access the same ' +129 'value within the child component, you should pass it as a different ' +130 'prop. (https://react.dev/link/special-props)',131 displayName,132 );133 }134 };135 warnAboutAccessingKey.isReactWarning = true;136 Object.defineProperty(props, 'key', {137 get: warnAboutAccessingKey,138 configurable: true,139 });140 }141}142143function elementRefGetterWithDeprecationWarning() {144 if (__DEV__) {145 const componentName = getComponentNameFromType(this.type);146 if (!didWarnAboutElementRef[componentName]) {147 didWarnAboutElementRef[componentName] = true;148 console.error(149 'Accessing element.ref was removed in React 19. ref is now a ' +150 'regular prop. It will be removed from the JSX Element ' +151 'type in a future release.',152 );153 }154155 // An undefined `element.ref` is coerced to `null` for156 // backwards compatibility.157 const refProp = this.props.ref;158 return refProp !== undefined ? refProp : null;159 }160}161162/**163 * Factory method to create a new React element. This no longer adheres to164 * the class pattern, so do not use new to call it. Also, instanceof check165 * will not work. Instead test $$typeof field against Symbol.for('react.transitional.element') to check166 * if something is a React Element.167 *168 * @internal169 */170function ReactElement(type, key, props, owner, debugStack, debugTask) {171 // Ignore whatever was passed as the ref argument and treat `props.ref` as172 // the source of truth. The only thing we use this for is `element.ref`,173 // which will log a deprecation warning on access. In the next release, we174 // can remove `element.ref` as well as the `ref` argument.175 const refProp = props.ref;176177 // An undefined `element.ref` is coerced to `null` for178 // backwards compatibility.179 const ref = refProp !== undefined ? refProp : null;180181 let element;182 if (__DEV__) {183 // In dev, make `ref` a non-enumerable property with a warning. It's non-184 // enumerable so that test matchers and serializers don't access it and185 // trigger the warning.186 //187 // `ref` will be removed from the element completely in a future release.188 element = {189 // This tag allows us to uniquely identify this as a React Element190 $$typeof: REACT_ELEMENT_TYPE,191192 // Built-in properties that belong on the element193 type,194 key,195196 props,197198 // Record the component responsible for creating this element.199 _owner: owner,200 };201 if (ref !== null) {202 Object.defineProperty(element, 'ref', {203 enumerable: false,204 get: elementRefGetterWithDeprecationWarning,205 });206 } else {207 // Don't warn on access if a ref is not given. This reduces false208 // positives in cases where a test serializer uses209 // getOwnPropertyDescriptors to compare objects, like Jest does, which is210 // a problem because it bypasses non-enumerability.211 //212 // So unfortunately this will trigger a false positive warning in Jest213 // when the diff is printed:214 //215 // expect(<div ref={ref} />).toEqual(<span ref={ref} />);216 //217 // A bit sketchy, but this is what we've done for the `props.key` and218 // `props.ref` accessors for years, which implies it will be good enough219 // for `element.ref`, too. Let's see if anyone complains.220 Object.defineProperty(element, 'ref', {221 enumerable: false,222 value: null,223 });224 }225 } else {226 // In prod, `ref` is a regular property and _owner doesn't exist.227 element = {228 // This tag allows us to uniquely identify this as a React Element229 $$typeof: REACT_ELEMENT_TYPE,230231 // Built-in properties that belong on the element232 type,233 key,234 ref,235236 props,237 };238 }239240 if (__DEV__) {241 // The validation flag is currently mutative. We put it on242 // an external backing store so that we can freeze the whole object.243 // This can be replaced with a WeakMap once they are implemented in244 // commonly used development environments.245 element._store = {};246247 // To make comparing ReactElements easier for testing purposes, we make248 // the validation flag non-enumerable (where possible, which should249 // include every environment we run tests in), so the test framework250 // ignores it.251 Object.defineProperty(element._store, 'validated', {252 configurable: false,253 enumerable: false,254 writable: true,255 value: 0,256 });257 // debugInfo contains Server Component debug information.258 Object.defineProperty(element, '_debugInfo', {259 configurable: false,260 enumerable: false,261 writable: true,262 value: null,263 });264 Object.defineProperty(element, '_debugStack', {265 configurable: false,266 enumerable: false,267 writable: true,268 value: debugStack,269 });270 Object.defineProperty(element, '_debugTask', {271 configurable: false,272 enumerable: false,273 writable: true,274 value: debugTask,275 });276 if (Object.freeze) {277 Object.freeze(element.props);278 Object.freeze(element);279 }280 }281282 return element;283}284285/**286 * https://github.com/reactjs/rfcs/pull/107287 * @param {*} type288 * @param {object} props289 * @param {string} key290 */291export function jsxProd(type, config, maybeKey) {292 let key = null;293294 // Currently, key can be spread in as a prop. This causes a potential295 // issue if key is also explicitly declared (ie. <div {...props} key="Hi" />296 // or <div key="Hi" {...props} /> ). We want to deprecate key spread,297 // but as an intermediary step, we will use jsxDEV for everything except298 // <div {...props} key="Hi" />, because we aren't currently able to tell if299 // key is explicitly declared to be undefined or not.300 if (maybeKey !== undefined) {301 if (enableOptimisticKey && maybeKey === REACT_OPTIMISTIC_KEY) {302 key = REACT_OPTIMISTIC_KEY;303 } else {304 if (__DEV__) {305 checkKeyStringCoercion(maybeKey);306 }307 key = '' + maybeKey;308 }309 }310311 if (hasValidKey(config)) {312 if (enableOptimisticKey && maybeKey === REACT_OPTIMISTIC_KEY) {313 key = REACT_OPTIMISTIC_KEY;314 } else {315 if (__DEV__) {316 checkKeyStringCoercion(config.key);317 }318 key = '' + config.key;319 }320 }321322 let props;323 if (!('key' in config)) {324 // If key was not spread in, we can reuse the original props object. This325 // only works for `jsx`, not `createElement`, because `jsx` is a compiler326 // target and the compiler always passes a new object. For `createElement`,327 // we can't assume a new object is passed every time because it can be328 // called manually.329 //330 // Spreading key is a warning in dev. In a future release, we will not331 // remove a spread key from the props object. (But we'll still warn.) We'll332 // always pass the object straight through.333 props = config;334 } else {335 // We need to remove reserved props (key, prop, ref). Create a fresh props336 // object and copy over all the non-reserved props. We don't use `delete`337 // because in V8 it will deopt the object to dictionary mode.338 props = {};339 for (const propName in config) {340 // Skip over reserved prop names341 if (propName !== 'key') {342 props[propName] = config[propName];343 }344 }345 }346347 return ReactElement(type, key, props, getOwner(), undefined, undefined);348}349350// While `jsxDEV` should never be called when running in production, we do351// support `jsx` and `jsxs` when running in development. This supports the case352// where a third-party dependency ships code that was compiled for production;353// we want to still provide warnings in development.354//355// So these functions are the _dev_ implementations of the _production_356// API signatures.357//358// Since these functions are dev-only, it's ok to add an indirection here. They359// only exist to provide different versions of `isStaticChildren`. (We shouldn't360// use this pattern for the prod versions, though, because it will add an call361// frame.)362export function jsxProdSignatureRunningInDevWithDynamicChildren(363 type,364 config,365 maybeKey,366) {367 if (__DEV__) {368 const isStaticChildren = false;369 const trackActualOwner =370 __DEV__ &&371 ReactSharedInternals.recentlyCreatedOwnerStacks++ < ownerStackLimit;372 let debugStackDEV = false;373 if (__DEV__) {374 if (trackActualOwner) {375 const previousStackTraceLimit = Error.stackTraceLimit;376 Error.stackTraceLimit = ownerStackTraceLimit;377 debugStackDEV = Error('react-stack-top-frame');378 Error.stackTraceLimit = previousStackTraceLimit;379 } else {380 debugStackDEV = unknownOwnerDebugStack;381 }382 }383384 return jsxDEVImpl(385 type,386 config,387 maybeKey,388 isStaticChildren,389 debugStackDEV,390 __DEV__ &&391 (trackActualOwner392 ? createTask(getTaskName(type))393 : unknownOwnerDebugTask),394 );395 }396}397398export function jsxProdSignatureRunningInDevWithStaticChildren(399 type,400 config,401 maybeKey,402) {403 if (__DEV__) {404 const isStaticChildren = true;405 const trackActualOwner =406 __DEV__ &&407 ReactSharedInternals.recentlyCreatedOwnerStacks++ < ownerStackLimit;408 let debugStackDEV = false;409 if (__DEV__) {410 if (trackActualOwner) {411 const previousStackTraceLimit = Error.stackTraceLimit;412 Error.stackTraceLimit = ownerStackTraceLimit;413 debugStackDEV = Error('react-stack-top-frame');414 Error.stackTraceLimit = previousStackTraceLimit;415 } else {416 debugStackDEV = unknownOwnerDebugStack;417 }418 }419 return jsxDEVImpl(420 type,421 config,422 maybeKey,423 isStaticChildren,424 debugStackDEV,425 __DEV__ &&426 (trackActualOwner427 ? createTask(getTaskName(type))428 : unknownOwnerDebugTask),429 );430 }431}432433const didWarnAboutKeySpread = {};434435/**436 * https://github.com/reactjs/rfcs/pull/107437 * @param {*} type438 * @param {object} props439 * @param {string} key440 */441export function jsxDEV(type, config, maybeKey, isStaticChildren) {442 const trackActualOwner =443 __DEV__ &&444 ReactSharedInternals.recentlyCreatedOwnerStacks++ < ownerStackLimit;445 let debugStackDEV = false;446 if (__DEV__) {447 if (trackActualOwner) {448 const previousStackTraceLimit = Error.stackTraceLimit;449 Error.stackTraceLimit = ownerStackTraceLimit;450 debugStackDEV = Error('react-stack-top-frame');451 Error.stackTraceLimit = previousStackTraceLimit;452 } else {453 debugStackDEV = unknownOwnerDebugStack;454 }455 }456 return jsxDEVImpl(457 type,458 config,459 maybeKey,460 isStaticChildren,461 debugStackDEV,462 __DEV__ &&463 (trackActualOwner464 ? createTask(getTaskName(type))465 : unknownOwnerDebugTask),466 );467}468469function jsxDEVImpl(470 type,471 config,472 maybeKey,473 isStaticChildren,474 debugStack,475 debugTask,476) {477 if (__DEV__) {478 // We don't warn for invalid element type here because with owner stacks,479 // we error in the renderer. The renderer is the only one that knows what480 // types are valid for this particular renderer so we let it error there.481482 // Skip key warning if the type isn't valid since our key validation logic483 // doesn't expect a non-string/function type and can throw confusing484 // errors. We don't want exception behavior to differ between dev and485 // prod. (Rendering will throw with a helpful message and as soon as the486 // type is fixed, the key warnings will appear.)487 // With owner stacks, we no longer need the type here so this comment is488 // no longer true. Which is why we can run this even for invalid types.489 const children = config.children;490 if (children !== undefined) {491 if (isStaticChildren) {492 if (isArray(children)) {493 for (let i = 0; i < children.length; i++) {494 validateChildKeys(children[i]);495 }496497 if (Object.freeze) {498 Object.freeze(children);499 }500 } else {501 console.error(502 'React.jsx: Static children should always be an array. ' +503 'You are likely explicitly calling React.jsxs or React.jsxDEV. ' +504 'Use the Babel transform instead.',505 );506 }507 } else {508 validateChildKeys(children);509 }510 }511512 // Warn about key spread regardless of whether the type is valid.513 if (hasOwnProperty.call(config, 'key')) {514 const componentName = getComponentNameFromType(type);515 const keys = Object.keys(config).filter(k => k !== 'key');516 const beforeExample =517 keys.length > 0518 ? '{key: someKey, ' + keys.join(': ..., ') + ': ...}'519 : '{key: someKey}';520 if (!didWarnAboutKeySpread[componentName + beforeExample]) {521 const afterExample =522 keys.length > 0 ? '{' + keys.join(': ..., ') + ': ...}' : '{}';523 console.error(524 'A props object containing a "key" prop is being spread into JSX:\n' +525 ' let props = %s;\n' +526 ' <%s {...props} />\n' +527 'React keys must be passed directly to JSX without using spread:\n' +528 ' let props = %s;\n' +529 ' <%s key={someKey} {...props} />',530 beforeExample,531 componentName,532 afterExample,533 componentName,534 );535 didWarnAboutKeySpread[componentName + beforeExample] = true;536 }537 }538539 let key = null;540541 // Currently, key can be spread in as a prop. This causes a potential542 // issue if key is also explicitly declared (ie. <div {...props} key="Hi" />543 // or <div key="Hi" {...props} /> ). We want to deprecate key spread,544 // but as an intermediary step, we will use jsxDEV for everything except545 // <div {...props} key="Hi" />, because we aren't currently able to tell if546 // key is explicitly declared to be undefined or not.547 if (maybeKey !== undefined) {548 if (enableOptimisticKey && maybeKey === REACT_OPTIMISTIC_KEY) {549 key = REACT_OPTIMISTIC_KEY;550 } else {551 if (__DEV__) {552 checkKeyStringCoercion(maybeKey);553 }554 key = '' + maybeKey;555 }556 }557558 if (hasValidKey(config)) {559 if (enableOptimisticKey && config.key === REACT_OPTIMISTIC_KEY) {560 key = REACT_OPTIMISTIC_KEY;561 } else {562 if (__DEV__) {563 checkKeyStringCoercion(config.key);564 }565 key = '' + config.key;566 }567 }568569 let props;570 if (!('key' in config)) {571 // If key was not spread in, we can reuse the original props object. This572 // only works for `jsx`, not `createElement`, because `jsx` is a compiler573 // target and the compiler always passes a new object. For `createElement`,574 // we can't assume a new object is passed every time because it can be575 // called manually.576 //577 // Spreading key is a warning in dev. In a future release, we will not578 // remove a spread key from the props object. (But we'll still warn.) We'll579 // always pass the object straight through.580 props = config;581 } else {582 // We need to remove reserved props (key, prop, ref). Create a fresh props583 // object and copy over all the non-reserved props. We don't use `delete`584 // because in V8 it will deopt the object to dictionary mode.585 props = {};586 for (const propName in config) {587 // Skip over reserved prop names588 if (propName !== 'key') {589 props[propName] = config[propName];590 }591 }592 }593594 if (key) {595 const displayName =596 typeof type === 'function'597 ? type.displayName || type.name || 'Unknown'598 : type;599 defineKeyPropWarningGetter(props, displayName);600 }601602 return ReactElement(type, key, props, getOwner(), debugStack, debugTask);603 }604}605606/**607 * Create and return a new ReactElement of the given type.608 * See https://reactjs.org/docs/react-api.html#createelement609 */610export function createElement(type, config, children) {611 if (__DEV__) {612 // We don't warn for invalid element type here because with owner stacks,613 // we error in the renderer. The renderer is the only one that knows what614 // types are valid for this particular renderer so we let it error there.615616 // Skip key warning if the type isn't valid since our key validation logic617 // doesn't expect a non-string/function type and can throw confusing618 // errors. We don't want exception behavior to differ between dev and619 // prod. (Rendering will throw with a helpful message and as soon as the620 // type is fixed, the key warnings will appear.)621 for (let i = 2; i < arguments.length; i++) {622 validateChildKeys(arguments[i]);623 }624625 // Unlike the jsx() runtime, createElement() doesn't warn about key spread.626 }627628 let propName;629630 // Reserved names are extracted631 const props = {};632633 let key = null;634635 if (config != null) {636 if (__DEV__) {637 if (638 !didWarnAboutOldJSXRuntime &&639 '__self' in config &&640 // Do not assume this is the result of an oudated JSX transform if key641 // is present, because the modern JSX transform sometimes outputs642 // createElement to preserve precedence between a static key and a643 // spread key. To avoid false positive warnings, we never warn if644 // there's a key.645 !('key' in config)646 ) {647 didWarnAboutOldJSXRuntime = true;648 console.warn(649 'Your app (or one of its dependencies) is using an outdated JSX ' +650 'transform. Update to the modern JSX transform for ' +651 'faster performance: https://react.dev/link/new-jsx-transform',652 );653 }654 }655656 if (hasValidKey(config)) {657 if (enableOptimisticKey && config.key === REACT_OPTIMISTIC_KEY) {658 key = REACT_OPTIMISTIC_KEY;659 } else {660 if (__DEV__) {661 checkKeyStringCoercion(config.key);662 }663 key = '' + config.key;664 }665 }666667 // Remaining properties are added to a new props object668 for (propName in config) {669 if (670 hasOwnProperty.call(config, propName) &&671 // Skip over reserved prop names672 propName !== 'key' &&673 // Even though we don't use these anymore in the runtime, we don't want674 // them to appear as props, so in createElement we filter them out.675 // We don't have to do this in the jsx() runtime because the jsx()676 // transform never passed these as props; it used separate arguments.677 propName !== '__self' &&678 propName !== '__source'679 ) {680 props[propName] = config[propName];681 }682 }683 }684685 // Children can be more than one argument, and those are transferred onto686 // the newly allocated props object.687 const childrenLength = arguments.length - 2;688 if (childrenLength === 1) {689 props.children = children;690 } else if (childrenLength > 1) {691 const childArray = Array(childrenLength);692 for (let i = 0; i < childrenLength; i++) {693 childArray[i] = arguments[i + 2];694 }695 if (__DEV__) {696 if (Object.freeze) {697 Object.freeze(childArray);698 }699 }700 props.children = childArray;701 }702703 // Resolve default props704 if (type && type.defaultProps) {705 const defaultProps = type.defaultProps;706 for (propName in defaultProps) {707 if (props[propName] === undefined) {708 props[propName] = defaultProps[propName];709 }710 }711 }712 if (__DEV__) {713 if (key) {714 const displayName =715 typeof type === 'function'716 ? type.displayName || type.name || 'Unknown'717 : type;718 defineKeyPropWarningGetter(props, displayName);719 }720 }721 const trackActualOwner =722 __DEV__ &&723 ReactSharedInternals.recentlyCreatedOwnerStacks++ < ownerStackLimit;724 let debugStackDEV = false;725 if (__DEV__) {726 if (trackActualOwner) {727 const previousStackTraceLimit = Error.stackTraceLimit;728 Error.stackTraceLimit = ownerStackTraceLimit;729 debugStackDEV = Error('react-stack-top-frame');730 Error.stackTraceLimit = previousStackTraceLimit;731 } else {732 debugStackDEV = unknownOwnerDebugStack;733 }734 }735 return ReactElement(736 type,737 key,738 props,739 getOwner(),740 debugStackDEV,741 __DEV__ &&742 (trackActualOwner743 ? createTask(getTaskName(type))744 : unknownOwnerDebugTask),745 );746}747748export function cloneAndReplaceKey(oldElement, newKey) {749 const clonedElement = ReactElement(750 oldElement.type,751 newKey,752 oldElement.props,753 !__DEV__ ? undefined : oldElement._owner,754 __DEV__ && oldElement._debugStack,755 __DEV__ && oldElement._debugTask,756 );757 if (__DEV__) {758 // The cloned element should inherit the original element's key validation.759 if (oldElement._store) {760 clonedElement._store.validated = oldElement._store.validated;761 }762 }763 return clonedElement;764}765766/**767 * Clone and return a new ReactElement using element as the starting point.768 * See https://reactjs.org/docs/react-api.html#cloneelement769 */770export function cloneElement(element, config, children) {771 if (element === null || element === undefined) {772 throw new Error(773 `The argument must be a React element, but you passed ${element}.`,774 );775 }776777 let propName;778779 // Original props are copied780 const props = assign({}, element.props);781782 // Reserved names are extracted783 let key = element.key;784785 // Owner will be preserved, unless ref is overridden786 let owner = !__DEV__ ? undefined : element._owner;787788 if (config != null) {789 if (hasValidRef(config)) {790 owner = __DEV__ ? getOwner() : undefined;791 }792 if (hasValidKey(config)) {793 if (enableOptimisticKey && config.key === REACT_OPTIMISTIC_KEY) {794 key = REACT_OPTIMISTIC_KEY;795 } else {796 if (__DEV__) {797 checkKeyStringCoercion(config.key);798 }799 key = '' + config.key;800 }801 }802803 // Remaining properties override existing props804 for (propName in config) {805 if (806 hasOwnProperty.call(config, propName) &&807 // Skip over reserved prop names808 propName !== 'key' &&809 // ...and maybe these, too, though we currently rely on them for810 // warnings and debug information in dev. Need to decide if we're OK811 // with dropping them. In the jsx() runtime it's not an issue because812 // the data gets passed as separate arguments instead of props, but813 // it would be nice to stop relying on them entirely so we can drop814 // them from the internal Fiber field.815 propName !== '__self' &&816 propName !== '__source' &&817 // Undefined `ref` is ignored by cloneElement. We treat it the same as818 // if the property were missing. This is mostly for819 // backwards compatibility.820 !(propName === 'ref' && config.ref === undefined)821 ) {822 props[propName] = config[propName];823 }824 }825 }826827 // Children can be more than one argument, and those are transferred onto828 // the newly allocated props object.829 const childrenLength = arguments.length - 2;830 if (childrenLength === 1) {831 props.children = children;832 } else if (childrenLength > 1) {833 const childArray = Array(childrenLength);834 for (let i = 0; i < childrenLength; i++) {835 childArray[i] = arguments[i + 2];836 }837 props.children = childArray;838 }839840 const clonedElement = ReactElement(841 element.type,842 key,843 props,844 owner,845 __DEV__ && element._debugStack,846 __DEV__ && element._debugTask,847 );848849 for (let i = 2; i < arguments.length; i++) {850 validateChildKeys(arguments[i]);851 }852853 return clonedElement;854}855856/**857 * Ensure that every element either is passed in a static location, in an858 * array with an explicit keys property defined, or in an object literal859 * with valid key property.860 *861 * @internal862 * @param {ReactNode} node Statically passed child of any type.863 */864function validateChildKeys(node) {865 if (__DEV__) {866 // Mark elements as being in a valid static child position so they867 // don't need keys.868 if (isValidElement(node)) {869 if (node._store) {870 node._store.validated = 1;871 }872 } else if (isLazyType(node)) {873 if (node._payload.status === 'fulfilled') {874 if (isValidElement(node._payload.value) && node._payload.value._store) {875 node._payload.value._store.validated = 1;876 }877 } else if (node._store) {878 node._store.validated = 1;879 }880 }881 }882}883884/**885 * Verifies the object is a ReactElement.886 * See https://reactjs.org/docs/react-api.html#isvalidelement887 * @param {?object} object888 * @return {boolean} True if `object` is a ReactElement.889 * @final890 */891export function isValidElement(object) {892 return (893 typeof object === 'object' &&894 object !== null &&895 object.$$typeof === REACT_ELEMENT_TYPE896 );897}898899export function isLazyType(object) {900 return (901 typeof object === 'object' &&902 object !== null &&903 object.$$typeof === REACT_LAZY_TYPE904 );905}
Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.