turbopack_resolve/
ecmascript.rs1use anyhow::Result;
2use turbo_tasks::{ResolvedVc, Value, Vc};
3use turbopack_core::{
4 issue::IssueSource,
5 reference_type::{CommonJsReferenceSubType, EcmaScriptModulesReferenceSubType, ReferenceType},
6 resolve::{
7 ModuleResolveResult, ResolveResult, handle_resolve_error, handle_resolve_source_error,
8 options::{
9 ConditionValue, ResolutionConditions, ResolveInPackage, ResolveIntoPackage,
10 ResolveOptions,
11 },
12 origin::{ResolveOrigin, ResolveOriginExt},
13 parse::Request,
14 resolve,
15 },
16};
17pub fn get_condition_maps(
23 options: &mut ResolveOptions,
24) -> impl Iterator<Item = &mut ResolutionConditions> {
25 options
26 .into_package
27 .iter_mut()
28 .filter_map(|item| {
29 if let ResolveIntoPackage::ExportsField { conditions, .. } = item {
30 Some(conditions)
31 } else {
32 None
33 }
34 })
35 .chain(options.in_package.iter_mut().filter_map(|item| {
36 if let ResolveInPackage::ImportsField { conditions, .. } = item {
37 Some(conditions)
38 } else {
39 None
40 }
41 }))
42}
43
44pub fn apply_esm_specific_options(
45 options: Vc<ResolveOptions>,
46 reference_type: Value<ReferenceType>,
47) -> Vc<ResolveOptions> {
48 apply_esm_specific_options_internal(
49 options,
50 matches!(
51 reference_type.into_value(),
52 ReferenceType::EcmaScriptModules(EcmaScriptModulesReferenceSubType::ImportWithType(_))
53 ),
54 )
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("import".into(), ConditionValue::Set);
67 conditions.insert("require".into(), 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("import".into(), ConditionValue::Unset);
84 conditions.insert("require".into(), 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: Value<EcmaScriptModulesReferenceSubType>,
93 is_optional: bool,
94 issue_source: Option<IssueSource>,
95) -> Result<Vc<ModuleResolveResult>> {
96 let ty = Value::new(ReferenceType::EcmaScriptModules(ty.into_value()));
97 let options = apply_esm_specific_options(origin.resolve_options(ty.clone()), 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 = Value::new(ReferenceType::CommonJs(CommonJsReferenceSubType::Undefined));
112 let options = apply_cjs_specific_options(origin.resolve_options(ty.clone()))
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 = Value::new(ReferenceType::CommonJs(CommonJsReferenceSubType::Undefined));
127 let options = apply_cjs_specific_options(origin.resolve_options(ty.clone()))
128 .resolve()
129 .await?;
130 let result = resolve(
131 origin.origin_path().parent().resolve().await?,
132 ty.clone(),
133 *request,
134 options,
135 );
136
137 handle_resolve_source_error(
138 result,
139 ty,
140 origin.origin_path(),
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: Value<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(),
165 request,
166 options,
167 is_optional,
168 issue_source,
169 )
170 .await
171}