@samitouri / QOS-React-1 / commits / 8e4d2fb69d

Repro for false positive in validatePreserveMemoization on non-escaping value

This demonstrates a false positive in validatePreserveExistingManualMemoization. We prune memoization of non-escaping values, but the validation pass just sees that the value "should" have a scope and that scope doesn't exist, and thinks we failed to preserve memoization.

Joe Savona committed Jan 11, 2024 at 16:52 UTC 8e4d2fb69d690695db0a33001fb1aee586bde15f
2 files changed +41
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.repro-false-positive-preserve-memoization-nonescaping-value.expect.md new
+28
@@ -0,0 +1,28 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @validatePreserveExistingMemoizationGuarantees @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions
6 +function Component({ entity, children }) {
7 + // showMessage doesn't escape so we don't memoize it.
8 + // However, validatePreserveExistingMemoizationGuarantees only sees that the scope
9 + // doesn't exist, and thinks the memoization was missed instead of being intentionally dropped.
10 + const showMessage = useCallback(() => entity != null);
11 +
12 + if (!showMessage) {
13 + return children;
14 + }
15 +
16 + return <Message>{children}</Message>;
17 +}
18 +
19 +```
20 +
21 +
22 +## Error
23 +
24 +```
25 +[ReactForget] InvalidReact: This value was manually memoized, but cannot be memoized under Forget because it may be mutated after it is memoized (6:6)
26 +```
27 +
28 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.repro-false-positive-preserve-memoization-nonescaping-value.js new
+13
@@ -0,0 +1,13 @@
1 +// @validatePreserveExistingMemoizationGuarantees @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions
2 +function Component({ entity, children }) {
3 + // showMessage doesn't escape so we don't memoize it.
4 + // However, validatePreserveExistingMemoizationGuarantees only sees that the scope
5 + // doesn't exist, and thinks the memoization was missed instead of being intentionally dropped.
6 + const showMessage = useCallback(() => entity != null);
7 +
8 + if (!showMessage) {
9 + return children;
10 + }
11 +
12 + return <Message>{children}</Message>;
13 +}