diff --git a/.changeset/many-lobsters-knock.md b/.changeset/many-lobsters-knock.md new file mode 100644 index 00000000000..2a9704abcd1 --- /dev/null +++ b/.changeset/many-lobsters-knock.md @@ -0,0 +1,6 @@ +--- +swc_ecma_minifier: patch +swc_core: patch +--- + +fix(es/minifier): Force rename synthesized identifiers diff --git a/crates/swc_ecma_minifier/src/compress/pure/evaluate.rs b/crates/swc_ecma_minifier/src/compress/pure/evaluate.rs index 856c68a66c2..8ae04866645 100644 --- a/crates/swc_ecma_minifier/src/compress/pure/evaluate.rs +++ b/crates/swc_ecma_minifier/src/compress/pure/evaluate.rs @@ -2,11 +2,11 @@ use radix_fmt::Radix; use swc_common::{util::take::Take, Spanned, SyntaxContext}; use swc_ecma_ast::*; use swc_ecma_utils::{number::ToJsString, ExprExt, IsEmpty, Value}; -#[cfg(feature = "debug")] -use {crate::debug::dump, tracing::debug}; use super::Pure; use crate::compress::util::{eval_as_number, is_pure_undefined_or_null}; +#[cfg(feature = "debug")] +use crate::debug::dump; impl Pure<'_> { pub(super) fn eval_array_method_call(&mut self, e: &mut Expr) { @@ -659,21 +659,15 @@ impl Pure<'_> { _ => return, }; - #[cfg(feature = "debug")] - debug!( - "before: optimize_member_expr: {}", - dump(&*member_expr, false) - ); - if let Some(replacement) = self.optimize_member_expr(&mut member_expr.obj, &member_expr.prop) { *e = replacement; self.changed = true; - report_change!("member_expr: Optimized member expression"); - - #[cfg(feature = "debug")] - debug!("after: optimize_member_expr: {}", dump(&*e, false)); + report_change!( + "member_expr: Optimized member expression as {}", + dump(&*e, false) + ); } } diff --git a/crates/swc_ecma_minifier/src/lib.rs b/crates/swc_ecma_minifier/src/lib.rs index a792dd82fcd..d4bfdb92d71 100644 --- a/crates/swc_ecma_minifier/src/lib.rs +++ b/crates/swc_ecma_minifier/src/lib.rs @@ -232,7 +232,7 @@ pub fn optimize( let _timer = timer!("mangle names"); // TODO: base54.reset(); - let preserved = idents_to_preserve(mangle.clone(), &n); + let preserved = idents_to_preserve(mangle.clone(), marks, &n); let chars = CharFreq::compute( &n, diff --git a/crates/swc_ecma_minifier/src/pass/mangle_names/preserver.rs b/crates/swc_ecma_minifier/src/pass/mangle_names/preserver.rs index ac7984075e2..d68ab1602ba 100644 --- a/crates/swc_ecma_minifier/src/pass/mangle_names/preserver.rs +++ b/crates/swc_ecma_minifier/src/pass/mangle_names/preserver.rs @@ -1,26 +1,36 @@ use rustc_hash::FxHashSet; use swc_ecma_ast::*; +use swc_ecma_usage_analyzer::marks::Marks; use swc_ecma_utils::find_pat_ids; use swc_ecma_visit::{noop_visit_type, Visit, VisitWith}; use crate::option::MangleOptions; /// Returns `(preserved, unresolved)` -pub(crate) fn idents_to_preserve(options: MangleOptions, n: &N) -> FxHashSet +pub(crate) fn idents_to_preserve(options: MangleOptions, marks: Marks, n: &N) -> FxHashSet where - N: VisitWith, + N: for<'a> VisitWith>, { let mut v = Preserver { - options, + options: &options, preserved: Default::default(), should_preserve: false, in_top_level: false, }; n.visit_with(&mut v); + + let top_level_mark = marks.top_level_ctxt.outer(); + + // Force rename synthesized names + // See https://github.com/swc-project/swc/issues/9468 + v.preserved.retain(|id| { + options.reserved.contains(&id.0) || id.1.outer().is_descendant_of(top_level_mark) + }); + v.preserved } -pub(crate) struct Preserver { - options: MangleOptions, +pub(crate) struct Preserver<'a> { + options: &'a MangleOptions, preserved: FxHashSet, @@ -28,13 +38,13 @@ pub(crate) struct Preserver { in_top_level: bool, } -impl Preserver { +impl<'a> Preserver<'a> { fn is_reserved(&self, ident: &Ident) -> bool { self.options.reserved.contains(&ident.sym) } } -impl Visit for Preserver { +impl<'a> Visit for Preserver<'a> { noop_visit_type!(); fn visit_block_stmt(&mut self, n: &BlockStmt) { diff --git a/crates/swc_ecma_minifier/tests/fixture/issues/9468/input.js b/crates/swc_ecma_minifier/tests/fixture/issues/9468/input.js new file mode 100644 index 00000000000..d11e2ec4860 --- /dev/null +++ b/crates/swc_ecma_minifier/tests/fixture/issues/9468/input.js @@ -0,0 +1,10 @@ +function func1(arg1, arg2) { + return getX(arg1) + arg2 +} +function getX(x) { + const v = document.getElementById('eid').getAttribute(x) + return v +} +console.log(func1(7, getX('data-x'))) +console.log(func1(7, getX('data-y'))) + diff --git a/crates/swc_ecma_minifier/tests/fixture/issues/9468/mangle.json b/crates/swc_ecma_minifier/tests/fixture/issues/9468/mangle.json new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/crates/swc_ecma_minifier/tests/fixture/issues/9468/mangle.json @@ -0,0 +1 @@ +{} diff --git a/crates/swc_ecma_minifier/tests/fixture/issues/9468/output.js b/crates/swc_ecma_minifier/tests/fixture/issues/9468/output.js new file mode 100644 index 00000000000..dc5cf7aa1f0 --- /dev/null +++ b/crates/swc_ecma_minifier/tests/fixture/issues/9468/output.js @@ -0,0 +1,5 @@ +var t, e; +function getX(t) { + return document.getElementById('eid').getAttribute(t); +} +console.log((t = getX('data-x'), getX(7) + t)), console.log((e = getX('data-y'), getX(7) + e));