next_core/next_dynamic/
dynamic_module.rs1use anyhow::Result;
2use indoc::formatdoc;
3use turbo_rcstr::rcstr;
4use turbo_tasks::{ResolvedVc, Vc};
5use turbopack_core::{
6 chunk::{AsyncModuleInfo, ChunkableModule, ChunkingContext, ModuleChunkItemIdExt},
7 ident::AssetIdent,
8 module::{Module, ModuleSideEffects},
9 module_graph::ModuleGraph,
10 reference::{ModuleReference, ModuleReferences, SingleChunkableModuleReference},
11 resolve::ExportUsage,
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
24#[turbo_tasks::value(shared)]
27pub struct NextDynamicEntryModule {
28 module: ResolvedVc<Box<dyn EcmascriptChunkPlaceable>>,
29}
30
31#[turbo_tasks::value_impl]
32impl NextDynamicEntryModule {
33 #[turbo_tasks::function]
34 pub fn new(module: ResolvedVc<Box<dyn EcmascriptChunkPlaceable>>) -> Vc<Self> {
35 NextDynamicEntryModule { module }.cell()
36 }
37}
38
39impl NextDynamicEntryModule {
40 fn module_reference(&self) -> Vc<Box<dyn ModuleReference>> {
41 Vc::upcast(SingleChunkableModuleReference::new(
42 Vc::upcast(*self.module),
43 rcstr!("next/dynamic reference"),
44 ExportUsage::all(),
45 ))
46 }
47}
48
49#[turbo_tasks::value_impl]
50impl Module for NextDynamicEntryModule {
51 #[turbo_tasks::function]
52 async fn ident(&self) -> Result<Vc<AssetIdent>> {
53 Ok(self
54 .module
55 .ident()
56 .owned()
57 .await?
58 .with_modifier(rcstr!("next/dynamic entry"))
59 .into_vc())
60 }
61
62 #[turbo_tasks::function]
63 fn source(&self) -> Vc<OptionSource> {
64 Vc::cell(None)
65 }
66
67 #[turbo_tasks::function]
68 async fn references(&self) -> Result<Vc<ModuleReferences>> {
69 Ok(Vc::cell(vec![self.module_reference().to_resolved().await?]))
70 }
71
72 #[turbo_tasks::function]
73 fn side_effects(self: Vc<Self>) -> Vc<ModuleSideEffects> {
74 ModuleSideEffects::ModuleEvaluationIsSideEffectFree.cell()
76 }
77}
78
79#[turbo_tasks::value_impl]
80impl ChunkableModule for NextDynamicEntryModule {
81 #[turbo_tasks::function]
82 fn as_chunk_item(
83 self: ResolvedVc<Self>,
84 module_graph: ResolvedVc<ModuleGraph>,
85 chunking_context: ResolvedVc<Box<dyn ChunkingContext>>,
86 ) -> Vc<Box<dyn turbopack_core::chunk::ChunkItem>> {
87 ecmascript_chunk_item(ResolvedVc::upcast(self), module_graph, chunking_context)
88 }
89}
90
91#[turbo_tasks::value_impl]
92impl EcmascriptChunkPlaceable for NextDynamicEntryModule {
93 #[turbo_tasks::function]
94 fn get_exports(&self) -> Vc<EcmascriptExports> {
95 let module_reference = self.module_reference();
96 EsmExports::reexport_including_default(module_reference)
97 }
98
99 #[turbo_tasks::function]
100 async fn chunk_item_content(
101 &self,
102 chunking_context: Vc<Box<dyn ChunkingContext>>,
103 _module_graph: Vc<ModuleGraph>,
104 _async_module_info: Option<Vc<AsyncModuleInfo>>,
105 _estimated: bool,
106 ) -> Result<Vc<EcmascriptChunkItemContent>> {
107 let module_id = self.module.chunk_item_id(chunking_context).await?;
108 Ok(EcmascriptChunkItemContent {
109 inner_code: formatdoc!(
110 r#"
111 {TURBOPACK_EXPORT_NAMESPACE}({TURBOPACK_IMPORT}({}));
112 "#,
113 StringifyJs(&module_id),
114 )
115 .into(),
116 ..Default::default()
117 }
118 .cell())
119 }
120}