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