Skip to content

Commit 6e59c22

Browse files
shudingMaxLeiter
authored andcommitted
Improve the Server Actions SWC transform (part 2) (#62052)
This fills the last piece in the puzzle and it's based on #61001. In "use server" file. And this PR extends that to a "use server" file so exported values are automatically handled just like before, but any other definitions including nested ones will be hoisted and marked correctly now. ```ts 'use server' let a, f export async function action0(b, c, ...g) { // <- Handled like before. return async function action1(d) { // <- Renamed, marked and hoisted. 'use server' let f console.log(...window, { window }) console.log(a, b, action2) async function action2(e) { // <- Renamed, marked and hoisted. 'use server' console.log(a, c, d, e, f, g) } return [ action2, async function action3(e) { // <- Renamed, marked and hoisted. 'use server' action2(e) console.log(a, c, d, e) }, ] } } ``` Closes NEXT-2491
1 parent ef81b10 commit 6e59c22

File tree

6 files changed

+112
-8
lines changed

6 files changed

+112
-8
lines changed

packages/next-swc/crates/next-custom-transforms/src/transforms/server_actions.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ impl<C: Comments> ServerActions<C> {
132132
self.config.enabled,
133133
);
134134

135-
if is_action_fn && !self.config.is_react_server_layer {
135+
if is_action_fn && !self.config.is_react_server_layer && !self.in_action_file {
136136
HANDLER.with(|handler| {
137137
handler
138138
.struct_span_err(
@@ -459,7 +459,8 @@ impl<C: Comments> VisitMut for ServerActions<C> {
459459
});
460460
}
461461

462-
if !self.in_action_file {
462+
if !(self.in_action_file && self.in_export_decl) {
463+
// It's an action function. If it doesn't have a name, give it one.
463464
match f.ident.as_mut() {
464465
None => {
465466
let action_name = gen_ident(&mut self.action_cnt);
@@ -541,7 +542,7 @@ impl<C: Comments> VisitMut for ServerActions<C> {
541542
});
542543
}
543544

544-
if !self.in_action_file {
545+
if !(self.in_action_file && self.in_export_decl) {
545546
// Collect all the identifiers defined inside the closure and used
546547
// in the action function. With deduplication.
547548
retain_names_from_declared_idents(&mut child_names, &current_declared_idents);
@@ -1022,6 +1023,8 @@ impl<C: Comments> VisitMut for ServerActions<C> {
10221023

10231024
if self.has_action {
10241025
let mut actions = self.export_actions.clone();
1026+
1027+
// All exported values are considered as actions if the file is an action file.
10251028
if self.in_action_file {
10261029
actions.extend(self.exported_idents.iter().map(|e| e.1.clone()));
10271030
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
'use server'
2+
3+
let a, f
4+
5+
export async function action0(b, c, ...g) {
6+
return async function action1(d) {
7+
'use server'
8+
let f
9+
console.log(...window, { window })
10+
console.log(a, b, action2)
11+
12+
async function action2(e) {
13+
'use server'
14+
console.log(a, c, d, e, f, g)
15+
}
16+
17+
return [
18+
action2,
19+
async function action3(e) {
20+
'use server'
21+
action2(e)
22+
console.log(a, c, d, e)
23+
},
24+
]
25+
}
26+
}

packages/next-swc/crates/next-custom-transforms/tests/fixture/server-actions/client/5/output.js

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
'use server'
2+
3+
let a, f
4+
5+
export async function action0(b, c, ...g) {
6+
return async function action1(d) {
7+
'use server'
8+
let f
9+
console.log(...window, { window })
10+
console.log(a, b, action2)
11+
12+
async function action2(e) {
13+
'use server'
14+
console.log(a, c, d, e, f, g)
15+
}
16+
17+
return [
18+
action2,
19+
async function action3(e) {
20+
'use server'
21+
action2(e)
22+
console.log(a, c, d, e)
23+
},
24+
]
25+
}
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/* __next_internal_action_entry_do_not_use__ {"0090eaf4e1f08a2d94f6be401e54a2ded399b87c":"action0","188d5d945750dc32e2c842b93c75a65763d4a922":"$$ACTION_1","6d53ce510b2e36499b8f56038817b9bad86cabb4":"$$ACTION_0","9878bfa39811ca7650992850a8751f9591b6a557":"$$ACTION_2"} */ import { registerServerReference } from "private-next-rsc-server-reference";
2+
import { encryptActionBoundArgs, decryptActionBoundArgs } from "private-next-rsc-action-encryption";
3+
let a, f;
4+
export async function action0(b, c, ...g) {
5+
return registerServerReference("9878bfa39811ca7650992850a8751f9591b6a557", $$ACTION_2).bind(null, encryptActionBoundArgs("9878bfa39811ca7650992850a8751f9591b6a557", [
6+
c,
7+
g,
8+
b
9+
]));
10+
}
11+
export async function $$ACTION_0($$ACTION_CLOSURE_BOUND, e) {
12+
var [$$ACTION_ARG_0, $$ACTION_ARG_1, $$ACTION_ARG_2, $$ACTION_ARG_3] = await decryptActionBoundArgs("6d53ce510b2e36499b8f56038817b9bad86cabb4", $$ACTION_CLOSURE_BOUND);
13+
console.log(a, $$ACTION_ARG_0, $$ACTION_ARG_1, e, $$ACTION_ARG_2, $$ACTION_ARG_3);
14+
}
15+
export async function $$ACTION_1($$ACTION_CLOSURE_BOUND, e) {
16+
var [$$ACTION_ARG_0, $$ACTION_ARG_1, $$ACTION_ARG_2] = await decryptActionBoundArgs("188d5d945750dc32e2c842b93c75a65763d4a922", $$ACTION_CLOSURE_BOUND);
17+
$$ACTION_ARG_0(e);
18+
console.log(a, $$ACTION_ARG_1, $$ACTION_ARG_2, e);
19+
}
20+
export async function $$ACTION_2($$ACTION_CLOSURE_BOUND, d) {
21+
var [$$ACTION_ARG_0, $$ACTION_ARG_1, $$ACTION_ARG_2] = await decryptActionBoundArgs("9878bfa39811ca7650992850a8751f9591b6a557", $$ACTION_CLOSURE_BOUND);
22+
let f;
23+
console.log(...window, {
24+
window
25+
});
26+
console.log(a, $$ACTION_ARG_2, action2);
27+
var action2 = registerServerReference("6d53ce510b2e36499b8f56038817b9bad86cabb4", $$ACTION_0).bind(null, encryptActionBoundArgs("6d53ce510b2e36499b8f56038817b9bad86cabb4", [
28+
$$ACTION_ARG_0,
29+
d,
30+
f,
31+
$$ACTION_ARG_1
32+
]));
33+
return [
34+
action2,
35+
registerServerReference("188d5d945750dc32e2c842b93c75a65763d4a922", $$ACTION_1).bind(null, encryptActionBoundArgs("188d5d945750dc32e2c842b93c75a65763d4a922", [
36+
action2,
37+
$$ACTION_ARG_0,
38+
d
39+
]))
40+
];
41+
}
42+
import { ensureServerEntryExports } from "private-next-rsc-action-validate";
43+
ensureServerEntryExports([
44+
action0
45+
]);
46+
registerServerReference("0090eaf4e1f08a2d94f6be401e54a2ded399b87c", action0);
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
1-
/* __next_internal_action_entry_do_not_use__ {"1ab723c80dcca470e0410b4b2a2fc2bf21f41476":"c","6e7bc104e4d6e7fda190c4a51be969cfd0be6d6d":"a","d1f7eb64271d7c601dfef7d4d7053de1c2ca4338":"b"} */ import { createActionProxy } from "private-next-rsc-action-proxy";
1+
/* __next_internal_action_entry_do_not_use__ {"1ab723c80dcca470e0410b4b2a2fc2bf21f41476":"c","6d53ce510b2e36499b8f56038817b9bad86cabb4":"$$ACTION_0","6e7bc104e4d6e7fda190c4a51be969cfd0be6d6d":"a","d1f7eb64271d7c601dfef7d4d7053de1c2ca4338":"b"} */ import { registerServerReference } from "private-next-rsc-server-reference";
22
import { encryptActionBoundArgs, decryptActionBoundArgs } from "private-next-rsc-action-encryption";
33
export async function a() {}
44
export async function b() {}
55
export async function c() {}
66
function d() {}
77
function Foo() {
8-
async function e() {}
8+
var e = registerServerReference("6d53ce510b2e36499b8f56038817b9bad86cabb4", $$ACTION_0);
99
}
10+
export async function $$ACTION_0() {}
1011
import { ensureServerEntryExports } from "private-next-rsc-action-validate";
1112
ensureServerEntryExports([
1213
a,
1314
b,
1415
c
1516
]);
16-
createActionProxy("6e7bc104e4d6e7fda190c4a51be969cfd0be6d6d", a);
17-
createActionProxy("d1f7eb64271d7c601dfef7d4d7053de1c2ca4338", b);
18-
createActionProxy("1ab723c80dcca470e0410b4b2a2fc2bf21f41476", c);
17+
registerServerReference("6e7bc104e4d6e7fda190c4a51be969cfd0be6d6d", a);
18+
registerServerReference("d1f7eb64271d7c601dfef7d4d7053de1c2ca4338", b);
19+
registerServerReference("1ab723c80dcca470e0410b4b2a2fc2bf21f41476", c);

0 commit comments

Comments
 (0)