mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
This is a simplified version of #1454. The goal of this PR is to inline the contents of `useMemo()` callbacks, rather than just immediately invoke the lambda. Turning useMemo() into an IIFE works, but it means that we can't optimize within the lambda block. Our investigations showed that there's a lot of room to optimize at a finer granularity than manually written useMemo calls. For example, one product instance had a useMemo that created a list of child JSX elements. Most of those elements only relied on a single variable (`a`), but a few relied on a second variable (`b). Thus _all_ elements were invalidated whenever `b` changed. If Forget retains the original lambda, we have no choice but to keep that (coarse) granularity for memoization. When we inline, we can optimize to make e.g. individual JSX elements depend on their precise dependencies. The rough idea is: * Keep track of all function expressions * When we find a useMemo, lookup its function expression, and add its CFG to the main function (the previous PR ensures that BlockIds won't collide) * Replace any return statements with a StoreLocal to save the result and a Goto to the code following the useMemo call. * Then we run the usual set of passes to patch the HIR back up again. Example: ```javascript // Before function Component(props) { const x = useMemo(() => { if (props.cond) { return null; } return foo(props.x); }, [props.x]); return x + props.y; } // Intended - **before** memoization function Component(props) { let x; if (props.cond) { x = null; } else { x = foo(props.x); } return x + props.y; } ```