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