Skip to content

Commit

Permalink
feat(minifier): minify alternated one child if block
Browse files Browse the repository at this point in the history
  • Loading branch information
7086cmd committed Nov 10, 2024
1 parent f3f2f12 commit ef721fc
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 48 deletions.
92 changes: 56 additions & 36 deletions crates/oxc_minifier/src/ast_passes/peephole_minimize_conditions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,36 +91,57 @@ impl<'a> PeepholeMinimizeConditions {
) -> Option<Statement<'a>> {
if let Statement::ExpressionStatement(expr) = &mut if_stmt.consequent {
// The rest of things for known boolean are tasks for dce instead of here.
(if_stmt.alternate.is_none() && if_stmt.test.to_boolean().is_none()).then(|| {
// Make if (x) y; => x && y;
let (operator, mut test) = match &mut if_stmt.test {
Expression::UnaryExpression(unary) if unary.operator.is_not() => {
let arg = ctx.ast.move_expression(&mut unary.argument);
(LogicalOperator::Or, arg)
if_stmt
.test
.to_boolean()
.is_none()
.then(|| {
if !matches!(if_stmt.alternate, None | Some(Statement::ExpressionStatement(_))) {
return None
}
_ => (LogicalOperator::And, ctx.ast.move_expression(&mut if_stmt.test)),
};
match &mut test {
Expression::BinaryExpression(bin) if bin.operator.is_equality() => {
if !bin.left.is_literal() && bin.right.is_literal() {
test = ctx.ast.expression_binary(
SPAN,
ctx.ast.move_expression(&mut bin.right),
bin.operator,
ctx.ast.move_expression(&mut bin.left),
);
// Make if (x) y; => x && y;
let (reverse, mut test) = match &mut if_stmt.test {
Expression::UnaryExpression(unary) if unary.operator.is_not() => {
let arg = ctx.ast.move_expression(&mut unary.argument);
(true, arg)
}
_ => (false, ctx.ast.move_expression(&mut if_stmt.test)),
};
match &mut test {
Expression::BinaryExpression(bin) if bin.operator.is_equality() => {
if !bin.left.is_literal() && bin.right.is_literal() {
test = ctx.ast.expression_binary(
SPAN,
ctx.ast.move_expression(&mut bin.right),
bin.operator,
ctx.ast.move_expression(&mut bin.left),
);
}
}
_ => {}
}
if let Some(Statement::ExpressionStatement(alt)) = &mut if_stmt.alternate {
let left = ctx.ast.move_expression(&mut expr.expression);
let right = ctx.ast.move_expression(&mut alt.expression);
let cond = if reverse {
ctx.ast.expression_conditional(SPAN, test, right, left)
} else {
ctx.ast.expression_conditional(SPAN, test, left, right)
};
Some(ctx.ast.statement_expression(SPAN, cond))
} else if if_stmt.alternate.is_none() {
let new_expr = ctx.ast.expression_logical(
SPAN,
test,
if reverse { LogicalOperator::Or } else { LogicalOperator::And },
ctx.ast.move_expression(&mut expr.expression),
);
Some(ctx.ast.statement_expression(SPAN, new_expr))
} else {
None
}
_ => {}
}
let new_expr = ctx.ast.expression_logical(
SPAN,
test,
operator,
ctx.ast.move_expression(&mut expr.expression),
);
ctx.ast.statement_expression(SPAN, new_expr)
})
})
.unwrap_or(None)
} else {
None
}
Expand Down Expand Up @@ -168,7 +189,7 @@ mod test {

// Try it out with functions
fold("function f(){if(x){foo()}}", "function f(){x&&foo()}");
// fold("function f(){if(x){foo()}else{bar()}}", "function f(){x?foo():bar()}");
fold("function f(){if(x){foo()}else{bar()}}", "function f(){x?foo():bar()}");

// Try it out with properties and methods
fold("function f(){if(x){a.b=1}}", "function f(){x&&(a.b=1)}");
Expand All @@ -191,12 +212,12 @@ mod test {

// Play with nested IFs
fold("function f(){if(x){if(y)foo()}}", "function f(){x && (y && foo())}");
// fold("function f(){if(x){if(y)foo();else bar()}}", "function f(){x&&(y?foo():bar())}");
// fold("function f(){if(x){if(y)foo()}else bar()}", "function f(){x?y&&foo():bar()}");
// fold(
// "function f(){if(x){if(y)foo();else bar()}else{baz()}}",
// "function f(){x?y?foo():bar():baz()}",
// );
fold("function f(){if(x){if(y)foo();else bar()}}", "function f(){x&&(y?foo():bar())}");
fold("function f(){if(x){if(y)foo()}else bar()}", "function f(){x?y&&foo():bar()}");
fold(
"function f(){if(x){if(y)foo();else bar()}else{baz()}}",
"function f(){x?y?foo():bar():baz()}",
);

// fold("if(e1){while(e2){if(e3){foo()}}}else{bar()}", "if(e1)while(e2)e3&&foo();else bar()");

Expand Down Expand Up @@ -371,11 +392,10 @@ mod test {
}

#[test]
#[ignore]
fn test_not_cond() {
fold("function f(){if(!x)foo()}", "function f(){x||foo()}");
fold("function f(){if(!x)b=1}", "function f(){x||(b=1)}");
fold("if(!x)z=1;else if(y)z=2", "if(x){y&&(z=2);}else{z=1;}");
fold("if(!x)z=1;else if(y)z=2", "x ? y&&(z=2) : z=1;");
fold("if(x)y&&(z=2);else z=1;", "x ? y&&(z=2) : z=1");
fold("function f(){if(!(x=1))a.b=1}", "function f(){(x=1)||(a.b=1)}");
}
Expand Down
24 changes: 12 additions & 12 deletions tasks/minsize/minsize.snap
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
Original | Minified | esbuild | Gzip | esbuild

72.14 kB | 24.08 kB | 23.70 kB | 8.68 kB | 8.54 kB | react.development.js
72.14 kB | 24.00 kB | 23.70 kB | 8.67 kB | 8.54 kB | react.development.js

173.90 kB | 61.56 kB | 59.82 kB | 19.66 kB | 19.33 kB | moment.js
173.90 kB | 61.17 kB | 59.82 kB | 19.63 kB | 19.33 kB | moment.js

287.63 kB | 92.41 kB | 90.07 kB | 32.50 kB | 31.95 kB | jquery.js
287.63 kB | 91.79 kB | 90.07 kB | 32.41 kB | 31.95 kB | jquery.js

342.15 kB | 121.37 kB | 118.14 kB | 44.90 kB | 44.37 kB | vue.js
342.15 kB | 120.32 kB | 118.14 kB | 44.78 kB | 44.37 kB | vue.js

544.10 kB | 73.41 kB | 72.48 kB | 26.20 kB | 26.20 kB | lodash.js
544.10 kB | 73.04 kB | 72.48 kB | 26.17 kB | 26.20 kB | lodash.js

555.77 kB | 276.33 kB | 270.13 kB | 91.52 kB | 90.80 kB | d3.js
555.77 kB | 275.31 kB | 270.13 kB | 91.37 kB | 90.80 kB | d3.js

1.01 MB | 466.82 kB | 458.89 kB | 127.24 kB | 126.71 kB | bundle.min.js
1.01 MB | 465.00 kB | 458.89 kB | 127.13 kB | 126.71 kB | bundle.min.js

1.25 MB | 662.29 kB | 646.76 kB | 164.78 kB | 163.73 kB | three.js
1.25 MB | 660.57 kB | 646.76 kB | 164.64 kB | 163.73 kB | three.js

2.14 MB | 741.26 kB | 724.14 kB | 181.86 kB | 181.07 kB | victory.js
2.14 MB | 740.02 kB | 724.14 kB | 181.65 kB | 181.07 kB | victory.js

3.20 MB | 1.02 MB | 1.01 MB | 333.53 kB | 331.56 kB | echarts.js
3.20 MB | 1.02 MB | 1.01 MB | 333.18 kB | 331.56 kB | echarts.js

6.69 MB | 2.39 MB | 2.31 MB | 497.30 kB | 488.28 kB | antd.js
6.69 MB | 2.39 MB | 2.31 MB | 496.85 kB | 488.28 kB | antd.js

10.95 MB | 3.55 MB | 3.49 MB | 914.18 kB | 915.50 kB | typescript.js
10.95 MB | 3.55 MB | 3.49 MB | 913.86 kB | 915.50 kB | typescript.js

0 comments on commit ef721fc

Please sign in to comment.