Add frozen reason for props and hook arguments
Add frozen reason for props and hook arguments Improves the error message when mutating props or hook arguments. Previously, this would print a generic error about mutating global variables.
Jan Kassens committed
Jan 12, 2024 at 14:51 UTC
8a634bc1c0a3658a23f50662d1c0225ae6212720
6 files changed
+54
-1
compiler/packages/babel-plugin-react-forget/src/HIR/HIR.ts
+5
@@ -982,6 +982,11 @@ export enum ValueReason {
982
*/
983
Context = "context",
984
985
+ /**
986
+ * Props of a component or arguments of a hook.
987
+ */
988
+ ReactiveFunctionArgument = "reactive-function-argument",
989
+
990
Other = "other",
991
}
992
compiler/packages/babel-plugin-react-forget/src/Inference/InferReferenceEffects.ts
+3
-1
@@ -131,7 +131,7 @@ export default function inferReferenceEffects(
131
}
132
: {
133
kind: ValueKind.Frozen,
134
- reason: new Set([ValueReason.Other]),
134
+ reason: new Set([ValueReason.ReactiveFunctionArgument]),
135
};
136
for (const param of fn.params) {
137
let value: InstructionValue;
@@ -1503,6 +1503,8 @@ function getWriteErrorReason(abstractValue: AbstractValue): string {
1503
return `Mutating a value returned from 'useContext()', which should not be mutated.`;
1504
} else if (abstractValue.reason.has(ValueReason.KnownReturnSignature)) {
1505
return "Mutating a value returned from a function that should not be mutated.";
1506
+ } else if (abstractValue.reason.has(ValueReason.ReactiveFunctionArgument)) {
1507
+ return "Mutating props or hook arguments is not allowed. Consider using a local variable instead.";
1508
} else {
1509
return "This mutates a global or a variable after it was passed to React, which means that React cannot observe changes to it.";
1510
}
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.mutate-hook-argument.expect.md
new
+19
@@ -0,0 +1,19 @@
1
+
2
+## Input
3
+
4
+```javascript
5
+function useHook(a, b) {
6
+ b.test = 1;
7
+ a.test = 2;
8
+}
9
+
10
+```
11
+
12
+
13
+## Error
14
+
15
+```
16
+[ReactForget] InvalidReact: Mutating props or hook arguments is not allowed. Consider using a local variable instead. (2:2)
17
+```
18
+
19
+
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.mutate-hook-argument.js
new
+4
@@ -0,0 +1,4 @@
1
+function useHook(a, b) {
2
+ b.test = 1;
3
+ a.test = 2;
4
+}
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.mutate-props.expect.md
new
+19
@@ -0,0 +1,19 @@
1
+
2
+## Input
3
+
4
+```javascript
5
+function Foo(props) {
6
+ props.test = 1;
7
+ return null;
8
+}
9
+
10
+```
11
+
12
+
13
+## Error
14
+
15
+```
16
+[ReactForget] InvalidReact: Mutating props or hook arguments is not allowed. Consider using a local variable instead. (2:2)
17
+```
18
+
19
+
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.mutate-props.js
new
+4
@@ -0,0 +1,4 @@
1
+function Foo(props) {
2
+ props.test = 1;
3
+ return null;
4
+}