Advanced Custom JS generator

235 views
Skip to first unread message

Porfírio Ribeiro

unread,
Jul 20, 2014, 1:02:48 PM7/20/14
to haxe...@googlegroups.com
Hi,

I have been trying to improve the ExampleJSGenerator included in Haxe to generate JS code just like the one generated by the native (ocaml) compiler.

For that i needed to be able to check and set "features", that is used by compiler to generate only needed JS.
Unfortunately that API wasn't available for custom JS generators so i submitted a pull request (https://github.com/HaxeFoundation/haxe/pull/3193) that adds `addFeature` and `hasFeature` to JSGenApi. I have barely no knowledge of ocaml, so that code might not be the best, please someone check it.

The code is available here: https://gist.github.com/porfirioribeiro/4202abd244e78c8217cf

I tried to make it work with dce and all output modes: js-flatten, js-classic, etc...
Had a example compiling with native and macro generators and spend many time on a diff viewer to make macro generated code look like native one.

Currently there are still some cosmetic bugs, some indents are not outputting right and some properties are ordered differently.
The only missing code i found is `Math.__name__ = ["Math"];`, for some reason `Math` is not being passed to the generator.
But everything works ok.
Obviously the macro generating takes a bit more time than the native.

I tough about include these changes to  ExampleJSGenerator and include it in the pull request, but it might be too complex for an example.

If someone want to try this generator on their projects, don't forget you need the pull request, while and if it isn't accepted.

Usages for this? Extend it to support other JS libraries, but have a good base to start. Thats the reason i worked on this, extending ExampleJSGenerator wasn't good enough.

Dan Korostelev

unread,
Jul 20, 2014, 1:36:35 PM7/20/14
to haxe...@googlegroups.com
To be honest, I'd like the whole "custom js generator" feature to be deprecated and replaced by "onGenerate" macros and the new TypedExpr stuff, but it's still not quite possible because we can't override platform-specific compiler behaviour from macros (see https://github.com/HaxeFoundation/haxe/pull/2588).

воскресенье, 20 июля 2014 г., 21:02:48 UTC+4 пользователь Porfírio Ribeiro написал:

Porfírio Ribeiro

unread,
Jul 20, 2014, 2:23:48 PM7/20/14
to haxe...@googlegroups.com

Can "onGenerate" macros change the actual output JS code? I didn't knew that.
It's far from being a perfect solution but it's what we have.

I'll explain why i need it.

I am working on making html5 custom elements, as the spec says http://w3c.github.io/webcomponents/spec/custom/#dfn-document-registerElement, elements are registed with document.registerElement and the prototype is generated with Object.create. something like this JS:

var XBtn = window.XBtn = document.registerElement(
       
'x-btn',{
          prototype
: Object.create(
           
HTMLButtonElement.prototype, {
            createdCallback
: {value: function() {
                console
.log("created: x-btn");
           
}}
           
//etc
         
})
       
}
     
);

So i want to change the JS generation of some specific classes so that they match this convention.
Code would still be compatible with other haxe code.

I have no idea if i can do that with onGenerate macros, i'll have a look.

Chris Anderson

unread,
Jul 22, 2014, 12:17:37 PM7/22/14
to haxe...@googlegroups.com
I'm really interested in this direction too.  For both html5 custom templates and similarly Polymer (which seems to eventually boil down to the same behavior and adds some polyfills).  I've been tied up with day to day Flex work but tried squeezing in time to research reading and writing Polymer components.  It's been real slow however because I'm a beginner with Haxe and especially macros (if they are even needed for this task).  As you make progress do you mind notifying us here?  Appreciate the help.

Porfírio Ribeiro

unread,
Jul 22, 2014, 2:40:21 PM7/22/14
to haxe...@googlegroups.com
Curently i am changing the generation of classes to match the custom element format.
A class like this:
package test;
@:keep
@:registerElement("hx-btn")
class Btn extends js.html.Element {
   
function createdCallback(){
       
var shadow:js.html.Element = untyped this.createShadowRoot();
       
var text=getAttribute("text");
        shadow
.innerHTML='<input type="button" value="$text" />';
   
}
   
function attachedCallback(){}    
   
function detachedCallback(){}    
   
function attributeChangedCallback(attrName:String, oldVal:String, newVal:String){}
}
That generates:
var test_Btn = document.registerElement("hx-btn",{
    prototype
: Object.create(Element.prototype, {
        createdCallback
:{value: function() {
           
var shadow = this.createShadowRoot();
           
var text = this.getAttribute("text");
            shadow
.innerHTML = "<input type=\"button\" value=\"" + text + "\" />";
       
}},
        attachedCallback
:{value: function() {
       
}},
        detachedCallback
:{value: function() {
       
}},
        attributeChangedCallback
:{value: function(attrName,oldVal,newVal) {
       
}}
   
})
});
That let me use in html this:
<hx-btn text="works"></hx-btn>

Still a work in progress, allot need to be done.
I'll put the code in a github repo as soon i have time.

Chris Anderson

unread,
Jul 22, 2014, 3:04:28 PM7/22/14
to haxe...@googlegroups.com
This is a great help, really do appreciate it too.
Reply all
Reply to author
Forward
0 new messages