Skip to content

Commit

Permalink
Improve the Server Actions SWC transform (part 2) (#62052)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
shuding authored and MaxLeiter committed Feb 28, 2024
1 parent ef81b10 commit 6e59c22
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ impl<C: Comments> ServerActions<C> {
self.config.enabled,
);

if is_action_fn && !self.config.is_react_server_layer {
if is_action_fn && !self.config.is_react_server_layer && !self.in_action_file {
HANDLER.with(|handler| {
handler
.struct_span_err(
Expand Down Expand Up @@ -459,7 +459,8 @@ impl<C: Comments> VisitMut for ServerActions<C> {
});
}

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

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

if self.has_action {
let mut actions = self.export_actions.clone();

// All exported values are considered as actions if the file is an action file.
if self.in_action_file {
actions.extend(self.exported_idents.iter().map(|e| e.1.clone()));
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
'use server'

let a, f

export async function action0(b, c, ...g) {
return async function action1(d) {
'use server'
let f
console.log(...window, { window })
console.log(a, b, action2)

async function action2(e) {
'use server'
console.log(a, c, d, e, f, g)
}

return [
action2,
async function action3(e) {
'use server'
action2(e)
console.log(a, c, d, e)
},
]
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
'use server'

let a, f

export async function action0(b, c, ...g) {
return async function action1(d) {
'use server'
let f
console.log(...window, { window })
console.log(a, b, action2)

async function action2(e) {
'use server'
console.log(a, c, d, e, f, g)
}

return [
action2,
async function action3(e) {
'use server'
action2(e)
console.log(a, c, d, e)
},
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/* __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";
import { encryptActionBoundArgs, decryptActionBoundArgs } from "private-next-rsc-action-encryption";
let a, f;
export async function action0(b, c, ...g) {
return registerServerReference("9878bfa39811ca7650992850a8751f9591b6a557", $$ACTION_2).bind(null, encryptActionBoundArgs("9878bfa39811ca7650992850a8751f9591b6a557", [
c,
g,
b
]));
}
export async function $$ACTION_0($$ACTION_CLOSURE_BOUND, e) {
var [$$ACTION_ARG_0, $$ACTION_ARG_1, $$ACTION_ARG_2, $$ACTION_ARG_3] = await decryptActionBoundArgs("6d53ce510b2e36499b8f56038817b9bad86cabb4", $$ACTION_CLOSURE_BOUND);
console.log(a, $$ACTION_ARG_0, $$ACTION_ARG_1, e, $$ACTION_ARG_2, $$ACTION_ARG_3);
}
export async function $$ACTION_1($$ACTION_CLOSURE_BOUND, e) {
var [$$ACTION_ARG_0, $$ACTION_ARG_1, $$ACTION_ARG_2] = await decryptActionBoundArgs("188d5d945750dc32e2c842b93c75a65763d4a922", $$ACTION_CLOSURE_BOUND);
$$ACTION_ARG_0(e);
console.log(a, $$ACTION_ARG_1, $$ACTION_ARG_2, e);
}
export async function $$ACTION_2($$ACTION_CLOSURE_BOUND, d) {
var [$$ACTION_ARG_0, $$ACTION_ARG_1, $$ACTION_ARG_2] = await decryptActionBoundArgs("9878bfa39811ca7650992850a8751f9591b6a557", $$ACTION_CLOSURE_BOUND);
let f;
console.log(...window, {
window
});
console.log(a, $$ACTION_ARG_2, action2);
var action2 = registerServerReference("6d53ce510b2e36499b8f56038817b9bad86cabb4", $$ACTION_0).bind(null, encryptActionBoundArgs("6d53ce510b2e36499b8f56038817b9bad86cabb4", [
$$ACTION_ARG_0,
d,
f,
$$ACTION_ARG_1
]));
return [
action2,
registerServerReference("188d5d945750dc32e2c842b93c75a65763d4a922", $$ACTION_1).bind(null, encryptActionBoundArgs("188d5d945750dc32e2c842b93c75a65763d4a922", [
action2,
$$ACTION_ARG_0,
d
]))
];
}
import { ensureServerEntryExports } from "private-next-rsc-action-validate";
ensureServerEntryExports([
action0
]);
registerServerReference("0090eaf4e1f08a2d94f6be401e54a2ded399b87c", action0);
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
/* __next_internal_action_entry_do_not_use__ {"1ab723c80dcca470e0410b4b2a2fc2bf21f41476":"c","6e7bc104e4d6e7fda190c4a51be969cfd0be6d6d":"a","d1f7eb64271d7c601dfef7d4d7053de1c2ca4338":"b"} */ import { createActionProxy } from "private-next-rsc-action-proxy";
/* __next_internal_action_entry_do_not_use__ {"1ab723c80dcca470e0410b4b2a2fc2bf21f41476":"c","6d53ce510b2e36499b8f56038817b9bad86cabb4":"$$ACTION_0","6e7bc104e4d6e7fda190c4a51be969cfd0be6d6d":"a","d1f7eb64271d7c601dfef7d4d7053de1c2ca4338":"b"} */ import { registerServerReference } from "private-next-rsc-server-reference";
import { encryptActionBoundArgs, decryptActionBoundArgs } from "private-next-rsc-action-encryption";
export async function a() {}
export async function b() {}
export async function c() {}
function d() {}
function Foo() {
async function e() {}
var e = registerServerReference("6d53ce510b2e36499b8f56038817b9bad86cabb4", $$ACTION_0);
}
export async function $$ACTION_0() {}
import { ensureServerEntryExports } from "private-next-rsc-action-validate";
ensureServerEntryExports([
a,
b,
c
]);
createActionProxy("6e7bc104e4d6e7fda190c4a51be969cfd0be6d6d", a);
createActionProxy("d1f7eb64271d7c601dfef7d4d7053de1c2ca4338", b);
createActionProxy("1ab723c80dcca470e0410b4b2a2fc2bf21f41476", c);
registerServerReference("6e7bc104e4d6e7fda190c4a51be969cfd0be6d6d", a);
registerServerReference("d1f7eb64271d7c601dfef7d4d7053de1c2ca4338", b);
registerServerReference("1ab723c80dcca470e0410b4b2a2fc2bf21f41476", c);

0 comments on commit 6e59c22

Please sign in to comment.