Haxe js package conflict

234 views
Skip to first unread message

Adrian Martinez

unread,
Sep 19, 2014, 7:38:19 AM9/19/14
to haxe...@googlegroups.com

Hi all,


I got quit an important issue to address.

I hope this gets a bit of attention because I'm planning to use this technic all over the place.

I'm trying to create js modules and loading them dynamically.


The problem I got is when 2 different Modules recite in the same package the last loaded Module redefines the the package of the current existing Module.


I 'll give an example.

I got class modules.Module1 and modules.Module2, both have the @:expose metadata.

Module1 is accessing Module2 by an extern class.


The js code looks like this:


<body>

<script type="text/javascript" src="Module2.js"></script>

<script type="text/javascript" src="Module1.js"></script>
</body>


I highlighted the imported part in red.


modules.Module2

(function ($hx_exports) { "use strict";
$hx_exports.modules = $hx_exports.modules || {};
var modules = {};
modules.Module2 = $hx_exports.modules.Module2 = function() {
};
modules.Module2.main = function() {
};
modules.Module2.prototype = {
fromModule2: function() {
return "fromModule2";
}
};
modules.Module2.main();
})(typeof window != "undefined" ? window : exports);


modules.Module1
(function ($hx_exports) { "use strict";
$hx_exports.modules = $hx_exports.modules || {};
var modules = {};
modules.Module1 = $hx_exports.modules.Module1 = function() {
};
modules.Module1.main = function() {
var module1 = new modules.Module1();
var module2 = new modules.Module2();
console.log(module1.fromModule1());
console.log(module2.fromModule2());
};
modules.Module1.prototype = {
fromModule1: function() {
return "fromModule1";
}
};
modules.Module1.main();
})(typeof window != "undefined" ? window : exports);


What happens is that Module1 redefines the package modules whereby it cannot longer access modules.Modules2


My browser gives me this error:

TypeError: modules.Module2 is not a constructor

var module2 = new modules.Module2();


So my question is how can this be fixed?

Is there an already existing fix?

And so not is this gonna be fixed in the future versions of the haxe js compiler?


Adrian


Andreas Mokros

unread,
Sep 19, 2014, 7:53:54 AM9/19/14
to haxe...@googlegroups.com
Hi.

On Fri, 19 Sep 2014 04:38:19 -0700 (PDT)
Adrian Martinez <adria...@gmail.com> wrote:
> What happens is that Module1 redefines the package modules whereby it
> cannot longer access modules.Modules2

$hx_exports.modules = $hx_exports.modules || {};
looks OK to me. window.modules should be used when it exists, shouldn't
it?

> My browser gives me this error:
> TypeError: modules.Module2 is not a constructor
> var module2 = new modules.Module2();

When and where do you call this? Maybe Module2.js is not loaded?

--
Mockey

adrian martinez

unread,
Sep 19, 2014, 8:41:51 AM9/19/14
to haxe...@googlegroups.com
Hi Mockey,

Thanks for your response!

> $hx_exports.modules = $hx_exports.modules || {};
> looks OK to me. window.modules should be used when it exists, shouldn't
> it?


That's right, but below $hx_exports.modules = $hx_exports.modules || {}; there's another line that does:
var modules = {};

This breaks the access to modules.

> When and where do you call this? Maybe Module2.js is not loaded?


Module2,js is definitely loaded because I put it as <script> in my html file for this test.
The call is made from modules.Module1.main, check the code above, I highlighted it in red.
Apparently the call does not reach the window object, but get's stuck at var modules = {};

Adrian
> --
> To post to this group haxe...@googlegroups.com
> http://groups.google.com/group/haxelang?hl=en
> ---
> You received this message because you are subscribed to a topic in the Google Groups "Haxe" group.
> For more options, visit https://groups.google.com/d/optout.

Andreas Mokros

unread,
Sep 19, 2014, 8:58:08 AM9/19/14
to haxe...@googlegroups.com
Hi.

On Fri, 19 Sep 2014 14:41:41 +0200
adrian martinez <adria...@gmail.com> wrote:
> That's right, but below $hx_exports.modules = $hx_exports.modules ||
> {}; there's another line that does: var modules = {};
> This breaks the access to modules.

Yeah, you're right. It should be:
var modules = $hx_exports.modules || {};

$hx_exports.modules = $hx_exports.modules || {};
doesn't really make sense.

File an issue. Shouldn't take long to get that fixed. What does your .hx
look like? Maybe a workaround with __js__ is possible for now.

--
Mockey

Adrian Martinez

unread,
Sep 19, 2014, 9:21:34 AM9/19/14
to haxe...@googlegroups.com
Hi Mockey,

Yeah your fix seems to work fine when I adjust the js code.
Alright I will do that, is this the place to file issues: https://github.com/HaxeFoundation/haxe/issues ?
Do you have any suggestion for using a temporary fix with __js__ ?
My haxe code is pretty plain forward, I simplified it to the minimum for this test.

modules.Module1
package modules;

import externs.Module2;

@:expose
class Module1 
{
public static function main() : Void
{
var module1 = new Module1();
var module2 = new Module2();
trace( module1.fromModule1() );
trace( module2.fromModule2() );
}
public function new(){}
public function fromModule1() : String
{
return "fromModule1";
}
}

modules.Modules2
package modules;

@:expose
class Module2 
{
public static function main(){}
public function new(){}
public function fromModule2() : String
{
return "fromModule2";
}
}

externs.Module2
package externs;

@:expose
@:native("modules.Module2")

extern class Module2 
{
public function new();
public function fromModule2() : String;
}

Adrian

Op vrijdag 19 september 2014 14:58:08 UTC+2 schreef Andreas Mokros:

Andreas Mokros

unread,
Sep 19, 2014, 12:51:38 PM9/19/14
to haxe...@googlegroups.com
Hi.

On Fri, 19 Sep 2014 06:21:33 -0700 (PDT)
Adrian Martinez <adria...@gmail.com> wrote:
> Alright I will do that, is this the place to file
> issues: https://github.com/HaxeFoundation/haxe/issues ?

Yes.

> Do you have any suggestion for using a temporary fix with __js__ ?

Yes, you could add something like:
static function __init__()
untyped __js__("modules = $hx_exports.modules");
to Module1

Maybe you know this already, but you could put something like this in
your hxml:

-js Module1.js
-main modules.Module1
--macro exclude('modules.Module2') #no need for extern
--next
-js Module2.js
modules.Module2 #no need for main function

--
Mockey

Adrian Martinez

unread,
Sep 19, 2014, 2:36:41 PM9/19/14
to haxe...@googlegroups.com
Hi Mockey,

No I didn't know about all those things: 
__init__
-main thingy
and exclude()

Very helpful, this really makes things a lot easier, especially not having to mess with externs!
I've addressed the issue at HaxeFoundation so hopefully the issue gets resolved some time soon.

In the meantime I will use your excellent hack! :)
Thanks a lot!

Adrian

Philippe Elsass

unread,
Sep 19, 2014, 3:22:56 PM9/19/14
to haxe...@googlegroups.com
Interesting discussion, but this is incorrect:
var modules = $hx_exports.modules || {};

I mean, it "works" for what you want to do, but it's not correct because the hx_exports are supposed to be separated from the local definitions. With your change, all the declaration in the modules package will basically be automatically exported.

A good solution isn't simple, ideally @:expose (which is meant for exposing to JS not to Haxe) should have an opposite meta meant to point to a class exposed.

For now if you have an extern definition you can use @:native to explicitly use the definition in hx_exports:
@:native("$hx_exports.modules.Module2")
extern class Module2 {...}


--
You received this message because you are subscribed to the Google Groups "Haxe" group.

For more options, visit https://groups.google.com/d/optout.



--
Philippe

Andreas Mokros

unread,
Sep 19, 2014, 3:43:11 PM9/19/14
to haxe...@googlegroups.com
Hi.

On Fri, 19 Sep 2014 20:22:26 +0100
Philippe Elsass <philipp...@gmail.com> wrote:
> Interesting discussion, but this is incorrect:
> var modules = $hx_exports.modules || {};
>
> I mean, it "works" for what you want to do, but it's not correct
> because the hx_exports are supposed to be separated from the local
> definitions. With your change, all the declaration in the modules
> package will basically be automatically exported.

Hmm yes, in a normal haxe-js (all classes in one js function block) you
would have only one var module. Not good, I agree.
Better leave it as a hack then ;-) Or another meta @:exposeModule maybe?

> For now if you have an extern definition you can use @:native to
> explicitly use the definition in hx_exports:
> @:native("$hx_exports.modules.Module2")
> extern class Module2 {...}

This is not about externs (as far as I understood at least), but about
separate haxe-generated js-modules (without duplicate code).
Also there is no $hx_exports outside the function. $hx_exports is just a
local var meaning window or exports.
And an extern with @:native("modules.Module2") Adrian also tried.

--
Mockey

Philippe Elsass

unread,
Sep 19, 2014, 5:26:55 PM9/19/14
to haxe...@googlegroups.com
Of course you can use $hx_exports anywhere in your code.

Here's one way to making modules:

That approach however doesn't scale if you want to use many classes from a loaded module, but that can be nice for a modular website where each module's functionality is well encapsulated.


--
To post to this group haxe...@googlegroups.com
http://groups.google.com/group/haxelang?hl=en
---
You received this message because you are subscribed to the Google Groups "Haxe" group.
For more options, visit https://groups.google.com/d/optout.



--
Philippe

Andreas Mokros

unread,
Sep 19, 2014, 6:05:53 PM9/19/14
to haxe...@googlegroups.com
Hi.

On Fri, 19 Sep 2014 22:26:32 +0100
Philippe Elsass <philipp...@gmail.com> wrote:
> Of course you can use $hx_exports anywhere in your code.

Well, ok, if the loading module is exposed itself, then $hx_exports
happens to be defined there. $hx_exports is not a global var it's just
a var passed to the factory function. And as it's passed as window, it
might be better to write:
@:native("window.modules.Module2")
in your example. That can be used without exposing Module1.

> That approach however doesn't scale if you want to use many classes
> from a loaded module, but that can be nice for a modular website
> where each module's functionality is well encapsulated.

What about that new @:jsRequire stuff? Couldn't that be used for
something like that?

--
Mockey

Adrian Martinez

unread,
Sep 19, 2014, 8:01:23 PM9/19/14
to haxe...@googlegroups.com
Hi guys,

Why would be this nesecerly be a bad thing?
var modules = $hx_exports.modules || {};

I mean oke it exposes al subclasses, so what?
What is actually bad about this?

I'm actually wondering why not all classes are exposed by default?
This would make it accessing them from other places more approachable.
Why are they not just accessible from the window object:
window.modules.etc.

Mockey, if i change
@:native("$hx_exports.modules.Module2") 
into 
@:native("window.modules.Module2") 
I get this error:
TypeError: "window" is read-only
$hx_exports.window = $hx_exports.window || {};

Adrian

Andreas Mokros

unread,
Sep 19, 2014, 8:26:01 PM9/19/14
to haxe...@googlegroups.com
Hi.

On Fri, 19 Sep 2014 17:01:23 -0700 (PDT)
Adrian Martinez <adria...@gmail.com> wrote:
> Why would be this nesecerly be a bad thing?
> var modules = $hx_exports.modules || {};
> I mean oke it exposes al subclasses, so what?
> What is actually bad about this?

Well, normally you should not pollute the global namespace in JS.

> I'm actually wondering why not all classes are exposed by default?
> This would make it accessing them from other places more approachable.
> Why are they not just accessible from the window object:
> window.modules.etc.

You can actually have this with -D js-classic in your hxml. This is the
old js generation style of haxe, all global, but as I said, generally
it's considered bad practice.

> Mockey, if i change
> @:native("$hx_exports.modules.Module2")
> into
> @:native("window.modules.Module2")
> I get this error:
> TypeError: "window" is read-only
> $hx_exports.window = $hx_exports.window || {};

The extern with @:native should not have @:expose metadata.

--
Mockey

Adrian Martinez

unread,
Sep 20, 2014, 6:17:52 AM9/20/14
to haxe...@googlegroups.com
Hi,

-D js-classic works even better :)
No use of __init__, @expose or @native.
And in conjunction with --macro exlude() the easiest to apply.
Everything is accessible just like when loading a flash library.

I can image when working with lots of different js files from different developers that there could occur duplicate namespaces or something. But in my project my haxe code is de leading factor. There's no js file imported in my html page that the compiler doesn't know about. I know exactly what I use and the compiler knows it too.

Philippe I appreciate your advise, while your example is maybe the most secure, it's also the most of work and if the compiler gets fixed it would be again a lot of work to change everything to the new. I find it in this situation quite favorable to use -D js-classic and if the haxe compiler gets fixed in the near future it would be easier to make the transition.

Thanks again guys!

Adrian

Andreas Mokros

unread,
Sep 20, 2014, 7:32:55 AM9/20/14
to haxe...@googlegroups.com
Hi.

On Sat, 20 Sep 2014 03:17:52 -0700 (PDT)
Adrian Martinez <adria...@gmail.com> wrote:
> -D js-classic works even better :)

A bit unusual, but if it works for you, why not?

> And in conjunction with --macro exlude() the easiest to apply.

About exclude, in your case it might be useful for module compilation to
exclude the whole modules-package except for one class. I have a patched
exclude that does this. Useful for you?

> Everything is accessible just like when loading a flash library.

Well, Flash has ApplicationDomains and stuff like this, doesn't it?

> I can image when working with lots of different js files from
> different developers that there could occur duplicate namespaces or
> something. But in my project my haxe code is de leading factor.
> There's no js file imported in my html page that the compiler doesn't
> know about. I know exactly what I use and the compiler knows it too.

It's not only about namespaces. In complex JS-apps you can get garbage
collection problems with too many global vars.

> I find it in this situation quite favorable to use -D js-classic
> and if the haxe compiler gets fixed in the near future it would be
> easier to make the transition.

I don't think there's really anything to fix in the compiler here. It
works correctly for the usual haxe-js setup (compile everything to one
js-file, only expose certain parts) and according to common
js-practices. Your setup is a bit special but haxe is already flexible
enough to deal with it, be it with js-classic.

BTW: In my use-cases it was always better in the to load one file and
have it cached then.

--
Mockey

Adrian Martinez

unread,
Sep 20, 2014, 10:10:46 AM9/20/14
to haxe...@googlegroups.com
Hi,

> I don't think there's really anything to fix in the compiler here. It
> works correctly for the usual haxe-js setup (compile everything to one
> js-file, only expose certain parts) and according to common
> js-practices.

How can this not be a bug?
When I for example change the root package from modules.Module2 into modules2.Modules2, expose it and then call it form modules.Module1 then everything go's well.
But when they recite in the same package then this conflict occurs.
Where would the @:expose keyword be for otherwise?
Maybe if a class is marked by @:expose it should be called by default like:
var module2 = new $hx_exports.modules.Module2();
instead of:
var module2 = new modules.Module2();
This is essentieally what the extern with @:native("$hx_exports.modules.Module2") does.

> It's not only about namespaces. In complex JS-apps you can get garbage
> collection problems with too many global vars.

Now I'm afraid using -D js-classis :)
I can't have such complications I'm my projects.
What are to manny global vars?
Essentially my whole project would in this case recite under one package: var modules = modules || {};
Does that mean that one global var is used for the garbage collection?
Or are all the subclasses different global vars for the garbage collection?
I'm not sure how to see this.

> About exclude, in your case it might be useful for module compilation to
> exclude the whole modules-package except for one class. I have a patched
> exclude that does this. Useful for you?

I've noticed the method exclude() can also exclude a whole package by default, that's also what excited me: http://api.haxe.org/haxe/macro/Compiler.html
Is this what you mean?

> Well, Flash has ApplicationDomains and stuff like this, doesn't it?

That's right but when loaded all classes are available you don't have to mess with @:expose and such, less complicated.

> BTW: In my use-cases it was always better in the to load one file and
> have it cached then. 

I won't always use modules, but maybe in some cases when a project is really big it would be more practical to use modules.
I want therefore to be able to use both strategies, as a single file and as modules.

Adrian

Andreas Mokros

unread,
Sep 20, 2014, 11:23:48 AM9/20/14
to haxe...@googlegroups.com
Hi.

On Sat, 20 Sep 2014 07:10:46 -0700 (PDT)
Adrian Martinez <adria...@gmail.com> wrote:
> How can this not be a bug?
> But when they recite in the same package then this conflict occurs.
> Where would the @:expose keyword be for otherwise?

The @:expose keyword is for exposing parts of a haxe-generated js (which
is all in one file normally) to the global namespace. The problem is
that you have two haxe-generated files exposed in the same namespace.
Not sure if this is a setup that really needs to be considered,
especially if there are workarounds. But you filed the issue, we'll see
what happens.

> Maybe if a class is marked by @:expose it should be called by default
> like: var module2 = new $hx_exports.modules.Module2();

Maybe.

> Now I'm afraid using -D js-classis :)
> I can't have such complications I'm my projects.
> What are to manny global vars?

I don't know your projects. For global vars there's no global answer,
this one nails it pretty well IMHO:
http://stackoverflow.com/questions/8862665
There are probably good reasons for the common JS practices nowadays of
using closure functions as factories.

> That's right but when loaded all classes are available you don't have
> to mess with @:expose and such, less complicated.

When you compile to one single file you get the same. Besides, my
memories of Flash are all but less complicated.

> I won't always use modules, but maybe in some cases when a project is
> really big it would be more practical to use modules.

But you know that every haxe-generated js gets it's own code depending
on the features you use, don't you? If you use an array with some array
functions e.g. in both modules you'll get a lot of duplicate code. Very
hard to avoid.

--
Mockey

Philippe Elsass

unread,
Sep 20, 2014, 11:51:42 AM9/20/14
to haxe...@googlegroups.com
Ha! good point the whole point of expose is to attach the definitions to window :/ 

You can use js-classic if you want to keep things simple, but generally it's a better practice (ie. safer to avoid collisions and hiding classes that shouldn't be accessed otherwise) and possibly offers better performance to have a local scope instead of looking up in the overcrowded window object.


--
Mockey

--
To post to this group haxe...@googlegroups.com
http://groups.google.com/group/haxelang?hl=en
---
You received this message because you are subscribed to the Google Groups "Haxe" group.
For more options, visit https://groups.google.com/d/optout.



--
Philippe

Adrian Martinez

unread,
Sep 20, 2014, 1:05:39 PM9/20/14
to haxe...@googlegroups.com
Hi,

I actually would rather not take any risks with this.
I want the best of all worlds :)

Maybe I should just avoid creating modules that recite in the same package, mark the classes I want to be available with @:expose and exclude() the using modules.

The whole idea of the modules is to make my projects unlimited big and to only load what I need at the moment like a website where on each page there's different content.

> If you use an array with some array functions e.g. in both modules you'll get a lot of duplicate code. Very hard to avoid.

Yeah I know, I will be careful with that. Therefor I will try to use my own classes as much as possible since these will not be duplicated.

Philippe your example works fine for modules but if I would want to use the same classes in a non-modular way it gets quite complicated and is still a lot of work managing them. I think I'll avoid js-classic then because the use of modules are essentially meant for big projects and I want the best possible performance at all times. For simple projects I'll just use one js file without the use of modules.

Adrian

Philippe Elsass

unread,
Sep 20, 2014, 3:43:15 PM9/20/14
to haxe...@googlegroups.com
Obviously splitting the JS can get fairly complicated, that's why most of the time you don't do it. BTW we didn't start talking about dead-code elimination - with modules it could become quite painful...

In practice, even when you work in pure JS, people tend to combine everything (excepted some 3rd party libraries).

But let's imagine you have a fairly complex, rarely used, feature (say, a calendar) with one class as the entry point to create it, you can still have a standalone project/build and then different options for linking it:
- use the module approach,
- use untyped/Dynamic,
- use untyped/Dynamic (creation) and interfaces (setup/control).

--
To post to this group haxe...@googlegroups.com
http://groups.google.com/group/haxelang?hl=en
---
You received this message because you are subscribed to the Google Groups "Haxe" group.
For more options, visit https://groups.google.com/d/optout.



--
Philippe

Adrian Martinez

unread,
Sep 20, 2014, 4:24:44 PM9/20/14
to haxe...@googlegroups.com
Yeah I already know that dead-code-elimination is not possible working in modules.
But I could always choose to turn the module option off and compile it to one file with dce.
But I want to able to choose to to use it or not depending on the situation.
I'm sure there are enough situations where one would wish to use js modules instead of one js file.
Createjs for example works with modules.
If you use tweening you load the tween module and so on.
On facebook there are also approximately 50 weird named js files loaded on startup I'm sure there's something modular going on too.

I've thought about the Dynamic and use of interfaces but I would rather prefer to use the modules as I would use any other haxe library.
It would'nt be that complicated if the classes that have @:expose would be called from $hx_exports or window object.
I already  got a builder program who can generate the ideal build.hxml file with all the needed excludes and so on.
The only problem is the @:expose keyword.
If a class has @:expose you would expect it to be accessible from the window object.
It then needs to be called from there when instantiated: var module2 = new window.modules.Module2();
It wouldn't make sense not do so.
Well that's my opinion on this actually :)

Philippe Elsass

unread,
Sep 20, 2014, 5:51:51 PM9/20/14
to haxe...@googlegroups.com
Libraries like createjs are broken down into "modules" so that you are not forced to include the entire thing at once if you don't need everything - this is only useful because dead-code elimination is very difficult when working in JS while it is easy in Haxe ;)

--
To post to this group haxe...@googlegroups.com
http://groups.google.com/group/haxelang?hl=en
---
You received this message because you are subscribed to the Google Groups "Haxe" group.
For more options, visit https://groups.google.com/d/optout.



--
Philippe

Adrian Martinez

unread,
Sep 20, 2014, 7:41:02 PM9/20/14
to haxe...@googlegroups.com
Hi Philippe and Mockey,

Thanks for your help so far!
You guys have been very helpful!

I was looking on http://api.haxe.org/haxe/macro/Compiler.html and I noticed the addMetadata() method.
Wouldn't it be possible to use this in conjunction with exclude()?

--macro exclude("modules.Module2")
--macro addMetadata('@:native("window.modules.Module2")',"modules.Module2") //not sure how to apply this.

So the regular modules.Module 2 class would behave as the extern of Philippe.
Do you guys know if this is possible?

Adrian

Andreas Mokros

unread,
Sep 20, 2014, 8:26:38 PM9/20/14
to haxe...@googlegroups.com
Hi.

On Sat, 20 Sep 2014 16:41:02 -0700 (PDT)
Adrian Martinez <adria...@gmail.com> wrote:
> --macro exclude("modules.Module2")
> --macro
> addMetadata('@:native("window.modules.Module2")',"modules.Module2")

Should work, if you also add the @:expose to Module2 later:
--next
-js Module2.js
--macro addMetadata('@:expose', 'modules.Module2')
modules.Module2

--
Mockey

Adrian Martinez

unread,
Sep 21, 2014, 6:51:05 AM9/21/14
to haxe...@googlegroups.com
Hi guys,

Excellent! :)
Yeah this is by far the best solution:

-main modules.Module1
--macro exclude('modules.Module2')
--macro addMetadata('@:native("window.modules.Module2")','modules.Module2')
--next
modules.Module2

--macro addMetadata('@:expose','modules.Module2')

It has best of all worlds.
It looks maybe hard to manage the hxml file but it really isn't.
I got a nice little program who generates the hxml file for me.
So for me this is the easiest and cleanest way to work.

So eventually we all contributed to the solution.
We would make an excellent team.
Thanks again for the help guys!

Best, Adrian

Andreas Mokros

unread,
Sep 21, 2014, 7:36:13 AM9/21/14
to haxe...@googlegroups.com
Hi.

On Sun, 21 Sep 2014 03:51:05 -0700 (PDT)
Adrian Martinez <adria...@gmail.com> wrote:
> Excellent! :)
> Yeah this is by far the best solution:

Glad if you're pleased. As I said, compile macros give you a lot of
flexibility.

> --macro exclude('modules.Module2')
> --macro
> addMetadata('@:native("window.modules.Module2")','modules.Module2')

You could also put these two macro calls in one function to simplify it,
like:

class Macro {
static function useAsModule(mod:String) {
haxe.macro.Compiler.exclude(mod);
haxe.macro.Compiler.addMetadata('@:native("window.$mod")', mod);
}
}

--macro path.to.Macro.useAsModule('modules.Module2')

> I got a nice little program who generates the hxml file for me.

Which is that?

--
Mockey

Adrian Martinez

unread,
Sep 21, 2014, 8:32:53 AM9/21/14
to haxe...@googlegroups.com
Hi,

> You could also put these two macro calls in one function to simplify it,

Nice, yeah I was thinking something on those lines.
I'm definitely gonna use this. 

> Which is that? 

I created it myself in haxe of course.
But it still needs some work, especially now that I need to add the module functionality.
Hxml files can get hard to manage sometimes, especially when working with modules. 
That's where this tool comes in and makes things easy to manage.
I will upload it to github some time soon, I will let you know when I've done so ;)

Adrian


Adrian Martinez

unread,
Sep 21, 2014, 3:35:02 PM9/21/14
to haxe...@googlegroups.com
Hi Mockey,

It's actually quite simple to explain how this tool works.
I have my build.hxml file that looks like this:

-cp src/
--macro Build.main()
--next
buildscript.hxml

It calls Build.main() that looks like this:

package ;

import modules.Modules;
import modules.Module1;
import modules.Module2;

class Build 
{
public static function main() : Void
{
var builder = new Builder( Build );
var mod1 = builder.create.jsProject( Module1 );
var mod2 = builder.create.jsProject( Module2 );
mod2.useMainFunction = false;
mod1.setModules( Modules.Module1() );
mod2.setModules( Modules.Module2() );
builder.addProject( mod1 );
builder.addProject( mod2 );
builder.build();
//builder.print();
}
}

builder.build(); generates the required script and saves it to buildscript.hxml that is then invoced by build.hxml.
I'm not quite done with the modules part but I think this gives you an idea about what I mean.
This way I don't have to bother about spelling of classnames and I got code hinting giving me al the options and so on.
Quite neat hu?

Adrian

Op zondag 21 september 2014 13:36:13 UTC+2 schreef Andreas Mokros:

adrian martinez

unread,
Sep 23, 2014, 1:02:15 AM9/23/14
to haxe...@googlegroups.com
Hi,

> I don't think there's really anything to fix in the compiler here. It
> works correctly for the usual haxe-js setup (compile everything to one
> js-file, only expose certain parts) and according to common
> js-practices.


How can this not be a bug?
When I for example change the root package from modules.Module2 into modules2.Modules2, expose it and then call it form modules.Module1 then everything go's fine.
But when they recite in the same package then this conflict occurs.
Where would the @:expose keyword be for otherwise?
Maybe if a class is marked by @:expose it should be called by default like:
var module2 = new $hx_exports.modules.Module2();
instead of:
var module2 = new modules.Module2();
This is essentieally what the extern with @:native("$hx_exports.modules.Module2") does.

> It's not only about namespaces. In complex JS-apps you can get garbage
> collection problems with too many global vars.

Now I'm afraid using -D js-classis :)
I can't have such complications I'm my projects.
What are manny namespaces?
Essentially my whole project would in this case recite under one package: var modules = modules || {};
Does that mean that one namespace is used for the garbage collection?
Or are all the subclasses different namespaces for the garbage collection?
I'm not sure how to see this.

> About exclude, in your case it might be useful for module compilation to
> exclude the whole modules-package except for one class. I have a patched
> exclude that does this. Useful for you?


I've noticed the method exclude() can also exclude a whole package by default, that's also what excited me: http://api.haxe.org/haxe/macro/Compiler.html
Is this what you mean?

> Well, Flash has ApplicationDomains and stuff like this, doesn't it?


That's right but when loaded all classes are available you don't have to mess with @:expose and such, less complicated.

> BTW: In my use-cases it was always better in the to load one file and
> have it cached then.


I won't always use modules, but maybe in some cases when a project is really big it would be more practical to use modules.
I want therefore to be able to use both strategies, as a single file and as modules.

Adrian

> You received this message because you are subscribed to a topic in the Google Groups "Haxe" group.

Adrian Martinez

unread,
Nov 1, 2014, 7:30:57 AM11/1/14
to haxe...@googlegroups.com

Hi guys,


I did some work on my modular approach recently.

And I must say that I got almost everything working now.

I also uploaded my library to github.

Called it Zcale becasue the projects are scalable to any size with the use modules.


I got my hxml builder that for example generates this:

https://github.com/adrianmm44/zcale/blob/master/tests/core/ModulesTester/src/Build.hx

into:

https://github.com/adrianmm44/zcale/blob/master/tests/core/ModulesTester/buildscript.hxml


I got a Modules class that defines the modules and knows which modules are used each module:

https://github.com/adrianmm44/zcale/blob/master/tests/core/ModulesTester/src/Modules.hx


And then I got my core classes that are needed for startup and the most basic needs:

https://github.com/adrianmm44/zcale/tree/master/zcale/core


This is the class I use for my compiler macros:

https://github.com/adrianmm44/zcale/blob/master/zcale/macros/CompileMacros.hx


Now…


Compiler.exclude( source ) does what it says it does. It excludes the defined classes or package …but… not the native haxe classes that are used by those classes. So if for example if I exclude ScriptLoader that uses haxe.Http, it excludes ScriptLoader but not haxe.Http.


So I'm wondering right now how to solve this.

Firstly do you guys know if this is correct behavior of haxe? Or is this a bug?

Secondly do you know if there is an easy way to fix this?

Otherwise I was thinking of using Context.onGenerate and checking which class is used by which class to check whether it's allowed to compile or not but I think that's quite a complex task and I'm not sure if that's even possible.


Any thought about on this?


Adrian


Op zondag 21 september 2014 13:36:13 UTC+2 schreef Andreas Mokros:
Hi.

tom rhodes

unread,
Nov 1, 2014, 7:51:34 AM11/1/14
to haxe...@googlegroups.com
It might be cool to have a haxe Std lib for JS that we could all use online? Then if we can exclude the standard lib from our compiled js and with the std lib cached then that would go a long way to making this modular approach work nicely right? Compiler.exclude could then handle the rest so each page can get the smalest amount of JS delivered possible...

--

Adrian Martinez

unread,
Nov 1, 2014, 11:56:56 AM11/1/14
to haxe...@googlegroups.com
That's not a bad idea Tom!
I would vote for that immediately!

Maybe I could make my own system that generates a separate JS file for the Std Haxe classes.
I would need to expose  them to the window object and change their native paths.
Not sure if this is possible though.
Also not sure if the other modules could work with the exclusion of all Std classes.

If anyone has some tips on this matter I would be pleased to here them.

Adrian

Op zaterdag 1 november 2014 12:51:34 UTC+1 schreef tom rhodes:
Reply all
Reply to author
Forward
0 new messages