Skip to content

Commit e04c7b3

Browse files
hanseltimekdy1
andauthored
feat(es/transforms): Add module.outFileExtension (#9784)
**Description:** Summary of Changes: 1. Adds an `outFileExtension` property to every module configuration option struct 2. passes this configuration through to the resolver function and changes all hard-coded `"js"` checks to use the new parameter 3. As a matter of backwards compatibility, structures default to "js" if nothing is provided 4. `@swc/core` snapshot tests for each module using `resolveFully` and `outFileExtension` (Please check the rendered output of the snapshots to make sure you don't have any issues with it). 1. QOL - updates `@swc/core` jest config to use explicit module names (this was because the mapping util in jest was exploding when it would try to load in the .node files that were over 512MB) 5. QOL - updates the test script to pass through any existing NODE_OPTIONS - this allows debugging tools to add their own inspect configurations while preserving our esm module flag **Note** This is a rudimentary fix to: #3067 (comment). I had to implement it locally since I could not find a workaround in my timeline. I do know that @kdy1 said they would work on it a few days ago, so I am opening this to either provide some visibility to a solution that works for me if they haven't started or to let them switch to PR critique if that feels more valuable for their time on this issue. Let me know if this should be closed due to a better implementation already being in the works. **Related issue:** - Closes #3067 --------- Co-authored-by: Donny/강동윤 <kdy1997.dev@gmail.com>
1 parent e05e4c7 commit e04c7b3

File tree

69 files changed

+1048
-28
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+1048
-28
lines changed

.changeset/heavy-apes-collect.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
swc_ecma_transforms_module: major
3+
---
4+
5+
Feat out file extension resolution

crates/swc/src/config/mod.rs

+34-15
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ use swc_ecma_transforms::{
4848
self,
4949
path::{ImportResolver, NodeImportResolver, Resolver},
5050
rewriter::import_rewriter,
51-
EsModuleConfig,
51+
util, EsModuleConfig,
5252
},
5353
optimization::{const_modules, json_parse, simplifier},
5454
proposals::{
@@ -1400,22 +1400,39 @@ impl ModuleConfig {
14001400

14011401
let base_url = base_url.to_path_buf();
14021402
let resolver = match config {
1403-
None => build_resolver(base_url, paths, false),
1403+
None => build_resolver(base_url, paths, false, &util::Config::default_js_ext()),
14041404
Some(ModuleConfig::Es6(config)) | Some(ModuleConfig::NodeNext(config)) => {
1405-
build_resolver(base_url, paths, config.resolve_fully)
1406-
}
1407-
Some(ModuleConfig::CommonJs(config)) => {
1408-
build_resolver(base_url, paths, config.resolve_fully)
1409-
}
1410-
Some(ModuleConfig::Umd(config)) => {
1411-
build_resolver(base_url, paths, config.config.resolve_fully)
1412-
}
1413-
Some(ModuleConfig::Amd(config)) => {
1414-
build_resolver(base_url, paths, config.config.resolve_fully)
1415-
}
1416-
Some(ModuleConfig::SystemJs(config)) => {
1417-
build_resolver(base_url, paths, config.resolve_fully)
1405+
build_resolver(
1406+
base_url,
1407+
paths,
1408+
config.config.resolve_fully,
1409+
&config.config.out_file_extension,
1410+
)
14181411
}
1412+
Some(ModuleConfig::CommonJs(config)) => build_resolver(
1413+
base_url,
1414+
paths,
1415+
config.resolve_fully,
1416+
&config.out_file_extension,
1417+
),
1418+
Some(ModuleConfig::Umd(config)) => build_resolver(
1419+
base_url,
1420+
paths,
1421+
config.config.resolve_fully,
1422+
&config.config.out_file_extension,
1423+
),
1424+
Some(ModuleConfig::Amd(config)) => build_resolver(
1425+
base_url,
1426+
paths,
1427+
config.config.resolve_fully,
1428+
&config.config.out_file_extension,
1429+
),
1430+
Some(ModuleConfig::SystemJs(config)) => build_resolver(
1431+
base_url,
1432+
paths,
1433+
config.config.resolve_fully,
1434+
&config.config.out_file_extension,
1435+
),
14191436
};
14201437

14211438
Some((base, resolver))
@@ -1733,6 +1750,7 @@ fn build_resolver(
17331750
mut base_url: PathBuf,
17341751
paths: CompiledPaths,
17351752
resolve_fully: bool,
1753+
file_extension: &str,
17361754
) -> SwcImportResolver {
17371755
static CACHE: Lazy<DashMap<(PathBuf, CompiledPaths, bool), SwcImportResolver, ARandomState>> =
17381756
Lazy::new(Default::default);
@@ -1772,6 +1790,7 @@ fn build_resolver(
17721790
swc_ecma_transforms::modules::path::Config {
17731791
base_dir: Some(base_url.clone()),
17741792
resolve_fully,
1793+
file_extension: file_extension.to_owned(),
17751794
},
17761795
);
17771796
Arc::new(r)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"jsc": {
3+
"parser": {
4+
"syntax": "typescript",
5+
"dynamicImport": true,
6+
},
7+
"target": "es2020",
8+
"baseUrl": ".",
9+
"paths": {
10+
"@print/c": ["./packages/c/src/index.js"],
11+
},
12+
"externalHelpers": true,
13+
},
14+
"module": {
15+
"type": "amd",
16+
"resolveFully": true,
17+
// This should say "resolve this fully to .mjs".
18+
// Normally should be paired with --out-file-extension in the cli
19+
"outFileExtension": "mjs",
20+
},
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Simulate accessing a .js file in a third party package that shouldn't be edited
2+
import something from 'lodash/dist/something.js'
3+
export function displayC(): string {
4+
something()
5+
return 'Display C'
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
2+
import { displayB } from './inner/b'
3+
import { displayC } from '@print/c'
4+
import { merge } from 'lodash'
5+
6+
async function display() {
7+
const displayA = await import('./inner/a').then(c => c.displayA)
8+
console.log(displayA())
9+
console.log(displayB())
10+
console.log(displayC())
11+
const foo = merge({}, { a: 22 })
12+
}
13+
14+
display()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function displayA() {
2+
return 'Display A'
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function displayB() {
2+
return 'Display B'
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Simulate accessing a .js file in a third party package that shouldn't be edited
2+
define([
3+
"require",
4+
"exports",
5+
"@swc/helpers/_/_interop_require_default",
6+
"lodash/dist/something.js"
7+
], function(require, exports, _interop_require_default, _something) {
8+
"use strict";
9+
Object.defineProperty(exports, "__esModule", {
10+
value: true
11+
});
12+
Object.defineProperty(exports, "displayC", {
13+
enumerable: true,
14+
get: function() {
15+
return displayC;
16+
}
17+
});
18+
_something = /*#__PURE__*/ _interop_require_default._(_something);
19+
function displayC() {
20+
(0, _something.default)();
21+
return 'Display C';
22+
}
23+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
define([
2+
"require",
3+
"exports",
4+
"@swc/helpers/_/_interop_require_wildcard",
5+
"./inner/b/index.mjs",
6+
"../packages/c/src/index.mjs",
7+
"lodash"
8+
], function(require, exports, _interop_require_wildcard, _b, _c, _lodash) {
9+
"use strict";
10+
Object.defineProperty(exports, "__esModule", {
11+
value: true
12+
});
13+
async function display() {
14+
const displayA = await new Promise((resolve, reject)=>require([
15+
"./inner/a/index.mjs"
16+
], (m)=>resolve(/*#__PURE__*/ _interop_require_wildcard._(m)), reject)).then((c)=>c.displayA);
17+
console.log(displayA());
18+
console.log((0, _b.displayB)());
19+
console.log((0, _c.displayC)());
20+
const foo = (0, _lodash.merge)({}, {
21+
a: 22
22+
});
23+
}
24+
display();
25+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
define([
2+
"require",
3+
"exports"
4+
], function(require, exports) {
5+
"use strict";
6+
Object.defineProperty(exports, "__esModule", {
7+
value: true
8+
});
9+
Object.defineProperty(exports, "displayA", {
10+
enumerable: true,
11+
get: function() {
12+
return displayA;
13+
}
14+
});
15+
function displayA() {
16+
return 'Display A';
17+
}
18+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
define([
2+
"require",
3+
"exports"
4+
], function(require, exports) {
5+
"use strict";
6+
Object.defineProperty(exports, "__esModule", {
7+
value: true
8+
});
9+
Object.defineProperty(exports, "displayB", {
10+
enumerable: true,
11+
get: function() {
12+
return displayB;
13+
}
14+
});
15+
function displayB() {
16+
return 'Display B';
17+
}
18+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"jsc": {
3+
"parser": {
4+
"syntax": "typescript",
5+
"dynamicImport": true,
6+
},
7+
"target": "es2020",
8+
"baseUrl": ".",
9+
"paths": {
10+
"@print/c": ["./packages/c/src/index.js"],
11+
},
12+
"externalHelpers": true,
13+
},
14+
"module": {
15+
"type": "commonjs",
16+
"resolveFully": true,
17+
// This should say "resolve this fully to .mjs".
18+
// Normally should be paired with --out-file-extension in the cli
19+
"outFileExtension": "mjs",
20+
},
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Simulate accessing a .js file in a third party package that shouldn't be edited
2+
import something from 'lodash/dist/something.js'
3+
export function displayC(): string {
4+
something()
5+
return 'Display C'
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
2+
import { displayB } from './inner/b'
3+
import { displayC } from '@print/c'
4+
import { merge } from 'lodash'
5+
6+
async function display() {
7+
const displayA = await import('./inner/a').then(c => c.displayA)
8+
console.log(displayA())
9+
console.log(displayB())
10+
console.log(displayC())
11+
const foo = merge({}, { a: 22 })
12+
}
13+
14+
display()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function displayA() {
2+
return 'Display A'
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function displayB() {
2+
return 'Display B'
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Simulate accessing a .js file in a third party package that shouldn't be edited
2+
"use strict";
3+
Object.defineProperty(exports, "__esModule", {
4+
value: true
5+
});
6+
Object.defineProperty(exports, "displayC", {
7+
enumerable: true,
8+
get: function() {
9+
return displayC;
10+
}
11+
});
12+
const _interop_require_default = require("@swc/helpers/_/_interop_require_default");
13+
const _something = /*#__PURE__*/ _interop_require_default._(require("lodash/dist/something.js"));
14+
function displayC() {
15+
(0, _something.default)();
16+
return 'Display C';
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
"use strict";
2+
Object.defineProperty(exports, "__esModule", {
3+
value: true
4+
});
5+
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
6+
const _b = require("./inner/b/index.mjs");
7+
const _c = require("../packages/c/src/index.mjs");
8+
const _lodash = require("lodash");
9+
async function display() {
10+
const displayA = await Promise.resolve().then(()=>/*#__PURE__*/ _interop_require_wildcard._(require("./inner/a/index.mjs"))).then((c)=>c.displayA);
11+
console.log(displayA());
12+
console.log((0, _b.displayB)());
13+
console.log((0, _c.displayC)());
14+
const foo = (0, _lodash.merge)({}, {
15+
a: 22
16+
});
17+
}
18+
display();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
"use strict";
2+
Object.defineProperty(exports, "__esModule", {
3+
value: true
4+
});
5+
Object.defineProperty(exports, "displayA", {
6+
enumerable: true,
7+
get: function() {
8+
return displayA;
9+
}
10+
});
11+
function displayA() {
12+
return 'Display A';
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
"use strict";
2+
Object.defineProperty(exports, "__esModule", {
3+
value: true
4+
});
5+
Object.defineProperty(exports, "displayB", {
6+
enumerable: true,
7+
get: function() {
8+
return displayB;
9+
}
10+
});
11+
function displayB() {
12+
return 'Display B';
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"jsc": {
3+
"parser": {
4+
"syntax": "typescript",
5+
"dynamicImport": true,
6+
},
7+
"target": "es2020",
8+
"baseUrl": ".",
9+
"paths": {
10+
"@print/c": ["./packages/c/src/index.js"],
11+
},
12+
"externalHelpers": true,
13+
},
14+
"module": {
15+
"type": "es6",
16+
"resolveFully": true,
17+
// This should say "resolve this fully to .mjs".
18+
// Normally should be paired with --out-file-extension in the cli
19+
"outFileExtension": "mjs",
20+
},
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Simulate accessing a .js file in a third party package that shouldn't be edited
2+
import something from 'lodash/dist/something.js'
3+
export function displayC(): string {
4+
something()
5+
return 'Display C'
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
2+
import { displayB } from './inner/b'
3+
import { displayC } from '@print/c'
4+
import { merge } from 'lodash'
5+
6+
async function display() {
7+
const displayA = await import('./inner/a').then(c => c.displayA)
8+
console.log(displayA())
9+
console.log(displayB())
10+
console.log(displayC())
11+
const foo = merge({}, { a: 22 })
12+
}
13+
14+
display()

0 commit comments

Comments
 (0)