From 6b1ce09b6f59e53a750a71e447a148aedcef8468 Mon Sep 17 00:00:00 2001 From: magic-akari Date: Sat, 16 Jul 2022 15:09:06 +0800 Subject: [PATCH] fix(es/modules): Preserve order for ts import equals (#5215) --- .../src/common_js.rs | 104 +++++++++++++----- .../export-assign/output.cts | 4 +- .../export-import/output.cts | 6 +- .../common/cts-import-export/mixed/output.cts | 8 +- .../tests/fixture/common/issue-1686/input.ts | 3 + .../fixture/common/issue-1686/output.amd.ts | 13 +++ .../fixture/common/issue-1686/output.cts | 7 ++ .../fixture/common/issue-1686/output.umd.ts | 16 +++ .../fixture/common/issue-4898/1/output.cts | 4 +- .../fixture/common/issue-4898/2/output.cts | 8 +- .../fixture/common/issue-5042/1/output.cts | 16 +-- .../fixture/common/issue-5042/2/output.cts | 8 +- 12 files changed, 136 insertions(+), 61 deletions(-) create mode 100644 crates/swc_ecma_transforms_module/tests/fixture/common/issue-1686/input.ts create mode 100644 crates/swc_ecma_transforms_module/tests/fixture/common/issue-1686/output.amd.ts create mode 100644 crates/swc_ecma_transforms_module/tests/fixture/common/issue-1686/output.cts create mode 100644 crates/swc_ecma_transforms_module/tests/fixture/common/issue-1686/output.umd.ts diff --git a/crates/swc_ecma_transforms_module/src/common_js.rs b/crates/swc_ecma_transforms_module/src/common_js.rs index 5a07c80bfe7..273d9b2bbc6 100644 --- a/crates/swc_ecma_transforms_module/src/common_js.rs +++ b/crates/swc_ecma_transforms_module/src/common_js.rs @@ -93,6 +93,21 @@ where fn visit_mut_module_items(&mut self, n: &mut Vec) { let import_interop = self.config.import_interop(); + let mut module_map = Default::default(); + + let mut has_ts_import_equals = false; + + // handle `import foo = require("mod")` + n.iter_mut().for_each(|item| { + if let ModuleItem::ModuleDecl(module_decl) = item { + *item = self.handle_ts_import_equals( + module_decl.take(), + &mut module_map, + &mut has_ts_import_equals, + ); + } + }); + let mut strip = ModuleDeclStrip::new(self.const_var_kind); n.visit_mut_with(&mut strip); @@ -111,20 +126,21 @@ where .. } = strip; + let has_module_decl = has_module_decl || has_ts_import_equals; + let is_export_assign = export_assign.is_some(); if has_module_decl && !import_interop.is_none() && !is_export_assign { stmts.push(define_es_module(self.exports()).into()) } - let mut import_map = Default::default(); let mut lazy_record = Default::default(); // `import` -> `require` // `export` -> `_export(exports, {});` stmts.extend( self.handle_import_export( - &mut import_map, + &mut module_map, &mut lazy_record, link, export, @@ -157,7 +173,7 @@ where } stmts.visit_mut_children_with(&mut ModuleRefRewriter { - import_map, + import_map: module_map, lazy_record, allow_top_level_this: self.config.allow_top_level_this, is_global_this: true, @@ -268,9 +284,6 @@ where } let mod_ident = private_ident!(local_name_for_src(&src)); - let raw_mod_ident = link_flag - .need_raw_import() - .then(|| private_ident!(local_name_for_src(&src))); let mut decl_mod_ident = false; @@ -278,7 +291,7 @@ where import_map, &mut export_obj_prop_list, &mod_ident, - &raw_mod_ident, + &None, &mut decl_mod_ident, is_swc_default_helper || is_node_default, ); @@ -288,9 +301,6 @@ where if is_lazy { lazy_record.insert(mod_ident.to_id()); - if let Some(raw_mod_ident) = &raw_mod_ident { - lazy_record.insert(raw_mod_ident.to_id()); - } } // require("mod"); @@ -304,21 +314,6 @@ where import_expr }; - let import_assign = raw_mod_ident.map(|raw_mod_ident| { - let import_expr = import_expr.clone(); - if is_lazy { - Stmt::Decl(Decl::Fn(lazy_require( - import_expr, - raw_mod_ident, - self.const_var_kind, - ))) - } else { - Stmt::Decl(Decl::Var( - import_expr.into_var_decl(self.const_var_kind, raw_mod_ident.into()), - )) - } - }); - // _exportStar(require("mod"), exports); let import_expr = if link_flag.export_star() { helper_expr!(export_star, "exportStar").as_call( @@ -364,10 +359,6 @@ where ) }; - if let Some(import_assign) = import_assign { - stmts.push(import_assign); - } - stmts.push(stmt); } else { stmts.push(import_expr.into_stmt()); @@ -393,6 +384,61 @@ where export_stmts.into_iter().chain(stmts) } + fn handle_ts_import_equals( + &self, + module_decl: ModuleDecl, + module_map: &mut ImportMap, + has_ts_import_equals: &mut bool, + ) -> ModuleItem { + if let ModuleDecl::TsImportEquals(TsImportEqualsDecl { + span, + declare: false, + is_export, + is_type_only: false, + id, + module_ref: + TsModuleRef::TsExternalModuleRef(TsExternalModuleRef { + expr: + Str { + span: src_span, + value: src, + .. + }, + .. + }), + }) = module_decl + { + *has_ts_import_equals = true; + + let require = self + .resolver + .make_require_call(self.unresolved_mark, src, src_span); + + if is_export { + // exports.foo = require("mod") + module_map.insert(id.to_id(), (self.exports(), Some(id.sym.clone()))); + + let assign_expr = AssignExpr { + span, + op: op!("="), + left: id.as_pat_or_expr(), + right: Box::new(require), + }; + + assign_expr.into_stmt() + } else { + // const foo = require("mod") + let mut var_decl = require.into_var_decl(self.const_var_kind, id.into()); + var_decl.span = span; + + Stmt::Decl(var_decl.into()) + } + .into() + } else { + module_decl.into() + } + } + fn exports(&self) -> Ident { quote_ident!(DUMMY_SP.apply_mark(self.unresolved_mark), "exports") } diff --git a/crates/swc_ecma_transforms_module/tests/fixture/common/cts-import-export/export-assign/output.cts b/crates/swc_ecma_transforms_module/tests/fixture/common/cts-import-export/export-assign/output.cts index 28ca36aa1b0..e642ef8d7de 100644 --- a/crates/swc_ecma_transforms_module/tests/fixture/common/cts-import-export/export-assign/output.cts +++ b/crates/swc_ecma_transforms_module/tests/fixture/common/cts-import-export/export-assign/output.cts @@ -1,3 +1,3 @@ "use strict"; -const _foo = require("foo"); -module.exports = _foo; +const foo = require("foo"); +module.exports = foo; diff --git a/crates/swc_ecma_transforms_module/tests/fixture/common/cts-import-export/export-import/output.cts b/crates/swc_ecma_transforms_module/tests/fixture/common/cts-import-export/export-import/output.cts index b31a2b77f8a..6a27ca6eca4 100644 --- a/crates/swc_ecma_transforms_module/tests/fixture/common/cts-import-export/export-import/output.cts +++ b/crates/swc_ecma_transforms_module/tests/fixture/common/cts-import-export/export-import/output.cts @@ -2,8 +2,4 @@ Object.defineProperty(exports, "__esModule", { value: true }); -Object.defineProperty(exports, "foo", { - enumerable: true, - get: ()=>_foo -}); -const _foo = require("foo"); +exports.foo = require("foo"); diff --git a/crates/swc_ecma_transforms_module/tests/fixture/common/cts-import-export/mixed/output.cts b/crates/swc_ecma_transforms_module/tests/fixture/common/cts-import-export/mixed/output.cts index 33de747e437..f867ddcf19e 100644 --- a/crates/swc_ecma_transforms_module/tests/fixture/common/cts-import-export/mixed/output.cts +++ b/crates/swc_ecma_transforms_module/tests/fixture/common/cts-import-export/mixed/output.cts @@ -2,7 +2,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); -const _foo = require("foo"); -const _foo1 = /*#__PURE__*/ _interopRequireDefault(require("foo")); -(0, _foo1.default)(); -_foo(); +const _foo = /*#__PURE__*/ _interopRequireDefault(require("foo")); +const bar = require("foo"); +(0, _foo.default)(); +bar(); diff --git a/crates/swc_ecma_transforms_module/tests/fixture/common/issue-1686/input.ts b/crates/swc_ecma_transforms_module/tests/fixture/common/issue-1686/input.ts new file mode 100644 index 00000000000..d5f832752b8 --- /dev/null +++ b/crates/swc_ecma_transforms_module/tests/fixture/common/issue-1686/input.ts @@ -0,0 +1,3 @@ +import A = require("a"); // print a +console.log(1); +import B = require("b"); // print b diff --git a/crates/swc_ecma_transforms_module/tests/fixture/common/issue-1686/output.amd.ts b/crates/swc_ecma_transforms_module/tests/fixture/common/issue-1686/output.amd.ts new file mode 100644 index 00000000000..5ba04db2c54 --- /dev/null +++ b/crates/swc_ecma_transforms_module/tests/fixture/common/issue-1686/output.amd.ts @@ -0,0 +1,13 @@ +define([ + "require", + "exports", + "a", + "b" +], function(require, exports, _a, _b) { + "use strict"; + Object.defineProperty(exports, "__esModule", { + value: true + }); + console.log(1); +}); + // print b diff --git a/crates/swc_ecma_transforms_module/tests/fixture/common/issue-1686/output.cts b/crates/swc_ecma_transforms_module/tests/fixture/common/issue-1686/output.cts new file mode 100644 index 00000000000..e4f064b69bf --- /dev/null +++ b/crates/swc_ecma_transforms_module/tests/fixture/common/issue-1686/output.cts @@ -0,0 +1,7 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { + value: true +}); +const A = require("a"); // print a +console.log(1); +const B = require("b"); // print b diff --git a/crates/swc_ecma_transforms_module/tests/fixture/common/issue-1686/output.umd.ts b/crates/swc_ecma_transforms_module/tests/fixture/common/issue-1686/output.umd.ts new file mode 100644 index 00000000000..b6b3c11014e --- /dev/null +++ b/crates/swc_ecma_transforms_module/tests/fixture/common/issue-1686/output.umd.ts @@ -0,0 +1,16 @@ +(function(global, factory) { + if (typeof module === "object" && typeof module.exports === "object") factory(exports, require("a"), require("b")); + else if (typeof define === "function" && define.amd) define([ + "exports", + "a", + "b" + ], factory); + else if (global = typeof globalThis !== "undefined" ? globalThis : global || self) factory(global.input = {}, global.a, global.b); +})(this, function(exports, _a, _b) { + "use strict"; + Object.defineProperty(exports, "__esModule", { + value: true + }); + console.log(1); +}); + // print b diff --git a/crates/swc_ecma_transforms_module/tests/fixture/common/issue-4898/1/output.cts b/crates/swc_ecma_transforms_module/tests/fixture/common/issue-4898/1/output.cts index 919586ddab4..7981151b6ef 100644 --- a/crates/swc_ecma_transforms_module/tests/fixture/common/issue-4898/1/output.cts +++ b/crates/swc_ecma_transforms_module/tests/fixture/common/issue-4898/1/output.cts @@ -2,5 +2,5 @@ Object.defineProperty(exports, "__esModule", { value: true }); -const _assert = require("assert"); -_assert(true); +const assert = require("assert"); +assert(true); diff --git a/crates/swc_ecma_transforms_module/tests/fixture/common/issue-4898/2/output.cts b/crates/swc_ecma_transforms_module/tests/fixture/common/issue-4898/2/output.cts index 9f862929668..ea0cbd26c0d 100644 --- a/crates/swc_ecma_transforms_module/tests/fixture/common/issue-4898/2/output.cts +++ b/crates/swc_ecma_transforms_module/tests/fixture/common/issue-4898/2/output.cts @@ -2,7 +2,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); -const _assert = require("assert"); -const _assert1 = /*#__PURE__*/ _interopRequireDefault(require("assert")); -_assert(true); -(0, _assert1.default)(true); +const _assert = /*#__PURE__*/ _interopRequireDefault(require("assert")); +const assert = require("assert"); +assert(true); +(0, _assert.default)(true); diff --git a/crates/swc_ecma_transforms_module/tests/fixture/common/issue-5042/1/output.cts b/crates/swc_ecma_transforms_module/tests/fixture/common/issue-5042/1/output.cts index e98b67eac2e..07b49fd3c7a 100644 --- a/crates/swc_ecma_transforms_module/tests/fixture/common/issue-5042/1/output.cts +++ b/crates/swc_ecma_transforms_module/tests/fixture/common/issue-5042/1/output.cts @@ -2,15 +2,9 @@ Object.defineProperty(exports, "__esModule", { value: true }); -function _export(target, all) { - for(var name in all)Object.defineProperty(target, name, { - enumerable: true, - get: all[name] - }); -} -_export(exports, { - "$": ()=>_jquery, - jquery: ()=>_jquery +Object.defineProperty(exports, "jquery", { + enumerable: true, + get: ()=>exports["$"] }); -const _jquery = require("jquery"); -_jquery(".hello"); +exports["$"] = require("jquery"); +(0, exports["$"])(".hello"); diff --git a/crates/swc_ecma_transforms_module/tests/fixture/common/issue-5042/2/output.cts b/crates/swc_ecma_transforms_module/tests/fixture/common/issue-5042/2/output.cts index d317270e640..4cc5fe3da90 100644 --- a/crates/swc_ecma_transforms_module/tests/fixture/common/issue-5042/2/output.cts +++ b/crates/swc_ecma_transforms_module/tests/fixture/common/issue-5042/2/output.cts @@ -1,5 +1,5 @@ "use strict"; -const _foo = require("foo"); -_foo.bar = 1; -_foo.bar = 2; -module.exports = _foo; +const foo = require("foo"); +foo.bar = 1; +foo.bar = 2; +module.exports = foo;