Files
Hendrik Liebau b6a7714057 Hoist inner 'use cache' functions to reduce function allocations (#85904)
This PR fixes a slight performance regression introduced in #85519 where
inline async function expressions were created for each unique set of
arguments passed to a `'use cache'` function.

For a function like this:

```js
export async function getCachedData(id) {
  'use cache';
  return fetch(`/api/data/${id}`);
}
```

we were previously generating (simplified):

```js
export var $$RSC_SERVER_CACHE_0 = cache("default", "0815", 0, async function(id) {
  return fetch(`/api/data/${id}`);
});
```

In #85519, we restructured this to ensure proper stack frames in error
messages (simplified):

```js
export var $$RSC_SERVER_CACHE_0 = React.cache(function getCachedData() {
  return cache("default", "0815", 0, async function(id) {
    return fetch(`/api/data/${id}`);
  }, arguments);
});
```

However, this introduced a small performance issue: the inner async
function expression was passed inline to the cache wrapper. While
`React.cache` memoizes the outer function, each unique set of arguments
would cause a new inner function object to be allocated.

Now we're generating (simplified):

```js
const $$RSC_SERVER_CACHE_0_INNER = async function getCachedData(id) {
  return fetch(`/api/data/${id}`);
};

export var $$RSC_SERVER_CACHE_0 = React.cache(function getCachedData() {
  return cache("default", "0815", 0, $$RSC_SERVER_CACHE_0_INNER, arguments);
});
```

The cache implementation is now hoisted to module scope with an `_INNER`
suffix as a const declaration with a named function expression. The
function name is preserved to ensure proper stack traces in dev. This
eliminates the repeated function allocations while preserving the
improvements from #85519.
2025-11-10 13:09:59 +01:00
..
…