eslint-plugin-react-web-api 1.20.2-next.1 → 1.20.2-next.3
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 +54 -54
- package/dist/index.mjs +2 -2
- package/package.json +9 -9
package/dist/index.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
var AST2 = require('@eslint-react/ast');
|
|
4
4
|
var core = require('@eslint-react/core');
|
|
5
|
+
var eff = require('@eslint-react/eff');
|
|
5
6
|
var JSX = require('@eslint-react/jsx');
|
|
6
|
-
var tools = require('@eslint-react/tools');
|
|
7
7
|
var VAR2 = require('@eslint-react/var');
|
|
8
8
|
var utils = require('@typescript-eslint/utils');
|
|
9
9
|
var tsPattern = require('ts-pattern');
|
|
@@ -34,24 +34,24 @@ var VAR2__namespace = /*#__PURE__*/_interopNamespace(VAR2);
|
|
|
34
34
|
|
|
35
35
|
// package.json
|
|
36
36
|
var name = "eslint-plugin-react-web-api";
|
|
37
|
-
var version = "1.20.2-next.
|
|
37
|
+
var version = "1.20.2-next.3";
|
|
38
38
|
var createRule = shared.createRuleForPlugin("web-api");
|
|
39
39
|
function getInstanceID(node, prev) {
|
|
40
40
|
switch (true) {
|
|
41
41
|
case (node.type === types.AST_NODE_TYPES.VariableDeclarator && node.init === prev):
|
|
42
|
-
return
|
|
42
|
+
return eff.O.some(node.id);
|
|
43
43
|
case (node.type === types.AST_NODE_TYPES.AssignmentExpression && node.right === prev):
|
|
44
|
-
return
|
|
44
|
+
return eff.O.some(node.left);
|
|
45
45
|
case (node.type === types.AST_NODE_TYPES.PropertyDefinition && node.value === prev):
|
|
46
|
-
return
|
|
46
|
+
return eff.O.some(node.key);
|
|
47
47
|
case (node.type === types.AST_NODE_TYPES.BlockStatement || node.type === types.AST_NODE_TYPES.Program || node.parent === node):
|
|
48
|
-
return
|
|
48
|
+
return eff.O.none();
|
|
49
49
|
default:
|
|
50
50
|
return getInstanceID(node.parent, node);
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
function getPhaseKindOfFunction(node) {
|
|
54
|
-
return tsPattern.match(node).when(core.isSetupFunction, () =>
|
|
54
|
+
return tsPattern.match(node).when(core.isSetupFunction, () => eff.O.some("setup")).when(core.isCleanupFunction, () => eff.O.some("cleanup")).when(core.isComponentDidMountFunction, () => eff.O.some("mount")).when(core.isComponentWillUnmountFunction, () => eff.O.some("unmount")).otherwise(eff.O.none);
|
|
55
55
|
}
|
|
56
56
|
function isInstanceIDEqual(a, b, context) {
|
|
57
57
|
return AST2__namespace.isNodeEqual(a, b) || VAR2__namespace.isNodeValueEqual(a, b, [
|
|
@@ -59,8 +59,8 @@ function isInstanceIDEqual(a, b, context) {
|
|
|
59
59
|
context.sourceCode.getScope(b)
|
|
60
60
|
]);
|
|
61
61
|
}
|
|
62
|
-
var EventListenerEntry =
|
|
63
|
-
var ObserverEntry =
|
|
62
|
+
var EventListenerEntry = eff.Data.taggedEnum();
|
|
63
|
+
var ObserverEntry = eff.Data.taggedEnum();
|
|
64
64
|
|
|
65
65
|
// src/rules/no-leaked-event-listener.ts
|
|
66
66
|
var RULE_NAME = "no-leaked-event-listener";
|
|
@@ -68,9 +68,9 @@ var RULE_FEATURES = [
|
|
|
68
68
|
"CHK"
|
|
69
69
|
];
|
|
70
70
|
var defaultOptions = {
|
|
71
|
-
capture:
|
|
72
|
-
once:
|
|
73
|
-
signal:
|
|
71
|
+
capture: eff.O.some(false),
|
|
72
|
+
once: eff.O.some(false),
|
|
73
|
+
signal: eff.O.none()
|
|
74
74
|
};
|
|
75
75
|
function getCallKind(node) {
|
|
76
76
|
switch (true) {
|
|
@@ -83,18 +83,18 @@ function getCallKind(node) {
|
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
function getFunctionKind(node) {
|
|
86
|
-
return
|
|
86
|
+
return eff.O.getOrElse(getPhaseKindOfFunction(node), eff.F.constant("other"));
|
|
87
87
|
}
|
|
88
88
|
function getOptions(node, initialScope) {
|
|
89
89
|
const findProp = (properties, propName) => {
|
|
90
90
|
return JSX__namespace.findPropInProperties(properties, initialScope)(propName);
|
|
91
91
|
};
|
|
92
92
|
const getPropValue = (prop) => {
|
|
93
|
-
if (prop.type !== utils.AST_NODE_TYPES.Property) return
|
|
93
|
+
if (prop.type !== utils.AST_NODE_TYPES.Property) return eff.O.none();
|
|
94
94
|
const { value } = prop;
|
|
95
95
|
switch (value.type) {
|
|
96
96
|
case utils.AST_NODE_TYPES.Literal: {
|
|
97
|
-
return
|
|
97
|
+
return eff.O.some(value.value);
|
|
98
98
|
}
|
|
99
99
|
default: {
|
|
100
100
|
return VAR2__namespace.getStaticValue(value, initialScope);
|
|
@@ -104,38 +104,38 @@ function getOptions(node, initialScope) {
|
|
|
104
104
|
function getOpts(node2) {
|
|
105
105
|
switch (node2.type) {
|
|
106
106
|
case utils.AST_NODE_TYPES.Identifier: {
|
|
107
|
-
return
|
|
107
|
+
return eff.F.pipe(
|
|
108
108
|
VAR2__namespace.findVariable(node2, initialScope),
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
109
|
+
eff.O.flatMap(VAR2__namespace.getVariableNode(0)),
|
|
110
|
+
eff.O.filter(AST2__namespace.is(utils.AST_NODE_TYPES.ObjectExpression)),
|
|
111
|
+
eff.O.map(getOpts),
|
|
112
|
+
eff.O.getOrElse(() => defaultOptions)
|
|
113
113
|
);
|
|
114
114
|
}
|
|
115
115
|
case utils.AST_NODE_TYPES.Literal: {
|
|
116
|
-
return { ...defaultOptions, capture:
|
|
116
|
+
return { ...defaultOptions, capture: eff.O.some(!!node2.value) };
|
|
117
117
|
}
|
|
118
118
|
case utils.AST_NODE_TYPES.ObjectExpression: {
|
|
119
119
|
const pOnce = findProp(node2.properties, "once");
|
|
120
|
-
const vOnce =
|
|
120
|
+
const vOnce = eff.O.flatMap(pOnce, getPropValue).pipe(eff.O.filter(eff.isBoolean));
|
|
121
121
|
const pCapture = findProp(node2.properties, "capture");
|
|
122
|
-
const vCapture =
|
|
122
|
+
const vCapture = eff.O.flatMap(pCapture, getPropValue).pipe(eff.O.filter(eff.isBoolean));
|
|
123
123
|
const pSignal = findProp(node2.properties, "signal");
|
|
124
|
-
const vSignal =
|
|
125
|
-
if (prop.type !== utils.AST_NODE_TYPES.Property) return
|
|
124
|
+
const vSignal = eff.O.flatMap(pSignal, (prop) => {
|
|
125
|
+
if (prop.type !== utils.AST_NODE_TYPES.Property) return eff.O.none();
|
|
126
126
|
const { value } = prop;
|
|
127
127
|
const getSignalExp = (node3) => {
|
|
128
128
|
switch (node3.type) {
|
|
129
129
|
case utils.AST_NODE_TYPES.Identifier:
|
|
130
|
-
return
|
|
130
|
+
return eff.F.pipe(
|
|
131
131
|
VAR2__namespace.findVariable(node3, initialScope),
|
|
132
|
-
|
|
133
|
-
|
|
132
|
+
eff.O.flatMap(VAR2__namespace.getVariableNode(0)),
|
|
133
|
+
eff.O.flatMap(getSignalExp)
|
|
134
134
|
);
|
|
135
135
|
case utils.AST_NODE_TYPES.MemberExpression:
|
|
136
|
-
return
|
|
136
|
+
return eff.O.some(node3);
|
|
137
137
|
default:
|
|
138
|
-
return
|
|
138
|
+
return eff.O.none();
|
|
139
139
|
}
|
|
140
140
|
};
|
|
141
141
|
return getSignalExp(value);
|
|
@@ -173,15 +173,15 @@ var no_leaked_event_listener_default = createRule({
|
|
|
173
173
|
const abortedSignals = [];
|
|
174
174
|
function checkInlineFunction(node, callKind, options) {
|
|
175
175
|
const [_, listener] = node.arguments;
|
|
176
|
-
if (!AST2__namespace.isFunction(listener)) return
|
|
177
|
-
if (
|
|
178
|
-
return
|
|
176
|
+
if (!AST2__namespace.isFunction(listener)) return eff.O.none();
|
|
177
|
+
if (eff.O.isSome(options.signal)) return eff.O.none();
|
|
178
|
+
return eff.O.some({
|
|
179
179
|
messageId: "noLeakedEventListenerOfInlineFunction",
|
|
180
180
|
node: listener,
|
|
181
181
|
data: { eventMethodKind: callKind }
|
|
182
182
|
});
|
|
183
183
|
}
|
|
184
|
-
const isSameObject =
|
|
184
|
+
const isSameObject = eff.F.dual(2, (a, b) => {
|
|
185
185
|
switch (true) {
|
|
186
186
|
case (a.type === utils.AST_NODE_TYPES.MemberExpression && b.type === utils.AST_NODE_TYPES.MemberExpression):
|
|
187
187
|
return AST2__namespace.isNodeEqual(a.object, b.object);
|
|
@@ -190,14 +190,14 @@ var no_leaked_event_listener_default = createRule({
|
|
|
190
190
|
return false;
|
|
191
191
|
}
|
|
192
192
|
});
|
|
193
|
-
const isInverseEntry =
|
|
193
|
+
const isInverseEntry = eff.F.dual(2, (aEntry, rEntry) => {
|
|
194
194
|
const { type: aType, callee: aCallee, capture: aCapture, listener: aListener, phase: aPhase } = aEntry;
|
|
195
195
|
const { type: rType, callee: rCallee, capture: rCapture, listener: rListener, phase: rPhase } = rEntry;
|
|
196
196
|
if (!core.isInversePhase(aPhase, rPhase)) return false;
|
|
197
197
|
return isSameObject(aCallee, rCallee) && AST2__namespace.isNodeEqual(aListener, rListener) && VAR2__namespace.isNodeValueEqual(aType, rType, [
|
|
198
198
|
context.sourceCode.getScope(aType),
|
|
199
199
|
context.sourceCode.getScope(rType)
|
|
200
|
-
]) &&
|
|
200
|
+
]) && eff.O.getOrElse(aCapture, eff.F.constFalse) === eff.O.getOrElse(rCapture, eff.F.constFalse);
|
|
201
201
|
});
|
|
202
202
|
return {
|
|
203
203
|
[":function"](node) {
|
|
@@ -216,7 +216,7 @@ var no_leaked_event_listener_default = createRule({
|
|
|
216
216
|
if (!type || !listener) return;
|
|
217
217
|
const opts = options ? getOptions(options, context.sourceCode.getScope(options)) : defaultOptions;
|
|
218
218
|
const { callee } = node;
|
|
219
|
-
|
|
219
|
+
eff.O.map(checkInlineFunction(node, callKind, opts), context.report);
|
|
220
220
|
aEntries.push(EventListenerEntry.AddEventListener({
|
|
221
221
|
...opts,
|
|
222
222
|
type,
|
|
@@ -230,7 +230,7 @@ var no_leaked_event_listener_default = createRule({
|
|
|
230
230
|
if (!type || !listener) return;
|
|
231
231
|
const opts = options ? getOptions(options, context.sourceCode.getScope(options)) : defaultOptions;
|
|
232
232
|
const { callee } = node;
|
|
233
|
-
|
|
233
|
+
eff.O.map(checkInlineFunction(node, callKind, opts), context.report);
|
|
234
234
|
rEntries.push(EventListenerEntry.RemoveEventListener({
|
|
235
235
|
...opts,
|
|
236
236
|
type,
|
|
@@ -241,11 +241,11 @@ var no_leaked_event_listener_default = createRule({
|
|
|
241
241
|
}));
|
|
242
242
|
}).with("abort", () => {
|
|
243
243
|
abortedSignals.push(node.callee);
|
|
244
|
-
}).otherwise(
|
|
244
|
+
}).otherwise(eff.F.constVoid);
|
|
245
245
|
},
|
|
246
246
|
["Program:exit"]() {
|
|
247
247
|
for (const aEntry of aEntries) {
|
|
248
|
-
if (
|
|
248
|
+
if (eff.O.exists(aEntry.signal, (signal) => abortedSignals.some(isSameObject(signal)))) continue;
|
|
249
249
|
if (rEntries.some(isInverseEntry(aEntry))) continue;
|
|
250
250
|
switch (aEntry.phase) {
|
|
251
251
|
case "cleanup":
|
|
@@ -306,12 +306,12 @@ var no_leaked_interval_default = createRule({
|
|
|
306
306
|
const fStack = [];
|
|
307
307
|
const sEntries = [];
|
|
308
308
|
const cEntries = [];
|
|
309
|
-
const isInverseEntry =
|
|
309
|
+
const isInverseEntry = eff.F.dual(2, (a, b) => {
|
|
310
310
|
return isInstanceIDEqual(a.timerID, b.timerID, context);
|
|
311
311
|
});
|
|
312
312
|
return {
|
|
313
313
|
[":function"](node) {
|
|
314
|
-
const fKind =
|
|
314
|
+
const fKind = eff.O.getOrElse(getPhaseKindOfFunction(node), () => "other");
|
|
315
315
|
fStack.push([node, fKind]);
|
|
316
316
|
},
|
|
317
317
|
[":function:exit"]() {
|
|
@@ -338,7 +338,7 @@ var no_leaked_interval_default = createRule({
|
|
|
338
338
|
const [fNode, fKind] = fStack.findLast((f) => f.at(1) !== "other") ?? [];
|
|
339
339
|
if (!fNode || !fKind) break;
|
|
340
340
|
if (!core.ERPhaseRelevance.has(fKind)) break;
|
|
341
|
-
const intervalIdNode =
|
|
341
|
+
const intervalIdNode = eff.O.getOrNull(VAR2__namespace.getVariableDeclaratorID(node));
|
|
342
342
|
if (!intervalIdNode) {
|
|
343
343
|
context.report({
|
|
344
344
|
messageId: "noLeakedIntervalNoIntervalId",
|
|
@@ -398,10 +398,10 @@ function isNewResizeObserver(node) {
|
|
|
398
398
|
function isFromObserver(node, context) {
|
|
399
399
|
switch (true) {
|
|
400
400
|
case node.type === utils.AST_NODE_TYPES.Identifier:
|
|
401
|
-
return
|
|
401
|
+
return eff.F.pipe(
|
|
402
402
|
VAR2__namespace.findVariable(node, context.sourceCode.getScope(node)),
|
|
403
|
-
|
|
404
|
-
|
|
403
|
+
eff.O.flatMap(VAR2__namespace.getVariableNode(0)),
|
|
404
|
+
eff.O.exists(isNewResizeObserver)
|
|
405
405
|
);
|
|
406
406
|
case node.type === utils.AST_NODE_TYPES.MemberExpression:
|
|
407
407
|
return isFromObserver(node.object, context);
|
|
@@ -420,7 +420,7 @@ function getCallKind3(node, context) {
|
|
|
420
420
|
}
|
|
421
421
|
}
|
|
422
422
|
function getFunctionKind2(node) {
|
|
423
|
-
return
|
|
423
|
+
return eff.O.getOrElse(getPhaseKindOfFunction(node), eff.F.constant("other"));
|
|
424
424
|
}
|
|
425
425
|
var no_leaked_resize_observer_default = createRule({
|
|
426
426
|
meta: {
|
|
@@ -493,14 +493,14 @@ var no_leaked_resize_observer_default = createRule({
|
|
|
493
493
|
phase: fKind
|
|
494
494
|
})
|
|
495
495
|
);
|
|
496
|
-
}).otherwise(
|
|
496
|
+
}).otherwise(eff.F.constVoid);
|
|
497
497
|
},
|
|
498
498
|
["NewExpression"](node) {
|
|
499
499
|
const [fNode, fKind] = fStack.findLast((f) => f.at(1) !== "other") ?? [];
|
|
500
500
|
if (!fNode || !core.ERPhaseRelevance.has(fKind)) return;
|
|
501
501
|
if (!isNewResizeObserver(node)) return;
|
|
502
502
|
const id = getInstanceID(node);
|
|
503
|
-
if (
|
|
503
|
+
if (eff.O.isNone(id)) {
|
|
504
504
|
context.report({
|
|
505
505
|
messageId: "noLeakedResizeObserverNoFloatingInstance",
|
|
506
506
|
node
|
|
@@ -514,9 +514,9 @@ var no_leaked_resize_observer_default = createRule({
|
|
|
514
514
|
if (dEntries.some((e) => isInstanceIDEqual(e.observer, id, context))) continue;
|
|
515
515
|
const oentries = oEntries.filter((e) => isInstanceIDEqual(e.observer, id, context));
|
|
516
516
|
const uentries = uEntries.filter((e) => isInstanceIDEqual(e.observer, id, context));
|
|
517
|
-
const isDynamic =
|
|
517
|
+
const isDynamic = eff.or(AST2__namespace.isConditional, AST2__namespace.is(utils.AST_NODE_TYPES.CallExpression));
|
|
518
518
|
const isPhaseNode = (node2) => node2 === phaseNode;
|
|
519
|
-
const hasDynamicallyAdded = oentries.some((e) =>
|
|
519
|
+
const hasDynamicallyAdded = oentries.some((e) => eff.O.exists(AST2__namespace.traverseUp(e.node, eff.or(isDynamic, isPhaseNode)), eff.not(isPhaseNode)));
|
|
520
520
|
if (hasDynamicallyAdded) {
|
|
521
521
|
context.report({ messageId: "noLeakedResizeObserverInControlFlow", node });
|
|
522
522
|
continue;
|
|
@@ -565,12 +565,12 @@ var no_leaked_timeout_default = createRule({
|
|
|
565
565
|
const fStack = [];
|
|
566
566
|
const sEntries = [];
|
|
567
567
|
const rEntries = [];
|
|
568
|
-
const isInverseEntry =
|
|
568
|
+
const isInverseEntry = eff.F.dual(2, (a, b) => {
|
|
569
569
|
return isInstanceIDEqual(a.timerID, b.timerID, context);
|
|
570
570
|
});
|
|
571
571
|
return {
|
|
572
572
|
[":function"](node) {
|
|
573
|
-
const fKind =
|
|
573
|
+
const fKind = eff.O.getOrElse(getPhaseKindOfFunction(node), () => "other");
|
|
574
574
|
fStack.push([node, fKind]);
|
|
575
575
|
},
|
|
576
576
|
[":function:exit"]() {
|
|
@@ -594,7 +594,7 @@ var no_leaked_timeout_default = createRule({
|
|
|
594
594
|
break;
|
|
595
595
|
}
|
|
596
596
|
case "setTimeout": {
|
|
597
|
-
const timeoutIdNode =
|
|
597
|
+
const timeoutIdNode = eff.O.getOrNull(VAR2__namespace.getVariableDeclaratorID(node));
|
|
598
598
|
if (!timeoutIdNode) {
|
|
599
599
|
context.report({
|
|
600
600
|
messageId: "noLeakedTimeoutNoTimeoutId",
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as AST2 from '@eslint-react/ast';
|
|
2
2
|
import { isInversePhase, ERPhaseRelevance, isSetupFunction, isCleanupFunction, isComponentDidMountFunction, isComponentWillUnmountFunction } from '@eslint-react/core';
|
|
3
|
+
import { Data, O, F, or, not, isBoolean } from '@eslint-react/eff';
|
|
3
4
|
import * as JSX from '@eslint-react/jsx';
|
|
4
|
-
import { Data, O, F, or, not, isBoolean } from '@eslint-react/tools';
|
|
5
5
|
import * as VAR2 from '@eslint-react/var';
|
|
6
6
|
import { AST_NODE_TYPES } from '@typescript-eslint/utils';
|
|
7
7
|
import { match, isMatching, P } from 'ts-pattern';
|
|
@@ -10,7 +10,7 @@ import { AST_NODE_TYPES as AST_NODE_TYPES$1 } from '@typescript-eslint/types';
|
|
|
10
10
|
|
|
11
11
|
// package.json
|
|
12
12
|
var name = "eslint-plugin-react-web-api";
|
|
13
|
-
var version = "1.20.2-next.
|
|
13
|
+
var version = "1.20.2-next.3";
|
|
14
14
|
var createRule = createRuleForPlugin("web-api");
|
|
15
15
|
function getInstanceID(node, prev) {
|
|
16
16
|
switch (true) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-react-web-api",
|
|
3
|
-
"version": "1.20.2-next.
|
|
3
|
+
"version": "1.20.2-next.3",
|
|
4
4
|
"description": "ESLint React's ESLint plugin for interacting with Web APIs",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -48,16 +48,16 @@
|
|
|
48
48
|
"@typescript-eslint/utils": "^8.18.1",
|
|
49
49
|
"birecord": "^0.1.1",
|
|
50
50
|
"ts-pattern": "^5.6.0",
|
|
51
|
-
"@eslint-react/ast": "1.20.2-next.
|
|
52
|
-
"@eslint-react/
|
|
53
|
-
"@eslint-react/
|
|
54
|
-
"@eslint-react/
|
|
55
|
-
"@eslint-react/
|
|
56
|
-
"@eslint-react/
|
|
57
|
-
"@eslint-react/
|
|
51
|
+
"@eslint-react/ast": "1.20.2-next.3",
|
|
52
|
+
"@eslint-react/jsx": "1.20.2-next.3",
|
|
53
|
+
"@eslint-react/core": "1.20.2-next.3",
|
|
54
|
+
"@eslint-react/eff": "1.20.2-next.3",
|
|
55
|
+
"@eslint-react/shared": "1.20.2-next.3",
|
|
56
|
+
"@eslint-react/types": "1.20.2-next.3",
|
|
57
|
+
"@eslint-react/var": "1.20.2-next.3"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
|
-
"@types/react": "^19.0.
|
|
60
|
+
"@types/react": "^19.0.2",
|
|
61
61
|
"@types/react-dom": "^19.0.2",
|
|
62
62
|
"string-ts": "^2.2.0",
|
|
63
63
|
"tsup": "^8.3.5",
|