Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,41 +1,27 @@
use oxc_allocator::Vec;
use oxc_ast::ast::*;
use oxc_traverse::{traverse_mut_with_ctx, ReusableTraverseCtx, Traverse, TraverseCtx};

use crate::CompressorPass;

/// Collapse variable declarations.
///
/// Join Vars:
/// `var a; var b = 1; var c = 2` => `var a, b = 1; c = 2`
/// <https://github.com/google/closure-compiler/blob/v20240609/src/com/google/javascript/jscomp/CollapseVariableDeclarations.java>
///
/// Collapse into for statements:
/// `var a = 0; for(;a<0;a++) {}` => `for(var a = 0;a<0;a++) {}`
/// <https://github.com/google/closure-compiler/blob/v20240609/src/com/google/javascript/jscomp/Denormalize.java>
pub struct CollapseVariableDeclarations {
pub(crate) changed: bool,
}

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

impl<'a> Traverse<'a> for CollapseVariableDeclarations {
fn exit_statements(&mut self, stmts: &mut Vec<'a, Statement<'a>>, ctx: &mut TraverseCtx<'a>) {
use oxc_traverse::TraverseCtx;

use super::PeepholeOptimizations;

impl<'a> PeepholeOptimizations {
/// Collapse variable declarations.
///
/// Join Vars:
/// `var a; var b = 1; var c = 2` => `var a, b = 1; c = 2`
/// <https://github.com/google/closure-compiler/blob/v20240609/src/com/google/javascript/jscomp/CollapseVariableDeclarations.java>
///
/// Collapse into for statements:
/// `var a = 0; for(;a<0;a++) {}` => `for(var a = 0;a<0;a++) {}`
/// <https://github.com/google/closure-compiler/blob/v20240609/src/com/google/javascript/jscomp/Denormalize.java>
pub fn collapse_variable_declarations(
&mut self,
stmts: &mut Vec<'a, Statement<'a>>,
ctx: &mut TraverseCtx<'a>,
) {
self.join_vars(stmts, ctx);
self.maybe_collapse_into_for_statements(stmts, ctx);
}
}

// Join Vars
impl<'a> CollapseVariableDeclarations {
pub fn new() -> Self {
Self { changed: false }
}

fn is_require_call(var_decl: &VariableDeclaration) -> bool {
var_decl
Expand Down Expand Up @@ -112,7 +98,7 @@ impl<'a> CollapseVariableDeclarations {
}

// Collapse into for statements
impl<'a> CollapseVariableDeclarations {
impl<'a> PeepholeOptimizations {
fn maybe_collapse_into_for_statements(
&mut self,
stmts: &mut Vec<'a, Statement<'a>>,
Expand Down Expand Up @@ -240,18 +226,6 @@ mod test {
mod join_vars {
use super::{test, test_same};

#[test]
fn cjs() {
// Do not join `require` calls for cjs-module-lexer.
test_same(
" Object.defineProperty(exports, '__esModule', { value: true });
var compilerDom = require('@vue/compiler-dom');
var runtimeDom = require('@vue/runtime-dom');
var shared = require('@vue/shared');
",
);
}

#[test]
fn test_collapsing() {
// Basic collapsing
Expand Down
35 changes: 9 additions & 26 deletions crates/oxc_minifier/src/ast_passes/convert_to_dotted_properties.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,16 @@
use oxc_ast::ast::*;
use oxc_syntax::identifier::is_identifier_name;
use oxc_traverse::{traverse_mut_with_ctx, ReusableTraverseCtx, Traverse, TraverseCtx};
use oxc_traverse::TraverseCtx;

use crate::{ctx::Ctx, CompressorPass};
use super::PeepholeOptimizations;
use crate::ctx::Ctx;

/// Converts property accesses from quoted string or bracket access syntax to dot or unquoted string
/// syntax, where possible. Dot syntax is more compact.
///
/// <https://github.com/google/closure-compiler/blob/v20240609/src/com/google/javascript/jscomp/ConvertToDottedProperties.java>
pub struct ConvertToDottedProperties {
pub(crate) changed: bool,
in_fixed_loop: bool,
}

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

impl<'a> Traverse<'a> for ConvertToDottedProperties {
fn exit_member_expression(
impl<'a> PeepholeOptimizations {
/// Converts property accesses from quoted string or bracket access syntax to dot or unquoted string
/// syntax, where possible. Dot syntax is more compact.
///
/// <https://github.com/google/closure-compiler/blob/v20240609/src/com/google/javascript/jscomp/ConvertToDottedProperties.java>
pub fn convert_to_dotted_properties(
&mut self,
expr: &mut MemberExpression<'a>,
ctx: &mut TraverseCtx<'a>,
Expand All @@ -30,12 +19,6 @@ impl<'a> Traverse<'a> for ConvertToDottedProperties {
self.try_compress_computed_member_expression(expr, Ctx(ctx));
}
}
}

impl<'a> ConvertToDottedProperties {
pub fn new(in_fixed_loop: bool) -> Self {
Self { changed: false, in_fixed_loop }
}

/// `foo['bar']` -> `foo.bar`
/// `foo?.['bar']` -> `foo?.bar`
Expand Down
40 changes: 14 additions & 26 deletions crates/oxc_minifier/src/ast_passes/exploit_assigns.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,19 @@
use oxc_allocator::Vec;
use oxc_ast::ast::*;
use oxc_traverse::{traverse_mut_with_ctx, ReusableTraverseCtx, Traverse, TraverseCtx};

use crate::CompressorPass;

/// Tries to chain assignments together.
///
/// <https://github.com/google/closure-compiler/blob/v20240609/src/com/google/javascript/jscomp/ExploitAssigns.java>
pub struct ExploitAssigns {
pub(crate) changed: bool,
}

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

impl<'a> Traverse<'a> for ExploitAssigns {
fn exit_statements(&mut self, _stmts: &mut Vec<'a, Statement<'a>>, _ctx: &mut TraverseCtx<'a>) {
}
}

impl ExploitAssigns {
pub fn new() -> Self {
Self { changed: false }
use oxc_traverse::TraverseCtx;

use super::PeepholeOptimizations;

impl<'a> PeepholeOptimizations {
/// Tries to chain assignments together.
///
/// <https://github.com/google/closure-compiler/blob/v20240609/src/com/google/javascript/jscomp/ExploitAssigns.java>
#[expect(clippy::unused_self)]
pub fn exploit_assigns(
&mut self,
_stmts: &mut Vec<'a, Statement<'a>>,
_ctx: &mut TraverseCtx<'a>,
) {
}
}

Expand Down
41 changes: 14 additions & 27 deletions crates/oxc_minifier/src/ast_passes/minimize_exit_points.rs
Original file line number Diff line number Diff line change
@@ -1,34 +1,21 @@
use oxc_allocator::Vec;
use oxc_ast::ast::*;
use oxc_traverse::{traverse_mut_with_ctx, ReusableTraverseCtx, Traverse, TraverseCtx};

use crate::CompressorPass;

/// Transform the structure of the AST so that the number of explicit exits
/// are minimized and instead flows to implicit exits conditions.
///
/// <https://github.com/google/closure-compiler/blob/v20240609/src/com/google/javascript/jscomp/MinimizeExitPoints.java>
pub struct MinimizeExitPoints {
pub(crate) changed: bool,
}

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

impl Traverse<'_> for MinimizeExitPoints {
fn exit_function_body(&mut self, body: &mut FunctionBody<'_>, _ctx: &mut TraverseCtx<'_>) {
use oxc_traverse::TraverseCtx;

use super::PeepholeOptimizations;

impl<'a> PeepholeOptimizations {
/// Transform the structure of the AST so that the number of explicit exits
/// are minimized and instead flows to implicit exits conditions.
///
/// <https://github.com/google/closure-compiler/blob/v20240609/src/com/google/javascript/jscomp/MinimizeExitPoints.java>
pub fn minimize_exit_points(
&mut self,
body: &mut FunctionBody<'_>,
_ctx: &mut TraverseCtx<'_>,
) {
self.remove_last_return(&mut body.statements);
}
}

impl<'a> MinimizeExitPoints {
pub fn new() -> Self {
Self { changed: false }
}

// `function foo() { return }` -> `function foo() {}`
fn remove_last_return(&mut self, stmts: &mut Vec<'a, Statement<'a>>) {
Expand Down
Loading
Loading