More useCallback with ref fixtures
Joe Savona committed
Dec 15, 2023 at 16:59 UTC
3e79c386048c4fe569afb023d85b71ed2ffe5b8e
9 files changed
+283
-3
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-useCallback-accesses-ref-mutated-later-via-function-preserve-memoization.expect.md
new
+42
@@ -0,0 +1,42 @@
1
+
2
+## Input
3
+
4
+```javascript
5
+// @enablePreserveExistingMemoizationGuarantees
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
+ // The ref is modified later, extending its range and preventing memoization of onChange
18
+ const reset = () => {
19
+ ref.current.inner = null;
20
+ };
21
+ reset();
22
+
23
+ return <input onChange={onChange} />;
24
+}
25
+
26
+export const FIXTURE_ENTRYPOINT = {
27
+ fn: Component,
28
+ params: [{}],
29
+};
30
+
31
+```
32
+
33
+
34
+## Error
35
+
36
+```
37
+[ReactForget] InvalidReact: This value was manually memoized, but cannot be memoized under Forget because it may be mutated after it is memoized (7:11)
38
+
39
+[ReactForget] InvalidReact: This value was manually memoized, but cannot be memoized under Forget because it may be mutated after it is memoized (7:11)
40
+```
41
+
42
+
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-useCallback-accesses-ref-mutated-later-via-function-preserve-memoization.js
new
+25
@@ -0,0 +1,25 @@
1
+// @enablePreserveExistingMemoizationGuarantees
2
+import { useCallback, useRef } from "react";
3
+
4
+function Component(props) {
5
+ const ref = useRef({ inner: null });
6
+
7
+ const onChange = useCallback((event) => {
8
+ // The ref should still be mutable here even though function deps are frozen in
9
+ // @enablePreserveExistingMemoizationGuarantees mode
10
+ ref.current.inner = event.target.value;
11
+ });
12
+
13
+ // The ref is modified later, extending its range and preventing memoization of onChange
14
+ const reset = () => {
15
+ ref.current.inner = null;
16
+ };
17
+ reset();
18
+
19
+ return <input onChange={onChange} />;
20
+}
21
+
22
+export const FIXTURE_ENTRYPOINT = {
23
+ fn: Component,
24
+ params: [{}],
25
+};
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-useCallback-set-ref-nested-property-ref-modified-later-preserve-memoization.expect.md
renamed
+1
@@ -14,6 +14,7 @@ function Component(props) {
14
ref.current.inner = event.target.value;
15
});
16
17
+ // The ref is modified later, extending its range and preventing memoization of onChange
18
ref.current.inner = null;
19
20
return <input onChange={onChange} />;
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-useCallback-set-ref-nested-property-ref-modified-later-preserve-memoization.js
new
+22
@@ -0,0 +1,22 @@
1
+// @enablePreserveExistingMemoizationGuarantees
2
+import { useCallback, useRef } from "react";
3
+
4
+function Component(props) {
5
+ const ref = useRef({ inner: null });
6
+
7
+ const onChange = useCallback((event) => {
8
+ // The ref should still be mutable here even though function deps are frozen in
9
+ // @enablePreserveExistingMemoizationGuarantees mode
10
+ ref.current.inner = event.target.value;
11
+ });
12
+
13
+ // The ref is modified later, extending its range and preventing memoization of onChange
14
+ ref.current.inner = null;
15
+
16
+ return <input onChange={onChange} />;
17
+}
18
+
19
+export const FIXTURE_ENTRYPOINT = {
20
+ fn: Component,
21
+ params: [{}],
22
+};
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useCallback-multiple-callbacks-modifying-same-ref-preserve-memoization.expect.md
new
+91
@@ -0,0 +1,91 @@
1
+
2
+## Input
3
+
4
+```javascript
5
+// @enablePreserveExistingMemoizationGuarantees
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
+ const onReset = useCallback(() => {
18
+ ref.current.inner = null;
19
+ });
20
+
21
+ return <input onChange={onChange} onReset={onReset} />;
22
+}
23
+
24
+export const FIXTURE_ENTRYPOINT = {
25
+ fn: Component,
26
+ params: [{}],
27
+};
28
+
29
+```
30
+
31
+## Code
32
+
33
+```javascript
34
+// @enablePreserveExistingMemoizationGuarantees
35
+import {
36
+ useCallback,
37
+ useRef,
38
+ unstable_useMemoCache as useMemoCache,
39
+} from "react";
40
+
41
+function Component(props) {
42
+ const $ = useMemoCache(6);
43
+ let t0;
44
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
45
+ t0 = { inner: null };
46
+ $[0] = t0;
47
+ } else {
48
+ t0 = $[0];
49
+ }
50
+ const ref = useRef(t0);
51
+ let t1;
52
+ if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
53
+ t1 = (event) => {
54
+ ref.current.inner = event.target.value;
55
+ };
56
+ $[1] = t1;
57
+ } else {
58
+ t1 = $[1];
59
+ }
60
+ const onChange = t1;
61
+ let t2;
62
+ if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
63
+ t2 = () => {
64
+ ref.current.inner = null;
65
+ };
66
+ $[2] = t2;
67
+ } else {
68
+ t2 = $[2];
69
+ }
70
+ const onReset = t2;
71
+ let t3;
72
+ if ($[3] !== onChange || $[4] !== onReset) {
73
+ t3 = <input onChange={onChange} onReset={onReset} />;
74
+ $[3] = onChange;
75
+ $[4] = onReset;
76
+ $[5] = t3;
77
+ } else {
78
+ t3 = $[5];
79
+ }
80
+ return t3;
81
+}
82
+
83
+export const FIXTURE_ENTRYPOINT = {
84
+ fn: Component,
85
+ params: [{}],
86
+};
87
+
88
+```
89
+
90
+### Eval output
91
+(kind: ok) <input>
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useCallback-multiple-callbacks-modifying-same-ref-preserve-memoization.js
new
+23
@@ -0,0 +1,23 @@
1
+// @enablePreserveExistingMemoizationGuarantees
2
+import { useCallback, useRef } from "react";
3
+
4
+function Component(props) {
5
+ const ref = useRef({ inner: null });
6
+
7
+ const onChange = useCallback((event) => {
8
+ // The ref should still be mutable here even though function deps are frozen in
9
+ // @enablePreserveExistingMemoizationGuarantees mode
10
+ ref.current.inner = event.target.value;
11
+ });
12
+
13
+ const onReset = useCallback(() => {
14
+ ref.current.inner = null;
15
+ });
16
+
17
+ return <input onChange={onChange} onReset={onReset} />;
18
+}
19
+
20
+export const FIXTURE_ENTRYPOINT = {
21
+ fn: Component,
22
+ params: [{}],
23
+};
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useCallback-set-ref-nested-property-dont-preserve-memoization.expect.md
+3
-1
@@ -62,4 +62,6 @@ export const FIXTURE_ENTRYPOINT = {
62
};
63
64
```
65
-
\ No newline at end of file
65
+
66
+### Eval output
67
+(kind: ok) <input>
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useCallback-set-ref-nested-property-preserve-memoization.expect.md
new
+76
@@ -0,0 +1,76 @@
1
+
2
+## Input
3
+
4
+```javascript
5
+// @enablePreserveExistingMemoizationGuarantees
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
+ return <input onChange={onChange} />;
18
+}
19
+
20
+export const FIXTURE_ENTRYPOINT = {
21
+ fn: Component,
22
+ params: [{}],
23
+};
24
+
25
+```
26
+
27
+## Code
28
+
29
+```javascript
30
+// @enablePreserveExistingMemoizationGuarantees
31
+import {
32
+ useCallback,
33
+ useRef,
34
+ unstable_useMemoCache as useMemoCache,
35
+} from "react";
36
+
37
+function Component(props) {
38
+ const $ = useMemoCache(4);
39
+ let t0;
40
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
41
+ t0 = { inner: null };
42
+ $[0] = t0;
43
+ } else {
44
+ t0 = $[0];
45
+ }
46
+ const ref = useRef(t0);
47
+ let t1;
48
+ if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
49
+ t1 = (event) => {
50
+ ref.current.inner = event.target.value;
51
+ };
52
+ $[1] = t1;
53
+ } else {
54
+ t1 = $[1];
55
+ }
56
+ const onChange = t1;
57
+ let t2;
58
+ if ($[2] !== onChange) {
59
+ t2 = <input onChange={onChange} />;
60
+ $[2] = onChange;
61
+ $[3] = t2;
62
+ } else {
63
+ t2 = $[3];
64
+ }
65
+ return t2;
66
+}
67
+
68
+export const FIXTURE_ENTRYPOINT = {
69
+ fn: Component,
70
+ params: [{}],
71
+};
72
+
73
+```
74
+
75
+### Eval output
76
+(kind: ok) <input>
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useCallback-set-ref-nested-property-preserve-memoization.js
renamed
-2
@@ -10,8 +10,6 @@ function Component(props) {
10
ref.current.inner = event.target.value;
11
});
12
13
- ref.current.inner = null;
14
-
13
return <input onChange={onChange} />;
14
}
15