2 * @fileoverview Rule to check for implicit global variables, functions and classes.
8 //------------------------------------------------------------------------------
10 //------------------------------------------------------------------------------
17 description: "disallow declarations in the global scope",
18 category: "Best Practices",
20 url: "https://eslint.org/docs/rules/no-implicit-globals"
31 additionalProperties: false
35 globalNonLexicalBinding: "Unexpected {{kind}} declaration in the global scope, wrap in an IIFE for a local variable, assign as global property for a global variable.",
36 globalLexicalBinding: "Unexpected {{kind}} declaration in the global scope, wrap in a block or in an IIFE.",
37 globalVariableLeak: "Global variable leak, declare the variable if it is intended to be local.",
38 assignmentToReadonlyGlobal: "Unexpected assignment to read-only global variable.",
39 redeclarationOfReadonlyGlobal: "Unexpected redeclaration of read-only global variable."
45 const checkLexicalBindings = context.options[0] && context.options[0].lexicalBindings === true;
49 * @param {ASTNode} node Node to report.
50 * @param {string} messageId Id of the message to report.
51 * @param {string|undefined} kind Declaration kind, can be 'var', 'const', 'let', function or class.
54 function report(node, messageId, kind) {
66 const scope = context.getScope();
68 scope.variables.forEach(variable => {
70 // Only ESLint global variables have the `writable` key.
71 const isReadonlyEslintGlobalVariable = variable.writeable === false;
72 const isWritableEslintGlobalVariable = variable.writeable === true;
74 if (isWritableEslintGlobalVariable) {
76 // Everything is allowed with writable ESLint global variables.
80 variable.defs.forEach(def => {
81 const defNode = def.node;
83 if (def.type === "FunctionName" || (def.type === "Variable" && def.parent.kind === "var")) {
84 if (isReadonlyEslintGlobalVariable) {
85 report(defNode, "redeclarationOfReadonlyGlobal");
89 "globalNonLexicalBinding",
90 def.type === "FunctionName" ? "function" : `'${def.parent.kind}'`
95 if (checkLexicalBindings) {
96 if (def.type === "ClassName" ||
97 (def.type === "Variable" && (def.parent.kind === "let" || def.parent.kind === "const"))) {
98 if (isReadonlyEslintGlobalVariable) {
99 report(defNode, "redeclarationOfReadonlyGlobal");
103 "globalLexicalBinding",
104 def.type === "ClassName" ? "class" : `'${def.parent.kind}'`
112 // Undeclared assigned variables.
113 scope.implicit.variables.forEach(variable => {
114 const scopeVariable = scope.set.get(variable.name);
119 // ESLint global variable
120 if (scopeVariable.writeable) {
123 messageId = "assignmentToReadonlyGlobal";
127 // Reference to an unknown variable, possible global leak.
128 messageId = "globalVariableLeak";
131 // def.node is an AssignmentExpression, ForInStatement or ForOfStatement.
132 variable.defs.forEach(def => {
133 report(def.node, messageId);