New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ES6 class support #6546

Closed
damoebius opened this Issue Aug 31, 2017 · 28 comments

Comments

Projects
None yet
@damoebius
Copy link
Contributor

damoebius commented Aug 31, 2017

Hi,
As mentioned in this thread #4552 (comment) , it's important to have a way to use ES6 class instead of prototypes.
We could have either a compiler flag or a meta @:es6 on class definition.

@back2dos

This comment has been minimized.

Copy link
Member

back2dos commented Aug 31, 2017

I find the option with metadata interesting, because one could just use --macro addGlobalMetadata("", "@:es6") to have it everywhere. OTOH I can't think of a use case of having mixed output. If ES6 is acceptable, you might as well use it for all classes and if it's not, then you cannot have it even for a single class.

@Simn

This comment has been minimized.

Copy link
Member

Simn commented Sep 1, 2017

We already have -D js_es=5 so we should certainly use that.

@ncannasse

This comment has been minimized.

Copy link
Member

ncannasse commented Sep 4, 2017

@fullofcaffeine

This comment has been minimized.

Copy link

fullofcaffeine commented Sep 5, 2017

@nadako

This comment has been minimized.

Copy link
Member

nadako commented Feb 19, 2018

I worked on this a bit and found one unfortunate behaviour of ES6 classes: in Haxe we currently can call super at any time inside the child constructor, but ES6 will complain if one tries to access this before calling super, e.g.:

class A {
  constructor() {}
}

class B extends A {
  constructor() {
    this.v = 15; // ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor
  }
}

new B();

The similar requirements are found in C#, but it's solved there by using constructor overloading and moving actual constructor body into static functions. Obviously we can't do the same for JS because there's no constructor overloading.

Will have to think some more about how to implement this without much ugliness or run-time overhead. Advices welcome :-)

nadako added a commit that referenced this issue Feb 19, 2018

@nadako

This comment has been minimized.

Copy link
Member

nadako commented Feb 19, 2018

Obviously we can't do the same for JS because there's no constructor overloading.

Well we kind of can, by having an EMPTY marker instance and adding if (arguments.length === 1 && arguments[0] === EMPTY) return; to emulate similar overloading:

var EMPTY = {};

class A {
  constructor() {
    if (arguments.length === 1 && arguments[0] === EMPTY) return;
    A._hx_ctor_A();
  }

  static _hx_ctor_A() {
    console.log("base ctor");
  }
}

class B extends A {
  constructor() {
    super(EMPTY);
    if (arguments.length === 1 && arguments[0] === EMPTY) return;
    B._hx_ctor_B();
  }

  static _hx_ctor_B() {
    console.log("before super()");
    A._hx_ctor_A();
  }
}

new B();

Doesn't look cute though.

@nadako

This comment has been minimized.

Copy link
Member

nadako commented Feb 20, 2018

ping @kevinresol @back2dos as our js target power-users :)

@back2dos

This comment has been minimized.

Copy link
Member

back2dos commented Feb 20, 2018

Yeah, I guess that's fine. I wonder if you could generate that code only when necessary and give a warning. But to be honest I don't use inheritance much, so I don't have a strong opinion here.

@kevinresol

This comment has been minimized.

Copy link
Contributor

kevinresol commented Feb 22, 2018

Sorry, but the fact is that I never explicitly touched ES6 at all. So I simply have no comments on this one.

@nanjizal

This comment has been minimized.

Copy link

nanjizal commented Feb 22, 2018

Can it be implemented so the output is only complex when required or would that have side effects, I just thinking that the uglier the js looks the more objections there is against Haxe's use by mainstream.

@RealyUniqueName

This comment has been minimized.

Copy link
Member

RealyUniqueName commented Feb 22, 2018

I think branching implementation is a bad idea in this case.
It will complicate code on the js generator side (more difficult to maintain, more error-prone) and it will complicate things for anyone who want to deal with the generated js.
Just an additional trouble for no real profit (correct me if i'm wrong).

@nanjizal

This comment has been minimized.

Copy link

nanjizal commented Feb 23, 2018

Well that's a lot of boiler plate for code that will often not be needed, my understanding is in most case you don't need to run code before super - or is that always needed with Haxe inheritance in ES6 js?

If you are trying to sell Haxe as a tech the first thing a javascript developer does is look at the generated code, I know because that is the first thing they do when you show them something cool created in Haxe when in a recent interview or at a js meetup.

I often feel the '$', 'Hx', '_', '__', 'hx' etc... prefaces can make Haxe generated javascript more daunting and will make it less appealing. So quick experiment I just went through doing some search and replace on a reasonably sized experiment, often using 'x' instead of the other characters. The code still seems to still work. I guess 'stuff' could be replaced with 'andStuff' or something to reduce the perl feeling.

https://gist.github.com/nanjizal/77f4b69115e0ad1d9df9bb308f25d517

Original demo here you can see the source feels less 'human' with $ and hx_ etc...
https://hxdaedalus.github.io/hxDaedalus-Kha-examples/build/basic/

For me the gist looks less scary, I know the current output is safe, but less people friendly. Should I open up a suggestion in Evolution, I doubt if anyone will care because Haxe is all about good solutions which I understand and not really about impressions. But anyway I hope illustrates atleast that complicating the js output can make haxe less inviting to people unfamiliar with the tech and may affect performance expectations ( ie js dev is going to feel it makes it slower even if it makes little real difference ).

Anyway won't further labour the point as I know that suggestions can add a lot of work and can increase stability risks, so I just bring it up, RealyUniqueName is probably correct.

@nanjizal

This comment has been minimized.

Copy link

nanjizal commented Feb 23, 2018

it's stripped out some of the char, the 'stuff' part makes no sense, oh well it should have had underscores doubled each side stuff.

@back2dos

This comment has been minimized.

Copy link
Member

back2dos commented Feb 23, 2018

Well, I guess we need something like this anyway, because otherwise Type.createEmptyInstance is not going to work.

@ncannasse

This comment has been minimized.

Copy link
Member

ncannasse commented Feb 25, 2018

@nadako I don't have a better idea and yes as @back2dos said it's necessary anyway for Type.createEmptyInstance. You can maybe simply disable it in case the constructor (and the superclasses constructors) are pure, which should cover many cases already.

(pure in that case meaning we only assign "this" variables)

@nadako

This comment has been minimized.

Copy link
Member

nadako commented Feb 25, 2018

We use Object.create(cl.prototype) for Type.createEmptyInstance at the moment. Is that not compatible with ES6 classes?

Anyway, I'll look into extracting the empty-ctor filter from gencommon into something reusable for JS.

@back2dos

This comment has been minimized.

Copy link
Member

back2dos commented Feb 26, 2018

Uhm, if that works., sure :)

IIRC the reason for ES6 classes was that something doesn't get set when you use prototypes instead of classes.

@nadako

This comment has been minimized.

Copy link
Member

nadako commented Feb 26, 2018

IIRC the reason for ES6 classes was that something doesn't get set when you use prototypes instead of classes.

I'll have to research on that, maybe it's somehow related to classes implemented natively...

@nanjizal

This comment has been minimized.

Copy link

nanjizal commented Mar 1, 2018

I hear of OpenFL having Typescript support but not looked into it, what is the official approach on Angular and Typescript. In my area React seems popular :( but talked to a dev in Oxford, a lot of the science parks are using Angular so it won't disappear.

Is ES6 important or just an easier fruit, I get the impression supporting ES5 is pretty much enough at moment? But neglecting TS is a decision that matter, which direction Haxe chooses is important and I am not convinced a strategy has been discussed, I am kind of worried about OpenFL offering Typescript has not been discussed. The worry is that will all the toolkits end up getting rewritten in typescript, this could be a risk for Haxe's progress ? A plan in regard to Typescript should be made even if it's not public, but it should be about either to support or avoid it.

Completely off topic but related to the toolkit risk is should haxe foundation fork Luxe, it has always seemed more robust than openfl ( in the superficial aspect of out of the box ) and is simple and clean to use like heaps and does not need AIR so heaps in some respects is behind. But I am not sure it can compete with the power of Kha, but we seem to have already lost a buildable Flambe ( can be built by haxe vetrans for html but not by new users, and for c++ it seemed a bit broken last time I tried? ).

@back2dos

This comment has been minimized.

Copy link
Member

back2dos commented Mar 1, 2018

For ES6 classes, there are technical reasons to have them, because they introduce subtle differences with functions + prototypes. It's also not a rocket science, as shown in the hxgenjs (which also provides the TS support for OpenFl).

As for TypeScript support (which is a bit off topic here): being able to consume .d.ts files would be awesome for obvious reasons. And I think the ability to generate TypeScript is a good thing too. It's consistent with Haxe's principle of not locking you in and I wouldn't sacrifice that for some fear of funneling people away.

@ncannasse

This comment has been minimized.

Copy link
Member

ncannasse commented Mar 2, 2018

Regarding Typescript support, I've recently updated https://github.com/ncannasse/ts2hx to convert .d.ts to .hx

@skial skial referenced this issue Mar 8, 2018

Closed

Haxe Roundup 422 #484

1 of 1 task complete

@Simn Simn added this to the Design milestone Apr 17, 2018

@Simn Simn referenced this issue Sep 5, 2018

Closed

ES6 #47

@jgranick

This comment has been minimized.

Copy link

jgranick commented Sep 6, 2018

Regarding TypeScript, generating .d.ts files to coincide with generated .js could be helpful, especially if documentation is included as well. However, I'd be happy enough if we just get ES6 output, as that's basically what TypeScript is (with a different filename and optional annotations)

@Pign

This comment has been minimized.

Copy link

Pign commented Oct 7, 2018

Hello,

I have troubles following the conversation… What is the current status of this request? Is it accepted? Is it awaiting a proposal for language design?

@fullofcaffeine

This comment has been minimized.

Copy link

fullofcaffeine commented Nov 8, 2018

I'd like to know as well, as this is relevant to a current codebase of mine. Any news here?

@back2dos

This comment has been minimized.

Copy link
Member

back2dos commented Nov 8, 2018

I guess there are two issues:

  1. dealing with the super constructor call having to be called before accessing anything else on this
  2. supporting ES5 output as well, without creating too much of a mess.
@nadako

This comment has been minimized.

Copy link
Member

nadako commented Dec 8, 2018

I will implement the generation with super-call support as described before (have a wip branch already), but I think it'll release after 4.0 as this is quite a lot of changes and AFAIK we're in "soft-freeze" already.

@nadako

This comment has been minimized.

Copy link
Member

nadako commented Feb 20, 2019

implemented with -D js-es=6 since 406d3fb

@nadako nadako closed this Feb 20, 2019

@haxiomic

This comment has been minimized.

Copy link
Member

haxiomic commented Feb 20, 2019

Amazing stuff @nadako, thank you for working on this :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment