Skip to content

Commit 6b1ce09

Browse files
authored
fix(es/modules): Preserve order for ts import equals (#5215)
1 parent d693bbb commit 6b1ce09

File tree

12 files changed

+136
-61
lines changed

12 files changed

+136
-61
lines changed

crates/swc_ecma_transforms_module/src/common_js.rs

Lines changed: 75 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,21 @@ where
9393
fn visit_mut_module_items(&mut self, n: &mut Vec<ModuleItem>) {
9494
let import_interop = self.config.import_interop();
9595

96+
let mut module_map = Default::default();
97+
98+
let mut has_ts_import_equals = false;
99+
100+
// handle `import foo = require("mod")`
101+
n.iter_mut().for_each(|item| {
102+
if let ModuleItem::ModuleDecl(module_decl) = item {
103+
*item = self.handle_ts_import_equals(
104+
module_decl.take(),
105+
&mut module_map,
106+
&mut has_ts_import_equals,
107+
);
108+
}
109+
});
110+
96111
let mut strip = ModuleDeclStrip::new(self.const_var_kind);
97112
n.visit_mut_with(&mut strip);
98113

@@ -111,20 +126,21 @@ where
111126
..
112127
} = strip;
113128

129+
let has_module_decl = has_module_decl || has_ts_import_equals;
130+
114131
let is_export_assign = export_assign.is_some();
115132

116133
if has_module_decl && !import_interop.is_none() && !is_export_assign {
117134
stmts.push(define_es_module(self.exports()).into())
118135
}
119136

120-
let mut import_map = Default::default();
121137
let mut lazy_record = Default::default();
122138

123139
// `import` -> `require`
124140
// `export` -> `_export(exports, {});`
125141
stmts.extend(
126142
self.handle_import_export(
127-
&mut import_map,
143+
&mut module_map,
128144
&mut lazy_record,
129145
link,
130146
export,
@@ -157,7 +173,7 @@ where
157173
}
158174

159175
stmts.visit_mut_children_with(&mut ModuleRefRewriter {
160-
import_map,
176+
import_map: module_map,
161177
lazy_record,
162178
allow_top_level_this: self.config.allow_top_level_this,
163179
is_global_this: true,
@@ -268,17 +284,14 @@ where
268284
}
269285

270286
let mod_ident = private_ident!(local_name_for_src(&src));
271-
let raw_mod_ident = link_flag
272-
.need_raw_import()
273-
.then(|| private_ident!(local_name_for_src(&src)));
274287

275288
let mut decl_mod_ident = false;
276289

277290
link_specifier_set.reduce(
278291
import_map,
279292
&mut export_obj_prop_list,
280293
&mod_ident,
281-
&raw_mod_ident,
294+
&None,
282295
&mut decl_mod_ident,
283296
is_swc_default_helper || is_node_default,
284297
);
@@ -288,9 +301,6 @@ where
288301

289302
if is_lazy {
290303
lazy_record.insert(mod_ident.to_id());
291-
if let Some(raw_mod_ident) = &raw_mod_ident {
292-
lazy_record.insert(raw_mod_ident.to_id());
293-
}
294304
}
295305

296306
// require("mod");
@@ -304,21 +314,6 @@ where
304314
import_expr
305315
};
306316

307-
let import_assign = raw_mod_ident.map(|raw_mod_ident| {
308-
let import_expr = import_expr.clone();
309-
if is_lazy {
310-
Stmt::Decl(Decl::Fn(lazy_require(
311-
import_expr,
312-
raw_mod_ident,
313-
self.const_var_kind,
314-
)))
315-
} else {
316-
Stmt::Decl(Decl::Var(
317-
import_expr.into_var_decl(self.const_var_kind, raw_mod_ident.into()),
318-
))
319-
}
320-
});
321-
322317
// _exportStar(require("mod"), exports);
323318
let import_expr = if link_flag.export_star() {
324319
helper_expr!(export_star, "exportStar").as_call(
@@ -364,10 +359,6 @@ where
364359
)
365360
};
366361

367-
if let Some(import_assign) = import_assign {
368-
stmts.push(import_assign);
369-
}
370-
371362
stmts.push(stmt);
372363
} else {
373364
stmts.push(import_expr.into_stmt());
@@ -393,6 +384,61 @@ where
393384
export_stmts.into_iter().chain(stmts)
394385
}
395386

387+
fn handle_ts_import_equals(
388+
&self,
389+
module_decl: ModuleDecl,
390+
module_map: &mut ImportMap,
391+
has_ts_import_equals: &mut bool,
392+
) -> ModuleItem {
393+
if let ModuleDecl::TsImportEquals(TsImportEqualsDecl {
394+
span,
395+
declare: false,
396+
is_export,
397+
is_type_only: false,
398+
id,
399+
module_ref:
400+
TsModuleRef::TsExternalModuleRef(TsExternalModuleRef {
401+
expr:
402+
Str {
403+
span: src_span,
404+
value: src,
405+
..
406+
},
407+
..
408+
}),
409+
}) = module_decl
410+
{
411+
*has_ts_import_equals = true;
412+
413+
let require = self
414+
.resolver
415+
.make_require_call(self.unresolved_mark, src, src_span);
416+
417+
if is_export {
418+
// exports.foo = require("mod")
419+
module_map.insert(id.to_id(), (self.exports(), Some(id.sym.clone())));
420+
421+
let assign_expr = AssignExpr {
422+
span,
423+
op: op!("="),
424+
left: id.as_pat_or_expr(),
425+
right: Box::new(require),
426+
};
427+
428+
assign_expr.into_stmt()
429+
} else {
430+
// const foo = require("mod")
431+
let mut var_decl = require.into_var_decl(self.const_var_kind, id.into());
432+
var_decl.span = span;
433+
434+
Stmt::Decl(var_decl.into())
435+
}
436+
.into()
437+
} else {
438+
module_decl.into()
439+
}
440+
}
441+
396442
fn exports(&self) -> Ident {
397443
quote_ident!(DUMMY_SP.apply_mark(self.unresolved_mark), "exports")
398444
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
"use strict";
2-
const _foo = require("foo");
3-
module.exports = _foo;
2+
const foo = require("foo");
3+
module.exports = foo;

crates/swc_ecma_transforms_module/tests/fixture/common/cts-import-export/export-import/output.cts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,4 @@
22
Object.defineProperty(exports, "__esModule", {
33
value: true
44
});
5-
Object.defineProperty(exports, "foo", {
6-
enumerable: true,
7-
get: ()=>_foo
8-
});
9-
const _foo = require("foo");
5+
exports.foo = require("foo");

crates/swc_ecma_transforms_module/tests/fixture/common/cts-import-export/mixed/output.cts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Object.defineProperty(exports, "__esModule", {
33
value: true
44
});
5-
const _foo = require("foo");
6-
const _foo1 = /*#__PURE__*/ _interopRequireDefault(require("foo"));
7-
(0, _foo1.default)();
8-
_foo();
5+
const _foo = /*#__PURE__*/ _interopRequireDefault(require("foo"));
6+
const bar = require("foo");
7+
(0, _foo.default)();
8+
bar();
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import A = require("a"); // print a
2+
console.log(1);
3+
import B = require("b"); // print b
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
define([
2+
"require",
3+
"exports",
4+
"a",
5+
"b"
6+
], function(require, exports, _a, _b) {
7+
"use strict";
8+
Object.defineProperty(exports, "__esModule", {
9+
value: true
10+
});
11+
console.log(1);
12+
});
13+
// print b
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
"use strict";
2+
Object.defineProperty(exports, "__esModule", {
3+
value: true
4+
});
5+
const A = require("a"); // print a
6+
console.log(1);
7+
const B = require("b"); // print b
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
(function(global, factory) {
2+
if (typeof module === "object" && typeof module.exports === "object") factory(exports, require("a"), require("b"));
3+
else if (typeof define === "function" && define.amd) define([
4+
"exports",
5+
"a",
6+
"b"
7+
], factory);
8+
else if (global = typeof globalThis !== "undefined" ? globalThis : global || self) factory(global.input = {}, global.a, global.b);
9+
})(this, function(exports, _a, _b) {
10+
"use strict";
11+
Object.defineProperty(exports, "__esModule", {
12+
value: true
13+
});
14+
console.log(1);
15+
});
16+
// print b

crates/swc_ecma_transforms_module/tests/fixture/common/issue-4898/1/output.cts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
Object.defineProperty(exports, "__esModule", {
33
value: true
44
});
5-
const _assert = require("assert");
6-
_assert(true);
5+
const assert = require("assert");
6+
assert(true);

crates/swc_ecma_transforms_module/tests/fixture/common/issue-4898/2/output.cts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Object.defineProperty(exports, "__esModule", {
33
value: true
44
});
5-
const _assert = require("assert");
6-
const _assert1 = /*#__PURE__*/ _interopRequireDefault(require("assert"));
7-
_assert(true);
8-
(0, _assert1.default)(true);
5+
const _assert = /*#__PURE__*/ _interopRequireDefault(require("assert"));
6+
const assert = require("assert");
7+
assert(true);
8+
(0, _assert.default)(true);

crates/swc_ecma_transforms_module/tests/fixture/common/issue-5042/1/output.cts

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,9 @@
22
Object.defineProperty(exports, "__esModule", {
33
value: true
44
});
5-
function _export(target, all) {
6-
for(var name in all)Object.defineProperty(target, name, {
7-
enumerable: true,
8-
get: all[name]
9-
});
10-
}
11-
_export(exports, {
12-
"$": ()=>_jquery,
13-
jquery: ()=>_jquery
5+
Object.defineProperty(exports, "jquery", {
6+
enumerable: true,
7+
get: ()=>exports["$"]
148
});
15-
const _jquery = require("jquery");
16-
_jquery(".hello");
9+
exports["$"] = require("jquery");
10+
(0, exports["$"])(".hello");
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"use strict";
2-
const _foo = require("foo");
3-
_foo.bar = 1;
4-
_foo.bar = 2;
5-
module.exports = _foo;
2+
const foo = require("foo");
3+
foo.bar = 1;
4+
foo.bar = 2;
5+
module.exports = foo;

0 commit comments

Comments
 (0)