Boot.hx 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. /*
  2. * Copyright (C)2005-2017 Haxe Foundation
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  20. * DEALINGS IN THE SOFTWARE.
  21. */
  22. package js;
  23. private class HaxeError extends js.Error {
  24. var val:Dynamic;
  25. public function new(val:Dynamic) untyped {
  26. super();
  27. this.val = __define_feature__("js.Boot.HaxeError", val);
  28. this.message = String(val);
  29. if (js.Error.captureStackTrace) js.Error.captureStackTrace(this, HaxeError);
  30. }
  31. public static function wrap(val:Dynamic):Dynamic untyped {
  32. return if (__instanceof__(val, js.Error)) val else new HaxeError(val);
  33. }
  34. }
  35. @:dox(hide)
  36. class Boot {
  37. static inline function isClass(o:Dynamic) : Bool {
  38. return untyped __define_feature__("js.Boot.isClass", o.__name__);
  39. }
  40. static inline function isEnum(e:Dynamic) : Bool {
  41. return untyped __define_feature__("js.Boot.isEnum", e.__ename__);
  42. }
  43. static function getClass(o:Dynamic) : Dynamic {
  44. if (Std.is(o, Array))
  45. return Array;
  46. else {
  47. var cl = untyped __define_feature__("js.Boot.getClass", o.__class__);
  48. if (cl != null)
  49. return cl;
  50. var name = __nativeClassName(o);
  51. if (name != null)
  52. return __resolveNativeClass(name);
  53. return null;
  54. }
  55. }
  56. @:ifFeature("has_enum")
  57. private static function __string_rec(o,s:String) {
  58. untyped {
  59. if( o == null )
  60. return "null";
  61. if( s.length >= 5 )
  62. return "<...>"; // too much deep recursion
  63. var t = js.Lib.typeof(o);
  64. if( t == "function" && (isClass(o) || isEnum(o)) )
  65. t = "object";
  66. switch( t ) {
  67. case "object":
  68. #if js_enums_as_objects
  69. if (o.__enum__) {
  70. var e = $hxEnums[o.__enum__];
  71. var n = e.__constructs__[o._hx_index];
  72. var con = e[n];
  73. if (con.__params__) {
  74. s += "\t";
  75. return n + "(" +
  76. [for (p in (con.__params__:Array<String>)) __string_rec(o[p],s)].join(",") + ")";
  77. } else {
  78. return n;
  79. }
  80. }
  81. #end
  82. if( __js__("o instanceof Array") ) {
  83. #if !js_enums_as_objects
  84. if( o.__enum__ ) {
  85. if( o.length == 2 )
  86. return o[0];
  87. var str = o[0]+"(";
  88. s += "\t";
  89. for( i in 2...o.length ) {
  90. if( i != 2 )
  91. str += "," + __string_rec(o[i],s);
  92. else
  93. str += __string_rec(o[i],s);
  94. }
  95. return str + ")";
  96. }
  97. #end
  98. var l = o.length;
  99. var i;
  100. var str = "[";
  101. s += "\t";
  102. for( i in 0...l )
  103. str += (if (i > 0) "," else "")+__string_rec(o[i],s);
  104. str += "]";
  105. return str;
  106. }
  107. var tostr;
  108. try {
  109. tostr = untyped o.toString;
  110. } catch( e : Dynamic ) {
  111. // strange error on IE
  112. return "???";
  113. }
  114. if( tostr != null && tostr != __js__("Object.toString") && js.Lib.typeof(tostr) == "function" ) {
  115. var s2 = o.toString();
  116. if( s2 != "[object Object]")
  117. return s2;
  118. }
  119. var k : String = null;
  120. var str = "{\n";
  121. s += "\t";
  122. var hasp = (o.hasOwnProperty != null);
  123. __js__("for( var k in o ) {");
  124. if( hasp && !o.hasOwnProperty(k) )
  125. __js__("continue");
  126. if( k == "prototype" || k == "__class__" || k == "__super__" || k == "__interfaces__" || k == "__properties__" )
  127. __js__("continue");
  128. if( str.length != 2 )
  129. str += ", \n";
  130. str += s + k + " : "+__string_rec(o[k],s);
  131. __js__("}");
  132. s = s.substring(1);
  133. str += "\n" + s + "}";
  134. return str;
  135. case "function":
  136. return "<function>";
  137. case "string":
  138. return o;
  139. default:
  140. return String(o);
  141. }
  142. }
  143. }
  144. private static function __interfLoop(cc : Dynamic,cl : Dynamic) {
  145. if( cc == null )
  146. return false;
  147. if( cc == cl )
  148. return true;
  149. var intf : Dynamic = cc.__interfaces__;
  150. if( intf != null )
  151. for( i in 0...intf.length ) {
  152. var i : Dynamic = intf[i];
  153. if( i == cl || __interfLoop(i,cl) )
  154. return true;
  155. }
  156. return __interfLoop(cc.__super__,cl);
  157. }
  158. @:ifFeature("typed_catch") private static function __instanceof(o : Dynamic,cl : Dynamic) {
  159. if( cl == null )
  160. return false;
  161. switch( cl ) {
  162. case Int:
  163. return js.Lib.typeof(o) == "number" && untyped __js__("(o|0) === o");
  164. case Float:
  165. return js.Lib.typeof(o) == "number";
  166. case Bool:
  167. return js.Lib.typeof(o) == "boolean";
  168. case String:
  169. return js.Lib.typeof(o) == "string";
  170. case Array:
  171. return (untyped __js__("(o instanceof Array)")) && o.__enum__ == null;
  172. case Dynamic:
  173. return true;
  174. default:
  175. if( o != null ) {
  176. // Check if o is an instance of a Haxe class or a native JS object
  177. if( js.Lib.typeof(cl) == "function" ) {
  178. if( untyped __js__("o instanceof cl") )
  179. return true;
  180. if( __interfLoop(getClass(o),cl) )
  181. return true;
  182. }
  183. else if ( js.Lib.typeof(cl) == "object" && __isNativeObj(cl) ) {
  184. if( untyped __js__("o instanceof cl") )
  185. return true;
  186. }
  187. } else {
  188. return false;
  189. }
  190. // do not use isClass/isEnum here
  191. untyped __feature__("Class.*",if( cl == Class && o.__name__ != null ) return true);
  192. untyped __feature__("Enum.*",if( cl == Enum && o.__ename__ != null ) return true);
  193. #if !js_enums_as_objects
  194. return untyped o.__enum__ == cl;
  195. #else
  196. return (untyped $hxEnums[o.__enum__]) == cl;
  197. #end
  198. }
  199. }
  200. @:ifFeature("typed_cast") private static function __cast(o : Dynamic, t : Dynamic) {
  201. if (__instanceof(o, t)) return o;
  202. else throw "Cannot cast " +Std.string(o) + " to " +Std.string(t);
  203. }
  204. static var __toStr = untyped ({}).toString;
  205. // get native JS [[Class]]
  206. static function __nativeClassName(o:Dynamic):String {
  207. var name = untyped __toStr.call(o).slice(8, -1);
  208. // exclude general Object and Function
  209. // also exclude Math and JSON, because instanceof cannot be called on them
  210. if (name == "Object" || name == "Function" || name == "Math" || name == "JSON")
  211. return null;
  212. return name;
  213. }
  214. // check for usable native JS object
  215. static function __isNativeObj(o:Dynamic):Bool {
  216. return __nativeClassName(o) != null;
  217. }
  218. // resolve native JS class in the global scope:
  219. static function __resolveNativeClass(name:String) {
  220. return untyped js.Lib.global[name];
  221. }
  222. }