2 * @fileoverview Rule to check for implicit global variables, functions and classes.
8 //------------------------------------------------------------------------------
10 //------------------------------------------------------------------------------
12 /** @type {import('../shared/types').Rule} */
18 description
: "Disallow declarations in the global scope",
20 url
: "https://eslint.org/docs/latest/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;
46 const sourceCode
= context
.sourceCode
;
50 * @param {ASTNode} node Node to report.
51 * @param {string} messageId Id of the message to report.
52 * @param {string|undefined} kind Declaration kind, can be 'var', 'const', 'let', function or class.
55 function report(node
, messageId
, kind
) {
67 const scope
= sourceCode
.getScope(node
);
69 scope
.variables
.forEach(variable
=> {
71 // Only ESLint global variables have the `writable` key.
72 const isReadonlyEslintGlobalVariable
= variable
.writeable
=== false;
73 const isWritableEslintGlobalVariable
= variable
.writeable
=== true;
75 if (isWritableEslintGlobalVariable
) {
77 // Everything is allowed with writable ESLint global variables.
81 // Variables exported by "exported" block comments
82 if (variable
.eslintExported
) {
86 variable
.defs
.forEach(def
=> {
87 const defNode
= def
.node
;
89 if (def
.type
=== "FunctionName" || (def
.type
=== "Variable" && def
.parent
.kind
=== "var")) {
90 if (isReadonlyEslintGlobalVariable
) {
91 report(defNode
, "redeclarationOfReadonlyGlobal");
95 "globalNonLexicalBinding",
96 def
.type
=== "FunctionName" ? "function" : `'${def.parent.kind}'`
101 if (checkLexicalBindings
) {
102 if (def
.type
=== "ClassName" ||
103 (def
.type
=== "Variable" && (def
.parent
.kind
=== "let" || def
.parent
.kind
=== "const"))) {
104 if (isReadonlyEslintGlobalVariable
) {
105 report(defNode
, "redeclarationOfReadonlyGlobal");
109 "globalLexicalBinding",
110 def
.type
=== "ClassName" ? "class" : `'${def.parent.kind}'`
118 // Undeclared assigned variables.
119 scope
.implicit
.variables
.forEach(variable
=> {
120 const scopeVariable
= scope
.set.get(variable
.name
);
125 // ESLint global variable
126 if (scopeVariable
.writeable
) {
129 messageId
= "assignmentToReadonlyGlobal";
133 // Reference to an unknown variable, possible global leak.
134 messageId
= "globalVariableLeak";
137 // def.node is an AssignmentExpression, ForInStatement or ForOfStatement.
138 variable
.defs
.forEach(def
=> {
139 report(def
.node
, messageId
);