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