2 * @fileoverview A rule to disallow `this` keywords outside of classes or class-like objects.
3 * @author Toru Nagashima
8 //------------------------------------------------------------------------------
10 //------------------------------------------------------------------------------
12 const astUtils = require("./utils/ast-utils");
14 //------------------------------------------------------------------------------
16 //------------------------------------------------------------------------------
23 description: "disallow `this` keywords outside of classes or class-like objects",
24 category: "Best Practices",
26 url: "https://eslint.org/docs/rules/no-invalid-this"
38 additionalProperties: false
43 unexpectedThis: "Unexpected 'this'."
48 const options = context.options[0] || {};
49 const capIsConstructor = options.capIsConstructor !== false;
51 sourceCode = context.getSourceCode();
54 * Gets the current checking context.
56 * The return value has a flag that whether or not `this` keyword is valid.
57 * The flag is initialized when got at the first time.
58 * @returns {{valid: boolean}}
59 * an object which has a flag that whether or not `this` keyword is valid.
61 stack.getCurrent = function() {
62 const current = this[this.length - 1];
66 current.valid = !astUtils.isDefaultThisBinding(
76 * Pushs new checking context into the stack.
78 * The checking context is not initialized yet.
79 * Because most functions don't have `this` keyword.
80 * When `this` keyword was found, the checking context is initialized.
81 * @param {ASTNode} node A function node that was entered.
84 function enterFunction(node) {
86 // `this` can be invalid only under strict mode.
88 init: !context.getScope().isStrict,
95 * Pops the current checking context from the stack.
98 function exitFunction() {
105 * `this` is invalid only under strict mode.
106 * Modules is always strict mode.
109 const scope = context.getScope(),
110 features = context.parserOptions.ecmaFeatures || {};
117 node.sourceType === "module" ||
118 (features.globalReturn && scope.childScopes[0].isStrict)
127 FunctionDeclaration: enterFunction,
128 "FunctionDeclaration:exit": exitFunction,
129 FunctionExpression: enterFunction,
130 "FunctionExpression:exit": exitFunction,
132 // Reports if `this` of the current context is invalid.
133 ThisExpression(node) {
134 const current = stack.getCurrent();
136 if (current && !current.valid) {
139 messageId: "unexpectedThis"