@samitouri / QOS-React-2 / commits / db7e7c7fae

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 +};