diff --git a/crates/oxc_minifier/src/ctx.rs b/crates/oxc_minifier/src/ctx.rs index b408d5407b778..e369ec8696028 100644 --- a/crates/oxc_minifier/src/ctx.rs +++ b/crates/oxc_minifier/src/ctx.rs @@ -6,6 +6,7 @@ use oxc_ecmascript::constant_evaluation::{ }; use oxc_ecmascript::side_effects::{MayHaveSideEffects, PropertyReadSideEffects}; use oxc_semantic::{IsGlobalReference, Scoping}; +use oxc_span::format_atom; use oxc_traverse::TraverseCtx; #[derive(Clone, Copy)] @@ -86,10 +87,13 @@ impl<'a> Ctx<'a, '_> { if is_exact_int64(n) { NumberBase::Decimal } else { NumberBase::Float }; self.ast.expression_numeric_literal(span, n, None, number_base) } - ConstantValue::BigInt(n) => { - self.ast.expression_big_int_literal(span, n.to_string() + "n", BigintBase::Decimal) + ConstantValue::BigInt(bigint) => { + let raw = format_atom!(self.ast.allocator, "{bigint}n"); + self.ast.expression_big_int_literal(span, raw, BigintBase::Decimal) + } + ConstantValue::String(s) => { + self.ast.expression_string_literal(span, self.ast.atom_from_cow(&s), None) } - ConstantValue::String(s) => self.ast.expression_string_literal(span, s, None), ConstantValue::Boolean(b) => self.ast.expression_boolean_literal(span, b), ConstantValue::Undefined => self.ast.void_0(span), ConstantValue::Null => self.ast.expression_null_literal(span), diff --git a/crates/oxc_minifier/src/peephole/fold_constants.rs b/crates/oxc_minifier/src/peephole/fold_constants.rs index 047311be086ee..de0f0fb7e3642 100644 --- a/crates/oxc_minifier/src/peephole/fold_constants.rs +++ b/crates/oxc_minifier/src/peephole/fold_constants.rs @@ -389,7 +389,7 @@ impl<'a> PeepholeOptimizations { e.right.get_side_free_string_value(&ctx), ) { let span = Span::new(left_binary_expr.right.span().start, e.right.span().end); - let value = left_str.into_owned() + &right_str; + let value = ctx.ast.atom_from_strs_array([&left_str, &right_str]); let right = ctx.ast.expression_string_literal(span, value, None); let left = left_binary_expr.left.take_in(ctx.ast.allocator); return Some(ctx.ast.expression_binary(e.span, left, e.operator, right)); diff --git a/crates/oxc_minifier/src/peephole/replace_known_methods.rs b/crates/oxc_minifier/src/peephole/replace_known_methods.rs index eeb40f0d3edec..9a63229b110d1 100644 --- a/crates/oxc_minifier/src/peephole/replace_known_methods.rs +++ b/crates/oxc_minifier/src/peephole/replace_known_methods.rs @@ -9,7 +9,7 @@ use oxc_ecmascript::{ constant_evaluation::{ConstantEvaluation, DetermineValueType}, side_effects::MayHaveSideEffects, }; -use oxc_span::SPAN; +use oxc_span::{Atom, SPAN, format_atom}; use oxc_syntax::es_target::ESTarget; use oxc_traverse::Ancestor; @@ -97,12 +97,14 @@ impl<'a> PeepholeOptimizations { return None; } let Expression::StringLiteral(s) = object else { return None }; + + let value = s.value.as_str(); let value = match name { - "toLowerCase" => s.value.cow_to_lowercase(), - "toUpperCase" => s.value.cow_to_uppercase(), - "trim" => Cow::Borrowed(s.value.trim()), - "trimStart" => Cow::Borrowed(s.value.trim_start()), - "trimEnd" => Cow::Borrowed(s.value.trim_end()), + "toLowerCase" => ctx.ast.atom_from_cow(&value.cow_to_lowercase()), + "toUpperCase" => ctx.ast.atom_from_cow(&value.cow_to_uppercase()), + "trim" => Atom::from(value.trim()), + "trimStart" => Atom::from(value.trim_start()), + "trimEnd" => Atom::from(value.trim_end()), _ => return None, }; Some(ctx.ast.expression_string_literal(span, value, None)) @@ -204,9 +206,9 @@ impl<'a> PeepholeOptimizations { None => None, }; let result = match s.value.as_str().char_at(char_at_index) { - StringCharAtResult::Value(c) => &c.to_string(), + StringCharAtResult::Value(c) => format_atom!(ctx.ast.allocator, "{c}"), StringCharAtResult::InvalidChar(_) => return None, - StringCharAtResult::OutOfRange => "", + StringCharAtResult::OutOfRange => Atom::empty(), }; Some(ctx.ast.expression_string_literal(span, result, None)) } @@ -267,7 +269,7 @@ impl<'a> PeepholeOptimizations { "replaceAll" => s.value.as_str().cow_replace(search_value.as_ref(), &replace_value), _ => unreachable!(), }; - Some(ctx.ast.expression_string_literal(span, result, None)) + Some(ctx.ast.expression_string_literal(span, ctx.ast.atom_from_cow(&result), None)) } #[expect(clippy::cast_possible_truncation, clippy::cast_sign_loss, clippy::cast_lossless)] @@ -352,7 +354,9 @@ impl<'a> PeepholeOptimizations { if args.is_empty() => { use oxc_ecmascript::ToJsString; - object.to_js_string(&ctx).map(|s| ctx.ast.expression_string_literal(span, s, None)) + object.to_js_string(&ctx).map(|s| { + ctx.ast.expression_string_literal(span, ctx.ast.atom_from_cow(&s), None) + }) } _ => None, } @@ -761,16 +765,13 @@ impl<'a> PeepholeOptimizations { debug_assert_eq!(quasi_strs.len(), 1); return Some(ctx.ast.expression_string_literal( span, - quasi_strs.pop().unwrap(), + ctx.ast.atom_from_cow(&quasi_strs.pop().unwrap()), None, )); } let mut quasis = ctx.ast.vec_from_iter(quasi_strs.into_iter().map(|s| { - let cooked = match &s { - Cow::Owned(s) => ctx.ast.atom(s), - Cow::Borrowed(s) => Atom::from(*s), - }; + let cooked = ctx.ast.atom_from_cow(&s); ctx.ast.template_element( SPAN, TemplateElementValue { diff --git a/crates/oxc_minifier/src/peephole/substitute_alternate_syntax.rs b/crates/oxc_minifier/src/peephole/substitute_alternate_syntax.rs index 146a0af1f2a81..1551c7ea894a8 100644 --- a/crates/oxc_minifier/src/peephole/substitute_alternate_syntax.rs +++ b/crates/oxc_minifier/src/peephole/substitute_alternate_syntax.rs @@ -77,7 +77,10 @@ impl<'a> PeepholeOptimizations { if prop_name == binding_identifier.name { *prop = ctx.ast.assignment_target_property_assignment_target_property_identifier( assign_target_prop_prop.span, - ctx.ast.identifier_reference(assign_target_prop_prop.span, prop_name), + ctx.ast.identifier_reference( + assign_target_prop_prop.span, + binding_identifier.name, + ), None, ); state.changed = true; @@ -895,8 +898,13 @@ impl<'a> PeepholeOptimizations { } } - fn try_fold_template_literal(t: &TemplateLiteral, ctx: Ctx<'a, '_>) -> Option> { - t.to_js_string(&ctx).map(|val| ctx.ast.expression_string_literal(t.span(), val, None)) + fn try_fold_template_literal( + t: &TemplateLiteral<'a>, + ctx: Ctx<'a, '_>, + ) -> Option> { + t.to_js_string(&ctx).map(|val| { + ctx.ast.expression_string_literal(t.span(), ctx.ast.atom_from_cow(&val), None) + }) } //