Repository: swc-project/swc (rust)

Issue:
SWC minify and webpack DLL/Federation interoperability issues
### Describe the bug

Hi,

I found that in the default minification configuration, swc removes a bit more than it should. Please take a look at the attached playground...

There is a `specific_microfront` variable that was defined and it was left untouched as it should, but the assignment to this variable was removed. Currently, I've disabled the `compress.unused` configuration to overcome the issue.

### Input code

_No response_

### Config

_No response_

### Playground link

https://play.swc.rs/?version=1.3.66&code=H4sIAAAAAAAAA61XW2%2FbNhR%2BdoD8hxM91FLnWe82ggLrMqDACmzp3oJAYCQqZiKTLkklzQL99x1SpCTatJuiMwxYJs%2F1O1c9EQlqR0tWs7LYslKKWgqu1%2Bdn%2BXv7ySGtW15qJniawSvkOTzTux0pH38TQistyW5CO0taRQFPWamTqZDZEyoqCsdabEXVNlQVBVxC%2Bnp%2B1lPmkDiCvEQjCONU5pRr%2BZIPNu7IPU1Wnn60rShajrqrPRULoN92Qmq1mGiX9GvLJC0KdMjoNrb15J%2FJDi3Cw1myTFYw9RzPZpLqVnL4S4otU3RJmia9uc2WekN5iJIjjJ2lETvSZJk%2FC%2FlIpVpqlWTZGjr8ZojgrDs%2F69a9jfdUo3WDUO8hHn8pxY72RkbEL6%2BRzVMZmf7ZoG%2F8ivGIdIBk4dDJDO3sw4jVTf90m%2FY3qwEZSZVonmgawcZSzvRGimfg9BmupBQynX%2B2kiCZwy9OPj7ME6gEVcCFxjgypYFxGFJjObcAzWadUW%2Bfjznf8orWyFMZIheICSAeYMZZgLDaEEkt0cLeTWBmNaQXMXVfMhdpo8oI5WRrgE7QAtI2OnHHoql8DKJibgzf7dqqSgfid%2B9GxovLSxgtzGAf0%2BSjR8oaz0jD%2FiXGL6gJa2gFRAH6u8Ef0khKqhe4o5SPxEjyzPQGCFSsrqnEUuwVgjIak6OQO%2BNhat8E%2BRjLp9SwTGF2ccFSz%2BGfDVO%2Bkk3gNFYKaIF2KSxC9BpTxrQH6546P4tpqNKhFbz2NbCKFiheYO0tDPBoS5zG3CARWpitx%2B7VZYtJK0NEsQlGWpUrpr739H%2BW3rdLuDZsR4U%2BfG2pfPlxqQ9%2FG75ArH%2Fu%2B7N1xP39%2BU8%2BFW3jR31Vl6Tc0O9NhsJS2fHw2gVzJCLYhXgI1JTEn8VyzkH2qbKgjTxG7scNLR8Bi9xZjelnWs%2B%2B7dZ4e1q5BnZ51Jcbr%2B42cMh2kkCEqeuhYe3b5mtoyuHjHMrtDnzCjNQUq9m0COdXSngFu1abRsA4VhT26152duDn9u0e9kN0ajarVuCvF%2BFVI0hF8bomjaJ7d86zFaZB6NzRpDCeXn2jZYuu6jHtYskxiywkow%2FL0sz3sJL8JPS%2Fy5PbxUkb%2F2jI%2FdRA7MI9EAGhU9PfIKpatvSk2Os%2BPYxgX%2F2inugJ6F0ubY9nUXei9gy9moKMqu4eaKmnO84AbJBPsf68jWQW8p2q%2FgMLDis0pqk8kcNxdT%2F%2FCTvie79E57Llmm0pLrzbHdF2xXOLgosfhKwX4S4VBh%2B5f%2B%2BZr3reof3VAvuUVcHuWMP0Sz%2FZueC%2F4oTeCv7iY3ikQEb0%2BOEOetCk3LaKYxqJXWhwdXGJVhRUuV73IeSbxYZtz3Uzd7jMb3HywurNjGaXDonj20FvLy4HQFbe%2BC7bYx13BLxen2hJXXqk%2FP%2FnVNqriGkZgNnUzDsRKAH2NQpbfIOrC78388zsTndN2G9QgtJE6na3d%2FonNiAnw%2FcrHBwODdc4jg91R2DnefT1522vfSGikdfWQPyg9FgH6TLz3rL%2BD0uijNgDDwAA&config=H4sIAAAAAAAAA42VzY7bIBCA73mKyOcednuoVn2A3voMiMDgkGLGYsAba7Xv3jGxs0k9tnqymW9%2BYH7g43A8Nhcyzc%2FjB%2F%2FyoteJIN3XLKExZn1lSQOm02SS73PzbaEXmpDTgaCKPm%2BkyTq1kKsVfX95fZstmoBIsFjMss5H78bHmJ2ObYAHyeQR%2BwADhGfjiv4A9MoETRR1B7Sl4XZpn%2FygM%2FAXe0nJw5sgJe108q8vT0m4p4EVDHZ9AqLnw3B2SgcxS4F0Svg%2BgZzKo%2FyEGEDHHaI0KR8ztJAkxwZD0D2BGnQSvEw75bMQSiEmWDLYe3pWPFqfPUaOuaYWtFUGLQjIJzDZDyCZcSw2i4QBhPNUbOFU2ra27D%2FWMOhQuKICudaS8G4Fr2f0lJUrUUrhDW7k4Abn5K7ax6kEuaS4trugjxs1%2Bd%2FO5n7ast7veh8dT18eBc6jKp0yQjuNifdOyOyUGUjZS9VMYIuBKbNG2s6MN9JH3oIC57hXBNf07rM5S0Hz2AM6AXB9tZO66gbUfQo3%2BDQQO%2FgXnzLLDTZrdDqftymN3QnDToAO8hntjgKXIuM2TnxLXPttXqIFbg2wokqhCtaXAA9ARhXq1b%2FqDR4P9qjagKeva2K5MefvYVnUK7Tp0JaHl6DW8%2Faq%2FGi%2BlJYHZInYePq9GN4330AcHhzVB2raRFMdHT7%2FAoX%2FIggNBwAA

### Expected behavior

The assignment to an untouched variable shouldn't be removed

### Actual behavior

_No response_

### Version

1.3.66

### Additional context

_No response_

Pull request:
fix(es/minifier): Don't drop assignments to unused top-level variables
**Description:**


**Related issue:**

 - Closes #7568


Patch:
diff --git a/crates/swc_ecma_minifier/src/compress/optimize/unused.rs b/crates/swc_ecma_minifier/src/compress/optimize/unused.rs
index a6ae885f44..54ccfbad6c 100644
--- a/crates/swc_ecma_minifier/src/compress/optimize/unused.rs
+++ b/crates/swc_ecma_minifier/src/compress/optimize/unused.rs
@@ -711,6 +711,8 @@ impl Optimizer<'_> {
                             && var.usage_count == 0
                             && var.declared
                             && (!var.declared_as_fn_param || !used_arguments || self.ctx.in_strict)
+                            && (self.options.top_level()
+                                || i.span.ctxt != self.marks.top_level_ctxt)
                         {
                             report_change!(
                                 "unused: Dropping assignment to var '{}{:?}', which is never used",
diff --git a/crates/swc_ecma_minifier/src/lib.rs b/crates/swc_ecma_minifier/src/lib.rs
index 25887ced3a..ef2d1b67ea 100644
--- a/crates/swc_ecma_minifier/src/lib.rs
+++ b/crates/swc_ecma_minifier/src/lib.rs
@@ -100,6 +100,7 @@ pub fn optimize(
     let _timer = timer!("minify");
 
     let mut marks = Marks::new();
+    marks.top_level_ctxt = SyntaxContext::empty().apply_mark(extra.top_level_mark);
     marks.unresolved_mark = extra.unresolved_mark;
 
     debug_assert_valid(&n);
diff --git a/crates/swc_ecma_usage_analyzer/src/marks.rs b/crates/swc_ecma_usage_analyzer/src/marks.rs
index a98f6f3f76..a904f0db05 100644
--- a/crates/swc_ecma_usage_analyzer/src/marks.rs
+++ b/crates/swc_ecma_usage_analyzer/src/marks.rs
@@ -1,6 +1,6 @@
 #![allow(dead_code)]
 
-use swc_common::Mark;
+use swc_common::{Mark, SyntaxContext};
 
 #[derive(Debug, Clone, Copy)]
 pub struct Marks {
@@ -47,6 +47,8 @@ pub struct Marks {
     /// preserve the side effects.
     pub fake_block: Mark,
 
+    pub top_level_ctxt: SyntaxContext,
+
     pub unresolved_mark: Mark,
 }
 
@@ -66,6 +68,7 @@ impl Marks {
             noinline: m(),
             pure: m(),
             fake_block: m(),
+            top_level_ctxt: SyntaxContext::empty().apply_mark(m()),
             unresolved_mark: m(),
         }
     }


Test patch:
diff --git a/crates/swc_ecma_minifier/tests/fixture/issues/7568/1/input.js b/crates/swc_ecma_minifier/tests/fixture/issues/7568/1/input.js
new file mode 100644
index 0000000000..df45390ffb
--- /dev/null
+++ b/crates/swc_ecma_minifier/tests/fixture/issues/7568/1/input.js
@@ -0,0 +1,28 @@
+var specific_microfront;
+(function () { // webpackBootstrap
+    "use strict";
+    var __webpack_modules__ = ({
+
+
+
+    });
+    function __webpack_require__(moduleId) {
+        var module = __webpack_module_cache__[moduleId] = {
+            id: moduleId,
+            loaded: false,
+            exports: {}
+
+        };
+
+        __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+        module.loaded = true;
+        return module.exports;
+
+    }
+
+    var __webpack_exports__ = __webpack_require__("webpack/container/entry/specific_page");
+    specific_microfront = __webpack_exports__;
+
+
+})()
+    ;
\ No newline at end of file
diff --git a/crates/swc_ecma_minifier/tests/fixture/issues/7568/1/output.js b/crates/swc_ecma_minifier/tests/fixture/issues/7568/1/output.js
new file mode 100644
index 0000000000..1d5ab91068
--- /dev/null
+++ b/crates/swc_ecma_minifier/tests/fixture/issues/7568/1/output.js
@@ -0,0 +1,13 @@
+var specific_microfront;
+!function() {
+    "use strict";
+    var __webpack_modules__ = {};
+    specific_microfront = function __webpack_require__(moduleId) {
+        var module = __webpack_module_cache__[moduleId] = {
+            id: moduleId,
+            loaded: !1,
+            exports: {}
+        };
+        return __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__), module.loaded = !0, module.exports;
+    }("webpack/container/entry/specific_page");
+}();
diff --git a/crates/swc_ecma_minifier/tests/fixture/issues/7568/config.json b/crates/swc_ecma_minifier/tests/fixture/issues/7568/config.json
new file mode 100644
index 0000000000..50c2afa6ca
--- /dev/null
+++ b/crates/swc_ecma_minifier/tests/fixture/issues/7568/config.json
@@ -0,0 +1,5 @@
+{
+    "defaults": true,
+    "toplevel": false,
+    "passes": 0
+}