esbuild
esbuild copied to clipboard
Private properties are lowered when combine with static properties
Hi,
I have initially reported that in #2158 but I thought it may be useful to report it as an individual issue as the original issue is a bit different.
As of today, even when setting esnext as a target, esbuild improperly lower private syntax when one class contains a static method and bundling is enabled.
For instance, this:
export class Test {
#foo = 5;
}
is properly transformed to:
// js/foo.js
var Test = class {
#foo = 5;
};
export {
Test
};
However, as soon as a static property enter into the game, everything is lowered, although esnext should support both syntax natively:
export class Test {
static bar = 1;
#foo = 5;
}
Is transformed to:
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
var __privateAdd = (obj, member, value) => {
if (member.has(obj))
throw TypeError("Cannot add the same private member more than once");
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
};
// js/foo.js
var _foo;
var Test = class {
constructor() {
__privateAdd(this, _foo, 5);
}
};
_foo = new WeakMap();
__publicField(Test, "bar", 1);
export {
Test
};
Reproduction Link, it only occurs when bundle: true.
Yes, that's true. This is likely not a bug but a limitation of esbuild's single-pass design. See this comment for an example.
Is there any workaround for this ? Maybe could we pass an option to instruct Esbuild we are not using static field with new ?
I've just encountered this strange behaviour. Why doing var Test = class {} ? (as class Test{}can be hidden within a (function () {})() ? Why calling an external __publicField() where it could be only Test.bar = 1 ?
I know it's a bummer but a workaround seems to be go old school
export class Test {
#foo = 5;
}
Test.bar = 1;
https://hyrious.me/esbuild-repl/?version=0.14.50&mode=build&modules=%5B%5B%22main.js%22%2C%22export+class+Test+%7B%5Cn++%23foo+%3D+5%3B%5Cn%7D%5CnTest.bar+%3D+1%3B%22%2C1%5D%5D&buildOptions=%7B%22bundle%22%3Atrue%7D