feat(minifier): reenable minifier tests (#969)

This commit is contained in:
Boshen 2023-10-09 11:25:29 +08:00 committed by GitHub
parent 0fcad27515
commit 14e1dacd0a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 82 additions and 29 deletions

View file

@ -2,6 +2,7 @@
mod ast_util; mod ast_util;
mod fold; mod fold;
mod prepass;
mod util; mod util;
use oxc_allocator::{Allocator, Vec}; use oxc_allocator::{Allocator, Vec};
@ -14,6 +15,8 @@ use oxc_syntax::{
NumberBase, NumberBase,
}; };
use self::prepass::Prepass;
#[allow(clippy::struct_excessive_bools)] #[allow(clippy::struct_excessive_bools)]
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct CompressOptions { pub struct CompressOptions {
@ -70,16 +73,19 @@ impl Default for CompressOptions {
pub struct Compressor<'a> { pub struct Compressor<'a> {
ast: AstBuilder<'a>, ast: AstBuilder<'a>,
options: CompressOptions, options: CompressOptions,
prepass: Prepass<'a>,
} }
const SPAN: Span = Span::new(0, 0); const SPAN: Span = Span::new(0, 0);
impl<'a> Compressor<'a> { impl<'a> Compressor<'a> {
pub fn new(allocator: &'a Allocator, options: CompressOptions) -> Self { pub fn new(allocator: &'a Allocator, options: CompressOptions) -> Self {
Self { ast: AstBuilder::new(allocator), options } Self { ast: AstBuilder::new(allocator), options, prepass: Prepass::new(allocator) }
} }
pub fn build<'b>(mut self, program: &'b mut Program<'a>) { pub fn build<'b>(mut self, program: &'b mut Program<'a>) {
self.prepass.visit_program(program);
self.visit_program(program); self.visit_program(program);
} }
@ -208,16 +214,15 @@ impl<'a> Compressor<'a> {
/* Expressions */ /* Expressions */
/// Transforms `undefined` => `void 0` /// Transforms `undefined` => `void 0`
fn compress_undefined<'b>(&mut self, _expr: &'b mut Expression<'a>) -> bool { fn compress_undefined<'b>(&mut self, expr: &'b mut Expression<'a>) -> bool {
// let Expression::Identifier(ident) = expr else { return false }; let Expression::Identifier(ident) = expr else { return false };
// if let Some(reference_id) = ident.reference_id.clone().into_inner() { if ident.name == "undefined" {
// if ident.name == "undefined" // if let Some(reference_id) = ident.reference_id.clone().into_inner() {
// && self.semantic.symbols().is_global_reference(reference_id) // && self.semantic.symbols().is_global_reference(reference_id)
// { *expr = self.create_void_0();
// *expr = self.create_void_0(); return true;
// return true; // }
// } }
// }
false false
} }
@ -225,13 +230,13 @@ impl<'a> Compressor<'a> {
#[allow(unused)] #[allow(unused)]
fn compress_infinity<'b>(&mut self, expr: &'b mut Expression<'a>) -> bool { fn compress_infinity<'b>(&mut self, expr: &'b mut Expression<'a>) -> bool {
let Expression::Identifier(ident) = expr else { return false }; let Expression::Identifier(ident) = expr else { return false };
// if let Some(reference_id) = ident.reference_id.clone().into_inner() { if ident.name == "Infinity" {
// if ident.name == "Infinity" && self.semantic.symbols().is_global_reference(reference_id) // if let Some(reference_id) = ident.reference_id.clone().into_inner() {
// { //&& self.semantic.symbols().is_global_reference(reference_id)
// *expr = self.create_one_div_zero(); *expr = self.create_one_div_zero();
// return true; return true;
// } // }
// } }
false false
} }
@ -319,7 +324,18 @@ impl<'a> Compressor<'a> {
impl<'a, 'b> VisitMut<'a, 'b> for Compressor<'a> { impl<'a, 'b> VisitMut<'a, 'b> for Compressor<'a> {
fn visit_statements(&mut self, stmts: &'b mut Vec<'a, Statement<'a>>) { fn visit_statements(&mut self, stmts: &'b mut Vec<'a, Statement<'a>>) {
stmts.retain(|stmt| !(self.drop_debugger(stmt) || self.drop_console(stmt))); stmts.retain(|stmt| {
if matches!(stmt, Statement::EmptyStatement(_)) {
return false;
}
if self.drop_debugger(stmt) {
return false;
}
if self.drop_console(stmt) {
return false;
}
true
});
self.join_vars(stmts); self.join_vars(stmts);

View file

@ -0,0 +1,28 @@
use oxc_allocator::Allocator;
#[allow(clippy::wildcard_imports)]
use oxc_ast::{ast::*, AstBuilder, VisitMut};
pub struct Prepass<'a> {
ast: AstBuilder<'a>,
}
impl<'a> Prepass<'a> {
pub fn new(allocator: &'a Allocator) -> Self {
Self { ast: AstBuilder::new(allocator) }
}
fn strip_parenthesized_expression<'b>(&self, expr: &'b mut Expression<'a>) {
if let Expression::ParenthesizedExpression(paren_expr) = expr {
*expr = self.ast.move_expression(&mut paren_expr.expression);
self.strip_parenthesized_expression(expr);
}
}
}
impl<'a, 'b> VisitMut<'a, 'b> for Prepass<'a> {
fn visit_expression(&mut self, expr: &'b mut Expression<'a>) {
self.strip_parenthesized_expression(expr);
self.visit_expression_match(expr);
}
}

View file

@ -76,8 +76,9 @@ impl<'a> Gen for Statement<'a> {
Self::BreakStatement(stmt) => stmt.gen(p, ctx), Self::BreakStatement(stmt) => stmt.gen(p, ctx),
Self::ContinueStatement(stmt) => stmt.gen(p, ctx), Self::ContinueStatement(stmt) => stmt.gen(p, ctx),
Self::DebuggerStatement(stmt) => stmt.gen(p, ctx), Self::DebuggerStatement(stmt) => stmt.gen(p, ctx),
Self::Declaration(decl) => decl.gen(p, ctx),
Self::DoWhileStatement(stmt) => stmt.gen(p, ctx), Self::DoWhileStatement(stmt) => stmt.gen(p, ctx),
Self::EmptyStatement(decl) => {} Self::EmptyStatement(stmt) => stmt.gen(p, ctx),
Self::ExpressionStatement(stmt) => stmt.gen(p, ctx), Self::ExpressionStatement(stmt) => stmt.gen(p, ctx),
Self::ForInStatement(stmt) => stmt.gen(p, ctx), Self::ForInStatement(stmt) => stmt.gen(p, ctx),
Self::ForOfStatement(stmt) => stmt.gen(p, ctx), Self::ForOfStatement(stmt) => stmt.gen(p, ctx),
@ -91,7 +92,6 @@ impl<'a> Gen for Statement<'a> {
Self::TryStatement(stmt) => stmt.gen(p, ctx), Self::TryStatement(stmt) => stmt.gen(p, ctx),
Self::WhileStatement(stmt) => stmt.gen(p, ctx), Self::WhileStatement(stmt) => stmt.gen(p, ctx),
Self::WithStatement(stmt) => stmt.gen(p, ctx), Self::WithStatement(stmt) => stmt.gen(p, ctx),
Self::Declaration(decl) => decl.gen(p, ctx),
} }
} }
} }
@ -295,6 +295,12 @@ impl<'a> Gen for DoWhileStatement<'a> {
} }
} }
impl Gen for EmptyStatement {
fn gen(&self, p: &mut Printer, ctx: Context) {
p.print(b';');
}
}
impl Gen for ContinueStatement { impl Gen for ContinueStatement {
fn gen(&self, p: &mut Printer, ctx: Context) { fn gen(&self, p: &mut Printer, ctx: Context) {
p.print_str(b"continue"); p.print_str(b"continue");
@ -768,6 +774,9 @@ impl<'a> GenExpr for Expression<'a> {
Self::ClassExpression(expr) => expr.gen(p, ctx), Self::ClassExpression(expr) => expr.gen(p, ctx),
Self::JSXElement(el) => el.gen(p, ctx), Self::JSXElement(el) => el.gen(p, ctx),
Self::JSXFragment(fragment) => fragment.gen(p, ctx), Self::JSXFragment(fragment) => fragment.gen(p, ctx),
Self::ParenthesizedExpression(_) => {
panic!("The compressor mut strip this ParenthesizedExpression.")
}
_ => {} _ => {}
} }
} }

View file

@ -14,10 +14,10 @@ pub(crate) fn test(source_text: &str, expected: &str) {
test_with_options(source_text, expected, options); test_with_options(source_text, expected, options);
} }
pub(crate) fn test_with_options(source_text: &str, _expected: &str, options: MinifierOptions) { pub(crate) fn test_with_options(source_text: &str, expected: &str, options: MinifierOptions) {
let source_type = SourceType::default(); let source_type = SourceType::default();
let _minified = Minifier::new(source_text, source_type, options).build(); let minified = Minifier::new(source_text, source_type, options).build();
// assert_eq!(expected, minified, "for source {source_text}"); assert_eq!(expected, minified, "for source {source_text}");
} }
pub(crate) fn test_same(source_text: &str) { pub(crate) fn test_same(source_text: &str) {
@ -28,17 +28,17 @@ pub(crate) fn test_reparse(source_text: &str) {
let source_type = SourceType::default(); let source_type = SourceType::default();
let options = MinifierOptions { mangle: false, ..MinifierOptions::default() }; let options = MinifierOptions { mangle: false, ..MinifierOptions::default() };
let minified = Minifier::new(source_text, source_type, options).build(); let minified = Minifier::new(source_text, source_type, options).build();
let _minified2 = Minifier::new(&minified, source_type, options).build(); let minified2 = Minifier::new(&minified, source_type, options).build();
// assert_eq!(minified, minified2, "for source {source_text}"); assert_eq!(minified, minified2, "for source {source_text}");
} }
pub(crate) fn test_without_compress_booleans(source_text: &str, _expected: &str) { pub(crate) fn test_without_compress_booleans(source_text: &str, expected: &str) {
let source_type = SourceType::default(); let source_type = SourceType::default();
let compress_options = CompressOptions { booleans: false, ..CompressOptions::default() }; let compress_options = CompressOptions { booleans: false, ..CompressOptions::default() };
let options = let options =
MinifierOptions { mangle: false, compress: compress_options, print: PrinterOptions }; MinifierOptions { mangle: false, compress: compress_options, print: PrinterOptions };
let _minified = Minifier::new(source_text, source_type, options).build(); let minified = Minifier::new(source_text, source_type, options).build();
// assert_eq!(expected, minified, "for source {source_text}"); assert_eq!(expected, minified, "for source {source_text}");
} }
pub(crate) fn test_snapshot<S>(name: &str, sources: S) pub(crate) fn test_snapshot<S>(name: &str, sources: S)