Skip to content

Commit

Permalink
[compiler] Option for preserving calls to useMemo/useCallback
Browse files Browse the repository at this point in the history
Summary: This adds a compiler option to not drop existing manual memoization and leaving useMemo/useCallback in the generated source. Why do we need this, given that we also have options to validate or ensure that existing memoization is preserved? It's because later diffs on this stack are designed to alter the behavior of the memoization that the compiler emits, in order to detect rules of react violations and debug issues. We don't want to change the behavior of user-level memoization, however, since doing so would be altering the semantics of the user's program in an unacceptable way.

ghstack-source-id: 89dccdec9ccb4306b16e849e9fa2170bb5dd021f
Pull Request resolved: #29654
  • Loading branch information
mvitousek committed May 31, 2024
1 parent 8bc81ca commit 28fe581
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,10 @@ function* runWithEnvironment(
validateContextVariableLValues(hir);
validateUseMemo(hir);

dropManualMemoization(hir);
yield log({ kind: "hir", name: "DropManualMemoization", value: hir });
if (!env.config.enablePreserveExistingManualUseMemo) {
dropManualMemoization(hir);
yield log({ kind: "hir", name: "DropManualMemoization", value: hir });
}

inlineImmediatelyInvokedFunctionExpressions(hir);
yield log({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,13 @@ const EnvironmentConfigSchema = z.object({
*/
validatePreserveExistingMemoizationGuarantees: z.boolean().default(true),

/**
* When this is true, rather than pruning existing manual memoization but ensuring or validating
* that the memoized values remain memoized, the compiler will simply not prune existing calls to
* useMemo/useCallback.
*/
enablePreserveExistingManualUseMemo: z.boolean().default(false),

// 🌲
enableForest: z.boolean().default(false),

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@

## Input

```javascript
// @enablePreserveExistingManualUseMemo
import { useMemo } from "react";

function Component({ a }) {
let x = useMemo(() => [a], []);
return <div>{x}</div>;
}

export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{ a: 42 }],
isComponent: true,
};

```

## Code

```javascript
import { c as _c } from "react/compiler-runtime"; // @enablePreserveExistingManualUseMemo
import { useMemo } from "react";

function Component(t0) {
const $ = _c(5);
const { a } = t0;
let t1;
if ($[0] !== a) {
t1 = () => [a];
$[0] = a;
$[1] = t1;
} else {
t1 = $[1];
}
let t2;
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
t2 = [];
$[2] = t2;
} else {
t2 = $[2];
}
const x = useMemo(t1, t2);
let t3;
if ($[3] !== x) {
t3 = <div>{x}</div>;
$[3] = x;
$[4] = t3;
} else {
t3 = $[4];
}
return t3;
}

export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{ a: 42 }],
isComponent: true,
};

```
### Eval output
(kind: ok) <div>42</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// @enablePreserveExistingManualUseMemo
import { useMemo } from "react";

function Component({ a }) {
let x = useMemo(() => [a], []);
return <div>{x}</div>;
}

export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{ a: 42 }],
isComponent: true,
};

0 comments on commit 28fe581

Please sign in to comment.