diff --git a/packages/cli/flight-server-transform-plugin/flight_server_transform_plugin.wasm b/packages/cli/flight-server-transform-plugin/flight_server_transform_plugin.wasm index ff5cda041d2..0cf1f4edcaf 100755 Binary files a/packages/cli/flight-server-transform-plugin/flight_server_transform_plugin.wasm and b/packages/cli/flight-server-transform-plugin/flight_server_transform_plugin.wasm differ diff --git a/packages/cli/flight-server-transform-plugin/src/lib.rs b/packages/cli/flight-server-transform-plugin/src/lib.rs index fd61e60d74d..39d2d76a5a5 100644 --- a/packages/cli/flight-server-transform-plugin/src/lib.rs +++ b/packages/cli/flight-server-transform-plugin/src/lib.rs @@ -58,6 +58,7 @@ where comments: Option, export_mappings: Vec, runtime_path: String, + action_count: u8, } #[derive(Debug)] @@ -67,6 +68,13 @@ struct ServerReferenceInfo { local_name: String, } +#[derive(Debug)] +struct VarDeclInsertInfo { + position: usize, + ident: Ident, + expr: Box, +} + impl TransformVisitor where C: Comments, @@ -81,6 +89,7 @@ where comments, export_mappings: vec![], runtime_path, + action_count: 0, } } @@ -494,8 +503,10 @@ where let mut actions_to_insert: Vec = vec![]; let has_server_directive = self.directive == Some(Directive::Server); + let mut var_decls_to_insert: Vec = vec![]; + while i < module.body.len() { - match &module.body[i] { + match &mut module.body[i] { ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl { decl, .. })) => { match decl { Decl::Fn(fn_decl) => { @@ -553,14 +564,25 @@ where } } } - ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultDecl(ExportDefaultDecl { decl, .. })) => { + ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultDecl(ExportDefaultDecl { ref mut decl, .. })) => { match decl { - DefaultDecl::Fn(fn_expr) => { + DefaultDecl::Fn(ref mut fn_expr) => { if has_server_directive || self.has_server_directive_in_function(&fn_expr.function) { self.add_reference("default".to_string(), ReferenceType::Server); + + let ident = if let Some(ref mut ident) = fn_expr.ident { + ident.clone() + } else { + let new_ident = format!("$$ACTION_{}", self.action_count); + self.action_count += 1; + let new_ident_ident = Ident::new(new_ident.into(), DUMMY_SP, Default::default()); + fn_expr.ident = Some(new_ident_ident.clone()); + new_ident_ident + }; + actions_to_insert.push(ServerReferenceInfo { position: i + 1, - ident: Ident::new("default".into(), DUMMY_SP, Default::default()), + ident, local_name: "default".to_string(), }); } @@ -573,9 +595,23 @@ where Expr::Arrow(arrow) => { if has_server_directive || self.has_server_directive_in_arrow(arrow) { self.add_reference("default".to_string(), ReferenceType::Server); + + let new_ident = format!("$$ACTION_{}", self.action_count); + self.action_count += 1; + let ident = Ident::new(new_ident.into(), DUMMY_SP, Default::default()); + + let var_decl_info = VarDeclInsertInfo { + position: i, + ident: ident.clone(), + expr: expr.clone(), + }; + var_decls_to_insert.push(var_decl_info); + + *expr = Box::new(Expr::Ident(ident.clone())); + actions_to_insert.push(ServerReferenceInfo { - position: i + 1, - ident: Ident::new("default".into(), DUMMY_SP, Default::default()), + position: i, + ident, local_name: "default".to_string(), }); } @@ -662,6 +698,26 @@ where module.body.insert(info.position + offset + 1, ModuleItem::Stmt(server_ref)); } } + + for (offset, info) in var_decls_to_insert.into_iter().enumerate() { + let var_decl = ModuleItem::Stmt(Stmt::Decl(Decl::Var(Box::new(VarDecl { + span: DUMMY_SP, + kind: VarDeclKind::Const, + declare: false, + decls: vec![VarDeclarator { + span: DUMMY_SP, + name: Pat::Ident(BindingIdent { + id: info.ident, + type_ann: None, + }), + init: Some(info.expr), + definite: false, + }], + ctxt: Default::default(), + })))); + + module.body.insert(info.position + offset + 1, var_decl); + } } diff --git a/packages/cli/flight-server-transform-plugin/tests/fixture/default-actions/arrow/input.tsx b/packages/cli/flight-server-transform-plugin/tests/fixture/default-actions/arrow/input.tsx new file mode 100644 index 00000000000..027dda42b54 --- /dev/null +++ b/packages/cli/flight-server-transform-plugin/tests/fixture/default-actions/arrow/input.tsx @@ -0,0 +1,6 @@ +import { z } from 'zod'; + +export default () => { + 'use server'; + return `default`; +} diff --git a/packages/cli/flight-server-transform-plugin/tests/fixture/default-actions/arrow/output.js b/packages/cli/flight-server-transform-plugin/tests/fixture/default-actions/arrow/output.js new file mode 100644 index 00000000000..aa9e999023c --- /dev/null +++ b/packages/cli/flight-server-transform-plugin/tests/fixture/default-actions/arrow/output.js @@ -0,0 +1,12 @@ +/* @modern-js-rsc-metadata +{"directive":null,"exportNames":[{"exportName":"default"}]}*/ +import { registerServerReference } from "@modern-js/runtime/rsc/server"; +import { z } from 'zod'; + +const $$ACTION_0 = () => { + 'use server'; + return `default`; +} + +registerServerReference($$ACTION_0, module.id, "default"); +export default $$ACTION_0; diff --git a/packages/cli/flight-server-transform-plugin/tests/fixture/default-actions/function-decl/input.tsx b/packages/cli/flight-server-transform-plugin/tests/fixture/default-actions/function-decl/input.tsx new file mode 100644 index 00000000000..a84d2a619d3 --- /dev/null +++ b/packages/cli/flight-server-transform-plugin/tests/fixture/default-actions/function-decl/input.tsx @@ -0,0 +1,6 @@ +import { z } from 'zod'; + +export default async function(){ + 'use server'; + return `default`; +} diff --git a/packages/cli/flight-server-transform-plugin/tests/fixture/default-actions/function-decl/output.js b/packages/cli/flight-server-transform-plugin/tests/fixture/default-actions/function-decl/output.js new file mode 100644 index 00000000000..07933f70d3f --- /dev/null +++ b/packages/cli/flight-server-transform-plugin/tests/fixture/default-actions/function-decl/output.js @@ -0,0 +1,11 @@ +/* @modern-js-rsc-metadata +{"directive":null,"exportNames":[{"exportName":"default"}]}*/ +import { registerServerReference } from "@modern-js/runtime/rsc/server"; +import { z } from 'zod'; + +export default async function $$ACTION_0(){ + 'use server'; + return `default`; +} + +registerServerReference($$ACTION_0, module.id, "default"); diff --git a/packages/cli/flight-server-transform-plugin/tests/fixture/inline-actions/input.tsx b/packages/cli/flight-server-transform-plugin/tests/fixture/inline-actions/input.tsx index 49c8646c484..19a30b3890c 100644 --- a/packages/cli/flight-server-transform-plugin/tests/fixture/inline-actions/input.tsx +++ b/packages/cli/flight-server-transform-plugin/tests/fixture/inline-actions/input.tsx @@ -23,6 +23,11 @@ async function qux() { return `qux`; } +export default async function increment() { + 'use server'; + return `increment`; +} + export async function Component() { async function handleServerAction(formData) { 'use server'; diff --git a/packages/cli/flight-server-transform-plugin/tests/fixture/inline-actions/output.js b/packages/cli/flight-server-transform-plugin/tests/fixture/inline-actions/output.js index 3c509d3b9b6..79de50a0ef0 100644 --- a/packages/cli/flight-server-transform-plugin/tests/fixture/inline-actions/output.js +++ b/packages/cli/flight-server-transform-plugin/tests/fixture/inline-actions/output.js @@ -1,5 +1,5 @@ /* @modern-js-rsc-metadata -{"directive":null,"exportNames":[{"exportName":"foo"},{"exportName":"baz"},{"exportName":"qux"}]}*/ +{"directive":null,"exportNames":[{"exportName":"foo"},{"exportName":"baz"},{"exportName":"qux"},{"exportName":"default"}]}*/ import { registerServerReference } from "@modern-js/runtime/rsc/server"; import { z } from 'zod'; @@ -27,6 +27,13 @@ async function qux() { registerServerReference(qux, module.id, "qux"); +export default async function increment() { + 'use server'; + return `increment`; +} + +registerServerReference(increment, module.id, "default"); + export async function Component() { async function handleServerAction(formData) { 'use server';