eslint-plugin-react-web-api 2.0.1-next.2 → 2.0.1-next.4
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 +29 -29
- package/package.json +8 -8
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { DEFAULT_ESLINT_REACT_SETTINGS, getConfigAdapters, getDocsUrl } from "@eslint-react/shared";
|
|
2
2
|
import * as AST from "@eslint-react/ast";
|
|
3
|
-
import
|
|
3
|
+
import { ComponentPhaseRelevance, getInstanceId, getPhaseKindOfFunction, isInstanceIdEqual, isInversePhase } from "@eslint-react/core";
|
|
4
4
|
import { or, unit } from "@eslint-react/eff";
|
|
5
|
-
import
|
|
5
|
+
import { findAssignmentTarget, findProperty, findVariable, getVariableDefinitionNode, isNodeValueEqual } from "@eslint-react/var";
|
|
6
6
|
import { AST_NODE_TYPES, ESLintUtils } from "@typescript-eslint/utils";
|
|
7
7
|
import { getStaticValue } from "@typescript-eslint/utils/ast-utils";
|
|
8
8
|
import { P, isMatching, match } from "ts-pattern";
|
|
@@ -38,7 +38,7 @@ const settings = { "react-x": DEFAULT_ESLINT_REACT_SETTINGS };
|
|
|
38
38
|
//#endregion
|
|
39
39
|
//#region package.json
|
|
40
40
|
var name = "eslint-plugin-react-web-api";
|
|
41
|
-
var version = "2.0.1-next.
|
|
41
|
+
var version = "2.0.1-next.4";
|
|
42
42
|
|
|
43
43
|
//#endregion
|
|
44
44
|
//#region src/utils/create-rule.ts
|
|
@@ -65,19 +65,19 @@ function getCallKind$3(node) {
|
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
function getFunctionKind$1(node) {
|
|
68
|
-
return
|
|
68
|
+
return getPhaseKindOfFunction(node) ?? "other";
|
|
69
69
|
}
|
|
70
70
|
function getSignalValueExpression(node, initialScope) {
|
|
71
71
|
if (node == null) return unit;
|
|
72
72
|
switch (node.type) {
|
|
73
|
-
case AST_NODE_TYPES.Identifier: return getSignalValueExpression(
|
|
73
|
+
case AST_NODE_TYPES.Identifier: return getSignalValueExpression(getVariableDefinitionNode(findVariable(node, initialScope), 0), initialScope);
|
|
74
74
|
case AST_NODE_TYPES.MemberExpression: return node;
|
|
75
75
|
default: return unit;
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
function getOptions(node, initialScope) {
|
|
79
79
|
function findProp(properties, propName) {
|
|
80
|
-
return
|
|
80
|
+
return findProperty(propName, properties, initialScope);
|
|
81
81
|
}
|
|
82
82
|
function getPropValue(prop, filter = (a) => true) {
|
|
83
83
|
if (prop?.type !== AST_NODE_TYPES.Property) return unit;
|
|
@@ -96,8 +96,8 @@ function getOptions(node, initialScope) {
|
|
|
96
96
|
function getOpts(node$1) {
|
|
97
97
|
switch (node$1.type) {
|
|
98
98
|
case AST_NODE_TYPES.Identifier: {
|
|
99
|
-
const variable =
|
|
100
|
-
const variableNode =
|
|
99
|
+
const variable = findVariable(node$1, initialScope);
|
|
100
|
+
const variableNode = getVariableDefinitionNode(variable, 0);
|
|
101
101
|
if (variableNode?.type === AST_NODE_TYPES.ObjectExpression) return getOpts(variableNode);
|
|
102
102
|
return defaultOptions;
|
|
103
103
|
}
|
|
@@ -154,8 +154,8 @@ function create$3(context) {
|
|
|
154
154
|
function isInverseEntry(aEntry, rEntry) {
|
|
155
155
|
const { type: aType, callee: aCallee, capture: aCapture, listener: aListener, phase: aPhase } = aEntry;
|
|
156
156
|
const { type: rType, callee: rCallee, capture: rCapture, listener: rListener, phase: rPhase } = rEntry;
|
|
157
|
-
if (!
|
|
158
|
-
return isSameObject(aCallee, rCallee) && AST.isNodeEqual(aListener, rListener) &&
|
|
157
|
+
if (!isInversePhase(aPhase, rPhase)) return false;
|
|
158
|
+
return isSameObject(aCallee, rCallee) && AST.isNodeEqual(aListener, rListener) && isNodeValueEqual(aType, rType, [context.sourceCode.getScope(aType), context.sourceCode.getScope(rType)]) && aCapture === rCapture;
|
|
159
159
|
}
|
|
160
160
|
function checkInlineFunction(node, callKind, options) {
|
|
161
161
|
const listener = node.arguments.at(1);
|
|
@@ -181,7 +181,7 @@ function create$3(context) {
|
|
|
181
181
|
["CallExpression"](node) {
|
|
182
182
|
const fKind = fEntries.findLast((x) => x.kind !== "other")?.kind;
|
|
183
183
|
if (fKind == null) return;
|
|
184
|
-
if (!
|
|
184
|
+
if (!ComponentPhaseRelevance.has(fKind)) return;
|
|
185
185
|
match(getCallKind$3(node)).with("addEventListener", (callKind) => {
|
|
186
186
|
const [type, listener, options] = node.arguments;
|
|
187
187
|
if (type == null || listener == null) return;
|
|
@@ -278,11 +278,11 @@ function create$2(context) {
|
|
|
278
278
|
const sEntries = [];
|
|
279
279
|
const cEntries = [];
|
|
280
280
|
function isInverseEntry(a, b) {
|
|
281
|
-
return
|
|
281
|
+
return isInstanceIdEqual(context, a.timerId, b.timerId);
|
|
282
282
|
}
|
|
283
283
|
return {
|
|
284
284
|
[":function"](node) {
|
|
285
|
-
const kind =
|
|
285
|
+
const kind = getPhaseKindOfFunction(node) ?? "other";
|
|
286
286
|
fEntries.push({
|
|
287
287
|
kind,
|
|
288
288
|
node
|
|
@@ -296,8 +296,8 @@ function create$2(context) {
|
|
|
296
296
|
case "setInterval": {
|
|
297
297
|
const fEntry = fEntries.findLast((x) => x.kind !== "other");
|
|
298
298
|
if (fEntry == null) break;
|
|
299
|
-
if (!
|
|
300
|
-
const intervalIdNode =
|
|
299
|
+
if (!ComponentPhaseRelevance.has(fEntry.kind)) break;
|
|
300
|
+
const intervalIdNode = findAssignmentTarget(node);
|
|
301
301
|
if (intervalIdNode == null) {
|
|
302
302
|
context.report({
|
|
303
303
|
messageId: "expectedIntervalId",
|
|
@@ -317,7 +317,7 @@ function create$2(context) {
|
|
|
317
317
|
case "clearInterval": {
|
|
318
318
|
const fEntry = fEntries.findLast((x) => x.kind !== "other");
|
|
319
319
|
if (fEntry == null) break;
|
|
320
|
-
if (!
|
|
320
|
+
if (!ComponentPhaseRelevance.has(fEntry.kind)) break;
|
|
321
321
|
const [intervalIdNode] = node.arguments;
|
|
322
322
|
if (intervalIdNode == null) break;
|
|
323
323
|
cEntries.push({
|
|
@@ -368,7 +368,7 @@ function isFromObserver(context, node) {
|
|
|
368
368
|
switch (true) {
|
|
369
369
|
case node.type === AST_NODE_TYPES.Identifier: {
|
|
370
370
|
const initialScope = context.sourceCode.getScope(node);
|
|
371
|
-
const object =
|
|
371
|
+
const object = getVariableDefinitionNode(findVariable(node, initialScope), 0);
|
|
372
372
|
return isNewResizeObserver(object);
|
|
373
373
|
}
|
|
374
374
|
case node.type === AST_NODE_TYPES.MemberExpression: return isFromObserver(context, node.object);
|
|
@@ -383,7 +383,7 @@ function getCallKind$1(context, node) {
|
|
|
383
383
|
}
|
|
384
384
|
}
|
|
385
385
|
function getFunctionKind(node) {
|
|
386
|
-
return
|
|
386
|
+
return getPhaseKindOfFunction(node) ?? "other";
|
|
387
387
|
}
|
|
388
388
|
var no_leaked_resize_observer_default = createRule({
|
|
389
389
|
meta: {
|
|
@@ -424,7 +424,7 @@ function create$1(context) {
|
|
|
424
424
|
["CallExpression"](node) {
|
|
425
425
|
if (node.callee.type !== AST_NODE_TYPES.MemberExpression) return;
|
|
426
426
|
const fKind = fEntries.findLast((x) => x.kind !== "other")?.kind;
|
|
427
|
-
if (fKind == null || !
|
|
427
|
+
if (fKind == null || !ComponentPhaseRelevance.has(fKind)) return;
|
|
428
428
|
const { object } = node.callee;
|
|
429
429
|
match(getCallKind$1(context, node)).with("disconnect", () => {
|
|
430
430
|
dEntries.push({
|
|
@@ -464,9 +464,9 @@ function create$1(context) {
|
|
|
464
464
|
["NewExpression"](node) {
|
|
465
465
|
const fEntry = fEntries.findLast((x) => x.kind !== "other");
|
|
466
466
|
if (fEntry == null) return;
|
|
467
|
-
if (!
|
|
467
|
+
if (!ComponentPhaseRelevance.has(fEntry.kind)) return;
|
|
468
468
|
if (!isNewResizeObserver(node)) return;
|
|
469
|
-
const id =
|
|
469
|
+
const id = getInstanceId(node);
|
|
470
470
|
if (id == null) {
|
|
471
471
|
context.report({
|
|
472
472
|
messageId: "unexpectedFloatingInstance",
|
|
@@ -483,9 +483,9 @@ function create$1(context) {
|
|
|
483
483
|
},
|
|
484
484
|
["Program:exit"]() {
|
|
485
485
|
for (const { id, node, phaseNode } of observers) {
|
|
486
|
-
if (dEntries.some((e) =>
|
|
487
|
-
const oentries = oEntries.filter((e) =>
|
|
488
|
-
const uentries = uEntries.filter((e) =>
|
|
486
|
+
if (dEntries.some((e) => isInstanceIdEqual(context, e.observer, id))) continue;
|
|
487
|
+
const oentries = oEntries.filter((e) => isInstanceIdEqual(context, e.observer, id));
|
|
488
|
+
const uentries = uEntries.filter((e) => isInstanceIdEqual(context, e.observer, id));
|
|
489
489
|
const isDynamic = (node$1) => node$1?.type === AST_NODE_TYPES.CallExpression || isConditional(node$1);
|
|
490
490
|
const isPhaseNode = (node$1) => node$1 === phaseNode;
|
|
491
491
|
if (oentries.some((e) => !isPhaseNode(AST.findParentNode(e.node, or(isDynamic, isPhaseNode))))) {
|
|
@@ -496,7 +496,7 @@ function create$1(context) {
|
|
|
496
496
|
continue;
|
|
497
497
|
}
|
|
498
498
|
for (const oEntry of oentries) {
|
|
499
|
-
if (uentries.some((uEntry) =>
|
|
499
|
+
if (uentries.some((uEntry) => isInstanceIdEqual(context, uEntry.element, oEntry.element))) continue;
|
|
500
500
|
context.report({
|
|
501
501
|
messageId: "expectedDisconnectOrUnobserveInCleanup",
|
|
502
502
|
node: oEntry.node
|
|
@@ -542,11 +542,11 @@ function create(context) {
|
|
|
542
542
|
const sEntries = [];
|
|
543
543
|
const rEntries = [];
|
|
544
544
|
function isInverseEntry(a, b) {
|
|
545
|
-
return
|
|
545
|
+
return isInstanceIdEqual(context, a.timerId, b.timerId);
|
|
546
546
|
}
|
|
547
547
|
return {
|
|
548
548
|
[":function"](node) {
|
|
549
|
-
const kind =
|
|
549
|
+
const kind = getPhaseKindOfFunction(node) ?? "other";
|
|
550
550
|
fEntries.push({
|
|
551
551
|
kind,
|
|
552
552
|
node
|
|
@@ -557,10 +557,10 @@ function create(context) {
|
|
|
557
557
|
},
|
|
558
558
|
["CallExpression"](node) {
|
|
559
559
|
const fEntry = fEntries.findLast((f) => f.kind !== "other");
|
|
560
|
-
if (!
|
|
560
|
+
if (!ComponentPhaseRelevance.has(fEntry?.kind)) return;
|
|
561
561
|
switch (getCallKind(node)) {
|
|
562
562
|
case "setTimeout": {
|
|
563
|
-
const timeoutIdNode =
|
|
563
|
+
const timeoutIdNode = findAssignmentTarget(node);
|
|
564
564
|
if (timeoutIdNode == null) {
|
|
565
565
|
context.report({
|
|
566
566
|
messageId: "expectedTimeoutId",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-react-web-api",
|
|
3
|
-
"version": "2.0.1-next.
|
|
3
|
+
"version": "2.0.1-next.4",
|
|
4
4
|
"description": "ESLint React's ESLint plugin for interacting with Web APIs",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -40,15 +40,15 @@
|
|
|
40
40
|
"@typescript-eslint/utils": "^8.44.1",
|
|
41
41
|
"string-ts": "^2.2.1",
|
|
42
42
|
"ts-pattern": "^5.8.0",
|
|
43
|
-
"@eslint-react/ast": "2.0.1-next.
|
|
44
|
-
"@eslint-react/
|
|
45
|
-
"@eslint-react/eff": "2.0.1-next.
|
|
46
|
-
"@eslint-react/
|
|
47
|
-
"@eslint-react/
|
|
48
|
-
"@eslint-react/var": "2.0.1-next.
|
|
43
|
+
"@eslint-react/ast": "2.0.1-next.4",
|
|
44
|
+
"@eslint-react/kit": "2.0.1-next.4",
|
|
45
|
+
"@eslint-react/eff": "2.0.1-next.4",
|
|
46
|
+
"@eslint-react/shared": "2.0.1-next.4",
|
|
47
|
+
"@eslint-react/core": "2.0.1-next.4",
|
|
48
|
+
"@eslint-react/var": "2.0.1-next.4"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
|
-
"@types/react": "^19.1.
|
|
51
|
+
"@types/react": "^19.1.14",
|
|
52
52
|
"@types/react-dom": "^19.1.9",
|
|
53
53
|
"tsdown": "^0.15.4",
|
|
54
54
|
"@local/configs": "0.0.0"
|