HaxeFoundation / haxe

Haxe - The Cross-Platform Toolkit
https://haxe.org
6.11k stars 648 forks source link

ES5 Getter / Setter #5104

Open eduardo-costa opened 8 years ago

eduardo-costa commented 8 years ago

Can we have the get/set features of ES5? It will allow javascript libs to be compiled and used outside the Haxe scope.

//Vector2.hx
public class Vector2 {
 public var x : Float;
 public var y: Float;
 public var length(get,set):Float;
 private function get_length() : Float { ... }
 private function set_length(v:Float) : Float { ... }
}
//Vector2.js
/* ... */
Vector2.prototype = {
 get length: this.get_length,
 set length: this.set_length,
/*... */
};
nadako commented 8 years ago

The issue here is that we can't access the length field without get/set anymore and we still need to do that. Or is there a way?

nadako commented 8 years ago

What we could do is support @:property, similar to how it's done in C#: only for get,set, get,never, never,set properties without @:isVar, so there's no physical field.

eduardo-costa commented 8 years ago

My current workaround is

public function new() 
{
  untyped Object.defineProperty(this, "length", { get: this.get_length, set: this.set_length });
}

So basically the get_ and set_ versions still exists (for Reflection) and the ES5 versions are injected

eduardo-costa commented 8 years ago

I'm just afraid of possible performance implications of doing such in each new instance.

nadako commented 8 years ago

The issue i was talking about is this:

class C {
    public var a(get,null):Int;
    function get_a() return a;
}

Here we need the physical a field, so we can't just generate js properties by default, but explicit @:property thing described in https://github.com/HaxeFoundation/haxe/issues/5104#issuecomment-208752587 could work.

eduardo-costa commented 8 years ago

I'm cool with manually pointing which ones to have this behaviour!

eduardo-costa commented 8 years ago

The reason is I have a really complete Math lib for Haxor which would be cool to use as a compiled javascript lib and embedded on the page. I'll stick with the Object.defineProperty workaround until 3.4 then.

nadako commented 8 years ago

I think I'll look into this after 3.3.

eduardo-costa commented 8 years ago

Thanks!

nadako commented 8 years ago

I think you can support properties on prototype via __init__ magic method

eduardo-costa commented 8 years ago

Will check on that! Thanks!

eduardo-costa commented 8 years ago

Worked!

@:expose
class Vector4
{
    static function __init__():Void {
        #if js
        untyped Object.defineProperty(Vector4.prototype, "length", { get: Vector4.prototype.get_length });
        #end
    }

/*...*/
}
singpolyma commented 2 months ago

Not sure why having a physical field is a problem? If it's just name shadowing could we not mangle the physical name?