turbopack_core/source_map/
source_map_asset.rs1use anyhow::Result;
2use serde::{Deserialize, Serialize};
3use turbo_rcstr::RcStr;
4use turbo_tasks::{
5 FxIndexSet, NonLocalValue, ResolvedVc, ValueToString, Vc, debug::ValueDebugFormat,
6 trace::TraceRawVcs,
7};
8use turbo_tasks_fs::{File, FileSystemPath};
9
10use crate::{
11 asset::{Asset, AssetContent},
12 chunk::ChunkingContext,
13 ident::AssetIdent,
14 introspect::{Introspectable, IntrospectableChildren},
15 output::OutputAsset,
16 source_map::{GenerateSourceMap, SourceMap},
17};
18
19#[derive(PartialEq, Eq, Serialize, Deserialize, NonLocalValue, TraceRawVcs, ValueDebugFormat)]
20enum PathType {
21 Fixed {
22 path: ResolvedVc<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: ResolvedVc<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 OutputAsset for SourceMapAsset {
70 #[turbo_tasks::function]
71 async fn path(self: Vc<Self>) -> Result<Vc<FileSystemPath>> {
72 let this = self.await?;
75 Ok(match this.path_ty {
76 PathType::FromIdent {
77 chunking_context,
78 ident_for_path,
79 } => chunking_context
80 .chunk_path(Some(Vc::upcast(self)), *ident_for_path, ".js".into())
81 .append(".map".into()),
82 PathType::Fixed { path } => path.append(".map".into()),
83 })
84 }
85}
86
87#[turbo_tasks::value_impl]
88impl Asset for SourceMapAsset {
89 #[turbo_tasks::function]
90 async fn content(&self) -> Result<Vc<AssetContent>> {
91 if let Some(sm) = &*self.generate_source_map.generate_source_map().await? {
92 Ok(AssetContent::file(File::from(sm.clone()).into()))
93 } else {
94 Ok(AssetContent::file(
95 File::from(SourceMap::empty_rope()).into(),
96 ))
97 }
98 }
99}
100
101#[turbo_tasks::function]
102fn introspectable_type() -> Vc<RcStr> {
103 Vc::cell("source map".into())
104}
105
106#[turbo_tasks::function]
107fn introspectable_details() -> Vc<RcStr> {
108 Vc::cell("source map of an asset".into())
109}
110
111#[turbo_tasks::value_impl]
112impl Introspectable for SourceMapAsset {
113 #[turbo_tasks::function]
114 fn ty(&self) -> Vc<RcStr> {
115 introspectable_type()
116 }
117
118 #[turbo_tasks::function]
119 fn title(self: Vc<Self>) -> Vc<RcStr> {
120 self.path().to_string()
121 }
122
123 #[turbo_tasks::function]
124 fn details(&self) -> Vc<RcStr> {
125 introspectable_details()
126 }
127
128 #[turbo_tasks::function]
129 async fn children(&self) -> Result<Vc<IntrospectableChildren>> {
130 let mut children = FxIndexSet::default();
131 if let Some(asset) =
132 ResolvedVc::try_sidecast::<Box<dyn Introspectable>>(self.generate_source_map)
133 {
134 children.insert((ResolvedVc::cell("asset".into()), asset));
135 }
136 Ok(Vc::cell(children))
137 }
138}