HaxeFoundation / HaxeFoundation/haxe

Cannot override select classes (e.g. Array) via addClassPath

Open
#9,346 3 comments 0 reactions 0 assignees View on GitHub
bug platform-javascript
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.