Skip to content

Commit

Permalink
[Fix] jsx-no-leaked-render: invalid fixes in coerce mode
Browse files Browse the repository at this point in the history
  • Loading branch information
akulsr0 authored and ljharb committed Dec 24, 2022
1 parent 12fe944 commit f350303
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 3 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
* [`jsx-no-leaked-render`]: Don't report errors on empty strings if React >= v18 ([#3488][] @himanshu007-creator)
* [`no-invalid-html-attribute`]: convert autofix to suggestion ([#3474][] @himanshu007-creator @ljharb)
* [`jsx-no-leaked-render`]: fix removing parentheses for conditionals ([#3502][] @akulsr0)
* [`jsx-no-leaked-render`]: invalid fixes in coerce mode ([#3511][] @akulsr0)

### Changed
* [Docs] [`jsx-no-leaked-render`]: Remove mentions of empty strings for React 18 ([#3468][] @karlhorky)
Expand All @@ -28,6 +29,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
* [Docs] [`prefer-exact-props`]: fix example flow syntax ([#3510][] @smackfu)
* [Perf] use `anyOf` instead of `oneOf` (@ljharb @remcohaszing)

[#3511]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3511
[#3510]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3510
[#3504]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3504
[#3502]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3502
Expand Down
15 changes: 15 additions & 0 deletions lib/rules/jsx-no-leaked-render.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,27 @@ function ruleFixer(context, fixStrategy, fixer, reportedNode, leftNode, rightNod
if (isParenthesized(context, node)) {
nodeText = `(${nodeText})`;
}
if (node.parent && node.parent.type === 'ConditionalExpression' && node.parent.consequent.value === false) {
return `${getIsCoerceValidNestedLogicalExpression(node) ? '' : '!'}${nodeText}`;
}
return `${getIsCoerceValidNestedLogicalExpression(node) ? '' : '!!'}${nodeText}`;
}).join(' && ');

if (rightNode.parent && rightNode.parent.type === 'ConditionalExpression' && rightNode.parent.consequent.value === false) {
const consequentVal = rightNode.parent.consequent.raw || rightNode.parent.consequent.name;
const alternateVal = rightNode.parent.alternate.raw || rightNode.parent.alternate.name;
if (rightNode.parent.test && rightNode.parent.test.type === 'LogicalExpression') {
return fixer.replaceText(reportedNode, `${newText} ? ${consequentVal} : ${alternateVal}`);
}
return fixer.replaceText(reportedNode, `${newText} && ${alternateVal}`);
}

if (rightNode.type === 'ConditionalExpression') {
return fixer.replaceText(reportedNode, `${newText} && (${rightSideText})`);
}
if (rightNode.type === 'Literal') {
return null;
}
return fixer.replaceText(reportedNode, `${newText} && ${rightSideText}`);
}

Expand Down
44 changes: 41 additions & 3 deletions tests/lib/rules/jsx-no-leaked-render.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
// Requirements
//------------------------------------------------------------------------------

const semver = require('semver');
const eslintPkg = require('eslint/package.json');
const RuleTester = require('eslint').RuleTester;
const rule = require('../../../lib/rules/jsx-no-leaked-render');

Expand Down Expand Up @@ -193,9 +195,9 @@ ruleTester.run('jsx-no-leaked-render', rule, {
`,
options: [{ validStrategies: ['coerce'] }],
},
]),
]) || [],

invalid: parsers.all([
invalid: parsers.all([].concat(
// Common invalid cases with default options
{
code: `
Expand Down Expand Up @@ -847,5 +849,41 @@ ruleTester.run('jsx-no-leaked-render', rule, {
column: 24,
}],
},
]),
{
code: `
const MyComponent = () => {
return <Something checked={isIndeterminate ? false : isChecked} />
}
`,
output: semver.satisfies(eslintPkg.version, '> 4') ? `
const MyComponent = () => {
return <Something checked={!isIndeterminate && isChecked} />
}
` : null,
options: [{ validStrategies: ['coerce'] }],
errors: [{
message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes',
line: 3,
column: 38,
}],
},
{
code: `
const MyComponent = () => {
return <Something checked={cond && isIndeterminate ? false : isChecked} />
}
`,
output: semver.satisfies(eslintPkg.version, '> 4') ? `
const MyComponent = () => {
return <Something checked={!!cond && !!isIndeterminate ? false : isChecked} />
}
` : null,
options: [{ validStrategies: ['coerce'] }],
errors: [{
message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes',
line: 3,
column: 38,
}],
}
)),
});

0 comments on commit f350303

Please sign in to comment.