Skip to main content

next_core/next_server_utility/
server_utility_module.rs

1use anyhow::Result;
2use indoc::formatdoc;
3use turbo_rcstr::rcstr;
4use turbo_tasks::{ResolvedVc, Vc};
5use turbo_tasks_fs::FileSystemPath;
6use turbopack_core::{
7    chunk::{AsyncModuleInfo, ChunkableModule, ChunkingContext, ModuleChunkItemIdExt},
8    ident::AssetIdent,
9    module::{Module, ModuleSideEffects},
10    module_graph::ModuleGraph,
11    reference::{ModuleReference, ModuleReferences},
12    source::OptionSource,
13};
14use turbopack_ecmascript::{
15    chunk::{
16        EcmascriptChunkItemContent, EcmascriptChunkPlaceable, EcmascriptExports,
17        ecmascript_chunk_item,
18    },
19    references::esm::EsmExports,
20    runtime_functions::{TURBOPACK_EXPORT_NAMESPACE, TURBOPACK_IMPORT},
21    utils::StringifyJs,
22};
23
24use super::server_utility_reference::NextServerUtilityModuleReference;
25
26#[turbo_tasks::value(shared)]
27pub struct NextServerUtilityModule {
28    pub module: ResolvedVc<Box<dyn EcmascriptChunkPlaceable>>,
29}
30
31#[turbo_tasks::value_impl]
32impl NextServerUtilityModule {
33    #[turbo_tasks::function]
34    pub fn new(module: ResolvedVc<Box<dyn EcmascriptChunkPlaceable>>) -> Vc<Self> {
35        NextServerUtilityModule { module }.cell()
36    }
37
38    #[turbo_tasks::function]
39    pub async fn server_path(&self) -> Result<Vc<FileSystemPath>> {
40        Ok(self.module.ident().await?.path.clone().cell())
41    }
42}
43
44impl NextServerUtilityModule {
45    async fn module_reference(&self) -> Result<ResolvedVc<Box<dyn ModuleReference>>> {
46        Ok(ResolvedVc::upcast(
47            NextServerUtilityModuleReference::new(Vc::upcast(*self.module))
48                .to_resolved()
49                .await?,
50        ))
51    }
52}
53
54#[turbo_tasks::value_impl]
55impl Module for NextServerUtilityModule {
56    #[turbo_tasks::function]
57    async fn ident(&self) -> Result<Vc<AssetIdent>> {
58        Ok(self
59            .module
60            .ident()
61            .owned()
62            .await?
63            .with_modifier(rcstr!("Next.js server utility"))
64            .into_vc())
65    }
66
67    #[turbo_tasks::function]
68    fn source(&self) -> Vc<OptionSource> {
69        Vc::cell(None)
70    }
71
72    #[turbo_tasks::function]
73    async fn references(&self) -> Result<Vc<ModuleReferences>> {
74        Ok(Vc::cell(vec![self.module_reference().await?]))
75    }
76
77    #[turbo_tasks::function]
78    fn side_effects(self: Vc<Self>) -> Vc<ModuleSideEffects> {
79        // This just exports another import
80        ModuleSideEffects::ModuleEvaluationIsSideEffectFree.cell()
81    }
82}
83
84#[turbo_tasks::value_impl]
85impl ChunkableModule for NextServerUtilityModule {
86    #[turbo_tasks::function]
87    fn as_chunk_item(
88        self: ResolvedVc<Self>,
89        module_graph: ResolvedVc<ModuleGraph>,
90        chunking_context: ResolvedVc<Box<dyn ChunkingContext>>,
91    ) -> Vc<Box<dyn turbopack_core::chunk::ChunkItem>> {
92        ecmascript_chunk_item(ResolvedVc::upcast(self), module_graph, chunking_context)
93    }
94}
95
96#[turbo_tasks::value_impl]
97impl EcmascriptChunkPlaceable for NextServerUtilityModule {
98    #[turbo_tasks::function]
99    fn get_exports(&self) -> Vc<EcmascriptExports> {
100        let module_reference: Vc<Box<dyn ModuleReference>> = Vc::upcast(
101            NextServerUtilityModuleReference::new(Vc::upcast(*self.module)),
102        );
103        EsmExports::reexport_including_default(module_reference)
104    }
105
106    #[turbo_tasks::function]
107    async fn chunk_item_content(
108        &self,
109        chunking_context: Vc<Box<dyn ChunkingContext>>,
110        _module_graph: Vc<ModuleGraph>,
111        _async_module_info: Option<Vc<AsyncModuleInfo>>,
112        _estimated: bool,
113    ) -> Result<Vc<EcmascriptChunkItemContent>> {
114        let module_id = self.module.chunk_item_id(chunking_context).await?;
115        Ok(EcmascriptChunkItemContent {
116            inner_code: formatdoc!(
117                r#"
118                    {TURBOPACK_EXPORT_NAMESPACE}({TURBOPACK_IMPORT}({}));
119                "#,
120                StringifyJs(&module_id),
121            )
122            .into(),
123            ..Default::default()
124        }
125        .cell())
126    }
127}