From c2322b58cb927dc9a448fa415daafa3115d7e4a5 Mon Sep 17 00:00:00 2001 From: magic-akari Date: Thu, 1 Aug 2024 23:47:11 +0800 Subject: [PATCH 1/5] fix(es/typescript): Analyze import chain --- .../src/strip_import_export.rs | 39 +++++++++++++++++-- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/crates/swc_ecma_transforms_typescript/src/strip_import_export.rs b/crates/swc_ecma_transforms_typescript/src/strip_import_export.rs index f3952f07f18f..d61a47751496 100644 --- a/crates/swc_ecma_transforms_typescript/src/strip_import_export.rs +++ b/crates/swc_ecma_transforms_typescript/src/strip_import_export.rs @@ -1,6 +1,6 @@ use std::mem; -use swc_common::collections::AHashSet; +use swc_common::collections::{AHashMap, AHashSet}; use swc_ecma_ast::*; use swc_ecma_utils::stack_size::maybe_grow_default; use swc_ecma_visit::{noop_visit_type, Visit, VisitMut, VisitMutWith, VisitWith}; @@ -10,11 +10,15 @@ use crate::{strip_type::IsConcrete, ImportsNotUsedAsValues}; #[derive(Debug, Default)] struct UsageCollect { id_usage: AHashSet, + import_chain: AHashMap, } impl From> for UsageCollect { fn from(id_usage: AHashSet) -> Self { - Self { id_usage } + Self { + id_usage, + import_chain: Default::default(), + } } } @@ -68,7 +72,15 @@ impl Visit for UsageCollect { return; }; - get_module_ident(ts_entity_name).visit_with(self); + let id = get_module_ident(ts_entity_name); + + if n.is_export { + id.visit_with(self); + n.id.visit_with(self); + return; + } + + self.import_chain.insert(n.id.to_id(), id.to_id()); } fn visit_export_named_specifier(&mut self, n: &ExportNamedSpecifier) { @@ -101,6 +113,25 @@ impl UsageCollect { fn has_usage(&self, id: &Id) -> bool { self.id_usage.contains(id) } + + fn analyze_import_chain(&mut self) { + if self.import_chain.is_empty() { + return; + } + + let mut new_usage = AHashSet::default(); + for id in &self.id_usage { + let mut id = id.clone(); + while let Some(next) = self.import_chain.remove(&id) { + new_usage.insert(next.clone()); + id = next; + } + if self.import_chain.is_empty() { + break; + } + } + self.id_usage.extend(new_usage); + } } fn get_module_ident(ts_entity_name: &TsEntityName) -> &Ident { @@ -264,6 +295,8 @@ impl VisitMut for StripImportExport { n.visit_with(&mut usage_info); n.visit_with(&mut declare_info); + usage_info.analyze_import_chain(); + let mut strip_ts_import_equals = StripTsImportEquals; n.retain_mut(|module_item| match module_item { From bdd3d5123ed20b3649dbc08b7ca0acfe1c8e61cf Mon Sep 17 00:00:00 2001 From: magic-akari Date: Thu, 1 Aug 2024 23:52:24 +0800 Subject: [PATCH 2/5] chore: update test cases --- .../amdImportNotAsPrimaryExpression.1.normal.js | 5 ++--- ...amdImportNotAsPrimaryExpression.2.minified.js | 5 ++--- ...monJSImportNotAsPrimaryExpression.1.normal.js | 1 - ...nJSImportNotAsPrimaryExpression.2.minified.js | 2 +- .../importStatementsInterfaces.1.normal.js | 1 - .../importStatementsInterfaces.2.minified.js | 2 +- .../tests/strip.rs/deno_12395_import_equals_2.js | 1 - .../tests/fixture/issue-9368/input.ts | 16 ++++++++++++++++ .../tests/fixture/issue-9368/output.js | 6 ++++++ 9 files changed, 28 insertions(+), 11 deletions(-) create mode 100644 crates/swc_ecma_transforms_typescript/tests/fixture/issue-9368/input.ts create mode 100644 crates/swc_ecma_transforms_typescript/tests/fixture/issue-9368/output.js diff --git a/crates/swc/tests/tsc-references/amdImportNotAsPrimaryExpression.1.normal.js b/crates/swc/tests/tsc-references/amdImportNotAsPrimaryExpression.1.normal.js index 1b2eef9d1863..eb9f3745fec6 100644 --- a/crates/swc/tests/tsc-references/amdImportNotAsPrimaryExpression.1.normal.js +++ b/crates/swc/tests/tsc-references/amdImportNotAsPrimaryExpression.1.normal.js @@ -38,9 +38,8 @@ define([ //// [foo_1.ts] define([ "require", - "exports", - "./foo_0" -], function(require, exports, _foo_0) { + "exports" +], function(require, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true diff --git a/crates/swc/tests/tsc-references/amdImportNotAsPrimaryExpression.2.minified.js b/crates/swc/tests/tsc-references/amdImportNotAsPrimaryExpression.2.minified.js index 8ff118e13278..3ffcd4cf0324 100644 --- a/crates/swc/tests/tsc-references/amdImportNotAsPrimaryExpression.2.minified.js +++ b/crates/swc/tests/tsc-references/amdImportNotAsPrimaryExpression.2.minified.js @@ -27,9 +27,8 @@ define([ //// [foo_1.ts] define([ "require", - "exports", - "./foo_0" -], function(require, exports, _foo_0) { + "exports" +], function(require, exports) { Object.defineProperty(exports, "__esModule", { value: !0 }); diff --git a/crates/swc/tests/tsc-references/commonJSImportNotAsPrimaryExpression.1.normal.js b/crates/swc/tests/tsc-references/commonJSImportNotAsPrimaryExpression.1.normal.js index bbce10fcee7c..44d87fb2e67c 100644 --- a/crates/swc/tests/tsc-references/commonJSImportNotAsPrimaryExpression.1.normal.js +++ b/crates/swc/tests/tsc-references/commonJSImportNotAsPrimaryExpression.1.normal.js @@ -35,7 +35,6 @@ var E1; Object.defineProperty(exports, "__esModule", { value: true }); -var foo = require("./foo_0"); var i; var x = {}; var y = false; diff --git a/crates/swc/tests/tsc-references/commonJSImportNotAsPrimaryExpression.2.minified.js b/crates/swc/tests/tsc-references/commonJSImportNotAsPrimaryExpression.2.minified.js index c18d2b9820d4..3f12bb103c2b 100644 --- a/crates/swc/tests/tsc-references/commonJSImportNotAsPrimaryExpression.2.minified.js +++ b/crates/swc/tests/tsc-references/commonJSImportNotAsPrimaryExpression.2.minified.js @@ -21,4 +21,4 @@ C1.s1 = !0, (E1 = E11 || (E11 = {}))[E1.A = 0] = "A", E1[E1.B = 1] = "B", E1[E1. //// [foo_1.ts] Object.defineProperty(exports, "__esModule", { value: !0 -}), require("./foo_0"); +}); diff --git a/crates/swc/tests/tsc-references/importStatementsInterfaces.1.normal.js b/crates/swc/tests/tsc-references/importStatementsInterfaces.1.normal.js index 1ee46bc5ff32..99284a9839d2 100644 --- a/crates/swc/tests/tsc-references/importStatementsInterfaces.1.normal.js +++ b/crates/swc/tests/tsc-references/importStatementsInterfaces.1.normal.js @@ -2,7 +2,6 @@ var C; // no code gen expected (function(C) { - var a = A; var m; var p; var p = { diff --git a/crates/swc/tests/tsc-references/importStatementsInterfaces.2.minified.js b/crates/swc/tests/tsc-references/importStatementsInterfaces.2.minified.js index e5f6534008e4..4334d5daa9d8 100644 --- a/crates/swc/tests/tsc-references/importStatementsInterfaces.2.minified.js +++ b/crates/swc/tests/tsc-references/importStatementsInterfaces.2.minified.js @@ -1,5 +1,5 @@ //// [importStatementsInterfaces.ts] var C, D, E; -C || (C = {}), A, D || (D = {}), (E || (E = {})).xDist = function(x) { +C || (C = {}), D || (D = {}), (E || (E = {})).xDist = function(x) { return 0 - x.x; }; diff --git a/crates/swc_ecma_transforms_typescript/tests/__swc_snapshots__/tests/strip.rs/deno_12395_import_equals_2.js b/crates/swc_ecma_transforms_typescript/tests/__swc_snapshots__/tests/strip.rs/deno_12395_import_equals_2.js index 4a0913877086..c9be2f4ec727 100644 --- a/crates/swc_ecma_transforms_typescript/tests/__swc_snapshots__/tests/strip.rs/deno_12395_import_equals_2.js +++ b/crates/swc_ecma_transforms_typescript/tests/__swc_snapshots__/tests/strip.rs/deno_12395_import_equals_2.js @@ -1,2 +1 @@ -import * as mongo from 'https://deno.land/x/mongo@v0.27.0/mod.ts'; const mongoClient = {}; diff --git a/crates/swc_ecma_transforms_typescript/tests/fixture/issue-9368/input.ts b/crates/swc_ecma_transforms_typescript/tests/fixture/issue-9368/input.ts new file mode 100644 index 000000000000..30dbafb1bb4f --- /dev/null +++ b/crates/swc_ecma_transforms_typescript/tests/fixture/issue-9368/input.ts @@ -0,0 +1,16 @@ +import { Schemas } from './types.d'; +import AddressResource = Schemas.AddressResource; + +// type usage +const x: AddressResource = {}; + + +import { foo, bar } from "mod"; + +// value usage +import y = foo.y; + +// type usage +import z = bar.z; + +console.log(y as z); diff --git a/crates/swc_ecma_transforms_typescript/tests/fixture/issue-9368/output.js b/crates/swc_ecma_transforms_typescript/tests/fixture/issue-9368/output.js new file mode 100644 index 000000000000..bea8219de834 --- /dev/null +++ b/crates/swc_ecma_transforms_typescript/tests/fixture/issue-9368/output.js @@ -0,0 +1,6 @@ +// type usage +const x = {}; +import { foo } from "mod"; +// value usage +const y = foo.y; +console.log(y); From a4d19ea4f887195a26b5814d2d1b89de20951028 Mon Sep 17 00:00:00 2001 From: magic-akari Date: Fri, 2 Aug 2024 00:09:10 +0800 Subject: [PATCH 3/5] chore: avoid clone --- .../src/strip_import_export.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/swc_ecma_transforms_typescript/src/strip_import_export.rs b/crates/swc_ecma_transforms_typescript/src/strip_import_export.rs index d61a47751496..2ceff9ae8bfc 100644 --- a/crates/swc_ecma_transforms_typescript/src/strip_import_export.rs +++ b/crates/swc_ecma_transforms_typescript/src/strip_import_export.rs @@ -121,10 +121,10 @@ impl UsageCollect { let mut new_usage = AHashSet::default(); for id in &self.id_usage { - let mut id = id.clone(); - while let Some(next) = self.import_chain.remove(&id) { - new_usage.insert(next.clone()); - id = next; + let mut entry = self.import_chain.remove_entry(id); + while let Some((id, next)) = entry { + new_usage.insert(next); + entry = self.import_chain.remove_entry(&id); } if self.import_chain.is_empty() { break; From 2ab7fb6f09d3aca65686591fd83fe198c3c86f85 Mon Sep 17 00:00:00 2001 From: magic-akari Date: Fri, 2 Aug 2024 00:24:37 +0800 Subject: [PATCH 4/5] chore: Clear import chain in UsageCollect --- crates/swc_ecma_transforms_typescript/src/strip_import_export.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/swc_ecma_transforms_typescript/src/strip_import_export.rs b/crates/swc_ecma_transforms_typescript/src/strip_import_export.rs index 2ceff9ae8bfc..ab4eda550ae4 100644 --- a/crates/swc_ecma_transforms_typescript/src/strip_import_export.rs +++ b/crates/swc_ecma_transforms_typescript/src/strip_import_export.rs @@ -130,6 +130,7 @@ impl UsageCollect { break; } } + self.import_chain.clear(); self.id_usage.extend(new_usage); } } From 25624ead6f518d8722e3f1af53ec5d12f57ac6e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Donny/=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Fri, 2 Aug 2024 10:14:44 +0900 Subject: [PATCH 5/5] Create wicked-lizards-smoke.md --- .changeset/wicked-lizards-smoke.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/wicked-lizards-smoke.md diff --git a/.changeset/wicked-lizards-smoke.md b/.changeset/wicked-lizards-smoke.md new file mode 100644 index 000000000000..903ad056e9ef --- /dev/null +++ b/.changeset/wicked-lizards-smoke.md @@ -0,0 +1,5 @@ +--- +swc_ecma_transforms_typescript: patch +--- + +fix(es/typescript): Analyze import chain