HaxeFoundation / HaxeFoundation/haxe
[js] Function names and local imports
- Dominant language
- Haxe
- Stars
- 6.9k
- Forks
- 715
- Avg merge
- 2d 2h
- Merged PRs (30d)
- 11
Description
Hello,
I'd like to discuss if a few small modification and enhancements could be applied to the javascript target.
## Named functions
For debugging purposes, it would be ideal to have functions be emitted with their name. Right now functions are emitted as such:
``` javascript
Foo.prototype = {
bar: function () { ... }
...
};
```
Which is an anonymous function. I can't recall how it comes up in Node, buti n my personal use, I'm using duktape as the javascript runtime in my game engine, which won't show the name for the anonymous function [please see here](https://github.com/svaarala/duktape/issues/591#issuecomment-185127978), therefore the functions should be emmiited as such:
``` javascript
Foo.prototype = {
bar: function bar() { ... }
...
};
```
This should be also done with the constructor as well:
``` javascript
var Foo = function Foo() { ... }
```
## Local Imports References
By this I mean grabbing imported classes into function-level variables. Which will allow runtimes to perform better as they do not need to do property lookups each time.
This would require wrapping each generated file in its own function scope. Right now classes get emmited in the global scope, or wrapped in a single function, which wouldn't allow this. However if each file is generated in its own function scope (this would be similar in the way Typescript emits classes), then imports can be grabbed into that function as local variables which would allow for much faster access. This perhaps might not be that big an issue for JIT runtimes, but for interpreted ones, like duktape, especially with demanding apps like games, it's a problem. Example:
``` javascript
// Right now Haxe emits something like this:
// In .hx file: import mymath.Vector3;
var entities = entities || {};
entities.Entity = function() {
this._pos = mymath.Vector3( 0, 0, 0 ); // Have to lookup 'Vector3' on 'mymath'
this._speed = 10;
};
entities.Entity.prototype = {
update: function(dt) {
let move = mymath.Vector3( this._speed * dt, 0, 0 ); // Lookup again
this._pos.add( move );
}
};
// Instead if they are generated as displayed below:
var entities = entities || {};
(function( entities ) {
var Vector3 = mymath.Vector3; // lookup 'Vector3' on 'mymath' only once.
// In this case, Vector3 is an extern class implemented natively,
// it should still generate this import.
function Entity() {
this._pos = Vector3( 0, 0, 0 ); // Vector3 is bound as a function local, fast access
this._speed = 10;
}
Entity.prototype = {
update: function update(dt) {
let move = Vector3( this._speed * dt, 0, 0 ); // Same here
this._pos.add( move );
}
};
entities.Entity = Entity;
})( entities );
```
I don't know ocaml, and have never used any **ml** type language, so this is foreign territory to me, however I decided to dig into the source anyway to see how tough it would be to implement. I managed to get it to emit function names and wrapped each class in its own function scope, but I've no idea how to tackle the local import stuff which is the critical part.
On a personal note on why I'm requesting this: I'm currently using Typescript to transpile to javascritpt, which has some headaches and I don't find it as well suited as Haxe for use in gameplay scripting. I used to be Haxe user back in the day when I primarily developed Flash games, but had not used it in a while as I have not developed for Flash in years. Recently I found out Haxe had a javascript target, I was excited as this would allow me to use Haxe features I'm missing. Goodies like the preprocessor, sane package system, inlining and abstract types (would love to have arithmetic operators for Vectors!) are highly desirable. So it would be great to be able to switch to it. :)
If no one is up for implementing this, any help or direction on how to approach the source regarding the imports would be great.
## Finally, function calls with/without `new`
In javascript when a function is called with `new`, a default instance object is created with an inherited prototype, that object is bound to `this` then the function called is executed. If the function does not return any object, then the default instance (currently bound to `this`) is returned, otherwise whatever object was returned is used.
I noticed one can specify a constructor to be called without `new` by using `@:selfCall`. But then it becomes either one or the other (that is, that particular constructor can only be called with `new` or not, but not either one), this is not always desirable as there are object that may behave differently when called with `new` as opposed to without it.
Is there any way currently to be able to call single constructor with **and** without `new`?
Thanks for your time.
Contributor guide
Assessment
This issue has not been assessed yet.