packages/react/src/jsx/ReactJSXElement.js JAVASCRIPT 906 lines View on github.com → Search inside
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}

Code quality findings 53

Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (type === REACT_FRAGMENT_TYPE) {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
typeof type === 'object' &&
Be cautious with typeof; it has limitations (e.g., typeof null === 'object')
info correctness typeof-pitfall
typeof type === 'object' &&
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
type !== null &&
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
type.$$typeof === REACT_LAZY_TYPE
Be cautious with typeof; it has limitations (e.g., typeof null === 'object')
info correctness typeof-pitfall
type.$$typeof === REACT_LAZY_TYPE
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (dispatcher === null) {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
return config.ref !== undefined;
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
return config.key !== undefined;
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
return refProp !== undefined ? refProp : null;
Be cautious with typeof; it has limitations (e.g., typeof null === 'object')
info correctness typeof-pitfall
* will not work. Instead test $$typeof field against Symbol.for('react.transitional.element') to check
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
const ref = refProp !== undefined ? refProp : null;
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (ref !== null) {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (maybeKey !== undefined) {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (enableOptimisticKey && maybeKey === REACT_OPTIMISTIC_KEY) {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (enableOptimisticKey && maybeKey === REACT_OPTIMISTIC_KEY) {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (propName !== 'key') {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (children !== undefined) {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
const keys = Object.keys(config).filter(k => k !== 'key');
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (maybeKey !== undefined) {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (enableOptimisticKey && maybeKey === REACT_OPTIMISTIC_KEY) {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (enableOptimisticKey && config.key === REACT_OPTIMISTIC_KEY) {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (propName !== 'key') {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
typeof type === 'function'
Be cautious with typeof; it has limitations (e.g., typeof null === 'object')
info correctness typeof-pitfall
typeof type === 'function'
Use strict inequality (!==) to prevent type coercion bugs
info correctness loose-inequality
if (config != null) {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (enableOptimisticKey && config.key === REACT_OPTIMISTIC_KEY) {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
propName !== 'key' &&
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
propName !== '__self' &&
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
propName !== '__source'
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (childrenLength === 1) {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (props[propName] === undefined) {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
typeof type === 'function'
Be cautious with typeof; it has limitations (e.g., typeof null === 'object')
info correctness typeof-pitfall
typeof type === 'function'
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (element === null || element === undefined) {
Use strict inequality (!==) to prevent type coercion bugs
info correctness loose-inequality
if (config != null) {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (enableOptimisticKey && config.key === REACT_OPTIMISTIC_KEY) {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
propName !== 'key' &&
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
propName !== '__self' &&
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
propName !== '__source' &&
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
!(propName === 'ref' && config.ref === undefined)
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (childrenLength === 1) {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (node._payload.status === 'fulfilled') {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
typeof object === 'object' &&
Be cautious with typeof; it has limitations (e.g., typeof null === 'object')
info correctness typeof-pitfall
typeof object === 'object' &&
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
object !== null &&
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
object.$$typeof === REACT_ELEMENT_TYPE
Be cautious with typeof; it has limitations (e.g., typeof null === 'object')
info correctness typeof-pitfall
object.$$typeof === REACT_ELEMENT_TYPE
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
typeof object === 'object' &&
Be cautious with typeof; it has limitations (e.g., typeof null === 'object')
info correctness typeof-pitfall
typeof object === 'object' &&
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
object !== null &&
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
object.$$typeof === REACT_LAZY_TYPE
Be cautious with typeof; it has limitations (e.g., typeof null === 'object')
info correctness typeof-pitfall
object.$$typeof === REACT_LAZY_TYPE

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.