eslint-plugin-react-x 5.23.1 → 5.23.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.
Files changed (2) hide show
  1. package/dist/index.js +34 -3
  2. package/package.json +8 -7
package/dist/index.js CHANGED
@@ -144,7 +144,7 @@ const rules$6 = {
144
144
  //#endregion
145
145
  //#region package.json
146
146
  var name$6 = "eslint-plugin-react-x";
147
- var version = "5.23.1";
147
+ var version = "5.23.3";
148
148
 
149
149
  //#endregion
150
150
  //#region src/utils/create-rule.ts
@@ -1681,13 +1681,29 @@ function getMutatedObject(mutation) {
1681
1681
  function inferDirectMutations(context, mutations, components) {
1682
1682
  const directMutations = [];
1683
1683
  for (const mutation of mutations) {
1684
- if (mutation.kind !== "value") continue;
1685
1684
  if (mutation.node.type === AST_NODE_TYPES.CallExpression && isKnownNonMutatingMethodCall(context, mutation.node)) continue;
1686
1685
  if (isRefMutation(context, mutation)) continue;
1687
1686
  const variable = findVariable(context.sourceCode.getScope(mutation.root), mutation.root);
1688
1687
  if (variable == null) continue;
1689
1688
  const origin = classifyFrozenOrigin(context, variable, components);
1690
1689
  if (origin == null) continue;
1690
+ if (mutation.kind === "binding") {
1691
+ switch (origin.kind) {
1692
+ case "props":
1693
+ directMutations.push({
1694
+ name: origin.name,
1695
+ detail: "It is a prop of this component and must not be reassigned.",
1696
+ node: mutation.node
1697
+ });
1698
+ break;
1699
+ case "state": directMutations.push({
1700
+ name: origin.name,
1701
+ detail: `It is a state value returned from '${origin.hook}' and must not be reassigned.`,
1702
+ node: mutation.node
1703
+ });
1704
+ }
1705
+ continue;
1706
+ }
1691
1707
  switch (origin.kind) {
1692
1708
  case "props":
1693
1709
  directMutations.push({
@@ -7974,7 +7990,7 @@ function isInitializedFromRef(context, name, initialScope, seen = /* @__PURE__ *
7974
7990
  return Check.isIdentifier(object) && (object.name === "ref" || object.name.endsWith("Ref"));
7975
7991
  }
7976
7992
  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));
7993
+ default: return getNestedIdentifiers(init).some((id) => isInitializedFromRef(context, id.name, context.sourceCode.getScope(id), seen));
7978
7994
  }
7979
7995
  }
7980
7996
  return false;
@@ -7987,6 +8003,7 @@ function isInitializedFromRef(context, name, initialScope, seen = /* @__PURE__ *
7987
8003
  * @returns `true` if the node is inside a ref-gated conditional block
7988
8004
  */
7989
8005
  function isRefGatedContext(context, node) {
8006
+ let child = node;
7990
8007
  let current = node.parent;
7991
8008
  while (current != null) {
7992
8009
  if (Check.isFunction(current)) break;
@@ -7996,10 +8013,24 @@ function isRefGatedContext(context, node) {
7996
8013
  if (current.type === AST_NODE_TYPES.ConditionalExpression) {
7997
8014
  if (isRefInExpression(context, current.test)) return true;
7998
8015
  }
8016
+ if (current.type === AST_NODE_TYPES.BlockStatement) {
8017
+ const index = current.body.findIndex((statement) => statement === child);
8018
+ for (const statement of current.body.slice(0, Math.max(0, index))) {
8019
+ if (statement.type !== AST_NODE_TYPES.IfStatement) continue;
8020
+ if (!isRefInExpression(context, statement.test)) continue;
8021
+ if (isTerminatingStatement(statement.consequent)) return true;
8022
+ }
8023
+ }
8024
+ child = current;
7999
8025
  current = current.parent;
8000
8026
  }
8001
8027
  return false;
8002
8028
  }
8029
+ function isTerminatingStatement(node) {
8030
+ if (node.type === AST_NODE_TYPES.ReturnStatement || node.type === AST_NODE_TYPES.ThrowStatement) return true;
8031
+ if (node.type === AST_NODE_TYPES.BlockStatement) return node.body.some(isTerminatingStatement);
8032
+ return false;
8033
+ }
8003
8034
  function isRefInExpression(context, node) {
8004
8035
  return getNestedIdentifiers(node).some((id) => isInitializedFromRef(context, id.name, context.sourceCode.getScope(id)));
8005
8036
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-react-x",
3
- "version": "5.23.1",
3
+ "version": "5.23.3",
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.1",
40
- "@eslint-react/core": "5.23.1",
41
- "@eslint-react/eslint": "5.23.1",
42
- "@eslint-react/jsx": "5.23.1",
43
- "@eslint-react/shared": "5.23.1",
44
- "@eslint-react/var": "5.23.1",
39
+ "@eslint-react/ast": "5.23.3",
40
+ "@eslint-react/core": "5.23.3",
41
+ "@eslint-react/eslint": "5.23.3",
42
+ "@eslint-react/jsx": "5.23.3",
43
+ "@eslint-react/shared": "5.23.3",
44
+ "@eslint-react/var": "5.23.3",
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",
@@ -54,6 +54,7 @@
54
54
  "devDependencies": {
55
55
  "@local/configs": "0.0.0",
56
56
  "@local/eff": "0.0.0",
57
+ "@rbxts/react": "17.3.7-ts.2",
57
58
  "@types/react": "^19.3.0",
58
59
  "@types/react-dom": "^19.3.0",
59
60
  "dedent": "^1.7.2",