ES6 class generation for Haxe/JS is here! (testers needed)

Hi, fellow users of the Haxe JavaScript target!

I just merged some code that makes Haxe/JS output ES6 classes instead of classic Function+prototype. It’s available in latest nightlies (also installable with Lix) and can be activated with the -D js-es=6 compiler argument.

We decided to include it in already Haxe 4.0, because ES6 class support is becoming critical nowadays, as they are not backwards-compatible with the classic inheritance style, making it impossible to use some ES6 libraries with Haxe.

We might look into adding more ES6 features usage for future versions, and meanwhile, the bravest ones are welcome to give it a try and give feedback!

UPD: I just wrote some documentation on this, describing limitations and required workarounds. Hopefully that will be part of the Haxe Manual soon enough!

32 Likes

Great, was waiting for it! (already had the flag in my hxml xD)

Does the very latest dev version of haxe (#33df799 atm) has known issues that could lead to this, or should I create an issue and try to reproduce it with a minimal example?

Must call super() constructor before accessing this in classes derived from an extern class with constructor

Yes, this is an expected error when you a) extend an extern class with the constructor and b) access this before calling super in the subclass (that might also happen implicitly if you have fields with initializers). The compiler should give you position of such access or field init.

Yeah, I have fields with initializers. How should I handle them?

You have to move them into the constructor after the super call in this case. Because Haxe guarantees that field with inits are initialized before any constructor call and with ES6 you cannot have that. For fully Haxe-generated we work that around by extracting constructor body in a method and applying a small hack, but for extern classes we can’t do anything besides printing an error message with a position pointing to the offending code.

I’m gonna write some documentation explaining this limitation a bit better soon.

Ok, thanks! This is kind of a huge limitation in my use case, but I’ll try to handle this via macros (since it should only happen in classes extending a particular extern class which is already using a lot of macros).

FYI the check should allow doing that if you specify extern class as NOT having a constructor (so, remove function new from the definition).

My first tests are good. I could update my web components lib to support the ES6 target and it works well dispite the constructor restriction.
Very good job Dan !

1 Like

For externs you should just generate the initialisation after the super constructor call. That’s how a JS class would be designed.

That sounds like a fragile assumption and I want to be on the safe side. We could maybe have some meta to allow it explicitly though.

Couldn’t we just translate this:

class Test {
  var foo = "bar";

  public function new() {
     // ...
  }
}

Into this?

class Test {
  foo = "bar";

  constructor() {
     // ...
  }
}

no, that’s still a stage 3 proposal and doesn’t work everywhere. also it suffers from the same issues with super calls, at least on chrome

any planned addition of get set attribute generation ?
public var r0c0(get, set):Float;

will be also support for export and import es6?

Import/export didn’t change - still one big JS with commonjs-style require/exports. It’s not yet producing separated JS files, just using ES6 classes for code generation.

1 Like