Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[compiler] add fixture for optimization across scopes #29998

Merged
merged 8 commits into from
Jun 21, 2024
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@

## Input

```javascript
import { Stringify } from "shared-runtime";

function Component({ config }) {
/**
* The original memoization is optimal in the sense that it has
* one output (the object) and one dependency (`config`). Both
* the `a` and `b` functions will have to be recreated whenever
* `config` changes, cascading to update the object.
*
* However, we currently only consider consecutive scopes for
* merging, so we first see the `a` scope, then the `b` scope,
* and see that the output of the `a` scope is used later -
* so we don't merge these scopes, and so on.
*
* The more optimal thing would be to build a dependency graph
* of scopes so that we can see the data flow is along the lines
* of:
*
* config
* / \
* [a] [b]
* \ /
* [object]
*
* All the scopes (shown in []) are transitively dependent on
* `config`, so they can be merged.
*/
const object = useMemo(() => {
const a = (event) => {
config?.onA?.(event);
};

const b = (event) => {
config?.onB?.(event);
};

return {
b,
a,
};
}, [config]);

return <Stringify value={object} />;
}

```

## Code

```javascript
import { c as _c } from "react/compiler-runtime";
import { Stringify } from "shared-runtime";

function Component(t0) {
const $ = _c(9);
const { config } = t0;
let t1;
let t2;
if ($[0] !== config) {
t2 = (event) => {
config?.onA?.(event);
};
$[0] = config;
$[1] = t2;
} else {
t2 = $[1];
}
const a = t2;
let t3;
if ($[2] !== config) {
t3 = (event_0) => {
config?.onB?.(event_0);
};
$[2] = config;
$[3] = t3;
} else {
t3 = $[3];
}
const b = t3;
let t4;
if ($[4] !== b || $[5] !== a) {
t4 = { b, a };
$[4] = b;
$[5] = a;
$[6] = t4;
} else {
t4 = $[6];
}
t1 = t4;
const object = t1;
let t5;
if ($[7] !== object) {
t5 = <Stringify value={object} />;
$[7] = object;
$[8] = t5;
} else {
t5 = $[8];
}
return t5;
}

```

### Eval output
(kind: exception) Fixture not implemented
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { Stringify } from "shared-runtime";

function Component({ config }) {
/**
* The original memoization is optimal in the sense that it has
* one output (the object) and one dependency (`config`). Both
* the `a` and `b` functions will have to be recreated whenever
* `config` changes, cascading to update the object.
*
* However, we currently only consider consecutive scopes for
* merging, so we first see the `a` scope, then the `b` scope,
* and see that the output of the `a` scope is used later -
* so we don't merge these scopes, and so on.
*
* The more optimal thing would be to build a dependency graph
* of scopes so that we can see the data flow is along the lines
* of:
*
* config
* / \
* [a] [b]
* \ /
* [object]
*
* All the scopes (shown in []) are transitively dependent on
* `config`, so they can be merged.
*/
const object = useMemo(() => {
const a = (event) => {
config?.onA?.(event);
};

const b = (event) => {
config?.onB?.(event);
};

return {
b,
a,
};
}, [config]);

return <Stringify value={object} />;
}