Skip to content

Commit 7446da9

Browse files
fix(es/minifier): preserve lexical method defaults (#12239)
**Description:** Fix object method-to-arrow conversion when a parameter default references lexical `arguments` or `super`. - Reject conversion for those parameter initializers, preserving method bindings and valid `super` syntax. - Add an SWC-owned #12187 fixture with runtime coverage for both unsafe defaults, existing body controls, and a safe default that still converts to an arrow. - Add patch changesets for `swc_ecma_minifier` and `swc_core`. **BREAKING CHANGE:** None. **Related issue (if exists):** Closes #12187 **Tests:** - `UPDATE=1 cargo test -p swc_ecma_minifier` - `cargo test -p swc_ecma_minifier` - `crates/swc_ecma_minifier/scripts/test.sh` - `crates/swc_ecma_minifier/scripts/exec.sh` - `cargo fmt --all` - `cargo clippy --all --all-targets -- -D warnings` --------- Co-authored-by: Labor0 Bot <279936132+labor0-bot[bot]@users.noreply.github.com>
1 parent 4a73df1 commit 7446da9

6 files changed

Lines changed: 123 additions & 1 deletion

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
swc_core: patch
3+
swc_ecma_minifier: patch
4+
---
5+
6+
fix(es/minifier): Preserve lexical arguments and super in method parameter defaults

‎crates/swc_ecma_minifier/src/compress/pure/arrows.rs‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use swc_common::{util::take::Take, DUMMY_SP};
22
use swc_ecma_ast::*;
3+
use swc_ecma_transforms_base::rename::contains_eval;
34
use swc_ecma_utils::{contains_arguments, contains_this_expr};
45

56
use super::Pure;
@@ -72,7 +73,12 @@ impl Pure<'_> {
7273
if m.function.is_generator
7374
|| contains_arguments(&m.function.body)
7475
|| contains_super(&m.function.body)
75-
|| m.function.params.iter().any(contains_this_expr)
76+
|| m.function.params.iter().any(|param| {
77+
contains_this_expr(param)
78+
|| contains_arguments(param)
79+
|| contains_super(param)
80+
|| contains_eval(param, false)
81+
})
7682
{
7783
return;
7884
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"defaults": true
3+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
0 0 7 0 7 5
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
function argumentsDefault() {
2+
if (arguments.length !== 2) {
3+
throw new Error("arguments were dropped");
4+
}
5+
6+
return {
7+
m(value = arguments.length) {
8+
return value;
9+
},
10+
}.m();
11+
}
12+
13+
function evalDefault() {
14+
if (arguments.length !== 2) {
15+
throw new Error("arguments were dropped");
16+
}
17+
18+
return {
19+
m(value = eval("arguments.length")) {
20+
return value;
21+
},
22+
}.m();
23+
}
24+
25+
const superDefault = {
26+
__proto__: {
27+
value: 7,
28+
},
29+
m(value = super.value) {
30+
return value;
31+
},
32+
};
33+
34+
function argumentsBody() {
35+
return {
36+
m() {
37+
return arguments.length;
38+
},
39+
}.m();
40+
}
41+
42+
const superBody = {
43+
__proto__: {
44+
value: 7,
45+
},
46+
m() {
47+
return super.value;
48+
},
49+
};
50+
51+
const safeDefault = {
52+
m(value = 5) {
53+
return value;
54+
},
55+
};
56+
57+
console.log(
58+
argumentsDefault(1, 2),
59+
evalDefault(1, 2),
60+
superDefault.m(),
61+
argumentsBody(1, 2),
62+
superBody.m(),
63+
safeDefault.m(),
64+
);
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
function argumentsDefault() {
2+
if (2 != arguments.length) throw Error("arguments were dropped");
3+
return ({
4+
m (value = arguments.length) {
5+
return value;
6+
}
7+
}).m();
8+
}
9+
function evalDefault() {
10+
if (2 != arguments.length) throw Error("arguments were dropped");
11+
return ({
12+
m (value = eval("arguments.length")) {
13+
return value;
14+
}
15+
}).m();
16+
}
17+
const superDefault = {
18+
__proto__: {
19+
value: 7
20+
},
21+
m (value = super.value) {
22+
return value;
23+
}
24+
};
25+
function argumentsBody() {
26+
return ({
27+
m () {
28+
return arguments.length;
29+
}
30+
}).m();
31+
}
32+
const superBody = {
33+
__proto__: {
34+
value: 7
35+
},
36+
m () {
37+
return super.value;
38+
}
39+
}, safeDefault = {
40+
m: (value = 5)=>value
41+
};
42+
console.log(argumentsDefault(1, 2), evalDefault(1, 2), superDefault.m(), argumentsBody(1, 2), superBody.m(), safeDefault.m());

0 commit comments

Comments
 (0)