Skip to content

Commit 71fb5c1

Browse files
authoredJan 21, 2024
fix(es/module): Fix resolving of dependencies (#8533)
**Description:** I changed the signature of `Resolve` because there was a need to pass the `value` part from `jsc.paths` to the caller. **Related issue:** - Closes #8184
1 parent fb8d6cd commit 71fb5c1

File tree

32 files changed

+257
-74
lines changed

32 files changed

+257
-74
lines changed
 

‎Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎crates/swc/src/config/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -619,7 +619,7 @@ impl Options {
619619
&plugin_name,
620620
)?;
621621

622-
let path = if let FileName::Real(value) = resolved_path {
622+
let path = if let FileName::Real(value) = resolved_path.filename {
623623
value
624624
} else {
625625
anyhow::bail!("Failed to resolve plugin path: {:?}", resolved_path);
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
import styles from "./foo.ts/index.js";
1+
import styles from "./foo.ts/index";
22
console.log(styles);
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
import { NekoRoute } from "./src/lib/structures/route/index.js";
1+
import { NekoRoute } from "./src/lib/structures/route";
22
console.log(NekoRoute);
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
import { fn } from "./libs/pkg/src";
1+
import { fn } from "./libs/pkg/src/index.ts";
22
console.log(fn);

‎crates/swc/tests/fixture/issues-7xxx/7898/1/output/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
Object.defineProperty(exports, "__esModule", {
33
value: true
44
});
5-
const _a = require("./packages/a/src/index.js");
5+
const _a = require("./packages/a/src/index.ts");
66
console.log(`${(0, _a.displayA)()}`);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"jsc": {
3+
"parser": {
4+
"syntax": "typescript",
5+
"tsx": true
6+
},
7+
"baseUrl": ".",
8+
"paths": {
9+
"~/*": [
10+
"./src/*"
11+
]
12+
}
13+
}
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
4+
const a = props => {
5+
return (
6+
<div>
7+
8+
</div>
9+
);
10+
};
11+
12+
a.propTypes = {
13+
14+
};
15+
16+
export default a;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
4+
const b = props => {
5+
return (
6+
<div>
7+
8+
</div>
9+
);
10+
};
11+
12+
b.propTypes = {
13+
14+
};
15+
16+
export default b;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default (a) => a
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import * as React from 'react';
2+
3+
interface IAppProps {
4+
}
5+
6+
const App: React.FunctionComponent<IAppProps> = (props) => {
7+
return <div>123</div>;
8+
};
9+
10+
export default App;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import a from '~/a';
2+
import b from '~/b';
3+
import c from '~/c';
4+
import d from '~/d';
5+
6+
console.log(a, b, c, d);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import React from "react";
2+
var b = function(props) {
3+
return /*#__PURE__*/ React.createElement("div", null);
4+
};
5+
b.propTypes = {};
6+
export default b;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default function(a) {
2+
return a;
3+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import * as React from "react";
2+
var App = function(props) {
3+
return /*#__PURE__*/ React.createElement("div", null, "123");
4+
};
5+
export default App;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import a from "./a";
2+
import b from "./b";
3+
import c from "./c";
4+
import d from "./d";
5+
console.log(a, b, c, d);

‎crates/swc_bundler/examples/path.rs

+11-7
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use swc_bundler::{BundleKind, Bundler, Config, Hook, Load, ModuleData, ModuleRec
55
use swc_common::{sync::Lrc, FileName, FilePathMapping, Globals, SourceMap, Span};
66
use swc_ecma_ast::KeyValueProp;
77
use swc_ecma_codegen::{text_writer::JsWriter, Emitter};
8+
use swc_ecma_loader::resolve::Resolution;
89
use swc_ecma_parser::{parse_file_as_module, Syntax};
910

1011
fn main() {
@@ -87,7 +88,7 @@ impl Load for PathLoader {
8788
struct PathResolver;
8889

8990
impl Resolve for PathResolver {
90-
fn resolve(&self, base: &FileName, module_specifier: &str) -> Result<FileName, Error> {
91+
fn resolve(&self, base: &FileName, module_specifier: &str) -> Result<Resolution, Error> {
9192
assert!(
9293
module_specifier.starts_with('.'),
9394
"We are not using node_modules within this example"
@@ -98,12 +99,15 @@ impl Resolve for PathResolver {
9899
_ => unreachable!(),
99100
};
100101

101-
Ok(FileName::Real(
102-
base.parent()
103-
.unwrap()
104-
.join(module_specifier)
105-
.with_extension("js"),
106-
))
102+
Ok(Resolution {
103+
filename: FileName::Real(
104+
base.parent()
105+
.unwrap()
106+
.join(module_specifier)
107+
.with_extension("js"),
108+
),
109+
slug: None,
110+
})
107111
}
108112
}
109113

‎crates/swc_bundler/src/bundler/finalize.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ where
382382
.resolver
383383
.resolve(&FileName::Real(self.base.clone()), &import.src.value)
384384
{
385-
Ok(v) => match v {
385+
Ok(v) => match v.filename {
386386
FileName::Real(v) => v,
387387
_ => panic!("rename_bundles called with non-path module"),
388388
},

‎crates/swc_bundler/src/bundler/import/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ where
5757
let path = self
5858
.resolver
5959
.resolve(base, module_specifier)
60+
.map(|v| v.filename)
6061
.with_context(|| format!("failed to resolve {} from {}", module_specifier, base))?;
6162

6263
let path = Lrc::new(path);

‎crates/swc_bundler/src/bundler/tests.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use anyhow::Error;
55
use indexmap::IndexMap;
66
use swc_common::{collections::ARandomState, sync::Lrc, FileName, SourceMap, Span, GLOBALS};
77
use swc_ecma_ast::*;
8+
use swc_ecma_loader::resolve::Resolution;
89
use swc_ecma_parser::{lexer::Lexer, Parser, StringInput};
910
use swc_ecma_utils::drop_span;
1011
use swc_ecma_visit::VisitMutWith;
@@ -52,7 +53,7 @@ impl Load for Loader {
5253
pub struct Resolver;
5354

5455
impl Resolve for Resolver {
55-
fn resolve(&self, _: &FileName, s: &str) -> Result<FileName, Error> {
56+
fn resolve(&self, _: &FileName, s: &str) -> Result<Resolution, Error> {
5657
assert!(s.starts_with("./"));
5758

5859
let path = PathBuf::from(s.to_string())
@@ -61,7 +62,10 @@ impl Resolve for Resolver {
6162
.unwrap()
6263
.into();
6364

64-
Ok(FileName::Real(path))
65+
Ok(Resolution {
66+
filename: FileName::Real(path),
67+
slug: None,
68+
})
6569
}
6670
}
6771

‎crates/swc_bundler/tests/common/mod.rs

+12-3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use swc_common::{
1717
FileName, Mark, SourceMap,
1818
};
1919
use swc_ecma_ast::{EsVersion, Program};
20+
use swc_ecma_loader::resolve::Resolution;
2021
use swc_ecma_parser::{parse_file_as_module, Syntax, TsConfig};
2122
use swc_ecma_transforms_base::{
2223
helpers::{inject_helpers, Helpers, HELPERS},
@@ -273,10 +274,8 @@ impl NodeResolver {
273274
None => bail!("not found"),
274275
}
275276
}
276-
}
277277

278-
impl Resolve for NodeResolver {
279-
fn resolve(&self, base: &FileName, target: &str) -> Result<FileName, Error> {
278+
fn resolve_inner(&self, base: &FileName, target: &str) -> Result<FileName, Error> {
280279
if let Ok(v) = Url::parse(target) {
281280
return Ok(FileName::Custom(v.to_string()));
282281
}
@@ -337,3 +336,13 @@ impl Resolve for NodeResolver {
337336
.and_then(|p| self.wrap(p))
338337
}
339338
}
339+
340+
impl Resolve for NodeResolver {
341+
fn resolve(&self, base: &FileName, module_specifier: &str) -> Result<Resolution, Error> {
342+
self.resolve_inner(base, module_specifier)
343+
.map(|filename| Resolution {
344+
filename,
345+
slug: None,
346+
})
347+
}
348+
}

‎crates/swc_ecma_loader/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ serde = { version = "1", features = ["derive"] }
3636
serde_json = { version = "1.0.64", optional = true }
3737
tracing = "0.1.37"
3838

39+
swc_atoms = { version = "0.6.5", path = "../swc_atoms" }
3940
swc_cached = { version = "0.3.18", optional = true, path = "../swc_cached" }
4041
swc_common = { version = "0.33.14", path = "../swc_common" }
4142

‎crates/swc_ecma_loader/src/resolve.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
11
use std::sync::Arc;
22

33
use anyhow::Error;
4+
use swc_atoms::Atom;
45
use swc_common::{
56
sync::{Send, Sync},
67
FileName,
78
};
89

10+
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
11+
pub struct Resolution {
12+
pub filename: FileName,
13+
pub slug: Option<Atom>,
14+
}
15+
916
pub trait Resolve: Send + Sync {
10-
fn resolve(&self, base: &FileName, module_specifier: &str) -> Result<FileName, Error>;
17+
fn resolve(&self, base: &FileName, module_specifier: &str) -> Result<Resolution, Error>;
1118
}
1219

1320
macro_rules! impl_ref {
@@ -16,7 +23,7 @@ macro_rules! impl_ref {
1623
where
1724
R: ?Sized + Resolve,
1825
{
19-
fn resolve(&self, base: &FileName, src: &str) -> Result<FileName, Error> {
26+
fn resolve(&self, base: &FileName, src: &str) -> Result<Resolution, Error> {
2027
(**self).resolve(base, src)
2128
}
2229
}

‎crates/swc_ecma_loader/src/resolvers/lru.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ use lru::LruCache;
55
use parking_lot::Mutex;
66
use swc_common::FileName;
77

8-
use crate::resolve::Resolve;
8+
use crate::resolve::{Resolution, Resolve};
99

1010
#[derive(Debug)]
1111
pub struct CachingResolver<R>
1212
where
1313
R: Resolve,
1414
{
15-
cache: Mutex<LruCache<(FileName, String), FileName>>,
15+
cache: Mutex<LruCache<(FileName, String), Resolution>>,
1616
inner: R,
1717
}
1818

@@ -43,7 +43,7 @@ impl<R> Resolve for CachingResolver<R>
4343
where
4444
R: Resolve,
4545
{
46-
fn resolve(&self, base: &FileName, src: &str) -> Result<FileName, Error> {
46+
fn resolve(&self, base: &FileName, src: &str) -> Result<Resolution, Error> {
4747
{
4848
let mut lock = self.cache.lock();
4949
//

‎crates/swc_ecma_loader/src/resolvers/node.rs

+15-4
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ use swc_common::{
2323
};
2424
use tracing::{debug, trace, Level};
2525

26-
use crate::{resolve::Resolve, TargetEnv, NODE_BUILTINS};
26+
use crate::{
27+
resolve::{Resolution, Resolve},
28+
TargetEnv, NODE_BUILTINS,
29+
};
2730

2831
static PACKAGE: &str = "package.json";
2932

@@ -409,10 +412,8 @@ impl NodeModulesResolver {
409412

410413
Ok(None)
411414
}
412-
}
413415

414-
impl Resolve for NodeModulesResolver {
415-
fn resolve(&self, base: &FileName, target: &str) -> Result<FileName, Error> {
416+
fn resolve_filename(&self, base: &FileName, target: &str) -> Result<FileName, Error> {
416417
debug!(
417418
"Resolving {} from {:#?} for {:#?}",
418419
target, base, self.target_env
@@ -527,3 +528,13 @@ impl Resolve for NodeModulesResolver {
527528
file_name
528529
}
529530
}
531+
532+
impl Resolve for NodeModulesResolver {
533+
fn resolve(&self, base: &FileName, module_specifier: &str) -> Result<Resolution, Error> {
534+
self.resolve_filename(base, module_specifier)
535+
.map(|filename| Resolution {
536+
filename,
537+
slug: None,
538+
})
539+
}
540+
}

‎crates/swc_ecma_loader/src/resolvers/tsc.rs

+32-14
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use anyhow::{bail, Context, Error};
44
use swc_common::FileName;
55
use tracing::{debug, info, trace, warn, Level};
66

7-
use crate::resolve::Resolve;
7+
use crate::resolve::{Resolution, Resolve};
88

99
#[derive(Debug)]
1010
enum Pattern {
@@ -104,7 +104,7 @@ where
104104
&self,
105105
base: &FileName,
106106
module_specifier: &str,
107-
) -> Result<FileName, Error> {
107+
) -> Result<Resolution, Error> {
108108
let res = self.inner.resolve(base, module_specifier).with_context(|| {
109109
format!(
110110
"failed to resolve `{module_specifier}` from `{base}` using inner \
@@ -117,7 +117,7 @@ where
117117
Ok(resolved) => {
118118
info!(
119119
"Resolved `{}` as `{}` from `{}`",
120-
module_specifier, resolved, base
120+
module_specifier, resolved.filename, base
121121
);
122122

123123
let is_base_in_node_modules = if let FileName::Real(v) = base {
@@ -128,7 +128,7 @@ where
128128
} else {
129129
false
130130
};
131-
let is_target_in_node_modules = if let FileName::Real(v) = &resolved {
131+
let is_target_in_node_modules = if let FileName::Real(v) = &resolved.filename {
132132
v.components().any(|c| match c {
133133
Component::Normal(v) => v == "node_modules",
134134
_ => false,
@@ -139,7 +139,10 @@ where
139139

140140
// If node_modules is in path, we should return module specifier.
141141
if !is_base_in_node_modules && is_target_in_node_modules {
142-
return Ok(FileName::Real(module_specifier.into()));
142+
return Ok(Resolution {
143+
filename: FileName::Real(module_specifier.into()),
144+
..resolved
145+
});
143146
}
144147

145148
Ok(resolved)
@@ -157,7 +160,7 @@ impl<R> Resolve for TsConfigResolver<R>
157160
where
158161
R: Resolve,
159162
{
160-
fn resolve(&self, base: &FileName, module_specifier: &str) -> Result<FileName, Error> {
163+
fn resolve(&self, base: &FileName, module_specifier: &str) -> Result<Resolution, Error> {
161164
let _tracing = if cfg!(debug_assertions) {
162165
Some(
163166
tracing::span!(
@@ -219,7 +222,7 @@ where
219222

220223
let mut errors = vec![];
221224
for target in to {
222-
let mut replaced = target.replace('*', extra);
225+
let replaced = target.replace('*', extra);
223226

224227
let _tracing = if cfg!(debug_assertions) {
225228
Some(
@@ -250,17 +253,22 @@ where
250253
Err(err) => err,
251254
});
252255

253-
if cfg!(target_os = "windows") {
254-
replaced = replaced.replace('/', "\\");
255-
}
256-
257256
if to.len() == 1 {
258257
info!(
259258
"Using `{}` for `{}` because the length of the jsc.paths entry is \
260259
1",
261260
replaced, module_specifier
262261
);
263-
return Ok(FileName::Real(replaced.into()));
262+
return Ok(Resolution {
263+
slug: Some(
264+
replaced
265+
.split([std::path::MAIN_SEPARATOR, '/'])
266+
.last()
267+
.unwrap()
268+
.into(),
269+
),
270+
filename: FileName::Real(replaced.into()),
271+
});
264272
}
265273
}
266274

@@ -278,16 +286,26 @@ where
278286
}
279287

280288
let tp = Path::new(&to[0]);
289+
let slug = to[0]
290+
.split([std::path::MAIN_SEPARATOR, '/'])
291+
.last()
292+
.map(|v| v.into());
281293
if tp.is_absolute() {
282-
return Ok(FileName::Real(tp.into()));
294+
return Ok(Resolution {
295+
filename: FileName::Real(tp.into()),
296+
slug,
297+
});
283298
}
284299

285300
if let Ok(res) = self.resolve(&self.base_url_filename, &format!("./{}", &to[0]))
286301
{
287302
return Ok(res);
288303
}
289304

290-
return Ok(FileName::Real(self.base_url.join(&to[0])));
305+
return Ok(Resolution {
306+
filename: FileName::Real(self.base_url.join(&to[0])),
307+
slug,
308+
});
291309
}
292310
}
293311
}

‎crates/swc_ecma_loader/tests/node_resolver.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ fn basic_import() {
4141

4242
// Expect
4343
assert_eq!(
44-
resolved,
44+
resolved.filename,
4545
FileName::Real(PathBuf::from("node_modules/jquery/index.js"))
4646
);
4747
});
@@ -60,7 +60,7 @@ fn hoisting() {
6060

6161
// Expect
6262
assert_eq!(
63-
resolved,
63+
resolved.filename,
6464
FileName::Real(PathBuf::from("../../node_modules/jquery/index.js"))
6565
);
6666
});
@@ -76,15 +76,15 @@ fn builtin_modules() {
7676
.expect("should resolve");
7777

7878
// Expect
79-
assert_eq!(resolved, FileName::Custom("node:path".to_string()));
79+
assert_eq!(resolved.filename, FileName::Custom("node:path".to_string()));
8080

8181
// When
8282
let resolved = node_resolver
8383
.resolve(&FileName::Real(PathBuf::from("index.js")), "node:path")
8484
.expect("should resolve");
8585

8686
// Expect
87-
assert_eq!(resolved, FileName::Custom("node:path".to_string()));
87+
assert_eq!(resolved.filename, FileName::Custom("node:path".to_string()));
8888
}
8989

9090
#[test]
@@ -100,7 +100,7 @@ fn browser_overwrite() {
100100

101101
// Expect
102102
assert_eq!(
103-
resolved,
103+
resolved.filename,
104104
FileName::Real(PathBuf::from("node_modules/jquery/browser.js"))
105105
);
106106
});

‎crates/swc_ecma_loader/tests/tsc_resolver.rs

+30-5
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ use std::collections::HashMap;
44

55
use anyhow::{anyhow, Error};
66
use swc_common::{collections::AHashMap, FileName};
7-
use swc_ecma_loader::{resolve::Resolve, resolvers::tsc::TsConfigResolver};
7+
use swc_ecma_loader::{
8+
resolve::{Resolution, Resolve},
9+
resolvers::tsc::TsConfigResolver,
10+
};
811

912
#[test]
1013
fn base_dir_exact() {}
@@ -34,7 +37,13 @@ fn exact() {
3437
.resolve(&FileName::Anon, "jquery")
3538
.expect("should resolve");
3639

37-
assert_eq!(resolved, FileName::Custom("success".into()));
40+
assert_eq!(
41+
resolved,
42+
Resolution {
43+
filename: FileName::Custom("success".into()),
44+
slug: None
45+
}
46+
);
3847
}
3948

4049
{
@@ -64,26 +73,42 @@ fn pattern_1() {
6473
.resolve(&FileName::Anon, "folder1/file2")
6574
.expect("should resolve");
6675

67-
assert_eq!(resolved, FileName::Custom("success-2".into()));
76+
assert_eq!(
77+
resolved,
78+
Resolution {
79+
filename: FileName::Custom("success-2".into()),
80+
slug: None
81+
}
82+
);
6883
}
6984

7085
{
7186
let resolved = r
7287
.resolve(&FileName::Anon, "folder2/file3")
7388
.expect("should resolve");
7489

75-
assert_eq!(resolved, FileName::Custom("success-3".into()));
90+
assert_eq!(
91+
resolved,
92+
Resolution {
93+
filename: FileName::Custom("success-3".into()),
94+
slug: None
95+
}
96+
);
7697
}
7798
}
7899

79100
struct TestResolver(AHashMap<String, String>);
80101

81102
impl Resolve for TestResolver {
82-
fn resolve(&self, _: &FileName, src: &str) -> Result<FileName, Error> {
103+
fn resolve(&self, _: &FileName, src: &str) -> Result<Resolution, Error> {
83104
self.0
84105
.get(src)
85106
.cloned()
86107
.map(FileName::Custom)
108+
.map(|v| Resolution {
109+
filename: v,
110+
slug: None,
111+
})
87112
.ok_or_else(|| anyhow!("failed to resolve `{}`", src))
88113
}
89114
}

‎crates/swc_ecma_transforms_module/src/path.rs

+35-15
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use pathdiff::diff_paths;
1313
use swc_atoms::JsWord;
1414
use swc_common::{FileName, Mark, Span, DUMMY_SP};
1515
use swc_ecma_ast::*;
16-
use swc_ecma_loader::resolve::Resolve;
16+
use swc_ecma_loader::resolve::{Resolution, Resolve};
1717
use swc_ecma_utils::{quote_ident, ExprFactory};
1818
use tracing::{debug, info, warn, Level};
1919

@@ -155,8 +155,8 @@ where
155155
false
156156
};
157157

158-
let is_resolved_as_ts = if let Some(ext) = target_path.extension() {
159-
ext == "ts" || ext == "tsx"
158+
let is_resolved_as_non_js = if let Some(ext) = target_path.extension() {
159+
ext != "js"
160160
} else {
161161
false
162162
};
@@ -173,17 +173,31 @@ where
173173
false
174174
};
175175

176-
if !is_resolved_as_js && !is_resolved_as_index && !is_exact {
176+
if orig_filename == "index" {
177+
// Import: `./foo/index`
178+
// Resolved: `./foo/index.js`
179+
180+
if self.config.resolve_fully {
181+
target_path.set_file_name("index.js");
182+
} else {
183+
target_path.set_file_name("index");
184+
}
185+
} else if is_resolved_as_index && is_resolved_as_js && orig_filename != "index.js" {
186+
// Import: `./foo`
187+
// Resolved: `./foo/index.js`
188+
189+
target_path.pop();
190+
} else if !is_resolved_as_js && !is_resolved_as_index && !is_exact {
177191
target_path.set_file_name(orig_filename);
178-
} else if is_resolved_as_ts && is_exact {
192+
} else if is_resolved_as_non_js && is_exact {
179193
if let Some(ext) = Path::new(orig_filename).extension() {
180194
target_path.set_extension(ext);
181195
} else {
182196
target_path.set_extension("js");
183197
}
184-
} else if self.config.resolve_fully && is_resolved_as_ts {
198+
} else if self.config.resolve_fully && is_resolved_as_non_js {
185199
target_path.set_extension("js");
186-
} else if is_resolved_as_ts && is_resolved_as_index {
200+
} else if is_resolved_as_non_js && is_resolved_as_index {
187201
if orig_filename == "index" {
188202
target_path.set_extension("");
189203
} else {
@@ -216,7 +230,7 @@ where
216230
None
217231
};
218232

219-
let orig_filename = module_specifier.split('/').last();
233+
let orig_slug = module_specifier.split('/').last();
220234

221235
let target = self.resolver.resolve(base, module_specifier);
222236
let mut target = match target {
@@ -230,24 +244,30 @@ where
230244
// Bazel uses symlink
231245
//
232246
// https://github.com/swc-project/swc/issues/8265
233-
if let FileName::Real(resolved) = &target {
247+
if let FileName::Real(resolved) = &target.filename {
234248
if let Ok(orig) = read_link(resolved) {
235-
target = FileName::Real(orig);
249+
target.filename = FileName::Real(orig);
236250
}
237251
}
238252

239-
info!("Resolved to {}", target);
253+
let Resolution {
254+
filename: target,
255+
slug,
256+
} = target;
257+
let slug = slug.as_deref().or(orig_slug);
258+
259+
info!("Resolved as {target:?} with slug = {slug:?}");
240260

241261
let mut target = match target {
242262
FileName::Real(v) => {
243263
// @nestjs/common should be preserved as a whole
244264
if v.starts_with(".") || v.starts_with("..") || v.is_absolute() {
245265
v
246266
} else {
247-
return Ok(self.to_specifier(v, orig_filename));
267+
return Ok(self.to_specifier(v, slug));
248268
}
249269
}
250-
FileName::Custom(s) => return Ok(self.to_specifier(s.into(), orig_filename)),
270+
FileName::Custom(s) => return Ok(self.to_specifier(s.into(), slug)),
251271
_ => {
252272
unreachable!(
253273
"Node path provider does not support using `{:?}` as a target file name",
@@ -293,7 +313,7 @@ where
293313

294314
let rel_path = match rel_path {
295315
Some(v) => v,
296-
None => return Ok(self.to_specifier(target, orig_filename)),
316+
None => return Ok(self.to_specifier(target, slug)),
297317
};
298318

299319
debug!("Relative path: {}", rel_path.display());
@@ -323,7 +343,7 @@ where
323343
Cow::Owned(format!("./{}", s))
324344
};
325345

326-
Ok(self.to_specifier(s.into_owned().into(), orig_filename))
346+
Ok(self.to_specifier(s.into_owned().into(), slug))
327347
}
328348
}
329349

‎crates/swc_ecma_transforms_module/tests/fixture-manual/issue-4730/output/index.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { displayB } from "../packages/b/src";
1+
import { displayB } from "../packages/b/src/index.js";
22
async function display() {
3-
const displayA = await import("../packages/a/src").then((c)=>c.displayA);
3+
const displayA = await import("../packages/a/src/index.js").then((c)=>c.displayA);
44
console.log(displayA());
55
console.log(displayB());
66
}

‎crates/swc_ecma_transforms_module/tests/path_node.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ fn issue_4730() {
5151
.join("packages")
5252
.join("a")
5353
.join("src")
54-
.join("index.ts")
54+
.join("index.js")
5555
.display()
5656
.to_string()],
5757
);
@@ -62,7 +62,7 @@ fn issue_4730() {
6262
.join("packages")
6363
.join("b")
6464
.join("src")
65-
.join("index.ts")
65+
.join("index.js")
6666
.display()
6767
.to_string()],
6868
);

‎node-swc/__tests__/transform/issue_4730_test.mjs

+4-4
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ it("should work", async () => {
2323
target: "es2020",
2424
baseUrl: resolve("."),
2525
paths: {
26-
"@print/a": [join(dir, "./packages/a/src/index.ts")],
27-
"@print/b": [join(dir, "./packages/b/src/index.ts")],
26+
"@print/a": [join(dir, "./packages/a/src/index.js")],
27+
"@print/b": [join(dir, "./packages/b/src/index.js")],
2828
},
2929
externalHelpers: true,
3030
},
@@ -38,9 +38,9 @@ it("should work", async () => {
3838
value: true
3939
});
4040
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
41-
const _b = require("../packages/b/src");
41+
const _b = require("../packages/b/src/index.js");
4242
async function display() {
43-
const displayA = await Promise.resolve().then(()=>/*#__PURE__*/ _interop_require_wildcard._(require("../packages/a/src"))).then((c)=>c.displayA);
43+
const displayA = await Promise.resolve().then(()=>/*#__PURE__*/ _interop_require_wildcard._(require("../packages/a/src/index.js"))).then((c)=>c.displayA);
4444
console.log(displayA());
4545
console.log((0, _b.displayB)());
4646
}

0 commit comments

Comments
 (0)
Please sign in to comment.