From 5cb2993f7397e1de8bd4b53069a436c67f4096df Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Wed, 14 Feb 2024 18:14:04 +0000 Subject: [PATCH] Remove JSX propTypes checks --- packages/react-art/npm/Circle.js | 5 - packages/react-art/npm/Rectangle.js | 11 -- packages/react-art/npm/Wedge.js | 8 - .../react-art/src/__tests__/ReactART-test.js | 39 ---- .../__tests__/ReactFunctionComponent-test.js | 6 +- .../src/__tests__/ReactElementClone-test.js | 37 ---- .../ReactElementValidator-test.internal.js | 140 +------------- .../ReactJSXElementValidator-test.js | 180 +----------------- packages/react/src/jsx/ReactJSXElement.js | 64 ------- packages/shared/checkPropTypes.js | 108 ----------- 10 files changed, 12 insertions(+), 586 deletions(-) delete mode 100644 packages/shared/checkPropTypes.js diff --git a/packages/react-art/npm/Circle.js b/packages/react-art/npm/Circle.js index 06bbf3d836ead..e27b473dcb7cf 100644 --- a/packages/react-art/npm/Circle.js +++ b/packages/react-art/npm/Circle.js @@ -18,7 +18,6 @@ 'use strict'; var assign = Object.assign; -var PropTypes = require('prop-types'); var React = require('react'); var ReactART = require('react-art'); @@ -34,10 +33,6 @@ var Shape = ReactART.Shape; var Circle = createReactClass({ displayName: 'Circle', - propTypes: { - radius: PropTypes.number.isRequired, - }, - render: function render() { var radius = this.props.radius; diff --git a/packages/react-art/npm/Rectangle.js b/packages/react-art/npm/Rectangle.js index ae85ccba393c4..c71eeaf06d09d 100644 --- a/packages/react-art/npm/Rectangle.js +++ b/packages/react-art/npm/Rectangle.js @@ -25,7 +25,6 @@ 'use strict'; var assign = Object.assign; -var PropTypes = require('prop-types'); var React = require('react'); var ReactART = require('react-art'); @@ -41,16 +40,6 @@ var Path = ReactART.Path; var Rectangle = createReactClass({ displayName: 'Rectangle', - propTypes: { - width: PropTypes.number.isRequired, - height: PropTypes.number.isRequired, - radius: PropTypes.number, - radiusTopLeft: PropTypes.number, - radiusTopRight: PropTypes.number, - radiusBottomRight: PropTypes.number, - radiusBottomLeft: PropTypes.number, - }, - render: function render() { var width = this.props.width; var height = this.props.height; diff --git a/packages/react-art/npm/Wedge.js b/packages/react-art/npm/Wedge.js index e1323e4ae44b9..333cd22834185 100644 --- a/packages/react-art/npm/Wedge.js +++ b/packages/react-art/npm/Wedge.js @@ -21,7 +21,6 @@ 'use strict'; var assign = Object.assign; -var PropTypes = require('prop-types'); var React = require('react'); var ReactART = require('react-art'); @@ -37,13 +36,6 @@ var Path = ReactART.Path; var Wedge = createReactClass({ displayName: 'Wedge', - propTypes: { - outerRadius: PropTypes.number.isRequired, - startAngle: PropTypes.number.isRequired, - endAngle: PropTypes.number.isRequired, - innerRadius: PropTypes.number, - }, - circleRadians: Math.PI * 2, radiansPerDegree: Math.PI / 180, diff --git a/packages/react-art/src/__tests__/ReactART-test.js b/packages/react-art/src/__tests__/ReactART-test.js index b59af8ee02b9d..26ec23da95e16 100644 --- a/packages/react-art/src/__tests__/ReactART-test.js +++ b/packages/react-art/src/__tests__/ReactART-test.js @@ -456,18 +456,6 @@ describe('ReactARTComponents', () => { expect(circle.toJSON()).toMatchSnapshot(); }); - it('should warn if radius is missing on a Circle component', () => { - expect(() => - ReactTestRenderer.create( - , - ), - ).toErrorDev( - 'Warning: Failed prop type: The prop `radius` is marked as required in `Circle`, ' + - 'but its value is `undefined`.' + - '\n in Circle (at **)', - ); - }); - it('should generate a with props for drawing the Rectangle', () => { const rectangle = ReactTestRenderer.create( , @@ -529,19 +517,6 @@ describe('ReactARTComponents', () => { expect(rectangle.toJSON()).toMatchSnapshot(); }); - it('should warn if width/height is missing on a Rectangle component', () => { - expect(() => - ReactTestRenderer.create(), - ).toErrorDev([ - 'Warning: Failed prop type: The prop `width` is marked as required in `Rectangle`, ' + - 'but its value is `undefined`.' + - '\n in Rectangle (at **)', - 'Warning: Failed prop type: The prop `height` is marked as required in `Rectangle`, ' + - 'but its value is `undefined`.' + - '\n in Rectangle (at **)', - ]); - }); - it('should generate a with props for drawing the Wedge', () => { const wedge = ReactTestRenderer.create( , @@ -555,18 +530,4 @@ describe('ReactARTComponents', () => { ); expect(wedge.toJSON()).toBeNull(); }); - - it('should warn if outerRadius/startAngle/endAngle is missing on a Wedge component', () => { - expect(() => ReactTestRenderer.create()).toErrorDev([ - 'Warning: Failed prop type: The prop `outerRadius` is marked as required in `Wedge`, ' + - 'but its value is `undefined`.' + - '\n in Wedge (at **)', - 'Warning: Failed prop type: The prop `startAngle` is marked as required in `Wedge`, ' + - 'but its value is `undefined`.' + - '\n in Wedge (at **)', - 'Warning: Failed prop type: The prop `endAngle` is marked as required in `Wedge`, ' + - 'but its value is `undefined`.' + - '\n in Wedge (at **)', - ]); - }); }); diff --git a/packages/react-dom/src/__tests__/ReactFunctionComponent-test.js b/packages/react-dom/src/__tests__/ReactFunctionComponent-test.js index 2d04c4af90937..735d19d0f144e 100644 --- a/packages/react-dom/src/__tests__/ReactFunctionComponent-test.js +++ b/packages/react-dom/src/__tests__/ReactFunctionComponent-test.js @@ -382,18 +382,14 @@ describe('ReactFunctionComponent', () => { // TODO: change this test after we deprecate default props support // for function components - it('should support default props and prop types', () => { + it('should support default props', () => { function Child(props) { return
{props.test}
; } Child.defaultProps = {test: 2}; - Child.propTypes = {test: PropTypes.string}; expect(() => ReactTestUtils.renderIntoDocument()).toErrorDev([ 'Warning: Child: Support for defaultProps will be removed from function components in a future major release. Use JavaScript default parameters instead.', - 'Warning: Failed prop type: Invalid prop `test` of type `number` ' + - 'supplied to `Child`, expected `string`.\n' + - ' in Child (at **)', ]); }); diff --git a/packages/react/src/__tests__/ReactElementClone-test.js b/packages/react/src/__tests__/ReactElementClone-test.js index 053341013a6ed..be3541b32ab57 100644 --- a/packages/react/src/__tests__/ReactElementClone-test.js +++ b/packages/react/src/__tests__/ReactElementClone-test.js @@ -10,7 +10,6 @@ 'use strict'; let act; -let PropTypes; let React; let ReactDOMClient; @@ -20,7 +19,6 @@ describe('ReactElementClone', () => { beforeEach(() => { act = require('internal-test-utils').act; - PropTypes = require('prop-types'); React = require('react'); ReactDOMClient = require('react-dom/client'); @@ -329,41 +327,6 @@ describe('ReactElementClone', () => { React.cloneElement(
, null, [{}, {}]); }); - it('should check declared prop types after clone', async () => { - class Component extends React.Component { - static propTypes = { - color: PropTypes.string.isRequired, - }; - render() { - return React.createElement('div', null, 'My color is ' + this.color); - } - } - class Parent extends React.Component { - render() { - return React.cloneElement(this.props.child, {color: 123}); - } - } - class GrandParent extends React.Component { - render() { - return React.createElement(Parent, { - child: React.createElement(Component, {color: 'red'}), - }); - } - } - const root = ReactDOMClient.createRoot(document.createElement('div')); - await expect( - async () => - await act(() => root.render(React.createElement(GrandParent))), - ).toErrorDev( - 'Warning: Failed prop type: ' + - 'Invalid prop `color` of type `number` supplied to `Component`, ' + - 'expected `string`.\n' + - ' in Component (at **)\n' + - ' in Parent (at **)\n' + - ' in GrandParent', - ); - }); - it('should ignore key and ref warning getters', () => { const elementA = React.createElement('div'); const elementB = React.cloneElement(elementA, elementA.props); diff --git a/packages/react/src/__tests__/ReactElementValidator-test.internal.js b/packages/react/src/__tests__/ReactElementValidator-test.internal.js index c32ddd3b3fcbd..3bfded6d6d824 100644 --- a/packages/react/src/__tests__/ReactElementValidator-test.internal.js +++ b/packages/react/src/__tests__/ReactElementValidator-test.internal.js @@ -15,7 +15,6 @@ // that do use JSX syntax. We should port them to React.createElement, and also // confirm there's a corresponding test that uses JSX syntax. -let PropTypes; let React; let ReactDOMClient; let act; @@ -28,7 +27,6 @@ describe('ReactElementValidator', () => { beforeEach(() => { jest.resetModules(); - PropTypes = require('prop-types'); ReactFeatureFlags = require('shared/ReactFeatureFlags'); ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false; React = require('react'); @@ -221,26 +219,19 @@ describe('ReactElementValidator', () => { React.createElement(ComponentClass, null, [{}, {}]); }); - it('should give context for PropType errors in nested components.', async () => { - // In this test, we're making sure that if a proptype error is found in a - // component, we give a small hint as to which parent instantiated that - // component as per warnings about key usage in ReactElementValidator. - function MyComp(props) { - return React.createElement('div', null, 'My color is ' + props.color); + it('should give context for errors in nested components.', async () => { + function MyComp() { + return [React.createElement('div')]; } - MyComp.propTypes = { - color: PropTypes.string, - }; function ParentComp() { - return React.createElement(MyComp, {color: 123}); + return React.createElement(MyComp); } await expect(async () => { const root = ReactDOMClient.createRoot(document.createElement('div')); await act(() => root.render(React.createElement(ParentComp))); }).toErrorDev( - 'Warning: Failed prop type: ' + - 'Invalid prop `color` of type `number` supplied to `MyComp`, ' + - 'expected `string`.\n' + + 'Each child in a list should have a unique "key" prop. ' + + 'See https://reactjs.org/link/warning-keys for more information.\n' + ' in MyComp (at **)\n' + ' in ParentComp (at **)', ); @@ -328,125 +319,6 @@ describe('ReactElementValidator', () => { ]); }); - it('should check default prop values', async () => { - class Component extends React.Component { - static propTypes = {prop: PropTypes.string.isRequired}; - static defaultProps = {prop: null}; - render() { - return React.createElement('span', null, this.props.prop); - } - } - - await expect(async () => { - const root = ReactDOMClient.createRoot(document.createElement('div')); - await act(() => root.render(React.createElement(Component))); - }).toErrorDev( - 'Warning: Failed prop type: The prop `prop` is marked as required in ' + - '`Component`, but its value is `null`.\n' + - ' in Component', - ); - }); - - it('should not check the default for explicit null', async () => { - class Component extends React.Component { - static propTypes = {prop: PropTypes.string.isRequired}; - static defaultProps = {prop: 'text'}; - render() { - return React.createElement('span', null, this.props.prop); - } - } - - await expect(async () => { - const root = ReactDOMClient.createRoot(document.createElement('div')); - await act(() => - root.render(React.createElement(Component, {prop: null})), - ); - }).toErrorDev( - 'Warning: Failed prop type: The prop `prop` is marked as required in ' + - '`Component`, but its value is `null`.\n' + - ' in Component', - ); - }); - - it('should check declared prop types', async () => { - class Component extends React.Component { - static propTypes = { - prop: PropTypes.string.isRequired, - }; - render() { - return React.createElement('span', null, this.props.prop); - } - } - - const root = ReactDOMClient.createRoot(document.createElement('div')); - await expect(async () => { - await act(() => root.render(React.createElement(Component))); - await act(() => root.render(React.createElement(Component, {prop: 42}))); - }).toErrorDev([ - 'Warning: Failed prop type: ' + - 'The prop `prop` is marked as required in `Component`, but its value ' + - 'is `undefined`.\n' + - ' in Component', - 'Warning: Failed prop type: ' + - 'Invalid prop `prop` of type `number` supplied to ' + - '`Component`, expected `string`.\n' + - ' in Component', - ]); - - // Should not error for strings - await act(() => - root.render(React.createElement(Component, {prop: 'string'})), - ); - }); - - it('should warn if a PropType creator is used as a PropType', async () => { - class Component extends React.Component { - static propTypes = { - myProp: PropTypes.shape, - }; - render() { - return React.createElement('span', null, this.props.myProp.value); - } - } - - await expect(async () => { - const root = ReactDOMClient.createRoot(document.createElement('div')); - await act(() => - root.render(React.createElement(Component, {myProp: {value: 'hi'}})), - ); - }).toErrorDev( - 'Warning: Component: type specification of prop `myProp` is invalid; ' + - 'the type checker function must return `null` or an `Error` but ' + - 'returned a function. You may have forgotten to pass an argument to ' + - 'the type checker creator (arrayOf, instanceOf, objectOf, oneOf, ' + - 'oneOfType, and shape all require an argument).', - ); - }); - - it('should warn if component declares PropTypes instead of propTypes', async () => { - class MisspelledPropTypesComponent extends React.Component { - static PropTypes = { - prop: PropTypes.string, - }; - render() { - return React.createElement('span', null, this.props.prop); - } - } - - await expect(async () => { - const root = ReactDOMClient.createRoot(document.createElement('div')); - await act(() => - root.render( - React.createElement(MisspelledPropTypesComponent, {prop: 'Hi'}), - ), - ); - }).toErrorDev( - 'Warning: Component MisspelledPropTypesComponent declared `PropTypes` ' + - 'instead of `propTypes`. Did you misspell the property assignment?', - {withoutStack: true}, - ); - }); - it('warns for fragments with illegal attributes', async () => { class Foo extends React.Component { render() { diff --git a/packages/react/src/__tests__/ReactJSXElementValidator-test.js b/packages/react/src/__tests__/ReactJSXElementValidator-test.js index 53b200462385b..ee5104586e51b 100644 --- a/packages/react/src/__tests__/ReactJSXElementValidator-test.js +++ b/packages/react/src/__tests__/ReactJSXElementValidator-test.js @@ -12,11 +12,7 @@ // TODO: All these warnings should become static errors using Flow instead // of dynamic errors when using JSX with Flow. let React; -let ReactDOM; -let ReactDOMClient; let ReactTestUtils; -let PropTypes; -let act; describe('ReactJSXElementValidator', () => { let Component; @@ -25,12 +21,8 @@ describe('ReactJSXElementValidator', () => { beforeEach(() => { jest.resetModules(); - PropTypes = require('prop-types'); React = require('react'); - ReactDOM = require('react-dom'); - ReactDOMClient = require('react-dom/client'); ReactTestUtils = require('react-dom/test-utils'); - act = require('internal-test-utils').act; Component = class extends React.Component { render() { @@ -44,7 +36,6 @@ describe('ReactJSXElementValidator', () => { } }; RequiredPropComponent.displayName = 'RequiredPropComponent'; - RequiredPropComponent.propTypes = {prop: PropTypes.string.isRequired}; }); it('warns for keys for arrays of elements in children position', () => { @@ -150,70 +141,25 @@ describe('ReactJSXElementValidator', () => { void ({[{}, {}]}); }); - it('should give context for PropType errors in nested components.', () => { - // In this test, we're making sure that if a proptype error is found in a - // component, we give a small hint as to which parent instantiated that - // component as per warnings about key usage in ReactElementValidator. + it('should give context for errors in nested components.', () => { class MyComp extends React.Component { render() { - return
My color is {this.color}
; + return [
]; } } - MyComp.propTypes = { - color: PropTypes.string, - }; class ParentComp extends React.Component { render() { - return ; + return ; } } expect(() => ReactTestUtils.renderIntoDocument()).toErrorDev( - 'Warning: Failed prop type: ' + - 'Invalid prop `color` of type `number` supplied to `MyComp`, ' + - 'expected `string`.\n' + + 'Each child in a list should have a unique "key" prop. ' + + 'See https://reactjs.org/link/warning-keys for more information.\n' + ' in MyComp (at **)\n' + ' in ParentComp (at **)', ); }); - it('should update component stack after receiving next element', async () => { - function MyComp() { - return null; - } - MyComp.propTypes = { - color: PropTypes.string, - }; - function MiddleComp(props) { - return ; - } - function ParentComp(props) { - if (props.warn) { - // This element has a source thanks to JSX. - return ; - } - // This element has no source. - return React.createElement(MiddleComp, {color: 'blue'}); - } - - const container = document.createElement('div'); - const root = ReactDOMClient.createRoot(container); - await act(() => { - root.render(); - }); - expect(() => - ReactDOM.flushSync(() => { - root.render(); - }), - ).toErrorDev( - 'Warning: Failed prop type: ' + - 'Invalid prop `color` of type `number` supplied to `MyComp`, ' + - 'expected `string`.\n' + - ' in MyComp (at **)\n' + - ' in MiddleComp (at **)\n' + - ' in ParentComp (at **)', - ); - }); - it('gives a helpful error when passing null, undefined, or boolean', () => { const Undefined = undefined; const Null = null; @@ -246,122 +192,6 @@ describe('ReactJSXElementValidator', () => { void (
); }); - it('should check default prop values', () => { - RequiredPropComponent.defaultProps = {prop: null}; - - expect(() => - ReactTestUtils.renderIntoDocument(), - ).toErrorDev( - 'Warning: Failed prop type: The prop `prop` is marked as required in ' + - '`RequiredPropComponent`, but its value is `null`.\n' + - ' in RequiredPropComponent (at **)', - ); - }); - - it('should not check the default for explicit null', () => { - expect(() => - ReactTestUtils.renderIntoDocument(), - ).toErrorDev( - 'Warning: Failed prop type: The prop `prop` is marked as required in ' + - '`RequiredPropComponent`, but its value is `null`.\n' + - ' in RequiredPropComponent (at **)', - ); - }); - - it('should check declared prop types', () => { - expect(() => - ReactTestUtils.renderIntoDocument(), - ).toErrorDev( - 'Warning: Failed prop type: ' + - 'The prop `prop` is marked as required in `RequiredPropComponent`, but ' + - 'its value is `undefined`.\n' + - ' in RequiredPropComponent (at **)', - ); - expect(() => - ReactTestUtils.renderIntoDocument(), - ).toErrorDev( - 'Warning: Failed prop type: ' + - 'Invalid prop `prop` of type `number` supplied to ' + - '`RequiredPropComponent`, expected `string`.\n' + - ' in RequiredPropComponent (at **)', - ); - - // Should not error for strings - ReactTestUtils.renderIntoDocument(); - }); - - it('should warn on invalid prop types', () => { - // Since there is no prevalidation step for ES6 classes, there is no hook - // for us to issue a warning earlier than element creation when the error - // actually occurs. Since this step is skipped in production, we should just - // warn instead of throwing for this case. - class NullPropTypeComponent extends React.Component { - render() { - return {this.props.prop}; - } - } - NullPropTypeComponent.propTypes = { - prop: null, - }; - expect(() => - ReactTestUtils.renderIntoDocument(), - ).toErrorDev( - 'NullPropTypeComponent: prop type `prop` is invalid; it must be a ' + - 'function, usually from the `prop-types` package,', - ); - }); - - // @gate !disableLegacyContext || !__DEV__ - it('should not warn on invalid context types', () => { - class NullContextTypeComponent extends React.Component { - render() { - return {this.props.prop}; - } - } - NullContextTypeComponent.contextTypes = { - prop: null, - }; - ReactTestUtils.renderIntoDocument(); - }); - - it('should warn if getDefaultProps is specified on the class', () => { - class GetDefaultPropsComponent extends React.Component { - render() { - return {this.props.prop}; - } - } - GetDefaultPropsComponent.getDefaultProps = () => ({ - prop: 'foo', - }); - expect(() => - ReactTestUtils.renderIntoDocument(), - ).toErrorDev( - 'getDefaultProps is only used on classic React.createClass definitions.' + - ' Use a static property named `defaultProps` instead.', - {withoutStack: true}, - ); - }); - - it('should warn if component declares PropTypes instead of propTypes', () => { - class MisspelledPropTypesComponent extends React.Component { - render() { - return {this.props.prop}; - } - } - MisspelledPropTypesComponent.PropTypes = { - prop: PropTypes.string, - }; - expect(() => - ReactTestUtils.renderIntoDocument( - , - ), - ).toErrorDev( - 'Warning: Component MisspelledPropTypesComponent declared `PropTypes` ' + - 'instead of `propTypes`. Did you misspell the property assignment?', - {withoutStack: true}, - ); - }); - it('warns for fragments with illegal attributes', () => { class Foo extends React.Component { render() { diff --git a/packages/react/src/jsx/ReactJSXElement.js b/packages/react/src/jsx/ReactJSXElement.js index 4e546963292a3..d37f871a58695 100644 --- a/packages/react/src/jsx/ReactJSXElement.js +++ b/packages/react/src/jsx/ReactJSXElement.js @@ -12,15 +12,12 @@ import assign from 'shared/assign'; import { getIteratorFn, REACT_ELEMENT_TYPE, - REACT_FORWARD_REF_TYPE, - REACT_MEMO_TYPE, REACT_FRAGMENT_TYPE, } from 'shared/ReactSymbols'; import {checkKeyStringCoercion} from 'shared/CheckStringCoercion'; import isValidElementType from 'shared/isValidElementType'; import isArray from 'shared/isArray'; import {describeUnknownElementTypeFrameInDEV} from 'shared/ReactComponentStackFrame'; -import checkPropTypes from 'shared/checkPropTypes'; const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; const ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; @@ -505,8 +502,6 @@ export function jsxDEV(type, config, maybeKey, isStaticChildren, source, self) { if (type === REACT_FRAGMENT_TYPE) { validateFragmentProps(element); - } else { - validatePropTypes(element); } return element; @@ -678,8 +673,6 @@ export function createElement(type, config, children) { if (type === REACT_FRAGMENT_TYPE) { validateFragmentProps(element); - } else { - validatePropTypes(element); } return element; @@ -833,7 +826,6 @@ export function cloneElement(element, config, children) { for (let i = 2; i < arguments.length; i++) { validateChildKeys(arguments[i], clonedElement.type); } - validatePropTypes(clonedElement); return clonedElement; } @@ -1039,59 +1031,3 @@ function validateFragmentProps(fragment) { } } } - -let propTypesMisspellWarningShown = false; - -/** - * Given an element, validate that its props follow the propTypes definition, - * provided by the type. - * - * @param {ReactElement} element - */ -function validatePropTypes(element) { - if (__DEV__) { - const type = element.type; - if (type === null || type === undefined || typeof type === 'string') { - return; - } - if (type.$$typeof === REACT_CLIENT_REFERENCE) { - return; - } - let propTypes; - if (typeof type === 'function') { - propTypes = type.propTypes; - } else if ( - typeof type === 'object' && - (type.$$typeof === REACT_FORWARD_REF_TYPE || - // Note: Memo only checks outer props here. - // Inner props are checked in the reconciler. - type.$$typeof === REACT_MEMO_TYPE) - ) { - propTypes = type.propTypes; - } else { - return; - } - if (propTypes) { - // Intentionally inside to avoid triggering lazy initializers: - const name = getComponentNameFromType(type); - checkPropTypes(propTypes, element.props, 'prop', name, element); - } else if (type.PropTypes !== undefined && !propTypesMisspellWarningShown) { - propTypesMisspellWarningShown = true; - // Intentionally inside to avoid triggering lazy initializers: - const name = getComponentNameFromType(type); - console.error( - 'Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?', - name || 'Unknown', - ); - } - if ( - typeof type.getDefaultProps === 'function' && - !type.getDefaultProps.isReactClassApproved - ) { - console.error( - 'getDefaultProps is only used on classic React.createClass ' + - 'definitions. Use a static property named `defaultProps` instead.', - ); - } - } -} diff --git a/packages/shared/checkPropTypes.js b/packages/shared/checkPropTypes.js deleted file mode 100644 index 0b9582b236284..0000000000000 --- a/packages/shared/checkPropTypes.js +++ /dev/null @@ -1,108 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -const loggedTypeFailures: {[string]: boolean} = {}; - -import {describeUnknownElementTypeFrameInDEV} from 'shared/ReactComponentStackFrame'; - -import ReactSharedInternals from 'shared/ReactSharedInternals'; -import hasOwnProperty from 'shared/hasOwnProperty'; - -const ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; - -function setCurrentlyValidatingElement(element: any) { - if (__DEV__) { - if (element) { - const owner = element._owner; - const stack = describeUnknownElementTypeFrameInDEV( - element.type, - owner ? owner.type : null, - ); - ReactDebugCurrentFrame.setExtraStackFrame(stack); - } else { - ReactDebugCurrentFrame.setExtraStackFrame(null); - } - } -} - -export default function checkPropTypes( - typeSpecs: Object, - values: Object, - location: string, - componentName: ?string, - element?: any, -): void { - if (__DEV__) { - // $FlowFixMe[incompatible-use] This is okay but Flow doesn't know it. - const has = Function.call.bind(hasOwnProperty); - for (const typeSpecName in typeSpecs) { - if (has(typeSpecs, typeSpecName)) { - let error; - // Prop type validation may throw. In case they do, we don't want to - // fail the render phase where it didn't fail before. So we log it. - // After these have been cleaned up, we'll let them throw. - try { - // This is intentionally an invariant that gets caught. It's the same - // behavior as without this statement except with a better message. - if (typeof typeSpecs[typeSpecName] !== 'function') { - // eslint-disable-next-line react-internal/prod-error-codes - const err = Error( - (componentName || 'React class') + - ': ' + - location + - ' type `' + - typeSpecName + - '` is invalid; ' + - 'it must be a function, usually from the `prop-types` package, but received `' + - typeof typeSpecs[typeSpecName] + - '`.' + - 'This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.', - ); - err.name = 'Invariant Violation'; - throw err; - } - error = typeSpecs[typeSpecName]( - values, - typeSpecName, - componentName, - location, - null, - 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED', - ); - } catch (ex) { - error = ex; - } - if (error && !(error instanceof Error)) { - setCurrentlyValidatingElement(element); - console.error( - '%s: type specification of %s' + - ' `%s` is invalid; the type checker ' + - 'function must return `null` or an `Error` but returned a %s. ' + - 'You may have forgotten to pass an argument to the type checker ' + - 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + - 'shape all require an argument).', - componentName || 'React class', - location, - typeSpecName, - typeof error, - ); - setCurrentlyValidatingElement(null); - } - if (error instanceof Error && !(error.message in loggedTypeFailures)) { - // Only monitor this failure once because there tends to be a lot of the - // same error. - loggedTypeFailures[error.message] = true; - setCurrentlyValidatingElement(element); - console.error('Failed %s type: %s', location, error.message); - setCurrentlyValidatingElement(null); - } - } - } - } -}