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