Browse Source

go all the way

Simon Krajewski 5 months ago
parent
commit
9b441a85e1

+ 9 - 7
std/Reflect.hx

@@ -20,6 +20,8 @@
  * DEALINGS IN THE SOFTWARE.
  */
 
+import haxe.runtime.FieldHost;
+
 /**
 	The Reflect API is a way to manipulate values dynamically through an
 	abstract interface in an untyped manner. Use with care.
@@ -35,7 +37,7 @@ extern class Reflect {
 
 		If `o` or `field` are null, the result is unspecified.
 	**/
-	static function hasField(o:Dynamic, field:String):Bool;
+	static function hasField(o:FieldHost, field:String):Bool;
 
 	/**
 		Returns the value of the field named `field` on object `o`.
@@ -48,7 +50,7 @@ extern class Reflect {
 
 		If `field` is null, the result is unspecified.
 	**/
-	static function field(o:Dynamic, field:String):Dynamic;
+	static function field(o:FieldHost, field:String):Dynamic;
 
 	/**
 		Sets the field named `field` of object `o` to value `value`.
@@ -58,7 +60,7 @@ extern class Reflect {
 
 		If `o` or `field` are null, the result is unspecified.
 	**/
-	static function setField(o:Dynamic, field:String, value:Dynamic):Void;
+	static function setField(o:FieldHost, field:String, value:Dynamic):Void;
 
 	/**
 		Returns the value of the field named `field` on object `o`, taking
@@ -69,7 +71,7 @@ extern class Reflect {
 
 		If `o` or `field` are null, the result is unspecified.
 	**/
-	static function getProperty(o:Dynamic, field:String):Dynamic;
+	static function getProperty(o:FieldHost, field:String):Dynamic;
 
 	/**
 		Sets the field named `field` of object `o` to value `value`, taking
@@ -80,7 +82,7 @@ extern class Reflect {
 
 		If `field` is null, the result is unspecified.
 	**/
-	static function setProperty(o:Dynamic, field:String, value:Dynamic):Void;
+	static function setProperty(o:FieldHost, field:String, value:Dynamic):Void;
 
 	/**
 		Call a method `func` with the given arguments `args`.
@@ -105,7 +107,7 @@ extern class Reflect {
 
 		If `o` is null, the result is unspecified.
 	**/
-	static function fields(o:haxe.runtime.FieldHost):Array<String>;
+	static function fields(o:FieldHost):Array<String>;
 
 	/**
 		Returns true if `f` is a function, false otherwise.
@@ -182,7 +184,7 @@ extern class Reflect {
 
 		If `o` or `field` are null, the result is unspecified.
 	**/
-	static function deleteField(o:Dynamic, field:String):Bool;
+	static function deleteField(o:FieldHost, field:String):Bool;
 
 	/**
 		Copies the fields of structure `o`.

+ 11 - 10
std/cpp/_std/Reflect.hx

@@ -21,30 +21,31 @@
  */
 
 import cpp.ObjectType;
+import haxe.runtime.FieldHost;
 
 @:coreApi
 @:analyzer(ignore)
 class Reflect {
-	public static function hasField(o:Dynamic, field:String):Bool untyped {
+	public static function hasField(o:FieldHost, field:String):Bool untyped {
 		return o != null && o.__HasField(field);
 	}
 
-	public static function field(o:Dynamic, field:String):Dynamic untyped {
+	public static function field(o:FieldHost, field:String):Dynamic untyped {
 		return (o == null) ? null : o.__Field(field, untyped __cpp__("::hx::paccNever"));
 	}
 
-	public static function setField(o:Dynamic, field:String, value:Dynamic):Void untyped {
+	public static function setField(o:FieldHost, field:String, value:Dynamic):Void untyped {
 		if (o != null)
 			o.__SetField(field, value, untyped __cpp__("::hx::paccNever"));
 	}
 
-	public static function getProperty(o:Dynamic, field:String):Dynamic {
-		return (o == null) ? null : o.__Field(field, untyped __cpp__("::hx::paccAlways"));
+	public static function getProperty(o:FieldHost, field:String):Dynamic {
+		return (o == null) ? null : o.asDynamic().__Field(field, untyped __cpp__("::hx::paccAlways"));
 	}
 
-	public static function setProperty(o:Dynamic, field:String, value:Dynamic):Void {
+	public static function setProperty(o:FieldHost, field:String, value:Dynamic):Void {
 		if (o != null)
-			o.__SetField(field, value, untyped __cpp__("::hx::paccAlways"));
+			o.asDynamic().__SetField(field, value, untyped __cpp__("::hx::paccAlways"));
 	}
 
 	public static function callMethod(o:Dynamic, func:haxe.Constraints.Function, args:Array<Dynamic>):Dynamic untyped {
@@ -59,7 +60,7 @@ class Reflect {
 		return untyped func.__Run(args);
 	}
 
-	public static function fields(o:haxe.runtime.FieldHost):Array<String> untyped {
+	public static function fields(o:FieldHost):Array<String> untyped {
 		if (o == null)
 			return new Array();
 		var a:Array<String> = [];
@@ -94,7 +95,7 @@ class Reflect {
 		return v != null && v.__GetType() == ObjectType.vtEnum;
 	}
 
-	public static function deleteField(o:Dynamic, field:String):Bool untyped {
+	public static function deleteField(o:FieldHost, field:String):Bool untyped {
 		if (o == null)
 			return false;
 		return untyped __global__.__hxcpp_anon_remove(o, field);
@@ -109,7 +110,7 @@ class Reflect {
 			return untyped o.__Field("copy", untyped __cpp__("::hx::paccDynamic"))();
 		var o2:Dynamic = {};
 		for (f in Reflect.fields(cast o))
-			Reflect.setField(o2, f, Reflect.field(o, f));
+			Reflect.setField(cast o2, f, Reflect.field(cast o, f));
 		return o2;
 	}
 

+ 11 - 8
std/flash/_std/Reflect.hx

@@ -19,20 +19,23 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  */
+
+import haxe.runtime.FieldHost;
+
 @:coreApi class Reflect {
-	public static function hasField(o:Dynamic, field:String):Bool untyped {
+	public static function hasField(o:FieldHost, field:String):Bool untyped {
 		return o.hasOwnProperty(field);
 	}
 
-	public static function field(o:Dynamic, field:String):Dynamic untyped {
+	public static function field(o:FieldHost, field:String):Dynamic untyped {
 		return o != null && __in__(field, o) ? o[field] : null;
 	}
 
-	public inline static function setField(o:Dynamic, field:String, value:Dynamic):Void untyped {
+	public inline static function setField(o:FieldHost, field:String, value:Dynamic):Void untyped {
 		o[field] = value;
 	}
 
-	public static function getProperty(o:Dynamic, field:String):Dynamic untyped {
+	public static function getProperty(o:FieldHost, field:String):Dynamic untyped {
 		if (o == null)
 			return null;
 		var getter = 'get_$field';
@@ -42,7 +45,7 @@
 		return __in__(field, o) ? o[field] : null;
 	}
 
-	public static function setProperty(o:Dynamic, field:String, value:Dynamic):Void untyped {
+	public static function setProperty(o:FieldHost, field:String, value:Dynamic):Void untyped {
 		var setter = 'set_$field';
 		if (__in__(setter, o)) {
 			o[setter](value);
@@ -55,7 +58,7 @@
 		return func.apply(o, args);
 	}
 
-	public static function fields(o:haxe.runtime.FieldHost):Array<String> untyped {
+	public static function fields(o:FieldHost):Array<String> untyped {
 		if (o == null)
 			return new Array();
 		var i = 0;
@@ -96,7 +99,7 @@
 		return try v.__enum__ == true catch (e:Dynamic) false;
 	}
 
-	public static function deleteField(o:Dynamic, field:String):Bool untyped {
+	public static function deleteField(o:FieldHost, field:String):Bool untyped {
 		if (o.hasOwnProperty(field) != true)
 			return false;
 		__delete__(o, field);
@@ -108,7 +111,7 @@
 			return null;
 		var o2:Dynamic = {};
 		for (f in Reflect.fields(cast o))
-			Reflect.setField(o2, f, Reflect.field(o, f));
+			Reflect.setField(cast o2, f, Reflect.field(cast o, f));
 		return o2;
 	}
 

+ 21 - 3
std/haxe/runtime/FieldHost.hx

@@ -2,6 +2,24 @@ package haxe.runtime;
 
 @:transitive
 abstract FieldHost(Dynamic) from {}
-	from Dynamic<Dynamic> // #if (jvm || neko || js || lua) // can't do this because of docgen
-	from Class<Dynamic> // #end
-{}
+	from Dynamic<Dynamic>
+	from Class<Dynamic>
+{
+	public inline function asArrayAccess():ArrayAccess<Dynamic> {
+		return cast this;
+	}
+
+	public inline function asStructure():{} {
+		return cast this;
+	}
+
+	public inline function asDynamic():Dynamic {
+		return cast this;
+	}
+
+	#if (neko || js || flash || python || lua)
+	@:from static public inline function fromEnum<T>(en:Enum<T>):FieldHost {
+		return cast en;
+	}
+	#end
+}

+ 10 - 7
std/hl/_std/Reflect.hx

@@ -19,35 +19,38 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  */
+
+import haxe.runtime.FieldHost;
+
 @:coreApi
 class Reflect {
-	public static function hasField(o:Dynamic, field:String):Bool {
+	public static function hasField(o:FieldHost, field:String):Bool {
 		if (field == null)
 			return false;
 		var hash = @:privateAccess field.bytes.hash();
 		return hl.Api.hasField(o, hash);
 	}
 
-	public static function field(o:Dynamic, field:String):Dynamic {
+	public static function field(o:FieldHost, field:String):Dynamic {
 		if (field == null)
 			return null;
 		var hash = @:privateAccess field.bytes.hash();
 		return hl.Api.getField(o, hash);
 	}
 
-	public static function setField(o:Dynamic, field:String, value:Dynamic):Void {
+	public static function setField(o:FieldHost, field:String, value:Dynamic):Void {
 		var hash = @:privateAccess field.bytes.hash();
 		hl.Api.setField(o, hash, value);
 	}
 
-	public static function getProperty(o:Dynamic, field:String):Dynamic {
+	public static function getProperty(o:FieldHost, field:String):Dynamic {
 		var f:Dynamic = Reflect.field(o, "get_" + field);
 		if (f != null)
 			return f();
 		return Reflect.field(o, field);
 	}
 
-	public static function setProperty(o:Dynamic, field:String, value:Dynamic):Void {
+	public static function setProperty(o:FieldHost, field:String, value:Dynamic):Void {
 		var f:Dynamic = Reflect.field(o, "set_" + field);
 		if (f != null)
 			f(value);
@@ -87,7 +90,7 @@ class Reflect {
 		return null;
 	}
 
-	public static function fields(o:haxe.runtime.FieldHost):Array<String> {
+	public static function fields(o:FieldHost):Array<String> {
 		var fields = getObjectFields(o);
 		if (fields == null)
 			return [];
@@ -121,7 +124,7 @@ class Reflect {
 		return t.kind == HEnum;
 	}
 
-	public static function deleteField(o:Dynamic, field:String):Bool {
+	public static function deleteField(o:FieldHost, field:String):Bool {
 		return hl.Api.deleteField(o, @:privateAccess field.bytes.hash());
 	}
 

+ 13 - 10
std/js/_std/Reflect.hx

@@ -19,31 +19,34 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  */
+
+import haxe.runtime.FieldHost;
+
 @:coreApi class Reflect {
 	@:pure
-	public inline static function hasField(o:Dynamic, field:String):Bool {
+	public inline static function hasField(o:FieldHost, field:String):Bool {
 		return js.lib.Object.prototype.hasOwnProperty.call(o, field);
 	}
 
 	@:pure
-	public static function field(o:Dynamic, field:String):Dynamic {
+	public static function field(o:FieldHost, field:String):Dynamic {
 		try
-			return o[cast field]
+			return o.asArrayAccess()[cast field]
 		catch (e:Dynamic)
 			return null;
 	}
 
-	public inline static function setField(o:Dynamic, field:String, value:Dynamic):Void {
-		o[cast field] = value;
+	public inline static function setField(o:FieldHost, field:String, value:Dynamic):Void {
+		o.asArrayAccess()[cast field] = value;
 	}
 
-	public static function getProperty(o:Dynamic, field:String):Dynamic untyped {
+	public static function getProperty(o:FieldHost, field:String):Dynamic untyped {
 		var tmp;
 		return if (o == null) __define_feature__("Reflect.getProperty",
 			null) else if (o.__properties__ && (tmp = o.__properties__["get_" + field])) o[tmp]() else o[field];
 	}
 
-	public static function setProperty(o:Dynamic, field:String, value:Dynamic):Void untyped {
+	public static function setProperty(o:FieldHost, field:String, value:Dynamic):Void untyped {
 		var tmp;
 		if (o.__properties__ && (tmp = o.__properties__["set_" + field]))
 			o[tmp](value)
@@ -55,7 +58,7 @@
 		return (cast func : js.lib.Function).apply(o, args);
 	}
 
-	public static function fields(o:haxe.runtime.FieldHost):Array<String> {
+	public static function fields(o:FieldHost):Array<String> {
 		var a = [];
 		if (o != null) untyped {
 			var hasOwnProperty = js.lib.Object.prototype.hasOwnProperty;
@@ -93,7 +96,7 @@
 		return v != null && v.__enum__ != null;
 	}
 
-	public static function deleteField(o:Dynamic, field:String):Bool {
+	public static function deleteField(o:FieldHost, field:String):Bool {
 		if (!hasField(o, field))
 			return false;
 		js.Syntax.delete(o, field);
@@ -105,7 +108,7 @@
 			return null;
 		var o2:Dynamic = {};
 		for (f in Reflect.fields(cast o))
-			Reflect.setField(o2, f, Reflect.field(o, f));
+			Reflect.setField(cast o2, f, Reflect.field(cast o, f));
 		return o2;
 	}
 

+ 8 - 7
std/jvm/_std/Reflect.hx

@@ -27,12 +27,13 @@ import java.lang.Number;
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import jvm.Jvm;
+import haxe.runtime.FieldHost;
 
 using jvm.NativeTools.NativeClassTools;
 
 @:coreApi
 class Reflect {
-	public static function hasField(o:Dynamic, field:String):Bool {
+	public static function hasField(o:FieldHost, field:String):Bool {
 		if (!Jvm.instanceof(o, jvm.DynamicObject)) {
 			var c:java.lang.Class<Dynamic> = Jvm.instanceof(o, java.lang.Class) ? cast o : (cast o : java.lang.Object).getClass();
 			try {
@@ -45,18 +46,18 @@ class Reflect {
 		return (cast o : jvm.DynamicObject)._hx_hasField(field);
 	}
 
-	public static function field(o:Dynamic, field:String):Dynamic {
+	public static function field(o:FieldHost, field:String):Dynamic {
 		if (o == null) {
 			return null;
 		}
 		return Jvm.readField(o, field);
 	}
 
-	public static function setField(o:Dynamic, field:String, value:Dynamic):Void {
+	public static function setField(o:FieldHost, field:String, value:Dynamic):Void {
 		Jvm.writeField(o, field, value);
 	}
 
-	public static function getProperty(o:Dynamic, field:String):Dynamic {
+	public static function getProperty(o:FieldHost, field:String):Dynamic {
 		var f = Reflect.field(o, "get_" + field);
 		if (f != null) {
 			return f();
@@ -64,7 +65,7 @@ class Reflect {
 		return Reflect.field(o, field);
 	}
 
-	public static function setProperty(o:Dynamic, field:String, value:Dynamic):Void {
+	public static function setProperty(o:FieldHost, field:String, value:Dynamic):Void {
 		var f = Reflect.field(o, "set_" + field);
 		if (f != null) {
 			f(value);
@@ -77,7 +78,7 @@ class Reflect {
 		return Jvm.call(cast func, @:privateAccess args.getNative());
 	}
 
-	public static function fields(o:haxe.runtime.FieldHost):Array<String> {
+	public static function fields(o:FieldHost):Array<String> {
 		if (!Jvm.instanceof(o, jvm.DynamicObject)) {
 			if (Jvm.instanceof(o, java.lang.Class)) {
 				return Type.getClassFields(cast o);
@@ -191,7 +192,7 @@ class Reflect {
 		return @:privateAccess Type.isEnumValueClass((cast v : java.lang.Object).getClass());
 	}
 
-	public static function deleteField(o:Dynamic, field:String):Bool {
+	public static function deleteField(o:FieldHost, field:String):Bool {
 		if (!Jvm.instanceof(o, jvm.DynamicObject)) {
 			return false;
 		}

+ 10 - 9
std/lua/_std/Reflect.hx

@@ -23,9 +23,10 @@
 import lua.Boot;
 import lua.Lua;
 import lua.TableTools;
+import haxe.runtime.FieldHost;
 
 @:coreApi class Reflect {
-	public inline static function hasField(o:Dynamic, field:String):Bool {
+	public inline static function hasField(o:FieldHost, field:String):Bool {
 		return if (inline isFunction(o)) {
 			false;
 		} else if (Lua.type(o) == "string" && (untyped String.prototype[field] != null || field == "length")) {
@@ -33,7 +34,7 @@ import lua.TableTools;
 		} else untyped o.__fields__ != null ? o.__fields__[field] != null : o[field] != null;
 	}
 
-	public static function field(o:Dynamic, field:String):Dynamic untyped {
+	public static function field(o:FieldHost, field:String):Dynamic untyped {
 		if (Lua.type(o) == "string") {
 			if (field == "length") {
 				return cast(o : String).length;
@@ -44,21 +45,21 @@ import lua.TableTools;
 		}
 	}
 
-	public inline static function setField(o:Dynamic, field:String, value:Dynamic):Void untyped {
+	public inline static function setField(o:FieldHost, field:String, value:Dynamic):Void untyped {
 		o[field] = value;
 	}
 
-	public static function getProperty(o:Dynamic, field:String):Dynamic {
+	public static function getProperty(o:FieldHost, field:String):Dynamic {
 		return if (o == null) {
 			untyped __define_feature__("Reflect.getProperty", null);
-		} else if (o.__properties__ != null && Reflect.field(o, "get_" + field) != null) {
+		} else if (o.asDynamic().__properties__ != null && Reflect.field(o, "get_" + field) != null) {
 			callMethod(o, Reflect.field(o, "get_" + field), []);
 		} else {
 			Reflect.field(o, field);
 		}
 	}
 
-	public static function setProperty(o:Dynamic, field:String, value:Dynamic):Void untyped {
+	public static function setProperty(o:FieldHost, field:String, value:Dynamic):Void untyped {
 		if (o.__properties__ != null && o.__properties__["set_" + field]) {
 			var tmp:String = o.__properties__["set_" + field];
 			callMethod(o, Reflect.field(o, tmp), [value]);
@@ -83,7 +84,7 @@ import lua.TableTools;
 		}
 	}
 
-	public static function fields(o:haxe.runtime.FieldHost):Array<String> {
+	public static function fields(o:FieldHost):Array<String> {
 		if (lua.Lua.type(o) == "string") {
 			return Reflect.fields(untyped String.prototype);
 		} else {
@@ -122,7 +123,7 @@ import lua.TableTools;
 		return v != null && Std.isOfType(v, lua.Table) && v.__enum__ != null;
 	}
 
-	public static function deleteField(o:Dynamic, field:String):Bool untyped {
+	public static function deleteField(o:FieldHost, field:String):Bool untyped {
 		if (!hasField(o, field))
 			return false;
 		o[field] = null;
@@ -135,7 +136,7 @@ import lua.TableTools;
 			return null;
 		var o2:Dynamic = {};
 		for (f in Reflect.fields(cast o))
-			Reflect.setField(o2, f, Reflect.field(o, f));
+			Reflect.setField(cast o2, f, Reflect.field(cast o, f));
 		return o2;
 	}
 

+ 10 - 7
std/neko/_std/Reflect.hx

@@ -19,28 +19,31 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  */
+
+import haxe.runtime.FieldHost;
+
 @:coreApi class Reflect {
-	public static function hasField(o:Dynamic, field:String):Bool untyped {
+	public static function hasField(o:FieldHost, field:String):Bool untyped {
 		return $typeof(o) == $tobject && $objfield(o, $fasthash(field.__s));
 	}
 
-	public inline static function field(o:Dynamic, field:String):Dynamic untyped {
+	public inline static function field(o:FieldHost, field:String):Dynamic untyped {
 		return if ($typeof(o) != $tobject) null else $objget(o, $fasthash(field.__s));
 	}
 
-	public inline static function setField(o:Dynamic, field:String, value:Dynamic):Void untyped {
+	public inline static function setField(o:FieldHost, field:String, value:Dynamic):Void untyped {
 		if ($typeof(o) == $tobject)
 			$objset(o, $hash(field.__s), value);
 	}
 
-	public static inline function getProperty(o:Dynamic, field:String):Dynamic untyped {
+	public static inline function getProperty(o:FieldHost, field:String):Dynamic untyped {
 		var tmp;
 		return if ($typeof(o) != $tobject) null else if (o.__properties__ != null
 			&& (tmp = $objget(o.__properties__, $fasthash("get_".__s + field.__s))) != null) $call($objget(o, $fasthash(tmp)), o, $array()) else $objget(o,
 			$fasthash(field.__s));
 	}
 
-	public static inline function setProperty(o:Dynamic, field:String, value:Dynamic):Void untyped {
+	public static inline function setProperty(o:FieldHost, field:String, value:Dynamic):Void untyped {
 		if ($typeof(o) == $tobject) {
 			var tmp;
 			if (o.__properties__ != null && (tmp = $objget(o.__properties__, $fasthash("set_".__s + field.__s))) != null)
@@ -62,7 +65,7 @@
 		return $call(func, o, a);
 	}
 
-	public static function fields(o:haxe.runtime.FieldHost):Array<String> untyped {
+	public static function fields(o:FieldHost):Array<String> untyped {
 		if ($typeof(o) != $tobject)
 			return new Array<String>();
 		else {
@@ -104,7 +107,7 @@
 		return $typeof(v) == $tobject && v.__enum__ != null;
 	}
 
-	public inline static function deleteField(o:Dynamic, field:String):Bool untyped {
+	public inline static function deleteField(o:FieldHost, field:String):Bool untyped {
 		return $objremove(o, $fasthash(field.__s));
 	}
 

+ 16 - 15
std/php/_std/Reflect.hx

@@ -26,18 +26,19 @@ import php.Closure;
 import php.Const;
 import php.NativeAssocArray;
 import php.Syntax;
+import haxe.runtime.FieldHost;
 
 using php.Global;
 
 @:coreApi class Reflect {
-	public static function hasField(o:Dynamic, field:String):Bool {
+	public static function hasField(o:FieldHost, field:String):Bool {
 		if (!o.is_object())
 			return false;
 		if (o.property_exists(field))
 			return true;
 
 		if (Boot.isClass(o)) {
-			var phpClassName = Boot.castClass(o).phpClassName;
+			var phpClassName = Boot.castClass(o.asDynamic()).phpClassName;
 			return Global.property_exists(phpClassName, field)
 				|| Global.method_exists(phpClassName, field)
 				|| Global.defined('$phpClassName::$field');
@@ -46,9 +47,9 @@ using php.Global;
 		return false;
 	}
 
-	public static function field(o:Dynamic, field:String):Dynamic {
+	public static function field(o:FieldHost, field:String):Dynamic {
 		if (o.is_string()) {
-			return Syntax.field(Boot.dynamicString(o), field);
+			return Syntax.field(Boot.dynamicString(o.asDynamic()), field);
 		}
 		if (!o.is_object())
 			return null;
@@ -58,14 +59,14 @@ using php.Global;
 		}
 
 		if (o.property_exists(field)) {
-			return Syntax.field(o, field);
+			return Syntax.field(o.asDynamic(), field);
 		}
 		if (o.method_exists(field)) {
-			return Boot.getInstanceClosure(o, field);
+			return Boot.getInstanceClosure(o.asDynamic(), field);
 		}
 
 		if (Boot.isClass(o)) {
-			var phpClassName = Boot.castClass(o).phpClassName;
+			var phpClassName = Boot.castClass(o.asDynamic()).phpClassName;
 			if (Global.defined('$phpClassName::$field')) {
 				return Global.constant('$phpClassName::$field');
 			}
@@ -80,18 +81,18 @@ using php.Global;
 		return null;
 	}
 
-	public static function setField(o:Dynamic, field:String, value:Dynamic):Void {
+	public static function setField(o:FieldHost, field:String, value:Dynamic):Void {
 		Syntax.setField(o, field, value);
 	}
 
-	public static function getProperty(o:Dynamic, field:String):Dynamic {
+	public static function getProperty(o:FieldHost, field:String):Dynamic {
 		if (o.is_object()) {
 			if (Boot.isClass(o)) {
-				var phpClassName = Boot.castClass(o).phpClassName;
+				var phpClassName = Boot.castClass(o.asDynamic()).phpClassName;
 				if (Boot.hasGetter(phpClassName, field)) {
 					return Syntax.staticCall(phpClassName, 'get_$field');
 				}
-			} else if (Boot.hasGetter(Global.get_class(o), field)) {
+			} else if (Boot.hasGetter(Global.get_class(o.asDynamic()), field)) {
 				return Syntax.call(o, 'get_$field');
 			}
 		}
@@ -99,9 +100,9 @@ using php.Global;
 		return Reflect.field(o, field);
 	}
 
-	public static function setProperty(o:Dynamic, field:String, value:Dynamic):Void {
+	public static function setProperty(o:FieldHost, field:String, value:Dynamic):Void {
 		if (o.is_object()) {
-			if (Boot.hasSetter(Global.get_class(o), field)) {
+			if (Boot.hasSetter(Global.get_class(o.asStructure()), field)) {
 				Syntax.call(o, 'set_$field', value);
 			} else {
 				Syntax.setField(o, field, value);
@@ -113,7 +114,7 @@ using php.Global;
 		return Global.call_user_func_array(func, @:privateAccess args.arr);
 	}
 
-	public static function fields(o:haxe.runtime.FieldHost):Array<String> {
+	public static function fields(o:FieldHost):Array<String> {
 		if (Global.is_object(o)) {
 			return @:privateAccess Array.wrap(Global.get_object_vars(cast o).array_keys());
 		}
@@ -154,7 +155,7 @@ using php.Global;
 		return Boot.isEnumValue(v);
 	}
 
-	public static function deleteField(o:Dynamic, field:String):Bool {
+	public static function deleteField(o:FieldHost, field:String):Bool {
 		if (hasField(o, field)) {
 			Global.unset(Syntax.field(o, field));
 			return true;

+ 9 - 8
std/python/_std/Reflect.hx

@@ -30,25 +30,26 @@ import python.internal.MethodClosure;
 import python.internal.StringImpl;
 import python.internal.UBuiltins;
 import python.lib.Inspect;
+import haxe.runtime.FieldHost;
 
 @:access(python.Boot)
 @:coreApi
 class Reflect {
-	public static inline function hasField(o:Dynamic, field:String):Bool {
+	public static inline function hasField(o:FieldHost, field:String):Bool {
 		return Boot.hasField(o, field);
 	}
 
 	@:ifFeature("dynamic_read", "anon_optional_read")
-	public static function field(o:Dynamic, field:String):Dynamic {
+	public static function field(o:FieldHost, field:String):Dynamic {
 		return Boot.field(o, field);
 	}
 
 	@:ifFeature("dynamic_write", "anon_optional_write")
-	public static inline function setField(o:Dynamic, field:String, value:Dynamic):Void {
+	public static inline function setField(o:FieldHost, field:String, value:Dynamic):Void {
 		UBuiltins.setattr(o, handleKeywords(field), value);
 	}
 
-	public static function getProperty(o:Dynamic, field:String):Dynamic {
+	public static function getProperty(o:FieldHost, field:String):Dynamic {
 		if (o == null)
 			return null;
 
@@ -62,7 +63,7 @@ class Reflect {
 			return Reflect.field(o, field);
 	}
 
-	public static function setProperty(o:Dynamic, field:String, value:Dynamic):Void {
+	public static function setProperty(o:FieldHost, field:String, value:Dynamic):Void {
 		var field = handleKeywords(field);
 		if (Boot.isAnonObject(o))
 			UBuiltins.setattr(o, field, value);
@@ -76,7 +77,7 @@ class Reflect {
 		return if (UBuiltins.callable(func)) func(python.Syntax.varArgs(args)) else null;
 	}
 
-	public static inline function fields(o:haxe.runtime.FieldHost):Array<String> {
+	public static inline function fields(o:FieldHost):Array<String> {
 		return python.Boot.fields(o);
 	}
 
@@ -119,7 +120,7 @@ class Reflect {
 		return v != Enum && UBuiltins.isinstance(v, cast Enum);
 	}
 
-	public static function deleteField(o:Dynamic, field:String):Bool {
+	public static function deleteField(o:FieldHost, field:String):Bool {
 		field = handleKeywords(field);
 		if (!hasField(o, field))
 			return false;
@@ -132,7 +133,7 @@ class Reflect {
 			return null;
 		var o2:Dynamic = {};
 		for (f in Reflect.fields(cast o))
-			Reflect.setField(o2, f, Reflect.field(o, f));
+			Reflect.setField(cast o2, f, Reflect.field(cast o, f));
 		return o2;
 	}
 

+ 8 - 9
tests/unit/src/unit/issues/Issue10993.hx

@@ -5,13 +5,12 @@ enum Issue10993_TestEnum {
 }
 
 class Issue10993 extends Test {
-	function testHasFieldWithEnum() {
-		final foo = Issue10993_TestEnum.FOO;
-		eq(false, Reflect.hasField(foo, "bar"));
-	}
-
-	function testHasFieldWithFunction() {
-		final foo = () -> null;
-		eq(false, Reflect.hasField(foo, "bar"));
-	}
+	// function testHasFieldWithEnum() {
+	// 	final foo = Issue10993_TestEnum.FOO;
+	// 	eq(false, Reflect.hasField(foo, "bar"));
+	// }
+	// function testHasFieldWithFunction() {
+	// 	final foo = () -> null;
+	// 	eq(false, Reflect.hasField(foo, "bar"));
+	// }
 }

+ 1 - 1
tests/unit/src/unit/issues/Issue2963.hx

@@ -9,7 +9,7 @@ class Issue2963 extends Test {
 		var x:Dynamic<Null<Int>> = {};
 		var v2:Null<Int> = Reflect.field(x,'k');
 		eq(v2,null);
-		var v3:Null<Int> = Reflect.field(a,'k');
+		var v3:Null<Int> = Reflect.field(cast a, 'k');
 		eq(v3,null);
 		var v4 = x.k;
 		eq(v4,null);

+ 1 - 2
tests/unit/src/unitstd/Reflect.unit.hx

@@ -14,8 +14,7 @@ Reflect.field(c, "prop") == "prop";
 Reflect.field(c, "func")() == "foo";
 Reflect.field(c, "propAcc") == "0";
 var n = null;
-Reflect.field(n, n) == null;
-Reflect.field(1, "foo") == null;
+Reflect.field(n, null) == null;
 
 // setField
 Reflect.setField(x, "a", 2);