mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 20:32:10 +00:00
feat(minifier): reenable minifier tests (#969)
This commit is contained in:
parent
0fcad27515
commit
14e1dacd0a
4 changed files with 82 additions and 29 deletions
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
28
crates/oxc_minifier/src/compressor/prepass.rs
Normal file
28
crates/oxc_minifier/src/compressor/prepass.rs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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.")
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue