Skip to content

Commit

Permalink
refactor(minifier): replace self.ast with ctx.ast (#5748)
Browse files Browse the repository at this point in the history
  • Loading branch information
Boshen committed Sep 13, 2024
1 parent 6bc13f6 commit 9a9d8f6
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 124 deletions.
23 changes: 11 additions & 12 deletions crates/oxc_minifier/src/ast_passes/collapse.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use oxc_allocator::Vec;
use oxc_ast::{ast::*, AstBuilder};
use oxc_ast::ast::*;
use oxc_traverse::{Traverse, TraverseCtx};

use crate::{CompressOptions, CompressorPass};
Expand All @@ -8,28 +8,27 @@ use crate::{CompressOptions, CompressorPass};
///
/// `var a; var b = 1; var c = 2` => `var a, b = 1; c = 2`
/// TODO: `a = null; b = null;` => `a = b = null`
pub struct Collapse<'a> {
ast: AstBuilder<'a>,
pub struct Collapse {
options: CompressOptions,
}

impl<'a> CompressorPass<'a> for Collapse<'a> {}
impl<'a> CompressorPass<'a> for Collapse {}

impl<'a> Traverse<'a> for Collapse<'a> {
fn enter_statements(&mut self, stmts: &mut Vec<'a, Statement<'a>>, _ctx: &mut TraverseCtx<'a>) {
impl<'a> Traverse<'a> for Collapse {
fn enter_statements(&mut self, stmts: &mut Vec<'a, Statement<'a>>, ctx: &mut TraverseCtx<'a>) {
if self.options.join_vars {
self.join_vars(stmts);
self.join_vars(stmts, ctx);
}
}
}

impl<'a> Collapse<'a> {
pub fn new(ast: AstBuilder<'a>, options: CompressOptions) -> Self {
Self { ast, options }
impl<'a> Collapse {
pub fn new(options: CompressOptions) -> Self {
Self { options }
}

/// Join consecutive var statements
fn join_vars(&mut self, stmts: &mut Vec<'a, Statement<'a>>) {
fn join_vars(&self, stmts: &mut Vec<'a, Statement<'a>>, ctx: &mut TraverseCtx<'a>) {
// Collect all the consecutive ranges that contain joinable vars.
// This is required because Rust prevents in-place vec mutation.
let mut ranges = vec![];
Expand Down Expand Up @@ -72,7 +71,7 @@ impl<'a> Collapse<'a> {
}

// Reconstruct the stmts array by joining consecutive ranges
let mut new_stmts = self.ast.vec_with_capacity(stmts.len() - capacity);
let mut new_stmts = ctx.ast.vec_with_capacity(stmts.len() - capacity);
for (i, stmt) in stmts.drain(..).enumerate() {
if i > 0 && ranges.iter().any(|range| range.contains(&(i - 1)) && range.contains(&i)) {
if let Statement::VariableDeclaration(prev_decl) = new_stmts.last_mut().unwrap() {
Expand Down
58 changes: 28 additions & 30 deletions crates/oxc_minifier/src/ast_passes/fold_constants.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::{cmp::Ordering, mem};

use num_bigint::BigInt;
use oxc_ast::{ast::*, AstBuilder};
use oxc_ast::ast::*;
use oxc_span::{GetSpan, Span, SPAN};
use oxc_syntax::{
number::NumberBase,
Expand All @@ -19,22 +19,21 @@ use crate::{
/// Constant Folding
///
/// <https://github.com/google/closure-compiler/blob/master/src/com/google/javascript/jscomp/PeepholeFoldConstants.java>
pub struct FoldConstants<'a> {
ast: AstBuilder<'a>,
pub struct FoldConstants {
evaluate: bool,
}

impl<'a> CompressorPass<'a> for FoldConstants<'a> {}
impl<'a> CompressorPass<'a> for FoldConstants {}

impl<'a> Traverse<'a> for FoldConstants<'a> {
impl<'a> Traverse<'a> for FoldConstants {
fn exit_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) {
self.fold_expression(expr, ctx);
}
}

impl<'a> FoldConstants<'a> {
pub fn new(ast: AstBuilder<'a>) -> Self {
Self { ast, evaluate: false }
impl<'a> FoldConstants {
pub fn new() -> Self {
Self { evaluate: false }
}

pub fn with_evaluate(mut self, yes: bool) -> Self {
Expand Down Expand Up @@ -110,7 +109,7 @@ impl<'a> FoldConstants<'a> {
UnaryOperator::Void => Self::try_reduce_void(expr, ctx),
UnaryOperator::Typeof => self.try_fold_type_of(expr, ctx),
UnaryOperator::LogicalNot => {
expr.argument.to_boolean().map(|b| self.ast.expression_boolean_literal(SPAN, !b))
expr.argument.to_boolean().map(|b| ctx.ast.expression_boolean_literal(SPAN, !b))
}
// `-NaN` -> `NaN`
UnaryOperator::UnaryNegation if expr.argument.is_nan() => {
Expand Down Expand Up @@ -161,7 +160,7 @@ impl<'a> FoldConstants<'a> {
Expression::Identifier(ident) if ctx.is_identifier_undefined(ident) => "undefined",
_ => return None,
};
Some(self.ast.expression_string_literal(SPAN, s))
Some(ctx.ast.expression_string_literal(SPAN, s))
}

fn try_fold_addition<'b>(
Expand Down Expand Up @@ -189,7 +188,7 @@ impl<'a> FoldConstants<'a> {
let right_string = ctx.get_string_value(right)?;
// let value = left_string.to_owned().
let value = left_string + right_string;
Some(self.ast.expression_string_literal(span, value))
Some(ctx.ast.expression_string_literal(span, value))
},

// number addition
Expand All @@ -202,7 +201,7 @@ impl<'a> FoldConstants<'a> {
// Float if value has a fractional part, otherwise Decimal
let number_base = if is_exact_int64(value) { NumberBase::Decimal } else { NumberBase::Float };
// todo: add raw &str
Some(self.ast.expression_numeric_literal(span, value, "", number_base))
Some(ctx.ast.expression_numeric_literal(span, value, "", number_base))
},
_ => None
}
Expand All @@ -221,7 +220,7 @@ impl<'a> FoldConstants<'a> {
Tri::False => false,
Tri::Unknown => return None,
};
Some(self.ast.expression_boolean_literal(span, value))
Some(ctx.ast.expression_boolean_literal(span, value))
}

fn evaluate_comparison<'b>(
Expand All @@ -235,9 +234,9 @@ impl<'a> FoldConstants<'a> {
return Tri::Unknown;
}
match op {
BinaryOperator::Equality => self.try_abstract_equality_comparison(left, right, ctx),
BinaryOperator::Equality => Self::try_abstract_equality_comparison(left, right, ctx),
BinaryOperator::Inequality => {
self.try_abstract_equality_comparison(left, right, ctx).not()
Self::try_abstract_equality_comparison(left, right, ctx).not()
}
BinaryOperator::StrictEquality => {
Self::try_strict_equality_comparison(left, right, ctx)
Expand All @@ -263,7 +262,6 @@ impl<'a> FoldConstants<'a> {

/// <https://tc39.es/ecma262/#sec-abstract-equality-comparison>
fn try_abstract_equality_comparison<'b>(
&self,
left_expr: &'b Expression<'a>,
right_expr: &'b Expression<'a>,
ctx: &mut TraverseCtx<'a>,
Expand All @@ -282,14 +280,14 @@ impl<'a> FoldConstants<'a> {
let right_number = ctx.get_side_free_number_value(right_expr);

if let Some(NumberValue::Number(num)) = right_number {
let number_literal_expr = self.ast.expression_numeric_literal(
let number_literal_expr = ctx.ast.expression_numeric_literal(
right_expr.span(),
num,
num.to_string(),
if num.fract() == 0.0 { NumberBase::Decimal } else { NumberBase::Float },
);

return self.try_abstract_equality_comparison(
return Self::try_abstract_equality_comparison(
left_expr,
&number_literal_expr,
ctx,
Expand All @@ -303,14 +301,14 @@ impl<'a> FoldConstants<'a> {
let left_number = ctx.get_side_free_number_value(left_expr);

if let Some(NumberValue::Number(num)) = left_number {
let number_literal_expr = self.ast.expression_numeric_literal(
let number_literal_expr = ctx.ast.expression_numeric_literal(
left_expr.span(),
num,
num.to_string(),
if num.fract() == 0.0 { NumberBase::Decimal } else { NumberBase::Float },
);

return self.try_abstract_equality_comparison(
return Self::try_abstract_equality_comparison(
&number_literal_expr,
right_expr,
ctx,
Expand Down Expand Up @@ -567,7 +565,7 @@ impl<'a> FoldConstants<'a> {
_ => unreachable!("Unknown binary operator {:?}", op),
};

return Some(self.ast.expression_numeric_literal(
return Some(ctx.ast.expression_numeric_literal(
span,
result_val,
result_val.to_string(),
Expand Down Expand Up @@ -607,7 +605,7 @@ impl<'a> FoldConstants<'a> {
// (TRUE || x) => TRUE (also, (3 || x) => 3)
// (FALSE && x) => FALSE
if if lval { op == LogicalOperator::Or } else { op == LogicalOperator::And } {
return Some(self.ast.move_expression(&mut logical_expr.left));
return Some(ctx.ast.move_expression(&mut logical_expr.left));
} else if !left.may_have_side_effects() {
let parent = ctx.ancestry.parent();
// Bail `let o = { f() { assert.ok(this !== o); } }; (true && o.f)(); (true && o.f)``;`
Expand All @@ -616,17 +614,17 @@ impl<'a> FoldConstants<'a> {
}
// (FALSE || x) => x
// (TRUE && x) => x
return Some(self.ast.move_expression(&mut logical_expr.right));
return Some(ctx.ast.move_expression(&mut logical_expr.right));
}
// Left side may have side effects, but we know its boolean value.
// e.g. true_with_sideeffects || foo() => true_with_sideeffects, foo()
// or: false_with_sideeffects && foo() => false_with_sideeffects, foo()
let left = self.ast.move_expression(&mut logical_expr.left);
let right = self.ast.move_expression(&mut logical_expr.right);
let mut vec = self.ast.vec_with_capacity(2);
let left = ctx.ast.move_expression(&mut logical_expr.left);
let right = ctx.ast.move_expression(&mut logical_expr.right);
let mut vec = ctx.ast.vec_with_capacity(2);
vec.push(left);
vec.push(right);
let sequence_expr = self.ast.expression_sequence(logical_expr.span, vec);
let sequence_expr = ctx.ast.expression_sequence(logical_expr.span, vec);
return Some(sequence_expr);
} else if let Expression::LogicalExpression(left_child) = &mut logical_expr.left {
if left_child.operator == logical_expr.operator {
Expand All @@ -639,9 +637,9 @@ impl<'a> FoldConstants<'a> {
if !right_boolean && left_child_op == LogicalOperator::Or
|| right_boolean && left_child_op == LogicalOperator::And
{
let left = self.ast.move_expression(&mut left_child.left);
let right = self.ast.move_expression(&mut logical_expr.right);
let logic_expr = self.ast.expression_logical(
let left = ctx.ast.move_expression(&mut left_child.left);
let right = ctx.ast.move_expression(&mut logical_expr.right);
let logic_expr = ctx.ast.expression_logical(
logical_expr.span,
left,
left_child_op,
Expand Down
30 changes: 16 additions & 14 deletions crates/oxc_minifier/src/ast_passes/minimize_conditions.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use oxc_ast::{ast::*, AstBuilder};
use oxc_ast::ast::*;
use oxc_traverse::{Traverse, TraverseCtx};

use crate::{node_util::NodeUtil, tri::Tri, CompressorPass};
Expand All @@ -10,27 +10,25 @@ use crate::{node_util::NodeUtil, tri::Tri, CompressorPass};
/// with `? :` and short-circuit binary operators.
///
/// <https://github.com/google/closure-compiler/blob/master/src/com/google/javascript/jscomp/PeepholeMinimizeConditions.java>
pub struct MinimizeConditions<'a> {
ast: AstBuilder<'a>,
}
pub struct MinimizeConditions;

impl<'a> CompressorPass<'a> for MinimizeConditions<'a> {}
impl<'a> CompressorPass<'a> for MinimizeConditions {}

impl<'a> Traverse<'a> for MinimizeConditions<'a> {
impl<'a> Traverse<'a> for MinimizeConditions {
fn exit_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) {
self.fold_expression(expr, ctx);
}
}

impl<'a> MinimizeConditions<'a> {
pub fn new(ast: AstBuilder<'a>) -> Self {
Self { ast }
impl<'a> MinimizeConditions {
pub fn new() -> Self {
Self
}

fn fold_expression(&self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) {
if let Some(folded_expr) = match expr {
Expression::ConditionalExpression(e) => self.try_fold_conditional_expression(e, ctx),
Expression::UnaryExpression(e) if e.operator.is_not() => self.try_minimize_not(e),
Expression::UnaryExpression(e) if e.operator.is_not() => self.try_minimize_not(e, ctx),
_ => None,
} {
*expr = folded_expr;
Expand All @@ -49,20 +47,24 @@ impl<'a> MinimizeConditions<'a> {
if parent.is_tagged_template_expression() || parent.is_call_expression() {
return None;
}
Some(self.ast.move_expression(&mut expr.consequent))
Some(ctx.ast.move_expression(&mut expr.consequent))
}
Tri::False => Some(self.ast.move_expression(&mut expr.alternate)),
Tri::False => Some(ctx.ast.move_expression(&mut expr.alternate)),
Tri::Unknown => None,
}
}

/// Try to minimize NOT nodes such as `!(x==y)`.
fn try_minimize_not(&self, expr: &mut UnaryExpression<'a>) -> Option<Expression<'a>> {
fn try_minimize_not(
&self,
expr: &mut UnaryExpression<'a>,
ctx: &mut TraverseCtx<'a>,
) -> Option<Expression<'a>> {
debug_assert!(expr.operator.is_not());
if let Expression::BinaryExpression(binary_expr) = &mut expr.argument {
if let Some(new_op) = binary_expr.operator.equality_inverse_operator() {
binary_expr.operator = new_op;
return Some(self.ast.move_expression(&mut expr.argument));
return Some(ctx.ast.move_expression(&mut expr.argument));
}
}
None
Expand Down
Loading

0 comments on commit 9a9d8f6

Please sign in to comment.