Skip to content

Commit 5edbe29

Browse files
committed
[compiler] Make ref enforcement on by default
Summary: The change earlier in this stack makes it less safe to have ref enforcement disabled. This diff enables it by default. ghstack-source-id: d3ab5f1 Pull Request resolved: #30716
1 parent 21a9523 commit 5edbe29

22 files changed

+275
-417
lines changed

compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ const EnvironmentConfigSchema = z.object({
223223
validateHooksUsage: z.boolean().default(true),
224224

225225
// Validate that ref values (`ref.current`) are not accessed during render.
226-
validateRefAccessDuringRender: z.boolean().default(false),
226+
validateRefAccessDuringRender: z.boolean().default(true),
227227

228228
/*
229229
* Validates that setState is not unconditionally called during render, as it can lead to

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capture-ref-for-later-mutation.expect.md

Lines changed: 0 additions & 69 deletions
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
2+
## Input
3+
4+
```javascript
5+
import {useRef} from 'react';
6+
import {addOne} from 'shared-runtime';
7+
8+
function useKeyCommand() {
9+
const currentPosition = useRef(0);
10+
const handleKey = direction => () => {
11+
const position = currentPosition.current;
12+
const nextPosition = direction === 'left' ? addOne(position) : position;
13+
currentPosition.current = nextPosition;
14+
};
15+
const moveLeft = {
16+
handler: handleKey('left'),
17+
};
18+
const moveRight = {
19+
handler: handleKey('right'),
20+
};
21+
return [moveLeft, moveRight];
22+
}
23+
24+
export const FIXTURE_ENTRYPOINT = {
25+
fn: useKeyCommand,
26+
params: [],
27+
};
28+
29+
```
30+
31+
32+
## Error
33+
34+
```
35+
10 | };
36+
11 | const moveLeft = {
37+
> 12 | handler: handleKey('left'),
38+
| ^^^^^^^^^ InvalidReact: This function accesses a ref value (the `current` property), which may not be accessed during render. (https://react.dev/reference/react/useRef) (12:12)
39+
40+
InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (12:12)
41+
42+
InvalidReact: This function accesses a ref value (the `current` property), which may not be accessed during render. (https://react.dev/reference/react/useRef) (15:15)
43+
44+
InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (15:15)
45+
13 | };
46+
14 | const moveRight = {
47+
15 | handler: handleKey('right'),
48+
```
49+
50+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
2+
## Input
3+
4+
```javascript
5+
import {Stringify, identity, mutate, CONST_TRUE} from 'shared-runtime';
6+
7+
function Foo(props, ref) {
8+
const value = {};
9+
if (CONST_TRUE) {
10+
mutate(value);
11+
return <Stringify ref={ref} />;
12+
}
13+
mutate(value);
14+
if (CONST_TRUE) {
15+
return <Stringify ref={identity(ref)} />;
16+
}
17+
return value;
18+
}
19+
20+
export const FIXTURE_ENTRYPOINT = {
21+
fn: Foo,
22+
params: [{}, {current: 'fake-ref-object'}],
23+
};
24+
25+
```
26+
27+
28+
## Error
29+
30+
```
31+
9 | mutate(value);
32+
10 | if (CONST_TRUE) {
33+
> 11 | return <Stringify ref={identity(ref)} />;
34+
| ^^^ InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (11:11)
35+
12 | }
36+
13 | return value;
37+
14 | }
38+
```
39+
40+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
2+
## Input
3+
4+
```javascript
5+
// @enablePreserveExistingMemoizationGuarantees:false
6+
import {useCallback, useRef} from 'react';
7+
8+
function Component(props) {
9+
const ref = useRef({inner: null});
10+
11+
const onChange = useCallback(event => {
12+
// The ref should still be mutable here even though function deps are frozen in
13+
// @enablePreserveExistingMemoizationGuarantees mode
14+
ref.current.inner = event.target.value;
15+
});
16+
17+
ref.current.inner = null;
18+
19+
return <input onChange={onChange} />;
20+
}
21+
22+
export const FIXTURE_ENTRYPOINT = {
23+
fn: Component,
24+
params: [{}],
25+
};
26+
27+
```
28+
29+
30+
## Error
31+
32+
```
33+
11 | });
34+
12 |
35+
> 13 | ref.current.inner = null;
36+
| ^^^^^^^^^^^ InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (13:13)
37+
14 |
38+
15 | return <input onChange={onChange} />;
39+
16 | }
40+
```
41+
42+

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/original-reactive-scopes-fork/capture-ref-for-later-mutation.expect.md

Lines changed: 0 additions & 70 deletions
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
2+
## Input
3+
4+
```javascript
5+
// @enableReactiveScopesInHIR:false
6+
import {useRef} from 'react';
7+
import {addOne} from 'shared-runtime';
8+
9+
function useKeyCommand() {
10+
const currentPosition = useRef(0);
11+
const handleKey = direction => () => {
12+
const position = currentPosition.current;
13+
const nextPosition = direction === 'left' ? addOne(position) : position;
14+
currentPosition.current = nextPosition;
15+
};
16+
const moveLeft = {
17+
handler: handleKey('left'),
18+
};
19+
const moveRight = {
20+
handler: handleKey('right'),
21+
};
22+
return [moveLeft, moveRight];
23+
}
24+
25+
export const FIXTURE_ENTRYPOINT = {
26+
fn: useKeyCommand,
27+
params: [],
28+
};
29+
30+
```
31+
32+
33+
## Error
34+
35+
```
36+
11 | };
37+
12 | const moveLeft = {
38+
> 13 | handler: handleKey('left'),
39+
| ^^^^^^^^^ InvalidReact: This function accesses a ref value (the `current` property), which may not be accessed during render. (https://react.dev/reference/react/useRef) (13:13)
40+
41+
InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (13:13)
42+
43+
InvalidReact: This function accesses a ref value (the `current` property), which may not be accessed during render. (https://react.dev/reference/react/useRef) (16:16)
44+
45+
InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (16:16)
46+
14 | };
47+
15 | const moveRight = {
48+
16 | handler: handleKey('right'),
49+
```
50+
51+

0 commit comments

Comments
 (0)