mirror of
https://github.com/oxc-project/oxc.git
synced 2026-11-04 10:29:58 +00:00
fix(minifier): allow argument rewrite with with leading var assignments (#28056)
allow rewrite of `arguments` loop with leading empty var assignments.
```js
function _() { for (var keep, r = [], a = 0; a < arguments.length; a++) r[a] = arguments[a]; use(r, keep) }
function _() { var keep, r = [...arguments]; use(r, keep) }
```
This commit is contained in:
1 parent
4629bb294a
commit
09bdb80a45
3 files changed
+31
-6
No files matched your search
@@ -855,7 +855,18 @@ impl<'a> PeepholeOptimizations {
|
||||
|
||||
let Some(init) = &mut for_stmt.init else { return };
|
||||
let ForStatementInit::VariableDeclaration(var_init) = init else { return };
|
||||
let Some(siblings) = var_init.declarations.get(init_decl_len..) else { return };
|
||||
let leading_var_count = if var_init.kind.is_var() {
|
||||
let Some(var_position) =
|
||||
var_init.declarations.iter().position(|decl| decl.init.is_some())
|
||||
else {
|
||||
return;
|
||||
};
|
||||
var_position
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let pattern_end = leading_var_count + init_decl_len;
|
||||
let Some(siblings) = var_init.declarations.get(pattern_end..) else { return };
|
||||
// Sibling declarators may be in the source loop or folded into it by `sequences`.
|
||||
// Keep uninitialized `var` siblings, but don't move an initializer across the spread.
|
||||
if !siblings.is_empty()
|
||||
@@ -873,7 +884,7 @@ impl<'a> PeepholeOptimizations {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut idx = 0usize;
|
||||
let mut idx = leading_var_count;
|
||||
|
||||
// Check `e = arguments.length`
|
||||
if let Some((e_id_name, _)) = e_id_info {
|
||||
@@ -1012,13 +1023,13 @@ impl<'a> PeepholeOptimizations {
|
||||
let new_decl = VariableDeclarator::new(SPAN, r_id_pat, None, Some(arr), false, ctx);
|
||||
// Drop only the copy-loop declarators. Siblings remain in the `var` statement.
|
||||
// Walk removed declarators so refs inside them reach `PassChanges`.
|
||||
for decl in var_init.declarations.drain(..init_decl_len) {
|
||||
for decl in var_init.declarations.drain(leading_var_count..pattern_end) {
|
||||
ctx.drop_variable_declarator(&decl);
|
||||
}
|
||||
var_init.declarations.insert(0, new_decl);
|
||||
var_init.declarations.insert(leading_var_count, new_decl);
|
||||
} else {
|
||||
// The copied array is unused, but sibling declarations still need to survive.
|
||||
for decl in var_init.declarations.drain(..init_decl_len) {
|
||||
for decl in var_init.declarations.drain(leading_var_count..pattern_end) {
|
||||
ctx.drop_variable_declarator(&decl);
|
||||
}
|
||||
// Avoid invalid `for (var; 0;)` when no siblings remain.
|
||||
|
||||
@@ -1078,6 +1078,14 @@ fn test_rewrite_arguments_copy_loop() {
|
||||
"function _() { for (var r = [], a = 0, keep; a < arguments.length; a++) r[a] = arguments[a]; use(r, keep) }",
|
||||
"function _() { var r = [...arguments], keep; use(r, keep) }",
|
||||
);
|
||||
test(
|
||||
"function _() { for (var keep, r = [], a = 0; a < arguments.length; a++) r[a] = arguments[a]; use(r, keep) }",
|
||||
"function _() { var keep, r = [...arguments]; use(r, keep) }",
|
||||
);
|
||||
test(
|
||||
"function _() { for (var first, second, r = [], a = 0; a < arguments.length; a++) r[a] = arguments[a]; use(r, first, second) }",
|
||||
"function _() { var first, second, r = [...arguments]; use(r, first, second) }",
|
||||
);
|
||||
test(
|
||||
"function _() { var items = [], t = 0, i, u, r; for (; t < arguments.length; t++) items[t] = arguments[t]; if (this.list = [], items != null) for (i = 0, u = items; i < u.length; i++) r = u[i], this.list.push(r) }",
|
||||
"function _() { var items = [...arguments], i, u, r; if (this.list = [], items != null) for (i = 0, u = items; i < u.length; i++) r = u[i], this.list.push(r) }",
|
||||
@@ -1089,6 +1097,12 @@ fn test_rewrite_arguments_copy_loop() {
|
||||
test_same(
|
||||
"function _() { for (var r = [], a = 0, keep = side(); a < arguments.length; a++) r[a] = arguments[a]; use(r, keep) }",
|
||||
);
|
||||
test_same(
|
||||
"function _() { for (var keep = side(), r = [], a = 0; a < arguments.length; a++) r[a] = arguments[a]; use(r, keep) }",
|
||||
);
|
||||
test_same(
|
||||
"function _() { for (var keep; a < arguments.length; a++) r[a] = arguments[a]; use(r, keep) }",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -23,5 +23,5 @@ Original | minified | minified | gzip | gzip | Iterations | Fi
|
||||
|
||||
6.69 MB | 2.12 MB | 2.31 MB | 453.41 kB | 488.28 kB | 4 | antd.js
|
||||
|
||||
10.95 MB | 3.31 MB | 3.49 MB | 849.81 kB | 915.50 kB | 4 | typescript.js
|
||||
10.95 MB | 3.31 MB | 3.49 MB | 849.76 kB | 915.50 kB | 4 | typescript.js
|
||||
|
||||
Reference in new issue
Block a user