Convert any export from a `'use cache'` module to a cache function (#86014)
Previously, in a `'use cache'` module, we only compiled statically-known
exported functions and arrow expressions to cache functions. Now, we
also compile re-exports and exports of values that might be functions.
This includes exports like:
- `export { getData } from './data'` - re-exporting from another module
- `export const aliased = getData` - exporting an imported identifier
- `const Page = withSlug(...); export default Page` - exporting the
result of a function call
These cases can't be statically verified as functions at compile time,
so we generate runtime wrappers with `typeof === "function"` checks
(simplified):
```js
let $$RSC_SERVER_CACHE_getData = getData;
if (typeof getData === "function") {
$$RSC_SERVER_CACHE_getData = React.cache(function() {
return cache("default", "...", 0, getData, arguments);
});
registerServerReference($$RSC_SERVER_CACHE_getData, "...", null);
Object.defineProperty($$RSC_SERVER_CACHE_getData, "name", { value: "getData" });
}
export { $$RSC_SERVER_CACHE_getData as getData };
```
This ensures that all function exports from `'use cache'` modules are
properly cached, while non-function exports pass through unchanged.
This approach comes with some limitations compared to statically-known
function exports:
1. **No compile-time type checking:** We can't verify that these exports
are actually functions. Non-function exports will be passed through
as-is at runtime.
2. **No async enforcement:** We can't enforce that functions must be
async (as we do for statically-known functions). Synchronous functions
are supported, but will lie about their type signature. They become
async after being wrapped as cache functions, even though their original
signature was synchronous.
closes NAR-196