Skip to content

Commit

Permalink
fix(minifier): compute void number as undefined (#6028)
Browse files Browse the repository at this point in the history
  • Loading branch information
Boshen committed Sep 24, 2024
1 parent 539751c commit e0a8959
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 22 deletions.
24 changes: 15 additions & 9 deletions crates/oxc_minifier/examples/minifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,29 @@ fn main() -> std::io::Result<()> {
let source_text = std::fs::read_to_string(path)?;
let source_type = SourceType::from_path(path).unwrap();

let printed = minify(&source_text, source_type, mangle);
let mut allocator = Allocator::default();
let printed = minify(&allocator, &source_text, source_type, mangle);
println!("{printed}");

if twice {
let printed2 = minify(&printed, source_type, mangle);
allocator.reset();
let printed2 = minify(&allocator, &printed, source_type, mangle);
println!("{printed2}");
println!("same = {}", printed == printed2);
}

Ok(())
}

fn minify(source_text: &str, source_type: SourceType, mangle: bool) -> String {
let allocator = Allocator::default();
let ret = Parser::new(&allocator, source_text, source_type).parse();
let program = allocator.alloc(ret.program);
let options = MinifierOptions { mangle, compress: CompressOptions::all_true() };
let ret = Minifier::new(options).build(&allocator, program);
CodeGenerator::new().with_mangler(ret.mangler).build(program).source_text
fn minify(
allocator: &Allocator,
source_text: &str,
source_type: SourceType,
mangle: bool,
) -> String {
let ret = Parser::new(allocator, source_text, source_type).parse();
let mut program = ret.program;
let options = MinifierOptions { mangle, compress: CompressOptions::default() };
let ret = Minifier::new(options).build(allocator, &mut program);
CodeGenerator::new().with_mangler(ret.mangler).build(&program).source_text
}
10 changes: 6 additions & 4 deletions crates/oxc_minifier/src/ast_passes/peephole_fold_constants.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{cmp::Ordering, mem};
use std::cmp::Ordering;

use num_bigint::BigInt;
use oxc_ast::ast::*;
Expand Down Expand Up @@ -105,12 +105,12 @@ impl<'a> PeepholeFoldConstants {
}

fn try_fold_unary_expression(
&self,
&mut self,
expr: &mut UnaryExpression<'a>,
ctx: &mut TraverseCtx<'a>,
) -> Option<Expression<'a>> {
match expr.operator {
UnaryOperator::Void => Self::try_reduce_void(expr, ctx),
UnaryOperator::Void => self.try_reduce_void(expr, ctx),
UnaryOperator::Typeof => self.try_fold_type_of(expr, ctx),
#[allow(clippy::float_cmp)]
UnaryOperator::LogicalNot => {
Expand All @@ -135,13 +135,15 @@ impl<'a> PeepholeFoldConstants {

/// `void 1` -> `void 0`
fn try_reduce_void(
&mut self,
expr: &mut UnaryExpression<'a>,
ctx: &mut TraverseCtx<'a>,
) -> Option<Expression<'a>> {
if (!expr.argument.is_number() || !expr.argument.is_number_0())
&& !expr.may_have_side_effects()
{
let _ = mem::replace(&mut expr.argument, ctx.ast.number_0());
expr.argument = ctx.ast.number_0();
self.changed = true;
}
None
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ impl<'a> Traverse<'a> for PeepholeSubstituteAlternateSyntax {
fn enter_variable_declaration(
&mut self,
decl: &mut VariableDeclaration<'a>,
_ctx: &mut TraverseCtx<'a>,
ctx: &mut TraverseCtx<'a>,
) {
for declarator in decl.declarations.iter_mut() {
self.compress_variable_declarator(declarator);
self.compress_variable_declarator(declarator, ctx);
}
}

Expand Down Expand Up @@ -247,11 +247,15 @@ impl<'a> PeepholeSubstituteAlternateSyntax {
}
}

fn compress_variable_declarator(&mut self, decl: &mut VariableDeclarator<'a>) {
fn compress_variable_declarator(
&mut self,
decl: &mut VariableDeclarator<'a>,
ctx: &mut TraverseCtx<'a>,
) {
if decl.kind.is_const() {
return;
}
if decl.init.as_ref().is_some_and(|init| init.is_undefined() || init.is_void_0()) {
if decl.init.as_ref().is_some_and(|init| ctx.is_expression_undefined(init)) {
decl.init = None;
self.changed = true;
}
Expand Down
11 changes: 7 additions & 4 deletions crates/oxc_minifier/src/node_util/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,13 @@ pub trait NodeUtil {
fn scopes(&self) -> &ScopeTree;

fn is_expression_undefined(&self, expr: &Expression) -> bool {
if let Expression::Identifier(ident) = expr {
return self.is_identifier_undefined(ident);
};
false
match expr {
Expression::Identifier(ident) if self.is_identifier_undefined(ident) => true,
Expression::UnaryExpression(e) if e.operator.is_void() && e.argument.is_number() => {
true
}
_ => false,
}
}

fn is_identifier_undefined(&self, ident: &IdentifierReference) -> bool {
Expand Down
6 changes: 5 additions & 1 deletion crates/oxc_syntax/src/operator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use oxc_allocator::CloneIn;
use oxc_ast_macros::ast;
use oxc_span::{cmp::ContentEq, hash::ContentHash};
#[cfg(feature = "serialize")]
use ::{serde::Serialize, tsify::Tsify};
use {serde::Serialize, tsify::Tsify};

use crate::precedence::{GetPrecedence, Precedence};

Expand Down Expand Up @@ -356,6 +356,10 @@ impl UnaryOperator {
matches!(self, Self::BitwiseNot)
}

pub fn is_void(self) -> bool {
matches!(self, Self::Void)
}

pub fn is_keyword(self) -> bool {
matches!(self, Self::Typeof | Self::Void | Self::Delete)
}
Expand Down

0 comments on commit e0a8959

Please sign in to comment.