1/** 2 * @fileoverview Disallow shadowing of NaN, undefined, and Infinity (ES5 section 15.1.1) 3 * @author Michael Ficarra 4 */ 5"use strict"; 6 7/** 8 * Determines if a variable safely shadows undefined. 9 * This is the case when a variable named `undefined` is never assigned to a value (i.e. it always shares the same value 10 * as the global). 11 * @param {eslintScope.Variable} variable The variable to check 12 * @returns {boolean} true if this variable safely shadows `undefined` 13 */ 14function safelyShadowsUndefined(variable) { 15 return variable.name === "undefined" && 16 variable.references.every(ref => !ref.isWrite()) && 17 variable.defs.every(def => def.node.type === "VariableDeclarator" && def.node.init === null); 18} 19 20//------------------------------------------------------------------------------ 21// Rule Definition 22//------------------------------------------------------------------------------ 23 24module.exports = { 25 meta: { 26 type: "suggestion", 27 28 docs: { 29 description: "disallow identifiers from shadowing restricted names", 30 category: "Variables", 31 recommended: true, 32 url: "https://eslint.org/docs/rules/no-shadow-restricted-names" 33 }, 34 35 schema: [], 36 37 messages: { 38 shadowingRestrictedName: "Shadowing of global property '{{name}}'." 39 } 40 }, 41 42 create(context) { 43 44 45 const RESTRICTED = new Set(["undefined", "NaN", "Infinity", "arguments", "eval"]); 46 47 return { 48 "VariableDeclaration, :function, CatchClause"(node) { 49 for (const variable of context.getDeclaredVariables(node)) { 50 if (variable.defs.length > 0 && RESTRICTED.has(variable.name) && !safelyShadowsUndefined(variable)) { 51 context.report({ 52 node: variable.defs[0].name, 53 messageId: "shadowingRestrictedName", 54 data: { 55 name: variable.name 56 } 57 }); 58 } 59 } 60 } 61 }; 62 63 } 64}; 65