diff --git a/crates/oxc_linter/src/rules/eslint/no_shadow_restricted_names.rs b/crates/oxc_linter/src/rules/eslint/no_shadow_restricted_names.rs index 2087482ad63e4..252f074993236 100644 --- a/crates/oxc_linter/src/rules/eslint/no_shadow_restricted_names.rs +++ b/crates/oxc_linter/src/rules/eslint/no_shadow_restricted_names.rs @@ -18,12 +18,27 @@ pub struct NoShadowRestrictedNames; declare_oxc_lint!( /// ### What it does /// - /// Disallow redefine the global variables like 'undefined', 'NaN', 'Infinity', 'eval', 'arguments'. + /// Disallows the redefining of global variables such as `undefined`, `NaN`, `Infinity`, `eval` + /// and `arguments`. /// /// ### Why is this bad? /// + /// Value properties of the Global Object `NaN`, `Infinity`, `undefined` as well as the strict + /// mode restricted identifiers `eval` and `arguments` are considered to be restricted names in + /// JavaScript. Defining them to mean something else can have unintended consequences and + /// confuse others reading the code. For example, there’s nothing preventing you from + /// writing: /// - /// ### Example + /// ```javascript + /// var undefined = "foo"; + /// ``` + /// + /// Then any code used within the same scope would not get the global undefined, but rather the + /// local version with a very different meaning. + /// + /// ### Examples + /// + /// Examples of **incorrect** code for this rule: /// ```javascript /// function NaN(){} /// @@ -33,6 +48,28 @@ declare_oxc_lint!( /// /// try {} catch(eval){} /// ``` + /// + /// ```javascript + /// import NaN from "foo"; + /// + /// import { undefined } from "bar"; + /// + /// class Infinity {} + /// ``` + /// + /// Examples of **correct** code for this rule: + /// ```javascript + /// var Object; + /// + /// function f(a, b){} + /// + /// // Exception: `undefined` may be shadowed if the variable is never assigned a value. + /// var undefined; + /// ``` + /// + /// ```javascript + /// import { undefined as undef } from "bar"; + /// ``` NoShadowRestrictedNames, eslint, correctness @@ -97,6 +134,7 @@ fn test() { "parserOptions": { "ecmaVersion": 2019 } })), ), + ("var Object;", None), ("var undefined;", None), ("var undefined;var undefined", None), ( @@ -115,9 +153,13 @@ fn test() { })), ), ("var normal, undefined; var undefined;", None), + (r#"import { undefined as undef } from "bar";"#, None), ]; let fail = vec![ + ("var undefined = 5;", None), + ("function NaN(){}", None), + ("try {} catch(eval){}", None), ("function NaN(NaN) { var NaN; !function NaN(NaN) { try {} catch(NaN) {} }; }", None), ( "function undefined(undefined) { !function undefined(undefined) { try {} catch(undefined) {} }; }", @@ -161,6 +203,9 @@ fn test() { ("class undefined { }", None), ("class foo { undefined(undefined) { } }", None), ("class foo { #undefined(undefined) { } }", None), + ("class Infinity {}", None), + (r#"import { undefined } from "bar";"#, None), + (r#"import NaN from "foo";"#, None), ]; Tester::new(NoShadowRestrictedNames::NAME, NoShadowRestrictedNames::PLUGIN, pass, fail) diff --git a/crates/oxc_linter/src/snapshots/eslint_no_shadow_restricted_names.snap b/crates/oxc_linter/src/snapshots/eslint_no_shadow_restricted_names.snap index 73129bd610d37..3654bc1ddeea8 100644 --- a/crates/oxc_linter/src/snapshots/eslint_no_shadow_restricted_names.snap +++ b/crates/oxc_linter/src/snapshots/eslint_no_shadow_restricted_names.snap @@ -1,6 +1,27 @@ --- source: crates/oxc_linter/src/tester.rs --- + ⚠ eslint(no-shadow-restricted-names): Shadowing of global properties such as 'undefined' is not allowed. + ╭─[no_shadow_restricted_names.tsx:1:5] + 1 │ var undefined = 5; + · ───────── + ╰──── + help: Shadowing of global properties 'undefined'. + + ⚠ eslint(no-shadow-restricted-names): Shadowing of global properties such as 'undefined' is not allowed. + ╭─[no_shadow_restricted_names.tsx:1:10] + 1 │ function NaN(){} + · ─── + ╰──── + help: Shadowing of global properties 'NaN'. + + ⚠ eslint(no-shadow-restricted-names): Shadowing of global properties such as 'undefined' is not allowed. + ╭─[no_shadow_restricted_names.tsx:1:14] + 1 │ try {} catch(eval){} + · ──── + ╰──── + help: Shadowing of global properties 'eval'. + ⚠ eslint(no-shadow-restricted-names): Shadowing of global properties such as 'undefined' is not allowed. ╭─[no_shadow_restricted_names.tsx:1:10] 1 │ function NaN(NaN) { var NaN; !function NaN(NaN) { try {} catch(NaN) {} }; } @@ -315,3 +336,24 @@ source: crates/oxc_linter/src/tester.rs · ───────── ╰──── help: Shadowing of global properties 'undefined'. + + ⚠ eslint(no-shadow-restricted-names): Shadowing of global properties such as 'undefined' is not allowed. + ╭─[no_shadow_restricted_names.tsx:1:7] + 1 │ class Infinity {} + · ──────── + ╰──── + help: Shadowing of global properties 'Infinity'. + + ⚠ eslint(no-shadow-restricted-names): Shadowing of global properties such as 'undefined' is not allowed. + ╭─[no_shadow_restricted_names.tsx:1:10] + 1 │ import { undefined } from "bar"; + · ───────── + ╰──── + help: Shadowing of global properties 'undefined'. + + ⚠ eslint(no-shadow-restricted-names): Shadowing of global properties such as 'undefined' is not allowed. + ╭─[no_shadow_restricted_names.tsx:1:8] + 1 │ import NaN from "foo"; + · ─── + ╰──── + help: Shadowing of global properties 'NaN'.