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
115 changes: 60 additions & 55 deletions crates/oxc_minifier/src/peephole/minimize_statements.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1038,65 +1038,70 @@ impl<'a> PeepholeOptimizations {
if Self::keep_top_level_var_in_script_mode(ctx) {
return false;
}
let Some(Statement::VariableDeclaration(prev_var_decl)) = stmts.last_mut() else {
return false;
};
if prev_var_decl.kind.is_using() {
return false;
}

let last_non_inlined_index = prev_var_decl.declarations.iter_mut().rposition(|prev_decl| {
let Some(prev_decl_init) = &mut prev_decl.init else {
return true;
};
let BindingPatternKind::BindingIdentifier(prev_decl_id) = &prev_decl.id.kind else {
return true;
};
if ctx.is_expression_whose_name_needs_to_be_kept(prev_decl_init) {
return true;
}
let Some(symbol_value) =
ctx.state.symbol_values.get_symbol_value(prev_decl_id.symbol_id())
else {
return true;
};
// we should check whether it's exported by `symbol_value.exported`
// because the variable might be exported with `export { foo }` rather than `export var foo`
if symbol_value.exported
|| symbol_value.read_references_count > 1
|| symbol_value.write_references_count > 0
{
return true;
}
let replaced = Self::substitute_single_use_symbol_in_expression(
expr_in_stmt,
&prev_decl_id.name,
prev_decl_init,
prev_decl_init.may_have_side_effects(ctx),
ctx,
);
if replaced != Some(true) {
return true;
}
false
});
match last_non_inlined_index {
None => {
// all inlined
stmts.pop();
true
}
Some(last_non_inlined_index)
if last_non_inlined_index + 1 == prev_var_decl.declarations.len() =>
{
// no change
false
let mut inlined = false;
while let Some(Statement::VariableDeclaration(prev_var_decl)) = stmts.last_mut() {
if prev_var_decl.kind.is_using() {
break;
}
Some(last_non_inlined_index) => {
prev_var_decl.declarations.truncate(last_non_inlined_index + 1);
true

let last_non_inlined_index =
prev_var_decl.declarations.iter_mut().rposition(|prev_decl| {
let Some(prev_decl_init) = &mut prev_decl.init else {
return true;
};
let BindingPatternKind::BindingIdentifier(prev_decl_id) = &prev_decl.id.kind
else {
return true;
};
if ctx.is_expression_whose_name_needs_to_be_kept(prev_decl_init) {
return true;
}
let Some(symbol_value) =
ctx.state.symbol_values.get_symbol_value(prev_decl_id.symbol_id())
else {
return true;
};
// we should check whether it's exported by `symbol_value.exported`
// because the variable might be exported with `export { foo }` rather than `export var foo`
if symbol_value.exported
|| symbol_value.read_references_count > 1
|| symbol_value.write_references_count > 0
{
return true;
}
let replaced = Self::substitute_single_use_symbol_in_expression(
expr_in_stmt,
&prev_decl_id.name,
prev_decl_init,
prev_decl_init.may_have_side_effects(ctx),
ctx,
);
if replaced != Some(true) {
return true;
}
false
});
match last_non_inlined_index {
None => {
// all inlined
stmts.pop();
inlined = true;
}
Some(last_non_inlined_index)
if last_non_inlined_index + 1 == prev_var_decl.declarations.len() =>
{
// no change
break;
}
Some(last_non_inlined_index) => {
prev_var_decl.declarations.truncate(last_non_inlined_index + 1);
inlined = true;
break;
}
}
}
inlined
}

/// Returns Some(true) when the expression is successfully replaced.
Expand Down
75 changes: 75 additions & 0 deletions crates/oxc_minifier/tests/peephole/dead_code_elimination.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,3 +271,78 @@ fn dce_from_terser() {
"console.log(foo, bar, Baz);",
);
}

#[test]
fn dce_iterations() {
test(
"
var a1 = 'a1'
var a2 = 'a2'
var a3 = 'a3'
var a4 = 'a4'
var a5 = 'a5'
var a6 = 'a6'
var a7 = 'a7'
var a8 = 'a8'
var a9 = 'a9'
var a10 = 'a10'
var a11 = 'a11'
var a12 = 'a12'
var a13 = 'a13'
var a14 = 'a14'
var a15 = 'a15'
var a16 = 'a16'
var a17 = 'a17'
var a18 = 'a18'
var a19 = 'a19'
var a20 = 'a20'
var arr = [
a1,
a2,
a3,
a4,
a5,
a6,
a7,
a8,
a9,
a10,
a11,
a12,
a13,
a14,
a15,
a16,
a17,
a18,
a19,
a20
]
console.log(arr)
",
"
console.log([
'a1',
'a2',
'a3',
'a4',
'a5',
'a6',
'a7',
'a8',
'a9',
'a10',
'a11',
'a12',
'a13',
'a14',
'a15',
'a16',
'a17',
'a18',
'a19',
'a20'
])
",
);
}
Loading