Repository navigation
Conversation
1a34e9d to
97842a5
Compare
|
This conflicted. I'm also trying to understand why this is necessary. Generators usually treat a dynamic function as a |
Previously, setting a dynamic method to null would add it to the __fields__ table and set the method field to nil on the object. This meant that accessing the method again would fall back to using __index, which would use the original prototype implementation of the method. This patch introduces _hx_index_dyn, an __index meta method. Instead of just using the prototype indiscriminately, this function checks whether the method exists in o.__fields__, and only falls back to the prototype if it does not. The extra function call adds overhead, so it is restricted to classes that contain a dynamic method either in the class itself or in a parent.
Covers when the dynamic method exists on the current class, but also on the parent or the parent's parent.
97842a5 to
17855fb
Compare
That approach sounds better, as it would avoid turning I will try to look into it. I see php is generating: public $test;
/**
* @return void
*/
public function __construct () {
if ($this->test === null) $this->test = new HxClosure($this, '__hx__default__test');
}
public function test ()
{
return call_user_func_array($this->test, func_get_args());
}
public function __hx__default__test ()
{
}It looks like php still needs the |
|
It probably depends on the target, that seems like a good way to retain normal method call semantics while deferring the actual implementation to another implementation. |
|
I think it can work on lua with keeping the physical method, but it's simpler if it can be avoided. I came up with an example where not having it would affect behaviour: class Test {
public function new() {}
public dynamic function test() {}
}
class Test2 extends Test {
public final f:Void -> Void;
public function new() {
f = test;
super();
}
}
function main() {
final test = new Test2();
test.f();
}If the method doesn't exist on the prototype, |
|
Hmm, that example looks a bit rough. I'll have Claude check how it behaves on all targets at the moment. |
|
I tested @tobil4sk's example (reading an inherited dynamic method before function main() {
final test = new Test2();
Sys.println("f == null: " + (test.f == null));
try test.f() catch (e:Dynamic) Sys.println("calling f threw: " + e);
}
Edit: an earlier version of this comment said HL was broken, based only on reading Why PHP fails: PHP stores a dynamic method in an instance property, so reading Why HL works: HL also stores the method in an instance field, and Flash: Override variant: I also tried it with What this means for the PR: storing the method in an instance field works if the field is filled when the object is allocated, as HL's bindings do, or if the default implementation stays reachable from the class, as the prototype makes it on JS and Lua. It fails on PHP, where the field is only filled in the declaring constructor. If Lua moves to a field initialized in the constructor, it needs one of those two mechanisms to keep this example working. Whether this behaviour is specified is still open. If it is, PHP (and probably Flash) needs fixing. Generated by Claude Code |
|
It works ok for me on hl when I run it locally. I opened a bug report for flash and php: #13162. I will keep it working here on lua then. |
|
|
Hm, I tried to implement it that way: Test.super = function(self)
self.test = self.test or Test._hx_default_test
end
-- ...
Test.prototype._hx_default_test = function (self) end
Test.prototype.test = function(self) return rawget(self, "test")(self) end -- use rawget to bypass method resolutionbut that creates a problem, as long as the method exists, this will still give a non-null closure: t.test = null;
final f = t.test; // calling this will give a null error, but it's not null itselfMaybe it could be made to work with some hacking on So the two options I can see are:
Not sure if there are some other ways to get it to work. The fundamental problem here is that on lua there is no distinction between a field set to |
Previously, setting a dynamic method to null would add it to the
__fields__table and set the method field to nil on the object:haxe/std/lua/_lua/_hx_anon.lua
Lines 1 to 4 in 43f211f
This meant that accessing the method again would fall back to using
__index, which would use the original prototype implementation of the method:haxe/std/lua/_lua/_hx_objects.lua
Line 4 in 43f211f
This patch introduces
_hx_index_dyn, an__indexmeta method. Instead of just using the prototype indiscriminately, this function checks whether the method exists ino.__fields__, and only falls back to the prototype if it does not.The extra function call adds overhead, so it is restricted to classes that contain a dynamic method either in the class itself or in a parent.