turbopack_ecmascript/references/
node.rs1use anyhow::Result;
2use either::Either;
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 let matches = match (abs_path, rel_path) {
81 (Some(abs_path), Some(rel_path)) => Either::Right(
82 read_matches(
83 parent_path.root().await?.clone_value(),
84 rcstr!("/ROOT/"),
85 true,
86 Pattern::new(abs_path.or_any_nested_file()),
87 )
88 .await?
89 .into_iter()
90 .chain(
91 read_matches(
92 parent_path,
93 rcstr!(""),
94 true,
95 Pattern::new(rel_path.or_any_nested_file()),
96 )
97 .await?
98 .into_iter(),
99 ),
100 ),
101 (Some(abs_path), None) => Either::Left(
102 read_matches(
104 parent_path.root().await?.clone_value(),
105 rcstr!("/ROOT/"),
106 true,
107 Pattern::new(abs_path.or_any_nested_file()),
108 )
109 .await?
110 .into_iter(),
111 ),
112 (None, Some(rel_path)) => Either::Left(
113 read_matches(
115 parent_path,
116 rcstr!(""),
117 true,
118 Pattern::new(rel_path.or_any_nested_file()),
119 )
120 .await?
121 .into_iter(),
122 ),
123 (None, None) => return Ok(*ModuleResolveResult::unresolvable()),
124 };
125 let mut affecting_sources = Vec::new();
126 let mut results = Vec::new();
127 for pat_match in matches {
128 match pat_match {
129 PatternMatch::File(matched_path, file) => {
130 let realpath = file.realpath_with_links().await?;
131 for symlink in &realpath.symlinks {
132 affecting_sources.push(ResolvedVc::upcast(
133 FileSource::new(symlink.clone()).to_resolved().await?,
134 ));
135 }
136 results.push((
137 RequestKey::new(matched_path.clone()),
138 ResolvedVc::upcast(
139 RawModule::new(Vc::upcast(FileSource::new(realpath.path.clone())))
140 .to_resolved()
141 .await?,
142 ),
143 ));
144 }
145 PatternMatch::Directory(..) => {}
146 }
147 }
148 Ok(*ModuleResolveResult::modules_with_affecting_sources(
149 results,
150 affecting_sources,
151 ))
152}
153
154#[turbo_tasks::value_impl]
155impl ModuleReference for DirAssetReference {
156 #[turbo_tasks::function]
157 async fn resolve_reference(&self) -> Result<Vc<ModuleResolveResult>> {
158 let parent_path = self.source.ident().path().await?.parent();
159 Ok(resolve_reference_from_dir(parent_path, *self.path))
160 }
161}
162
163#[turbo_tasks::value_impl]
164impl ChunkableModuleReference for DirAssetReference {
165 #[turbo_tasks::function]
166 fn chunking_type(&self) -> Vc<ChunkingTypeOption> {
167 Vc::cell(Some(ChunkingType::Traced))
168 }
169}
170
171#[turbo_tasks::value_impl]
172impl ValueToString for DirAssetReference {
173 #[turbo_tasks::function]
174 async fn to_string(&self) -> Result<Vc<RcStr>> {
175 Ok(Vc::cell(
176 format!("directory assets {}", self.path.to_string().await?,).into(),
177 ))
178 }
179}