Runtime.hx 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  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 java.internal;
  23. /**
  24. This class is meant for internal compiler use only. It provides the Haxe runtime
  25. compatibility to the host language. Do not access it directly.
  26. **/
  27. @:native('haxe.lang.Runtime')
  28. @:nativeGen
  29. @:classCode('
  30. public static java.lang.Object getField(haxe.lang.IHxObject obj, java.lang.String field, boolean throwErrors)
  31. {
  32. if (obj == null && !throwErrors) return null;
  33. return obj.__hx_getField(field, throwErrors, false, false);
  34. }
  35. public static double getField_f(haxe.lang.IHxObject obj, java.lang.String field, boolean throwErrors)
  36. {
  37. if (obj == null && !throwErrors) return 0.0;
  38. return obj.__hx_getField_f(field, throwErrors, false);
  39. }
  40. public static java.lang.Object setField(haxe.lang.IHxObject obj, java.lang.String field, java.lang.Object value)
  41. {
  42. return obj.__hx_setField(field, value, false);
  43. }
  44. public static double setField_f(haxe.lang.IHxObject obj, java.lang.String field, double value)
  45. {
  46. return obj.__hx_setField_f(field, value, false);
  47. }
  48. public static java.lang.Object callField(haxe.lang.IHxObject obj, java.lang.String field, Array<?> args)
  49. {
  50. return obj.__hx_invokeField(field, args);
  51. }
  52. ')
  53. @:keep class Runtime
  54. {
  55. public static var undefined:Dynamic = { };
  56. @:functionCode('
  57. return new haxe.lang.Closure(obj, field);
  58. ')
  59. public static function closure(obj:Dynamic, field:String):Dynamic
  60. {
  61. return null;
  62. }
  63. @:functionCode('
  64. if (v1 == v2)
  65. return true;
  66. if (v1 == null || v2 == null)
  67. return false;
  68. if (v1 instanceof java.lang.Number)
  69. {
  70. if (!(v2 instanceof java.lang.Number))
  71. return false;
  72. java.lang.Number v1c = (java.lang.Number) v1;
  73. java.lang.Number v2c = (java.lang.Number) v2;
  74. if (v1 instanceof java.lang.Long || v2 instanceof java.lang.Long)
  75. return v1c.longValue() == v2c.longValue();
  76. return v1c.doubleValue() == v2c.doubleValue();
  77. } else if (v1 instanceof java.lang.String || v1 instanceof haxe.lang.IEquatable) { //TODO see what happens with Boolean cases
  78. return v1.equals(v2);
  79. }
  80. return false;
  81. ')
  82. public static function eq(v1:Dynamic, v2:Dynamic):Bool
  83. {
  84. return false;
  85. }
  86. @:functionCode('
  87. if (v1 == v2)
  88. return true;
  89. if (v1 instanceof java.lang.String || v1 instanceof haxe.lang.IEquatable)
  90. {
  91. return v1 != null && v1.equals(v2);
  92. } else {
  93. return v1 == v2;
  94. }
  95. ')
  96. public static function refEq(v1: { }, v2: { } ):Bool
  97. {
  98. return false;
  99. }
  100. @:functionCode('
  101. return v1 == v2 || (v1 != null && v1.equals(v2));
  102. ')
  103. public static function valEq(v1: { }, v2: { } ):Bool
  104. {
  105. return false;
  106. }
  107. @:functionCode('
  108. return (obj == null) ? 0.0 : ((java.lang.Number) obj).doubleValue();
  109. ')
  110. public static function toDouble(obj:Dynamic):Float
  111. {
  112. return 0.0;
  113. }
  114. @:functionCode('
  115. return (obj == null) ? false : ((java.lang.Boolean) obj).booleanValue();
  116. ')
  117. public static function toBool(obj:Dynamic):Bool
  118. {
  119. return false;
  120. }
  121. @:functionCode('
  122. return (obj == null) ? 0 : ((java.lang.Number) obj).intValue();
  123. ')
  124. public static function toInt(obj:Dynamic):Int
  125. {
  126. return 0;
  127. }
  128. public static function toLong(obj:Dynamic):haxe.Int64
  129. {
  130. return obj == null ? 0 : (obj : java.lang.Number).longValue();
  131. }
  132. @:functionCode('
  133. if (obj != null && obj instanceof java.lang.Number)
  134. {
  135. return true;
  136. } else {
  137. return false;
  138. }
  139. ')
  140. public static function isDouble(obj:Dynamic):Bool
  141. {
  142. return false;
  143. }
  144. @:overload public static function isInt(obj:Dynamic):Bool
  145. {
  146. if (Std.is(obj, java.lang.Number)) {
  147. var n:java.lang.Number = obj;
  148. return n.doubleValue() == n.intValue();
  149. } else {
  150. return false;
  151. }
  152. }
  153. @:overload public static function isInt(num:java.lang.Number):Bool {
  154. return num != null && num.doubleValue() == num.intValue();
  155. }
  156. @:functionCode('
  157. java.lang.Class cl = null;
  158. if (o instanceof java.lang.Class)
  159. {
  160. if (o == java.lang.String.class)
  161. return field.equals("fromCharCode");
  162. cl = (java.lang.Class) o;
  163. } else if (o instanceof java.lang.String) {
  164. return haxe.lang.StringRefl.handleGetField( (java.lang.String) o, field, false) != null;
  165. } else {
  166. cl = o.getClass();
  167. }
  168. try
  169. {
  170. java.lang.reflect.Field f = cl.getField(field);
  171. return true;
  172. }
  173. catch(Throwable t)
  174. {
  175. java.lang.reflect.Method[] ms = cl.getMethods();
  176. for (int i = 0; i < ms.length; i++)
  177. {
  178. if (ms[i].getName().equals(field))
  179. {
  180. return true;
  181. }
  182. }
  183. }
  184. return false;
  185. ')
  186. public static function slowHasField(o:Dynamic, field:String):Bool
  187. {
  188. return false;
  189. }
  190. @:functionCode('
  191. if (v1 == v2)
  192. return 0;
  193. if (v1 == null) return -1;
  194. if (v2 == null) return 1;
  195. if (v1 instanceof java.lang.Number || v2 instanceof java.lang.Number)
  196. {
  197. java.lang.Number v1c = (java.lang.Number) v1;
  198. java.lang.Number v2c = (java.lang.Number) v2;
  199. if (v1 instanceof java.lang.Long || v2 instanceof java.lang.Long)
  200. {
  201. long l1 = (v1 == null) ? 0L : v1c.longValue();
  202. long l2 = (v2 == null) ? 0L : v2c.longValue();
  203. return (l1 < l2) ? -1 : (l1 > l2) ? 1 : 0;
  204. } else {
  205. double d1 = (v1 == null) ? 0.0 : v1c.doubleValue();
  206. double d2 = (v2 == null) ? 0.0 : v2c.doubleValue();
  207. return (d1 < d2) ? -1 : (d1 > d2) ? 1 : 0;
  208. }
  209. }
  210. //if it\'s not a number it must be a String
  211. return ((java.lang.String) v1).compareTo((java.lang.String) v2);
  212. ')
  213. public static function compare(v1:Dynamic, v2:Dynamic):Int
  214. {
  215. return 0;
  216. }
  217. @:functionCode('
  218. if (v1 instanceof java.lang.String || v2 instanceof java.lang.String)
  219. return toString(v1) + toString(v2);
  220. if (v1 instanceof java.lang.Number || v2 instanceof java.lang.Number)
  221. {
  222. java.lang.Number v1c = (java.lang.Number) v1;
  223. java.lang.Number v2c = (java.lang.Number) v2;
  224. double d1 = (v1 == null) ? 0.0 : v1c.doubleValue();
  225. double d2 = (v2 == null) ? 0.0 : v2c.doubleValue();
  226. return d1 + d2;
  227. }
  228. throw new java.lang.IllegalArgumentException("Cannot dynamically add " + v1 + " and " + v2);
  229. ')
  230. public static function plus(v1:Dynamic, v2:Dynamic):Dynamic
  231. {
  232. return null;
  233. }
  234. @:functionCode('
  235. if (obj == null)
  236. if (throwErrors)
  237. throw new java.lang.NullPointerException("Cannot access field \'" + field + "\' of null.");
  238. else
  239. return null;
  240. java.lang.Class cl = null;
  241. try
  242. {
  243. if (obj instanceof java.lang.Class)
  244. {
  245. if (obj == java.lang.String.class && field.equals("fromCharCode"))
  246. return new haxe.lang.Closure(haxe.lang.StringExt.class, field);
  247. cl = (java.lang.Class) obj;
  248. obj = null;
  249. } else if (obj instanceof java.lang.String) {
  250. return haxe.lang.StringRefl.handleGetField((java.lang.String) obj, field, throwErrors);
  251. } else {
  252. cl = obj.getClass();
  253. }
  254. java.lang.reflect.Field f = cl.getField(field);
  255. f.setAccessible(true);
  256. return f.get(obj);
  257. } catch (Throwable t)
  258. {
  259. try
  260. {
  261. java.lang.reflect.Method[] ms = cl.getMethods();
  262. for (int i = 0; i < ms.length; i++)
  263. {
  264. if (ms[i].getName().equals(field))
  265. {
  266. return new haxe.lang.Closure(obj != null ? obj : cl, field);
  267. }
  268. }
  269. } catch (Throwable t2)
  270. {
  271. }
  272. if (throwErrors)
  273. throw HaxeException.wrap(t);
  274. return null;
  275. }
  276. ')
  277. public static function slowGetField(obj:Dynamic, field:String, throwErrors:Bool):Dynamic
  278. {
  279. return null;
  280. }
  281. @:functionCode('
  282. java.lang.Class cl = null;
  283. if (obj instanceof java.lang.Class)
  284. {
  285. cl = (java.lang.Class) obj;
  286. obj = null;
  287. } else {
  288. cl = obj.getClass();
  289. }
  290. try {
  291. java.lang.reflect.Field f = cl.getField(field);
  292. f.setAccessible(true);
  293. //FIXME we must evaluate if field to be set receives either int or double
  294. if (isInt(value))
  295. {
  296. f.setInt(obj, toInt(value));
  297. } else if (isDouble(value)) {
  298. f.setDouble(obj, toDouble(value));
  299. } else {
  300. f.set(obj, value);
  301. }
  302. return value;
  303. }
  304. catch (Throwable t)
  305. {
  306. throw HaxeException.wrap(t);
  307. }
  308. ')
  309. public static function slowSetField(obj:Dynamic, field:String, value:Dynamic):Dynamic
  310. {
  311. return null;
  312. }
  313. @:functionCode('
  314. java.lang.Class cl = null;
  315. if (obj instanceof java.lang.Class)
  316. {
  317. if (obj == java.lang.String.class && field.equals("fromCharCode"))
  318. return haxe.lang.StringExt.fromCharCode(toInt(args.__get(0)));
  319. cl = (java.lang.Class) obj;
  320. obj = null;
  321. } else if (obj instanceof java.lang.String) {
  322. return haxe.lang.StringRefl.handleCallField((java.lang.String) obj, field, args);
  323. } else {
  324. cl = obj.getClass();
  325. }
  326. if (args == null) args = new Array();
  327. int len = args.length;
  328. java.lang.Class[] cls = new java.lang.Class[len];
  329. java.lang.Object[] objs = new java.lang.Object[len];
  330. java.lang.reflect.Method[] ms = cl.getMethods();
  331. int msl = ms.length;
  332. int realMsl = 0;
  333. for(int i =0; i < msl; i++)
  334. {
  335. if (!ms[i].getName().equals(field) || (!ms[i].isVarArgs() && ms[i].getParameterTypes().length != len))
  336. {
  337. ms[i] = null;
  338. } else {
  339. ms[realMsl] = ms[i];
  340. if (realMsl != i)
  341. ms[i] = null;
  342. realMsl++;
  343. }
  344. }
  345. boolean hasNumber = false;
  346. for (int i = 0; i < len; i++)
  347. {
  348. Object o = args.__get(i);
  349. if (o == null)
  350. {
  351. continue; //can be anything
  352. }
  353. objs[i]= o;
  354. cls[i] = o.getClass();
  355. boolean isNum = false;
  356. if (o instanceof java.lang.Number)
  357. {
  358. cls[i] = java.lang.Number.class;
  359. isNum = hasNumber = true;
  360. } else if (o instanceof java.lang.Boolean) {
  361. cls[i] = java.lang.Boolean.class;
  362. isNum = true;
  363. }
  364. msl = realMsl;
  365. realMsl = 0;
  366. for (int j = 0; j < msl; j++)
  367. {
  368. java.lang.Class[] allcls = ms[j].getParameterTypes();
  369. if (i < allcls.length)
  370. {
  371. if (! ((isNum && allcls[i].isPrimitive()) || allcls[i].isAssignableFrom(cls[i])) )
  372. {
  373. ms[j] = null;
  374. } else {
  375. ms[realMsl] = ms[j];
  376. if (realMsl != j)
  377. ms[j] = null;
  378. realMsl++;
  379. }
  380. }
  381. }
  382. }
  383. java.lang.reflect.Method found;
  384. if (ms.length == 0 || (found = ms[0]) == null)
  385. throw haxe.lang.HaxeException.wrap("No compatible method found for: " + field);
  386. if (hasNumber)
  387. {
  388. java.lang.Class[] allcls = found.getParameterTypes();
  389. for (int i = 0; i < len; i++)
  390. {
  391. java.lang.Object o = objs[i];
  392. if (o instanceof java.lang.Number)
  393. {
  394. java.lang.Class curCls = null;
  395. if (i < allcls.length)
  396. {
  397. curCls = allcls[i];
  398. if (!curCls.isAssignableFrom(o.getClass()))
  399. {
  400. String name = curCls.getName();
  401. if (name.equals("double") || name.equals("java.lang.Double"))
  402. {
  403. objs[i] = ((java.lang.Number)o).doubleValue();
  404. } else if (name.equals("int") || name.equals("java.lang.Integer"))
  405. {
  406. objs[i] = ((java.lang.Number)o).intValue();
  407. } else if (name.equals("float") || name.equals("java.lang.Float"))
  408. {
  409. objs[i] = ((java.lang.Number)o).floatValue();
  410. } else if (name.equals("byte") || name.equals("java.lang.Byte"))
  411. {
  412. objs[i] = ((java.lang.Number)o).byteValue();
  413. } else if (name.equals("short") || name.equals("java.lang.Short"))
  414. {
  415. objs[i] = ((java.lang.Number)o).shortValue();
  416. } else if (name.equals("long") || name.equals("java.lang.Long"))
  417. {
  418. objs[i] = ((java.lang.Number)o).longValue();
  419. }
  420. }
  421. } //else varargs not handled TODO
  422. }
  423. }
  424. }
  425. try {
  426. found.setAccessible(true);
  427. return found.invoke(obj, objs);
  428. }
  429. catch (java.lang.reflect.InvocationTargetException e)
  430. {
  431. throw haxe.lang.HaxeException.wrap(e.getCause());
  432. }
  433. catch (Throwable t)
  434. {
  435. throw haxe.lang.HaxeException.wrap(t);
  436. }
  437. ')
  438. public static function slowCallField(obj:Dynamic, field:String, args:Array<Dynamic>):Dynamic
  439. {
  440. return null;
  441. }
  442. @:functionCode('
  443. if (obj instanceof haxe.lang.IHxObject)
  444. {
  445. return ((haxe.lang.IHxObject) obj).__hx_invokeField(field, args);
  446. }
  447. return slowCallField(obj, field, args);
  448. ')
  449. public static function callField(obj:Dynamic, field:String, args:Array<Dynamic>):Dynamic
  450. {
  451. return null;
  452. }
  453. @:functionCode('
  454. if (obj instanceof haxe.lang.IHxObject)
  455. return ((haxe.lang.IHxObject) obj).__hx_getField(field, throwErrors, false, false);
  456. return slowGetField(obj, field, throwErrors);
  457. ')
  458. public static function getField(obj:Dynamic, field:String, throwErrors:Bool):Dynamic
  459. {
  460. return null;
  461. }
  462. @:functionCode('
  463. if (obj instanceof haxe.lang.IHxObject)
  464. return ((haxe.lang.IHxObject) obj).__hx_getField_f(field, throwErrors, false);
  465. return toDouble(slowGetField(obj, field, throwErrors));
  466. ')
  467. public static function getField_f(obj:Dynamic, field:String, throwErrors:Bool):Float
  468. {
  469. return 0.0;
  470. }
  471. @:functionCode('
  472. if (obj instanceof haxe.lang.IHxObject)
  473. return ((haxe.lang.IHxObject) obj).__hx_setField(field, value, false);
  474. return slowSetField(obj, field, value);
  475. ')
  476. public static function setField(obj:Dynamic, field:String, value:Dynamic):Dynamic
  477. {
  478. return null;
  479. }
  480. @:functionCode('
  481. if (obj instanceof haxe.lang.IHxObject)
  482. return ((haxe.lang.IHxObject) obj).__hx_setField_f(field, value, false);
  483. return toDouble(slowSetField(obj, field, value));
  484. ')
  485. public static function setField_f(obj:Dynamic, field:String, value:Float):Float
  486. {
  487. return 0.0;
  488. }
  489. public static function toString(obj:Dynamic):String
  490. {
  491. if (obj == null)
  492. return null;
  493. if (Std.is(obj, java.lang.Number) && !Std.is(obj, java.lang.Integer.IntegerClass) && isInt( (obj : java.lang.Number) ))
  494. return java.lang.Integer._toString(toInt(obj));
  495. return untyped obj.toString();
  496. }
  497. public static function isFinite(v:Float):Bool
  498. {
  499. return (v == v) && !java.lang.Double.DoubleClass._isInfinite(v);
  500. }
  501. }
  502. @:keep @:native("haxe.lang.EmptyObject") enum EmptyObject
  503. {
  504. EMPTY;
  505. }