Giter Club home page Giter Club logo

hxgenjs's Introduction

Discontinued. Check out https://github.com/benmerckx/genes as an alternative.

hxgenjs Build Status

Extensible JS generator for Haxe

The default configuration emits one javascript file per Haxe class, and uses CommonJS (require()) to link the dependencies. It should work out of the box with your current Node.js project, React Native project or any other CommonJS-compatible runtimes. For browsers usage you can use packagers such as Webpack or Browserify, etc.

Note: This is written for Haxe version >= 3.4, it may not be usable on earlier versions.

Usage

Simply install the library and add -lib hxgenjs to your project.

Options:

  • add -D js_es=6 if you want to generate ES6 classes.
  • add -D hxextern if you want to generate Haxe extern files.
  • add -D tsextern if you want to generate TypeScript definition files.
  • add -D genjs=no if you don't want to generate Javascript files.

Custom Generators

  1. Implements the interfaces in the genjs.generator package (IClassGenerator, IEnumGenerator, IMainGenerator)
  2. Configure hxgenjs:
class Setup {
	public static function setup() {
		var customConfig:genjs.Generator.Config = ...;
		genjs.Generator.generators.push(customConfig);
	}
}

Then run it as init macro in your build: --macro Setup.setup()

Work in progress

  • Generate javascript file per Haxe class
  • Handle @:expose
  • Standardize way to configure the generator

hxgenjs's People

Contributors

back2dos avatar benmerckx avatar jgranick avatar joshtynjala avatar kevinresol avatar tbyrne-imag avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hxgenjs's Issues

Type information generated for d.ts extern definitions

Aloha!

I've been experimenting a bit more with hxgenjs and been playing with a hybrid TS<>HX approach for rapid app development. You can read a bit more about it here, the WIP source is here.

When trying the -D tsextern feature, I noticed that all type information is lost and Any is used instead. I have a few questions about that:

  1. I assume that's because this version is still rough and data mappings between both haven't been implemented?
  2. Are there any plans to implement it?
  3. Any tricky scenarios where it'd be hard to map types from HX>TS?

cc @jgranick

@:jsRequire object to load from module, not supported by hxgenjs?

I'm using the latest version of hxgenjs and I have the following extern class:

package externs.angular;

@:jsRequire('@angular/platform-browser-dynamic', 'platformBrowserDynamic')
  extern class PlatformBrowserDynamic implements Dynamic {
    @:selfCall public function new() {}
 }

As far as I understand, the @:jsRequire above should generate something like:

function externs_angular_PlatformBrowserDynamic() {return require("@angular/platform-browser-dynamic").platformBrowserDynamic;}

But it's generating it without the call to the platformBrowserDynamic object:

function externs_angular_PlatformBrowserDynamic() {return require("@angular/platform-browser-dynamic");}

The documentation for @:jsRequire (https://haxe.org/manual/target-javascript-require.html) states that the second argument to the metatag is an object to load from module.

Am I missing something here or does that mean that this functionality is not implemented in hxgenjs for the @:jsRequire tag?

Thanks in advance!

improve gen extern return type

HxExternClassGenerator.hx
	var processField = function (field:haxe.macro.ClassField, isStatic:Bool) {
			var fieldCode = "";
			
			if (field != null && field.type != null) {

				//trace(field.type);
				switch (field.type) {
					case TFun(args, r):
						var params = "";
						var i = 0;
						for (arg in args) {
							if (params != "") params += ", ";
							var name = (arg.name != "" && arg.name != null) ? arg.name : "a" + (++i);

							switch (arg.t){
								    case TAbstract(t, _):
										params += (arg.opt ? "?" : "") + name + ":" + $v{t}/*arg.t.toString ()*/;	
									default:	
								     params += (arg.opt ? "?" : "") + name + ":" + "Dynamic"/*arg.t.toString ()*/;	
							}
						
						}
						
						//fieldCode = ((c.type.superClass != null && hasField(field.name, c.type.superClass.t)) ? "override " : "") + (isStatic? "static " : "") + "function " + field.name + "(" + params + ")" + (field.name != "new" ? ":Dynamic" : "") + ";";
				        switch(r){
							case TAbstract(t,_):

								fieldCode = ((c.type.superClass != null && hasField(field.name, c.type.superClass.t)) ? "override " : "") + (isStatic? "static " : "") + "function " + field.name + "(" + params + ")" + (field.name != "new" ? ":"+$v{t} : "") + ";";
						     case TInst(t,_):
								fieldCode = ((c.type.superClass != null && hasField(field.name, c.type.superClass.t)) ? "override " : "") + (isStatic? "static " : "") + "function " + field.name + "(" + params + ")" + (field.name != "new" ? ":"+$v{t} : "") + ";";
								default:
								fieldCode = ((c.type.superClass != null && hasField(field.name, c.type.superClass.t)) ? "override " : "") + (isStatic? "static " : "") + "function " + field.name + "(" + params + ")" + (field.name != "new" ? ":Dynamic" : "") + ";";
							}
						case TInst(t, _):
						
						fieldCode = (isStatic? "static " : "") + "var " + field.name + ":"+$v{t}+";";
					case TAbstract(t, _):
						fieldCode = (isStatic? "static " : "") + "var " + field.name + ":"+$v{t}+";";
					default:
				}
			}

			
			body += "\t" + fieldCode + "\n";
		}

before

package;

@:jsRequire("MyCustomCompontHx")
extern class MyCustomCompontHx_ex extends global.cc.Component {
	function new();
	var power:Dynamic ;
	function getPower():Dynamic;
}

after

package;

@:jsRequire("MyCustomCompontHx")
extern class MyCustomCompontHx_ex extends global.cc.Component {
	function new();
	var power:Int;
	function getPower():Int;
}

support haxe4?

support haxe4?

public static function use() {
if (!Context.defined('js')) return;
Context.onMacroContextReused(function() return false);

//--------------------------------

@:deprecated
public static function registerModuleReuseCall( modulePath : String, macroCall : String ) {
throw "This method is no longer supported. See HaxeFoundation/haxe#5746";
}

@:deprecated
public static function onMacroContextReused( callb : Void -> Bool ) {
	throw "This method is no longer supported. See https://github.com/HaxeFoundation/haxe/issues/5746";
}

getting error in tink_core

I'm trying to convert haxe to es6 version, but getting this error

tink_macro/0,14,1/src/tink/macro/Types.hx:20:` characters 8-12 : Unknown identifier : Some
/haxelib/tink_macro/0,14,1/src/tink/macro/Types.hx:23: characters 61-65 : Unknown identifier : None
/haxelib/tink_macro/0,14,1/src/tink/macro/Types.hx:24: characters 13-39 : Dynamic should be Void

Just wondering if I'm missing something here.

Compilation time with a react-next project

Hi there !

I'm looking for advises.

We are trying to use hxgenjs in order to enable hot reloading in a React native project (debug mode).
We are almost there. The only thing now that is still a problem is the time it takes to compile the project with hxgenjs.

I've read this issue where @back2dos suggests to use --macro include and exclude and here is what I get:

When compiling the entire project (no exclusion):

name     | time(s) |   % |     # | info
----------------------------------
analyzer |   0.360 |   2 | 59584 | 
filters  |   0.190 |   1 |     2 | 
generate |   0.000 |   0 |     1 | 
  js     |   0.000 |   0 |     1 | 
haxelib  |   0.000 |   0 |     1 | 
macro    |  12.720 |  82 |  2416 | 
other    |   0.850 |   5 |     1 | 
parsing  |   0.340 |   2 |  1211 | 
typing   |   1.050 |   7 | 29043 | 
----------------------------------
total    |  15.510 | 100 |     0 | 

When compiling only one file (excluding all other packages and libs):

name     | time(s) |   % |     # | info
----------------------------------
analyzer |   0.360 |   3 | 59485 | 
filters  |   0.120 |   1 |     1 | 
generate |   0.000 |   0 |     1 | 
  js     |   0.000 |   0 |     1 | 
haxelib  |   0.000 |   0 |     1 | 
macro    |  11.850 |  83 |  2443 | 
other    |   0.360 |   3 |     1 | 
parsing  |   0.220 |   2 |  1100 | 
typing   |   1.350 |   9 | 29041 | 
----------------------------------
total    |  14.260 | 100 |     0 | 

I was expecting a greater improvement :)...

Here is the score we have without hxgenjs:

name     | time(s) |   % |     # | info
----------------------------------
analyzer |   0.340 |   4 | 59584 | 
filters  |   0.210 |   2 |     1 | 
generate |   0.150 |   2 |     1 | 
  js     |   0.150 |   2 |     1 | 
haxelib  |   0.000 |   0 |     1 | 
macro    |   5.960 |  67 |  2406 | 
other    |   0.920 |  10 |     1 | 
parsing  |   0.310 |   3 |  1078 | 
typing   |   1.020 |  11 | 29042 | 
----------------------------------
total    |   8.910 | 100 |     0 | 

Which is already high though...

But I'm surprised that we don't get a better score when compiling a single file. Any idea?

Variables of type Void are not allowed

I'm getting the following error:
Variables of type Void are not allowed

unfortunately there is any more info than this... any idea what the root cause might be?

Binding 'eval' in strict mode (108:20)

hi,just test with heaps framework ,and got this error.

haxe -lib heaps -lib hxgenjs -cp src -cp samples -js Y:/test/test/src/components/haxe/haxetest.js -main Main -dce no -D hxextern

haxe version:3.4.7

shareshader.js
run in vue

image

ES6 super call ordering

I know there has been a big discussion about how to generate ES6 constructors, with the restrictions that ES6 implements (in the Haxe repo).

I've taken a crack at resolving this in a slightly different way (as it doesn't seem to have any solution in hxgenjs).

Basically I've made it so that the only classes that implement a 'real' ES6 constructor are those which don't extend another class.
They all have exactly the same constructor:

constructor() {
	this._hx_constructor.apply(this, arguments);
}

Every class that extends another class doesn't define a 'real' es6 constructor at all.
All of the constructors as defined in Haxe get named _hx_constructor and they can retain their original code ordering.
This only works because JS doesn't enforce override methods to have the same signature as the original method, and because JS has the arguments array.

I've just written this today, so there may be some things I haven't taken into account, let me know @back2dos .

Pros:

  • Simpler than Haxe compiler solution
  • Allows 'this' to be accessed whenever (as in Haxe)

Cons:

  • The signature of the constructor is always zero-param, even when it actually does accept arguments, so it's not as legible. This isn't a 'real' issue if you're using TS definitions. Might also be able to generate javadoc style comments in front of constructors to fool IDE's type hinting.
  • If you're using everything in an ES6 compatible manner, it doesn't omit this workaround (could be fixed).

Generation Error catch variable

Hello,

Generation (es6mode if that does have an impact) of the haxe-thunk library give the following generated code :

original

public function middleware(action:Thunk<TState, TParams>, next:Void->Dynamic):Any {
		return switch (action) {
			case Action(cb):
				cb(store.dispatch, store.getState);

			case WithParams(cb):
				cb(store.dispatch, store.getState, this.params);
		};
	}

generated

switch((Type().default).enumIndex(action)) {
		case 0:
			var cb = action[2];
			return cb(($_=this.store,$bind($_,$_.dispatch)),($_=this.store,$bind($_,$_.getState)));
		case 1:
			var cb1 = action[2];
			return cb1(($_=this.store,$bind($_,$_.dispatch)),($_=this.store,$bind($_,$_.getState)),this.params);
		}

The execution (react-native bundler) complains about $_ variable which cannot be found

NodeJS compilation

I try to compile and run yout test ptoject, but I got this error when I wanted to run with node:

`$ node RunTests.js
/Volumes/Work/Haxe/git/hxgenjs/js/RunTests.js:3
(RunTests().default).main();
^

TypeError: Cannot read property 'main' of undefined
`

I also try to create custom node project, but I got the same error.
What do I wrong?

Use together with ufront nodejs target

I need to use hxgenjs with ufront (and some other lib) nodejs target.

build.hxml:

genjs.hxml

-lib hxgenjs

--macro allowPackage("sys")
-lib ufront-mvc
-lib hxnodejs
-lib js-kit
-lib smtpmailer
-lib record-macros
-lib gotocorehaxe
-lib gotocorehxnode
-lib erazor
-lib haxe-crypto
-lib hxnodejs-jsonwebtoken
-lib express
-lib tink_streams
-lib dotenv
-lib exceljs-hx
-js genjs/www/index.js
-dce full

genjs.hxml:

-cp src
-main Server


haxe build.hxml

src/model/api/AuthApi.hx:128: characters 63-67 : Unknown identifier : auth
src/model/api/AuthApi.hx:128: characters 63-67 : For function argument 'value'
/Volumes/Work/Haxe/libs/ufront-mvc/git/src/ufront/api/UFAsyncApi.hx:95: characters 2-67 : Missing return: tink.Surprise<_makeApiCall.A, tink.TypedError<ufront.remoting.RemotingError<_makeApiCall.B>>>
/Volumes/Work/Haxe/libs/ufront-mvc/git/src/ufront/web/result/CallJavascriptResult.hx:99: characters 16-24 : Unknown identifier : document
/Volumes/Work/Haxe/libs/ufront-mvc/git/src/ufront/web/result/CallJavascriptResult.hx:106: characters 17-25 : Unknown identifier : document
/Volumes/Work/Haxe/libs/ufront-mvc/git/src/ufront/web/result/CallJavascriptResult.hx:112: characters 4-12 : Unknown identifier : document
/Volumes/Work/Haxe/libs/ufront-mvc/git/src/ufront/web/result/CallJavascriptResult.hx:113: characters 4-12 : Unknown identifier : document

Memory consumption + Speed

This library is in general pretty fast!

I was wondering what would your suggestions be in terms of performance improvements, and where memory can be saved? I've been gradually testing hxgenjs by adding more and more classes from our main project, and I'm running out of 10 GB memory for projects that hit 10k classes. Ideally I'd like to run it on 30k+ classes ( most of them extend e.g. MovieClip or each other ).

In a project with 6k classes, the hxgenjs generator takes about :

 28 seconds | to read in types
 90 seconds | generate 6068 types
 15 seconds | write 5449 types
----------------------------------
135 seconds total in `--times`

My initial attempts were :

  • to filter what ends up in the ClassProcessor cache ( only id and externType seem to be needed /re-used )
  • changing DynamicAccess for stubs and typeIds to Map<String, Bool>(); & Map<TypeID, Bool>()
  • changing functions declarations inside methods to static functions, so they're not re-generated for every type
  • moving api to a static public class, so it's not passed through everywhere

But with not much luck yet. Any other ideas?

Could not find super call - Haxe 4.0.0rc3

I'm finding that the wild super() detection code in ClassGenerator isn't working in haxe4rc3.
I think I have a fix but I don't fully understand how it works, @back2dos?

Simple case:

class Main extends Superclass
{
	static public function main(){
		var test = new Main();
	}
	public function new(){
		super();
	}
}

class Superclass
{
	public function new(){}
}
// Gives error: Could not find super call

I think that the super call generated by JSGenApi has changed from something like Superclass.call(this) to just super() (at least in some cases).

My fix is to first search for the old syntax, then if that isn't found search for plain old 'super()', then continue on with the existing logic. It'd be good to get some confirmation that my assumptions here are accurate though.

var superCall = '$v.call(this';
var ind = ctor.indexOf(superCall);
if(ind == -1) ind = ctor.indexOf('super(');
switch ind { // continue on with existing switch

May be a duplicate of:
#34

Using Date

class Main {
  static function main() trace(Date.now());
}

Results in:

Main.js:33
        console.log(new $hxClasses["Date"]());
                    ^
TypeError: $hxClasses.Date is not a constructor

Or just trace(Date) logs undefined.

Fails when code contains template-like code

This example throws an exception

class Main
{
	public static function main()
	{
		trace("::" + Math.random());
	}
}
// Build: haxe -lib hxgenjs -p . -m Main --js bin/main.js

Exception:

Uncaught exception Unexpected '=' in  value = " +

Error when exporting to the same directory

I meant to try and resolve this myself, but for now I'd like to keep track of it using an issue. If you use -lib hxgenjs then use something like -js out.js, there are errors in paths, due to the target path having a trailing slash, resulting in "/" as the path, which does not exist on Windows, and is the wrong path on macOS and Linux. I'm sure this is a simple fix

jquery is generated to ::$::

haxe source

import js.jquery.JQuery;
....
 new JQuery(function() {
            new Admin();
        });

js output

::$::(function() {
		new Admin();
	});

so of course this has error while browserify:

browserify -t haxeify public/js/admin/Admin.js > public/js/AADDIIMMIINN.js
SyntaxError: Unexpected token (38:2) while parsing /Volumes/Work/develop/js/devinflow.hu/public/js/admin/Admin.js while parsing file: /Volumes/Work/develop/js/devinflow.hu/public/js/admin/Admin.js
    at DestroyableTransform.end [as _flush] (/usr/local/lib/node_modules/browserify/node_modules/insert-module-globals/index.js:114:21)
    at DestroyableTransform.prefinish (/usr/local/lib/node_modules/browserify/node_modules/readable-stream/lib/_stream_transform.js:138:10)
    at DestroyableTransform.emit (events.js:182:13)
    at prefinish (/usr/local/lib/node_modules/browserify/node_modules/readable-stream/lib/_stream_writable.js:619:14)
    at finishMaybe (/usr/local/lib/node_modules/browserify/node_modules/readable-stream/lib/_stream_writable.js:627:5)
    at endWritable (/usr/local/lib/node_modules/browserify/node_modules/readable-stream/lib/_stream_writable.js:638:3)
    at DestroyableTransform.Writable.end (/usr/local/lib/node_modules/browserify/node_modules/readable-stream/lib/_stream_writable.js:594:41)
    at DestroyableTransform.onend (/Volumes/Work/develop/js/devinflow.hu/node_modules/through2/node_modules/readable-stream/lib/_stream_readable.js:523:10)
    at Object.onceWrapper (events.js:275:13)
    at DestroyableTransform.emit (events.js:187:15)

HMR support

From gitter (thanks @elsassph):

So looking at the generated code, if you would insert this bit at the end of each React component file it should do the HMR without babel:

var $hmr = require("react-transform-hmr");
var $wrap = $hmr({
    filename: "/path/to/App.js",
    components: {"App":{"displayName":"App"}},
    locals: [module],
    imports: [require("react")]
});
myapp_App = $wrap(myapp_App, "App");

ES modules

Did you look into supporting the es module syntax? Would haxe's static intialization make it hard or can it be attempted?

generate openfl with away3d

I try to compile a simple away3d project, with hxgenjs.
Without hxgenjs is working, but with it i got thie:

(anonymous function) Uncaught ReferenceError: require is not defined Load3DS.js:1
the first line of the file is
require("./Std")

Ok so I add the requirejs to the index.html
<script type="text/javascript" src="http://requirejs.org/docs/release/2.2.0/minified/require.js"></script>
But after I got this:


F	m	requirejs	(anonymous function)	Uncaught Error: Module name "Std" has not been loaded yet for context: _. Use require([])
  
  
  
  
(anonymous function)	Uncaught ReferenceError: lime is not defined
  
F	P	(anonymous function)	Uncaught Error: Mismatched anonymous define() module: function (){return{Howler:t,Howl:n}}

What have I do?

thanks

Dce & abstracts

Seems like hxgenjs generates output for all abstracts even if their implementation is unused (even with -dce full).

image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.