Skip to content

Commit 7ed1684

Browse files
authored
fix #4141: Avoid redundant this access during async function lowering (#4142)
1 parent edc3a23 commit 7ed1684

File tree

7 files changed

+151
-59
lines changed

7 files changed

+151
-59
lines changed

CHANGELOG.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,44 @@
22

33
## Unreleased
44

5+
* Fix lowered `async` arrow functions before `super()` ([#4141](https://github.com/evanw/esbuild/issues/4141), [#4142](https://github.com/evanw/esbuild/pull/4142))
6+
7+
This change makes it possible to call an `async` arrow function in a constructor before calling `super()` when targeting environments without `async` support, as long as the function body doesn't reference `this`. Here's an example (notice the change from `this` to `null`):
8+
9+
```js
10+
// Original code
11+
class Foo extends Object {
12+
constructor() {
13+
(async () => await foo())()
14+
super()
15+
}
16+
}
17+
18+
// Old output (with --target=es2016)
19+
class Foo extends Object {
20+
constructor() {
21+
(() => __async(this, null, function* () {
22+
return yield foo();
23+
}))();
24+
super();
25+
}
26+
}
27+
28+
// New output (with --target=es2016)
29+
class Foo extends Object {
30+
constructor() {
31+
(() => __async(null, null, function* () {
32+
return yield foo();
33+
}))();
34+
super();
35+
}
36+
}
37+
```
38+
39+
Some background: Arrow functions with the `async` keyword are transformed into generator functions for older language targets such as `--target=es2016`. Since arrow functions capture `this`, the generated code forwards `this` into the body of the generator function. However, JavaScript class syntax forbids using `this` in a constructor before calling `super()`, and this forwarding was problematic since previously happened even when the function body doesn't use `this`. Starting with this release, esbuild will now only forward `this` if it's used within the function body.
40+
41+
This fix was contributed by [@magic-akari](https://github.com/magic-akari).
42+
543
* Fix memory leak with `--watch=true` ([#4131](https://github.com/evanw/esbuild/issues/4131), [#4132](https://github.com/evanw/esbuild/pull/4132))
644

745
This release fixes a memory leak with esbuild when `--watch=true` is used instead of `--watch`. Previously using `--watch=true` caused esbuild to continue to use more and more memory for every rebuild, but `--watch=true` should now behave like `--watch` and not leak memory.

internal/bundler_tests/bundler_lower_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,18 @@ func TestLowerAsync2016NoBundle(t *testing.T) {
786786
return [this, arguments]
787787
}
788788
class Foo {async foo() {}}
789+
new (class Bar extends class { } {
790+
constructor() {
791+
let x = 1;
792+
(async () => {
793+
console.log("before super", x); // (1) Sync phase
794+
await 1;
795+
console.log("after super", x); // (2) Async phase
796+
})();
797+
super();
798+
x = 2;
799+
}
800+
})();
789801
export default [
790802
foo,
791803
Foo,

0 commit comments

Comments
 (0)