turbopack_ecmascript/references/
node.rs1use anyhow::Result;
2use tracing::Instrument;
3use turbo_rcstr::{RcStr, rcstr};
4use turbo_tasks::{ResolvedVc, ValueToString, Vc};
5use turbo_tasks_fs::FileSystemPath;
6use turbopack_core::{
7 chunk::{ChunkableModuleReference, ChunkingType, ChunkingTypeOption},
8 file_source::FileSource,
9 raw_module::RawModule,
10 reference::ModuleReference,
11 resolve::{
12 ModuleResolveResult, RequestKey,
13 pattern::{Pattern, PatternMatch, read_matches},
14 },
15 source::Source,
16};
17
18#[turbo_tasks::value]
19#[derive(Hash, Clone, Debug)]
20pub struct PackageJsonReference {
21 pub package_json: FileSystemPath,
22}
23
24#[turbo_tasks::value_impl]
25impl PackageJsonReference {
26 #[turbo_tasks::function]
27 pub fn new(package_json: FileSystemPath) -> Vc<Self> {
28 Self::cell(PackageJsonReference { package_json })
29 }
30}
31
32#[turbo_tasks::value_impl]
33impl ModuleReference for PackageJsonReference {
34 #[turbo_tasks::function]
35 async fn resolve_reference(&self) -> Result<Vc<ModuleResolveResult>> {
36 Ok(*ModuleResolveResult::module(ResolvedVc::upcast(
37 RawModule::new(Vc::upcast(FileSource::new(self.package_json.clone())))
38 .to_resolved()
39 .await?,
40 )))
41 }
42}
43
44#[turbo_tasks::value_impl]
45impl ValueToString for PackageJsonReference {
46 #[turbo_tasks::function]
47 async fn to_string(&self) -> Result<Vc<RcStr>> {
48 Ok(Vc::cell(
49 format!(
50 "package.json {}",
51 self.package_json.value_to_string().await?
52 )
53 .into(),
54 ))
55 }
56}
57
58#[turbo_tasks::value]
59#[derive(Hash, Debug)]
60pub struct DirAssetReference {
61 pub source: ResolvedVc<Box<dyn Source>>,
62 pub path: ResolvedVc<Pattern>,
63}
64
65#[turbo_tasks::value_impl]
66impl DirAssetReference {
67 #[turbo_tasks::function]
68 pub fn new(source: ResolvedVc<Box<dyn Source>>, path: ResolvedVc<Pattern>) -> Vc<Self> {
69 Self::cell(DirAssetReference { source, path })
70 }
71}
72
73#[turbo_tasks::function]
74async fn resolve_reference_from_dir(
75 parent_path: FileSystemPath,
76 path: Vc<Pattern>,
77) -> Result<Vc<ModuleResolveResult>> {
78 let path_ref = path.await?;
79 let (abs_path, rel_path) = path_ref.split_could_match("/ROOT/");
80 if abs_path.is_none() && rel_path.is_none() {
81 return Ok(*ModuleResolveResult::unresolvable());
82 }
83
84 let abs_matches = if let Some(abs_path) = &abs_path {
85 Some(
86 read_matches(
87 parent_path.root().owned().await?,
88 rcstr!("/ROOT/"),
89 true,
90 Pattern::new(abs_path.or_any_nested_file()),
91 )
92 .await?,
93 )
94 } else {
95 None
96 };
97 let rel_matches = if let Some(rel_path) = &rel_path {
98 Some(
99 read_matches(
100 parent_path,
101 rcstr!(""),
102 true,
103 Pattern::new(rel_path.or_any_nested_file()),
104 )
105 .await?,
106 )
107 } else {
108 None
109 };
110
111 let matches = abs_matches
112 .into_iter()
113 .flatten()
114 .chain(rel_matches.into_iter().flatten());
115
116 let mut affecting_sources = Vec::new();
117 let mut results = Vec::new();
118 for pat_match in matches {
119 match pat_match {
120 PatternMatch::File(matched_path, file) => {
121 let realpath = file.realpath_with_links().await?;
122 for symlink in &realpath.symlinks {
123 affecting_sources.push(ResolvedVc::upcast(
124 FileSource::new(symlink.clone()).to_resolved().await?,
125 ));
126 }
127 results.push((
128 RequestKey::new(matched_path.clone()),
129 ResolvedVc::upcast(
130 RawModule::new(Vc::upcast(FileSource::new(realpath.path.clone())))
131 .to_resolved()
132 .await?,
133 ),
134 ));
135 }
136 PatternMatch::Directory(..) => {}
137 }
138 }
139 Ok(*ModuleResolveResult::modules_with_affecting_sources(
140 results,
141 affecting_sources,
142 ))
143}
144
145#[turbo_tasks::value_impl]
146impl ModuleReference for DirAssetReference {
147 #[turbo_tasks::function]
148 async fn resolve_reference(&self) -> Result<Vc<ModuleResolveResult>> {
149 let parent_path = self.source.ident().path().await?.parent();
150 let span = tracing::info_span!(
151 "trace directory",
152 pattern = display(self.path.to_string().await?)
153 );
154 async {
155 resolve_reference_from_dir(parent_path, *self.path)
156 .resolve()
157 .await
158 }
159 .instrument(span)
160 .await
161 }
162}
163
164#[turbo_tasks::value_impl]
165impl ChunkableModuleReference for DirAssetReference {
166 #[turbo_tasks::function]
167 fn chunking_type(&self) -> Vc<ChunkingTypeOption> {
168 Vc::cell(Some(ChunkingType::Traced))
169 }
170}
171
172#[turbo_tasks::value_impl]
173impl ValueToString for DirAssetReference {
174 #[turbo_tasks::function]
175 async fn to_string(&self) -> Result<Vc<RcStr>> {
176 Ok(Vc::cell(
177 format!("directory assets {}", self.path.to_string().await?,).into(),
178 ))
179 }
180}