Skip to main content

turbopack_browser/ecmascript/
chunk.rs

1use anyhow::Result;
2use turbo_rcstr::{RcStr, rcstr};
3use turbo_tasks::{FxIndexSet, ResolvedVc, ValueToString, Vc};
4use turbo_tasks_fs::{FileContent, FileSystemPath};
5use turbopack_core::{
6    asset::{Asset, AssetContent},
7    chunk::{Chunk, ChunkingContext, OutputChunk, OutputChunkRuntimeInfo},
8    ident::AssetIdent,
9    introspect::{Introspectable, IntrospectableChildren},
10    output::{OutputAsset, OutputAssetsReference, OutputAssetsWithReferenced},
11    source_map::{GenerateSourceMap, SourceMapAsset},
12    version::VersionedContent,
13};
14use turbopack_ecmascript::chunk::EcmascriptChunk;
15
16use crate::{BrowserChunkingContext, ecmascript::content::EcmascriptBrowserChunkContent};
17
18/// Development Ecmascript chunk.
19#[turbo_tasks::value(shared)]
20#[derive(ValueToString)]
21#[value_to_string("Ecmascript Dev Chunk")]
22pub struct EcmascriptBrowserChunk {
23    chunking_context: ResolvedVc<BrowserChunkingContext>,
24    chunk: ResolvedVc<EcmascriptChunk>,
25}
26
27#[turbo_tasks::value_impl]
28impl EcmascriptBrowserChunk {
29    /// Creates a new [`Vc<EcmascriptDevChunk>`].
30    #[turbo_tasks::function]
31    pub fn new(
32        chunking_context: ResolvedVc<BrowserChunkingContext>,
33        chunk: ResolvedVc<EcmascriptChunk>,
34    ) -> Vc<Self> {
35        EcmascriptBrowserChunk {
36            chunking_context,
37            chunk,
38        }
39        .cell()
40    }
41
42    #[turbo_tasks::function]
43    async fn source_map(self: Vc<Self>) -> Result<Vc<SourceMapAsset>> {
44        let this = self.await?;
45        Ok(SourceMapAsset::new(
46            Vc::upcast(*this.chunking_context),
47            this.ident_for_path(),
48            Vc::upcast(self),
49        ))
50    }
51}
52
53impl EcmascriptBrowserChunk {
54    fn ident_for_path(&self) -> Vc<AssetIdent> {
55        self.chunk
56            .ident()
57            .with_modifier(rcstr!("ecmascript dev chunk"))
58    }
59}
60
61#[turbo_tasks::value_impl]
62impl OutputChunk for EcmascriptBrowserChunk {
63    #[turbo_tasks::function]
64    async fn runtime_info(&self) -> Result<Vc<OutputChunkRuntimeInfo>> {
65        Ok(OutputChunkRuntimeInfo {
66            included_ids: Some(self.chunk.entry_ids().to_resolved().await?),
67            ..Default::default()
68        }
69        .cell())
70    }
71}
72
73#[turbo_tasks::value_impl]
74impl EcmascriptBrowserChunk {
75    #[turbo_tasks::function]
76    async fn own_content(self: Vc<Self>) -> Result<Vc<EcmascriptBrowserChunkContent>> {
77        let this = self.await?;
78        Ok(EcmascriptBrowserChunkContent::new(
79            *this.chunking_context,
80            self,
81            this.chunk.chunk_content(),
82            self.source_map(),
83        ))
84    }
85
86    #[turbo_tasks::function]
87    pub fn chunk(&self) -> Result<Vc<Box<dyn Chunk>>> {
88        Ok(Vc::upcast(*self.chunk))
89    }
90}
91
92#[turbo_tasks::value_impl]
93impl OutputAssetsReference for EcmascriptBrowserChunk {
94    #[turbo_tasks::function]
95    async fn references(self: Vc<Self>) -> Result<Vc<OutputAssetsWithReferenced>> {
96        let this = self.await?;
97        let chunk_references = this.chunk.references().await?;
98        let include_source_map = *this
99            .chunking_context
100            .reference_chunk_source_maps(Vc::upcast(self))
101            .await?;
102        let ref_assets = chunk_references.assets.await?;
103        let mut assets =
104            Vec::with_capacity(ref_assets.len() + if include_source_map { 1 } else { 0 });
105
106        assets.extend(ref_assets.iter().copied());
107
108        if include_source_map {
109            assets.push(ResolvedVc::upcast(self.source_map().to_resolved().await?));
110        }
111
112        Ok(OutputAssetsWithReferenced {
113            assets: ResolvedVc::cell(assets),
114            referenced_assets: chunk_references.referenced_assets,
115            references: chunk_references.references,
116        }
117        .cell())
118    }
119}
120
121#[turbo_tasks::value_impl]
122impl OutputAsset for EcmascriptBrowserChunk {
123    #[turbo_tasks::function]
124    async fn path(self: Vc<Self>) -> Result<Vc<FileSystemPath>> {
125        let this = self.await?;
126        let ident = this.ident_for_path();
127        Ok(this
128            .chunking_context
129            .chunk_path(Some(Vc::upcast(self)), ident, None, rcstr!(".js")))
130    }
131
132    #[turbo_tasks::function]
133    fn size_bytes(self: Vc<Self>) -> Vc<Option<u64>> {
134        self.own_content().content().len()
135    }
136}
137
138#[turbo_tasks::value_impl]
139impl Asset for EcmascriptBrowserChunk {
140    #[turbo_tasks::function]
141    fn content(self: Vc<Self>) -> Vc<AssetContent> {
142        self.own_content().content()
143    }
144
145    #[turbo_tasks::function]
146    fn versioned_content(self: Vc<Self>) -> Vc<Box<dyn VersionedContent>> {
147        Vc::upcast(self.own_content())
148    }
149}
150
151#[turbo_tasks::value_impl]
152impl GenerateSourceMap for EcmascriptBrowserChunk {
153    #[turbo_tasks::function]
154    fn generate_source_map(self: Vc<Self>) -> Vc<FileContent> {
155        self.own_content().generate_source_map()
156    }
157
158    #[turbo_tasks::function]
159    fn by_section(self: Vc<Self>, section: RcStr) -> Vc<FileContent> {
160        self.own_content().by_section(section)
161    }
162}
163
164#[turbo_tasks::value_impl]
165impl Introspectable for EcmascriptBrowserChunk {
166    #[turbo_tasks::function]
167    fn ty(&self) -> Vc<RcStr> {
168        Vc::cell(rcstr!("dev ecmascript chunk"))
169    }
170
171    #[turbo_tasks::function]
172    fn title(self: Vc<Self>) -> Vc<RcStr> {
173        self.path().to_string()
174    }
175
176    #[turbo_tasks::function]
177    fn details(&self) -> Vc<RcStr> {
178        Vc::cell(rcstr!("generates a development ecmascript chunk"))
179    }
180
181    #[turbo_tasks::function]
182    fn children(&self) -> Result<Vc<IntrospectableChildren>> {
183        let mut children = FxIndexSet::default();
184        let chunk = ResolvedVc::upcast::<Box<dyn Introspectable>>(self.chunk);
185        children.insert((rcstr!("chunk"), chunk));
186        Ok(Vc::cell(children))
187    }
188}