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)]
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 #[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}