From 95883def1a74338130f98d33a1d018cd2b11528c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20Beltr=C3=A1n=20Alarc=C3=B3n?= Date: Mon, 25 Apr 2022 12:46:59 +0200 Subject: [PATCH] rename rule to jsx-no-leaked-render --- README.md | 2 +- ...leaked-zero.md => jsx-no-leaked-render.md} | 31 +++++++-- index.js | 2 +- ...leaked-zero.js => jsx-no-leaked-render.js} | 12 ++-- ...leaked-zero.js => jsx-no-leaked-render.js} | 68 +++++++++---------- 5 files changed, 67 insertions(+), 48 deletions(-) rename docs/rules/{jsx-no-leaked-zero.md => jsx-no-leaked-render.md} (81%) rename lib/rules/{jsx-no-leaked-zero.js => jsx-no-leaked-render.js} (88%) rename tests/lib/rules/{jsx-no-leaked-zero.js => jsx-no-leaked-render.js} (81%) diff --git a/README.md b/README.md index 0fcd19c2e0..775686b85b 100644 --- a/README.md +++ b/README.md @@ -202,7 +202,7 @@ Enable the rules that you would like to use. | ✔ | | [react/jsx-no-comment-textnodes](docs/rules/jsx-no-comment-textnodes.md) | Comments inside children section of tag should be placed inside braces | | | | [react/jsx-no-constructed-context-values](docs/rules/jsx-no-constructed-context-values.md) | Prevents JSX context provider values from taking values that will cause needless rerenders. | | ✔ | | [react/jsx-no-duplicate-props](docs/rules/jsx-no-duplicate-props.md) | Enforce no duplicate props | -| | 🔧 | [react/jsx-no-leaked-zero](docs/rules/jsx-no-leaked-zero.md) | Prevent zero from being rendered on numerical condition | +| | 🔧 | [react/jsx-no-leaked-render](docs/rules/jsx-no-leaked-render.md) | Prevent problematic leaked values from being rendered | | | | [react/jsx-no-literals](docs/rules/jsx-no-literals.md) | Prevent using string literals in React component definition | | | | [react/jsx-no-script-url](docs/rules/jsx-no-script-url.md) | Forbid `javascript:` URLs | | ✔ | 🔧 | [react/jsx-no-target-blank](docs/rules/jsx-no-target-blank.md) | Forbid `target="_blank"` attribute without `rel="noreferrer"` | diff --git a/docs/rules/jsx-no-leaked-zero.md b/docs/rules/jsx-no-leaked-render.md similarity index 81% rename from docs/rules/jsx-no-leaked-zero.md rename to docs/rules/jsx-no-leaked-render.md index 8c8a734fbe..8e25d3eb42 100644 --- a/docs/rules/jsx-no-leaked-zero.md +++ b/docs/rules/jsx-no-leaked-render.md @@ -1,14 +1,33 @@ -# Prevent zero from being rendered on numerical condition (react/jsx-no-leaked-zero) +# Prevent problematic leaked values from being rendered (react/jsx-no-leaked-render) -When rendering an element in JSX based on a numerical condition, it might be possible to end up rendering a 0 to the DOM. +Using the `&&` operator to render some element conditionally in JSX can cause unexpected values being rendered, or even crashing the rendering. -The number 0 is a special case for JSX inline conditions, since it's the only falsy expression that it's returned by the render method. ## Rule Details -This rule aims to prevent potential numerical condition from rendering a 0 value to the DOM. Since the rule doesn't know if the condition is based on numbers or something else due to the lack of types, it will report all sorts of conditionals within a JSX expression. +This rule aims to prevent dangerous leaked values from being rendered since they can cause unexpected values reaching the final DOM or even crashing your render method. -TODO: add dangerous cases here +In React, you might end up rendering unexpected values like `0` or `NaN`. In React Native, your render method will crash if you render `0`, `''`, or `NaN`: + +```jsx +const Example = () => { + return ( + <> + {0 && } + {/* React: renders undesired 0 */} + {/* React Native: crashes 💥 */} + + {'' && } + {/* React: renders nothing */} + {/* React Native: crashes 💥 */} + + {NaN && } + {/* React: renders undesired NaN */} + {/* React Native: crashes 💥 */} + + ) +} +``` This can be avoided by: - casting the condition to bool: `{!!someValue && }` @@ -129,7 +148,7 @@ It can be set like: ```json5 { // ... - "react/jsx-no-leaked-zero": [, { "validStrategies": ["ternary", "cast"] }] + "react/jsx-no-leaked-render": [, { "validStrategies": ["ternary", "cast"] }] // ... } ``` diff --git a/index.js b/index.js index 90f292615b..be3c94a992 100644 --- a/index.js +++ b/index.js @@ -38,7 +38,7 @@ const allRules = { 'jsx-no-comment-textnodes': require('./lib/rules/jsx-no-comment-textnodes'), 'jsx-no-constructed-context-values': require('./lib/rules/jsx-no-constructed-context-values'), 'jsx-no-duplicate-props': require('./lib/rules/jsx-no-duplicate-props'), - 'jsx-no-leaked-zero': require('./lib/rules/jsx-no-leaked-zero'), + 'jsx-no-leaked-render': require('./lib/rules/jsx-no-leaked-render'), 'jsx-no-literals': require('./lib/rules/jsx-no-literals'), 'jsx-no-script-url': require('./lib/rules/jsx-no-script-url'), 'jsx-no-target-blank': require('./lib/rules/jsx-no-target-blank'), diff --git a/lib/rules/jsx-no-leaked-zero.js b/lib/rules/jsx-no-leaked-render.js similarity index 88% rename from lib/rules/jsx-no-leaked-zero.js rename to lib/rules/jsx-no-leaked-render.js index 911dc3a711..5321de3079 100644 --- a/lib/rules/jsx-no-leaked-zero.js +++ b/lib/rules/jsx-no-leaked-render.js @@ -1,5 +1,5 @@ /** - * @fileoverview Prevent zero from being rendered on numerical condition + * @fileoverview Prevent problematic leaked values from being rendered * @author Mario Beltrán */ @@ -14,7 +14,7 @@ const isParenthesized = require('../util/ast').isParenthesized; //------------------------------------------------------------------------------ const messages = { - noPotentialNumericEvaluation: 'Potential numeric evaluation resulting in an unintentionally rendered `0`', + noPotentialLeakedRender: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes', }; const CAST_STRATEGY = 'cast'; @@ -27,10 +27,10 @@ const DEFAULT_VALID_STRATEGIES = [TERNARY_STRATEGY, CAST_STRATEGY]; module.exports = { meta: { docs: { - description: 'Prevent zero from being rendered on numerical condition', + description: 'Prevent problematic leaked values from being rendered', category: 'Possible Errors', recommended: false, - url: docsUrl('jsx-no-leaked-zero'), + url: docsUrl('jsx-no-leaked-render'), }, messages, @@ -111,7 +111,7 @@ module.exports = { return; } - report(context, messages.noPotentialNumericEvaluation, 'noPotentialNumericEvaluation', { + report(context, messages.noPotentialLeakedRender, 'noPotentialLeakedRender', { node, fix(fixer) { return ruleFixer(fixer, node, leftSide, node.right); @@ -125,7 +125,7 @@ module.exports = { return; } - report(context, messages.noPotentialNumericEvaluation, 'noPotentialNumericEvaluation', { + report(context, messages.noPotentialLeakedRender, 'noPotentialLeakedRender', { node, fix(fixer) { return ruleFixer(fixer, node, node.test, node.consequent); diff --git a/tests/lib/rules/jsx-no-leaked-zero.js b/tests/lib/rules/jsx-no-leaked-render.js similarity index 81% rename from tests/lib/rules/jsx-no-leaked-zero.js rename to tests/lib/rules/jsx-no-leaked-render.js index c860ebbbaa..53cdb2d95d 100644 --- a/tests/lib/rules/jsx-no-leaked-zero.js +++ b/tests/lib/rules/jsx-no-leaked-render.js @@ -1,5 +1,5 @@ /** - * @fileoverview Prevent zero from being rendered on numerical condition + * @fileoverview Prevent problematic leaked values from being rendered * @author Mario Beltrán */ @@ -10,7 +10,7 @@ //------------------------------------------------------------------------------ const RuleTester = require('eslint').RuleTester; -const rule = require('../../../lib/rules/jsx-no-leaked-zero'); +const rule = require('../../../lib/rules/jsx-no-leaked-render'); const parsers = require('../../helpers/parsers'); @@ -27,7 +27,7 @@ const parserOptions = { //------------------------------------------------------------------------------ const ruleTester = new RuleTester({ parserOptions }); -ruleTester.run('jsx-no-leaked-zero', rule, { +ruleTester.run('jsx-no-leaked-render', rule, { valid: parsers.all([ { code: ` @@ -142,17 +142,17 @@ ruleTester.run('jsx-no-leaked-zero', rule, { `, errors: [ { - message: 'Potential numeric evaluation resulting in an unintentionally rendered `0`', + message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes', line: 5, column: 14, }, { - message: 'Potential numeric evaluation resulting in an unintentionally rendered `0`', + message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes', line: 6, column: 14, }, { - message: 'Potential numeric evaluation resulting in an unintentionally rendered `0`', + message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes', line: 7, column: 14, }, @@ -178,7 +178,7 @@ ruleTester.run('jsx-no-leaked-zero', rule, { } `, errors: [{ - message: 'Potential numeric evaluation resulting in an unintentionally rendered `0`', + message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes', line: 3, column: 24, }], @@ -195,7 +195,7 @@ ruleTester.run('jsx-no-leaked-zero', rule, { } `, errors: [{ - message: 'Potential numeric evaluation resulting in an unintentionally rendered `0`', + message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes', line: 3, column: 24, }], @@ -212,7 +212,7 @@ ruleTester.run('jsx-no-leaked-zero', rule, { } `, errors: [{ - message: 'Potential numeric evaluation resulting in an unintentionally rendered `0`', + message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes', line: 3, column: 24, }], @@ -229,7 +229,7 @@ ruleTester.run('jsx-no-leaked-zero', rule, { } `, errors: [{ - message: 'Potential numeric evaluation resulting in an unintentionally rendered `0`', + message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes', line: 3, column: 24, }], @@ -246,7 +246,7 @@ ruleTester.run('jsx-no-leaked-zero', rule, { } `, errors: [{ - message: 'Potential numeric evaluation resulting in an unintentionally rendered `0`', + message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes', line: 3, column: 24, }], @@ -263,7 +263,7 @@ ruleTester.run('jsx-no-leaked-zero', rule, { } `, errors: [{ - message: 'Potential numeric evaluation resulting in an unintentionally rendered `0`', + message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes', line: 3, column: 24, }], @@ -281,7 +281,7 @@ ruleTester.run('jsx-no-leaked-zero', rule, { `, options: [{ validStrategies: ['cast', 'ternary'] }], errors: [{ - message: 'Potential numeric evaluation resulting in an unintentionally rendered `0`', + message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes', line: 3, column: 24, }], @@ -301,7 +301,7 @@ ruleTester.run('jsx-no-leaked-zero', rule, { `, options: [{ validStrategies: ['ternary'] }], errors: [{ - message: 'Potential numeric evaluation resulting in an unintentionally rendered `0`', + message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes', line: 3, column: 24, }], @@ -319,7 +319,7 @@ ruleTester.run('jsx-no-leaked-zero', rule, { `, options: [{ validStrategies: ['ternary'] }], errors: [{ - message: 'Potential numeric evaluation resulting in an unintentionally rendered `0`', + message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes', line: 3, column: 24, }], @@ -337,7 +337,7 @@ ruleTester.run('jsx-no-leaked-zero', rule, { `, options: [{ validStrategies: ['ternary'] }], errors: [{ - message: 'Potential numeric evaluation resulting in an unintentionally rendered `0`', + message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes', line: 3, column: 24, }], @@ -355,7 +355,7 @@ ruleTester.run('jsx-no-leaked-zero', rule, { `, options: [{ validStrategies: ['ternary'] }], errors: [{ - message: 'Potential numeric evaluation resulting in an unintentionally rendered `0`', + message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes', line: 3, column: 24, }], @@ -373,7 +373,7 @@ ruleTester.run('jsx-no-leaked-zero', rule, { `, options: [{ validStrategies: ['ternary'] }], errors: [{ - message: 'Potential numeric evaluation resulting in an unintentionally rendered `0`', + message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes', line: 3, column: 24, }], @@ -391,7 +391,7 @@ ruleTester.run('jsx-no-leaked-zero', rule, { `, options: [{ validStrategies: ['ternary'] }], errors: [{ - message: 'Potential numeric evaluation resulting in an unintentionally rendered `0`', + message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes', line: 3, column: 24, }], @@ -411,7 +411,7 @@ ruleTester.run('jsx-no-leaked-zero', rule, { `, options: [{ validStrategies: ['ternary'] }], errors: [{ - message: 'Potential numeric evaluation resulting in an unintentionally rendered `0`', + message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes', line: 3, column: 24, }], @@ -429,7 +429,7 @@ ruleTester.run('jsx-no-leaked-zero', rule, { `, options: [{ validStrategies: ['ternary'] }], errors: [{ - message: 'Potential numeric evaluation resulting in an unintentionally rendered `0`', + message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes', line: 3, column: 24, }], @@ -447,7 +447,7 @@ ruleTester.run('jsx-no-leaked-zero', rule, { `, options: [{ validStrategies: ['ternary'] }], errors: [{ - message: 'Potential numeric evaluation resulting in an unintentionally rendered `0`', + message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes', line: 3, column: 24, }], @@ -465,7 +465,7 @@ ruleTester.run('jsx-no-leaked-zero', rule, { `, options: [{ validStrategies: ['ternary'] }], errors: [{ - message: 'Potential numeric evaluation resulting in an unintentionally rendered `0`', + message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes', line: 3, column: 24, }], @@ -483,7 +483,7 @@ ruleTester.run('jsx-no-leaked-zero', rule, { `, options: [{ validStrategies: ['ternary'] }], errors: [{ - message: 'Potential numeric evaluation resulting in an unintentionally rendered `0`', + message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes', line: 3, column: 24, }], @@ -501,7 +501,7 @@ ruleTester.run('jsx-no-leaked-zero', rule, { `, options: [{ validStrategies: ['ternary'] }], errors: [{ - message: 'Potential numeric evaluation resulting in an unintentionally rendered `0`', + message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes', line: 3, column: 24, }], @@ -521,7 +521,7 @@ ruleTester.run('jsx-no-leaked-zero', rule, { `, options: [{ validStrategies: ['cast'] }], errors: [{ - message: 'Potential numeric evaluation resulting in an unintentionally rendered `0`', + message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes', line: 3, column: 24, }], @@ -539,7 +539,7 @@ ruleTester.run('jsx-no-leaked-zero', rule, { `, options: [{ validStrategies: ['cast'] }], errors: [{ - message: 'Potential numeric evaluation resulting in an unintentionally rendered `0`', + message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes', line: 3, column: 24, }], @@ -557,7 +557,7 @@ ruleTester.run('jsx-no-leaked-zero', rule, { `, options: [{ validStrategies: ['cast'] }], errors: [{ - message: 'Potential numeric evaluation resulting in an unintentionally rendered `0`', + message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes', line: 3, column: 24, }], @@ -575,7 +575,7 @@ ruleTester.run('jsx-no-leaked-zero', rule, { `, options: [{ validStrategies: ['cast'] }], errors: [{ - message: 'Potential numeric evaluation resulting in an unintentionally rendered `0`', + message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes', line: 3, column: 24, }], @@ -593,7 +593,7 @@ ruleTester.run('jsx-no-leaked-zero', rule, { `, options: [{ validStrategies: ['cast'] }], errors: [{ - message: 'Potential numeric evaluation resulting in an unintentionally rendered `0`', + message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes', line: 3, column: 24, }], @@ -611,7 +611,7 @@ ruleTester.run('jsx-no-leaked-zero', rule, { `, options: [{ validStrategies: ['cast'] }], errors: [{ - message: 'Potential numeric evaluation resulting in an unintentionally rendered `0`', + message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes', line: 3, column: 24, }], @@ -631,7 +631,7 @@ ruleTester.run('jsx-no-leaked-zero', rule, { `, options: [{ validStrategies: ['cast'] }], errors: [{ - message: 'Potential numeric evaluation resulting in an unintentionally rendered `0`', + message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes', line: 3, column: 24, }], @@ -649,7 +649,7 @@ ruleTester.run('jsx-no-leaked-zero', rule, { `, options: [{ validStrategies: ['cast'] }], errors: [{ - message: 'Potential numeric evaluation resulting in an unintentionally rendered `0`', + message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes', line: 3, column: 24, }], @@ -667,7 +667,7 @@ ruleTester.run('jsx-no-leaked-zero', rule, { `, options: [{ validStrategies: ['cast'] }], errors: [{ - message: 'Potential numeric evaluation resulting in an unintentionally rendered `0`', + message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes', line: 3, column: 24, }],