Validate hook calls in object methods

Adds some test cases for hook calls in object methods. Initially we didn't catch 
these because InferTypes doesn't actually visit ObjectMethod bodies. Once we fix 
that we correctly reject these examples.
This commit is contained in:
Joe Savona
2024-02-16 11:27:52 -08:00
parent 9c419dfd80
commit d6406d8360
6 changed files with 112 additions and 1 deletions
@@ -69,7 +69,10 @@ function apply(func: HIRFunction, unifier: Unifier): void {
const { lvalue, value } = instr;
lvalue.identifier.type = unifier.get(lvalue.identifier.type);
if (value.kind === "FunctionExpression") {
if (
value.kind === "FunctionExpression" ||
value.kind === "ObjectMethod"
) {
apply(value.loweredFunc.func, unifier);
}
}
@@ -300,6 +303,7 @@ function* generateInstructionTypes(
}
case "ObjectMethod": {
yield* generate(value.loweredFunc.func);
yield equation(left, { kind: "ObjectMethod" });
break;
}
@@ -403,6 +403,7 @@ function visitFunctionExpression(errors: CompilerError, fn: HIRFunction): void {
for (const [, block] of fn.body.blocks) {
for (const instr of block.instructions) {
switch (instr.value.kind) {
case "ObjectMethod":
case "FunctionExpression": {
visitFunctionExpression(errors, instr.value.loweredFunc.func);
break;
@@ -0,0 +1,39 @@
## Input
```javascript
// @compilationMode(infer)
function Component() {
const f = () => {
const x = {
outer() {
const g = () => {
const y = {
inner() {
return useFoo();
},
};
return y;
};
},
};
return x;
};
}
```
## Error
```
7 | const y = {
8 | inner() {
> 9 | return useFoo();
| ^^^^^^ [ReactForget] InvalidReact: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning). Cannot call Custom within a function component (9:9)
10 | },
11 | };
12 | return y;
```
@@ -0,0 +1,18 @@
// @compilationMode(infer)
function Component() {
const f = () => {
const x = {
outer() {
const g = () => {
const y = {
inner() {
return useFoo();
},
};
return y;
};
},
};
return x;
};
}
@@ -0,0 +1,35 @@
## Input
```javascript
// @compilationMode(infer)
function Component() {
const x = {
outer() {
const y = {
inner() {
return useFoo();
},
};
return y;
},
};
return x;
}
```
## Error
```
5 | const y = {
6 | inner() {
> 7 | return useFoo();
| ^^^^^^ [ReactForget] InvalidReact: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning). Cannot call Custom within a function component (7:7)
8 | },
9 | };
10 | return y;
```
@@ -0,0 +1,14 @@
// @compilationMode(infer)
function Component() {
const x = {
outer() {
const y = {
inner() {
return useFoo();
},
};
return y;
},
};
return x;
}