eslint-plugin-react-x 5.23.2 → 5.23.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.
Files changed (2) hide show
  1. package/dist/index.js +36 -4
  2. package/package.json +7 -7
package/dist/index.js CHANGED
@@ -123,7 +123,8 @@ const rules$7 = {
123
123
  "react-x/no-unused-props": "off",
124
124
  "react-x/no-unused-state": "off",
125
125
  "react-x/refs": "off",
126
- "react-x/set-state-in-render": "off"
126
+ "react-x/set-state-in-render": "off",
127
+ "react-x/static-components": "off"
127
128
  };
128
129
 
129
130
  //#endregion
@@ -144,7 +145,7 @@ const rules$6 = {
144
145
  //#endregion
145
146
  //#region package.json
146
147
  var name$6 = "eslint-plugin-react-x";
147
- var version = "5.23.2";
148
+ var version = "5.23.4";
148
149
 
149
150
  //#endregion
150
151
  //#region src/utils/create-rule.ts
@@ -1681,13 +1682,29 @@ function getMutatedObject(mutation) {
1681
1682
  function inferDirectMutations(context, mutations, components) {
1682
1683
  const directMutations = [];
1683
1684
  for (const mutation of mutations) {
1684
- if (mutation.kind !== "value") continue;
1685
1685
  if (mutation.node.type === AST_NODE_TYPES.CallExpression && isKnownNonMutatingMethodCall(context, mutation.node)) continue;
1686
1686
  if (isRefMutation(context, mutation)) continue;
1687
1687
  const variable = findVariable(context.sourceCode.getScope(mutation.root), mutation.root);
1688
1688
  if (variable == null) continue;
1689
1689
  const origin = classifyFrozenOrigin(context, variable, components);
1690
1690
  if (origin == null) continue;
1691
+ if (mutation.kind === "binding") {
1692
+ switch (origin.kind) {
1693
+ case "props":
1694
+ directMutations.push({
1695
+ name: origin.name,
1696
+ detail: "It is a prop of this component and must not be reassigned.",
1697
+ node: mutation.node
1698
+ });
1699
+ break;
1700
+ case "state": directMutations.push({
1701
+ name: origin.name,
1702
+ detail: `It is a state value returned from '${origin.hook}' and must not be reassigned.`,
1703
+ node: mutation.node
1704
+ });
1705
+ }
1706
+ continue;
1707
+ }
1691
1708
  switch (origin.kind) {
1692
1709
  case "props":
1693
1710
  directMutations.push({
@@ -7974,7 +7991,7 @@ function isInitializedFromRef(context, name, initialScope, seen = /* @__PURE__ *
7974
7991
  return Check.isIdentifier(object) && (object.name === "ref" || object.name.endsWith("Ref"));
7975
7992
  }
7976
7993
  case init.type === AST_NODE_TYPES.CallExpression && core.isUseRefLikeCall(init, additionalRefHooks): return true;
7977
- case init.type === AST_NODE_TYPES.CallExpression: return getNestedIdentifiers(init).some((id) => isInitializedFromRef(context, id.name, context.sourceCode.getScope(id), seen));
7994
+ default: return getNestedIdentifiers(init).some((id) => isInitializedFromRef(context, id.name, context.sourceCode.getScope(id), seen));
7978
7995
  }
7979
7996
  }
7980
7997
  return false;
@@ -7987,6 +8004,7 @@ function isInitializedFromRef(context, name, initialScope, seen = /* @__PURE__ *
7987
8004
  * @returns `true` if the node is inside a ref-gated conditional block
7988
8005
  */
7989
8006
  function isRefGatedContext(context, node) {
8007
+ let child = node;
7990
8008
  let current = node.parent;
7991
8009
  while (current != null) {
7992
8010
  if (Check.isFunction(current)) break;
@@ -7996,10 +8014,24 @@ function isRefGatedContext(context, node) {
7996
8014
  if (current.type === AST_NODE_TYPES.ConditionalExpression) {
7997
8015
  if (isRefInExpression(context, current.test)) return true;
7998
8016
  }
8017
+ if (current.type === AST_NODE_TYPES.BlockStatement) {
8018
+ const index = current.body.findIndex((statement) => statement === child);
8019
+ for (const statement of current.body.slice(0, Math.max(0, index))) {
8020
+ if (statement.type !== AST_NODE_TYPES.IfStatement) continue;
8021
+ if (!isRefInExpression(context, statement.test)) continue;
8022
+ if (isTerminatingStatement(statement.consequent)) return true;
8023
+ }
8024
+ }
8025
+ child = current;
7999
8026
  current = current.parent;
8000
8027
  }
8001
8028
  return false;
8002
8029
  }
8030
+ function isTerminatingStatement(node) {
8031
+ if (node.type === AST_NODE_TYPES.ReturnStatement || node.type === AST_NODE_TYPES.ThrowStatement) return true;
8032
+ if (node.type === AST_NODE_TYPES.BlockStatement) return node.body.some(isTerminatingStatement);
8033
+ return false;
8034
+ }
8003
8035
  function isRefInExpression(context, node) {
8004
8036
  return getNestedIdentifiers(node).some((id) => isInitializedFromRef(context, id.name, context.sourceCode.getScope(id)));
8005
8037
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-react-x",
3
- "version": "5.23.2",
3
+ "version": "5.23.4",
4
4
  "description": "A set of composable ESLint rules for libraries and frameworks that use React as a UI runtime.",
5
5
  "keywords": [
6
6
  "react",
@@ -36,12 +36,12 @@
36
36
  "dist"
37
37
  ],
38
38
  "dependencies": {
39
- "@eslint-react/ast": "5.23.2",
40
- "@eslint-react/core": "5.23.2",
41
- "@eslint-react/eslint": "5.23.2",
42
- "@eslint-react/jsx": "5.23.2",
43
- "@eslint-react/shared": "5.23.2",
44
- "@eslint-react/var": "5.23.2",
39
+ "@eslint-react/ast": "5.23.4",
40
+ "@eslint-react/core": "5.23.4",
41
+ "@eslint-react/eslint": "5.23.4",
42
+ "@eslint-react/jsx": "5.23.4",
43
+ "@eslint-react/shared": "5.23.4",
44
+ "@eslint-react/var": "5.23.4",
45
45
  "@typescript-eslint/scope-manager": "^8.71.0",
46
46
  "@typescript-eslint/types": "^8.71.0",
47
47
  "@typescript-eslint/typescript-estree": "^8.71.0",