Repository: vercel/next.js
Pull request: Turbopack: more module ident collisions

Fixes two more module ident collisions

1. `ContextTransition` is a massive footgun, because it reuses the transitions from the parent context. So it essentially always creates a new context (which is not actually what we want), e.g. here this created two different `app-edge-shared` contexts because `app-edge-rsc` and `app-edge-ssr` have different transitions.
I hope this wasn't by design?

```
next/dist/esm/server/app-render/after-task-async-storage.external.js [app-edge-rsc]
->
next/dist/esm/server/app-render/after-task-async-storage-instance.js [app-edge-shared]


next/dist/esm/server/app-render/after-task-async-storage.external.js [app-edge-ssr]
-> 
next/dist/esm/server/app-render/after-task-async-storage-instance.js [app-edge-shared]
```


2. The client module proxy module was missing its layer in the identifier (the layer of the proxy module, i.e. `app-edge-rsc` or `app-rsc`). It's correct that there are two different modules.

Closes PACK-4373

Changed files:
filename: crates/next-api/src/app.rs
patch: @@ -47,7 +47,7 @@ use turbo_tasks_fs::{File, FileContent, FileSystemPath};
 use turbopack::{
     module_options::{transition_rule::TransitionRule, ModuleOptionsContext, RuleCondition},
     resolve_options_context::ResolveOptionsContext,
-    transition::{ContextTransition, FullContextTransition, Transition, TransitionOptions},
+    transition::{FullContextTransition, Transition, TransitionOptions},
     ModuleAssetContext,
 };
 use turbopack_core::{
@@ -663,13 +663,22 @@ impl AppProject {
     }
 
     #[turbo_tasks::function]
-    fn shared_transition(self: Vc<Self>) -> Vc<ContextTransition> {
-        ContextTransition::new(
+    async fn shared_module_context(self: Vc<Self>) -> Result<Vc<ModuleAssetContext>> {
+        Ok(ModuleAssetContext::new(
+            TransitionOptions {
+                ..Default::default()
+            }
+            .cell(),
             self.project().server_compile_time_info(),
             self.ssr_module_options_context(),
             self.ssr_resolve_options_context(),
             Vc::cell("app-shared".into()),
-        )
+        ))
+    }
+
+    #[turbo_tasks::function]
+    fn shared_transition(self: Vc<Self>) -> Vc<Box<dyn Transition>> {
+        Vc::upcast(FullContextTransition::new(self.shared_module_context()))
     }
 
     #[turbo_tasks::function]
@@ -714,13 +723,24 @@ impl AppProject {
     }
 
     #[turbo_tasks::function]
-    fn edge_shared_transition(self: Vc<Self>) -> Vc<ContextTransition> {
-        ContextTransition::new(
+    async fn edge_shared_module_context(self: Vc<Self>) -> Result<Vc<ModuleAssetContext>> {
+        Ok(ModuleAssetContext::new(
+            TransitionOptions {
+                ..Default::default()
+            }
+            .cell(),
             self.project().edge_compile_time_info(),
             self.edge_ssr_module_options_context(),
             self.edge_ssr_resolve_options_context(),
             Vc::cell("app-edge-shared".into()),
-        )
+        ))
+    }
+
+    #[turbo_tasks::function]
+    fn edge_shared_transition(self: Vc<Self>) -> Vc<Box<dyn Transition>> {
+        Vc::upcast(FullContextTransition::new(
+            self.edge_shared_module_context(),
+        ))
     }
 
     #[turbo_tasks::function]

filename: crates/next-api/src/pages.rs
patch: @@ -39,7 +39,7 @@ use turbo_tasks_fs::{
 use turbopack::{
     module_options::ModuleOptionsContext,
     resolve_options_context::ResolveOptionsContext,
-    transition::{ContextTransition, TransitionOptions},
+    transition::{FullContextTransition, Transition, TransitionOptions},
     ModuleAssetContext,
 };
 use turbopack_core::{
@@ -290,7 +290,27 @@ impl PagesProject {
     }
 
     #[turbo_tasks::function]
-    async fn transitions(self: Vc<Self>) -> Result<Vc<TransitionOptions>> {
+    async fn client_transitions(self: Vc<Self>) -> Result<Vc<TransitionOptions>> {
+        Ok(TransitionOptions {
+            named_transitions: [
+                (
+                    "next-dynamic".into(),
+                    ResolvedVc::upcast(NextDynamicTransition::new_marker().to_resolved().await?),
+                ),
+                (
+                    "next-dynamic-client".into(),
+                    ResolvedVc::upcast(NextDynamicTransition::new_marker().to_resolved().await?),
+                ),
+            ]
+            .into_iter()
+            .collect(),
+            ..Default::default()
+        }
+        .cell())
+    }
+
+    #[turbo_tasks::function]
+    async fn server_transitions(self: Vc<Self>) -> Result<Vc<TransitionOptions>> {
         Ok(TransitionOptions {
             named_transitions: [
                 (
@@ -314,13 +334,8 @@ impl PagesProject {
     }
 
     #[turbo_tasks::function]
-    fn client_transition(self: Vc<Self>) -> Vc<ContextTransition> {
-        ContextTransition::new(
-            self.project().client_compile_time_info(),
-            self.client_module_options_context(),
-            self.client_resolve_options_context(),
-            client_layer(),
-        )
+    fn client_transition(self: Vc<Self>) -> Vc<Box<dyn Transition>> {
+        Vc::upcast(FullContextTransition::new(self.client_module_context()))
     }
 
     #[turbo_tasks::function]
@@ -353,20 +368,20 @@ impl PagesProject {
     }
 
     #[turbo_tasks::function]
-    pub(super) fn client_module_context(self: Vc<Self>) -> Vc<Box<dyn AssetContext>> {
-        Vc::upcast(ModuleAssetContext::new(
-            self.transitions(),
+    pub(super) fn client_module_context(self: Vc<Self>) -> Vc<ModuleAssetContext> {
+        ModuleAssetContext::new(
+            self.client_transitions(),
             self.project().client_compile_time_info(),
             self.client_module_options_context(),
             self.client_resolve_options_context(),
             client_layer(),
-        ))
+        )
     }
 
     #[turbo_tasks::function]
     pub(super) fn ssr_module_context(self: Vc<Self>) -> Vc<ModuleAssetContext> {
         ModuleAssetContext::new(
-            self.transitions(),
+            self.server_transitions(),
             self.project().server_compile_time_info(),
             self.ssr_module_options_context(),
             self.ssr_resolve_options_context(),
@@ -379,7 +394,7 @@ impl PagesProject {
     #[turbo_tasks::function]
     pub(super) fn api_module_context(self: Vc<Self>) -> Vc<ModuleAssetContext> {
         ModuleAssetContext::new(
-            self.transitions(),
+            self.server_transitions(),
             self.project().server_compile_time_info(),
             self.api_module_options_context(),
             self.ssr_resolve_options_context(),
@@ -390,7 +405,7 @@ impl PagesProject {
     #[turbo_tasks::function]
     pub(super) fn ssr_data_module_context(self: Vc<Self>) -> Vc<ModuleAssetContext> {
         ModuleAssetContext::new(
-            self.transitions(),
+            self.server_transitions(),
             self.project().server_compile_time_info(),
             self.ssr_data_module_options_context(),
             self.ssr_resolve_options_context(),
@@ -566,7 +581,7 @@ impl PagesProject {
             self.project().next_config(),
             self.project().execution_context(),
         );
-        Ok(client_runtime_entries.resolve_entries(self.client_module_context()))
+        Ok(client_runtime_entries.resolve_entries(Vc::upcast(self.client_module_context())))
     }
 
     #[turbo_tasks::function]
@@ -615,7 +630,7 @@ impl PagesProject {
 
     #[turbo_tasks::function]
     pub async fn client_main_module(self: Vc<Self>) -> Result<Vc<Box<dyn Module>>> {
-        let client_module_context = self.client_module_context();
+        let client_module_context = Vc::upcast(self.client_module_context());
 
         let client_main_module = esm_resolve(
             Vc::upcast(PlainResolveOrigin::new(
@@ -722,7 +737,7 @@ impl PageEndpoint {
     async fn client_module(self: Vc<Self>) -> Result<Vc<Box<dyn Module>>> {
         let this = self.await?;
         let page_loader = create_page_loader_entry_module(
-            this.pages_project.client_module_context(),
+            Vc::upcast(this.pages_project.client_module_context()),
             self.source(),
             *this.pathname,
         );

filename: crates/next-core/src/next_client_reference/ecmascript_client_reference/ecmascript_client_reference_module.rs
patch: @@ -179,7 +179,7 @@ impl EcmascriptClientReferenceModule {
 
 #[turbo_tasks::function]
 fn client_reference_modifier() -> Vc<RcStr> {
-    Vc::cell("client reference/proxy".into())
+    Vc::cell("client reference proxy".into())
 }
 
 #[turbo_tasks::function]
@@ -200,7 +200,9 @@ pub static ECMASCRIPT_CLIENT_REFERENCE_MERGE_TAG_SSR: Lazy<RcStr> = Lazy::new(||
 impl Module for EcmascriptClientReferenceModule {
     #[turbo_tasks::function]
     fn ident(&self) -> Vc<AssetIdent> {
-        self.server_ident.with_modifier(client_reference_modifier())
+        self.server_ident
+            .with_modifier(client_reference_modifier())
+            .with_layer(self.server_asset_context.layer())
     }
 
     #[turbo_tasks::function]

filename: turbopack/crates/turbopack/src/transition/context_transition.rs
patch: @@ -1,66 +0,0 @@
-use turbo_rcstr::RcStr;
-use turbo_tasks::{ResolvedVc, Vc};
-use turbopack_core::compile_time_info::CompileTimeInfo;
-use turbopack_resolve::resolve_options_context::ResolveOptionsContext;
-
-use crate::{module_options::ModuleOptionsContext, transition::Transition};
-
-/// A transition that only affects the asset context.
-#[turbo_tasks::value(shared)]
-pub struct ContextTransition {
-    compile_time_info: ResolvedVc<CompileTimeInfo>,
-    module_options_context: ResolvedVc<ModuleOptionsContext>,
-    resolve_options_context: ResolvedVc<ResolveOptionsContext>,
-    layer: ResolvedVc<RcStr>,
-}
-
-#[turbo_tasks::value_impl]
-impl ContextTransition {
-    #[turbo_tasks::function]
-    pub fn new(
-        compile_time_info: ResolvedVc<CompileTimeInfo>,
-        module_options_context: ResolvedVc<ModuleOptionsContext>,
-        resolve_options_context: ResolvedVc<ResolveOptionsContext>,
-        layer: ResolvedVc<RcStr>,
-    ) -> Vc<ContextTransition> {
-        ContextTransition {
-            module_options_context,
-            resolve_options_context,
-            compile_time_info,
-            layer,
-        }
-        .cell()
-    }
-}
-
-#[turbo_tasks::value_impl]
-impl Transition for ContextTransition {
-    #[turbo_tasks::function]
-    fn process_compile_time_info(
-        &self,
-        _compile_time_info: Vc<CompileTimeInfo>,
-    ) -> Vc<CompileTimeInfo> {
-        *self.compile_time_info
-    }
-
-    #[turbo_tasks::function]
-    fn process_layer(&self, _layer: Vc<RcStr>) -> Vc<RcStr> {
-        *self.layer
-    }
-
-    #[turbo_tasks::function]
-    fn process_module_options_context(
-        &self,
-        _context: Vc<ModuleOptionsContext>,
-    ) -> Vc<ModuleOptionsContext> {
-        *self.module_options_context
-    }
-
-    #[turbo_tasks::function]
-    fn process_resolve_options_context(
-        &self,
-        _context: Vc<ResolveOptionsContext>,
-    ) -> Vc<ResolveOptionsContext> {
-        *self.resolve_options_context
-    }
-}

filename: turbopack/crates/turbopack/src/transition/mod.rs
patch: @@ -1,8 +1,6 @@
-pub(crate) mod context_transition;
 pub(crate) mod full_context_transition;
 
 use anyhow::Result;
-pub use context_transition::ContextTransition;
 pub use full_context_transition::FullContextTransition;
 use rustc_hash::FxHashMap;
 use turbo_rcstr::RcStr;
@@ -57,6 +55,14 @@ pub trait Transition {
         resolve_options_context
     }
 
+    /// Apply modifications/wrapping to the transition options
+    fn process_transition_options(
+        self: Vc<Self>,
+        transition_options: Vc<TransitionOptions>,
+    ) -> Vc<TransitionOptions> {
+        transition_options
+    }
+
     /// Apply modifications/wrapping to the final asset
     fn process_module(
         self: Vc<Self>,
@@ -79,8 +85,9 @@ pub trait Transition {
         let resolve_options_context =
             self.process_resolve_options_context(*module_asset_context.resolve_options_context);
         let layer = self.process_layer(*module_asset_context.layer);
+        let transition_options = self.process_transition_options(*module_asset_context.transitions);
         let module_asset_context = ModuleAssetContext::new(
-            *module_asset_context.transitions,
+            transition_options,
             compile_time_info,
             module_options_context,
             resolve_options_context,