In ES2019, private class fields are defined using a hash # prefix:
class MyClass {
a = 1; // .a is public
#b = 2; // .#b is private
static #c = 3; // .#c is private and static
incB() {
this.#b++;
}
}
let m = new MyClass();
m.incB(); // runs OK
m.#b = 0; // error - private property cannot be modified outside class
Hmpf. I donāt like the syntax myself, but Iād say the bashing is about as obnoxious. Weāre talking about generated code.
The important question to ask about our output is whether or not it can be improved in terms of interoperability. For example ES6 classes were actually needed for something - IIRC it was some framework or custom html elements ā¦ or both?
If you feel like you can make a good point why this would make the generated JS easier to use from ānativeā JavaScript, thatās a great basis for discussion. Wanting it because itās the latest hip thing is not. Especially because this particular feature is currently only supported by Chrome so in the end itās going to have to be transpiled out anyway. All changes require effort to perform and maintain - especially if itās support for a proposal thatās deemed experimental. Youāll need a convincing use case to motivate the team to exert that effort. Even more so if it requires overcoming their personal dislikes
Like @back2dos said, it is about generated code, not Haxe code. Class field being private make sense when making library out of Haxe code for specific target, where developer continues work using target language like JS for example.
Itās not just about code generation but semantics: if you make a Haxe class with private fields, you can extend it (in Haxe and JS) and access these private fields because they are āprotectedā in reality. You could break the transpiled Haxe code by using ātrue privateā JS fields.
Simple way, no. But it is not so complicated. For example if you have
class MyClass {
@:private var i:Int;
public function new() {}
}
you need to register macro callbacks
class Macro {
#if macro
static var types:Array<Type>;
public static function callbacks() {
haxe.macro.Context.onGenerate(function(t) {
// store all types going to be generated
types = t;
});
haxe.macro.Context.onAfterGenerate(function() {
// read types and look for meta
switch (haxe.macro.Context.getType("MyClass"))
{
case TInst(cl,_):
var f = cl.get().fields.get();
trace(f[0].meta.get());
case _:
}
// modify .js file afterwards
});
}
#end
}
and add --macro Macro.callbacks() to your build.hxml file.
You have to write a code by yourself which iterates over types, looks for custom meta and modifies (by adding #) generated .js file afterwards. In case you are using custom JS generator which creates multiple files, you have to take care about that as well.
src/Macro.hx:18: characters 27-31 : Uncaught exception field access on null
import haxe.macro.Type;
class Macro {
#if macro
static var types:Array<haxe.macro.Type>;
public static function callbacks() {
haxe.macro.Context.onGenerate(function(t) {
// store all types going to be generated
types = t;
});
haxe.macro.Context.onAfterGenerate(function() {
// read types and look for meta
switch (haxe.macro.Context.getType("MyClass"))
{
case TInst(cl,_):
var f = cl.get().fields.get();
trace(f[0].meta.get());
case _:
}
// modify .js file afterwards
});
}
#end
}
Thatās example assuming above class MyClass is provided, where first field contains meta. Example is hard-coded. As I said, you have to write your own code which iterates over types looking for meta(s)
Even putting aside my strong dislike for this feature, this is way too early to adopt it. Letās at least wait for support in firefox before considering that.
Edit: note that haxe still supports IE8 afaik, so generating code (and moreover allocate time to develop this, since weāre not talking about accepting a PR but actually having to implement it) that only works on recent nodejs/chrome seems a little out of place.
Well, I think it is not very important to wait for it. Because the main reason for private fields is the use of generated .js as a library in existing js projects which are already using Babel to achieve browserās support.
Using Haxe output (which is a pretty common scenario) as a library is a good reason for almost all targets to support @:private meta on fields
Not to be that guy but Haxe doesnāt have real privates. Our private keyword is actually a protected keyword, if you look to other code languages. Once in a while I would like to have real private, because I have to deal with OOP. With real I donāt mean isnāt hackable with @:access or @:privateAccess (like the es2019 one, which is very strict about it) but where I can define a private with same name in sub or parent class without issues.
Now I think changing our private to protected and introducing actual private is to big of a change, so that will never happen. But the hashtag in combination with private (as ugly as it might look) might help us getting realer privates, maybe?
private var x:Int; // protected private
private var #y:Int; // realer private
If it is just about generated code, I think it shouldnāt be that hard to support it using @:native, as alternative. At the moment that generates something that uses runtime reflection.