diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reordering-across-blocks.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reordering-across-blocks.expect.md new file mode 100644 index 0000000000000..af32ba709dd87 --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reordering-across-blocks.expect.md @@ -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 ; +} + +``` + +## 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 = ; + $[7] = object; + $[8] = t5; + } else { + t5 = $[8]; + } + return t5; +} + +``` + +### Eval output +(kind: exception) Fixture not implemented \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reordering-across-blocks.js b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reordering-across-blocks.js new file mode 100644 index 0000000000000..741eb71d526fb --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reordering-across-blocks.js @@ -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 ; +}