eslint-plugin-react-web-api 1.52.10-next.0 → 1.52.10-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,744 +1,675 @@
1
- 'use strict';
2
-
3
- var shared = require('@eslint-react/shared');
4
- var AST = require('@eslint-react/ast');
5
- var ER4 = require('@eslint-react/core');
6
- var eff = require('@eslint-react/eff');
7
- var VAR = require('@eslint-react/var');
8
- var utils = require('@typescript-eslint/utils');
9
- var tsPattern = require('ts-pattern');
10
- var types = require('@typescript-eslint/types');
11
-
12
- function _interopNamespace(e) {
13
- if (e && e.__esModule) return e;
14
- var n = Object.create(null);
15
- if (e) {
16
- Object.keys(e).forEach(function (k) {
17
- if (k !== 'default') {
18
- var d = Object.getOwnPropertyDescriptor(e, k);
19
- Object.defineProperty(n, k, d.get ? d : {
20
- enumerable: true,
21
- get: function () { return e[k]; }
22
- });
23
- }
24
- });
25
- }
26
- n.default = e;
27
- return Object.freeze(n);
28
- }
29
-
30
- var AST__namespace = /*#__PURE__*/_interopNamespace(AST);
31
- var ER4__namespace = /*#__PURE__*/_interopNamespace(ER4);
32
- var VAR__namespace = /*#__PURE__*/_interopNamespace(VAR);
33
-
1
+ //#region rolldown:runtime
2
+ var __create = Object.create;
34
3
  var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
35
8
  var __export = (target, all) => {
36
- for (var name3 in all)
37
- __defProp(target, name3, { get: all[name3], enumerable: true });
9
+ for (var name$2 in all) __defProp(target, name$2, {
10
+ get: all[name$2],
11
+ enumerable: true
12
+ });
38
13
  };
14
+ var __copyProps = (to, from, except, desc) => {
15
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
16
+ key = keys[i];
17
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
18
+ get: ((k) => from[k]).bind(null, key),
19
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
20
+ });
21
+ }
22
+ return to;
23
+ };
24
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
25
+ value: mod,
26
+ enumerable: true
27
+ }) : target, mod));
28
+
29
+ //#endregion
30
+ const __eslint_react_shared = __toESM(require("@eslint-react/shared"));
31
+ const __eslint_react_ast = __toESM(require("@eslint-react/ast"));
32
+ const __eslint_react_core = __toESM(require("@eslint-react/core"));
33
+ const __eslint_react_eff = __toESM(require("@eslint-react/eff"));
34
+ const __eslint_react_var = __toESM(require("@eslint-react/var"));
35
+ const __typescript_eslint_utils = __toESM(require("@typescript-eslint/utils"));
36
+ const ts_pattern = __toESM(require("ts-pattern"));
37
+ const __typescript_eslint_types = __toESM(require("@typescript-eslint/types"));
39
38
 
40
- // src/configs/recommended.ts
39
+ //#region src/configs/recommended.ts
41
40
  var recommended_exports = {};
42
41
  __export(recommended_exports, {
43
- name: () => name,
44
- rules: () => rules,
45
- settings: () => settings
42
+ name: () => name$1,
43
+ rules: () => rules,
44
+ settings: () => settings
46
45
  });
47
- var name = "react-web-api/recommended";
48
- var rules = {
49
- "react-web-api/no-leaked-event-listener": "warn",
50
- "react-web-api/no-leaked-interval": "warn",
51
- "react-web-api/no-leaked-resize-observer": "warn",
52
- "react-web-api/no-leaked-timeout": "warn"
53
- };
54
- var settings = {
55
- "react-x": shared.DEFAULT_ESLINT_REACT_SETTINGS
46
+ const name$1 = "react-web-api/recommended";
47
+ const rules = {
48
+ "react-web-api/no-leaked-event-listener": "warn",
49
+ "react-web-api/no-leaked-interval": "warn",
50
+ "react-web-api/no-leaked-resize-observer": "warn",
51
+ "react-web-api/no-leaked-timeout": "warn"
56
52
  };
53
+ const settings = { "react-x": __eslint_react_shared.DEFAULT_ESLINT_REACT_SETTINGS };
54
+
55
+ //#endregion
56
+ //#region package.json
57
+ var name = "eslint-plugin-react-web-api";
58
+ var version = "1.52.10-next.1";
59
+
60
+ //#endregion
61
+ //#region src/utils/create-rule.ts
62
+ const createRule = __typescript_eslint_utils.ESLintUtils.RuleCreator((0, __eslint_react_shared.getDocsUrl)("web-api"));
57
63
 
58
- // package.json
59
- var name2 = "eslint-plugin-react-web-api";
60
- var version = "1.52.10-next.0";
61
- var createRule = utils.ESLintUtils.RuleCreator(shared.getDocsUrl("web-api"));
64
+ //#endregion
65
+ //#region src/utils/get-phase-kind-of-function.ts
62
66
  function getPhaseKindOfFunction(node) {
63
- return tsPattern.match(node).when(ER4__namespace.isFunctionOfUseEffectSetup, () => "setup").when(ER4__namespace.isFunctionOfUseEffectCleanup, () => "cleanup").when(ER4__namespace.isFunctionOfComponentDidMount, () => "mount").when(ER4__namespace.isFunctionOfComponentWillUnmount, () => "unmount").otherwise(() => null);
67
+ return (0, ts_pattern.match)(node).when(__eslint_react_core.isFunctionOfUseEffectSetup, () => "setup").when(__eslint_react_core.isFunctionOfUseEffectCleanup, () => "cleanup").when(__eslint_react_core.isFunctionOfComponentDidMount, () => "mount").when(__eslint_react_core.isFunctionOfComponentWillUnmount, () => "unmount").otherwise(() => null);
64
68
  }
65
- var isControlFlow = eff.or(
66
- AST__namespace.isLoop,
67
- AST__namespace.isOneOf([
68
- types.AST_NODE_TYPES.IfStatement,
69
- types.AST_NODE_TYPES.SwitchStatement
70
- ])
71
- );
72
- var isConditional = eff.or(
73
- isControlFlow,
74
- AST__namespace.isOneOf([
75
- types.AST_NODE_TYPES.LogicalExpression,
76
- types.AST_NODE_TYPES.ConditionalExpression
77
- ])
78
- );
79
69
 
80
- // src/rules/no-leaked-event-listener.ts
81
- var RULE_NAME = "no-leaked-event-listener";
82
- var RULE_FEATURES = [];
83
- var defaultOptions = {
84
- capture: false,
85
- // once: false,
86
- signal: eff.unit
70
+ //#endregion
71
+ //#region src/utils/is-conditional.ts
72
+ const isControlFlow = (0, __eslint_react_eff.or)(__eslint_react_ast.isLoop, __eslint_react_ast.isOneOf([__typescript_eslint_types.AST_NODE_TYPES.IfStatement, __typescript_eslint_types.AST_NODE_TYPES.SwitchStatement]));
73
+ const isConditional = (0, __eslint_react_eff.or)(isControlFlow, __eslint_react_ast.isOneOf([__typescript_eslint_types.AST_NODE_TYPES.LogicalExpression, __typescript_eslint_types.AST_NODE_TYPES.ConditionalExpression]));
74
+
75
+ //#endregion
76
+ //#region src/rules/no-leaked-event-listener.ts
77
+ const RULE_NAME$3 = "no-leaked-event-listener";
78
+ const RULE_FEATURES$3 = [];
79
+ const defaultOptions = {
80
+ capture: false,
81
+ signal: __eslint_react_eff.unit
87
82
  };
88
- function getCallKind(node) {
89
- switch (true) {
90
- case (node.callee.type === utils.AST_NODE_TYPES.Identifier && tsPattern.isMatching(tsPattern.P.union("addEventListener", "removeEventListener", "abort"))(node.callee.name)):
91
- return node.callee.name;
92
- case (node.callee.type === utils.AST_NODE_TYPES.MemberExpression && node.callee.property.type === utils.AST_NODE_TYPES.Identifier && tsPattern.isMatching(tsPattern.P.union("addEventListener", "removeEventListener", "abort"))(node.callee.property.name)):
93
- return node.callee.property.name;
94
- default:
95
- return "other";
96
- }
83
+ function getCallKind$3(node) {
84
+ switch (true) {
85
+ case node.callee.type === __typescript_eslint_utils.AST_NODE_TYPES.Identifier && (0, ts_pattern.isMatching)(ts_pattern.P.union("addEventListener", "removeEventListener", "abort"))(node.callee.name): return node.callee.name;
86
+ case node.callee.type === __typescript_eslint_utils.AST_NODE_TYPES.MemberExpression && node.callee.property.type === __typescript_eslint_utils.AST_NODE_TYPES.Identifier && (0, ts_pattern.isMatching)(ts_pattern.P.union("addEventListener", "removeEventListener", "abort"))(node.callee.property.name): return node.callee.property.name;
87
+ default: return "other";
88
+ }
97
89
  }
98
- function getFunctionKind(node) {
99
- return getPhaseKindOfFunction(node) ?? "other";
90
+ function getFunctionKind$1(node) {
91
+ return getPhaseKindOfFunction(node) ?? "other";
100
92
  }
101
93
  function getSignalValueExpression(node, initialScope) {
102
- if (node == null) return eff.unit;
103
- switch (node.type) {
104
- case utils.AST_NODE_TYPES.Identifier: {
105
- return getSignalValueExpression(VAR__namespace.getVariableInitNode(VAR__namespace.findVariable(node, initialScope), 0), initialScope);
106
- }
107
- case utils.AST_NODE_TYPES.MemberExpression:
108
- return node;
109
- default:
110
- return eff.unit;
111
- }
94
+ if (node == null) return __eslint_react_eff.unit;
95
+ switch (node.type) {
96
+ case __typescript_eslint_utils.AST_NODE_TYPES.Identifier: return getSignalValueExpression(__eslint_react_var.getVariableInitNode(__eslint_react_var.findVariable(node, initialScope), 0), initialScope);
97
+ case __typescript_eslint_utils.AST_NODE_TYPES.MemberExpression: return node;
98
+ default: return __eslint_react_eff.unit;
99
+ }
112
100
  }
113
101
  function getOptions(node, initialScope) {
114
- function findProp(properties, propName) {
115
- return VAR__namespace.findPropertyInProperties(propName, properties, initialScope);
116
- }
117
- function getPropValue(prop, filter = (a) => true) {
118
- if (prop?.type !== utils.AST_NODE_TYPES.Property) return eff.unit;
119
- const { value } = prop;
120
- let v = value;
121
- switch (value.type) {
122
- case utils.AST_NODE_TYPES.Literal: {
123
- v = value.value;
124
- break;
125
- }
126
- default: {
127
- v = VAR__namespace.toStaticValue({ kind: "lazy", node: value, initialScope }).value;
128
- break;
129
- }
130
- }
131
- return filter(v) ? v : eff.unit;
132
- }
133
- function getOpts(node2) {
134
- switch (node2.type) {
135
- case utils.AST_NODE_TYPES.Identifier: {
136
- const variable = VAR__namespace.findVariable(node2, initialScope);
137
- const variableNode = VAR__namespace.getVariableInitNode(variable, 0);
138
- if (variableNode?.type === utils.AST_NODE_TYPES.ObjectExpression) {
139
- return getOpts(variableNode);
140
- }
141
- return defaultOptions;
142
- }
143
- case utils.AST_NODE_TYPES.Literal: {
144
- return { ...defaultOptions, capture: Boolean(node2.value) };
145
- }
146
- case utils.AST_NODE_TYPES.ObjectExpression: {
147
- const pCapture = findProp(node2.properties, "capture");
148
- const vCapture = !!getPropValue(pCapture);
149
- const pSignal = findProp(node2.properties, "signal");
150
- const vSignal = pSignal?.type === utils.AST_NODE_TYPES.Property ? getSignalValueExpression(pSignal.value, initialScope) : eff.unit;
151
- return { capture: vCapture, signal: vSignal };
152
- }
153
- default: {
154
- return defaultOptions;
155
- }
156
- }
157
- }
158
- return getOpts(node);
102
+ function findProp(properties, propName) {
103
+ return __eslint_react_var.findPropertyInProperties(propName, properties, initialScope);
104
+ }
105
+ function getPropValue(prop, filter = (a) => true) {
106
+ if (prop?.type !== __typescript_eslint_utils.AST_NODE_TYPES.Property) return __eslint_react_eff.unit;
107
+ const { value } = prop;
108
+ let v = value;
109
+ switch (value.type) {
110
+ case __typescript_eslint_utils.AST_NODE_TYPES.Literal:
111
+ v = value.value;
112
+ break;
113
+ default:
114
+ v = __eslint_react_var.toStaticValue({
115
+ kind: "lazy",
116
+ node: value,
117
+ initialScope
118
+ }).value;
119
+ break;
120
+ }
121
+ return filter(v) ? v : __eslint_react_eff.unit;
122
+ }
123
+ function getOpts(node$1) {
124
+ switch (node$1.type) {
125
+ case __typescript_eslint_utils.AST_NODE_TYPES.Identifier: {
126
+ const variable = __eslint_react_var.findVariable(node$1, initialScope);
127
+ const variableNode = __eslint_react_var.getVariableInitNode(variable, 0);
128
+ if (variableNode?.type === __typescript_eslint_utils.AST_NODE_TYPES.ObjectExpression) return getOpts(variableNode);
129
+ return defaultOptions;
130
+ }
131
+ case __typescript_eslint_utils.AST_NODE_TYPES.Literal: return {
132
+ ...defaultOptions,
133
+ capture: Boolean(node$1.value)
134
+ };
135
+ case __typescript_eslint_utils.AST_NODE_TYPES.ObjectExpression: {
136
+ const pCapture = findProp(node$1.properties, "capture");
137
+ const vCapture = !!getPropValue(pCapture);
138
+ const pSignal = findProp(node$1.properties, "signal");
139
+ const vSignal = pSignal?.type === __typescript_eslint_utils.AST_NODE_TYPES.Property ? getSignalValueExpression(pSignal.value, initialScope) : __eslint_react_eff.unit;
140
+ return {
141
+ capture: vCapture,
142
+ signal: vSignal
143
+ };
144
+ }
145
+ default: return defaultOptions;
146
+ }
147
+ }
148
+ return getOpts(node);
159
149
  }
160
150
  var no_leaked_event_listener_default = createRule({
161
- meta: {
162
- type: "problem",
163
- docs: {
164
- description: "Prevents leaked `addEventListener` in a component or custom Hook.",
165
- [Symbol.for("rule_features")]: RULE_FEATURES
166
- },
167
- messages: {
168
- expectedRemoveEventListenerInCleanup: "An 'addEventListener' in '{{effectMethodKind}}' should have a corresponding 'removeEventListener' in its cleanup function.",
169
- expectedRemoveEventListenerInUnmount: "An 'addEventListener' in 'componentDidMount' should have a corresponding 'removeEventListener' in 'componentWillUnmount' method.",
170
- unexpectedInlineFunction: "A/an '{{eventMethodKind}}' should not have an inline listener function."
171
- },
172
- schema: []
173
- },
174
- name: RULE_NAME,
175
- create,
176
- defaultOptions: []
151
+ meta: {
152
+ type: "problem",
153
+ docs: {
154
+ description: "Prevents leaked `addEventListener` in a component or custom Hook.",
155
+ [Symbol.for("rule_features")]: RULE_FEATURES$3
156
+ },
157
+ messages: {
158
+ expectedRemoveEventListenerInCleanup: "An 'addEventListener' in '{{effectMethodKind}}' should have a corresponding 'removeEventListener' in its cleanup function.",
159
+ expectedRemoveEventListenerInUnmount: "An 'addEventListener' in 'componentDidMount' should have a corresponding 'removeEventListener' in 'componentWillUnmount' method.",
160
+ unexpectedInlineFunction: "A/an '{{eventMethodKind}}' should not have an inline listener function."
161
+ },
162
+ schema: []
163
+ },
164
+ name: RULE_NAME$3,
165
+ create: create$3,
166
+ defaultOptions: []
177
167
  });
178
- function create(context) {
179
- if (!context.sourceCode.text.includes("addEventListener")) {
180
- return {};
181
- }
182
- if (!/use\w*Effect|componentDidMount|componentWillUnmount/u.test(context.sourceCode.text)) {
183
- return {};
184
- }
185
- const fEntries = [];
186
- const aEntries = [];
187
- const rEntries = [];
188
- const abortedSignals = [];
189
- function isSameObject(a, b) {
190
- switch (true) {
191
- case (a.type === utils.AST_NODE_TYPES.MemberExpression && b.type === utils.AST_NODE_TYPES.MemberExpression):
192
- return AST__namespace.isNodeEqual(a.object, b.object);
193
- // TODO: Maybe there other cases to consider here.
194
- default:
195
- return false;
196
- }
197
- }
198
- function isInverseEntry(aEntry, rEntry) {
199
- const { type: aType, callee: aCallee, capture: aCapture, listener: aListener, phase: aPhase } = aEntry;
200
- const { type: rType, callee: rCallee, capture: rCapture, listener: rListener, phase: rPhase } = rEntry;
201
- if (!ER4__namespace.isInversePhase(aPhase, rPhase)) {
202
- return false;
203
- }
204
- return isSameObject(aCallee, rCallee) && AST__namespace.isNodeEqual(aListener, rListener) && VAR__namespace.isNodeValueEqual(aType, rType, [
205
- context.sourceCode.getScope(aType),
206
- context.sourceCode.getScope(rType)
207
- ]) && aCapture === rCapture;
208
- }
209
- function checkInlineFunction(node, callKind, options) {
210
- const listener = node.arguments.at(1);
211
- if (!AST__namespace.isFunction(listener)) {
212
- return;
213
- }
214
- if (options.signal != null) {
215
- return;
216
- }
217
- context.report({
218
- messageId: "unexpectedInlineFunction",
219
- node: listener,
220
- data: { eventMethodKind: callKind }
221
- });
222
- }
223
- return {
224
- [":function"](node) {
225
- const kind = getFunctionKind(node);
226
- fEntries.push({ kind, node });
227
- },
228
- [":function:exit"]() {
229
- fEntries.pop();
230
- },
231
- ["CallExpression"](node) {
232
- const fKind = fEntries.findLast((x) => x.kind !== "other")?.kind;
233
- if (fKind == null) {
234
- return;
235
- }
236
- if (!ER4__namespace.ComponentPhaseRelevance.has(fKind)) {
237
- return;
238
- }
239
- tsPattern.match(getCallKind(node)).with("addEventListener", (callKind) => {
240
- const [type, listener, options] = node.arguments;
241
- if (type == null || listener == null) {
242
- return;
243
- }
244
- const opts = options == null ? defaultOptions : getOptions(options, context.sourceCode.getScope(options));
245
- const { callee } = node;
246
- checkInlineFunction(node, callKind, opts);
247
- aEntries.push({
248
- ...opts,
249
- kind: "addEventListener",
250
- type,
251
- node,
252
- callee,
253
- listener,
254
- phase: fKind
255
- });
256
- }).with("removeEventListener", (callKind) => {
257
- const [type, listener, options] = node.arguments;
258
- if (type == null || listener == null) {
259
- return;
260
- }
261
- const opts = options == null ? defaultOptions : getOptions(options, context.sourceCode.getScope(options));
262
- const { callee } = node;
263
- checkInlineFunction(node, callKind, opts);
264
- rEntries.push({
265
- ...opts,
266
- kind: "removeEventListener",
267
- type,
268
- node,
269
- callee,
270
- listener,
271
- phase: fKind
272
- });
273
- }).with("abort", () => {
274
- abortedSignals.push(node.callee);
275
- }).otherwise(() => null);
276
- },
277
- ["Program:exit"]() {
278
- for (const aEntry of aEntries) {
279
- const signal = aEntry.signal;
280
- if (signal != null && abortedSignals.some((a) => isSameObject(a, signal))) {
281
- continue;
282
- }
283
- if (rEntries.some((rEntry) => isInverseEntry(aEntry, rEntry))) {
284
- continue;
285
- }
286
- switch (aEntry.phase) {
287
- case "setup":
288
- case "cleanup":
289
- context.report({
290
- messageId: "expectedRemoveEventListenerInCleanup",
291
- node: aEntry.node,
292
- data: {
293
- effectMethodKind: "useEffect"
294
- }
295
- });
296
- continue;
297
- case "mount":
298
- case "unmount":
299
- context.report({
300
- messageId: "expectedRemoveEventListenerInUnmount",
301
- node: aEntry.node
302
- });
303
- continue;
304
- }
305
- }
306
- }
307
- };
168
+ function create$3(context) {
169
+ if (!context.sourceCode.text.includes("addEventListener")) return {};
170
+ if (!/use\w*Effect|componentDidMount|componentWillUnmount/u.test(context.sourceCode.text)) return {};
171
+ const fEntries = [];
172
+ const aEntries = [];
173
+ const rEntries = [];
174
+ const abortedSignals = [];
175
+ function isSameObject(a, b) {
176
+ switch (true) {
177
+ case a.type === __typescript_eslint_utils.AST_NODE_TYPES.MemberExpression && b.type === __typescript_eslint_utils.AST_NODE_TYPES.MemberExpression: return __eslint_react_ast.isNodeEqual(a.object, b.object);
178
+ default: return false;
179
+ }
180
+ }
181
+ function isInverseEntry(aEntry, rEntry) {
182
+ const { type: aType, callee: aCallee, capture: aCapture, listener: aListener, phase: aPhase } = aEntry;
183
+ const { type: rType, callee: rCallee, capture: rCapture, listener: rListener, phase: rPhase } = rEntry;
184
+ if (!__eslint_react_core.isInversePhase(aPhase, rPhase)) return false;
185
+ return isSameObject(aCallee, rCallee) && __eslint_react_ast.isNodeEqual(aListener, rListener) && __eslint_react_var.isNodeValueEqual(aType, rType, [context.sourceCode.getScope(aType), context.sourceCode.getScope(rType)]) && aCapture === rCapture;
186
+ }
187
+ function checkInlineFunction(node, callKind, options) {
188
+ const listener = node.arguments.at(1);
189
+ if (!__eslint_react_ast.isFunction(listener)) return;
190
+ if (options.signal != null) return;
191
+ context.report({
192
+ messageId: "unexpectedInlineFunction",
193
+ node: listener,
194
+ data: { eventMethodKind: callKind }
195
+ });
196
+ }
197
+ return {
198
+ [":function"](node) {
199
+ const kind = getFunctionKind$1(node);
200
+ fEntries.push({
201
+ kind,
202
+ node
203
+ });
204
+ },
205
+ [":function:exit"]() {
206
+ fEntries.pop();
207
+ },
208
+ ["CallExpression"](node) {
209
+ const fKind = fEntries.findLast((x) => x.kind !== "other")?.kind;
210
+ if (fKind == null) return;
211
+ if (!__eslint_react_core.ComponentPhaseRelevance.has(fKind)) return;
212
+ (0, ts_pattern.match)(getCallKind$3(node)).with("addEventListener", (callKind) => {
213
+ const [type, listener, options] = node.arguments;
214
+ if (type == null || listener == null) return;
215
+ const opts = options == null ? defaultOptions : getOptions(options, context.sourceCode.getScope(options));
216
+ const { callee } = node;
217
+ checkInlineFunction(node, callKind, opts);
218
+ aEntries.push({
219
+ ...opts,
220
+ kind: "addEventListener",
221
+ type,
222
+ node,
223
+ callee,
224
+ listener,
225
+ phase: fKind
226
+ });
227
+ }).with("removeEventListener", (callKind) => {
228
+ const [type, listener, options] = node.arguments;
229
+ if (type == null || listener == null) return;
230
+ const opts = options == null ? defaultOptions : getOptions(options, context.sourceCode.getScope(options));
231
+ const { callee } = node;
232
+ checkInlineFunction(node, callKind, opts);
233
+ rEntries.push({
234
+ ...opts,
235
+ kind: "removeEventListener",
236
+ type,
237
+ node,
238
+ callee,
239
+ listener,
240
+ phase: fKind
241
+ });
242
+ }).with("abort", () => {
243
+ abortedSignals.push(node.callee);
244
+ }).otherwise(() => null);
245
+ },
246
+ ["Program:exit"]() {
247
+ for (const aEntry of aEntries) {
248
+ const signal = aEntry.signal;
249
+ if (signal != null && abortedSignals.some((a) => isSameObject(a, signal))) continue;
250
+ if (rEntries.some((rEntry) => isInverseEntry(aEntry, rEntry))) continue;
251
+ switch (aEntry.phase) {
252
+ case "setup":
253
+ case "cleanup":
254
+ context.report({
255
+ messageId: "expectedRemoveEventListenerInCleanup",
256
+ node: aEntry.node,
257
+ data: { effectMethodKind: "useEffect" }
258
+ });
259
+ continue;
260
+ case "mount":
261
+ case "unmount":
262
+ context.report({
263
+ messageId: "expectedRemoveEventListenerInUnmount",
264
+ node: aEntry.node
265
+ });
266
+ continue;
267
+ }
268
+ }
269
+ }
270
+ };
308
271
  }
309
- var RULE_NAME2 = "no-leaked-interval";
310
- var RULE_FEATURES2 = [];
311
- function getCallKind2(node) {
312
- switch (true) {
313
- case (node.callee.type === utils.AST_NODE_TYPES.Identifier && tsPattern.isMatching(tsPattern.P.union("setInterval", "clearInterval"))(node.callee.name)):
314
- return node.callee.name;
315
- case (node.callee.type === utils.AST_NODE_TYPES.MemberExpression && node.callee.property.type === utils.AST_NODE_TYPES.Identifier && tsPattern.isMatching(tsPattern.P.union("setInterval", "clearInterval"))(node.callee.property.name)):
316
- return node.callee.property.name;
317
- default:
318
- return "other";
319
- }
272
+
273
+ //#endregion
274
+ //#region src/rules/no-leaked-interval.ts
275
+ const RULE_NAME$2 = "no-leaked-interval";
276
+ const RULE_FEATURES$2 = [];
277
+ function getCallKind$2(node) {
278
+ switch (true) {
279
+ case node.callee.type === __typescript_eslint_utils.AST_NODE_TYPES.Identifier && (0, ts_pattern.isMatching)(ts_pattern.P.union("setInterval", "clearInterval"))(node.callee.name): return node.callee.name;
280
+ case node.callee.type === __typescript_eslint_utils.AST_NODE_TYPES.MemberExpression && node.callee.property.type === __typescript_eslint_utils.AST_NODE_TYPES.Identifier && (0, ts_pattern.isMatching)(ts_pattern.P.union("setInterval", "clearInterval"))(node.callee.property.name): return node.callee.property.name;
281
+ default: return "other";
282
+ }
320
283
  }
321
284
  var no_leaked_interval_default = createRule({
322
- meta: {
323
- type: "problem",
324
- docs: {
325
- description: "Prevents leaked `setInterval` in a component or custom Hook.",
326
- [Symbol.for("rule_features")]: RULE_FEATURES2
327
- },
328
- messages: {
329
- expectedClearIntervalInCleanup: "A 'setInterval' created in '{{ kind }}' must be cleared with 'clearInterval' in the cleanup function.",
330
- expectedClearIntervalInUnmount: "A 'setInterval' created in '{{ kind }}' must be cleared with 'clearInterval' in the 'componentWillUnmount' method.",
331
- expectedIntervalId: "A 'setInterval' must be assigned to a variable for proper cleanup."
332
- },
333
- schema: []
334
- },
335
- name: RULE_NAME2,
336
- create: create2,
337
- defaultOptions: []
285
+ meta: {
286
+ type: "problem",
287
+ docs: {
288
+ description: "Prevents leaked `setInterval` in a component or custom Hook.",
289
+ [Symbol.for("rule_features")]: RULE_FEATURES$2
290
+ },
291
+ messages: {
292
+ expectedClearIntervalInCleanup: "A 'setInterval' created in '{{ kind }}' must be cleared with 'clearInterval' in the cleanup function.",
293
+ expectedClearIntervalInUnmount: "A 'setInterval' created in '{{ kind }}' must be cleared with 'clearInterval' in the 'componentWillUnmount' method.",
294
+ expectedIntervalId: "A 'setInterval' must be assigned to a variable for proper cleanup."
295
+ },
296
+ schema: []
297
+ },
298
+ name: RULE_NAME$2,
299
+ create: create$2,
300
+ defaultOptions: []
338
301
  });
339
- function create2(context) {
340
- if (!context.sourceCode.text.includes("setInterval")) {
341
- return {};
342
- }
343
- const fEntries = [];
344
- const sEntries = [];
345
- const cEntries = [];
346
- function isInverseEntry(a, b) {
347
- return ER4__namespace.isInstanceIdEqual(context, a.timerId, b.timerId);
348
- }
349
- return {
350
- [":function"](node) {
351
- const kind = getPhaseKindOfFunction(node) ?? "other";
352
- fEntries.push({ kind, node });
353
- },
354
- [":function:exit"]() {
355
- fEntries.pop();
356
- },
357
- ["CallExpression"](node) {
358
- switch (getCallKind2(node)) {
359
- case "setInterval": {
360
- const fEntry = fEntries.findLast((x) => x.kind !== "other");
361
- if (fEntry == null) {
362
- break;
363
- }
364
- if (!ER4__namespace.ComponentPhaseRelevance.has(fEntry.kind)) {
365
- break;
366
- }
367
- const intervalIdNode = VAR__namespace.getVariableDeclaratorId(node);
368
- if (intervalIdNode == null) {
369
- context.report({
370
- messageId: "expectedIntervalId",
371
- node
372
- });
373
- break;
374
- }
375
- sEntries.push({
376
- kind: "interval",
377
- node,
378
- callee: node.callee,
379
- phase: fEntry.kind,
380
- timerId: intervalIdNode
381
- });
382
- break;
383
- }
384
- case "clearInterval": {
385
- const fEntry = fEntries.findLast((x) => x.kind !== "other");
386
- if (fEntry == null) {
387
- break;
388
- }
389
- if (!ER4__namespace.ComponentPhaseRelevance.has(fEntry.kind)) {
390
- break;
391
- }
392
- const [intervalIdNode] = node.arguments;
393
- if (intervalIdNode == null) {
394
- break;
395
- }
396
- cEntries.push({
397
- kind: "interval",
398
- node,
399
- callee: node.callee,
400
- phase: fEntry.kind,
401
- timerId: intervalIdNode
402
- });
403
- break;
404
- }
405
- }
406
- },
407
- ["Program:exit"]() {
408
- for (const sEntry of sEntries) {
409
- if (cEntries.some((cEntry) => isInverseEntry(sEntry, cEntry))) {
410
- continue;
411
- }
412
- switch (sEntry.phase) {
413
- case "setup":
414
- case "cleanup":
415
- context.report({
416
- messageId: "expectedClearIntervalInCleanup",
417
- node: sEntry.node,
418
- data: {
419
- kind: "useEffect"
420
- }
421
- });
422
- continue;
423
- case "mount":
424
- case "unmount":
425
- context.report({
426
- messageId: "expectedClearIntervalInUnmount",
427
- node: sEntry.node,
428
- data: {
429
- kind: "componentDidMount"
430
- }
431
- });
432
- continue;
433
- }
434
- }
435
- }
436
- };
302
+ function create$2(context) {
303
+ if (!context.sourceCode.text.includes("setInterval")) return {};
304
+ const fEntries = [];
305
+ const sEntries = [];
306
+ const cEntries = [];
307
+ function isInverseEntry(a, b) {
308
+ return __eslint_react_core.isInstanceIdEqual(context, a.timerId, b.timerId);
309
+ }
310
+ return {
311
+ [":function"](node) {
312
+ const kind = getPhaseKindOfFunction(node) ?? "other";
313
+ fEntries.push({
314
+ kind,
315
+ node
316
+ });
317
+ },
318
+ [":function:exit"]() {
319
+ fEntries.pop();
320
+ },
321
+ ["CallExpression"](node) {
322
+ switch (getCallKind$2(node)) {
323
+ case "setInterval": {
324
+ const fEntry = fEntries.findLast((x) => x.kind !== "other");
325
+ if (fEntry == null) break;
326
+ if (!__eslint_react_core.ComponentPhaseRelevance.has(fEntry.kind)) break;
327
+ const intervalIdNode = __eslint_react_var.getVariableDeclaratorId(node);
328
+ if (intervalIdNode == null) {
329
+ context.report({
330
+ messageId: "expectedIntervalId",
331
+ node
332
+ });
333
+ break;
334
+ }
335
+ sEntries.push({
336
+ kind: "interval",
337
+ node,
338
+ callee: node.callee,
339
+ phase: fEntry.kind,
340
+ timerId: intervalIdNode
341
+ });
342
+ break;
343
+ }
344
+ case "clearInterval": {
345
+ const fEntry = fEntries.findLast((x) => x.kind !== "other");
346
+ if (fEntry == null) break;
347
+ if (!__eslint_react_core.ComponentPhaseRelevance.has(fEntry.kind)) break;
348
+ const [intervalIdNode] = node.arguments;
349
+ if (intervalIdNode == null) break;
350
+ cEntries.push({
351
+ kind: "interval",
352
+ node,
353
+ callee: node.callee,
354
+ phase: fEntry.kind,
355
+ timerId: intervalIdNode
356
+ });
357
+ break;
358
+ }
359
+ }
360
+ },
361
+ ["Program:exit"]() {
362
+ for (const sEntry of sEntries) {
363
+ if (cEntries.some((cEntry) => isInverseEntry(sEntry, cEntry))) continue;
364
+ switch (sEntry.phase) {
365
+ case "setup":
366
+ case "cleanup":
367
+ context.report({
368
+ messageId: "expectedClearIntervalInCleanup",
369
+ node: sEntry.node,
370
+ data: { kind: "useEffect" }
371
+ });
372
+ continue;
373
+ case "mount":
374
+ case "unmount":
375
+ context.report({
376
+ messageId: "expectedClearIntervalInUnmount",
377
+ node: sEntry.node,
378
+ data: { kind: "componentDidMount" }
379
+ });
380
+ continue;
381
+ }
382
+ }
383
+ }
384
+ };
437
385
  }
438
- var RULE_NAME3 = "no-leaked-resize-observer";
439
- var RULE_FEATURES3 = [];
386
+
387
+ //#endregion
388
+ //#region src/rules/no-leaked-resize-observer.ts
389
+ const RULE_NAME$1 = "no-leaked-resize-observer";
390
+ const RULE_FEATURES$1 = [];
440
391
  function isNewResizeObserver(node) {
441
- return node?.type === utils.AST_NODE_TYPES.NewExpression && node.callee.type === utils.AST_NODE_TYPES.Identifier && node.callee.name === "ResizeObserver";
392
+ return node?.type === __typescript_eslint_utils.AST_NODE_TYPES.NewExpression && node.callee.type === __typescript_eslint_utils.AST_NODE_TYPES.Identifier && node.callee.name === "ResizeObserver";
442
393
  }
443
394
  function isFromObserver(context, node) {
444
- switch (true) {
445
- case node.type === utils.AST_NODE_TYPES.Identifier: {
446
- const initialScope = context.sourceCode.getScope(node);
447
- const object = VAR__namespace.getVariableInitNode(VAR__namespace.findVariable(node, initialScope), 0);
448
- return isNewResizeObserver(object);
449
- }
450
- case node.type === utils.AST_NODE_TYPES.MemberExpression:
451
- return isFromObserver(context, node.object);
452
- default:
453
- return false;
454
- }
395
+ switch (true) {
396
+ case node.type === __typescript_eslint_utils.AST_NODE_TYPES.Identifier: {
397
+ const initialScope = context.sourceCode.getScope(node);
398
+ const object = __eslint_react_var.getVariableInitNode(__eslint_react_var.findVariable(node, initialScope), 0);
399
+ return isNewResizeObserver(object);
400
+ }
401
+ case node.type === __typescript_eslint_utils.AST_NODE_TYPES.MemberExpression: return isFromObserver(context, node.object);
402
+ default: return false;
403
+ }
455
404
  }
456
- function getCallKind3(context, node) {
457
- switch (true) {
458
- case (node.callee.type === utils.AST_NODE_TYPES.Identifier && tsPattern.isMatching(tsPattern.P.union("observe", "unobserve", "disconnect"))(node.callee.name) && isFromObserver(context, node.callee)):
459
- return node.callee.name;
460
- case (node.callee.type === utils.AST_NODE_TYPES.MemberExpression && node.callee.property.type === utils.AST_NODE_TYPES.Identifier && tsPattern.isMatching(tsPattern.P.union("observe", "unobserve", "disconnect"))(node.callee.property.name) && isFromObserver(context, node.callee)):
461
- return node.callee.property.name;
462
- default:
463
- return "other";
464
- }
405
+ function getCallKind$1(context, node) {
406
+ switch (true) {
407
+ case node.callee.type === __typescript_eslint_utils.AST_NODE_TYPES.Identifier && (0, ts_pattern.isMatching)(ts_pattern.P.union("observe", "unobserve", "disconnect"))(node.callee.name) && isFromObserver(context, node.callee): return node.callee.name;
408
+ case node.callee.type === __typescript_eslint_utils.AST_NODE_TYPES.MemberExpression && node.callee.property.type === __typescript_eslint_utils.AST_NODE_TYPES.Identifier && (0, ts_pattern.isMatching)(ts_pattern.P.union("observe", "unobserve", "disconnect"))(node.callee.property.name) && isFromObserver(context, node.callee): return node.callee.property.name;
409
+ default: return "other";
410
+ }
465
411
  }
466
- function getFunctionKind2(node) {
467
- return getPhaseKindOfFunction(node) ?? "other";
412
+ function getFunctionKind(node) {
413
+ return getPhaseKindOfFunction(node) ?? "other";
468
414
  }
469
415
  var no_leaked_resize_observer_default = createRule({
470
- meta: {
471
- type: "problem",
472
- docs: {
473
- description: "Prevents leaked `ResizeObserver` in a component or custom Hook.",
474
- [Symbol.for("rule_features")]: RULE_FEATURES3
475
- },
476
- messages: {
477
- expectedDisconnectInControlFlow: "Dynamically added 'ResizeObserver.observe' should be cleared all at once using 'ResizeObserver.disconnect' in the cleanup function.",
478
- expectedDisconnectOrUnobserveInCleanup: "A 'ResizeObserver' instance created in 'useEffect' must be disconnected in the cleanup function.",
479
- unexpectedFloatingInstance: "A 'ResizeObserver' instance created in component or custom Hook must be assigned to a variable for proper cleanup."
480
- },
481
- schema: []
482
- },
483
- name: RULE_NAME3,
484
- create: create3,
485
- defaultOptions: []
416
+ meta: {
417
+ type: "problem",
418
+ docs: {
419
+ description: "Prevents leaked `ResizeObserver` in a component or custom Hook.",
420
+ [Symbol.for("rule_features")]: RULE_FEATURES$1
421
+ },
422
+ messages: {
423
+ expectedDisconnectInControlFlow: "Dynamically added 'ResizeObserver.observe' should be cleared all at once using 'ResizeObserver.disconnect' in the cleanup function.",
424
+ expectedDisconnectOrUnobserveInCleanup: "A 'ResizeObserver' instance created in 'useEffect' must be disconnected in the cleanup function.",
425
+ unexpectedFloatingInstance: "A 'ResizeObserver' instance created in component or custom Hook must be assigned to a variable for proper cleanup."
426
+ },
427
+ schema: []
428
+ },
429
+ name: RULE_NAME$1,
430
+ create: create$1,
431
+ defaultOptions: []
486
432
  });
487
- function create3(context) {
488
- if (!context.sourceCode.text.includes("ResizeObserver")) {
489
- return {};
490
- }
491
- const fEntries = [];
492
- const observers = [];
493
- const oEntries = [];
494
- const uEntries = [];
495
- const dEntries = [];
496
- return {
497
- [":function"](node) {
498
- const kind = getFunctionKind2(node);
499
- fEntries.push({ kind, node });
500
- },
501
- [":function:exit"]() {
502
- fEntries.pop();
503
- },
504
- ["CallExpression"](node) {
505
- if (node.callee.type !== utils.AST_NODE_TYPES.MemberExpression) {
506
- return;
507
- }
508
- const fKind = fEntries.findLast((x) => x.kind !== "other")?.kind;
509
- if (fKind == null || !ER4__namespace.ComponentPhaseRelevance.has(fKind)) {
510
- return;
511
- }
512
- const { object } = node.callee;
513
- tsPattern.match(getCallKind3(context, node)).with("disconnect", () => {
514
- dEntries.push({
515
- kind: "disconnect",
516
- node,
517
- callee: node.callee,
518
- observer: object,
519
- observerKind: "ResizeObserver",
520
- phase: fKind
521
- });
522
- }).with("observe", () => {
523
- const [element] = node.arguments;
524
- if (element == null) {
525
- return;
526
- }
527
- oEntries.push({
528
- kind: "observe",
529
- node,
530
- callee: node.callee,
531
- element,
532
- observer: object,
533
- observerKind: "ResizeObserver",
534
- phase: fKind
535
- });
536
- }).with("unobserve", () => {
537
- const [element] = node.arguments;
538
- if (element == null) {
539
- return;
540
- }
541
- uEntries.push({
542
- kind: "unobserve",
543
- node,
544
- callee: node.callee,
545
- element,
546
- observer: object,
547
- observerKind: "ResizeObserver",
548
- phase: fKind
549
- });
550
- }).otherwise(() => null);
551
- },
552
- ["NewExpression"](node) {
553
- const fEntry = fEntries.findLast((x) => x.kind !== "other");
554
- if (fEntry == null) return;
555
- if (!ER4__namespace.ComponentPhaseRelevance.has(fEntry.kind)) {
556
- return;
557
- }
558
- if (!isNewResizeObserver(node)) {
559
- return;
560
- }
561
- const id = ER4__namespace.getInstanceId(node);
562
- if (id == null) {
563
- context.report({
564
- messageId: "unexpectedFloatingInstance",
565
- node
566
- });
567
- return;
568
- }
569
- observers.push({
570
- id,
571
- node,
572
- phase: fEntry.kind,
573
- phaseNode: fEntry.node
574
- });
575
- },
576
- ["Program:exit"]() {
577
- for (const { id, node, phaseNode } of observers) {
578
- if (dEntries.some((e) => ER4__namespace.isInstanceIdEqual(context, e.observer, id))) {
579
- continue;
580
- }
581
- const oentries = oEntries.filter((e) => ER4__namespace.isInstanceIdEqual(context, e.observer, id));
582
- const uentries = uEntries.filter((e) => ER4__namespace.isInstanceIdEqual(context, e.observer, id));
583
- const isDynamic = (node2) => node2?.type === utils.AST_NODE_TYPES.CallExpression || isConditional(node2);
584
- const isPhaseNode = (node2) => node2 === phaseNode;
585
- const hasDynamicallyAdded = oentries.some((e) => !isPhaseNode(AST__namespace.findParentNode(e.node, eff.or(isDynamic, isPhaseNode))));
586
- if (hasDynamicallyAdded) {
587
- context.report({ messageId: "expectedDisconnectInControlFlow", node });
588
- continue;
589
- }
590
- for (const oEntry of oentries) {
591
- if (uentries.some((uEntry) => ER4__namespace.isInstanceIdEqual(context, uEntry.element, oEntry.element))) {
592
- continue;
593
- }
594
- context.report({ messageId: "expectedDisconnectOrUnobserveInCleanup", node: oEntry.node });
595
- }
596
- }
597
- }
598
- };
433
+ function create$1(context) {
434
+ if (!context.sourceCode.text.includes("ResizeObserver")) return {};
435
+ const fEntries = [];
436
+ const observers = [];
437
+ const oEntries = [];
438
+ const uEntries = [];
439
+ const dEntries = [];
440
+ return {
441
+ [":function"](node) {
442
+ const kind = getFunctionKind(node);
443
+ fEntries.push({
444
+ kind,
445
+ node
446
+ });
447
+ },
448
+ [":function:exit"]() {
449
+ fEntries.pop();
450
+ },
451
+ ["CallExpression"](node) {
452
+ if (node.callee.type !== __typescript_eslint_utils.AST_NODE_TYPES.MemberExpression) return;
453
+ const fKind = fEntries.findLast((x) => x.kind !== "other")?.kind;
454
+ if (fKind == null || !__eslint_react_core.ComponentPhaseRelevance.has(fKind)) return;
455
+ const { object } = node.callee;
456
+ (0, ts_pattern.match)(getCallKind$1(context, node)).with("disconnect", () => {
457
+ dEntries.push({
458
+ kind: "disconnect",
459
+ node,
460
+ callee: node.callee,
461
+ observer: object,
462
+ observerKind: "ResizeObserver",
463
+ phase: fKind
464
+ });
465
+ }).with("observe", () => {
466
+ const [element] = node.arguments;
467
+ if (element == null) return;
468
+ oEntries.push({
469
+ kind: "observe",
470
+ node,
471
+ callee: node.callee,
472
+ element,
473
+ observer: object,
474
+ observerKind: "ResizeObserver",
475
+ phase: fKind
476
+ });
477
+ }).with("unobserve", () => {
478
+ const [element] = node.arguments;
479
+ if (element == null) return;
480
+ uEntries.push({
481
+ kind: "unobserve",
482
+ node,
483
+ callee: node.callee,
484
+ element,
485
+ observer: object,
486
+ observerKind: "ResizeObserver",
487
+ phase: fKind
488
+ });
489
+ }).otherwise(() => null);
490
+ },
491
+ ["NewExpression"](node) {
492
+ const fEntry = fEntries.findLast((x) => x.kind !== "other");
493
+ if (fEntry == null) return;
494
+ if (!__eslint_react_core.ComponentPhaseRelevance.has(fEntry.kind)) return;
495
+ if (!isNewResizeObserver(node)) return;
496
+ const id = __eslint_react_core.getInstanceId(node);
497
+ if (id == null) {
498
+ context.report({
499
+ messageId: "unexpectedFloatingInstance",
500
+ node
501
+ });
502
+ return;
503
+ }
504
+ observers.push({
505
+ id,
506
+ node,
507
+ phase: fEntry.kind,
508
+ phaseNode: fEntry.node
509
+ });
510
+ },
511
+ ["Program:exit"]() {
512
+ for (const { id, node, phaseNode } of observers) {
513
+ if (dEntries.some((e) => __eslint_react_core.isInstanceIdEqual(context, e.observer, id))) continue;
514
+ const oentries = oEntries.filter((e) => __eslint_react_core.isInstanceIdEqual(context, e.observer, id));
515
+ const uentries = uEntries.filter((e) => __eslint_react_core.isInstanceIdEqual(context, e.observer, id));
516
+ const isDynamic = (node$1) => node$1?.type === __typescript_eslint_utils.AST_NODE_TYPES.CallExpression || isConditional(node$1);
517
+ const isPhaseNode = (node$1) => node$1 === phaseNode;
518
+ const hasDynamicallyAdded = oentries.some((e) => !isPhaseNode(__eslint_react_ast.findParentNode(e.node, (0, __eslint_react_eff.or)(isDynamic, isPhaseNode))));
519
+ if (hasDynamicallyAdded) {
520
+ context.report({
521
+ messageId: "expectedDisconnectInControlFlow",
522
+ node
523
+ });
524
+ continue;
525
+ }
526
+ for (const oEntry of oentries) {
527
+ if (uentries.some((uEntry) => __eslint_react_core.isInstanceIdEqual(context, uEntry.element, oEntry.element))) continue;
528
+ context.report({
529
+ messageId: "expectedDisconnectOrUnobserveInCleanup",
530
+ node: oEntry.node
531
+ });
532
+ }
533
+ }
534
+ }
535
+ };
599
536
  }
600
- var RULE_NAME4 = "no-leaked-timeout";
601
- var RULE_FEATURES4 = [];
602
- function getCallKind4(node) {
603
- switch (true) {
604
- case (node.callee.type === utils.AST_NODE_TYPES.Identifier && tsPattern.isMatching(tsPattern.P.union("setTimeout", "clearTimeout"))(node.callee.name)):
605
- return node.callee.name;
606
- case (node.callee.type === utils.AST_NODE_TYPES.MemberExpression && node.callee.property.type === utils.AST_NODE_TYPES.Identifier && tsPattern.isMatching(tsPattern.P.union("setTimeout", "clearTimeout"))(node.callee.property.name)):
607
- return node.callee.property.name;
608
- default:
609
- return "other";
610
- }
537
+
538
+ //#endregion
539
+ //#region src/rules/no-leaked-timeout.ts
540
+ const RULE_NAME = "no-leaked-timeout";
541
+ const RULE_FEATURES = [];
542
+ function getCallKind(node) {
543
+ switch (true) {
544
+ case node.callee.type === __typescript_eslint_utils.AST_NODE_TYPES.Identifier && (0, ts_pattern.isMatching)(ts_pattern.P.union("setTimeout", "clearTimeout"))(node.callee.name): return node.callee.name;
545
+ case node.callee.type === __typescript_eslint_utils.AST_NODE_TYPES.MemberExpression && node.callee.property.type === __typescript_eslint_utils.AST_NODE_TYPES.Identifier && (0, ts_pattern.isMatching)(ts_pattern.P.union("setTimeout", "clearTimeout"))(node.callee.property.name): return node.callee.property.name;
546
+ default: return "other";
547
+ }
611
548
  }
612
549
  var no_leaked_timeout_default = createRule({
613
- meta: {
614
- type: "problem",
615
- docs: {
616
- description: "Prevents leaked `setTimeout` in a component or custom Hook.",
617
- [Symbol.for("rule_features")]: RULE_FEATURES4
618
- },
619
- messages: {
620
- expectedClearTimeoutInCleanup: "A 'setTimeout' created in '{{ kind }}' must be cleared with 'clearTimeout' in the cleanup function.",
621
- expectedClearTimeoutInUnmount: "A 'setTimeout' created in '{{ kind }}' must be cleared with 'clearTimeout' in the 'componentWillUnmount' method.",
622
- expectedTimeoutId: "A 'setTimeout' must be assigned to a variable for proper cleanup."
623
- },
624
- schema: []
625
- },
626
- name: RULE_NAME4,
627
- create: create4,
628
- defaultOptions: []
550
+ meta: {
551
+ type: "problem",
552
+ docs: {
553
+ description: "Prevents leaked `setTimeout` in a component or custom Hook.",
554
+ [Symbol.for("rule_features")]: RULE_FEATURES
555
+ },
556
+ messages: {
557
+ expectedClearTimeoutInCleanup: "A 'setTimeout' created in '{{ kind }}' must be cleared with 'clearTimeout' in the cleanup function.",
558
+ expectedClearTimeoutInUnmount: "A 'setTimeout' created in '{{ kind }}' must be cleared with 'clearTimeout' in the 'componentWillUnmount' method.",
559
+ expectedTimeoutId: "A 'setTimeout' must be assigned to a variable for proper cleanup."
560
+ },
561
+ schema: []
562
+ },
563
+ name: RULE_NAME,
564
+ create,
565
+ defaultOptions: []
629
566
  });
630
- function create4(context) {
631
- if (!context.sourceCode.text.includes("setTimeout")) {
632
- return {};
633
- }
634
- const fEntries = [];
635
- const sEntries = [];
636
- const rEntries = [];
637
- function isInverseEntry(a, b) {
638
- return ER4__namespace.isInstanceIdEqual(context, a.timerId, b.timerId);
639
- }
640
- return {
641
- [":function"](node) {
642
- const kind = getPhaseKindOfFunction(node) ?? "other";
643
- fEntries.push({ kind, node });
644
- },
645
- [":function:exit"]() {
646
- fEntries.pop();
647
- },
648
- ["CallExpression"](node) {
649
- const fEntry = fEntries.findLast((f) => f.kind !== "other");
650
- if (!ER4__namespace.ComponentPhaseRelevance.has(fEntry?.kind)) {
651
- return;
652
- }
653
- switch (getCallKind4(node)) {
654
- case "setTimeout": {
655
- const timeoutIdNode = VAR__namespace.getVariableDeclaratorId(node);
656
- if (timeoutIdNode == null) {
657
- context.report({
658
- messageId: "expectedTimeoutId",
659
- node
660
- });
661
- break;
662
- }
663
- sEntries.push({
664
- kind: "timeout",
665
- node,
666
- callee: node.callee,
667
- phase: fEntry.kind,
668
- timerId: timeoutIdNode
669
- });
670
- break;
671
- }
672
- case "clearTimeout": {
673
- const [timeoutIdNode] = node.arguments;
674
- if (timeoutIdNode == null) {
675
- break;
676
- }
677
- rEntries.push({
678
- kind: "timeout",
679
- node,
680
- callee: node.callee,
681
- phase: fEntry.kind,
682
- timerId: timeoutIdNode
683
- });
684
- break;
685
- }
686
- }
687
- },
688
- ["Program:exit"]() {
689
- for (const sEntry of sEntries) {
690
- if (rEntries.some((rEntry) => isInverseEntry(sEntry, rEntry))) {
691
- continue;
692
- }
693
- switch (sEntry.phase) {
694
- case "setup":
695
- case "cleanup":
696
- context.report({
697
- messageId: "expectedClearTimeoutInCleanup",
698
- node: sEntry.node,
699
- data: {
700
- kind: "useEffect"
701
- }
702
- });
703
- continue;
704
- case "mount":
705
- case "unmount":
706
- context.report({
707
- messageId: "expectedClearTimeoutInUnmount",
708
- node: sEntry.node,
709
- data: {
710
- kind: "componentDidMount"
711
- }
712
- });
713
- continue;
714
- }
715
- }
716
- }
717
- };
567
+ function create(context) {
568
+ if (!context.sourceCode.text.includes("setTimeout")) return {};
569
+ const fEntries = [];
570
+ const sEntries = [];
571
+ const rEntries = [];
572
+ function isInverseEntry(a, b) {
573
+ return __eslint_react_core.isInstanceIdEqual(context, a.timerId, b.timerId);
574
+ }
575
+ return {
576
+ [":function"](node) {
577
+ const kind = getPhaseKindOfFunction(node) ?? "other";
578
+ fEntries.push({
579
+ kind,
580
+ node
581
+ });
582
+ },
583
+ [":function:exit"]() {
584
+ fEntries.pop();
585
+ },
586
+ ["CallExpression"](node) {
587
+ const fEntry = fEntries.findLast((f) => f.kind !== "other");
588
+ if (!__eslint_react_core.ComponentPhaseRelevance.has(fEntry?.kind)) return;
589
+ switch (getCallKind(node)) {
590
+ case "setTimeout": {
591
+ const timeoutIdNode = __eslint_react_var.getVariableDeclaratorId(node);
592
+ if (timeoutIdNode == null) {
593
+ context.report({
594
+ messageId: "expectedTimeoutId",
595
+ node
596
+ });
597
+ break;
598
+ }
599
+ sEntries.push({
600
+ kind: "timeout",
601
+ node,
602
+ callee: node.callee,
603
+ phase: fEntry.kind,
604
+ timerId: timeoutIdNode
605
+ });
606
+ break;
607
+ }
608
+ case "clearTimeout": {
609
+ const [timeoutIdNode] = node.arguments;
610
+ if (timeoutIdNode == null) break;
611
+ rEntries.push({
612
+ kind: "timeout",
613
+ node,
614
+ callee: node.callee,
615
+ phase: fEntry.kind,
616
+ timerId: timeoutIdNode
617
+ });
618
+ break;
619
+ }
620
+ }
621
+ },
622
+ ["Program:exit"]() {
623
+ for (const sEntry of sEntries) {
624
+ if (rEntries.some((rEntry) => isInverseEntry(sEntry, rEntry))) continue;
625
+ switch (sEntry.phase) {
626
+ case "setup":
627
+ case "cleanup":
628
+ context.report({
629
+ messageId: "expectedClearTimeoutInCleanup",
630
+ node: sEntry.node,
631
+ data: { kind: "useEffect" }
632
+ });
633
+ continue;
634
+ case "mount":
635
+ case "unmount":
636
+ context.report({
637
+ messageId: "expectedClearTimeoutInUnmount",
638
+ node: sEntry.node,
639
+ data: { kind: "componentDidMount" }
640
+ });
641
+ continue;
642
+ }
643
+ }
644
+ }
645
+ };
718
646
  }
719
647
 
720
- // src/plugin.ts
721
- var plugin = {
722
- meta: {
723
- name: name2,
724
- version
725
- },
726
- rules: {
727
- "no-leaked-event-listener": no_leaked_event_listener_default,
728
- "no-leaked-interval": no_leaked_interval_default,
729
- "no-leaked-resize-observer": no_leaked_resize_observer_default,
730
- "no-leaked-timeout": no_leaked_timeout_default
731
- }
648
+ //#endregion
649
+ //#region src/plugin.ts
650
+ const plugin = {
651
+ meta: {
652
+ name,
653
+ version
654
+ },
655
+ rules: {
656
+ "no-leaked-event-listener": no_leaked_event_listener_default,
657
+ "no-leaked-interval": no_leaked_interval_default,
658
+ "no-leaked-resize-observer": no_leaked_resize_observer_default,
659
+ "no-leaked-timeout": no_leaked_timeout_default
660
+ }
732
661
  };
733
662
 
734
- // src/index.ts
735
- var { toFlatConfig, toLegacyConfig } = shared.getConfigAdapters("react-web-api", plugin);
736
- var index_default = {
737
- ...plugin,
738
- configs: {
739
- ["recommended"]: toFlatConfig(recommended_exports),
740
- ["recommended-legacy"]: toLegacyConfig(recommended_exports)
741
- }
663
+ //#endregion
664
+ //#region src/index.ts
665
+ const { toFlatConfig, toLegacyConfig } = (0, __eslint_react_shared.getConfigAdapters)("react-web-api", plugin);
666
+ var src_default = {
667
+ ...plugin,
668
+ configs: {
669
+ ["recommended"]: toFlatConfig(recommended_exports),
670
+ ["recommended-legacy"]: toLegacyConfig(recommended_exports)
671
+ }
742
672
  };
743
673
 
744
- module.exports = index_default;
674
+ //#endregion
675
+ module.exports = src_default;