fix(ecmascript): treat this as potentially having side effects (#21297)

fixes https://github.com/oxc-project/oxc/issues/21296 by treating `this` as potentially having side effects.
We can reduce the case that is bailed out by checking whether `this` is written inside `constructor` or not in the future.
This commit is contained in:
sapphi-red committed 2026-04-11 14:25:36 +00:00
1 parent f636217d2e
commit 2338e28f59
8 files changed
+60 -22

No files matched your search

@@ -26,7 +26,6 @@ impl<'a> MayHaveSideEffects<'a> for Expression<'a> {
| Expression::NullLiteral(_)
| Expression::RegExpLiteral(_)
| Expression::MetaProperty(_)
| Expression::ThisExpression(_)
| Expression::ArrowFunctionExpression(_)
| Expression::FunctionExpression(_)
| Expression::Super(_) => false,
@@ -471,9 +471,11 @@ fn test_identifier_reference() {
fn test_simple_expressions() {
test("1n", false);
test("true", false);
test("this", false);
test("import.meta", false);
test("(() => {})", false);
// referencing `this` in a derived class before `super()` is called causes a ReferenceError
test("this", true);
}
#[test]
@@ -1477,7 +1477,7 @@ fn test_remove_dead_expr() {
test("0; 'abc'", "");
test("'abc'; 'use strict'", "'abc';");
test("function f() { 'abc'; 'use strict' }", "function f() { 'abc'; }");
test("this", "");
// test("this", "");
test("/regex/", "");
test("(function() {})", "");
test("(() => {})", "");
@@ -65,7 +65,8 @@ fn test_inline_single_use_variable() {
}
",
);
test(
// Ideally we should merge it to `this.#foo = foo;`
test_same(
"
class Foo {
#foo;
@@ -75,14 +76,6 @@ fn test_inline_single_use_variable() {
}
}
",
"
class Foo {
#foo;
static {
this.#foo = foo;
}
}
",
);
test(
"
@@ -105,6 +98,47 @@ fn test_inline_single_use_variable() {
}
",
);
// need to avoid merging to `this.value = await ...` to avoid ReferenceError (https://github.com/oxc-project/oxc/issues/21296)
test(
"
class Base {
constructor(obj) {
obj.start()
}
}
class Wrapped extends Base {
constructor() {
super({
start: async () => {
let result = await new Promise(resolve => { setTimeout(() => { resolve(0) }, 0) })
this.value = result
}
})
}
}
let wrapped = new Wrapped()
setTimeout(() => { console.log('value', wrapped.value) }, 10)
",
"
class Base {
constructor(obj) {
obj.start()
}
}
class Wrapped extends Base {
constructor() {
super({
start: async () => {
let result = await new Promise(resolve => { setTimeout(() => { resolve(0) }, 0) })
this.value = result
}
})
}
}
let wrapped = new Wrapped()
setTimeout(() => { console.log('value', wrapped.value) }, 10)
",
);
test(
"function wrapper(arg0, arg1) { let x = arg0; return new arg1(...x);}",
"function wrapper(arg0, arg1) { return new arg1(...arg0);}",
@@ -75,6 +75,7 @@ mod terser_tests {
);
}
// we can remove `this` to reduce code size further
#[test]
fn babel() {
test(
@@ -88,7 +89,9 @@ mod terser_tests {
};
"#,
r"
export var Foo = function() {};
export var Foo = function() {
this;
};
",
&["_classCallCheck"],
);
@@ -13,7 +13,7 @@ fn test_remove_unused_expression() {
test("1", "");
test("1n", "");
test(";'s'", "");
test("this", "");
// test("this", "");
test("/asdf/", "");
test("(function () {})", "");
test("(() => {})", "");
+6 -6
View File
@@ -9,19 +9,19 @@ Original | minified | minified | gzip | gzip | Iterations | Fi
342.15 kB | 116.98 kB | 118.14 kB | 43.17 kB | 44.37 kB | 2 | vue.js
544.10 kB | 71.03 kB | 72.48 kB | 25.77 kB | 26.20 kB | 2 | lodash.js
544.10 kB | 71.04 kB | 72.48 kB | 25.77 kB | 26.20 kB | 2 | lodash.js
555.77 kB | 267.38 kB | 270.13 kB | 88.00 kB | 90.80 kB | 2 | d3.js
555.77 kB | 267.41 kB | 270.13 kB | 88.02 kB | 90.80 kB | 2 | d3.js
1.01 MB | 439.37 kB | 458.89 kB | 122.05 kB | 126.71 kB | 2 | bundle.min.js
1.25 MB | 642.65 kB | 646.76 kB | 159.39 kB | 163.73 kB | 2 | three.js
2.14 MB | 711.09 kB | 724.14 kB | 160.42 kB | 181.07 kB | 2 | victory.js
2.14 MB | 711.10 kB | 724.14 kB | 160.42 kB | 181.07 kB | 2 | victory.js
3.20 MB | 1.00 MB | 1.01 MB | 322.57 kB | 331.56 kB | 3 | echarts.js
3.20 MB | 1.00 MB | 1.01 MB | 322.61 kB | 331.56 kB | 2 | echarts.js
6.69 MB | 2.22 MB | 2.31 MB | 458.42 kB | 488.28 kB | 4 | antd.js
6.69 MB | 2.22 MB | 2.31 MB | 458.43 kB | 488.28 kB | 4 | antd.js
10.95 MB | 3.33 MB | 3.49 MB | 853.27 kB | 915.50 kB | 4 | typescript.js
10.95 MB | 3.33 MB | 3.49 MB | 853.29 kB | 915.50 kB | 4 | typescript.js
@@ -6,9 +6,9 @@ cal.com.tsx | 1.06 MB || 20214 | 46 |
RadixUIAdoptionSection.jsx | 2.52 kB || 29 | 6 || 30 | 6
pdf.mjs | 567.30 kB || 4052 | 417 || 47464 | 7734
pdf.mjs | 567.30 kB || 4052 | 417 || 47472 | 7746
antd.js | 6.69 MB || 7702 | 1657 || 331673 | 69344
antd.js | 6.69 MB || 7702 | 1657 || 331684 | 69349
binder.ts | 193.08 kB || 66 | 23 || 7075 | 824