Support method call when validating useEffect
Treat MethodCall similarly to CallExpression when validation useEffect
Sathya Gunasekaran committed
Mar 22, 2024 at 23:42 UTC
db7e7c7fae69e54fee8751b10790827e2dea0ac2
3 files changed
+62
-2
compiler/packages/babel-plugin-react-forget/src/Inference/InferReferenceEffects.ts
+14
-2
@@ -1190,7 +1190,9 @@ function inferBlock(
1190
const effects =
1191
signature !== null ? getFunctionEffects(instrValue, signature) : null;
1192
let hasCaptureArgument = false;
1193
+ let isUseEffect = isEffectHook(instrValue.property.identifier);
1194
for (let i = 0; i < instrValue.args.length; i++) {
1195
+ const argumentEffects: Array<FunctionEffect> = [];
1196
const arg = instrValue.args[i];
1197
const place = arg.kind === "Identifier" ? arg : arg.place;
1198
if (effects !== null) {
@@ -1200,18 +1202,28 @@ function inferBlock(
1202
*/
1203
state.reference(
1204
place,
1203
- functionEffects,
1205
+ argumentEffects,
1206
effects[i],
1207
ValueReason.Other
1208
);
1209
} else {
1210
state.reference(
1211
place,
1210
- functionEffects,
1212
+ argumentEffects,
1213
Effect.ConditionallyMutate,
1214
ValueReason.Other
1215
);
1216
}
1217
+ /*
1218
+ * Join the effects of the argument with the effects of the enclosing function,
1219
+ * unless the we're detecting a global mutation inside a useEffect hook
1220
+ */
1221
+ functionEffects.push(
1222
+ ...argumentEffects.filter(
1223
+ (argEffect) =>
1224
+ !isUseEffect || i !== 0 || argEffect.kind !== "GlobalMutation"
1225
+ )
1226
+ );
1227
hasCaptureArgument ||= place.effect === Effect.Capture;
1228
}
1229
if (signature !== null) {
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useEffect-method-call.expect.md
new
+37
@@ -0,0 +1,37 @@
1
+
2
+## Input
3
+
4
+```javascript
5
+let x = {};
6
+function Component() {
7
+ React.useEffect(() => {
8
+ x.foo = 1;
9
+ });
10
+}
11
+
12
+export const FIXTURE_ENTRYPOINT = {
13
+ fn: Component,
14
+ params: [],
15
+};
16
+
17
+```
18
+
19
+## Code
20
+
21
+```javascript
22
+let x = {};
23
+function Component() {
24
+ React.useEffect(() => {
25
+ x.foo = 1;
26
+ });
27
+}
28
+
29
+export const FIXTURE_ENTRYPOINT = {
30
+ fn: Component,
31
+ params: [],
32
+};
33
+
34
+```
35
+
36
+### Eval output
37
+(kind: ok)
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useEffect-method-call.js
new
+11
@@ -0,0 +1,11 @@
1
+let x = {};
2
+function Component() {
3
+ React.useEffect(() => {
4
+ x.foo = 1;
5
+ });
6
+}
7
+
8
+export const FIXTURE_ENTRYPOINT = {
9
+ fn: Component,
10
+ params: [],
11
+};