turbopack_static/
ecma.rs

1use anyhow::Result;
2use turbo_rcstr::{RcStr, rcstr};
3use turbo_tasks::{ResolvedVc, Vc};
4use turbopack_core::{
5    asset::{Asset, AssetContent},
6    chunk::{ChunkItem, ChunkType, ChunkableModule, ChunkingContext},
7    ident::AssetIdent,
8    module::Module,
9    module_graph::ModuleGraph,
10    output::{OutputAsset, OutputAssets},
11    source::Source,
12};
13use turbopack_ecmascript::{
14    chunk::{
15        EcmascriptChunkItem, EcmascriptChunkItemContent, EcmascriptChunkPlaceable,
16        EcmascriptChunkType, EcmascriptExports,
17    },
18    runtime_functions::TURBOPACK_EXPORT_VALUE,
19    utils::StringifyJs,
20};
21
22use crate::output_asset::StaticOutputAsset;
23
24#[turbo_tasks::value]
25#[derive(Clone)]
26pub struct StaticUrlJsModule {
27    pub source: ResolvedVc<Box<dyn Source>>,
28    pub tag: Option<RcStr>,
29}
30
31#[turbo_tasks::value_impl]
32impl StaticUrlJsModule {
33    #[turbo_tasks::function]
34    pub fn new(source: ResolvedVc<Box<dyn Source>>, tag: Option<RcStr>) -> Vc<Self> {
35        Self::cell(StaticUrlJsModule { source, tag })
36    }
37
38    #[turbo_tasks::function]
39    fn static_output_asset(
40        &self,
41        chunking_context: ResolvedVc<Box<dyn ChunkingContext>>,
42    ) -> Vc<StaticOutputAsset> {
43        StaticOutputAsset::new(*chunking_context, *self.source, self.tag.clone())
44    }
45}
46
47#[turbo_tasks::value_impl]
48impl Module for StaticUrlJsModule {
49    #[turbo_tasks::function]
50    fn ident(&self) -> Vc<AssetIdent> {
51        let mut ident = self
52            .source
53            .ident()
54            .with_modifier(rcstr!("static in ecmascript"));
55        if let Some(tag) = &self.tag {
56            ident = ident.with_modifier(format!("tag {}", tag).into());
57        }
58        ident
59    }
60}
61
62#[turbo_tasks::value_impl]
63impl Asset for StaticUrlJsModule {
64    #[turbo_tasks::function]
65    fn content(&self) -> Vc<AssetContent> {
66        self.source.content()
67    }
68}
69
70#[turbo_tasks::value_impl]
71impl ChunkableModule for StaticUrlJsModule {
72    #[turbo_tasks::function]
73    async fn as_chunk_item(
74        self: ResolvedVc<Self>,
75        _module_graph: Vc<ModuleGraph>,
76        chunking_context: ResolvedVc<Box<dyn ChunkingContext>>,
77    ) -> Result<Vc<Box<dyn turbopack_core::chunk::ChunkItem>>> {
78        Ok(Vc::upcast(StaticUrlJsChunkItem::cell(
79            StaticUrlJsChunkItem {
80                module: self,
81                chunking_context,
82                static_asset: self
83                    .static_output_asset(*chunking_context)
84                    .to_resolved()
85                    .await?,
86                tag: self.await?.tag.clone(),
87            },
88        )))
89    }
90}
91
92#[turbo_tasks::value_impl]
93impl EcmascriptChunkPlaceable for StaticUrlJsModule {
94    #[turbo_tasks::function]
95    fn get_exports(&self) -> Vc<EcmascriptExports> {
96        EcmascriptExports::Value.into()
97    }
98}
99
100#[turbo_tasks::value]
101struct StaticUrlJsChunkItem {
102    module: ResolvedVc<StaticUrlJsModule>,
103    chunking_context: ResolvedVc<Box<dyn ChunkingContext>>,
104    static_asset: ResolvedVc<StaticOutputAsset>,
105    tag: Option<RcStr>,
106}
107
108#[turbo_tasks::value_impl]
109impl ChunkItem for StaticUrlJsChunkItem {
110    #[turbo_tasks::function]
111    fn asset_ident(&self) -> Vc<AssetIdent> {
112        self.module.ident()
113    }
114
115    #[turbo_tasks::function]
116    fn references(&self) -> Vc<OutputAssets> {
117        Vc::cell(vec![ResolvedVc::upcast(self.static_asset)])
118    }
119
120    #[turbo_tasks::function]
121    fn chunking_context(&self) -> Vc<Box<dyn ChunkingContext>> {
122        *self.chunking_context
123    }
124
125    #[turbo_tasks::function]
126    async fn ty(&self) -> Result<Vc<Box<dyn ChunkType>>> {
127        Ok(Vc::upcast(
128            Vc::<EcmascriptChunkType>::default().resolve().await?,
129        ))
130    }
131
132    #[turbo_tasks::function]
133    fn module(&self) -> Vc<Box<dyn Module>> {
134        *ResolvedVc::upcast(self.module)
135    }
136}
137
138#[turbo_tasks::value_impl]
139impl EcmascriptChunkItem for StaticUrlJsChunkItem {
140    #[turbo_tasks::function]
141    async fn content(&self) -> Result<Vc<EcmascriptChunkItemContent>> {
142        Ok(EcmascriptChunkItemContent {
143            inner_code: format!(
144                "{TURBOPACK_EXPORT_VALUE}({path});",
145                path = StringifyJs(
146                    &self
147                        .chunking_context
148                        .asset_url(self.static_asset.path().owned().await?, self.tag.clone())
149                        .await?
150                )
151            )
152            .into(),
153            ..Default::default()
154        }
155        .into())
156    }
157}