From f3503037bf6b74dffeab2bfa07d085302443c266 Mon Sep 17 00:00:00 2001 From: Akul Srivastava Date: Sat, 24 Dec 2022 23:47:38 +0530 Subject: [PATCH] [Fix] `jsx-no-leaked-render`: invalid fixes in coerce mode --- CHANGELOG.md | 2 ++ lib/rules/jsx-no-leaked-render.js | 15 +++++++++ tests/lib/rules/jsx-no-leaked-render.js | 44 +++++++++++++++++++++++-- 3 files changed, 58 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8aa0a8f864..184f87485f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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) @@ -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 diff --git a/lib/rules/jsx-no-leaked-render.js b/lib/rules/jsx-no-leaked-render.js index dccba5b695..c36042bc1d 100644 --- a/lib/rules/jsx-no-leaked-render.js +++ b/lib/rules/jsx-no-leaked-render.js @@ -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}`); } diff --git a/tests/lib/rules/jsx-no-leaked-render.js b/tests/lib/rules/jsx-no-leaked-render.js index cd9a1f982c..fe9a577003 100644 --- a/tests/lib/rules/jsx-no-leaked-render.js +++ b/tests/lib/rules/jsx-no-leaked-render.js @@ -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'); @@ -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: ` @@ -847,5 +849,41 @@ ruleTester.run('jsx-no-leaked-render', rule, { column: 24, }], }, - ]), + { + code: ` + const MyComponent = () => { + return + } + `, + output: semver.satisfies(eslintPkg.version, '> 4') ? ` + const MyComponent = () => { + return + } + ` : 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 + } + `, + output: semver.satisfies(eslintPkg.version, '> 4') ? ` + const MyComponent = () => { + return + } + ` : null, + options: [{ validStrategies: ['coerce'] }], + errors: [{ + message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes', + line: 3, + column: 38, + }], + } + )), });