Skip to content

Commit

Permalink
feat(minifier): add Normalize ast pass (#8120)
Browse files Browse the repository at this point in the history
  • Loading branch information
Boshen committed Dec 26, 2024
1 parent fef0b25 commit 72d9967
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 12 deletions.
2 changes: 2 additions & 0 deletions crates/oxc_minifier/src/ast_passes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use oxc_traverse::{traverse_mut_with_ctx, ReusableTraverseCtx, Traverse, Travers

mod collapse_variable_declarations;
mod exploit_assigns;
mod normalize;
mod peephole_fold_constants;
mod peephole_minimize_conditions;
mod peephole_remove_dead_code;
Expand All @@ -14,6 +15,7 @@ mod statement_fusion;

pub use collapse_variable_declarations::CollapseVariableDeclarations;
pub use exploit_assigns::ExploitAssigns;
pub use normalize::Normalize;
pub use peephole_fold_constants::PeepholeFoldConstants;
pub use peephole_minimize_conditions::PeepholeMinimizeConditions;
pub use peephole_remove_dead_code::PeepholeRemoveDeadCode;
Expand Down
67 changes: 67 additions & 0 deletions crates/oxc_minifier/src/ast_passes/normalize.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
use oxc_ast::ast::*;
use oxc_syntax::scope::ScopeFlags;
use oxc_traverse::{traverse_mut_with_ctx, ReusableTraverseCtx, Traverse, TraverseCtx};

use crate::CompressorPass;

/// Normalize AST
///
/// Make subsequent AST passes easier to analyze:
///
/// * convert whiles to fors
///
/// <https://github.com/google/closure-compiler/blob/v20240609/src/com/google/javascript/jscomp/Normalize.java>
pub struct Normalize;

impl<'a> CompressorPass<'a> for Normalize {
fn build(&mut self, program: &mut Program<'a>, ctx: &mut ReusableTraverseCtx<'a>) {
traverse_mut_with_ctx(self, program, ctx);
}
}

impl<'a> Traverse<'a> for Normalize {
fn exit_statement(&mut self, stmt: &mut Statement<'a>, ctx: &mut TraverseCtx<'a>) {
if matches!(stmt, Statement::WhileStatement(_)) {
Self::convert_while_to_for(stmt, ctx);
}
}
}

impl<'a> Normalize {
pub fn new() -> Self {
Self
}

fn convert_while_to_for(stmt: &mut Statement<'a>, ctx: &mut TraverseCtx<'a>) {
let Statement::WhileStatement(while_stmt) = ctx.ast.move_statement(stmt) else { return };
let while_stmt = while_stmt.unbox();
let for_stmt = ctx.ast.alloc_for_statement_with_scope_id(
while_stmt.span,
None,
Some(while_stmt.test),
None,
while_stmt.body,
ctx.create_child_scope_of_current(ScopeFlags::empty()),
);
*stmt = Statement::ForStatement(for_stmt);
}
}

#[cfg(test)]
mod test {
use oxc_allocator::Allocator;

use crate::tester;

fn test(source_text: &str, expected: &str) {
let allocator = Allocator::default();
let mut pass = super::Normalize::new();
tester::test(&allocator, source_text, expected, &mut pass);
}

#[test]
fn test_while() {
// Verify while loops are converted to FOR loops.
test("while(c < b) foo()", "for(; c < b;) foo()");
}
}
5 changes: 3 additions & 2 deletions crates/oxc_minifier/src/compressor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use oxc_traverse::ReusableTraverseCtx;

use crate::{
ast_passes::{
CollapsePass, DeadCodeElimination, LatePeepholeOptimizations, PeepholeOptimizations,
RemoveSyntax,
CollapsePass, DeadCodeElimination, LatePeepholeOptimizations, Normalize,
PeepholeOptimizations, RemoveSyntax,
},
CompressOptions, CompressorPass,
};
Expand Down Expand Up @@ -35,6 +35,7 @@ impl<'a> Compressor<'a> {
) {
let mut ctx = ReusableTraverseCtx::new(scopes, symbols, self.allocator);
RemoveSyntax::new(self.options).build(program, &mut ctx);
Normalize::new().build(program, &mut ctx);
PeepholeOptimizations::new().build(program, &mut ctx);
CollapsePass::new().build(program, &mut ctx);
LatePeepholeOptimizations::new().run_in_loop(program, &mut ctx);
Expand Down
20 changes: 10 additions & 10 deletions tasks/minsize/minsize.snap
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,23 @@ Original | minified | minified | gzip | gzip | Fixture

173.90 kB | 61.52 kB | 59.82 kB | 19.54 kB | 19.33 kB | moment.js

287.63 kB | 92.47 kB | 90.07 kB | 32.30 kB | 31.95 kB | jquery.js
287.63 kB | 92.42 kB | 90.07 kB | 32.32 kB | 31.95 kB | jquery.js

342.15 kB | 121.36 kB | 118.14 kB | 44.67 kB | 44.37 kB | vue.js
342.15 kB | 121.31 kB | 118.14 kB | 44.69 kB | 44.37 kB | vue.js

544.10 kB | 73.32 kB | 72.48 kB | 26.13 kB | 26.20 kB | lodash.js
544.10 kB | 73.22 kB | 72.48 kB | 26.22 kB | 26.20 kB | lodash.js

555.77 kB | 275.77 kB | 270.13 kB | 91.12 kB | 90.80 kB | d3.js
555.77 kB | 275.67 kB | 270.13 kB | 91.19 kB | 90.80 kB | d3.js

1.01 MB | 466.38 kB | 458.89 kB | 126.72 kB | 126.71 kB | bundle.min.js
1.01 MB | 466.33 kB | 458.89 kB | 126.76 kB | 126.71 kB | bundle.min.js

1.25 MB | 660.41 kB | 646.76 kB | 163.99 kB | 163.73 kB | three.js
1.25 MB | 660.39 kB | 646.76 kB | 164.00 kB | 163.73 kB | three.js

2.14 MB | 740.08 kB | 724.14 kB | 181.34 kB | 181.07 kB | victory.js
2.14 MB | 739.97 kB | 724.14 kB | 181.42 kB | 181.07 kB | victory.js

3.20 MB | 1.02 MB | 1.01 MB | 332.26 kB | 331.56 kB | echarts.js
3.20 MB | 1.02 MB | 1.01 MB | 332.30 kB | 331.56 kB | echarts.js

6.69 MB | 2.39 MB | 2.31 MB | 495.65 kB | 488.28 kB | antd.js
6.69 MB | 2.39 MB | 2.31 MB | 495.67 kB | 488.28 kB | antd.js

10.95 MB | 3.54 MB | 3.49 MB | 909.94 kB | 915.50 kB | typescript.js
10.95 MB | 3.54 MB | 3.49 MB | 910.07 kB | 915.50 kB | typescript.js

0 comments on commit 72d9967

Please sign in to comment.