mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 12:19:15 +00:00
feat(minifier): add Normalize ast pass (#8120)
This commit is contained in:
parent
fef0b25fd3
commit
72d996709e
4 changed files with 82 additions and 12 deletions
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
67
crates/oxc_minifier/src/ast_passes/normalize.rs
Normal file
67
crates/oxc_minifier/src/ast_passes/normalize.rs
Normal file
|
|
@ -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,8 +5,8 @@ use oxc_traverse::ReusableTraverseCtx;
|
|||
|
||||
use crate::{
|
||||
ast_passes::{
|
||||
CollapsePass, DeadCodeElimination, LatePeepholeOptimizations, PeepholeOptimizations,
|
||||
RemoveSyntax,
|
||||
CollapsePass, DeadCodeElimination, LatePeepholeOptimizations, Normalize,
|
||||
PeepholeOptimizations, RemoveSyntax,
|
||||
},
|
||||
CompressOptions, CompressorPass,
|
||||
};
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue