Skip to content

Commit

Permalink
[Fix] prop-types: catch infinite loop
Browse files Browse the repository at this point in the history
  • Loading branch information
ljharb committed Feb 21, 2022
1 parent 0efe262 commit f4915ef
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 20 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -26,6 +26,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
* [`no-array-index-key`]: catch `.toString` and `String()` usage ([#2813][] @RedTn)
* [`function-component-definition`]: do not break on dollar signs ([#3207][] @ljharb)
* [`prefer-stateless-function`]: avoid a crash inside `doctrine` ([#2596][] @ljharb)
* [`prop-types`]: catch infinite loop ([#2861][] @ljharb)

### Changed
* [readme] change [`jsx-runtime`] link from branch to sha ([#3160][] @tatsushitoji)
Expand Down Expand Up @@ -56,6 +57,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
[#3160]: https://github.com/yannickcr/eslint-plugin-react/pull/3160
[#3133]: https://github.com/yannickcr/eslint-plugin-react/pull/3133
[#2921]: https://github.com/yannickcr/eslint-plugin-react/pull/2921
[#2861]: https://github.com/yannickcr/eslint-plugin-react/issues/2861
[#2813]: https://github.com/yannickcr/eslint-plugin-react/pull/2813
[#2753]: https://github.com/yannickcr/eslint-plugin-react/pull/2753
[#2614]: https://github.com/yannickcr/eslint-plugin-react/issues/2614
Expand Down
6 changes: 5 additions & 1 deletion lib/util/propTypes.js
Expand Up @@ -1187,7 +1187,11 @@ module.exports = function propTypesInstructions(context, components, utils) {
if (!component) {
return;
}
markPropTypesAsDeclared(component.node, node.parent.right || node.parent);
try {
markPropTypesAsDeclared(component.node, node.parent.right || node.parent);
} catch (e) {
if (e.constructor !== RangeError) { throw e; }
}
}
},

Expand Down
64 changes: 45 additions & 19 deletions tests/lib/rules/prop-types.js
Expand Up @@ -3753,19 +3753,19 @@ ruleTester.run('prop-types', rule, {
value: string,
error: string,
}
type Form = {
fields: {
[string]: Field,
},
formError: string,
}
type Props = {
bankDetails: Form,
onBankDetailsUpdate: any => void,
}
const Provider = (props:Props) =>
<Input
label={'Account Name'}
Expand Down Expand Up @@ -3804,7 +3804,7 @@ ruleTester.run('prop-types', rule, {
const {bar} = this.state;
console.log(bar);
}
render() {
return null;
}
Expand All @@ -3817,10 +3817,10 @@ ruleTester.run('prop-types', rule, {
const getNameDiv = () => {
return <div>{props.name}</div>;
};
return getNameDiv();
};
DisplayName.propTypes = {
name: PropTypes.string.isRequired,
};
Expand All @@ -3832,10 +3832,10 @@ ruleTester.run('prop-types', rule, {
function renderComponent() {
return <div>{props.name}</div>
}
return renderComponent();
}
SomeComponent.propTypes = {
name: PropTypes.string
}
Expand All @@ -3845,29 +3845,29 @@ ruleTester.run('prop-types', rule, {
code: `
import React from 'react';
import { MyType } from './types';
function Component(props: Props): JSX.Element | null {
const { array } = props;
function renderFound(): JSX.Element | null {
const found = array.find(x => x.id === id); // issue here
if (!found) {
return null;
}
return (
<div>{found.id}</div>
);
}
return renderFound();
}
interface Props {
array: MyType[];
}
export default Component;
`,
features: ['types'],
Expand Down Expand Up @@ -3916,9 +3916,9 @@ ruleTester.run('prop-types', rule, {
code: `
import PropTypes from 'prop-types';
import React from 'react';
import { Link } from '..';
const LinkWrapper = ({ primaryLinks }) => (
<>
{primaryLinks.map((x, index) => (
Expand All @@ -3928,17 +3928,43 @@ ruleTester.run('prop-types', rule, {
))}
</>
);
LinkWrapper.propTypes = {
primaryLinks: PropTypes.arrayOf(
PropTypes.shape({
text: PropTypes.string,
})
),
};
export default LinkWrapper;
`,
},
{
code: `
const projectType = PropTypes.shape({
id: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
});
const nodesType = PropTypes.arrayOf(
PropTypes.shape({ project: projectType, children: nodesType }),
);
class ProjectNode extends React.Component {
render() {
return <div />;
}
}
ProjectNode.propTypes = {
project: projectType.isRequired,
nodes: nodesType,
depth: PropTypes.number.isRequired,
setActiveProject: PropTypes.func.isRequired,
activeProject: projectType,
};
`,
}
)),

Expand Down

0 comments on commit f4915ef

Please sign in to comment.