packages/react-dom-bindings/src/client/ReactDOMInput.js JAVASCRIPT 488 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 *7 * @flow8 */910// TODO: direct imports like some-package/src/* are bad. Fix me.11import {getCurrentFiberOwnerNameInDevOrNull} from 'react-reconciler/src/ReactCurrentFiber';1213import {getFiberCurrentPropsFromNode} from './ReactDOMComponentTree';14import {getToStringValue, toString} from './ToStringValue';15import {track, trackHydrated, updateValueIfChanged} from './inputValueTracking';16import getActiveElement from './getActiveElement';17import {18  disableInputAttributeSyncing,19  enableHydrationChangeEvent,20} from 'shared/ReactFeatureFlags';21import {checkAttributeStringCoercion} from 'shared/CheckStringCoercion';2223import type {ToStringValue} from './ToStringValue';24import escapeSelectorAttributeValueInsideDoubleQuotes from './escapeSelectorAttributeValueInsideDoubleQuotes';25import {queueChangeEvent} from '../events/ReactDOMEventReplaying';2627let didWarnValueDefaultValue = false;28let didWarnCheckedDefaultChecked = false;2930/**31 * Implements an <input> host component that allows setting these optional32 * props: `checked`, `value`, `defaultChecked`, and `defaultValue`.33 *34 * If `checked` or `value` are not supplied (or null/undefined), user actions35 * that affect the checked state or value will trigger updates to the element.36 *37 * If they are supplied (and not null/undefined), the rendered element will not38 * trigger updates to the element. Instead, the props must change in order for39 * the rendered element to be updated.40 *41 * The rendered element will be initialized as unchecked (or `defaultChecked`)42 * with an empty value (or `defaultValue`).43 *44 * See http://www.w3.org/TR/2012/WD-html5-20121025/the-input-element.html45 */4647export function validateInputProps(element: Element, props: Object) {48  if (__DEV__) {49    // Normally we check for undefined and null the same, but explicitly specifying both50    // properties, at all is probably worth warning for. We could move this either direction51    // and just make it ok to pass null or just check hasOwnProperty.52    if (53      props.checked !== undefined &&54      props.defaultChecked !== undefined &&55      !didWarnCheckedDefaultChecked56    ) {57      console.error(58        '%s contains an input of type %s with both checked and defaultChecked props. ' +59          'Input elements must be either controlled or uncontrolled ' +60          '(specify either the checked prop, or the defaultChecked prop, but not ' +61          'both). Decide between using a controlled or uncontrolled input ' +62          'element and remove one of these props. More info: ' +63          'https://react.dev/link/controlled-components',64        getCurrentFiberOwnerNameInDevOrNull() || 'A component',65        props.type,66      );67      didWarnCheckedDefaultChecked = true;68    }69    if (70      props.value !== undefined &&71      props.defaultValue !== undefined &&72      !didWarnValueDefaultValue73    ) {74      console.error(75        '%s contains an input of type %s with both value and defaultValue props. ' +76          'Input elements must be either controlled or uncontrolled ' +77          '(specify either the value prop, or the defaultValue prop, but not ' +78          'both). Decide between using a controlled or uncontrolled input ' +79          'element and remove one of these props. More info: ' +80          'https://react.dev/link/controlled-components',81        getCurrentFiberOwnerNameInDevOrNull() || 'A component',82        props.type,83      );84      didWarnValueDefaultValue = true;85    }86  }87}8889export function updateInput(90  element: Element,91  value: ?string,92  defaultValue: ?string,93  lastDefaultValue: ?string,94  checked: ?boolean,95  defaultChecked: ?boolean,96  type: ?string,97  name: ?string,98) {99  const node: HTMLInputElement = element as any;100101  // Temporarily disconnect the input from any radio buttons.102  // Changing the type or name as the same time as changing the checked value103  // needs to be atomically applied. We can only ensure that by disconnecting104  // the name while do the mutations and then reapply the name after that's done.105  node.name = '';106107  if (108    type != null &&109    typeof type !== 'function' &&110    typeof type !== 'symbol' &&111    typeof type !== 'boolean'112  ) {113    if (__DEV__) {114      checkAttributeStringCoercion(type, 'type');115    }116    node.type = type;117  } else {118    node.removeAttribute('type');119  }120121  if (value != null) {122    if (type === 'number') {123      if (124        // $FlowFixMe[incompatible-type]125        // $FlowFixMe[invalid-compare]126        (value === 0 && node.value === '') ||127        // We explicitly want to coerce to number here if possible.128        // eslint-disable-next-line129        node.value != (value as any)130      ) {131        node.value = toString(getToStringValue(value));132      }133    } else if (node.value !== toString(getToStringValue(value))) {134      node.value = toString(getToStringValue(value));135    }136  } else if (type === 'submit' || type === 'reset') {137    // Submit/reset inputs need the attribute removed completely to avoid138    // blank-text buttons.139    node.removeAttribute('value');140  }141142  if (disableInputAttributeSyncing) {143    // When not syncing the value attribute, React only assigns a new value144    // whenever the defaultValue React prop has changed. When not present,145    // React does nothing146    if (defaultValue != null) {147      setDefaultValue(node, type, getToStringValue(defaultValue));148    } else if (lastDefaultValue != null) {149      node.removeAttribute('value');150    }151  } else {152    // When syncing the value attribute, the value comes from a cascade of153    // properties:154    //  1. The value React property155    //  2. The defaultValue React property156    //  3. Otherwise there should be no change157    if (value != null) {158      setDefaultValue(node, type, getToStringValue(value));159    } else if (defaultValue != null) {160      setDefaultValue(node, type, getToStringValue(defaultValue));161    } else if (lastDefaultValue != null) {162      node.removeAttribute('value');163    }164  }165166  if (disableInputAttributeSyncing) {167    // When not syncing the checked attribute, the attribute is directly168    // controllable from the defaultValue React property. It needs to be169    // updated as new props come in.170    if (defaultChecked == null) {171      node.removeAttribute('checked');172    } else {173      node.defaultChecked = !!defaultChecked;174    }175  } else {176    // When syncing the checked attribute, it only changes when it needs177    // to be removed, such as transitioning from a checkbox into a text input178    if (checked == null && defaultChecked != null) {179      node.defaultChecked = !!defaultChecked;180    }181  }182183  if (checked != null) {184    // Important to set this even if it's not a change in order to update input185    // value tracking with radio buttons186    // TODO: Should really update input value tracking for the whole radio187    // button group in an effect or something (similar to #27024)188    node.checked =189      checked && typeof checked !== 'function' && typeof checked !== 'symbol';190  }191192  if (193    name != null &&194    typeof name !== 'function' &&195    typeof name !== 'symbol' &&196    typeof name !== 'boolean'197  ) {198    if (__DEV__) {199      checkAttributeStringCoercion(name, 'name');200    }201    node.name = toString(getToStringValue(name));202  } else {203    node.removeAttribute('name');204  }205}206207export function initInput(208  element: Element,209  value: ?string,210  defaultValue: ?string,211  checked: ?boolean,212  defaultChecked: ?boolean,213  type: ?string,214  name: ?string,215  isHydrating: boolean,216) {217  const node: HTMLInputElement = element as any;218219  if (220    type != null &&221    typeof type !== 'function' &&222    typeof type !== 'symbol' &&223    typeof type !== 'boolean'224  ) {225    if (__DEV__) {226      checkAttributeStringCoercion(type, 'type');227    }228    node.type = type;229  }230231  if (value != null || defaultValue != null) {232    const isButton = type === 'submit' || type === 'reset';233234    // Avoid setting value attribute on submit/reset inputs as it overrides the235    // default value provided by the browser. See: #12872236    if (isButton && (value === undefined || value === null)) {237      // We track the value just in case it changes type later on.238      track(element as any);239      return;240    }241242    const defaultValueStr =243      defaultValue != null ? toString(getToStringValue(defaultValue)) : '';244    const initialValue =245      value != null ? toString(getToStringValue(value)) : defaultValueStr;246247    // Do not assign value if it is already set. This prevents user text input248    // from being lost during SSR hydration.249    if (!isHydrating || enableHydrationChangeEvent) {250      if (disableInputAttributeSyncing) {251        // When not syncing the value attribute, the value property points252        // directly to the React prop. Only assign it if it exists.253        if (value != null) {254          // Always assign on buttons so that it is possible to assign an255          // empty string to clear button text.256          //257          // Otherwise, do not re-assign the value property if is empty. This258          // potentially avoids a DOM write and prevents Firefox (~60.0.1) from259          // prematurely marking required inputs as invalid. Equality is compared260          // to the current value in case the browser provided value is not an261          // empty string.262          if (isButton || toString(getToStringValue(value)) !== node.value) {263            node.value = toString(getToStringValue(value));264          }265        }266      } else {267        // When syncing the value attribute, the value property should use268        // the wrapperState._initialValue property. This uses:269        //270        //   1. The value React property when present271        //   2. The defaultValue React property when present272        //   3. An empty string273        if (initialValue !== node.value) {274          node.value = initialValue;275        }276      }277    }278279    if (disableInputAttributeSyncing) {280      // When not syncing the value attribute, assign the value attribute281      // directly from the defaultValue React property (when present)282      if (defaultValue != null) {283        node.defaultValue = defaultValueStr;284      }285    } else {286      // Otherwise, the value attribute is synchronized to the property,287      // so we assign defaultValue to the same thing as the value property288      // assignment step above.289      node.defaultValue = initialValue;290    }291  }292293  // Normally, we'd just do `node.checked = node.checked` upon initial mount, less this bug294  // this is needed to work around a chrome bug where setting defaultChecked295  // will sometimes influence the value of checked (even after detachment).296  // Reference: https://bugs.chromium.org/p/chromium/issues/detail?id=608416297  // We need to temporarily unset name to avoid disrupting radio button groups.298299  const checkedOrDefault = checked != null ? checked : defaultChecked;300  // TODO: This 'function' or 'symbol' check isn't replicated in other places301  // so this semantic is inconsistent.302  const initialChecked =303    typeof checkedOrDefault !== 'function' &&304    typeof checkedOrDefault !== 'symbol' &&305    !!checkedOrDefault;306307  if (isHydrating && !enableHydrationChangeEvent) {308    // Detach .checked from .defaultChecked but leave user input alone309    node.checked = node.checked;310  } else {311    node.checked = !!initialChecked;312  }313314  if (disableInputAttributeSyncing) {315    // Only assign the checked attribute if it is defined. This saves316    // a DOM write when controlling the checked attribute isn't needed317    // (text inputs, submit/reset)318    if (defaultChecked != null) {319      node.defaultChecked = !node.defaultChecked;320      node.defaultChecked = !!defaultChecked;321    }322  } else {323    // When syncing the checked attribute, both the checked property and324    // attribute are assigned at the same time using defaultChecked. This uses:325    //326    //   1. The checked React property when present327    //   2. The defaultChecked React property when present328    //   3. Otherwise, false329    node.defaultChecked = !node.defaultChecked;330    node.defaultChecked = !!initialChecked;331  }332333  // Name needs to be set at the end so that it applies atomically to connected radio buttons.334  if (335    name != null &&336    typeof name !== 'function' &&337    typeof name !== 'symbol' &&338    typeof name !== 'boolean'339  ) {340    if (__DEV__) {341      checkAttributeStringCoercion(name, 'name');342    }343    node.name = name;344  }345  track(element as any);346}347348export function hydrateInput(349  element: Element,350  value: ?string,351  defaultValue: ?string,352  checked: ?boolean,353  defaultChecked: ?boolean,354): void {355  const node: HTMLInputElement = element as any;356357  const defaultValueStr =358    defaultValue != null ? toString(getToStringValue(defaultValue)) : '';359  const initialValue =360    value != null ? toString(getToStringValue(value)) : defaultValueStr;361362  const checkedOrDefault = checked != null ? checked : defaultChecked;363  // TODO: This 'function' or 'symbol' check isn't replicated in other places364  // so this semantic is inconsistent.365  const initialChecked =366    typeof checkedOrDefault !== 'function' &&367    typeof checkedOrDefault !== 'symbol' &&368    !!checkedOrDefault;369370  // Detach .checked from .defaultChecked but leave user input alone371  node.checked = node.checked;372373  const changed = trackHydrated(node as any, initialValue, initialChecked);374  if (changed) {375    // If the current value is different, that suggests that the user376    // changed it before hydration. Queue a replay of the change event.377    // For radio buttons the change event only fires on the selected one.378    if (node.type !== 'radio' || node.checked) {379      queueChangeEvent(node);380    }381  }382}383384export function restoreControlledInputState(element: Element, props: Object) {385  const rootNode: HTMLInputElement = element as any;386  updateInput(387    rootNode,388    props.value,389    props.defaultValue,390    props.defaultValue,391    props.checked,392    props.defaultChecked,393    props.type,394    props.name,395  );396  const name = props.name;397  if (props.type === 'radio' && name != null) {398    let queryRoot: Element = rootNode;399400    while (queryRoot.parentNode) {401      queryRoot = queryRoot.parentNode as any as Element;402    }403404    // If `rootNode.form` was non-null, then we could try `form.elements`,405    // but that sometimes behaves strangely in IE8. We could also try using406    // `form.getElementsByName`, but that will only return direct children407    // and won't include inputs that use the HTML5 `form=` attribute. Since408    // the input might not even be in a form. It might not even be in the409    // document. Let's just use the local `querySelectorAll` to ensure we don't410    // miss anything.411    if (__DEV__) {412      checkAttributeStringCoercion(name, 'name');413    }414    const group = queryRoot.querySelectorAll(415      'input[name="' +416        escapeSelectorAttributeValueInsideDoubleQuotes('' + name) +417        '"][type="radio"]',418    );419420    for (let i = 0; i < group.length; i++) {421      const otherNode = group[i] as any as HTMLInputElement;422      if (otherNode === rootNode || otherNode.form !== rootNode.form) {423        continue;424      }425      // This will throw if radio buttons rendered by different copies of React426      // and the same name are rendered into the same form (same as #1939).427      // That's probably okay; we don't support it just as we don't support428      // mixing React radio buttons with non-React ones.429      const otherProps: any = getFiberCurrentPropsFromNode(otherNode);430431      if (!otherProps) {432        throw new Error(433          'ReactDOMInput: Mixing React and non-React radio inputs with the ' +434            'same `name` is not supported.',435        );436      }437438      // If this is a controlled radio button group, forcing the input that439      // was previously checked to update will cause it to be come re-checked440      // as appropriate.441      updateInput(442        otherNode,443        otherProps.value,444        otherProps.defaultValue,445        otherProps.defaultValue,446        otherProps.checked,447        otherProps.defaultChecked,448        otherProps.type,449        otherProps.name,450      );451    }452453    // If any updateInput() call set .checked to true, an input in this group454    // (often, `rootNode` itself) may have become unchecked455    for (let i = 0; i < group.length; i++) {456      const otherNode = group[i] as any as HTMLInputElement;457      if (otherNode.form !== rootNode.form) {458        continue;459      }460      updateValueIfChanged(otherNode);461    }462  }463}464465// In Chrome, assigning defaultValue to certain input types triggers input validation.466// For number inputs, the display value loses trailing decimal points. For email inputs,467// Chrome raises "The specified value <x> is not a valid email address".468//469// Here we check to see if the defaultValue has actually changed, avoiding these problems470// when the user is inputting text471//472// https://github.com/facebook/react/issues/7253473export function setDefaultValue(474  node: HTMLInputElement,475  type: ?string,476  value: ToStringValue,477) {478  if (479    // Focused number inputs synchronize on blur. See ChangeEventPlugin.js480    type !== 'number' ||481    getActiveElement(node.ownerDocument) !== node482  ) {483    if (node.defaultValue !== toString(value)) {484      node.defaultValue = toString(value);485    }486  }487}

Code quality findings 79

Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
props.checked !== undefined &&
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
props.defaultChecked !== undefined &&
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
props.value !== undefined &&
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
props.defaultValue !== undefined &&
Use strict inequality (!==) to prevent type coercion bugs
info correctness loose-inequality
type != null &&
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
typeof type !== 'symbol' &&
Be cautious with typeof; it has limitations (e.g., typeof null === 'object')
info correctness typeof-pitfall
typeof type !== 'symbol' &&
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
typeof type !== 'boolean'
Be cautious with typeof; it has limitations (e.g., typeof null === 'object')
info correctness typeof-pitfall
typeof type !== 'boolean'
Use strict inequality (!==) to prevent type coercion bugs
info correctness loose-inequality
if (value != null) {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (type === 'number') {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
(value === 0 && node.value === '') ||
Use strict inequality (!==) to prevent type coercion bugs
info correctness loose-inequality
node.value != (value as any)
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
} else if (node.value !== toString(getToStringValue(value))) {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
} else if (type === 'submit' || type === 'reset') {
Use strict inequality (!==) to prevent type coercion bugs
info correctness loose-inequality
if (defaultValue != null) {
Use strict inequality (!==) to prevent type coercion bugs
info correctness loose-inequality
} else if (lastDefaultValue != null) {
Use strict inequality (!==) to prevent type coercion bugs
info correctness loose-inequality
if (value != null) {
Use strict inequality (!==) to prevent type coercion bugs
info correctness loose-inequality
} else if (defaultValue != null) {
Use strict inequality (!==) to prevent type coercion bugs
info correctness loose-inequality
} else if (lastDefaultValue != null) {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (defaultChecked == null) {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (checked == null && defaultChecked != null) {
Use strict inequality (!==) to prevent type coercion bugs
info correctness loose-inequality
if (checked == null && defaultChecked != null) {
Use strict inequality (!==) to prevent type coercion bugs
info correctness loose-inequality
if (checked != null) {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
checked && typeof checked !== 'function' && typeof checked !== 'symbol';
Be cautious with typeof; it has limitations (e.g., typeof null === 'object')
info correctness typeof-pitfall
checked && typeof checked !== 'function' && typeof checked !== 'symbol';
Use strict inequality (!==) to prevent type coercion bugs
info correctness loose-inequality
name != null &&
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
typeof name !== 'function' &&
Be cautious with typeof; it has limitations (e.g., typeof null === 'object')
info correctness typeof-pitfall
typeof name !== 'function' &&
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
typeof name !== 'symbol' &&
Be cautious with typeof; it has limitations (e.g., typeof null === 'object')
info correctness typeof-pitfall
typeof name !== 'symbol' &&
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
typeof name !== 'boolean'
Be cautious with typeof; it has limitations (e.g., typeof null === 'object')
info correctness typeof-pitfall
typeof name !== 'boolean'
Use strict inequality (!==) to prevent type coercion bugs
info correctness loose-inequality
type != null &&
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
typeof type !== 'symbol' &&
Be cautious with typeof; it has limitations (e.g., typeof null === 'object')
info correctness typeof-pitfall
typeof type !== 'symbol' &&
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
typeof type !== 'boolean'
Be cautious with typeof; it has limitations (e.g., typeof null === 'object')
info correctness typeof-pitfall
typeof type !== 'boolean'
Use strict inequality (!==) to prevent type coercion bugs
info correctness loose-inequality
if (value != null || defaultValue != null) {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
const isButton = type === 'submit' || type === 'reset';
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (isButton && (value === undefined || value === null)) {
Use strict inequality (!==) to prevent type coercion bugs
info correctness loose-inequality
defaultValue != null ? toString(getToStringValue(defaultValue)) : '';
Use strict inequality (!==) to prevent type coercion bugs
info correctness loose-inequality
value != null ? toString(getToStringValue(value)) : defaultValueStr;
Use strict inequality (!==) to prevent type coercion bugs
info correctness loose-inequality
if (value != null) {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (isButton || toString(getToStringValue(value)) !== node.value) {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (initialValue !== node.value) {
Use strict inequality (!==) to prevent type coercion bugs
info correctness loose-inequality
if (defaultValue != null) {
Use strict inequality (!==) to prevent type coercion bugs
info correctness loose-inequality
const checkedOrDefault = checked != null ? checked : defaultChecked;
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
typeof checkedOrDefault !== 'function' &&
Be cautious with typeof; it has limitations (e.g., typeof null === 'object')
info correctness typeof-pitfall
typeof checkedOrDefault !== 'function' &&
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
typeof checkedOrDefault !== 'symbol' &&
Be cautious with typeof; it has limitations (e.g., typeof null === 'object')
info correctness typeof-pitfall
typeof checkedOrDefault !== 'symbol' &&
Use strict inequality (!==) to prevent type coercion bugs
info correctness loose-inequality
if (defaultChecked != null) {
Use strict inequality (!==) to prevent type coercion bugs
info correctness loose-inequality
name != null &&
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
typeof name !== 'function' &&
Be cautious with typeof; it has limitations (e.g., typeof null === 'object')
info correctness typeof-pitfall
typeof name !== 'function' &&
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
typeof name !== 'symbol' &&
Be cautious with typeof; it has limitations (e.g., typeof null === 'object')
info correctness typeof-pitfall
typeof name !== 'symbol' &&
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
typeof name !== 'boolean'
Be cautious with typeof; it has limitations (e.g., typeof null === 'object')
info correctness typeof-pitfall
typeof name !== 'boolean'
Use strict inequality (!==) to prevent type coercion bugs
info correctness loose-inequality
defaultValue != null ? toString(getToStringValue(defaultValue)) : '';
Use strict inequality (!==) to prevent type coercion bugs
info correctness loose-inequality
value != null ? toString(getToStringValue(value)) : defaultValueStr;
Use strict inequality (!==) to prevent type coercion bugs
info correctness loose-inequality
const checkedOrDefault = checked != null ? checked : defaultChecked;
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
typeof checkedOrDefault !== 'function' &&
Be cautious with typeof; it has limitations (e.g., typeof null === 'object')
info correctness typeof-pitfall
typeof checkedOrDefault !== 'function' &&
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
typeof checkedOrDefault !== 'symbol' &&
Be cautious with typeof; it has limitations (e.g., typeof null === 'object')
info correctness typeof-pitfall
typeof checkedOrDefault !== 'symbol' &&
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (node.type !== 'radio' || node.checked) {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (props.type === 'radio' && name != null) {
Use strict inequality (!==) to prevent type coercion bugs
info correctness loose-inequality
if (props.type === 'radio' && name != null) {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (otherNode === rootNode || otherNode.form !== rootNode.form) {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (otherNode.form !== rootNode.form) {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
type !== 'number' ||
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
getActiveElement(node.ownerDocument) !== node
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (node.defaultValue !== toString(value)) {

Get this view in your editor

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