Allow property loads from hook
Looking up certain properties on a hook is a common pattern for logging. It's non-ideal but it's not a bug to do this. This updates Forget to not error on this pattern.
Sathya Gunasekaran committed
Feb 28, 2024 at 16:19 UTC
130b809ac2006ebfb381244bfa4bf3828304ea67
5 files changed
+104
-2
compiler/packages/babel-plugin-react-forget/src/Validation/ValidateHooksUsage.ts
+1
-2
@@ -233,7 +233,6 @@ export function validateHooksUsage(fn: HIRFunction): void {
233
break;
234
}
235
case "PropertyLoad": {
236
- visitPlace(instr.value.object);
236
const objectKind = getKindForPlace(instr.value.object);
237
const isHookProperty = isHookName(instr.value.property);
238
let kind: Kind;
@@ -249,7 +248,7 @@ export function validateHooksUsage(fn: HIRFunction): void {
248
* let x = useFoo.useBar; // useFoo is KnownHook, any property from it inherits KnownHook
249
* }
250
*/
252
- kind = Kind.KnownHook;
251
+ kind = isHookProperty ? Kind.KnownHook : Kind.Local;
252
break;
253
}
254
case Kind.PotentialHook: {
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.hook-property-load-local-hook.expect.md
new
+37
@@ -0,0 +1,37 @@
1
+
2
+## Input
3
+
4
+```javascript
5
+function useFoo() {}
6
+useFoo.useBar = function () {
7
+ return "foo";
8
+};
9
+
10
+function Foo() {
11
+ let bar = useFoo.useBar;
12
+ return bar();
13
+}
14
+
15
+export const FIXTURE_ENTRYPOINT = {
16
+ fn: Foo,
17
+ params: [],
18
+};
19
+
20
+```
21
+
22
+
23
+## Error
24
+
25
+```
26
+ 5 |
27
+ 6 | function Foo() {
28
+> 7 | let bar = useFoo.useBar;
29
+ | ^^^^^^^^^^^^^ [ReactForget] InvalidReact: Hooks may not be referenced as normal values, they must be called. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (7:7)
30
+
31
+[ReactForget] InvalidReact: Hooks may not be referenced as normal values, they must be called. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (8:8)
32
+ 8 | return bar();
33
+ 9 | }
34
+ 10 |
35
+```
36
+
37
+
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.hook-property-load-local-hook.js
new
+14
@@ -0,0 +1,14 @@
1
+function useFoo() {}
2
+useFoo.useBar = function () {
3
+ return "foo";
4
+};
5
+
6
+function Foo() {
7
+ let bar = useFoo.useBar;
8
+ return bar();
9
+}
10
+
11
+export const FIXTURE_ENTRYPOINT = {
12
+ fn: Foo,
13
+ params: [],
14
+};
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/hook-property-load-local.expect.md
new
+40
@@ -0,0 +1,40 @@
1
+
2
+## Input
3
+
4
+```javascript
5
+function useFoo() {}
6
+
7
+function Foo() {
8
+ let name = useFoo.name;
9
+ console.log(name);
10
+ return name;
11
+}
12
+
13
+export const FIXTURE_ENTRYPOINT = {
14
+ fn: Foo,
15
+ params: [],
16
+};
17
+
18
+```
19
+
20
+## Code
21
+
22
+```javascript
23
+function useFoo() {}
24
+
25
+function Foo() {
26
+ const name = useFoo.name;
27
+ console.log(name);
28
+ return name;
29
+}
30
+
31
+export const FIXTURE_ENTRYPOINT = {
32
+ fn: Foo,
33
+ params: [],
34
+};
35
+
36
+```
37
+
38
+### Eval output
39
+(kind: ok) "useFoo"
40
+logs: ['useFoo']
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/hook-property-load-local.js
new
+12
@@ -0,0 +1,12 @@
1
+function useFoo() {}
2
+
3
+function Foo() {
4
+ let name = useFoo.name;
5
+ console.log(name);
6
+ return name;
7
+}
8
+
9
+export const FIXTURE_ENTRYPOINT = {
10
+ fn: Foo,
11
+ params: [],
12
+};