diff --git a/crates/swc_ecma_minifier/src/compress/optimize/mod.rs b/crates/swc_ecma_minifier/src/compress/optimize/mod.rs index 68589dd964dc..8f3cd3d4a68a 100644 --- a/crates/swc_ecma_minifier/src/compress/optimize/mod.rs +++ b/crates/swc_ecma_minifier/src/compress/optimize/mod.rs @@ -1,4 +1,4 @@ -use std::{iter::once, mem::take}; +use std::iter::once; use rustc_hash::{FxHashMap, FxHashSet}; use swc_atoms::{js_word, JsWord}; @@ -19,7 +19,7 @@ use Value::Known; use self::{ unused::PropertyAccessOpts, - util::{extract_class_side_effect, Finalizer, NormalMultiReplacer}, + util::{extract_class_side_effect, Finalizer, NormalMultiReplacer, SynthesizedStmts}, }; use super::util::{drop_invalid_stmts, is_fine_for_if_cons}; #[cfg(feature = "debug")] @@ -1383,8 +1383,8 @@ where let mut old_prepend_stmts = self.prepend_stmts.take(); let old_append_stmts = self.append_stmts.take(); n.visit_mut_with(self); - old_prepend_stmts.append(&mut *self.prepend_stmts); - old_prepend_stmts.append(&mut *self.append_stmts); + old_prepend_stmts.append(&mut self.prepend_stmts); + old_prepend_stmts.append(&mut self.append_stmts); self.prepend_stmts = old_prepend_stmts; self.append_stmts = old_append_stmts; @@ -2423,11 +2423,15 @@ where // We use var decl with no declarator to indicate we dropped an decl. Stmt::Decl(Decl::Var(v)) if v.decls.is_empty() => { *s = Stmt::Empty(EmptyStmt { span: DUMMY_SP }); + self.prepend_stmts = old_prepend; + self.append_stmts = old_append; return; } Stmt::Expr(es) => { if es.expr.is_invalid() { *s = Stmt::Empty(EmptyStmt { span: DUMMY_SP }); + self.prepend_stmts = old_prepend; + self.append_stmts = old_append; return; } } @@ -2459,6 +2463,8 @@ where Stmt::Decl(Decl::Var(v)) if v.decls.is_empty() => { s.take(); if self.prepend_stmts.is_empty() && self.append_stmts.is_empty() { + self.prepend_stmts = old_prepend; + self.append_stmts = old_append; return; } } @@ -3062,42 +3068,3 @@ fn is_left_access_to_arguments(l: &PatOrExpr) -> bool { }, } } - -#[derive(Debug, Default, PartialEq, Eq)] -struct SynthesizedStmts(Vec); - -impl SynthesizedStmts { - fn take_stmts(&mut self) -> Vec { - take(&mut self.0) - } -} - -impl std::ops::Deref for SynthesizedStmts { - type Target = Vec; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl std::ops::DerefMut for SynthesizedStmts { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} - -impl Take for SynthesizedStmts { - fn dummy() -> Self { - Self(Take::dummy()) - } -} - -impl Drop for SynthesizedStmts { - fn drop(&mut self) { - if !self.0.is_empty() { - if !std::thread::panicking() { - panic!("We should not drop synthesized stmts"); - } - } - } -} diff --git a/crates/swc_ecma_minifier/src/compress/optimize/sequences.rs b/crates/swc_ecma_minifier/src/compress/optimize/sequences.rs index 50c46007a431..507420b407d4 100644 --- a/crates/swc_ecma_minifier/src/compress/optimize/sequences.rs +++ b/crates/swc_ecma_minifier/src/compress/optimize/sequences.rs @@ -492,7 +492,7 @@ where prepend_stmts(stmts, self.prepend_stmts.drain(..).map(T::from_stmt)); } - if self.append_stmts.is_empty() { + if !self.append_stmts.is_empty() { stmts.extend(self.append_stmts.drain(..).map(T::from_stmt)); } diff --git a/crates/swc_ecma_minifier/src/compress/optimize/unused.rs b/crates/swc_ecma_minifier/src/compress/optimize/unused.rs index 493c660f17e4..1aa13c5dcd9f 100644 --- a/crates/swc_ecma_minifier/src/compress/optimize/unused.rs +++ b/crates/swc_ecma_minifier/src/compress/optimize/unused.rs @@ -759,9 +759,14 @@ where for d in var.decls.iter_mut() { if d.init.is_none() { if let Pat::Ident(name) = &d.name { - if let Some(usage) = self.data.vars.get(&name.to_id()) { - if usage.is_fn_local && usage.declared_as_fn_param { + if let Some(usage) = self.data.vars.get_mut(&name.to_id()) { + if usage.is_fn_local + && usage.declared_as_fn_param + && usage.declared_count >= 2 + { d.name.take(); + usage.declared_count -= 1; + report_change!( "Removing a variable statement because it's a function parameter" ); diff --git a/crates/swc_ecma_minifier/src/compress/optimize/util.rs b/crates/swc_ecma_minifier/src/compress/optimize/util.rs index f53469b4f70a..17fb63d46853 100644 --- a/crates/swc_ecma_minifier/src/compress/optimize/util.rs +++ b/crates/swc_ecma_minifier/src/compress/optimize/util.rs @@ -1,4 +1,7 @@ -use std::ops::{Deref, DerefMut}; +use std::{ + mem::take, + ops::{Deref, DerefMut}, +}; use rustc_hash::{FxHashMap, FxHashSet}; use swc_atoms::js_word; @@ -532,3 +535,56 @@ impl VisitMut for ExprReplacer { } } } + +#[derive(Debug, Default, PartialEq, Eq)] +pub(super) struct SynthesizedStmts(Vec); + +impl SynthesizedStmts { + pub fn take_stmts(&mut self) -> Vec { + take(&mut self.0) + } +} + +impl std::ops::Deref for SynthesizedStmts { + type Target = Vec; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl SynthesizedStmts { + pub fn push(&mut self, stmt: Stmt) { + self.0.push(stmt); + } + + pub fn extend(&mut self, stmts: impl IntoIterator) { + self.0.extend(stmts); + } + + pub fn append(&mut self, other: &mut SynthesizedStmts) { + self.0.append(&mut other.0); + } +} + +impl std::ops::DerefMut for SynthesizedStmts { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl Take for SynthesizedStmts { + fn dummy() -> Self { + Self(Take::dummy()) + } +} + +impl Drop for SynthesizedStmts { + fn drop(&mut self) { + if !self.0.is_empty() { + if !std::thread::panicking() { + panic!("We should not drop synthesized stmts"); + } + } + } +} diff --git a/crates/swc_ecma_minifier/tests/fixture/next/tinymce/1/input.js b/crates/swc_ecma_minifier/tests/fixture/next/tinymce/1/input.js new file mode 100644 index 000000000000..6385f7b24f30 --- /dev/null +++ b/crates/swc_ecma_minifier/tests/fixture/next/tinymce/1/input.js @@ -0,0 +1,14 @@ +Yp.revoke, (a => Yp.config((b => ({ + aria: { + mode: "checked" + }, + ...ge(b, ((e, t) => "exclusive" !== t)), + onToggled: (c, d) => { + p(b.onToggled) && b.onToggled(c, d), ((e, f) => { + Or(e, th, { + item: e, + state: f + }) + })(c, d) + } +}))(a))) \ No newline at end of file diff --git a/crates/swc_ecma_minifier/tests/fixture/next/tinymce/1/output.js b/crates/swc_ecma_minifier/tests/fixture/next/tinymce/1/output.js new file mode 100644 index 000000000000..56cee54dcdde --- /dev/null +++ b/crates/swc_ecma_minifier/tests/fixture/next/tinymce/1/output.js @@ -0,0 +1,12 @@ +Yp.revoke, (a)=>Yp.config({ + aria: { + mode: "checked" + }, + ...ge(a, (e, t)=>"exclusive" !== t), + onToggled (c, d) { + p(a.onToggled) && a.onToggled(c, d), Or(c, th, { + item: c, + state: d + }); + } + });