소스 검색

Merge pull request #2857 from mockey/native-js-objects

added check for native js objects to __instanceof
Nicolas Cannasse 11 년 전
부모
커밋
fc18727d57
3개의 변경된 파일57개의 추가작업 그리고 5개의 파일을 삭제
  1. 39 5
      std/js/Boot.hx
  2. 2 0
      std/js/_std/Type.hx
  3. 16 0
      tests/unit/issues/Issue2857.hx

+ 39 - 5
std/js/Boot.hx

@@ -70,8 +70,15 @@ class Boot {
 	static inline function getClass(o:Dynamic) : Dynamic {
 		if (Std.is(o, Array))
 			return Array;
-		else
-			return untyped __define_feature__("js.Boot.getClass", o.__class__);
+		else {
+			var cl = untyped __define_feature__("js.Boot.getClass", o.__class__);
+			if (cl != null)
+				return cl;
+			var name = __nativeClassName(o);
+			if (name != null)
+				return __resolveNativeClass(name);
+			return null;
+		}
 	}
 
 	@:ifFeature("may_print_enum")
@@ -180,14 +187,17 @@ class Boot {
 			return true;
 		default:
 			if( o != null ) {
-				// Check if o is an instance of a Haxe class
+				// Check if o is an instance of a Haxe class or a native JS object
 				if( (untyped __js__("typeof"))(cl) == "function" ) {
-					if( untyped __js__("o instanceof cl") ) {
+					if( untyped __js__("o instanceof cl") )
 						return true;
-					}
 					if( __interfLoop(getClass(o),cl) )
 						return true;
 				}
+				else if ( (untyped __js__("typeof"))(cl) == "object" && __isNativeObj(cl) ) {
+					if( untyped __js__("o instanceof cl") )
+						return true;
+				}
 			} else {
 				return false;
 			}
@@ -202,5 +212,29 @@ class Boot {
 		if (__instanceof(o, t)) return o;
 		else throw "Cannot cast " +Std.string(o) + " to " +Std.string(t);
 	}
+	
+	static var __toStr = untyped __js__("{}.toString");
+	// get native JS [[Class]]
+	static function __nativeClassName(o:Dynamic):String {
+		var name = untyped __toStr.call(o).slice(8, -1);
+		// exclude general Object and Function
+		// also exclude Math and JSON, because instanceof cannot be called on them
+		if (name == "Object" || name == "Function" || name == "Math" || name == "JSON")
+			return null;
+		return name;
+	}
+	
+	// check for usable native JS object
+	static function __isNativeObj(o:Dynamic):Bool {
+		return __nativeClassName(o) != null;
+	}
+	
+	// resolve native JS class (with window or global):
+	static function __resolveNativeClass(name:String) untyped {
+		if (__js__("typeof window") != "undefined")
+			return window[name];
+		else
+			return global[name];
+	}
 
 }

+ 2 - 0
std/js/_std/Type.hx

@@ -52,6 +52,8 @@ enum ValueType {
 
 	public static function getClassName( c : Class<Dynamic> ) : String {
 		var a : Array<String> = untyped c.__name__;
+		if (a == null)
+			return null;
 		return a.join(".");
 	}
 

+ 16 - 0
tests/unit/issues/Issue2857.hx

@@ -0,0 +1,16 @@
+package unit.issues;
+
+class Issue2857 extends unit.Test {
+#if js
+	function testElement() {
+		if (js.Browser.supported) {
+			var vid = js.Browser.document.createVideoElement();
+			t(Std.is(vid, js.html.VideoElement));
+			t(Std.is(vid, js.html.Element));
+			f(Std.is(vid, haxe.Http));
+			f(Std.is(vid, js.html.ArrayBuffer));
+			eq(Type.getClass(vid), js.html.VideoElement);
+		}
+	}
+#end
+}