[compiler] Allow type cast expressions with refs (#31871)
We report a false positive for the combination of a ref-accessing function placed inside an array which is they type-cast. Here we teach ref validation about type casts. I also tried other variants like `return ref as const` but those already worked. Closes #31864
Joseph Savona committed
Dec 20, 2024 at 08:56 UTC
6a3d6a4382cdafc1260483a6fc5f76593fc038e4
3 files changed
+85
compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoRefAccesInRender.ts
+8
@@ -305,6 +305,14 @@ function validateNoRefAccessInRenderImpl(
305
);
306
break;
307
}
308
+ case 'TypeCastExpression': {
309
+ env.set(
310
+ instr.lvalue.identifier.id,
311
+ env.get(instr.value.value.identifier.id) ??
312
+ refTypeOfType(instr.lvalue),
313
+ );
314
+ break;
315
+ }
316
case 'LoadContext':
317
case 'LoadLocal': {
318
env.set(
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-type-cast-in-render.expect.md
new
+60
@@ -0,0 +1,60 @@
1
+
2
+## Input
3
+
4
+```javascript
5
+import {useRef} from 'react';
6
+
7
+function useArrayOfRef() {
8
+ const ref = useRef(null);
9
+ const callback = value => {
10
+ ref.current = value;
11
+ };
12
+ return [callback] as const;
13
+}
14
+
15
+export const FIXTURE_ENTRYPOINT = {
16
+ fn: () => {
17
+ useArrayOfRef();
18
+ return 'ok';
19
+ },
20
+ params: [{}],
21
+};
22
+
23
+```
24
+
25
+## Code
26
+
27
+```javascript
28
+import { c as _c } from "react/compiler-runtime";
29
+import { useRef } from "react";
30
+
31
+function useArrayOfRef() {
32
+ const $ = _c(1);
33
+ const ref = useRef(null);
34
+ let t0;
35
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
36
+ const callback = (value) => {
37
+ ref.current = value;
38
+ };
39
+
40
+ t0 = [callback];
41
+ $[0] = t0;
42
+ } else {
43
+ t0 = $[0];
44
+ }
45
+ return t0 as const;
46
+}
47
+
48
+export const FIXTURE_ENTRYPOINT = {
49
+ fn: () => {
50
+ useArrayOfRef();
51
+ return "ok";
52
+ },
53
+
54
+ params: [{}],
55
+};
56
+
57
+```
58
+
59
+### Eval output
60
+(kind: ok) "ok"
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-type-cast-in-render.js
new
+17
@@ -0,0 +1,17 @@
1
+import {useRef} from 'react';
2
+
3
+function useArrayOfRef() {
4
+ const ref = useRef(null);
5
+ const callback = value => {
6
+ ref.current = value;
7
+ };
8
+ return [callback] as const;
9
+}
10
+
11
+export const FIXTURE_ENTRYPOINT = {
12
+ fn: () => {
13
+ useArrayOfRef();
14
+ return 'ok';
15
+ },
16
+ params: [{}],
17
+};