minor adjustment to readme
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / eslint / lib / rules / no-invalid-this.js
1 /**
2  * @fileoverview A rule to disallow `this` keywords outside of classes or class-like objects.
3  * @author Toru Nagashima
4  */
5
6 "use strict";
7
8 //------------------------------------------------------------------------------
9 // Requirements
10 //------------------------------------------------------------------------------
11
12 const astUtils = require("./utils/ast-utils");
13
14 //------------------------------------------------------------------------------
15 // Rule Definition
16 //------------------------------------------------------------------------------
17
18 module.exports = {
19     meta: {
20         type: "suggestion",
21
22         docs: {
23             description: "disallow `this` keywords outside of classes or class-like objects",
24             category: "Best Practices",
25             recommended: false,
26             url: "https://eslint.org/docs/rules/no-invalid-this"
27         },
28
29         schema: [
30             {
31                 type: "object",
32                 properties: {
33                     capIsConstructor: {
34                         type: "boolean",
35                         default: true
36                     }
37                 },
38                 additionalProperties: false
39             }
40         ]
41     },
42
43     create(context) {
44         const options = context.options[0] || {};
45         const capIsConstructor = options.capIsConstructor !== false;
46         const stack = [],
47             sourceCode = context.getSourceCode();
48
49         /**
50          * Gets the current checking context.
51          *
52          * The return value has a flag that whether or not `this` keyword is valid.
53          * The flag is initialized when got at the first time.
54          * @returns {{valid: boolean}}
55          *   an object which has a flag that whether or not `this` keyword is valid.
56          */
57         stack.getCurrent = function() {
58             const current = this[this.length - 1];
59
60             if (!current.init) {
61                 current.init = true;
62                 current.valid = !astUtils.isDefaultThisBinding(
63                     current.node,
64                     sourceCode,
65                     { capIsConstructor }
66                 );
67             }
68             return current;
69         };
70
71         /**
72          * Pushs new checking context into the stack.
73          *
74          * The checking context is not initialized yet.
75          * Because most functions don't have `this` keyword.
76          * When `this` keyword was found, the checking context is initialized.
77          * @param {ASTNode} node A function node that was entered.
78          * @returns {void}
79          */
80         function enterFunction(node) {
81
82             // `this` can be invalid only under strict mode.
83             stack.push({
84                 init: !context.getScope().isStrict,
85                 node,
86                 valid: true
87             });
88         }
89
90         /**
91          * Pops the current checking context from the stack.
92          * @returns {void}
93          */
94         function exitFunction() {
95             stack.pop();
96         }
97
98         return {
99
100             /*
101              * `this` is invalid only under strict mode.
102              * Modules is always strict mode.
103              */
104             Program(node) {
105                 const scope = context.getScope(),
106                     features = context.parserOptions.ecmaFeatures || {};
107
108                 stack.push({
109                     init: true,
110                     node,
111                     valid: !(
112                         scope.isStrict ||
113                         node.sourceType === "module" ||
114                         (features.globalReturn && scope.childScopes[0].isStrict)
115                     )
116                 });
117             },
118
119             "Program:exit"() {
120                 stack.pop();
121             },
122
123             FunctionDeclaration: enterFunction,
124             "FunctionDeclaration:exit": exitFunction,
125             FunctionExpression: enterFunction,
126             "FunctionExpression:exit": exitFunction,
127
128             // Reports if `this` of the current context is invalid.
129             ThisExpression(node) {
130                 const current = stack.getCurrent();
131
132                 if (current && !current.valid) {
133                     context.report({ node, message: "Unexpected 'this'." });
134                 }
135             }
136         };
137     }
138 };