the `next_font_loaders` transform replaces imports from `next/font` with
slightly different ones. unfortunately it was inserting these imports
**at the top** of the file, which broke the `server_actions` transform
because it expects "use server"/"use cache" directives to be the first
item in the file.
this PR changes the logic in the font transform to insert the import in
the place where the original `next/font` import occurred instead of at
the top of the file.
(i suppose that we could just reorder the transforms and run
`server_actions` before `next_font_loaders`, but this feels more robust)
Fixes#72179
Follow-up to #68056, adding support for export default declarations with function expressions, e.g.:
```tsx
export default function Page() {
useEffect(() => {})
}
```
Enabling this feature will be done in a future PR.
With this PR, we're adding one extra leading byte to Server Reference
IDs (both Server Actions and `"use cache"` functions), to include some
static information about the function itself.
The information byte has the following format:
```
0 000000 0
^type ^arg mask ^rest args
```
The type bit represents if the action is a cache function or not. For
cache functions, the type bit is set to `1`. Otherwise, it's `0`.
The arg mask bit is used to determine which arguments are used by the
function itself, up to 6 arguments. The bit is set to `1` if the
argument is used, or being spread or destructured (so it can be
indirectly or partially used). The bit is set to `0` otherwise.
The rest args bit is used to determine if there's a `...` rest argument
in the function signature. If there is, the bit is set to `1`.
For example:
```tsx
async function foo(a, foo, b, bar, ...baz) {
'use cache';
return a + b;
}
```
will have it encoded as `[1][101011][1]`. The first bit is set to `1`
because it's a cache function. The second part has `1010` because the
only arguments used are `a` and `b`. The subsequent `11` bits are set to
`1` because there's a `...baz` argument starting from the 5th. The last
bit is set to `1` as well for the same reason.
Note: Currently in this PR we don't track if an argument is actually
referenced in the function body or not. That will be implemented as a
follow-up optimization.
Also, the reference ID is currently hex-encoded so there will be exact 2
characters for easier decoding. This encoding might change though.
With this extra byte, the client can do some further optimizations. More
details can be found in the code comment.
With this PR, we're assigning names to the transformed `"use cache"`
functions, using the same rules as in #71478. Since we can't use named
function expressions here, we're using `Object.defineProperty` instead,
which we already used in #71478 for server actions with default export
expressions.
In addition, this PR fixes source mapping of `"use cache"` functions,
which was slightly off before, due to the wrong spans being assigned to
the new expressions.
**Before:**
<img width="943" alt="before"
src="https://github.com/user-attachments/assets/f7cf674c-32d4-4f0d-a304-d5de5637a6a1">
**After:**
<img width="943" alt="after"
src="https://github.com/user-attachments/assets/8edda482-a666-4431-bfad-7e21987331eb">
When importing a server action module from a client component, we've
already opted into the server layer, so defining inline `"use cache"`
annotated functions should be allowed.
Follow-up to #71497, adding support for exporting a function from a
`"use cache"` module using a default export expression, e.g.:
```ts
"use cache"
const foo = async () => {}
export default foo
```
This PR adjusts the server action transforms to assign proper function names for the generated server reference proxies.
- If the original function has a name, this name is used.
- If a function expression is assigned to a variable, the variable's name is used.
- If an anonymous function expression is assigned to a prop, the prop's name is used.
In addition, this PR simplifies the output for exported functions, avoiding unnecessary `registerServerReference` calls.
It also fixes the source mapping of default exported server actions.
**Before:**
<img width="890" alt="before" src="https://github.com/user-attachments/assets/a3d6a5f8-d48e-474d-8f03-b49306fb704f">
**After:**
<img width="890" alt="after" src="https://github.com/user-attachments/assets/8f332690-6c26-46f1-9eef-7680f47ea578">
Next up, we will do the same for `'use cache'` functions.
The hoisting of the proxy expressions only needs to be done for the
server layer. We can skip this part completely when we know we're
compiling a module for the client layer.
This fixes the server reference ID generation in client modules so that
they can be import and called from client components. In addition,
support for cached functions with decoupled export declarations is
added.
This PR fixes the transform of handling `export default async function()
{}` and `export const foo = async function() {}` cases (both are
exported `fnExpr`, instead of `fnDecl`) in a `"use cache"` annotated
file.
This adds support of collecting and binding encrypted closure variables
to references of `"use cache"` functions. These closures can be mixed
with `"use server"` in any order, too.
Check the tests for more information.
This PR fixes the cache function transform on the client layer, which
should be transpiled into a Server Reference with proper sourcemap
parameters, similar to Server Actions.
In the same vein as #69190, where we already unwrapped `createServerReference`, we now also unwrap `registerServerReference`, which is required for React to select the right call stack frame when generating source locations for server actions (see facebook/react#30741).
Whereas unwrapping of `createServerReference` was required for server actions that are imported into client components, unwrapping `registerServerReference` is needed for server actions that are passed from server components to client components.
This does not fully enable the source mapping just yet. For this to work end-to-end, the next step is to generate proper spans in the SWC transform, which will be done in the next PR.
This PR extends the cache directive to accept an additional type
parameter which defaults to `"default"`.
Several follow-ups:
- Accept different syntaxes (like places of spaces) and typo detection;
- Have a limited set of valid options with better errors.
For https://github.com/facebook/react/pull/30741
This PR adds several additional parameters to the
`createServerReference` calls generated by the Server Reference SWC
transform, to later enable React to map server actions that are imported
into client components back to their server locations (dev mode only).
Currently the inner `findSourceMapURL` function is not yet implemented.
In a follow-up we will unwrap `registerServerReference` as well, which
is needed for server actions in the react server layer.
---------
Co-authored-by: Hendrik Liebau <mail@hendrik-liebau.de>
Closes PACK-3254
1. Previously, guards were never removed, so a single if statement
containing `if(clearImmediate)` would mean that it's valid in the whole
file to use `clearImmediate` anywhere. Now it's only valid inside the
bodies of conditional. I haven't seen any additional lints caused by
this.
2. `if(process.env.NEXT_RUNTIME === 'edge')` guards are now respected
There are new test cases for each of these.
One new warning from this is the following from
`react/cjs/react.development.js` where the unrelated `typeof` doesn't
silence the error for `new MessageChannel()` anymore
```
function enqueueTask(task) {
if (null === enqueueTaskImpl)
try {
var requireString = ("require" + Math.random()).slice(0, 7);
enqueueTaskImpl = (module && module[requireString]).call(
module,
"timers"
).setImmediate;
} catch (_err) {
enqueueTaskImpl = function (callback) {
!1 === didWarnAboutMessageChannel &&
((didWarnAboutMessageChannel = !0),
"undefined" === typeof MessageChannel &&
console.error(
"This browser does not have a MessageChannel implementation, so enqueuing tasks via await act(async () => ...) will fail. Please file an issue at https://github.com/facebook/react/issues if you encounter this warning."
));
var channel = new MessageChannel(); /// <---------
channel.port1.onmessage = callback;
channel.port2.postMessage(void 0);
};
}
return enqueueTaskImpl(task);
}
```
### What?
Implements a transform that adds readable names to anonymous function
expressions in react component functions.
Adding `{ debugFunctionName: true }` to swcOptions will do the trick.
### Why?
x-ref: https://vercel.slack.com/archives/C04TR3U872A/p1721702161121619
### How?