Skip to content

Commit ac01cf7

Browse files
committed
[compiler] Allow inferred non-optional paths when manual deps were optional
If the inferred deps are more precise (non-optional) than the manual deps (optional) it should pass validation. The other direction also seems like it would be fine - inferring optional deps when the original was non-optional - but for now let's keep the "at least as precise" rule. ghstack-source-id: 8f34860 Pull Request resolved: #30816
1 parent 76ce3ed commit ac01cf7

File tree

3 files changed

+67
-4
lines changed

3 files changed

+67
-4
lines changed

compiler/packages/babel-plugin-react-compiler/src/Validation/ValidatePreservedManualMemoization.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -167,12 +167,16 @@ function compareDeps(
167167

168168
let isSubpath = true;
169169
for (let i = 0; i < Math.min(inferred.path.length, source.path.length); i++) {
170-
if (
171-
inferred.path[i].property !== source.path[i].property ||
172-
inferred.path[i].optional !== source.path[i].optional
173-
) {
170+
if (inferred.path[i].property !== source.path[i].property) {
174171
isSubpath = false;
175172
break;
173+
} else if (inferred.path[i].optional && !source.path[i].optional) {
174+
/**
175+
* The inferred path must be at least as precise as the manual path:
176+
* if the inferred path is optional, then the source path must have
177+
* been optional too.
178+
*/
179+
return CompareDependencyResult.PathDifference;
176180
}
177181
}
178182

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
2+
## Input
3+
4+
```javascript
5+
// @validatePreserveExistingMemoizationGuarantees
6+
function Component(props) {
7+
const data = useMemo(() => {
8+
// actual code is non-optional
9+
return props.items.edges.nodes ?? [];
10+
// deps are optional
11+
}, [props.items?.edges?.nodes]);
12+
return <Foo data={data} />;
13+
}
14+
15+
```
16+
17+
## Code
18+
19+
```javascript
20+
import { c as _c } from "react/compiler-runtime"; // @validatePreserveExistingMemoizationGuarantees
21+
function Component(props) {
22+
const $ = _c(4);
23+
24+
props.items?.edges?.nodes;
25+
let t0;
26+
let t1;
27+
if ($[0] !== props.items.edges.nodes) {
28+
t1 = props.items.edges.nodes ?? [];
29+
$[0] = props.items.edges.nodes;
30+
$[1] = t1;
31+
} else {
32+
t1 = $[1];
33+
}
34+
t0 = t1;
35+
const data = t0;
36+
let t2;
37+
if ($[2] !== data) {
38+
t2 = <Foo data={data} />;
39+
$[2] = data;
40+
$[3] = t2;
41+
} else {
42+
t2 = $[3];
43+
}
44+
return t2;
45+
}
46+
47+
```
48+
49+
### Eval output
50+
(kind: exception) Fixture not implemented
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// @validatePreserveExistingMemoizationGuarantees
2+
function Component(props) {
3+
const data = useMemo(() => {
4+
// actual code is non-optional
5+
return props.items.edges.nodes ?? [];
6+
// deps are optional
7+
}, [props.items?.edges?.nodes]);
8+
return <Foo data={data} />;
9+
}

0 commit comments

Comments
 (0)