Repository: swc-project/swc (rust)

Issue:
`drop_console ` option is invalid
**Describe the bug**
The last one was not discarded

**Input code**
```js
console.log('discarded');
console.log('Not discarded');
```

**Config**

```json
{
  "jsc": {
    "minify": {
      "compress": {
        "drop_console": true
      }
    }
  }
}
```

**Version**
The version of @swc/core: 1.2.92


![image](https://user-images.githubusercontent.com/2508421/135389412-b7c9aaa1-3395-49ff-b14e-88a27a7d6700.png)


https://swc.rs/repl#%7B%22rawCode%22%3A%22console.log('discarded')%3B%5Cnconsole.log('Not%20discarded')%3B%5Cn%22%2C%22rawConfig%22%3A%22%7B%5Cn%20%20%5C%22jsc%5C%22%3A%20%7B%5Cn%20%20%20%20%5C%22minify%5C%22%3A%20%7B%5Cn%20%20%20%20%20%20%5C%22compress%5C%22%3A%20%7B%5Cn%20%20%20%20%20%20%20%20%5C%22drop_console%5C%22%3A%20true%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%7D%5Cn%20%20%7D%5Cn%7D%5Cn%22%7D

Pull request description:
feat(es/minifier): Implement `drop_console`
swc_ecma_minifier:
 - Merge `drop_console` into pure optimizer.
 - Implement `drop_console`. (Closes #2321)

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 77d115b0bc..562abb9271 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,9 @@
 
 - **(es/minifier)** Fix evaluator (#3391) ([38c2499](https://github.com/swc-project/swc/commit/38c2499358e2dc4df5b6acee25da54fe411f6e8a))
 
+
+- **(es/modules)** Allow using dynamic import with a name from another import (#3390) ([1dcc188](https://github.com/swc-project/swc/commit/1dcc188dd8230954e2801f7c6e3034b0c0215bc4))
+
 ### Features
 
 
diff --git a/Cargo.lock b/Cargo.lock
index 92611d2d3b..c7801a7b91 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2652,7 +2652,7 @@ dependencies = [
 
 [[package]]
 name = "swc"
-version = "0.119.5"
+version = "0.119.6"
 dependencies = [
  "ahash",
  "anyhow",
@@ -3098,7 +3098,7 @@ dependencies = [
 
 [[package]]
 name = "swc_ecma_transforms"
-version = "0.114.2"
+version = "0.114.3"
 dependencies = [
  "pretty_assertions 0.7.2",
  "sourcemap",
@@ -3197,7 +3197,7 @@ dependencies = [
 
 [[package]]
 name = "swc_ecma_transforms_module"
-version = "0.75.0"
+version = "0.75.1"
 dependencies = [
  "Inflector",
  "ahash",
@@ -3367,7 +3367,7 @@ dependencies = [
 
 [[package]]
 name = "swc_ecmascript"
-version = "0.111.7"
+version = "0.111.8"
 dependencies = [
  "swc_ecma_ast",
  "swc_ecma_codegen",
diff --git a/crates/swc/Cargo.toml b/crates/swc/Cargo.toml
index 3ddc09fb7a..9f88bcd2c0 100644
--- a/crates/swc/Cargo.toml
+++ b/crates/swc/Cargo.toml
@@ -9,7 +9,7 @@ include = ["Cargo.toml", "src/**/*.rs"]
 license = "Apache-2.0"
 name = "swc"
 repository = "https://github.com/swc-project/swc.git"
-version = "0.119.5"
+version = "0.119.6"
 
 [lib]
 name = "swc"
@@ -55,7 +55,7 @@ swc_ecma_loader = {version = "0.28.0", path = "../swc_ecma_loader", features = [
 swc_ecma_minifier = {version = "0.71.3", path = "../swc_ecma_minifier"}
 swc_ecma_parser = {version = "0.87.0", path = "../swc_ecma_parser"}
 swc_ecma_preset_env = {version = "0.87.1", path = "../swc_ecma_preset_env"}
-swc_ecma_transforms = {version = "0.114.2", path = "../swc_ecma_transforms", features = [
+swc_ecma_transforms = {version = "0.114.3", path = "../swc_ecma_transforms", features = [
   "compat",
   "module",
   "optimization",
@@ -68,7 +68,7 @@ swc_ecma_transforms_compat = {version = "0.68.7", path = "../swc_ecma_transforms
 swc_ecma_transforms_optimization = {version = "0.84.0", path = "../swc_ecma_transforms_optimization"}
 swc_ecma_utils = {version = "0.64.0", path = "../swc_ecma_utils"}
 swc_ecma_visit = {version = "0.51.1", path = "../swc_ecma_visit"}
-swc_ecmascript = {version = "0.111.7", path = "../swc_ecmascript"}
+swc_ecmascript = {version = "0.111.8", path = "../swc_ecmascript"}
 swc_node_comments = {version = "0.4.0", path = "../swc_node_comments"}
 swc_plugin_runner = {version = "0.30.0", path = "../swc_plugin_runner", optional = true}
 swc_visit = {version = "0.3.0", path = "../swc_visit"}
diff --git a/crates/swc_ecma_minifier/src/compress/drop_console.rs b/crates/swc_ecma_minifier/src/compress/drop_console.rs
deleted file mode 100644
index 67f75d140e..0000000000
--- a/crates/swc_ecma_minifier/src/compress/drop_console.rs
+++ /dev/null
@@ -1,87 +0,0 @@
-use std::{borrow::Cow, mem::take};
-use swc_common::pass::CompilerPass;
-use swc_ecma_ast::*;
-use swc_ecma_transforms::pass::JsPass;
-use swc_ecma_visit::{as_folder, noop_visit_mut_type, VisitMut, VisitMutWith};
-
-pub fn drop_console() -> impl JsPass + VisitMut {
-    as_folder(DropConsole { done: false })
-}
-
-struct DropConsole {
-    /// Invoking this pass multiple times is simply waste of time.
-    done: bool,
-}
-
-impl CompilerPass for DropConsole {
-    fn name() -> Cow<'static, str> {
-        "drop-console".into()
-    }
-}
-
-impl VisitMut for DropConsole {
-    noop_visit_mut_type!();
-
-    fn visit_mut_expr(&mut self, n: &mut Expr) {
-        if self.done {
-            return;
-        }
-
-        n.visit_mut_children_with(self);
-
-        if let Expr::Call(CallExpr {
-            span, callee, args, ..
-        }) = n
-        {
-            // Find console.log
-            let callee = match callee {
-                Callee::Expr(callee) => callee,
-                _ => return,
-            };
-
-            if let Expr::Member(MemberExpr {
-                obj: callee_obj,
-                prop: MemberProp::Ident(_),
-                ..
-            }) = &**callee
-            {
-                let mut loop_co = &**callee_obj;
-                loop {
-                    match loop_co {
-                        Expr::Ident(obj) => {
-                            if obj.sym != *"console" {
-                                return;
-                            }
-                            break;
-                        }
-
-                        Expr::Member(MemberExpr {
-                            obj: loop_co_obj,
-                            prop: MemberProp::Ident(_),
-                            ..
-                        }) => {
-                            loop_co = loop_co_obj;
-                        }
-                        _ => return,
-                    }
-                }
-
-                // Simplifier will remove side-effect-free items.
-                *n = Expr::Seq(SeqExpr {
-                    span: *span,
-                    exprs: take(args).into_iter().map(|arg| arg.expr).collect(),
-                })
-            }
-        }
-    }
-
-    fn visit_mut_module(&mut self, n: &mut Module) {
-        if self.done {
-            return;
-        }
-
-        n.visit_mut_children_with(self);
-
-        self.done = true;
-    }
-}
diff --git a/crates/swc_ecma_minifier/src/compress/mod.rs b/crates/swc_ecma_minifier/src/compress/mod.rs
index 13180e0f72..f9813d490d 100644
--- a/crates/swc_ecma_minifier/src/compress/mod.rs
+++ b/crates/swc_ecma_minifier/src/compress/mod.rs
@@ -1,5 +1,5 @@
 pub(crate) use self::pure::pure_optimizer;
-use self::{drop_console::drop_console, hoist_decls::DeclHoisterConfig, optimize::optimizer};
+use self::{hoist_decls::DeclHoisterConfig, optimize::optimizer};
 use crate::{
     analyzer::{analyze, UsageAnalyzer},
     compress::hoist_decls::decl_hoister,
@@ -35,7 +35,6 @@ use swc_ecma_visit::{as_folder, noop_visit_mut_type, VisitMut, VisitMutWith, Vis
 use swc_timer::timer;
 use tracing::error;
 
-mod drop_console;
 mod hoist_decls;
 mod optimize;
 mod pure;
@@ -50,10 +49,6 @@ pub(crate) fn compressor<'a, M>(
 where
     M: Mode,
 {
-    let console_remover = Optional {
-        enabled: options.drop_console,
-        visitor: drop_console(),
-    };
     let compressor = Compressor {
         globals,
         marks,
@@ -66,9 +61,11 @@ where
     };
 
     chain!(
-        console_remover,
         as_folder(compressor),
-        expr_simplifier(ExprSimplifierConfig {})
+        Optional {
+            enabled: options.evaluate || options.side_effects,
+            visitor: expr_simplifier(ExprSimplifierConfig {})
+        }
     )
 }
 
diff --git a/crates/swc_ecma_minifier/src/compress/optimize/loops.rs b/crates/swc_ecma_minifier/src/compress/optimize/loops.rs
index 8aef3bad5f..6fccfc5e64 100644
--- a/crates/swc_ecma_minifier/src/compress/optimize/loops.rs
+++ b/crates/swc_ecma_minifier/src/compress/optimize/loops.rs
@@ -1,5 +1,5 @@
 use crate::{
-    compress::optimize::{unused::UnreachableHandler, Optimizer},
+    compress::{optimize::Optimizer, util::UnreachableHandler},
     mode::Mode,
 };
 use swc_common::{util::take::Take, DUMMY_SP};
diff --git a/crates/swc_ecma_minifier/src/compress/optimize/mod.rs b/crates/swc_ecma_minifier/src/compress/optimize/mod.rs
index c0c8f2c920..c5da8c17c1 100644
--- a/crates/swc_ecma_minifier/src/compress/optimize/mod.rs
+++ b/crates/swc_ecma_minifier/src/compress/optimize/mod.rs
@@ -2635,6 +2635,7 @@ where
                 Expr::Lit(Lit::Num(..)) => {}
 
                 _ => {
+                    tracing::debug!("Ignoring arg of `void`");
                     let arg = self.ignore_return_value(&mut n.arg);
 
                     n.arg = Box::new(arg.unwrap_or_else(|| make_number(DUMMY_SP, 0.0)));
diff --git a/crates/swc_ecma_minifier/src/compress/optimize/unused.rs b/crates/swc_ecma_minifier/src/compress/optimize/unused.rs
index 81f022d9eb..1218002017 100644
--- a/crates/swc_ecma_minifier/src/compress/optimize/unused.rs
+++ b/crates/swc_ecma_minifier/src/compress/optimize/unused.rs
@@ -7,7 +7,6 @@ use swc_atoms::js_word;
 use swc_common::{util::take::Take, Span, DUMMY_SP};
 use swc_ecma_ast::*;
 use swc_ecma_utils::{contains_ident_ref, ident::IdentLike};
-use swc_ecma_visit::{noop_visit_mut_type, VisitMut, VisitMutWith};
 
 /// Methods related to the option `unused`.
 impl<M> Optimizer<'_, M>
@@ -553,89 +552,3 @@ where
         }
     }
 }
-
-#[derive(Debug, Default)]
-pub(super) struct UnreachableHandler {
-    vars: Vec<Ident>,
-    in_var_name: bool,
-    in_hoisted_var: bool,
-}
-
-impl UnreachableHandler {
-    /// Assumes `s` is not reachable, and preserves variable declarations and
-    /// function declarations in `s`.
-    ///
-    /// Returns true if statement is changed.
-    pub fn preserve_vars(s: &mut Stmt) -> bool {
-        if s.is_empty() {
-            return false;
-        }
-        if let Stmt::Decl(Decl::Var(v)) = s {
-            let mut changed = false;
-            for decl in &mut v.decls {
-                if decl.init.is_some() {
-                    decl.init = None;
-                    changed = true;
-                }
-            }
-
-            return changed;
-        }
-
-        let mut v = Self::default();
-        s.visit_mut_with(&mut v);
-        if v.vars.is_empty() {
-            *s = Stmt::Empty(EmptyStmt { span: DUMMY_SP });
-        } else {
-            *s = Stmt::Decl(Decl::Var(VarDecl {
-                span: DUMMY_SP,
-                kind: VarDeclKind::Var,
-                declare: false,
-                decls: v
-                    .vars
-                    .into_iter()
-                    .map(BindingIdent::from)
-                    .map(Pat::Ident)
-                    .map(|name| VarDeclarator {
-                        span: DUMMY_SP,
-                        name,
-                        init: None,
-                        definite: false,
-                    })
-                    .collect(),
-            }))
-        }
-
-        true
-    }
-}
-
-impl VisitMut for UnreachableHandler {
-    noop_visit_mut_type!();
-
-    fn visit_mut_pat(&mut self, n: &mut Pat) {
-        n.visit_mut_children_with(self);
-
-        if self.in_var_name && self.in_hoisted_var {
-            if let Pat::Ident(i) = n {
-                self.vars.push(i.id.clone());
-            }
-        }
-    }
-
-    fn visit_mut_var_decl(&mut self, n: &mut VarDecl) {
-        self.in_hoisted_var = n.kind == VarDeclKind::Var;
-        n.visit_mut_children_with(self);
-    }
-
-    fn visit_mut_var_declarator(&mut self, n: &mut VarDeclarator) {
-        self.in_var_name = true;
-        n.name.visit_mut_with(self);
-        self.in_var_name = false;
-        n.init.visit_mut_with(self);
-    }
-
-    fn visit_mut_arrow_expr(&mut self, _: &mut ArrowExpr) {}
-
-    fn visit_mut_function(&mut self, _: &mut Function) {}
-}
diff --git a/crates/swc_ecma_minifier/src/compress/pure/dead_code.rs b/crates/swc_ecma_minifier/src/compress/pure/dead_code.rs
index 5e16b2b949..685392e13d 100644
--- a/crates/swc_ecma_minifier/src/compress/pure/dead_code.rs
+++ b/crates/swc_ecma_minifier/src/compress/pure/dead_code.rs
@@ -2,6 +2,7 @@ use super::Pure;
 use crate::{
     compress::util::{always_terminates, is_fine_for_if_cons},
     mode::Mode,
+    util::ModuleItemExt,
 };
 use swc_common::{util::take::Take, DUMMY_SP};
 use swc_ecma_ast::*;
@@ -12,6 +13,51 @@ impl<M> Pure<'_, M>
 where
     M: Mode,
 {
+    pub(super) fn drop_unreachable_stmts<T>(&mut self, stmts: &mut Vec<T>)
+    where
+        T: StmtLike + ModuleItemExt + Take,
+    {
+        if !self.options.side_effects {
+            return;
+        }
+
+        let idx = stmts
+            .iter()
+            .enumerate()
+            .find(|(_, stmt)| match stmt.as_stmt() {
+                Some(s) => always_terminates(s),
+                _ => false,
+            });
+
+        if let Some((idx, _)) = idx {
+            stmts.iter_mut().skip(idx + 1).for_each(|stmt| {
+                match stmt.as_stmt() {
+                    Some(Stmt::Decl(
+                        Decl::Var(VarDecl {
+                            kind: VarDeclKind::Var,
+                            ..
+                        })
+                        | Decl::Fn(..),
+                    )) => {
+                        // Preserve
+                    }
+
+                    Some(Stmt::Empty(..)) => {
+                        // noop
+                    }
+
+                    Some(..) => {
+                        tracing::debug!("Removing unreachable statements");
+                        self.changed = true;
+                        stmt.take();
+                    }
+
+                    _ => {}
+                }
+            });
+        }
+    }
+
     pub(super) fn drop_useless_blocks<T>(&mut self, stmts: &mut Vec<T>)
     where
         T: StmtLike,
@@ -115,52 +161,4 @@ where
 
         *stmts = new;
     }
-
-    pub(super) fn remove_unreachable_stmts<T>(&mut self, stmts: &mut Vec<T>)
-    where
-        T: StmtLike,
-    {
-        if !self.options.side_effects {
-            return;
-        }
-
-        let mut last = None;
-        let mut terminated = false;
-        for (idx, stmt) in stmts.iter().enumerate() {
-            match stmt.as_stmt() {
-                Some(stmt) if always_terminates(stmt) => {
-                    terminated = true;
-                }
-                _ => {
-                    if terminated {
-                        last = Some(idx);
-                        break;
-                    }
-                }
-            }
-        }
-
-        if let Some(last) = last {
-            if stmts[last..]
-                .iter()
-                .all(|stmt| matches!(stmt.as_stmt(), Some(Stmt::Decl(..)) | None))
-            {
-                return;
-            }
-
-            self.changed = true;
-            tracing::debug!("dead_code: Removing unreachable statements");
-
-            let extras = stmts.drain(last..).collect::<Vec<_>>();
-
-            for extra in extras {
-                match extra.as_stmt() {
-                    Some(Stmt::Decl(..)) | None => {
-                        stmts.push(extra);
-                    }
-                    _ => {}
-                }
-            }
-        }
-    }
 }
diff --git a/crates/swc_ecma_minifier/src/compress/pure/drop_console.rs b/crates/swc_ecma_minifier/src/compress/pure/drop_console.rs
new file mode 100644
index 0000000000..18636280f3
--- /dev/null
+++ b/crates/swc_ecma_minifier/src/compress/pure/drop_console.rs
@@ -0,0 +1,52 @@
+use super::Pure;
+use swc_common::DUMMY_SP;
+use swc_ecma_ast::*;
+use swc_ecma_utils::undefined;
+
+impl<M> Pure<'_, M> {
+    pub(super) fn drop_console(&mut self, e: &mut Expr) {
+        if !self.options.drop_console {
+            return;
+        }
+
+        if let Expr::Call(CallExpr { callee, .. }) = e {
+            // Find console.log
+            let callee = match callee {
+                Callee::Expr(callee) => callee,
+                _ => return,
+            };
+
+            if let Expr::Member(MemberExpr {
+                obj: callee_obj,
+                prop: MemberProp::Ident(_),
+                ..
+            }) = &**callee
+            {
+                let mut loop_co = &**callee_obj;
+                loop {
+                    match loop_co {
+                        Expr::Ident(obj) => {
+                            if obj.sym != *"console" {
+                                return;
+                            }
+                            break;
+                        }
+
+                        Expr::Member(MemberExpr {
+                            obj: loop_co_obj,
+                            prop: MemberProp::Ident(_),
+                            ..
+                        }) => {
+                            loop_co = loop_co_obj;
+                        }
+                        _ => return,
+                    }
+                }
+
+                tracing::debug!("drop_console: Removing console call");
+                self.changed = true;
+                *e = *undefined(DUMMY_SP);
+            }
+        }
+    }
+}
diff --git a/crates/swc_ecma_minifier/src/compress/pure/if_return.rs b/crates/swc_ecma_minifier/src/compress/pure/if_return.rs
index e062add5a5..825a168a06 100644
--- a/crates/swc_ecma_minifier/src/compress/pure/if_return.rs
+++ b/crates/swc_ecma_minifier/src/compress/pure/if_return.rs
@@ -1,43 +1,9 @@
 use super::Pure;
-use crate::compress::util::{always_terminates, is_fine_for_if_cons, negate};
+use crate::compress::util::{is_fine_for_if_cons, negate};
 use swc_common::{util::take::Take, DUMMY_SP};
 use swc_ecma_ast::*;
 
 impl<M> Pure<'_, M> {
-    pub(super) fn drop_unreachable_stmts(&mut self, stmts: &mut Vec<Stmt>) {
-        if !self.options.dead_code && !self.options.side_effects {
-            return;
-        }
-
-        let idx = stmts
-            .iter()
-            .enumerate()
-            .find(|(_, stmt)| always_terminates(stmt));
-
-        if let Some((idx, _)) = idx {
-            stmts.iter_mut().skip(idx + 1).for_each(|stmt| match stmt {
-                Stmt::Decl(
-                    Decl::Var(VarDecl {
-                        kind: VarDeclKind::Var,
-                        ..
-                    })
-                    | Decl::Fn(..),
-                ) => {
-                    // Preserve
-                }
-
-                Stmt::Empty(..) => {
-                    // noop
-                }
-
-                _ => {
-                    self.changed = true;
-                    stmt.take();
-                }
-            });
-        }
-    }
-
     /// # Input
     ///
     /// ```js
diff --git a/crates/swc_ecma_minifier/src/compress/pure/mod.rs b/crates/swc_ecma_minifier/src/compress/pure/mod.rs
index 768450df87..cff60c88e7 100644
--- a/crates/swc_ecma_minifier/src/compress/pure/mod.rs
+++ b/crates/swc_ecma_minifier/src/compress/pure/mod.rs
@@ -18,6 +18,7 @@ mod bools;
 mod conds;
 mod ctx;
 mod dead_code;
+mod drop_console;
 mod evaluate;
 mod if_return;
 mod loops;
@@ -75,14 +76,14 @@ where
 {
     fn handle_stmt_likes<T>(&mut self, stmts: &mut Vec<T>)
     where
-        T: ModuleItemExt,
+        T: ModuleItemExt + Take,
         Vec<T>: VisitWith<self::vars::VarWithOutInitCounter>
             + VisitMutWith<self::vars::VarPrepender>
             + VisitMutWith<self::vars::VarMover>,
     {
         self.remove_dead_branch(stmts);
 
-        self.remove_unreachable_stmts(stmts);
+        self.drop_unreachable_stmts(stmts);
 
         self.drop_useless_blocks(stmts);
 
@@ -92,8 +93,6 @@ where
     }
 
     fn optimize_fn_stmts(&mut self, stmts: &mut Vec<Stmt>) {
-        self.drop_unreachable_stmts(stmts);
-
         self.remove_useless_return(stmts);
 
         self.negate_if_terminate(stmts, true, false);
@@ -222,6 +221,10 @@ where
 
         self.remove_invalid(e);
 
+        self.drop_console(e);
+
+        self.remove_invalid(e);
+
         if let Expr::Seq(seq) = e {
             if seq.exprs.is_empty() {
                 *e = Expr::Invalid(Invalid { span: DUMMY_SP });
diff --git a/crates/swc_ecma_minifier/src/compress/util/mod.rs b/crates/swc_ecma_minifier/src/compress/util/mod.rs
index 8f4073c3d7..586d1322cc 100644
--- a/crates/swc_ecma_minifier/src/compress/util/mod.rs
+++ b/crates/swc_ecma_minifier/src/compress/util/mod.rs
@@ -620,3 +620,95 @@ where
         },
     });
 }
+
+#[derive(Debug, Default)]
+pub(super) struct UnreachableHandler {
+    vars: Vec<Ident>,
+    in_var_name: bool,
+    in_hoisted_var: bool,
+}
+
+impl UnreachableHandler {
+    /// Assumes `s` is not reachable, and preserves variable declarations and
+    /// function declarations in `s`.
+    ///
+    /// Returns true if statement is changed.
+    pub fn preserve_vars(s: &mut Stmt) -> bool {
+        if s.is_empty() {
+            return false;
+        }
+        if let Stmt::Decl(Decl::Var(v)) = s {
+            let mut changed = false;
+            for decl in &mut v.decls {
+                if decl.init.is_some() {
+                    decl.init = None;
+                    changed = true;
+                }
+            }
+
+            return changed;
+        }
+
+        let mut v = Self::default();
+        s.visit_mut_with(&mut v);
+        if v.vars.is_empty() {
+            *s = Stmt::Empty(EmptyStmt { span: DUMMY_SP });
+        } else {
+            *s = Stmt::Decl(Decl::Var(VarDecl {
+                span: DUMMY_SP,
+                kind: VarDeclKind::Var,
+                declare: false,
+                decls: v
+                    .vars
+                    .into_iter()
+                    .map(BindingIdent::from)
+                    .map(Pat::Ident)
+                    .map(|name| VarDeclarator {
+                        span: DUMMY_SP,
+                        name,
+                        init: None,
+                        definite: false,
+                    })
+                    .collect(),
+            }))
+        }
+
+        true
+    }
+}
+
+impl VisitMut for UnreachableHandler {
+    noop_visit_mut_type!();
+
+    fn visit_mut_arrow_expr(&mut self, _: &mut ArrowExpr) {}
+
+    fn visit_mut_fn_decl(&mut self, n: &mut FnDecl) {
+        self.vars.push(n.ident.clone());
+
+        n.function.visit_mut_with(self);
+    }
+
+    fn visit_mut_function(&mut self, _: &mut Function) {}
+
+    fn visit_mut_pat(&mut self, n: &mut Pat) {
+        n.visit_mut_children_with(self);
+
+        if self.in_var_name && self.in_hoisted_var {
+            if let Pat::Ident(i) = n {
+                self.vars.push(i.id.clone());
+            }
+        }
+    }
+
+    fn visit_mut_var_decl(&mut self, n: &mut VarDecl) {
+        self.in_hoisted_var = n.kind == VarDeclKind::Var;
+        n.visit_mut_children_with(self);
+    }
+
+    fn visit_mut_var_declarator(&mut self, n: &mut VarDeclarator) {
+        self.in_var_name = true;
+        n.name.visit_mut_with(self);
+        self.in_var_name = false;
+        n.init.visit_mut_with(self);
+    }
+}
diff --git a/crates/swc_ecma_transforms/Cargo.toml b/crates/swc_ecma_transforms/Cargo.toml
index 69f211caff..7ddc7ef213 100644
--- a/crates/swc_ecma_transforms/Cargo.toml
+++ b/crates/swc_ecma_transforms/Cargo.toml
@@ -6,7 +6,7 @@ edition = "2021"
 license = "Apache-2.0"
 name = "swc_ecma_transforms"
 repository = "https://github.com/swc-project/swc.git"
-version = "0.114.2"
+version = "0.114.3"
 
 [package.metadata.docs.rs]
 all-features = true
@@ -29,7 +29,7 @@ swc_ecma_ast = {version = "0.65.0", path = "../swc_ecma_ast"}
 swc_ecma_parser = {version = "0.87.0", path = "../swc_ecma_parser"}
 swc_ecma_transforms_base = {version = "0.57.1", path = "../swc_ecma_transforms_base"}
 swc_ecma_transforms_compat = {version = "0.68.7", path = "../swc_ecma_transforms_compat", optional = true}
-swc_ecma_transforms_module = {version = "0.75.0", path = "../swc_ecma_transforms_module", optional = true}
+swc_ecma_transforms_module = {version = "0.75.1", path = "../swc_ecma_transforms_module", optional = true}
 swc_ecma_transforms_optimization = {version = "0.84.0", path = "../swc_ecma_transforms_optimization", optional = true}
 swc_ecma_transforms_proposal = {version = "0.75.0", path = "../swc_ecma_transforms_proposal", optional = true}
 swc_ecma_transforms_react = {version = "0.77.0", path = "../swc_ecma_transforms_react", optional = true}
diff --git a/crates/swc_ecma_transforms_module/Cargo.toml b/crates/swc_ecma_transforms_module/Cargo.toml
index 6c4f5d9b61..dff948019e 100644
--- a/crates/swc_ecma_transforms_module/Cargo.toml
+++ b/crates/swc_ecma_transforms_module/Cargo.toml
@@ -6,7 +6,7 @@ edition = "2021"
 license = "Apache-2.0"
 name = "swc_ecma_transforms_module"
 repository = "https://github.com/swc-project/swc.git"
-version = "0.75.0"
+version = "0.75.1"
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [dependencies]
diff --git a/crates/swc_ecma_transforms_module/src/util.rs b/crates/swc_ecma_transforms_module/src/util.rs
index 4af62997a7..604ee1008b 100644
--- a/crates/swc_ecma_transforms_module/src/util.rs
+++ b/crates/swc_ecma_transforms_module/src/util.rs
@@ -506,13 +506,21 @@ impl Scope {
             Expr::Call(CallExpr {
                 span,
                 callee: Callee::Import(_),
-                args,
+                mut args,
                 ..
             }) if !folder.config().ignore_dynamic
                 // TODO: import assertion
                 && args.len() == 1 =>
             {
-                folder.make_dynamic_import(span, args)
+                let expr = match *(args.pop().unwrap().expr) {
+                    Expr::Ident(ident) => match Self::fold_ident(folder, ident) {
+                        Ok(expr) => expr,
+                        Err(ident) => Expr::Ident(ident),
+                    },
+                    expr => expr,
+                };
+
+                folder.make_dynamic_import(span, vec![expr.as_arg()])
             }
 
             Expr::Call(CallExpr {
diff --git a/crates/swc_ecmascript/Cargo.toml b/crates/swc_ecmascript/Cargo.toml
index e3c3f980bb..cd8b2c629c 100644
--- a/crates/swc_ecmascript/Cargo.toml
+++ b/crates/swc_ecmascript/Cargo.toml
@@ -6,7 +6,7 @@ edition = "2021"
 license = "Apache-2.0"
 name = "swc_ecmascript"
 repository = "https://github.com/swc-project/swc.git"
-version = "0.111.7"
+version = "0.111.8"
 
 [package.metadata.docs.rs]
 all-features = true
@@ -39,7 +39,7 @@ swc_ecma_dep_graph = {version = "0.58.0", path = "../swc_ecma_dep_graph", option
 swc_ecma_minifier = {version = "0.71.3", path = "../swc_ecma_minifier", optional = true}
 swc_ecma_parser = {version = "0.87.0", path = "../swc_ecma_parser", optional = true, default-features = false}
 swc_ecma_preset_env = {version = "0.87.1", path = "../swc_ecma_preset_env", optional = true}
-swc_ecma_transforms = {version = "0.114.2", path = "../swc_ecma_transforms", optional = true}
+swc_ecma_transforms = {version = "0.114.3", path = "../swc_ecma_transforms", optional = true}
 swc_ecma_utils = {version = "0.64.0", path = "../swc_ecma_utils", optional = true}
 swc_ecma_visit = {version = "0.51.1", path = "../swc_ecma_visit", optional = true}
 


Test patch:
diff --git a/crates/swc_ecma_minifier/tests/golden.txt b/crates/swc_ecma_minifier/tests/golden.txt
index 129b0936cc..41f2afa0c2 100644
--- a/crates/swc_ecma_minifier/tests/golden.txt
+++ b/crates/swc_ecma_minifier/tests/golden.txt
@@ -317,6 +317,8 @@ destructuring/unused_destructuring_object_method_param/input.js
 directives/class_directives_compression/input.js
 directives/simple_statement_is_not_a_directive/input.js
 drop_console/drop_console_1/input.js
+drop_console/drop_console_2/input.js
+drop_console/unexpected_side_effects_dropping_console/input.js
 drop_unused/assign_binding/input.js
 drop_unused/assign_chain/input.js
 drop_unused/cascade_drop_assign/input.js
@@ -737,6 +739,7 @@ labels/labels_5/input.js
 labels/labels_8/input.js
 logical_assignment/assign_in_conditional_part_reused/input.js
 logical_assignment/assignment_in_left_part/input.js
+logical_assignment/logical_assignment_not_always_happens/input.js
 logical_assignment/prematurely_evaluate_assignment/input.js
 logical_assignment/prematurely_evaluate_assignment_inv/input.js
 loops/dead_code_condition/input.js
diff --git a/crates/swc_ecma_minifier/tests/ignored.txt b/crates/swc_ecma_minifier/tests/ignored.txt
index bb54510797..dd08b2cce1 100644
--- a/crates/swc_ecma_minifier/tests/ignored.txt
+++ b/crates/swc_ecma_minifier/tests/ignored.txt
@@ -87,8 +87,6 @@ destructuring/issue_t111_2a/input.js
 destructuring/issue_t111_2b/input.js
 destructuring/issue_t111_2c/input.js
 destructuring/issue_t111_3/input.js
-drop_console/drop_console_2/input.js
-drop_console/unexpected_side_effects_dropping_console/input.js
 drop_unused/drop_toplevel_keep_assign/input.js
 drop_unused/global_var/input.js
 drop_unused/issue_1583/input.js
@@ -266,7 +264,6 @@ labels/labels_7/input.js
 labels/labels_9/input.js
 logical_assignment/assign_in_conditional_part/input.js
 logical_assignment/assignment_in_left_part_2/input.js
-logical_assignment/logical_assignment_not_always_happens/input.js
 loops/drop_if_break_3/input.js
 loops/drop_if_break_4/input.js
 loops/drop_if_else_break_1/input.js
diff --git a/crates/swc_ecma_minifier/tests/terser/compress/drop-console/drop_console_2/output.js b/crates/swc_ecma_minifier/tests/terser/compress/drop-console/drop_console_2/output.js
index d48a2162a7..e69de29bb2 100644
--- a/crates/swc_ecma_minifier/tests/terser/compress/drop-console/drop_console_2/output.js
+++ b/crates/swc_ecma_minifier/tests/terser/compress/drop-console/drop_console_2/output.js
@@ -1,2 +0,0 @@
-void 0;
-void 0;
diff --git a/crates/swc_ecma_transforms_module/tests/common_js.rs b/crates/swc_ecma_transforms_module/tests/common_js.rs
index 58e355c788..58e0253db1 100644
--- a/crates/swc_ecma_transforms_module/tests/common_js.rs
+++ b/crates/swc_ecma_transforms_module/tests/common_js.rs
@@ -4283,6 +4283,41 @@ test!(
   }
   "
 );
+test!(
+    syntax(),
+    |_| tr(Config {
+        ..Default::default()
+    }),
+    issue_3246_1,
+    "import { foo } from 'bar';
+
+    import(foo);
+    ",
+    r#""use strict";
+    var _bar = require("bar");
+    Promise.resolve().then(function() {
+        return _interopRequireWildcard(require(_bar.foo));
+    });
+    "#
+);
+
+test!(
+    syntax(),
+    |_| tr(Config {
+        ..Default::default()
+    }),
+    issue_3246_2,
+    "import foo from 'bar';
+
+  import(foo);
+  ",
+    r#""use strict";
+  var _bar = _interopRequireDefault(require("bar"));
+  Promise.resolve().then(function() {
+      return _interopRequireWildcard(require(_bar.default));
+  });
+  "#
+);
 
 test!(
     syntax(),