-
-
Notifications
You must be signed in to change notification settings - Fork 5.8k
Description
💻
- Would you like to work on a fix?
How are you using Babel?
Programmatic API (babel.transform, babel.parse)
Input code
class Foo {
static { console.log(this, Foo) }
static x = () => { console.log(this, Foo) }
}
const oldFoo = Foo;
Foo = null;
oldFoo.x();Configuration file name
No response
Configuration
(I put the input code into the Babel REPL)
Current and expected behavior
Current behavior: When the output code Babel generates is run, it prints something like this:
Foo Foo
null null
When the input code is run natively, it prints something like this:
Foo Foo
Foo Foo
I expected the behavior of the output code Babel generates to match behavior of the input code.
Environment
(I put the input code into the Babel REPL)
Possible solution
Class declarations in JavaScript generate an outer binding name, which turns out to be mutable (and can be reassigned). Separately, JavaScript also generates an immutable inner binding name that is only in scope within the class body. Referencing the class name within the class body gives the inner immutable binding name, and referencing the class name outside the class body gives the mutable outer binding name.
Currently Babel generates this output code:
var Foo = /*#__PURE__*/_createClass(function Foo() {
_classCallCheck(this, Foo);
});
console.log(Foo, Foo);
_defineProperty(Foo, "x", function () {
console.log(Foo, Foo);
});
var oldFoo = Foo;
Foo = null;
oldFoo.x();This problem could be fixed by generating the following output code instead:
var Foo = /*#__PURE__*/_createClass(function Foo() {
_classCallCheck(this, Foo);
});
var _Foo = Foo;
console.log(_Foo, _Foo);
_defineProperty(_Foo, "x", function () {
console.log(_Foo, _Foo);
});
var oldFoo = Foo;
Foo = null;
oldFoo.x();The modified code explicitly materializes the immutable inner binding name for the code that had to be moved outside of the class body due to syntax lowering.
Additional context
I discovered this bug in Babel because I'm trying to figure out how to handle this in esbuild, and as part of that I'm investigating how Babel transpiles code that does this.