Skip to content

Commit 73fadca

Browse files
authored
Turbopack: don't look into fallback import map twice (#82786)
Fixes a panic where we tried to lookup a `Pattern::Alternatives` in a `fallback_import_map.lookup()` (but the API is that the caller is in charge of unwrapping the alternative and calling lookup multiple times). We can completely skip this in this case, because the individual requests inside the `Request::Alternatives` already looked at the `fallback_import_map`, so no need to check again for the whole alternative as well. This was a somewhat recent regression: - #77954 made sure that `var` variables always have a `<dynamic>` variant added, due to their weird scope rules (or lack thereof). - #81541 then added a `fallback_import_map`
1 parent bccdb3f commit 73fadca

File tree

4 files changed

+76
-20
lines changed

4 files changed

+76
-20
lines changed

turbopack/crates/turbopack-core/src/resolve/mod.rs

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2094,27 +2094,31 @@ async fn resolve_internal_inline(
20942094
}
20952095
};
20962096

2097-
// Apply fallback import mappings if provided
2098-
if let Some(import_map) = &options_value.fallback_import_map
2099-
&& *result.is_unresolvable().await?
2100-
{
2101-
let result = import_map
2102-
.await?
2103-
.lookup(lookup_path.clone(), request)
2104-
.await?;
2105-
let resolved_result = resolve_import_map_result(
2106-
&result,
2107-
lookup_path.clone(),
2108-
lookup_path.clone(),
2109-
request,
2110-
options,
2111-
request.query().owned().await?,
2112-
)
2113-
.await?;
2114-
if let Some(result) = resolved_result
2115-
&& !*result.is_unresolvable().await?
2097+
// The individual variants inside the alternative already looked at the fallback import
2098+
// map in the recursive `resolve_internal_inline` calls
2099+
if !matches!(*request_value, Request::Alternatives { .. }) {
2100+
// Apply fallback import mappings if provided
2101+
if let Some(import_map) = &options_value.fallback_import_map
2102+
&& *result.is_unresolvable().await?
21162103
{
2117-
return Ok(result);
2104+
let result = import_map
2105+
.await?
2106+
.lookup(lookup_path.clone(), request)
2107+
.await?;
2108+
let resolved_result = resolve_import_map_result(
2109+
&result,
2110+
lookup_path.clone(),
2111+
lookup_path.clone(),
2112+
request,
2113+
options,
2114+
request.query().owned().await?,
2115+
)
2116+
.await?;
2117+
if let Some(result) = resolved_result
2118+
&& !*result.is_unresolvable().await?
2119+
{
2120+
return Ok(result);
2121+
}
21182122
}
21192123
}
21202124

turbopack/crates/turbopack-tests/tests/execution.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,17 @@ async fn run_test_operation(prepared_test: ResolvedVc<PreparedTest>) -> Result<V
392392
.resolved_cell(),
393393
);
394394

395+
let mut fallback_import_map = ImportMap::empty();
396+
fallback_import_map.insert_exact_alias(
397+
rcstr!("fallback"),
398+
ImportMapping::External(
399+
None,
400+
ExternalType::EcmaScriptModule,
401+
ExternalTraced::Untraced,
402+
)
403+
.resolved_cell(),
404+
);
405+
395406
let remove_unused_exports = options.remove_unused_exports.unwrap_or(true);
396407

397408
let asset_context: Vc<Box<dyn AssetContext>> = Vc::upcast(ModuleAssetContext::new(
@@ -435,6 +446,7 @@ async fn run_test_operation(prepared_test: ResolvedVc<PreparedTest>) -> Result<V
435446
browser: true,
436447
module: true,
437448
import_map: Some(import_map.resolved_cell()),
449+
fallback_import_map: Some(fallback_import_map.resolved_cell()),
438450
..Default::default()
439451
}
440452
.cell(),
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
let names = ['cannot-resolve']
2+
if (globalThis.foo != undefined) {
3+
// ensure `<dynamic>` is part of the array
4+
names.push(globalThis.foo)
5+
}
6+
7+
let result
8+
for (let name of names) {
9+
try {
10+
result = require(name).Iconv
11+
return
12+
} catch {}
13+
}
14+
15+
console.log(result)
16+
17+
it('should correctly handle potentially completely dynamic requests', () => {
18+
expect(result).toBeUndefined()
19+
})
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
warning - [resolve] /turbopack/crates/turbopack-tests/tests/execution/turbopack/resolving/dynamic/input/index.js:10:13 Module not found: Can't resolve ('cannot-resolve' | <dynamic>)
2+
3+
6 |
4+
7 | let result
5+
8 | for (let name of names) {
6+
9 | try {
7+
+ v-----------v
8+
10 + result = require(name).Iconv
9+
+ ^-----------^
10+
11 | return
11+
12 | } catch {}
12+
13 | }
13+
14 |
14+
15+
16+
17+
| It was not possible to find the requested file.
18+
| Parsed request as written in source code: module "'cannot-resolve'" or dynamic
19+
| Path where resolving has started: [project]/turbopack/crates/turbopack-tests/tests/execution/turbopack/resolving/dynamic/input/index.js
20+
| Type of request: commonjs request
21+
|

0 commit comments

Comments
 (0)