1/** 2 * @fileoverview Rule to flag references to the undefined variable. 3 * @author Michael Ficarra 4 */ 5"use strict"; 6 7//------------------------------------------------------------------------------ 8// Rule Definition 9//------------------------------------------------------------------------------ 10 11module.exports = { 12 meta: { 13 type: "suggestion", 14 15 docs: { 16 description: "disallow the use of `undefined` as an identifier", 17 category: "Variables", 18 recommended: false, 19 url: "https://eslint.org/docs/rules/no-undefined" 20 }, 21 22 schema: [], 23 24 messages: { 25 unexpectedUndefined: "Unexpected use of undefined." 26 } 27 }, 28 29 create(context) { 30 31 /** 32 * Report an invalid "undefined" identifier node. 33 * @param {ASTNode} node The node to report. 34 * @returns {void} 35 */ 36 function report(node) { 37 context.report({ 38 node, 39 messageId: "unexpectedUndefined" 40 }); 41 } 42 43 /** 44 * Checks the given scope for references to `undefined` and reports 45 * all references found. 46 * @param {eslint-scope.Scope} scope The scope to check. 47 * @returns {void} 48 */ 49 function checkScope(scope) { 50 const undefinedVar = scope.set.get("undefined"); 51 52 if (!undefinedVar) { 53 return; 54 } 55 56 const references = undefinedVar.references; 57 58 const defs = undefinedVar.defs; 59 60 // Report non-initializing references (those are covered in defs below) 61 references 62 .filter(ref => !ref.init) 63 .forEach(ref => report(ref.identifier)); 64 65 defs.forEach(def => report(def.name)); 66 } 67 68 return { 69 "Program:exit"() { 70 const globalScope = context.getScope(); 71 72 const stack = [globalScope]; 73 74 while (stack.length) { 75 const scope = stack.pop(); 76 77 stack.push(...scope.childScopes); 78 checkScope(scope); 79 } 80 } 81 }; 82 83 } 84}; 85