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 479b65ce7a6..d5af45d7010 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 726c9a24567..3ee1539e412 100644 --- a/packages/cli/flight-server-transform-plugin/src/lib.rs +++ b/packages/cli/flight-server-transform-plugin/src/lib.rs @@ -1,15 +1,13 @@ use std::path::PathBuf; -use path_slash::PathBufExt; use serde::{Serialize, Deserialize}; use serde_json::json; use swc_core::{ - common::{comments::{Comment, CommentKind, Comments}, DUMMY_SP}, - ecma::{ + common::{comments::{Comment, CommentKind, Comments}, DUMMY_SP}, ecma::{ ast::{ArrowExpr, BindingIdent, BlockStmt, BlockStmtOrExpr, CallExpr, Callee, ClassDecl, Decl, DefaultDecl, ExportDecl, ExportDefaultDecl, ExportDefaultExpr, ExportSpecifier, Expr, ExprOrSpread, ExprStmt, FnDecl, Function, Ident, IdentName, ImportDecl, ImportNamedSpecifier, ImportPhase, ImportSpecifier, Lit, MemberExpr, MemberProp, Module, ModuleDecl, ModuleExportName, ModuleItem, NamedExport, NewExpr, Param, Pat, Program, ReturnStmt, Stmt, Str, ThrowStmt, Tpl, TplElement, VarDecl, VarDeclKind, VarDeclarator}, parser::{Syntax, TsSyntax}, transforms::testing::{test, test_fixture}, visit::{visit_mut_pass, VisitMut, VisitMutWith} - }, plugin::metadata::TransformPluginMetadataContextKind, testing::fixture + }, plugin::metadata::TransformPluginMetadataContextKind, quote, testing::fixture }; use swc_core::plugin::{plugin_transform, proxies::TransformPluginProgramMetadata}; @@ -112,7 +110,7 @@ where imported: None, is_type_only: false, })], - src: Box::new(Str::from(self.runtime_path.clone())), + src: Box::new(Str::from(self.runtime_path.as_str())), type_only: false, with: None, phase: ImportPhase::Evaluation, @@ -120,81 +118,16 @@ where } fn create_proxy_function(&self) -> ModuleItem { - let error_msg = format!( - "Attempted to call {{}}() from the server of {} but {{}} is on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.", - self.filename - ); - - let parts: Vec<&str> = error_msg.split("{}").collect(); - - ModuleItem::Stmt(Stmt::Decl(Decl::Fn(FnDecl { - ident: Ident::new("createClientReferenceProxy".into(), DUMMY_SP, Default::default()), - function: Box::new(Function { - params: vec![Param { - span: DUMMY_SP, - decorators: vec![], - pat: Pat::Ident(BindingIdent { - id: Ident::new("exportName".into(), DUMMY_SP, Default::default()), - type_ann: None, - }), - }], - ctxt: Default::default(), - body: Some(BlockStmt { - span: DUMMY_SP, - stmts: vec![Stmt::Return(ReturnStmt { - span: DUMMY_SP, - arg: Some(Box::new(Expr::Arrow(ArrowExpr { - span: DUMMY_SP, - params: vec![], - body: Box::new(BlockStmtOrExpr::BlockStmt(BlockStmt { - span: DUMMY_SP, - stmts: vec![Stmt::Throw(ThrowStmt { - span: DUMMY_SP, - arg: Box::new(Expr::New(NewExpr { - span: DUMMY_SP, - callee: Box::new(Expr::Ident(Ident::new("Error".into(), DUMMY_SP, Default::default()))), - args: Some(vec![ExprOrSpread { - spread: None, - expr: Box::new(Expr::Tpl(Tpl { - span: DUMMY_SP, - exprs: vec![ - Box::new(Expr::Ident(Ident::new("exportName".into(), DUMMY_SP, Default::default()))), - Box::new(Expr::Ident(Ident::new("exportName".into(), DUMMY_SP, Default::default()))), - ], - quasis: parts.iter().enumerate().map(|(i, &text)| { - TplElement { - span: DUMMY_SP, - tail: i == parts.len() - 1, - cooked: Some(text.into()), - raw: text.into(), - } - }).collect(), - })), - }]), - ctxt: Default::default(), - type_args: None, - })), - })], - ctxt: Default::default(), - })), - ctxt: Default::default(), - is_async: false, - is_generator: false, - return_type: None, - type_params: None, - }))), - })], - ctxt: Default::default(), - }), - span: DUMMY_SP, - is_async: false, - is_generator: false, - return_type: None, - type_params: None, - decorators: vec![], - }), - declare: false, - }))) + quote!( + "function createClientReferenceProxy($export_name) { + const filename = $file_path; + return () => { + throw new Error(`Attempted to call ${$export_name}() from the server of ${filename} but ${$export_name} is on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.`); + } + }" as ModuleItem, + file_path: Expr = Str::from(self.filename.as_str()).into(), + export_name = Ident::new("exportName".into(), DUMMY_SP, Default::default()) + ) } fn create_client_reference(&self, export_name: &str) -> Expr { @@ -238,7 +171,7 @@ where imported: None, is_type_only: false, })], - src: Box::new(Str::from(self.runtime_path.clone())), + src: Box::new(Str::from(self.runtime_path.as_str())), type_only: false, with: None, phase: ImportPhase::Evaluation, @@ -761,7 +694,7 @@ pub fn process_transform(program: Program, metadata: TransformPluginProgramMetad let config = serde_json::from_str::( &metadata.get_transform_plugin_config().unwrap_or_default() ).unwrap_or_default(); - let comments = metadata.comments.clone(); + let comments = metadata.comments; program.apply(&mut visit_mut_pass(TransformVisitor::new(filename, comments, config.app_dir, config.runtime_path))) } diff --git a/packages/cli/flight-server-transform-plugin/tests/fixture/client-components/output.js b/packages/cli/flight-server-transform-plugin/tests/fixture/client-components/output.js index b426dbdbfb9..ba68c3410a2 100644 --- a/packages/cli/flight-server-transform-plugin/tests/fixture/client-components/output.js +++ b/packages/cli/flight-server-transform-plugin/tests/fixture/client-components/output.js @@ -3,8 +3,9 @@ "use client"; import { registerClientReference } from "@modern-js/runtime/rsc/server"; function createClientReferenceProxy(exportName) { + const filename = "tests/fixture/client-components/input.tsx"; return ()=>{ - throw new Error(`Attempted to call ${exportName}() from the server of tests/fixture/client-components/input.tsx but ${exportName} is on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.`); + throw new Error(`Attempted to call ${exportName}() from the server of ${filename} but ${exportName} is on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.`); }; } export const ClassA = registerClientReference(createClientReferenceProxy("ClassA"), "tests/fixture/client-components/input.tsx#ClassA", "ClassA"); diff --git a/packages/cli/uni-builder/tests/loaders/__snapshots__/rsc-server-loader.test.ts.snap b/packages/cli/uni-builder/tests/loaders/__snapshots__/rsc-server-loader.test.ts.snap index 31d88b615cd..e2aafacec26 100644 --- a/packages/cli/uni-builder/tests/loaders/__snapshots__/rsc-server-loader.test.ts.snap +++ b/packages/cli/uni-builder/tests/loaders/__snapshots__/rsc-server-loader.test.ts.snap @@ -59,8 +59,9 @@ exports[`rscServerLoader > support use client directive 1`] = ` {\\"directive\\":\\"client\\",\\"exportNames\\":[{\\"exportName\\":\\"ClassA\\",\\"id\\":\\"fixtures/client-component.jsx#ClassA\\"},{\\"exportName\\":\\"ComponentA\\",\\"id\\":\\"fixtures/client-component.jsx#ComponentA\\"},{\\"exportName\\":\\"MemoizedComponentA\\",\\"id\\":\\"fixtures/client-component.jsx#MemoizedComponentA\\"},{\\"exportName\\":\\"ComponentB\\",\\"id\\":\\"fixtures/client-component.jsx#ComponentB\\"},{\\"exportName\\":\\"foo\\",\\"id\\":\\"fixtures/client-component.jsx#foo\\"},{\\"exportName\\":\\"ComponentC\\",\\"id\\":\\"fixtures/client-component.jsx#ComponentC\\"},{\\"exportName\\":\\"ComponentD\\",\\"id\\":\\"fixtures/client-component.jsx#ComponentD\\"},{\\"exportName\\":\\"bar\\",\\"id\\":\\"fixtures/client-component.jsx#bar\\"},{\\"exportName\\":\\"ComponentE\\",\\"id\\":\\"fixtures/client-component.jsx#ComponentE\\"},{\\"exportName\\":\\"ComponentF\\",\\"id\\":\\"fixtures/client-component.jsx#ComponentF\\"},{\\"exportName\\":\\"default\\",\\"id\\":\\"fixtures/client-component.jsx#default\\"}]}*/ \\"use client\\"; import { registerClientReference } from \\"@modern-js/runtime/rsc/server\\"; function createClientReferenceProxy(exportName) { + const filename = \\"fixtures/client-component.jsx\\"; return ()=>{ - throw new Error(\`Attempted to call \${exportName}() from the server of fixtures/client-component.jsx but \${exportName} is on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.\`); + throw new Error(\`Attempted to call \${exportName}() from the server of \${filename} but \${exportName} is on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.\`); }; } export const ClassA = registerClientReference(createClientReferenceProxy(\\"ClassA\\"), \\"fixtures/client-component.jsx#ClassA\\", \\"ClassA\\"); diff --git a/tests/integration/rsc-csr-app/src/App.tsx b/tests/integration/rsc-csr-app/src/App.tsx index f918ae7f492..d9d7fa49563 100644 --- a/tests/integration/rsc-csr-app/src/App.tsx +++ b/tests/integration/rsc-csr-app/src/App.tsx @@ -1,9 +1,9 @@ import 'server-only'; import { Suspense } from 'react'; import styles from './App.module.less'; -import Suspended from './Suspended'; import { Counter } from './components/Counter'; import { getCountState } from './components/ServerState'; +import Suspended from './components/Suspended'; const App = () => { const countStateFromServer = getCountState();