diff --git a/compiler/packages/babel-plugin-react-forget/src/TypeInference/InferTypes.ts b/compiler/packages/babel-plugin-react-forget/src/TypeInference/InferTypes.ts index a9a0e8d662..2fe2afeb69 100644 --- a/compiler/packages/babel-plugin-react-forget/src/TypeInference/InferTypes.ts +++ b/compiler/packages/babel-plugin-react-forget/src/TypeInference/InferTypes.ts @@ -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; } diff --git a/compiler/packages/babel-plugin-react-forget/src/Validation/ValidateHooksUsage.ts b/compiler/packages/babel-plugin-react-forget/src/Validation/ValidateHooksUsage.ts index 63da00e38f..dd42e09457 100644 --- a/compiler/packages/babel-plugin-react-forget/src/Validation/ValidateHooksUsage.ts +++ b/compiler/packages/babel-plugin-react-forget/src/Validation/ValidateHooksUsage.ts @@ -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; diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-in-nested-function-expression-object-expression.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-in-nested-function-expression-object-expression.expect.md new file mode 100644 index 0000000000..8ee48893f7 --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-in-nested-function-expression-object-expression.expect.md @@ -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; +``` + + \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-in-nested-function-expression-object-expression.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-in-nested-function-expression-object-expression.js new file mode 100644 index 0000000000..aead5b5e22 --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-in-nested-function-expression-object-expression.js @@ -0,0 +1,18 @@ +// @compilationMode(infer) +function Component() { + const f = () => { + const x = { + outer() { + const g = () => { + const y = { + inner() { + return useFoo(); + }, + }; + return y; + }; + }, + }; + return x; + }; +} diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-in-nested-object-method.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-in-nested-object-method.expect.md new file mode 100644 index 0000000000..b5d2deb664 --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-in-nested-object-method.expect.md @@ -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; +``` + + \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-in-nested-object-method.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-in-nested-object-method.js new file mode 100644 index 0000000000..5ba5a74c0d --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-in-nested-object-method.js @@ -0,0 +1,14 @@ +// @compilationMode(infer) +function Component() { + const x = { + outer() { + const y = { + inner() { + return useFoo(); + }, + }; + return y; + }, + }; + return x; +}