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 fn server_path(&self) -> Vc<FileSystemPath> {
40        self.module.ident().path()
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    fn ident(&self) -> Vc<AssetIdent> {
58        self.module
59            .ident()
60            .with_modifier(rcstr!("Next.js server utility"))
61    }
62
63    #[turbo_tasks::function]
64    fn source(&self) -> Vc<OptionSource> {
65        Vc::cell(None)
66    }
67
68    #[turbo_tasks::function]
69    async fn references(&self) -> Result<Vc<ModuleReferences>> {
70        Ok(Vc::cell(vec![self.module_reference().await?]))
71    }
72
73    #[turbo_tasks::function]
74    fn side_effects(self: Vc<Self>) -> Vc<ModuleSideEffects> {
75        // This just exports another import
76        ModuleSideEffects::ModuleEvaluationIsSideEffectFree.cell()
77    }
78}
79
80#[turbo_tasks::value_impl]
81impl ChunkableModule for NextServerUtilityModule {
82    #[turbo_tasks::function]
83    fn as_chunk_item(
84        self: ResolvedVc<Self>,
85        module_graph: ResolvedVc<ModuleGraph>,
86        chunking_context: ResolvedVc<Box<dyn ChunkingContext>>,
87    ) -> Vc<Box<dyn turbopack_core::chunk::ChunkItem>> {
88        ecmascript_chunk_item(ResolvedVc::upcast(self), module_graph, chunking_context)
89    }
90}
91
92#[turbo_tasks::value_impl]
93impl EcmascriptChunkPlaceable for NextServerUtilityModule {
94    #[turbo_tasks::function]
95    fn get_exports(&self) -> Vc<EcmascriptExports> {
96        let module_reference: Vc<Box<dyn ModuleReference>> = Vc::upcast(
97            NextServerUtilityModuleReference::new(Vc::upcast(*self.module)),
98        );
99        EsmExports::reexport_including_default(module_reference)
100    }
101
102    #[turbo_tasks::function]
103    async fn chunk_item_content(
104        &self,
105        chunking_context: Vc<Box<dyn ChunkingContext>>,
106        _module_graph: Vc<ModuleGraph>,
107        _async_module_info: Option<Vc<AsyncModuleInfo>>,
108        _estimated: bool,
109    ) -> Result<Vc<EcmascriptChunkItemContent>> {
110        let module_id = self.module.chunk_item_id(chunking_context).await?;
111        Ok(EcmascriptChunkItemContent {
112            inner_code: formatdoc!(
113                r#"
114                    {TURBOPACK_EXPORT_NAMESPACE}({TURBOPACK_IMPORT}({}));
115                "#,
116                StringifyJs(&module_id),
117            )
118            .into(),
119            ..Default::default()
120        }
121        .cell())
122    }
123}