turbopack_ecmascript/references/
node.rs1use anyhow::Result;
2use either::Either;
3use turbo_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: ResolvedVc<FileSystemPath>,
22}
23
24#[turbo_tasks::value_impl]
25impl PackageJsonReference {
26 #[turbo_tasks::function]
27 pub fn new(package_json: ResolvedVc<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)))
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!("package.json {}", self.package_json.to_string().await?,).into(),
50 ))
51 }
52}
53
54#[turbo_tasks::value]
55#[derive(Hash, Debug)]
56pub struct DirAssetReference {
57 pub source: ResolvedVc<Box<dyn Source>>,
58 pub path: ResolvedVc<Pattern>,
59}
60
61#[turbo_tasks::value_impl]
62impl DirAssetReference {
63 #[turbo_tasks::function]
64 pub fn new(source: ResolvedVc<Box<dyn Source>>, path: ResolvedVc<Pattern>) -> Vc<Self> {
65 Self::cell(DirAssetReference { source, path })
66 }
67}
68
69#[turbo_tasks::function]
70async fn resolve_reference_from_dir(
71 parent_path: Vc<FileSystemPath>,
72 path: Vc<Pattern>,
73) -> Result<Vc<ModuleResolveResult>> {
74 let path_ref = path.await?;
75 let (abs_path, rel_path) = path_ref.split_could_match("/ROOT/");
76 let matches = match (abs_path, rel_path) {
77 (Some(abs_path), Some(rel_path)) => Either::Right(
78 read_matches(
79 parent_path.root().resolve().await?,
80 "/ROOT/".into(),
81 true,
82 Pattern::new(abs_path.or_any_nested_file()),
83 )
84 .await?
85 .into_iter()
86 .chain(
87 read_matches(
88 parent_path,
89 "".into(),
90 true,
91 Pattern::new(rel_path.or_any_nested_file()),
92 )
93 .await?
94 .into_iter(),
95 ),
96 ),
97 (Some(abs_path), None) => Either::Left(
98 read_matches(
100 parent_path.root().resolve().await?,
101 "/ROOT/".into(),
102 true,
103 Pattern::new(abs_path.or_any_nested_file()),
104 )
105 .await?
106 .into_iter(),
107 ),
108 (None, Some(rel_path)) => Either::Left(
109 read_matches(
111 parent_path,
112 "".into(),
113 true,
114 Pattern::new(rel_path.or_any_nested_file()),
115 )
116 .await?
117 .into_iter(),
118 ),
119 (None, None) => return Ok(*ModuleResolveResult::unresolvable()),
120 };
121 let mut affecting_sources = Vec::new();
122 let mut results = Vec::new();
123 for pat_match in matches {
124 match pat_match {
125 PatternMatch::File(matched_path, file) => {
126 let realpath = file.realpath_with_links().await?;
127 for &symlink in &realpath.symlinks {
128 affecting_sources.push(ResolvedVc::upcast(
129 FileSource::new(*symlink).to_resolved().await?,
130 ));
131 }
132 results.push((
133 RequestKey::new(matched_path.clone()),
134 ResolvedVc::upcast(
135 RawModule::new(Vc::upcast(FileSource::new(*realpath.path)))
136 .to_resolved()
137 .await?,
138 ),
139 ));
140 }
141 PatternMatch::Directory(..) => {}
142 }
143 }
144 Ok(*ModuleResolveResult::modules_with_affecting_sources(
145 results,
146 affecting_sources,
147 ))
148}
149
150#[turbo_tasks::value_impl]
151impl ModuleReference for DirAssetReference {
152 #[turbo_tasks::function]
153 async fn resolve_reference(&self) -> Result<Vc<ModuleResolveResult>> {
154 let parent_path = self.source.ident().path().parent();
155 Ok(resolve_reference_from_dir(
156 parent_path.resolve().await?,
157 *self.path,
158 ))
159 }
160}
161
162#[turbo_tasks::value_impl]
163impl ChunkableModuleReference for DirAssetReference {
164 #[turbo_tasks::function]
165 fn chunking_type(&self) -> Vc<ChunkingTypeOption> {
166 Vc::cell(Some(ChunkingType::Traced))
167 }
168}
169
170#[turbo_tasks::value_impl]
171impl ValueToString for DirAssetReference {
172 #[turbo_tasks::function]
173 async fn to_string(&self) -> Result<Vc<RcStr>> {
174 Ok(Vc::cell(
175 format!("directory assets {}", self.path.to_string().await?,).into(),
176 ))
177 }
178}