HaxeFoundation / HaxeFoundation/haxe
Cannot override select classes (e.g. Array) via addClassPath
- Dominant language
- Haxe
- Stars
- 6.9k
- Forks
- 715
- Avg merge
- 2d 2h
- Merged PRs (30d)
- 11
Description
In my efforts with working with CustomJSGenerator I've ran into a recurring issue: I cannot provide implementations of specific standard-library classes without caveats.
For a small example:
Main.hx:
```haxe
class Main {
static function main() {
var a = [1, 2, 3];
trace(a.remove(2));
trace(Date.now());
}
}
```
Macro.hx:
```haxe
import haxe.macro.ExampleJSGenerator;
import haxe.macro.Context;
import haxe.macro.JSGenApi;
import haxe.macro.Compiler;
class Macro {
static function build() {
Compiler.addClassPath(Context.resolvePath("mystd"));
Compiler.setCustomJSGenerator(function(api:JSGenApi) {
new ExampleJSGenerator(api).generate();
});
}
}
```
mystd/Array.hx:
```haxe
// .. same as js/_std/Array.hx, except we replace `remove` with
inline function remove(x:T):Bool {
return cast "Array.remove";
}
```
mystd/Date.hx:
```haxe
// .. same as js/_std/Date.hx, except we replace `now` with
@:pure static inline function now():Date {
return cast "Date.now";
}
```
build.hxml:
```hxml
-dce full
-cp .
-js _.js
-main Main
--macro Macro.build()
```
output:
```js
var $_, $hxClasses = $hxClasses || {}, $estr = function() { return js.Boot.__string_rec(this,''); };
function $bind(o,m) { var f = function(){ return f.method.apply(f.scope, arguments); }; f.scope = o; f.method = m; return f; };;
HxOverrides = $hxClasses['HxOverrides'] = function() { };
HxOverrides.__name__ = "HxOverrides";
HxOverrides.remove = function(a,obj) {
var i = a.indexOf(obj);
if(i == -1) {
return false;
}
a.splice(i,1);
return true;
};
HxOverrides.prototype.__class__ = HxOverrides;
Main = $hxClasses['Main'] = function() { };
Main.__name__ = "Main";
Main.main = function() {
var a = [1,2,3];
console.log("Main.hx:4:",HxOverrides.remove(a,2)); // still original
console.log("Main.hx:5:","Date.now"); // uses remapped version
};
Main.prototype.__class__ = Main;
Std = $hxClasses['Std'] = function() { };
Std.__name__ = "Std";
Std.prototype.__class__ = Std;
;
;
{
};
Main.main();
// ... and ArrayIterator if running on current git version
```
zip sample: [cjs.zip](https://github.com/HaxeFoundation/haxe/files/4527884/cjs.zip)
Although I am able to get around the issue by providing a top-level Array class in the library, this introduces more problems:
* Build macros are going to attempt to use the class, therefore it must have an `#if !macro` and a copy of std Array in it.
* The class is unaffected by Compiler.define.
* Causes unusual compile errors in other parts of standard library (e.g. "cannot extend final class" in RegExp)
As a slightly cleaner workaround, I'm currently remapping Array.* functions by processing AST pre-generation, but this makes it impossible to remap any that are inlined in default implementation (such as .filter).
Contributor guide
Assessment
This issue has not been assessed yet.