Boot.hx 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. /*
  2. * Copyright (C)2005-2012 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. }
  32. @:dox(hide)
  33. class Boot {
  34. private static function __unhtml(s : String) {
  35. return s.split("&").join("&amp;").split("<").join("&lt;").split(">").join("&gt;");
  36. }
  37. private static function __trace(v,i : haxe.PosInfos) {
  38. untyped {
  39. var msg = if( i != null ) i.fileName+":"+i.lineNumber+": " else "";
  40. #if jsfl
  41. msg += __string_rec(v,"");
  42. fl.trace(msg);
  43. #else
  44. msg += __string_rec(v, "");
  45. if( i != null && i.customParams != null )
  46. for( v in i.customParams )
  47. msg += "," + __string_rec(v, "");
  48. var d;
  49. if( __js__("typeof")(document) != "undefined" && (d = document.getElementById("haxe:trace")) != null )
  50. d.innerHTML += __unhtml(msg)+"<br/>";
  51. else if( __js__("typeof console") != "undefined" && __js__("console").log != null )
  52. __js__("console").log(msg);
  53. #end
  54. }
  55. }
  56. private static function __clear_trace() {
  57. untyped {
  58. #if jsfl
  59. fl.outputPanel.clear();
  60. #else
  61. var d = document.getElementById("haxe:trace");
  62. if( d != null )
  63. d.innerHTML = "";
  64. #end
  65. }
  66. }
  67. static inline function isClass(o:Dynamic) : Bool {
  68. return untyped __define_feature__("js.Boot.isClass", o.__name__);
  69. }
  70. static inline function isEnum(e:Dynamic) : Bool {
  71. return untyped __define_feature__("js.Boot.isEnum", e.__ename__);
  72. }
  73. static function getClass(o:Dynamic) : Dynamic {
  74. if (Std.is(o, Array))
  75. return Array;
  76. else {
  77. var cl = untyped __define_feature__("js.Boot.getClass", o.__class__);
  78. if (cl != null)
  79. return cl;
  80. var name = __nativeClassName(o);
  81. if (name != null)
  82. return __resolveNativeClass(name);
  83. return null;
  84. }
  85. }
  86. @:ifFeature("has_enum")
  87. private static function __string_rec(o,s:String) {
  88. untyped {
  89. if( o == null )
  90. return "null";
  91. if( s.length >= 5 )
  92. return "<...>"; // too much deep recursion
  93. var t = __js__("typeof(o)");
  94. if( t == "function" && (isClass(o) || isEnum(o)) )
  95. t = "object";
  96. switch( t ) {
  97. case "object":
  98. if( __js__("o instanceof Array") ) {
  99. if( o.__enum__ ) {
  100. if( o.length == 2 )
  101. return o[0];
  102. var str = o[0]+"(";
  103. s += "\t";
  104. for( i in 2...o.length ) {
  105. if( i != 2 )
  106. str += "," + __string_rec(o[i],s);
  107. else
  108. str += __string_rec(o[i],s);
  109. }
  110. return str + ")";
  111. }
  112. var l = o.length;
  113. var i;
  114. var str = "[";
  115. s += "\t";
  116. for( i in 0...l )
  117. str += (if (i > 0) "," else "")+__string_rec(o[i],s);
  118. str += "]";
  119. return str;
  120. }
  121. var tostr;
  122. try {
  123. tostr = untyped o.toString;
  124. } catch( e : Dynamic ) {
  125. // strange error on IE
  126. return "???";
  127. }
  128. if( tostr != null && tostr != __js__("Object.toString") && __typeof__(tostr) == "function" ) {
  129. var s2 = o.toString();
  130. if( s2 != "[object Object]")
  131. return s2;
  132. }
  133. var k : String = null;
  134. var str = "{\n";
  135. s += "\t";
  136. var hasp = (o.hasOwnProperty != null);
  137. __js__("for( var k in o ) {");
  138. if( hasp && !o.hasOwnProperty(k) )
  139. __js__("continue");
  140. if( k == "prototype" || k == "__class__" || k == "__super__" || k == "__interfaces__" || k == "__properties__" )
  141. __js__("continue");
  142. if( str.length != 2 )
  143. str += ", \n";
  144. str += s + k + " : "+__string_rec(o[k],s);
  145. __js__("}");
  146. s = s.substring(1);
  147. str += "\n" + s + "}";
  148. return str;
  149. case "function":
  150. return "<function>";
  151. case "string":
  152. return o;
  153. default:
  154. return String(o);
  155. }
  156. }
  157. }
  158. private static function __interfLoop(cc : Dynamic,cl : Dynamic) {
  159. if( cc == null )
  160. return false;
  161. if( cc == cl )
  162. return true;
  163. var intf : Dynamic = cc.__interfaces__;
  164. if( intf != null )
  165. for( i in 0...intf.length ) {
  166. var i : Dynamic = intf[i];
  167. if( i == cl || __interfLoop(i,cl) )
  168. return true;
  169. }
  170. return __interfLoop(cc.__super__,cl);
  171. }
  172. @:ifFeature("typed_catch") private static function __instanceof(o : Dynamic,cl : Dynamic) {
  173. if( cl == null )
  174. return false;
  175. switch( cl ) {
  176. case Int:
  177. return (untyped __js__("(o|0) === o"));
  178. case Float:
  179. return (untyped __js__("typeof"))(o) == "number";
  180. case Bool:
  181. return (untyped __js__("typeof"))(o) == "boolean";
  182. case String:
  183. return (untyped __js__("typeof"))(o) == "string";
  184. case Array:
  185. return (untyped __js__("(o instanceof Array)")) && o.__enum__ == null;
  186. case Dynamic:
  187. return true;
  188. default:
  189. if( o != null ) {
  190. // Check if o is an instance of a Haxe class or a native JS object
  191. if( (untyped __js__("typeof"))(cl) == "function" ) {
  192. if( untyped __js__("o instanceof cl") )
  193. return true;
  194. if( __interfLoop(getClass(o),cl) )
  195. return true;
  196. }
  197. else if ( (untyped __js__("typeof"))(cl) == "object" && __isNativeObj(cl) ) {
  198. if( untyped __js__("o instanceof cl") )
  199. return true;
  200. }
  201. } else {
  202. return false;
  203. }
  204. // do not use isClass/isEnum here
  205. untyped __feature__("Class.*",if( cl == Class && o.__name__ != null ) return true);
  206. untyped __feature__("Enum.*",if( cl == Enum && o.__ename__ != null ) return true);
  207. return o.__enum__ == cl;
  208. }
  209. }
  210. @:ifFeature("typed_cast") private static function __cast(o : Dynamic, t : Dynamic) {
  211. if (__instanceof(o, t)) return o;
  212. else throw "Cannot cast " +Std.string(o) + " to " +Std.string(t);
  213. }
  214. static var __toStr = untyped __js__("{}.toString");
  215. // get native JS [[Class]]
  216. static function __nativeClassName(o:Dynamic):String {
  217. var name = untyped __toStr.call(o).slice(8, -1);
  218. // exclude general Object and Function
  219. // also exclude Math and JSON, because instanceof cannot be called on them
  220. if (name == "Object" || name == "Function" || name == "Math" || name == "JSON")
  221. return null;
  222. return name;
  223. }
  224. // check for usable native JS object
  225. static function __isNativeObj(o:Dynamic):Bool {
  226. return __nativeClassName(o) != null;
  227. }
  228. // resolve native JS class (with window or global):
  229. static function __resolveNativeClass(name:String) untyped {
  230. if (__js__("typeof window") != "undefined")
  231. return window[name];
  232. else
  233. return global[name];
  234. }
  235. }