1use anyhow::Result;
2use turbo_rcstr::rcstr;
3use turbo_tasks::{ResolvedVc, Vc};
4use turbopack_core::{
5 issue::IssueSource,
6 reference_type::{CommonJsReferenceSubType, EcmaScriptModulesReferenceSubType, ReferenceType},
7 resolve::{
8 ModuleResolveResult, ResolveErrorMode, ResolveResult,
9 error::{handle_resolve_error, handle_resolve_source_error},
10 options::{
11 ConditionValue, ResolutionConditions, ResolveInPackage, ResolveIntoPackage,
12 ResolveOptions,
13 },
14 origin::{ResolveOrigin, ResolveOriginExt},
15 parse::Request,
16 resolve,
17 },
18};
19pub fn get_condition_maps(
25 options: &mut ResolveOptions,
26) -> impl Iterator<Item = &mut ResolutionConditions> {
27 options
28 .into_package
29 .iter_mut()
30 .filter_map(|item| {
31 if let ResolveIntoPackage::ExportsField { conditions, .. } = item {
32 Some(conditions)
33 } else {
34 None
35 }
36 })
37 .chain(options.in_package.iter_mut().filter_map(|item| {
38 if let ResolveInPackage::ImportsField { conditions, .. } = item {
39 Some(conditions)
40 } else {
41 None
42 }
43 }))
44}
45
46pub fn apply_esm_specific_options(
47 options: Vc<ResolveOptions>,
48 reference_type: &ReferenceType,
49) -> Vc<ResolveOptions> {
50 let clear_extensions = matches!(
51 reference_type,
52 ReferenceType::EcmaScriptModules(EcmaScriptModulesReferenceSubType::ImportWithType(_))
53 );
54
55 apply_esm_specific_options_internal(options, clear_extensions)
56}
57
58#[turbo_tasks::function]
59async fn apply_esm_specific_options_internal(
60 options: Vc<ResolveOptions>,
61 clear_extensions: bool,
62) -> Result<Vc<ResolveOptions>> {
63 let mut options: ResolveOptions = options.owned().await?;
64 for conditions in get_condition_maps(&mut options) {
67 conditions.insert(rcstr!("import"), ConditionValue::Set);
68 conditions.insert(rcstr!("require"), ConditionValue::Unset);
69 }
73
74 if clear_extensions {
75 options.extensions.clear();
76 }
77
78 options.parse_data_uris = true;
79
80 Ok(options.cell())
81}
82
83#[turbo_tasks::function]
84pub async fn apply_cjs_specific_options(options: Vc<ResolveOptions>) -> Result<Vc<ResolveOptions>> {
85 let mut options: ResolveOptions = options.owned().await?;
86 for conditions in get_condition_maps(&mut options) {
87 conditions.insert(rcstr!("import"), ConditionValue::Unset);
88 conditions.insert(rcstr!("require"), ConditionValue::Set);
89 }
93 Ok(options.cell())
94}
95
96pub async fn esm_resolve(
97 origin: Vc<Box<dyn ResolveOrigin>>,
98 request: Vc<Request>,
99 ty: EcmaScriptModulesReferenceSubType,
100 error_mode: ResolveErrorMode,
101 issue_source: Option<IssueSource>,
102) -> Result<Vc<ModuleResolveResult>> {
103 let ty = ReferenceType::EcmaScriptModules(ty);
104 let options = *apply_esm_specific_options(origin.resolve_options(), &ty)
105 .to_resolved()
106 .await?;
107 specific_resolve(origin, request, options, ty, error_mode, issue_source).await
108}
109
110#[turbo_tasks::function]
111pub async fn cjs_resolve(
112 origin: Vc<Box<dyn ResolveOrigin>>,
113 request: Vc<Request>,
114 ty: CommonJsReferenceSubType,
115 issue_source: Option<IssueSource>,
116 error_mode: ResolveErrorMode,
117) -> Result<Vc<ModuleResolveResult>> {
118 let ty = ReferenceType::CommonJs(ty);
119 let options = *apply_cjs_specific_options(origin.resolve_options())
120 .to_resolved()
121 .await?;
122 specific_resolve(origin, request, options, ty, error_mode, issue_source).await
123}
124
125#[turbo_tasks::function]
126pub async fn cjs_resolve_source(
127 origin: ResolvedVc<Box<dyn ResolveOrigin>>,
128 request: ResolvedVc<Request>,
129 ty: CommonJsReferenceSubType,
130 issue_source: Option<IssueSource>,
131 error_mode: ResolveErrorMode,
132) -> Result<Vc<ResolveResult>> {
133 let ty = ReferenceType::CommonJs(ty);
134 let options = *apply_cjs_specific_options(origin.resolve_options())
135 .to_resolved()
136 .await?;
137 let result = resolve(
138 origin.origin_path().await?.parent(),
139 ty.clone(),
140 *request,
141 options,
142 );
143
144 handle_resolve_source_error(
145 result,
146 ty,
147 *origin,
148 *request,
149 options,
150 error_mode,
151 issue_source,
152 )
153 .await
154}
155
156async fn specific_resolve(
157 origin: Vc<Box<dyn ResolveOrigin>>,
158 request: Vc<Request>,
159 options: Vc<ResolveOptions>,
160 reference_type: ReferenceType,
161 error_mode: ResolveErrorMode,
162 issue_source: Option<IssueSource>,
163) -> Result<Vc<ModuleResolveResult>> {
164 let result = origin
165 .resolve_asset(request, options, reference_type.clone())
166 .await?;
167
168 handle_resolve_error(
169 result,
170 reference_type,
171 origin,
172 request,
173 options,
174 error_mode,
175 issue_source,
176 )
177 .await
178}