.gitignore added
[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         messages: {
43             unexpectedThis: "Unexpected 'this'."
44         }
45     },
46
47     create(context) {
48         const options = context.options[0] || {};
49         const capIsConstructor = options.capIsConstructor !== false;
50         const stack = [],
51             sourceCode = context.getSourceCode();
52
53         /**
54          * Gets the current checking context.
55          *
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.
60          */
61         stack.getCurrent = function() {
62             const current = this[this.length - 1];
63
64             if (!current.init) {
65                 current.init = true;
66                 current.valid = !astUtils.isDefaultThisBinding(
67                     current.node,
68                     sourceCode,
69                     { capIsConstructor }
70                 );
71             }
72             return current;
73         };
74
75         /**
76          * Pushs new checking context into the stack.
77          *
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.
82          * @returns {void}
83          */
84         function enterFunction(node) {
85
86             // `this` can be invalid only under strict mode.
87             stack.push({
88                 init: !context.getScope().isStrict,
89                 node,
90                 valid: true
91             });
92         }
93
94         /**
95          * Pops the current checking context from the stack.
96          * @returns {void}
97          */
98         function exitFunction() {
99             stack.pop();
100         }
101
102         return {
103
104             /*
105              * `this` is invalid only under strict mode.
106              * Modules is always strict mode.
107              */
108             Program(node) {
109                 const scope = context.getScope(),
110                     features = context.parserOptions.ecmaFeatures || {};
111
112                 stack.push({
113                     init: true,
114                     node,
115                     valid: !(
116                         scope.isStrict ||
117                         node.sourceType === "module" ||
118                         (features.globalReturn && scope.childScopes[0].isStrict)
119                     )
120                 });
121             },
122
123             "Program:exit"() {
124                 stack.pop();
125             },
126
127             FunctionDeclaration: enterFunction,
128             "FunctionDeclaration:exit": exitFunction,
129             FunctionExpression: enterFunction,
130             "FunctionExpression:exit": exitFunction,
131
132             // Reports if `this` of the current context is invalid.
133             ThisExpression(node) {
134                 const current = stack.getCurrent();
135
136                 if (current && !current.valid) {
137                     context.report({
138                         node,
139                         messageId: "unexpectedThis"
140                     });
141                 }
142             }
143         };
144     }
145 };