turbopack_core/source_map/
source_map_asset.rs1use anyhow::Result;
2use bincode::{Decode, Encode};
3use turbo_rcstr::{RcStr, rcstr};
4use turbo_tasks::{
5 FxIndexSet, NonLocalValue, ResolvedVc, ValueToString, Vc, debug::ValueDebugFormat,
6 trace::TraceRawVcs,
7};
8use turbo_tasks_fs::{File, FileContent, FileSystemPath};
9
10use crate::{
11 asset::{Asset, AssetContent},
12 chunk::ChunkingContext,
13 ident::AssetIdent,
14 introspect::{Introspectable, IntrospectableChildren},
15 output::{OutputAsset, OutputAssetsReference},
16 source_map::{GenerateSourceMap, SourceMap},
17};
18
19#[derive(PartialEq, Eq, NonLocalValue, TraceRawVcs, ValueDebugFormat, Encode, Decode)]
20enum PathType {
21 Fixed {
22 path: FileSystemPath,
23 },
24 FromIdent {
25 chunking_context: ResolvedVc<Box<dyn ChunkingContext>>,
26 ident_for_path: ResolvedVc<AssetIdent>,
27 },
28}
29
30#[turbo_tasks::value]
32pub struct SourceMapAsset {
33 path_ty: PathType,
34 generate_source_map: ResolvedVc<Box<dyn GenerateSourceMap>>,
35}
36
37#[turbo_tasks::value_impl]
38impl SourceMapAsset {
39 #[turbo_tasks::function]
40 pub fn new(
41 chunking_context: ResolvedVc<Box<dyn ChunkingContext>>,
42 ident_for_path: ResolvedVc<AssetIdent>,
43 generate_source_map: ResolvedVc<Box<dyn GenerateSourceMap>>,
44 ) -> Vc<Self> {
45 SourceMapAsset {
46 path_ty: PathType::FromIdent {
47 chunking_context,
48 ident_for_path,
49 },
50 generate_source_map,
51 }
52 .cell()
53 }
54
55 #[turbo_tasks::function]
56 pub fn new_fixed(
57 path: FileSystemPath,
58 generate_source_map: ResolvedVc<Box<dyn GenerateSourceMap>>,
59 ) -> Vc<Self> {
60 SourceMapAsset {
61 path_ty: PathType::Fixed { path },
62 generate_source_map,
63 }
64 .cell()
65 }
66}
67
68#[turbo_tasks::value_impl]
69impl OutputAssetsReference for SourceMapAsset {}
70
71#[turbo_tasks::value_impl]
72impl OutputAsset for SourceMapAsset {
73 #[turbo_tasks::function]
74 async fn path(self: Vc<Self>) -> Result<Vc<FileSystemPath>> {
75 let this = self.await?;
78 Ok(match &this.path_ty {
79 PathType::FromIdent {
80 chunking_context,
81 ident_for_path,
82 } => chunking_context
83 .chunk_path(
84 Some(Vc::upcast(self)),
85 **ident_for_path,
86 None,
87 rcstr!(".js"),
88 )
89 .await?
90 .append(".map")?
91 .cell(),
92 PathType::Fixed { path } => path.append(".map")?.cell(),
93 })
94 }
95}
96
97#[turbo_tasks::value_impl]
98impl Asset for SourceMapAsset {
99 #[turbo_tasks::function]
100 async fn content(&self) -> Result<Vc<AssetContent>> {
101 let content = self.generate_source_map.generate_source_map();
102 if content.await?.is_content() {
103 Ok(AssetContent::file(content))
104 } else {
105 Ok(AssetContent::file(
106 FileContent::Content(File::from(SourceMap::empty_rope())).cell(),
107 ))
108 }
109 }
110}
111
112#[turbo_tasks::value_impl]
113impl Introspectable for SourceMapAsset {
114 #[turbo_tasks::function]
115 fn ty(&self) -> Vc<RcStr> {
116 Vc::cell(rcstr!("source map"))
117 }
118
119 #[turbo_tasks::function]
120 fn title(self: Vc<Self>) -> Vc<RcStr> {
121 self.path().to_string()
122 }
123
124 #[turbo_tasks::function]
125 fn details(&self) -> Vc<RcStr> {
126 Vc::cell(rcstr!("source map of an asset"))
127 }
128
129 #[turbo_tasks::function]
130 fn children(&self) -> Result<Vc<IntrospectableChildren>> {
131 let mut children = FxIndexSet::default();
132 if let Some(asset) =
133 ResolvedVc::try_sidecast::<Box<dyn Introspectable>>(self.generate_source_map)
134 {
135 children.insert((rcstr!("asset"), asset));
136 }
137 Ok(Vc::cell(children))
138 }
139}