jbarnette-johnson 1.0.0.200806240111 → 1.0.0.200807291507

Sign up to get free protection for your applications and to get access to all the features.
Files changed (269) hide show
  1. data/MANIFEST +1 -0
  2. data/Rakefile +3 -10
  3. data/bin/johnson +2 -1
  4. data/ext/spidermonkey/context.c +3 -4
  5. data/ext/spidermonkey/context.h +1 -1
  6. data/ext/spidermonkey/conversions.c +39 -33
  7. data/ext/spidermonkey/debugger.c +5 -5
  8. data/ext/spidermonkey/immutable_node.c.erb +11 -11
  9. data/ext/spidermonkey/jroot.h +4 -4
  10. data/ext/spidermonkey/js_land_proxy.c +9 -8
  11. data/ext/spidermonkey/ruby_land_proxy.c +5 -4
  12. data/ext/spidermonkey/runtime.c +1 -1
  13. data/johnson.gemspec +36 -0
  14. data/lib/hoe.rb +0 -7
  15. data/lib/johnson/cli/options.rb +10 -4
  16. data/lib/johnson/spidermonkey/runtime.rb +2 -2
  17. data/lib/johnson/version.rb +4 -2
  18. data/lib/johnson.rb +1 -0
  19. data/test/johnson/runtime_test.rb +11 -0
  20. data/test/johnson/spidermonkey/ruby_land_proxy_test.rb +6 -0
  21. data/vendor/spidermonkey/.cvsignore +9 -0
  22. data/vendor/spidermonkey/Makefile.in +462 -0
  23. data/vendor/spidermonkey/Makefile.ref +364 -0
  24. data/vendor/spidermonkey/README.html +820 -0
  25. data/vendor/spidermonkey/SpiderMonkey.rsp +12 -0
  26. data/vendor/spidermonkey/Y.js +19 -0
  27. data/vendor/spidermonkey/build.mk +43 -0
  28. data/vendor/spidermonkey/config/AIX4.1.mk +65 -0
  29. data/vendor/spidermonkey/config/AIX4.2.mk +64 -0
  30. data/vendor/spidermonkey/config/AIX4.3.mk +65 -0
  31. data/vendor/spidermonkey/config/Darwin.mk +83 -0
  32. data/vendor/spidermonkey/config/Darwin1.3.mk +81 -0
  33. data/vendor/spidermonkey/config/Darwin1.4.mk +41 -0
  34. data/vendor/spidermonkey/config/Darwin5.2.mk +81 -0
  35. data/vendor/spidermonkey/config/Darwin5.3.mk +81 -0
  36. data/vendor/spidermonkey/config/HP-UXB.10.10.mk +77 -0
  37. data/vendor/spidermonkey/config/HP-UXB.10.20.mk +77 -0
  38. data/vendor/spidermonkey/config/HP-UXB.11.00.mk +80 -0
  39. data/vendor/spidermonkey/config/IRIX.mk +87 -0
  40. data/vendor/spidermonkey/config/IRIX5.3.mk +44 -0
  41. data/vendor/spidermonkey/config/IRIX6.1.mk +44 -0
  42. data/vendor/spidermonkey/config/IRIX6.2.mk +44 -0
  43. data/vendor/spidermonkey/config/IRIX6.3.mk +44 -0
  44. data/vendor/spidermonkey/config/IRIX6.5.mk +44 -0
  45. data/vendor/spidermonkey/config/Linux_All.mk +103 -0
  46. data/vendor/spidermonkey/config/Mac_OS10.0.mk +82 -0
  47. data/vendor/spidermonkey/config/OSF1V4.0.mk +72 -0
  48. data/vendor/spidermonkey/config/OSF1V5.0.mk +69 -0
  49. data/vendor/spidermonkey/config/SunOS4.1.4.mk +101 -0
  50. data/vendor/spidermonkey/config/SunOS5.10.mk +50 -0
  51. data/vendor/spidermonkey/config/SunOS5.3.mk +91 -0
  52. data/vendor/spidermonkey/config/SunOS5.4.mk +92 -0
  53. data/vendor/spidermonkey/config/SunOS5.5.1.mk +44 -0
  54. data/vendor/spidermonkey/config/SunOS5.5.mk +87 -0
  55. data/vendor/spidermonkey/config/SunOS5.6.mk +89 -0
  56. data/vendor/spidermonkey/config/SunOS5.7.mk +44 -0
  57. data/vendor/spidermonkey/config/SunOS5.8.mk +44 -0
  58. data/vendor/spidermonkey/config/SunOS5.9.mk +44 -0
  59. data/vendor/spidermonkey/config/WINNT4.0.mk +117 -0
  60. data/vendor/spidermonkey/config/WINNT5.0.mk +117 -0
  61. data/vendor/spidermonkey/config/WINNT5.1.mk +117 -0
  62. data/vendor/spidermonkey/config/WINNT5.2.mk +117 -0
  63. data/vendor/spidermonkey/config/WINNT6.0.mk +117 -0
  64. data/vendor/spidermonkey/config/dgux.mk +64 -0
  65. data/vendor/spidermonkey/config.mk +192 -0
  66. data/vendor/spidermonkey/editline/Makefile.ref +144 -0
  67. data/vendor/spidermonkey/editline/README +83 -0
  68. data/vendor/spidermonkey/editline/editline.3 +175 -0
  69. data/vendor/spidermonkey/editline/editline.c +1369 -0
  70. data/vendor/spidermonkey/editline/editline.h +135 -0
  71. data/vendor/spidermonkey/editline/sysunix.c +182 -0
  72. data/vendor/spidermonkey/editline/unix.h +82 -0
  73. data/vendor/spidermonkey/fdlibm/.cvsignore +7 -0
  74. data/vendor/spidermonkey/fdlibm/Makefile.in +127 -0
  75. data/vendor/spidermonkey/fdlibm/Makefile.ref +192 -0
  76. data/vendor/spidermonkey/fdlibm/e_acos.c +147 -0
  77. data/vendor/spidermonkey/fdlibm/e_acosh.c +105 -0
  78. data/vendor/spidermonkey/fdlibm/e_asin.c +156 -0
  79. data/vendor/spidermonkey/fdlibm/e_atan2.c +165 -0
  80. data/vendor/spidermonkey/fdlibm/e_atanh.c +110 -0
  81. data/vendor/spidermonkey/fdlibm/e_cosh.c +133 -0
  82. data/vendor/spidermonkey/fdlibm/e_exp.c +202 -0
  83. data/vendor/spidermonkey/fdlibm/e_fmod.c +184 -0
  84. data/vendor/spidermonkey/fdlibm/e_gamma.c +71 -0
  85. data/vendor/spidermonkey/fdlibm/e_gamma_r.c +70 -0
  86. data/vendor/spidermonkey/fdlibm/e_hypot.c +173 -0
  87. data/vendor/spidermonkey/fdlibm/e_j0.c +524 -0
  88. data/vendor/spidermonkey/fdlibm/e_j1.c +523 -0
  89. data/vendor/spidermonkey/fdlibm/e_jn.c +315 -0
  90. data/vendor/spidermonkey/fdlibm/e_lgamma.c +71 -0
  91. data/vendor/spidermonkey/fdlibm/e_lgamma_r.c +347 -0
  92. data/vendor/spidermonkey/fdlibm/e_log.c +184 -0
  93. data/vendor/spidermonkey/fdlibm/e_log10.c +134 -0
  94. data/vendor/spidermonkey/fdlibm/e_pow.c +386 -0
  95. data/vendor/spidermonkey/fdlibm/e_rem_pio2.c +222 -0
  96. data/vendor/spidermonkey/fdlibm/e_remainder.c +120 -0
  97. data/vendor/spidermonkey/fdlibm/e_scalb.c +89 -0
  98. data/vendor/spidermonkey/fdlibm/e_sinh.c +122 -0
  99. data/vendor/spidermonkey/fdlibm/e_sqrt.c +497 -0
  100. data/vendor/spidermonkey/fdlibm/fdlibm.h +273 -0
  101. data/vendor/spidermonkey/fdlibm/fdlibm.mak +1453 -0
  102. data/vendor/spidermonkey/fdlibm/fdlibm.mdp +0 -0
  103. data/vendor/spidermonkey/fdlibm/k_cos.c +135 -0
  104. data/vendor/spidermonkey/fdlibm/k_rem_pio2.c +354 -0
  105. data/vendor/spidermonkey/fdlibm/k_sin.c +114 -0
  106. data/vendor/spidermonkey/fdlibm/k_standard.c +785 -0
  107. data/vendor/spidermonkey/fdlibm/k_tan.c +170 -0
  108. data/vendor/spidermonkey/fdlibm/s_asinh.c +101 -0
  109. data/vendor/spidermonkey/fdlibm/s_atan.c +175 -0
  110. data/vendor/spidermonkey/fdlibm/s_cbrt.c +133 -0
  111. data/vendor/spidermonkey/fdlibm/s_ceil.c +120 -0
  112. data/vendor/spidermonkey/fdlibm/s_copysign.c +72 -0
  113. data/vendor/spidermonkey/fdlibm/s_cos.c +118 -0
  114. data/vendor/spidermonkey/fdlibm/s_erf.c +356 -0
  115. data/vendor/spidermonkey/fdlibm/s_expm1.c +267 -0
  116. data/vendor/spidermonkey/fdlibm/s_fabs.c +70 -0
  117. data/vendor/spidermonkey/fdlibm/s_finite.c +71 -0
  118. data/vendor/spidermonkey/fdlibm/s_floor.c +121 -0
  119. data/vendor/spidermonkey/fdlibm/s_frexp.c +99 -0
  120. data/vendor/spidermonkey/fdlibm/s_ilogb.c +85 -0
  121. data/vendor/spidermonkey/fdlibm/s_isnan.c +74 -0
  122. data/vendor/spidermonkey/fdlibm/s_ldexp.c +66 -0
  123. data/vendor/spidermonkey/fdlibm/s_lib_version.c +73 -0
  124. data/vendor/spidermonkey/fdlibm/s_log1p.c +211 -0
  125. data/vendor/spidermonkey/fdlibm/s_logb.c +79 -0
  126. data/vendor/spidermonkey/fdlibm/s_matherr.c +64 -0
  127. data/vendor/spidermonkey/fdlibm/s_modf.c +132 -0
  128. data/vendor/spidermonkey/fdlibm/s_nextafter.c +124 -0
  129. data/vendor/spidermonkey/fdlibm/s_rint.c +131 -0
  130. data/vendor/spidermonkey/fdlibm/s_scalbn.c +107 -0
  131. data/vendor/spidermonkey/fdlibm/s_signgam.c +40 -0
  132. data/vendor/spidermonkey/fdlibm/s_significand.c +68 -0
  133. data/vendor/spidermonkey/fdlibm/s_sin.c +118 -0
  134. data/vendor/spidermonkey/fdlibm/s_tan.c +112 -0
  135. data/vendor/spidermonkey/fdlibm/s_tanh.c +122 -0
  136. data/vendor/spidermonkey/fdlibm/w_acos.c +78 -0
  137. data/vendor/spidermonkey/fdlibm/w_acosh.c +78 -0
  138. data/vendor/spidermonkey/fdlibm/w_asin.c +80 -0
  139. data/vendor/spidermonkey/fdlibm/w_atan2.c +79 -0
  140. data/vendor/spidermonkey/fdlibm/w_atanh.c +81 -0
  141. data/vendor/spidermonkey/fdlibm/w_cosh.c +77 -0
  142. data/vendor/spidermonkey/fdlibm/w_exp.c +88 -0
  143. data/vendor/spidermonkey/fdlibm/w_fmod.c +78 -0
  144. data/vendor/spidermonkey/fdlibm/w_gamma.c +85 -0
  145. data/vendor/spidermonkey/fdlibm/w_gamma_r.c +81 -0
  146. data/vendor/spidermonkey/fdlibm/w_hypot.c +78 -0
  147. data/vendor/spidermonkey/fdlibm/w_j0.c +105 -0
  148. data/vendor/spidermonkey/fdlibm/w_j1.c +106 -0
  149. data/vendor/spidermonkey/fdlibm/w_jn.c +128 -0
  150. data/vendor/spidermonkey/fdlibm/w_lgamma.c +85 -0
  151. data/vendor/spidermonkey/fdlibm/w_lgamma_r.c +81 -0
  152. data/vendor/spidermonkey/fdlibm/w_log.c +78 -0
  153. data/vendor/spidermonkey/fdlibm/w_log10.c +81 -0
  154. data/vendor/spidermonkey/fdlibm/w_pow.c +99 -0
  155. data/vendor/spidermonkey/fdlibm/w_remainder.c +77 -0
  156. data/vendor/spidermonkey/fdlibm/w_scalb.c +95 -0
  157. data/vendor/spidermonkey/fdlibm/w_sinh.c +77 -0
  158. data/vendor/spidermonkey/fdlibm/w_sqrt.c +77 -0
  159. data/vendor/spidermonkey/javascript-trace.d +73 -0
  160. data/vendor/spidermonkey/js.c +3951 -0
  161. data/vendor/spidermonkey/js.mak +4438 -0
  162. data/vendor/spidermonkey/js.mdp +0 -0
  163. data/vendor/spidermonkey/js.msg +307 -0
  164. data/vendor/spidermonkey/js.pkg +2 -0
  165. data/vendor/spidermonkey/js3240.rc +79 -0
  166. data/vendor/spidermonkey/jsOS240.def +654 -0
  167. data/vendor/spidermonkey/jsapi.c +5836 -0
  168. data/vendor/spidermonkey/jsapi.h +2624 -0
  169. data/vendor/spidermonkey/jsarena.c +450 -0
  170. data/vendor/spidermonkey/jsarena.h +318 -0
  171. data/vendor/spidermonkey/jsarray.c +2988 -0
  172. data/vendor/spidermonkey/jsarray.h +124 -0
  173. data/vendor/spidermonkey/jsatom.c +1045 -0
  174. data/vendor/spidermonkey/jsatom.h +442 -0
  175. data/vendor/spidermonkey/jsbit.h +253 -0
  176. data/vendor/spidermonkey/jsbool.c +176 -0
  177. data/vendor/spidermonkey/jsbool.h +73 -0
  178. data/vendor/spidermonkey/jsclist.h +139 -0
  179. data/vendor/spidermonkey/jscntxt.c +1348 -0
  180. data/vendor/spidermonkey/jscntxt.h +1120 -0
  181. data/vendor/spidermonkey/jscompat.h +57 -0
  182. data/vendor/spidermonkey/jsconfig.h +248 -0
  183. data/vendor/spidermonkey/jsconfig.mk +181 -0
  184. data/vendor/spidermonkey/jscpucfg.c +383 -0
  185. data/vendor/spidermonkey/jscpucfg.h +212 -0
  186. data/vendor/spidermonkey/jsdate.c +2398 -0
  187. data/vendor/spidermonkey/jsdate.h +124 -0
  188. data/vendor/spidermonkey/jsdbgapi.c +1799 -0
  189. data/vendor/spidermonkey/jsdbgapi.h +464 -0
  190. data/vendor/spidermonkey/jsdhash.c +868 -0
  191. data/vendor/spidermonkey/jsdhash.h +592 -0
  192. data/vendor/spidermonkey/jsdtoa.c +3167 -0
  193. data/vendor/spidermonkey/jsdtoa.h +130 -0
  194. data/vendor/spidermonkey/jsdtracef.c +317 -0
  195. data/vendor/spidermonkey/jsdtracef.h +77 -0
  196. data/vendor/spidermonkey/jsemit.c +6909 -0
  197. data/vendor/spidermonkey/jsemit.h +741 -0
  198. data/vendor/spidermonkey/jsexn.c +1371 -0
  199. data/vendor/spidermonkey/jsexn.h +96 -0
  200. data/vendor/spidermonkey/jsfile.c +2736 -0
  201. data/vendor/spidermonkey/jsfile.h +56 -0
  202. data/vendor/spidermonkey/jsfile.msg +90 -0
  203. data/vendor/spidermonkey/jsfun.c +2634 -0
  204. data/vendor/spidermonkey/jsfun.h +254 -0
  205. data/vendor/spidermonkey/jsgc.c +3554 -0
  206. data/vendor/spidermonkey/jsgc.h +403 -0
  207. data/vendor/spidermonkey/jshash.c +476 -0
  208. data/vendor/spidermonkey/jshash.h +151 -0
  209. data/vendor/spidermonkey/jsify.pl +485 -0
  210. data/vendor/spidermonkey/jsinterp.c +6981 -0
  211. data/vendor/spidermonkey/jsinterp.h +521 -0
  212. data/vendor/spidermonkey/jsinvoke.c +43 -0
  213. data/vendor/spidermonkey/jsiter.c +1067 -0
  214. data/vendor/spidermonkey/jsiter.h +122 -0
  215. data/vendor/spidermonkey/jskeyword.tbl +124 -0
  216. data/vendor/spidermonkey/jskwgen.c +460 -0
  217. data/vendor/spidermonkey/jslibmath.h +266 -0
  218. data/vendor/spidermonkey/jslock.c +1309 -0
  219. data/vendor/spidermonkey/jslock.h +313 -0
  220. data/vendor/spidermonkey/jslocko.asm +60 -0
  221. data/vendor/spidermonkey/jslog2.c +94 -0
  222. data/vendor/spidermonkey/jslong.c +264 -0
  223. data/vendor/spidermonkey/jslong.h +412 -0
  224. data/vendor/spidermonkey/jsmath.c +568 -0
  225. data/vendor/spidermonkey/jsmath.h +57 -0
  226. data/vendor/spidermonkey/jsnum.c +1228 -0
  227. data/vendor/spidermonkey/jsnum.h +283 -0
  228. data/vendor/spidermonkey/jsobj.c +5266 -0
  229. data/vendor/spidermonkey/jsobj.h +709 -0
  230. data/vendor/spidermonkey/jsopcode.c +5245 -0
  231. data/vendor/spidermonkey/jsopcode.h +394 -0
  232. data/vendor/spidermonkey/jsopcode.tbl +523 -0
  233. data/vendor/spidermonkey/jsotypes.h +202 -0
  234. data/vendor/spidermonkey/jsparse.c +6680 -0
  235. data/vendor/spidermonkey/jsparse.h +511 -0
  236. data/vendor/spidermonkey/jsprf.c +1262 -0
  237. data/vendor/spidermonkey/jsprf.h +150 -0
  238. data/vendor/spidermonkey/jsproto.tbl +128 -0
  239. data/vendor/spidermonkey/jsprvtd.h +267 -0
  240. data/vendor/spidermonkey/jspubtd.h +744 -0
  241. data/vendor/spidermonkey/jsregexp.c +4352 -0
  242. data/vendor/spidermonkey/jsregexp.h +183 -0
  243. data/vendor/spidermonkey/jsreops.tbl +145 -0
  244. data/vendor/spidermonkey/jsscan.c +2003 -0
  245. data/vendor/spidermonkey/jsscan.h +387 -0
  246. data/vendor/spidermonkey/jsscope.c +1948 -0
  247. data/vendor/spidermonkey/jsscope.h +418 -0
  248. data/vendor/spidermonkey/jsscript.c +1832 -0
  249. data/vendor/spidermonkey/jsscript.h +287 -0
  250. data/vendor/spidermonkey/jsshell.msg +50 -0
  251. data/vendor/spidermonkey/jsstddef.h +83 -0
  252. data/vendor/spidermonkey/jsstr.c +5004 -0
  253. data/vendor/spidermonkey/jsstr.h +641 -0
  254. data/vendor/spidermonkey/jstypes.h +475 -0
  255. data/vendor/spidermonkey/jsutil.c +345 -0
  256. data/vendor/spidermonkey/jsutil.h +157 -0
  257. data/vendor/spidermonkey/jsxdrapi.c +800 -0
  258. data/vendor/spidermonkey/jsxdrapi.h +218 -0
  259. data/vendor/spidermonkey/jsxml.c +8471 -0
  260. data/vendor/spidermonkey/jsxml.h +349 -0
  261. data/vendor/spidermonkey/lock_SunOS.s +119 -0
  262. data/vendor/spidermonkey/perfect.js +39 -0
  263. data/vendor/spidermonkey/plify_jsdhash.sed +36 -0
  264. data/vendor/spidermonkey/prmjtime.c +846 -0
  265. data/vendor/spidermonkey/prmjtime.h +103 -0
  266. data/vendor/spidermonkey/resource.h +15 -0
  267. data/vendor/spidermonkey/rules.mk +197 -0
  268. data/vendor/spidermonkey/win32.order +384 -0
  269. metadata +4 -3
@@ -0,0 +1,57 @@
1
+ /* ***** BEGIN LICENSE BLOCK *****
2
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3
+ *
4
+ * The contents of this file are subject to the Mozilla Public License Version
5
+ * 1.1 (the "License"); you may not use this file except in compliance with
6
+ * the License. You may obtain a copy of the License at
7
+ * http://www.mozilla.org/MPL/
8
+ *
9
+ * Software distributed under the License is distributed on an "AS IS" basis,
10
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11
+ * for the specific language governing rights and limitations under the
12
+ * License.
13
+ *
14
+ * The Original Code is Mozilla Communicator client code, released
15
+ * March 31, 1998.
16
+ *
17
+ * The Initial Developer of the Original Code is
18
+ * Netscape Communications Corporation.
19
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
20
+ * the Initial Developer. All Rights Reserved.
21
+ *
22
+ * Contributor(s):
23
+ *
24
+ * Alternatively, the contents of this file may be used under the terms of
25
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
26
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27
+ * in which case the provisions of the GPL or the LGPL are applicable instead
28
+ * of those above. If you wish to allow use of your version of this file only
29
+ * under the terms of either the GPL or the LGPL, and not to allow others to
30
+ * use your version of this file under the terms of the MPL, indicate your
31
+ * decision by deleting the provisions above and replace them with the notice
32
+ * and other provisions required by the GPL or the LGPL. If you do not delete
33
+ * the provisions above, a recipient may use your version of this file under
34
+ * the terms of any one of the MPL, the GPL or the LGPL.
35
+ *
36
+ * ***** END LICENSE BLOCK ***** */
37
+
38
+ /* -*- Mode: C; tab-width: 8 -*-
39
+ * Copyright (C) 1998-1999 Netscape Communications Corporation, All Rights Reserved.
40
+ */
41
+
42
+ #ifndef jsmath_h___
43
+ #define jsmath_h___
44
+ /*
45
+ * JS math functions.
46
+ */
47
+
48
+ JS_BEGIN_EXTERN_C
49
+
50
+ extern JSClass js_MathClass;
51
+
52
+ extern JSObject *
53
+ js_InitMathClass(JSContext *cx, JSObject *obj);
54
+
55
+ JS_END_EXTERN_C
56
+
57
+ #endif /* jsmath_h___ */
@@ -0,0 +1,1228 @@
1
+ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2
+ *
3
+ * ***** BEGIN LICENSE BLOCK *****
4
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5
+ *
6
+ * The contents of this file are subject to the Mozilla Public License Version
7
+ * 1.1 (the "License"); you may not use this file except in compliance with
8
+ * the License. You may obtain a copy of the License at
9
+ * http://www.mozilla.org/MPL/
10
+ *
11
+ * Software distributed under the License is distributed on an "AS IS" basis,
12
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13
+ * for the specific language governing rights and limitations under the
14
+ * License.
15
+ *
16
+ * The Original Code is Mozilla Communicator client code, released
17
+ * March 31, 1998.
18
+ *
19
+ * The Initial Developer of the Original Code is
20
+ * Netscape Communications Corporation.
21
+ * Portions created by the Initial Developer are Copyright (C) 1998
22
+ * the Initial Developer. All Rights Reserved.
23
+ *
24
+ * Contributor(s):
25
+ * IBM Corp.
26
+ *
27
+ * Alternatively, the contents of this file may be used under the terms of
28
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
29
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30
+ * in which case the provisions of the GPL or the LGPL are applicable instead
31
+ * of those above. If you wish to allow use of your version of this file only
32
+ * under the terms of either the GPL or the LGPL, and not to allow others to
33
+ * use your version of this file under the terms of the MPL, indicate your
34
+ * decision by deleting the provisions above and replace them with the notice
35
+ * and other provisions required by the GPL or the LGPL. If you do not delete
36
+ * the provisions above, a recipient may use your version of this file under
37
+ * the terms of any one of the MPL, the GPL or the LGPL.
38
+ *
39
+ * ***** END LICENSE BLOCK ***** */
40
+
41
+ /*
42
+ * JS number type and wrapper class.
43
+ */
44
+ #include "jsstddef.h"
45
+ #if defined(XP_WIN) || defined(XP_OS2)
46
+ #include <float.h>
47
+ #endif
48
+ #include <locale.h>
49
+ #include <limits.h>
50
+ #include <math.h>
51
+ #include <stdlib.h>
52
+ #include <string.h>
53
+ #include "jstypes.h"
54
+ #include "jsutil.h" /* Added by JSIFY */
55
+ #include "jsapi.h"
56
+ #include "jsatom.h"
57
+ #include "jscntxt.h"
58
+ #include "jsconfig.h"
59
+ #include "jsdtoa.h"
60
+ #include "jsgc.h"
61
+ #include "jsinterp.h"
62
+ #include "jsnum.h"
63
+ #include "jsobj.h"
64
+ #include "jsopcode.h"
65
+ #include "jsprf.h"
66
+ #include "jsscope.h"
67
+ #include "jsstr.h"
68
+
69
+ static JSBool
70
+ num_isNaN(JSContext *cx, uintN argc, jsval *vp)
71
+ {
72
+ jsdouble x;
73
+
74
+ x = js_ValueToNumber(cx, &vp[2]);
75
+ if (JSVAL_IS_NULL(vp[2]))
76
+ return JS_FALSE;
77
+ *vp = BOOLEAN_TO_JSVAL(JSDOUBLE_IS_NaN(x));
78
+ return JS_TRUE;
79
+ }
80
+
81
+ static JSBool
82
+ num_isFinite(JSContext *cx, uintN argc, jsval *vp)
83
+ {
84
+ jsdouble x;
85
+
86
+ x = js_ValueToNumber(cx, &vp[2]);
87
+ if (JSVAL_IS_NULL(vp[2]))
88
+ return JS_FALSE;
89
+ *vp = BOOLEAN_TO_JSVAL(JSDOUBLE_IS_FINITE(x));
90
+ return JS_TRUE;
91
+ }
92
+
93
+ static JSBool
94
+ num_parseFloat(JSContext *cx, uintN argc, jsval *vp)
95
+ {
96
+ JSString *str;
97
+ jsdouble d;
98
+ const jschar *bp, *end, *ep;
99
+
100
+ str = js_ValueToString(cx, vp[2]);
101
+ if (!str)
102
+ return JS_FALSE;
103
+ JSSTRING_CHARS_AND_END(str, bp, end);
104
+ if (!js_strtod(cx, bp, end, &ep, &d))
105
+ return JS_FALSE;
106
+ if (ep == bp) {
107
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
108
+ return JS_TRUE;
109
+ }
110
+ return js_NewNumberInRootedValue(cx, d, vp);
111
+ }
112
+
113
+ /* See ECMA 15.1.2.2. */
114
+ static JSBool
115
+ num_parseInt(JSContext *cx, uintN argc, jsval *vp)
116
+ {
117
+ jsint radix;
118
+ JSString *str;
119
+ jsdouble d;
120
+ const jschar *bp, *end, *ep;
121
+
122
+ if (argc > 1) {
123
+ radix = js_ValueToECMAInt32(cx, &vp[3]);
124
+ if (JSVAL_IS_NULL(vp[3]))
125
+ return JS_FALSE;
126
+ } else {
127
+ radix = 0;
128
+ }
129
+ if (radix != 0 && (radix < 2 || radix > 36)) {
130
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
131
+ return JS_TRUE;
132
+ }
133
+
134
+ if (JSVAL_IS_INT(vp[2]) && (radix == 0 || radix == 10)) {
135
+ *vp = vp[2];
136
+ return JS_TRUE;
137
+ }
138
+
139
+ str = js_ValueToString(cx, vp[2]);
140
+ if (!str)
141
+ return JS_FALSE;
142
+ JSSTRING_CHARS_AND_END(str, bp, end);
143
+ if (!js_strtointeger(cx, bp, end, &ep, radix, &d))
144
+ return JS_FALSE;
145
+ if (ep == bp) {
146
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
147
+ return JS_TRUE;
148
+ }
149
+ return js_NewNumberInRootedValue(cx, d, vp);
150
+ }
151
+
152
+ const char js_Infinity_str[] = "Infinity";
153
+ const char js_NaN_str[] = "NaN";
154
+ const char js_isNaN_str[] = "isNaN";
155
+ const char js_isFinite_str[] = "isFinite";
156
+ const char js_parseFloat_str[] = "parseFloat";
157
+ const char js_parseInt_str[] = "parseInt";
158
+
159
+ static JSFunctionSpec number_functions[] = {
160
+ JS_FN(js_isNaN_str, num_isNaN, 1,1,0),
161
+ JS_FN(js_isFinite_str, num_isFinite, 1,1,0),
162
+ JS_FN(js_parseFloat_str, num_parseFloat, 1,1,0),
163
+ JS_FN(js_parseInt_str, num_parseInt, 1,2,0),
164
+ JS_FS_END
165
+ };
166
+
167
+ JSClass js_NumberClass = {
168
+ js_Number_str,
169
+ JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_Number),
170
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
171
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
172
+ JSCLASS_NO_OPTIONAL_MEMBERS
173
+ };
174
+
175
+ static JSBool
176
+ Number(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
177
+ {
178
+ jsval v;
179
+ jsdouble d;
180
+
181
+ if (argc != 0) {
182
+ d = js_ValueToNumber(cx, &argv[0]);
183
+ v = argv[0];
184
+ if (JSVAL_IS_NULL(v))
185
+ return JS_FALSE;
186
+ if (v != JSVAL_TRUE) {
187
+ JS_ASSERT(JSVAL_IS_INT(v) || JSVAL_IS_DOUBLE(v));
188
+ } else {
189
+ if (!js_NewNumberInRootedValue(cx, d, &argv[0]))
190
+ return JS_FALSE;
191
+ v = argv[0];
192
+ }
193
+ } else {
194
+ v = JSVAL_ZERO;
195
+ }
196
+ if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {
197
+ *rval = v;
198
+ return JS_TRUE;
199
+ }
200
+ STOBJ_SET_SLOT(obj, JSSLOT_PRIVATE, v);
201
+ return JS_TRUE;
202
+ }
203
+
204
+ #if JS_HAS_TOSOURCE
205
+ static JSBool
206
+ num_toSource(JSContext *cx, uintN argc, jsval *vp)
207
+ {
208
+ jsval v;
209
+ jsdouble d;
210
+ char numBuf[DTOSTR_STANDARD_BUFFER_SIZE], *numStr;
211
+ char buf[64];
212
+ JSString *str;
213
+
214
+ if (!js_GetPrimitiveThis(cx, vp, &js_NumberClass, &v))
215
+ return JS_FALSE;
216
+ JS_ASSERT(JSVAL_IS_NUMBER(v));
217
+ d = JSVAL_IS_INT(v) ? (jsdouble)JSVAL_TO_INT(v) : *JSVAL_TO_DOUBLE(v);
218
+ numStr = JS_dtostr(numBuf, sizeof numBuf, DTOSTR_STANDARD, 0, d);
219
+ if (!numStr) {
220
+ JS_ReportOutOfMemory(cx);
221
+ return JS_FALSE;
222
+ }
223
+ JS_snprintf(buf, sizeof buf, "(new %s(%s))", js_NumberClass.name, numStr);
224
+ str = JS_NewStringCopyZ(cx, buf);
225
+ if (!str)
226
+ return JS_FALSE;
227
+ *vp = STRING_TO_JSVAL(str);
228
+ return JS_TRUE;
229
+ }
230
+ #endif
231
+
232
+ /* The buf must be big enough for MIN_INT to fit including '-' and '\0'. */
233
+ char *
234
+ js_IntToCString(jsint i, char *buf, size_t bufSize)
235
+ {
236
+ char *cp;
237
+ jsuint u;
238
+
239
+ u = (i < 0) ? -i : i;
240
+
241
+ cp = buf + bufSize; /* one past last buffer cell */
242
+ *--cp = '\0'; /* null terminate the string to be */
243
+
244
+ /*
245
+ * Build the string from behind. We use multiply and subtraction
246
+ * instead of modulus because that's much faster.
247
+ */
248
+ do {
249
+ jsuint newu = u / 10;
250
+ *--cp = (char)(u - newu * 10) + '0';
251
+ u = newu;
252
+ } while (u != 0);
253
+
254
+ if (i < 0)
255
+ *--cp = '-';
256
+
257
+ JS_ASSERT(cp >= buf);
258
+ return cp;
259
+ }
260
+
261
+ static JSBool
262
+ num_toString(JSContext *cx, uintN argc, jsval *vp)
263
+ {
264
+ jsval v;
265
+ jsdouble d;
266
+ jsint base;
267
+ JSString *str;
268
+
269
+ if (!js_GetPrimitiveThis(cx, vp, &js_NumberClass, &v))
270
+ return JS_FALSE;
271
+ JS_ASSERT(JSVAL_IS_NUMBER(v));
272
+ d = JSVAL_IS_INT(v) ? (jsdouble)JSVAL_TO_INT(v) : *JSVAL_TO_DOUBLE(v);
273
+ base = 10;
274
+ if (argc != 0 && !JSVAL_IS_VOID(vp[2])) {
275
+ base = js_ValueToECMAInt32(cx, &vp[2]);
276
+ if (JSVAL_IS_NULL(vp[2]))
277
+ return JS_FALSE;
278
+ if (base < 2 || base > 36) {
279
+ char numBuf[12];
280
+ char *numStr = js_IntToCString(base, numBuf, sizeof numBuf);
281
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_RADIX,
282
+ numStr);
283
+ return JS_FALSE;
284
+ }
285
+ }
286
+ if (base == 10) {
287
+ str = js_NumberToString(cx, d);
288
+ } else {
289
+ char *dStr = JS_dtobasestr(base, d);
290
+ if (!dStr) {
291
+ JS_ReportOutOfMemory(cx);
292
+ return JS_FALSE;
293
+ }
294
+ str = JS_NewStringCopyZ(cx, dStr);
295
+ free(dStr);
296
+ }
297
+ if (!str)
298
+ return JS_FALSE;
299
+ *vp = STRING_TO_JSVAL(str);
300
+ return JS_TRUE;
301
+ }
302
+
303
+ static JSBool
304
+ num_toLocaleString(JSContext *cx, uintN argc, jsval *vp)
305
+ {
306
+ char thousandsLength, decimalLength;
307
+ const char *numGrouping, *tmpGroup;
308
+ JSRuntime *rt;
309
+ JSString *numStr, *str;
310
+ const char *num, *end, *tmpSrc;
311
+ char *buf, *tmpDest;
312
+ const char *dec;
313
+ int digits, size, remainder, nrepeat;
314
+
315
+ /*
316
+ * Create the string, move back to bytes to make string twiddling
317
+ * a bit easier and so we can insert platform charset seperators.
318
+ */
319
+ if (!num_toString(cx, 0, vp))
320
+ return JS_FALSE;
321
+ JS_ASSERT(JSVAL_IS_STRING(*vp));
322
+ numStr = JSVAL_TO_STRING(*vp);
323
+ num = js_GetStringBytes(cx, numStr);
324
+ if (!num)
325
+ return JS_FALSE;
326
+
327
+ /* Find bit before the decimal. */
328
+ dec = strchr(num, '.');
329
+ digits = dec ? dec - num : (int)strlen(num);
330
+ end = num + digits;
331
+
332
+ rt = cx->runtime;
333
+ thousandsLength = strlen(rt->thousandsSeparator);
334
+ decimalLength = strlen(rt->decimalSeparator);
335
+
336
+ /* Figure out how long resulting string will be. */
337
+ size = digits + (dec ? decimalLength + strlen(dec + 1) : 0);
338
+
339
+ numGrouping = tmpGroup = rt->numGrouping;
340
+ remainder = digits;
341
+ if (*num == '-')
342
+ remainder--;
343
+
344
+ while (*tmpGroup != CHAR_MAX && *tmpGroup != '\0') {
345
+ if (*tmpGroup >= remainder)
346
+ break;
347
+ size += thousandsLength;
348
+ remainder -= *tmpGroup;
349
+ tmpGroup++;
350
+ }
351
+ if (*tmpGroup == '\0' && *numGrouping != '\0') {
352
+ nrepeat = (remainder - 1) / tmpGroup[-1];
353
+ size += thousandsLength * nrepeat;
354
+ remainder -= nrepeat * tmpGroup[-1];
355
+ } else {
356
+ nrepeat = 0;
357
+ }
358
+ tmpGroup--;
359
+
360
+ buf = (char *)JS_malloc(cx, size + 1);
361
+ if (!buf)
362
+ return JS_FALSE;
363
+
364
+ tmpDest = buf;
365
+ tmpSrc = num;
366
+
367
+ while (*tmpSrc == '-' || remainder--)
368
+ *tmpDest++ = *tmpSrc++;
369
+ while (tmpSrc < end) {
370
+ strcpy(tmpDest, rt->thousandsSeparator);
371
+ tmpDest += thousandsLength;
372
+ memcpy(tmpDest, tmpSrc, *tmpGroup);
373
+ tmpDest += *tmpGroup;
374
+ tmpSrc += *tmpGroup;
375
+ if (--nrepeat < 0)
376
+ tmpGroup--;
377
+ }
378
+
379
+ if (dec) {
380
+ strcpy(tmpDest, rt->decimalSeparator);
381
+ tmpDest += decimalLength;
382
+ strcpy(tmpDest, dec + 1);
383
+ } else {
384
+ *tmpDest++ = '\0';
385
+ }
386
+
387
+ if (cx->localeCallbacks && cx->localeCallbacks->localeToUnicode)
388
+ return cx->localeCallbacks->localeToUnicode(cx, buf, vp);
389
+
390
+ str = JS_NewString(cx, buf, size);
391
+ if (!str) {
392
+ JS_free(cx, buf);
393
+ return JS_FALSE;
394
+ }
395
+
396
+ *vp = STRING_TO_JSVAL(str);
397
+ return JS_TRUE;
398
+ }
399
+
400
+ static JSBool
401
+ num_valueOf(JSContext *cx, uintN argc, jsval *vp)
402
+ {
403
+ jsval v;
404
+ JSObject *obj;
405
+
406
+ v = vp[1];
407
+ if (JSVAL_IS_NUMBER(v)) {
408
+ *vp = v;
409
+ return JS_TRUE;
410
+ }
411
+ obj = JS_THIS_OBJECT(cx, vp);
412
+ if (!JS_InstanceOf(cx, obj, &js_NumberClass, vp + 2))
413
+ return JS_FALSE;
414
+ *vp = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
415
+ return JS_TRUE;
416
+ }
417
+
418
+
419
+ #define MAX_PRECISION 100
420
+
421
+ static JSBool
422
+ num_to(JSContext *cx, JSDToStrMode zeroArgMode, JSDToStrMode oneArgMode,
423
+ jsint precisionMin, jsint precisionMax, jsint precisionOffset,
424
+ uintN argc, jsval *vp)
425
+ {
426
+ jsval v;
427
+ jsdouble d, precision;
428
+ JSString *str;
429
+
430
+ /* Use MAX_PRECISION+1 because precisionOffset can be 1. */
431
+ char buf[DTOSTR_VARIABLE_BUFFER_SIZE(MAX_PRECISION+1)];
432
+ char *numStr;
433
+
434
+ if (!js_GetPrimitiveThis(cx, vp, &js_NumberClass, &v))
435
+ return JS_FALSE;
436
+ JS_ASSERT(JSVAL_IS_NUMBER(v));
437
+ d = JSVAL_IS_INT(v) ? (jsdouble)JSVAL_TO_INT(v) : *JSVAL_TO_DOUBLE(v);
438
+
439
+ if (argc == 0) {
440
+ precision = 0.0;
441
+ oneArgMode = zeroArgMode;
442
+ } else {
443
+ precision = js_ValueToNumber(cx, &vp[2]);
444
+ if (JSVAL_IS_NULL(vp[2]))
445
+ return JS_FALSE;
446
+ precision = js_DoubleToInteger(precision);
447
+ if (precision < precisionMin || precision > precisionMax) {
448
+ numStr = JS_dtostr(buf, sizeof buf, DTOSTR_STANDARD, 0, precision);
449
+ if (!numStr)
450
+ JS_ReportOutOfMemory(cx);
451
+ else
452
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_PRECISION_RANGE, numStr);
453
+ return JS_FALSE;
454
+ }
455
+ }
456
+
457
+ numStr = JS_dtostr(buf, sizeof buf, oneArgMode, (jsint)precision + precisionOffset, d);
458
+ if (!numStr) {
459
+ JS_ReportOutOfMemory(cx);
460
+ return JS_FALSE;
461
+ }
462
+ str = JS_NewStringCopyZ(cx, numStr);
463
+ if (!str)
464
+ return JS_FALSE;
465
+ *vp = STRING_TO_JSVAL(str);
466
+ return JS_TRUE;
467
+ }
468
+
469
+ /*
470
+ * In the following three implementations, we allow a larger range of precision
471
+ * than ECMA requires; this is permitted by ECMA-262.
472
+ */
473
+ static JSBool
474
+ num_toFixed(JSContext *cx, uintN argc, jsval *vp)
475
+ {
476
+ return num_to(cx, DTOSTR_FIXED, DTOSTR_FIXED, -20, MAX_PRECISION, 0,
477
+ argc, vp);
478
+ }
479
+
480
+ static JSBool
481
+ num_toExponential(JSContext *cx, uintN argc, jsval *vp)
482
+ {
483
+ return num_to(cx, DTOSTR_STANDARD_EXPONENTIAL, DTOSTR_EXPONENTIAL, 0,
484
+ MAX_PRECISION, 1, argc, vp);
485
+ }
486
+
487
+ static JSBool
488
+ num_toPrecision(JSContext *cx, uintN argc, jsval *vp)
489
+ {
490
+ if (JSVAL_IS_VOID(vp[2]))
491
+ return num_toString(cx, 0, vp);
492
+ return num_to(cx, DTOSTR_STANDARD, DTOSTR_PRECISION, 1, MAX_PRECISION, 0,
493
+ argc, vp);
494
+ }
495
+
496
+ static JSFunctionSpec number_methods[] = {
497
+ #if JS_HAS_TOSOURCE
498
+ JS_FN(js_toSource_str, num_toSource, 0,0,JSFUN_THISP_NUMBER),
499
+ #endif
500
+ JS_FN(js_toString_str, num_toString, 0,1,JSFUN_THISP_NUMBER),
501
+ JS_FN(js_toLocaleString_str, num_toLocaleString, 0,0,JSFUN_THISP_NUMBER),
502
+ JS_FN(js_valueOf_str, num_valueOf, 0,0,JSFUN_THISP_NUMBER),
503
+ JS_FN("toFixed", num_toFixed, 1,1,JSFUN_THISP_NUMBER),
504
+ JS_FN("toExponential", num_toExponential, 1,1,JSFUN_THISP_NUMBER),
505
+ JS_FN("toPrecision", num_toPrecision, 1,1,JSFUN_THISP_NUMBER),
506
+ JS_FS_END
507
+ };
508
+
509
+ /* NB: Keep this in synch with number_constants[]. */
510
+ enum nc_slot {
511
+ NC_NaN,
512
+ NC_POSITIVE_INFINITY,
513
+ NC_NEGATIVE_INFINITY,
514
+ NC_MAX_VALUE,
515
+ NC_MIN_VALUE,
516
+ NC_LIMIT
517
+ };
518
+
519
+ /*
520
+ * Some to most C compilers forbid spelling these at compile time, or barf
521
+ * if you try, so all but MAX_VALUE are set up by js_InitRuntimeNumberState
522
+ * using union jsdpun.
523
+ */
524
+ static JSConstDoubleSpec number_constants[] = {
525
+ {0, js_NaN_str, 0,{0,0,0}},
526
+ {0, "POSITIVE_INFINITY", 0,{0,0,0}},
527
+ {0, "NEGATIVE_INFINITY", 0,{0,0,0}},
528
+ {1.7976931348623157E+308, "MAX_VALUE", 0,{0,0,0}},
529
+ {0, "MIN_VALUE", 0,{0,0,0}},
530
+ {0,0,0,{0,0,0}}
531
+ };
532
+
533
+ static jsdouble NaN;
534
+
535
+ #if (defined XP_WIN || defined XP_OS2) && \
536
+ !defined WINCE && \
537
+ !defined __MWERKS__ && \
538
+ (defined _M_IX86 || \
539
+ (defined __GNUC__ && !defined __MINGW32__))
540
+
541
+ /*
542
+ * Set the exception mask to mask all exceptions and set the FPU precision
543
+ * to 53 bit mantissa.
544
+ * On Alpha platform this is handled via Compiler option.
545
+ */
546
+ #define FIX_FPU() _control87(MCW_EM | PC_53, MCW_EM | MCW_PC)
547
+
548
+ #else
549
+
550
+ #define FIX_FPU() ((void)0)
551
+
552
+ #endif
553
+
554
+ JSBool
555
+ js_InitRuntimeNumberState(JSContext *cx)
556
+ {
557
+ JSRuntime *rt;
558
+ jsdpun u;
559
+ struct lconv *locale;
560
+
561
+ rt = cx->runtime;
562
+ JS_ASSERT(!rt->jsNaN);
563
+
564
+ FIX_FPU();
565
+
566
+ u.s.hi = JSDOUBLE_HI32_EXPMASK | JSDOUBLE_HI32_MANTMASK;
567
+ u.s.lo = 0xffffffff;
568
+ number_constants[NC_NaN].dval = NaN = u.d;
569
+ rt->jsNaN = js_NewWeaklyRootedDouble(cx, NaN);
570
+ if (!rt->jsNaN)
571
+ return JS_FALSE;
572
+
573
+ u.s.hi = JSDOUBLE_HI32_EXPMASK;
574
+ u.s.lo = 0x00000000;
575
+ number_constants[NC_POSITIVE_INFINITY].dval = u.d;
576
+ rt->jsPositiveInfinity = js_NewWeaklyRootedDouble(cx, u.d);
577
+ if (!rt->jsPositiveInfinity)
578
+ return JS_FALSE;
579
+
580
+ u.s.hi = JSDOUBLE_HI32_SIGNBIT | JSDOUBLE_HI32_EXPMASK;
581
+ u.s.lo = 0x00000000;
582
+ number_constants[NC_NEGATIVE_INFINITY].dval = u.d;
583
+ rt->jsNegativeInfinity = js_NewWeaklyRootedDouble(cx, u.d);
584
+ if (!rt->jsNegativeInfinity)
585
+ return JS_FALSE;
586
+
587
+ u.s.hi = 0;
588
+ u.s.lo = 1;
589
+ number_constants[NC_MIN_VALUE].dval = u.d;
590
+
591
+ locale = localeconv();
592
+ rt->thousandsSeparator =
593
+ JS_strdup(cx, locale->thousands_sep ? locale->thousands_sep : "'");
594
+ rt->decimalSeparator =
595
+ JS_strdup(cx, locale->decimal_point ? locale->decimal_point : ".");
596
+ rt->numGrouping =
597
+ JS_strdup(cx, locale->grouping ? locale->grouping : "\3\0");
598
+
599
+ return rt->thousandsSeparator && rt->decimalSeparator && rt->numGrouping;
600
+ }
601
+
602
+ void
603
+ js_TraceRuntimeNumberState(JSTracer *trc)
604
+ {
605
+ JSRuntime *rt;
606
+
607
+ rt = trc->context->runtime;
608
+ if (rt->jsNaN)
609
+ JS_CALL_DOUBLE_TRACER(trc, rt->jsNaN, "NaN");
610
+ if (rt->jsPositiveInfinity)
611
+ JS_CALL_DOUBLE_TRACER(trc, rt->jsPositiveInfinity, "+Infinity");
612
+ if (rt->jsNegativeInfinity)
613
+ JS_CALL_DOUBLE_TRACER(trc, rt->jsNegativeInfinity, "-Infinity");
614
+ }
615
+
616
+ void
617
+ js_FinishRuntimeNumberState(JSContext *cx)
618
+ {
619
+ JSRuntime *rt = cx->runtime;
620
+
621
+ js_UnlockGCThingRT(rt, rt->jsNaN);
622
+ js_UnlockGCThingRT(rt, rt->jsNegativeInfinity);
623
+ js_UnlockGCThingRT(rt, rt->jsPositiveInfinity);
624
+
625
+ rt->jsNaN = NULL;
626
+ rt->jsNegativeInfinity = NULL;
627
+ rt->jsPositiveInfinity = NULL;
628
+
629
+ JS_free(cx, (void *)rt->thousandsSeparator);
630
+ JS_free(cx, (void *)rt->decimalSeparator);
631
+ JS_free(cx, (void *)rt->numGrouping);
632
+ rt->thousandsSeparator = rt->decimalSeparator = rt->numGrouping = NULL;
633
+ }
634
+
635
+ JSObject *
636
+ js_InitNumberClass(JSContext *cx, JSObject *obj)
637
+ {
638
+ JSObject *proto, *ctor;
639
+ JSRuntime *rt;
640
+
641
+ /* XXX must do at least once per new thread, so do it per JSContext... */
642
+ FIX_FPU();
643
+
644
+ if (!JS_DefineFunctions(cx, obj, number_functions))
645
+ return NULL;
646
+
647
+ proto = JS_InitClass(cx, obj, NULL, &js_NumberClass, Number, 1,
648
+ NULL, number_methods, NULL, NULL);
649
+ if (!proto || !(ctor = JS_GetConstructor(cx, proto)))
650
+ return NULL;
651
+ STOBJ_SET_SLOT(proto, JSSLOT_PRIVATE, JSVAL_ZERO);
652
+ if (!JS_DefineConstDoubles(cx, ctor, number_constants))
653
+ return NULL;
654
+
655
+ /* ECMA 15.1.1.1 */
656
+ rt = cx->runtime;
657
+ if (!JS_DefineProperty(cx, obj, js_NaN_str, DOUBLE_TO_JSVAL(rt->jsNaN),
658
+ NULL, NULL, JSPROP_PERMANENT)) {
659
+ return NULL;
660
+ }
661
+
662
+ /* ECMA 15.1.1.2 */
663
+ if (!JS_DefineProperty(cx, obj, js_Infinity_str,
664
+ DOUBLE_TO_JSVAL(rt->jsPositiveInfinity),
665
+ NULL, NULL, JSPROP_PERMANENT)) {
666
+ return NULL;
667
+ }
668
+ return proto;
669
+ }
670
+
671
+ JSBool
672
+ js_NewNumberInRootedValue(JSContext *cx, jsdouble d, jsval *vp)
673
+ {
674
+ jsint i;
675
+
676
+ if (JSDOUBLE_IS_INT(d, i) && INT_FITS_IN_JSVAL(i)) {
677
+ *vp = INT_TO_JSVAL(i);
678
+ return JS_TRUE;
679
+ }
680
+ return js_NewDoubleInRootedValue(cx, d, vp);
681
+ }
682
+
683
+ char *
684
+ js_NumberToCString(JSContext *cx, jsdouble d, char *buf, size_t bufSize)
685
+ {
686
+ jsint i;
687
+ char *numStr;
688
+
689
+ JS_ASSERT(bufSize >= DTOSTR_STANDARD_BUFFER_SIZE);
690
+ if (JSDOUBLE_IS_INT(d, i)) {
691
+ numStr = js_IntToCString(i, buf, bufSize);
692
+ } else {
693
+ numStr = JS_dtostr(buf, bufSize, DTOSTR_STANDARD, 0, d);
694
+ if (!numStr) {
695
+ JS_ReportOutOfMemory(cx);
696
+ return NULL;
697
+ }
698
+ }
699
+ return numStr;
700
+ }
701
+
702
+ JSString *
703
+ js_NumberToString(JSContext *cx, jsdouble d)
704
+ {
705
+ char buf[DTOSTR_STANDARD_BUFFER_SIZE];
706
+ char *numStr;
707
+
708
+ numStr = js_NumberToCString(cx, d, buf, sizeof buf);
709
+ if (!numStr)
710
+ return NULL;
711
+ return JS_NewStringCopyZ(cx, numStr);
712
+ }
713
+
714
+ jsdouble
715
+ js_ValueToNumber(JSContext *cx, jsval *vp)
716
+ {
717
+ jsval v;
718
+ JSString *str;
719
+ const jschar *bp, *end, *ep;
720
+ jsdouble d, *dp;
721
+ JSObject *obj;
722
+ JSTempValueRooter tvr;
723
+
724
+ v = *vp;
725
+ for (;;) {
726
+ if (JSVAL_IS_INT(v))
727
+ return (jsdouble) JSVAL_TO_INT(v);
728
+ if (JSVAL_IS_DOUBLE(v))
729
+ return *JSVAL_TO_DOUBLE(v);
730
+ if (JSVAL_IS_STRING(v)) {
731
+ str = JSVAL_TO_STRING(v);
732
+
733
+ /*
734
+ * Note that ECMA doesn't treat a string beginning with a '0' as
735
+ * an octal number here. This works because all such numbers will
736
+ * be interpreted as decimal by js_strtod and will never get
737
+ * passed to js_strtointeger (which would interpret them as
738
+ * octal).
739
+ */
740
+ JSSTRING_CHARS_AND_END(str, bp, end);
741
+ if ((!js_strtod(cx, bp, end, &ep, &d) ||
742
+ js_SkipWhiteSpace(ep, end) != end) &&
743
+ (!js_strtointeger(cx, bp, end, &ep, 0, &d) ||
744
+ js_SkipWhiteSpace(ep, end) != end)) {
745
+ break;
746
+ }
747
+
748
+ /*
749
+ * JSVAL_TRUE indicates that double jsval was never constructed
750
+ * for the result.
751
+ */
752
+ *vp = JSVAL_TRUE;
753
+ return d;
754
+ }
755
+ if (JSVAL_IS_BOOLEAN(v)) {
756
+ if (JSVAL_TO_BOOLEAN(v)) {
757
+ *vp = JSVAL_ONE;
758
+ return 1.0;
759
+ } else {
760
+ *vp = JSVAL_ZERO;
761
+ return 0.0;
762
+ }
763
+ }
764
+ if (JSVAL_IS_NULL(v)) {
765
+ *vp = JSVAL_ZERO;
766
+ return 0.0;
767
+ }
768
+ if (JSVAL_IS_VOID(v))
769
+ break;
770
+
771
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(v));
772
+ obj = JSVAL_TO_OBJECT(v);
773
+
774
+ /*
775
+ * vp roots obj so we cannot use it as an extra root for
776
+ * OBJ_DEFAULT_VALUE result when calling the hook.
777
+ */
778
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, v, &tvr);
779
+ if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_NUMBER, &tvr.u.value))
780
+ obj = NULL;
781
+ else
782
+ v = *vp = tvr.u.value;
783
+ JS_POP_TEMP_ROOT(cx, &tvr);
784
+ if (!obj) {
785
+ *vp = JSVAL_NULL;
786
+ return 0.0;
787
+ }
788
+ if (!JSVAL_IS_PRIMITIVE(v))
789
+ break;
790
+ }
791
+
792
+ dp = cx->runtime->jsNaN;
793
+ *vp = DOUBLE_TO_JSVAL(dp);
794
+ return *dp;
795
+ }
796
+
797
+ int32
798
+ js_ValueToECMAInt32(JSContext *cx, jsval *vp)
799
+ {
800
+ jsval v;
801
+ jsdouble d;
802
+
803
+ v = *vp;
804
+ if (JSVAL_IS_INT(v))
805
+ return JSVAL_TO_INT(v);
806
+ if (JSVAL_IS_DOUBLE(v)) {
807
+ d = *JSVAL_TO_DOUBLE(v);
808
+ *vp = JSVAL_TRUE;
809
+ } else {
810
+ d = js_ValueToNumber(cx, vp);
811
+ if (JSVAL_IS_NULL(*vp))
812
+ return 0;
813
+ *vp = JSVAL_TRUE;
814
+ }
815
+ return js_DoubleToECMAInt32(d);
816
+ }
817
+
818
+ int32
819
+ js_DoubleToECMAInt32(jsdouble d)
820
+ {
821
+ int32 i;
822
+ jsdouble two32, two31;
823
+
824
+ if (!JSDOUBLE_IS_FINITE(d))
825
+ return 0;
826
+
827
+ i = (int32) d;
828
+ if ((jsdouble) i == d)
829
+ return i;
830
+
831
+ two32 = 4294967296.0;
832
+ two31 = 2147483648.0;
833
+ d = fmod(d, two32);
834
+ d = (d >= 0) ? floor(d) : ceil(d) + two32;
835
+ return (int32) (d >= two31 ? d - two32 : d);
836
+ }
837
+
838
+ uint32
839
+ js_ValueToECMAUint32(JSContext *cx, jsval *vp)
840
+ {
841
+ jsval v;
842
+ jsint i;
843
+ jsdouble d;
844
+
845
+ v = *vp;
846
+ if (JSVAL_IS_INT(v)) {
847
+ i = JSVAL_TO_INT(v);
848
+ if (i < 0)
849
+ *vp = JSVAL_TRUE;
850
+ return (uint32) i;
851
+ }
852
+ if (JSVAL_IS_DOUBLE(v)) {
853
+ d = *JSVAL_TO_DOUBLE(v);
854
+ *vp = JSVAL_TRUE;
855
+ } else {
856
+ d = js_ValueToNumber(cx, vp);
857
+ if (JSVAL_IS_NULL(*vp))
858
+ return 0;
859
+ *vp = JSVAL_TRUE;
860
+ }
861
+ return js_DoubleToECMAUint32(d);
862
+ }
863
+
864
+ uint32
865
+ js_DoubleToECMAUint32(jsdouble d)
866
+ {
867
+ int32 i;
868
+ JSBool neg;
869
+ jsdouble two32;
870
+
871
+ if (!JSDOUBLE_IS_FINITE(d))
872
+ return 0;
873
+
874
+ /*
875
+ * We check whether d fits int32, not uint32, as all but the ">>>" bit
876
+ * manipulation bytecode stores the result as int, not uint. When the
877
+ * result does not fit int jsval, it will be stored as a negative double.
878
+ */
879
+ i = (int32) d;
880
+ if ((jsdouble) i == d)
881
+ return (int32)i;
882
+
883
+ neg = (d < 0);
884
+ d = floor(neg ? -d : d);
885
+ d = neg ? -d : d;
886
+
887
+ two32 = 4294967296.0;
888
+ d = fmod(d, two32);
889
+
890
+ return (uint32) (d >= 0 ? d : d + two32);
891
+ }
892
+
893
+ int32
894
+ js_ValueToInt32(JSContext *cx, jsval *vp)
895
+ {
896
+ jsval v;
897
+ jsdouble d;
898
+
899
+ v = *vp;
900
+ if (JSVAL_IS_INT(v))
901
+ return JSVAL_TO_INT(v);
902
+ d = js_ValueToNumber(cx, vp);
903
+ if (JSVAL_IS_NULL(*vp))
904
+ return 0;
905
+ if (JSVAL_IS_INT(*vp))
906
+ return JSVAL_TO_INT(*vp);
907
+
908
+ *vp = JSVAL_TRUE;
909
+ if (JSDOUBLE_IS_NaN(d) || d <= -2147483649.0 || 2147483648.0 <= d) {
910
+ js_ReportValueError(cx, JSMSG_CANT_CONVERT,
911
+ JSDVG_SEARCH_STACK, v, NULL);
912
+ *vp = JSVAL_NULL;
913
+ return 0;
914
+ }
915
+ return (int32) floor(d + 0.5); /* Round to nearest */
916
+ }
917
+
918
+ uint16
919
+ js_ValueToUint16(JSContext *cx, jsval *vp)
920
+ {
921
+ jsdouble d;
922
+ uint16 u;
923
+ jsuint m;
924
+ JSBool neg;
925
+
926
+ d = js_ValueToNumber(cx, vp);
927
+ if (JSVAL_IS_NULL(*vp))
928
+ return 0;
929
+
930
+ if (JSVAL_IS_INT(*vp)) {
931
+ u = (uint16) JSVAL_TO_INT(*vp);
932
+ } else if (d == 0 || !JSDOUBLE_IS_FINITE(d)) {
933
+ u = (uint16) 0;
934
+ } else {
935
+ u = (uint16) d;
936
+ if ((jsdouble) u != d) {
937
+ neg = (d < 0);
938
+ d = floor(neg ? -d : d);
939
+ d = neg ? -d : d;
940
+ m = JS_BIT(16);
941
+ d = fmod(d, (double) m);
942
+ if (d < 0)
943
+ d += m;
944
+ u = (uint16) d;
945
+ }
946
+ }
947
+ *vp = INT_TO_JSVAL(u);
948
+ return u;
949
+ }
950
+
951
+ jsdouble
952
+ js_DoubleToInteger(jsdouble d)
953
+ {
954
+ JSBool neg;
955
+
956
+ if (d == 0)
957
+ return d;
958
+ if (!JSDOUBLE_IS_FINITE(d)) {
959
+ if (JSDOUBLE_IS_NaN(d))
960
+ return 0;
961
+ return d;
962
+ }
963
+ neg = (d < 0);
964
+ d = floor(neg ? -d : d);
965
+ return neg ? -d : d;
966
+ }
967
+
968
+ JSBool
969
+ js_strtod(JSContext *cx, const jschar *s, const jschar *send,
970
+ const jschar **ep, jsdouble *dp)
971
+ {
972
+ const jschar *s1;
973
+ size_t length, i;
974
+ char cbuf[32];
975
+ char *cstr, *istr, *estr;
976
+ JSBool negative;
977
+ jsdouble d;
978
+
979
+ s1 = js_SkipWhiteSpace(s, send);
980
+ length = send - s1;
981
+
982
+ /* Use cbuf to avoid malloc */
983
+ if (length >= sizeof cbuf) {
984
+ cstr = (char *) JS_malloc(cx, length + 1);
985
+ if (!cstr)
986
+ return JS_FALSE;
987
+ } else {
988
+ cstr = cbuf;
989
+ }
990
+
991
+ for (i = 0; i != length; i++) {
992
+ if (s1[i] >> 8)
993
+ break;
994
+ cstr[i] = (char)s1[i];
995
+ }
996
+ cstr[i] = 0;
997
+
998
+ istr = cstr;
999
+ if ((negative = (*istr == '-')) != 0 || *istr == '+')
1000
+ istr++;
1001
+ if (!strncmp(istr, js_Infinity_str, sizeof js_Infinity_str - 1)) {
1002
+ d = *(negative ? cx->runtime->jsNegativeInfinity : cx->runtime->jsPositiveInfinity);
1003
+ estr = istr + 8;
1004
+ } else {
1005
+ int err;
1006
+ d = JS_strtod(cstr, &estr, &err);
1007
+ if (err == JS_DTOA_ENOMEM) {
1008
+ JS_ReportOutOfMemory(cx);
1009
+ if (cstr != cbuf)
1010
+ JS_free(cx, cstr);
1011
+ return JS_FALSE;
1012
+ }
1013
+ if (err == JS_DTOA_ERANGE) {
1014
+ if (d == HUGE_VAL)
1015
+ d = *cx->runtime->jsPositiveInfinity;
1016
+ else if (d == -HUGE_VAL)
1017
+ d = *cx->runtime->jsNegativeInfinity;
1018
+ }
1019
+ #ifdef HPUX
1020
+ if (d == 0.0 && negative) {
1021
+ /*
1022
+ * "-0", "-1e-2000" come out as positive zero
1023
+ * here on HPUX. Force a negative zero instead.
1024
+ */
1025
+ JSDOUBLE_HI32(d) = JSDOUBLE_HI32_SIGNBIT;
1026
+ JSDOUBLE_LO32(d) = 0;
1027
+ }
1028
+ #endif
1029
+ }
1030
+
1031
+ i = estr - cstr;
1032
+ if (cstr != cbuf)
1033
+ JS_free(cx, cstr);
1034
+ *ep = i ? s1 + i : s;
1035
+ *dp = d;
1036
+ return JS_TRUE;
1037
+ }
1038
+
1039
+ struct BinaryDigitReader
1040
+ {
1041
+ uintN base; /* Base of number; must be a power of 2 */
1042
+ uintN digit; /* Current digit value in radix given by base */
1043
+ uintN digitMask; /* Mask to extract the next bit from digit */
1044
+ const jschar *digits; /* Pointer to the remaining digits */
1045
+ const jschar *end; /* Pointer to first non-digit */
1046
+ };
1047
+
1048
+ /* Return the next binary digit from the number or -1 if done */
1049
+ static intN GetNextBinaryDigit(struct BinaryDigitReader *bdr)
1050
+ {
1051
+ intN bit;
1052
+
1053
+ if (bdr->digitMask == 0) {
1054
+ uintN c;
1055
+
1056
+ if (bdr->digits == bdr->end)
1057
+ return -1;
1058
+
1059
+ c = *bdr->digits++;
1060
+ if ('0' <= c && c <= '9')
1061
+ bdr->digit = c - '0';
1062
+ else if ('a' <= c && c <= 'z')
1063
+ bdr->digit = c - 'a' + 10;
1064
+ else bdr->digit = c - 'A' + 10;
1065
+ bdr->digitMask = bdr->base >> 1;
1066
+ }
1067
+ bit = (bdr->digit & bdr->digitMask) != 0;
1068
+ bdr->digitMask >>= 1;
1069
+ return bit;
1070
+ }
1071
+
1072
+ JSBool
1073
+ js_strtointeger(JSContext *cx, const jschar *s, const jschar *send,
1074
+ const jschar **ep, jsint base, jsdouble *dp)
1075
+ {
1076
+ const jschar *s1, *start;
1077
+ JSBool negative;
1078
+ jsdouble value;
1079
+
1080
+ s1 = js_SkipWhiteSpace(s, send);
1081
+ if (s1 == send)
1082
+ goto no_digits;
1083
+ if ((negative = (*s1 == '-')) != 0 || *s1 == '+') {
1084
+ s1++;
1085
+ if (s1 == send)
1086
+ goto no_digits;
1087
+ }
1088
+
1089
+ if (base == 0) {
1090
+ /* No base supplied, or some base that evaluated to 0. */
1091
+ if (*s1 == '0') {
1092
+ /* It's either hex or octal; only increment char if str isn't '0' */
1093
+ if (s1 + 1 != send && (s1[1] == 'X' || s1[1] == 'x')) {
1094
+ base = 16;
1095
+ s1 += 2;
1096
+ if (s1 == send)
1097
+ goto no_digits;
1098
+ } else {
1099
+ base = 8;
1100
+ }
1101
+ } else {
1102
+ base = 10; /* Default to decimal. */
1103
+ }
1104
+ } else if (base == 16) {
1105
+ /* If base is 16, ignore hex prefix. */
1106
+ if (*s1 == '0' && s1 + 1 != send && (s1[1] == 'X' || s1[1] == 'x')) {
1107
+ s1 += 2;
1108
+ if (s1 == send)
1109
+ goto no_digits;
1110
+ }
1111
+ }
1112
+
1113
+ /*
1114
+ * Done with the preliminaries; find some prefix of the string that's
1115
+ * a number in the given base.
1116
+ */
1117
+ JS_ASSERT(s1 < send);
1118
+ start = s1;
1119
+ value = 0.0;
1120
+ do {
1121
+ uintN digit;
1122
+ jschar c = *s1;
1123
+ if ('0' <= c && c <= '9')
1124
+ digit = c - '0';
1125
+ else if ('a' <= c && c <= 'z')
1126
+ digit = c - 'a' + 10;
1127
+ else if ('A' <= c && c <= 'Z')
1128
+ digit = c - 'A' + 10;
1129
+ else
1130
+ break;
1131
+ if (digit >= (uintN)base)
1132
+ break;
1133
+ value = value * base + digit;
1134
+ } while (++s1 != send);
1135
+
1136
+ if (value >= 9007199254740992.0) {
1137
+ if (base == 10) {
1138
+ /*
1139
+ * If we're accumulating a decimal number and the number is >=
1140
+ * 2^53, then the result from the repeated multiply-add above may
1141
+ * be inaccurate. Call JS_strtod to get the correct answer.
1142
+ */
1143
+ size_t i;
1144
+ size_t length = s1 - start;
1145
+ char *cstr = (char *) JS_malloc(cx, length + 1);
1146
+ char *estr;
1147
+ int err=0;
1148
+
1149
+ if (!cstr)
1150
+ return JS_FALSE;
1151
+ for (i = 0; i != length; i++)
1152
+ cstr[i] = (char)start[i];
1153
+ cstr[length] = 0;
1154
+
1155
+ value = JS_strtod(cstr, &estr, &err);
1156
+ if (err == JS_DTOA_ENOMEM) {
1157
+ JS_ReportOutOfMemory(cx);
1158
+ JS_free(cx, cstr);
1159
+ return JS_FALSE;
1160
+ }
1161
+ if (err == JS_DTOA_ERANGE && value == HUGE_VAL)
1162
+ value = *cx->runtime->jsPositiveInfinity;
1163
+ JS_free(cx, cstr);
1164
+ } else if ((base & (base - 1)) == 0) {
1165
+ /*
1166
+ * The number may also be inaccurate for power-of-two bases. This
1167
+ * happens if the addition in value * base + digit causes a round-
1168
+ * down to an even least significant mantissa bit when the first
1169
+ * dropped bit is a one. If any of the following digits in the
1170
+ * number (which haven't been added in yet) are nonzero, then the
1171
+ * correct action would have been to round up instead of down. An
1172
+ * example occurs when reading the number 0x1000000000000081, which
1173
+ * rounds to 0x1000000000000000 instead of 0x1000000000000100.
1174
+ */
1175
+ struct BinaryDigitReader bdr;
1176
+ intN bit, bit2;
1177
+ intN j;
1178
+
1179
+ bdr.base = base;
1180
+ bdr.digitMask = 0;
1181
+ bdr.digits = start;
1182
+ bdr.end = s1;
1183
+ value = 0.0;
1184
+
1185
+ /* Skip leading zeros. */
1186
+ do {
1187
+ bit = GetNextBinaryDigit(&bdr);
1188
+ } while (bit == 0);
1189
+
1190
+ if (bit == 1) {
1191
+ /* Gather the 53 significant bits (including the leading 1) */
1192
+ value = 1.0;
1193
+ for (j = 52; j; j--) {
1194
+ bit = GetNextBinaryDigit(&bdr);
1195
+ if (bit < 0)
1196
+ goto done;
1197
+ value = value*2 + bit;
1198
+ }
1199
+ /* bit2 is the 54th bit (the first dropped from the mantissa) */
1200
+ bit2 = GetNextBinaryDigit(&bdr);
1201
+ if (bit2 >= 0) {
1202
+ jsdouble factor = 2.0;
1203
+ intN sticky = 0; /* sticky is 1 if any bit beyond the 54th is 1 */
1204
+ intN bit3;
1205
+
1206
+ while ((bit3 = GetNextBinaryDigit(&bdr)) >= 0) {
1207
+ sticky |= bit3;
1208
+ factor *= 2;
1209
+ }
1210
+ value += bit2 & (bit | sticky);
1211
+ value *= factor;
1212
+ }
1213
+ done:;
1214
+ }
1215
+ }
1216
+ }
1217
+ /* We don't worry about inaccurate numbers for any other base. */
1218
+
1219
+ if (s1 == start) {
1220
+ no_digits:
1221
+ *dp = 0.0;
1222
+ *ep = s;
1223
+ } else {
1224
+ *dp = negative ? -value : value;
1225
+ *ep = s1;
1226
+ }
1227
+ return JS_TRUE;
1228
+ }