Repository: vercel/next.js
File: crates/next-core/src/next_server_component/server_component_transition.rs (Rust)

Code before:
        let process_result = context_without_transition
            .process(source, reference_type)
            .await?;

        match &*process_result {
            ProcessResult::Module(module) => {
                let Some(ecma_module) =
                    Vc::try_resolve_sidecast::<Box<dyn EcmascriptChunkPlaceable>>(**module).await?
                else {
                    bail!("not an ecmascript module");
                };

                // Create the server component module with the original source path
                let server_component =
                    NextServerComponentModule::new(ecma_module, (*source_path).clone());

                Ok(
                    ProcessResult::Module(ResolvedVc::upcast(
                        server_component.to_resolved().await?,
                    ))
                    .cell(),
                )
            }
            ProcessResult::Unknown(source) => Ok(ProcessResult::Unknown(*source).cell()),
            ProcessResult::Ignore => Ok(ProcessResult::Ignore.cell()),
        }
    }
}


Review comment (suggestion):
This can be simplified by reusing some of these functions
https://github.com/vercel/next.js/blob/9e933be762ada796e4d263739cda3360a3c38e91/turbopack/crates/turbopack/src/transition/mod.rs#L76-L127

```suggestion
        // Capture the original source path before any transformation
        let source_path = source.ident().path().await?.clone();

        let asset = self.process_source(asset);
        let module_asset_context = self.process_context(module_asset_context);
        let asset = asset.to_resolved().await?;

        Ok(match &*module_asset_context
            .process_default(asset, reference_type)
            .await?
            .await?
        {
            ProcessResult::Module(module) => {
                let Some(ecma_module) =
                    Vc::try_resolve_sidecast::<Box<dyn EcmascriptChunkPlaceable>>(**module).await?
                else {
                    bail!("not an ecmascript module");
                };

                // Create the server component module with the original source path
                let server_component =
                    NextServerComponentModule::new(ecma_module, (*source_path).clone());

                Ok(
                    ProcessResult::Module(ResolvedVc::upcast(
                        server_component.to_resolved().await?,
                    ))
                    .cell(),
                )
            }
            ProcessResult::Unknown(source) => Ok(ProcessResult::Unknown(*source).cell()),
            ProcessResult::Ignore => Ok(ProcessResult::Ignore.cell()),
        }
```

Code after:
use anyhow::{Result, bail};
use turbo_tasks::{ResolvedVc, Vc};
use turbopack::{ModuleAssetContext, transition::Transition};
use turbopack_core::{
    context::{AssetContext, ProcessResult},
    reference_type::ReferenceType,
    source::Source,
};
use turbopack_ecmascript::chunk::EcmascriptChunkPlaceable;

use super::server_component_module::NextServerComponentModule;

/// This transition wraps a module into a marker
/// [`Vc<NextServerComponentModule>`].
///
/// When walking the module graph to build the client reference manifest, this
/// is used to determine under which server component CSS client references are
/// required. Ultimately, this tells Next.js what CSS to inject into the page.
#[turbo_tasks::value(shared)]
pub struct NextServerComponentTransition {}

#[turbo_tasks::value_impl]
impl NextServerComponentTransition {
    /// Creates a new [`Vc<NextServerComponentTransition>`].
    #[turbo_tasks::function]
    pub fn new() -> Vc<Self> {
        NextServerComponentTransition {}.cell()
    }
}

#[turbo_tasks::value_impl]
impl Transition for NextServerComponentTransition {
    /// Override process to capture the original source path before transformation.
    /// This is important for MDX files where page.mdx becomes page.mdx.tsx after
    /// transformation, but we need the original path for manifest key generation.
    #[turbo_tasks::function]
    async fn process(
        self: Vc<Self>,
        source: Vc<Box<dyn Source>>,
        module_asset_context: Vc<ModuleAssetContext>,
        reference_type: ReferenceType,
    ) -> Result<Vc<ProcessResult>> {
        // Capture the original source path before any transformation
        let source_path = source.ident().path().owned().await?;

        let source = self.process_source(source);
        let module_asset_context = self.process_context(module_asset_context);

        Ok(
            match &*module_asset_context.process(source, reference_type).await? {
                ProcessResult::Module(module) => {
                    let Some(module) =
                        ResolvedVc::try_sidecast::<Box<dyn EcmascriptChunkPlaceable>>(*module)
                    else {
                        bail!("not an ecmascript module");
                    };

                    // Create the server component module with the original source path
                    let server_component = NextServerComponentModule::new(*module, source_path);

                    ProcessResult::Module(ResolvedVc::upcast(server_component.to_resolved().await?))
                        .cell()
                }
                ProcessResult::Unknown(source) => ProcessResult::Unknown(*source).cell(),
                ProcessResult::Ignore => ProcessResult::Ignore.cell(),
            },
        )
    }
}