@samitouri / QOS-React-1 / commits / b7a14ecc8d

Detect unknown hooks on React namespace

Handles an edge-case from earlier in the stack. When looking up a property on a shape, if the property is defined we return it. But if it isn't defined, and the property name is a hook, we treat it like a default custom hook.

Joe Savona committed Oct 3, 2023 at 09:00 UTC b7a14ecc8d931922b44e92496eedf9710ea3ce39
4 files changed +48 -7
compiler/packages/babel-plugin-react-forget/src/HIR/Environment.ts
+6 -3
@@ -374,9 +374,12 @@ export class Environment {
374 loc: null,
375 suggestions: null,
376 });
377 - return (
378 - shape.properties.get(property) ?? shape.properties.get("*") ?? null
379 - );
377 + let value =
378 + shape.properties.get(property) ?? shape.properties.get("*") ?? null;
379 + if (value === null && isHookName(property)) {
380 + value = this.#getCustomHookType();
381 + }
382 + return value;
383 } else if (isHookName(property)) {
384 return this.#getCustomHookType();
385 } else {
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/drop-methodcall-usememo.expect.md
+13 -4
@@ -27,21 +27,30 @@ import { unstable_useMemoCache as useMemoCache } from "react";
27 import * as React from "react";
28
29 function Component(props) {
30 - const $ = useMemoCache(2);
30 + const $ = useMemoCache(4);
31 const c_0 = $[0] !== props.value;
32 let t0;
33 if (c_0) {
34 - t0 = (() => {
34 + t0 = () => {
35 const x = [];
36 x.push(props.value);
37 return x;
38 - })();
38 + };
39 $[0] = props.value;
40 $[1] = t0;
41 } else {
42 t0 = $[1];
43 }
44 - const x_0 = t0;
44 + const c_2 = $[2] !== t0;
45 + let t1;
46 + if (c_2) {
47 + t1 = t0();
48 + $[2] = t0;
49 + $[3] = t1;
50 + } else {
51 + t1 = $[3];
52 + }
53 + const x_0 = t1;
54 return x_0;
55 }
56
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.conditional-hook-unknown-hook-react-namespace.expect.md new
+22
@@ -0,0 +1,22 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +function Component(props) {
6 + let x = null;
7 + if (props.cond) {
8 + x = React.useNonexistentHook();
9 + }
10 + return x;
11 +}
12 +
13 +```
14 +
15 +
16 +## Error
17 +
18 +```
19 +[ReactForget] InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (4:4)
20 +```
21 +
22 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.conditional-hook-unknown-hook-react-namespace.js new
+7
@@ -0,0 +1,7 @@
1 +function Component(props) {
2 + let x = null;
3 + if (props.cond) {
4 + x = React.useNonexistentHook();
5 + }
6 + return x;
7 +}