Skip to content

Commit

Permalink
Process Client -> RSC Server Actions as TS (vercel#57454)
Browse files Browse the repository at this point in the history
### What?

Fixes Client -> RSC (client importing a `"user server"` file) Server
Actions that are using TS.

### Why?

### How?

I check if the source module is using TS before "processing" the module
into the RSC layer.

Closes WEB-1871
  • Loading branch information
jridgewell authored Oct 25, 2023
1 parent 164e439 commit aa28fa5
Showing 1 changed file with 32 additions and 14 deletions.
46 changes: 32 additions & 14 deletions packages/next-swc/crates/next-api/src/server_actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use next_core::{
use next_swc::server_actions::parse_server_actions;
use turbo_tasks::{
graph::{GraphTraversal, NonDeterministic},
TryFlatJoinIterExt, Value, ValueToString, Vc,
TryFlatJoinIterExt, TryJoinIterExt, Value, ValueToString, Vc,
};
use turbopack_binding::{
turbo::tasks_fs::{rope::RopeBuilder, File, FileSystemPath},
Expand All @@ -22,14 +22,16 @@ use turbopack_binding::{
module::Module,
output::OutputAsset,
reference::primary_referenced_modules,
reference_type::{EcmaScriptModulesReferenceSubType, ReferenceType},
reference_type::{
EcmaScriptModulesReferenceSubType, ReferenceType, TypeScriptReferenceSubType,
},
virtual_output::VirtualOutputAsset,
virtual_source::VirtualSource,
},
ecmascript::{
chunk::{EcmascriptChunkPlaceable, EcmascriptChunkingContext},
parse::ParseResult,
EcmascriptModuleAsset,
EcmascriptModuleAsset, EcmascriptModuleAssetType,
},
},
};
Expand Down Expand Up @@ -103,7 +105,7 @@ async fn build_server_actions_loader(
}
write!(contents, "}});")?;

let output_path = node_root.join(format!("server/app{page_name}/actions.js"));
let output_path = node_root.join(format!("server/app{page_name}/actions.ts"));
let file = File::from(contents.build());
let source = VirtualSource::new(output_path, AssetContent::file(file.into()));
let module = asset_context.process(
Expand Down Expand Up @@ -163,6 +165,11 @@ async fn build_manifest(
)))
}

#[turbo_tasks::function]
fn action_modifier() -> Vc<String> {
Vc::cell("action".to_string())
}

/// Traverses the entire module graph starting from [module], looking for magic
/// comment which identifies server actions. Every found server action will be
/// returned along with the module which exports that action.
Expand Down Expand Up @@ -191,25 +198,36 @@ async fn get_actions(
.try_flat_join()
.await?
.into_iter()
.map(|((layer, module), actions)| {
.map(|((layer, module), actions)| async move {
let module = if layer == ActionLayer::Rsc {
module
} else {
// The ActionBrowser layer's module is in the Client context, and we need to
// bring it into the RSC context.
let source = VirtualSource::new(
module.ident().path().join("action.js".to_string()),
let source = VirtualSource::new_with_ident(
module.ident().with_modifier(action_modifier()),
module.content(),
);
asset_context.process(
Vc::upcast(source),
Value::new(ReferenceType::EcmaScriptModules(
EcmaScriptModulesReferenceSubType::Undefined,
)),
)
let ty = if let Some(module) =
Vc::try_resolve_downcast_type::<EcmascriptModuleAsset>(module).await?
{
if module.await?.ty == EcmascriptModuleAssetType::Ecmascript {
ReferenceType::EcmaScriptModules(
EcmaScriptModulesReferenceSubType::Undefined,
)
} else {
ReferenceType::TypeScript(TypeScriptReferenceSubType::Undefined)
}
} else {
ReferenceType::TypeScript(TypeScriptReferenceSubType::Undefined)
};
asset_context.process(Vc::upcast(source), Value::new(ty))
};
((layer, module), actions)
Ok(((layer, module), actions))
})
.try_join()
.await?
.into_iter()
.collect::<IndexMap<_, _>>();

all_actions.sort_keys();
Expand Down

0 comments on commit aa28fa5

Please sign in to comment.