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,2398 @@
1
+ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2
+ * vim: set ts=8 sw=4 et tw=78:
3
+ *
4
+ * ***** BEGIN LICENSE BLOCK *****
5
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6
+ *
7
+ * The contents of this file are subject to the Mozilla Public License Version
8
+ * 1.1 (the "License"); you may not use this file except in compliance with
9
+ * the License. You may obtain a copy of the License at
10
+ * http://www.mozilla.org/MPL/
11
+ *
12
+ * Software distributed under the License is distributed on an "AS IS" basis,
13
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14
+ * for the specific language governing rights and limitations under the
15
+ * License.
16
+ *
17
+ * The Original Code is Mozilla Communicator client code, released
18
+ * March 31, 1998.
19
+ *
20
+ * The Initial Developer of the Original Code is
21
+ * Netscape Communications Corporation.
22
+ * Portions created by the Initial Developer are Copyright (C) 1998
23
+ * the Initial Developer. All Rights Reserved.
24
+ *
25
+ * Contributor(s):
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 date methods.
43
+ */
44
+
45
+ /*
46
+ * "For example, OS/360 devotes 26 bytes of the permanently
47
+ * resident date-turnover routine to the proper handling of
48
+ * December 31 on leap years (when it is Day 366). That
49
+ * might have been left to the operator."
50
+ *
51
+ * Frederick Brooks, 'The Second-System Effect'.
52
+ */
53
+
54
+ #include "jsstddef.h"
55
+ #include <ctype.h>
56
+ #include <locale.h>
57
+ #include <math.h>
58
+ #include <stdlib.h>
59
+ #include <string.h>
60
+ #include "jstypes.h"
61
+ #include "jsprf.h"
62
+ #include "prmjtime.h"
63
+ #include "jsutil.h" /* Added by JSIFY */
64
+ #include "jsapi.h"
65
+ #include "jsconfig.h"
66
+ #include "jscntxt.h"
67
+ #include "jsdate.h"
68
+ #include "jsinterp.h"
69
+ #include "jsnum.h"
70
+ #include "jsobj.h"
71
+ #include "jsstr.h"
72
+
73
+ /*
74
+ * The JS 'Date' object is patterned after the Java 'Date' object.
75
+ * Here is an script:
76
+ *
77
+ * today = new Date();
78
+ *
79
+ * print(today.toLocaleString());
80
+ *
81
+ * weekDay = today.getDay();
82
+ *
83
+ *
84
+ * These Java (and ECMA-262) methods are supported:
85
+ *
86
+ * UTC
87
+ * getDate (getUTCDate)
88
+ * getDay (getUTCDay)
89
+ * getHours (getUTCHours)
90
+ * getMinutes (getUTCMinutes)
91
+ * getMonth (getUTCMonth)
92
+ * getSeconds (getUTCSeconds)
93
+ * getMilliseconds (getUTCMilliseconds)
94
+ * getTime
95
+ * getTimezoneOffset
96
+ * getYear
97
+ * getFullYear (getUTCFullYear)
98
+ * parse
99
+ * setDate (setUTCDate)
100
+ * setHours (setUTCHours)
101
+ * setMinutes (setUTCMinutes)
102
+ * setMonth (setUTCMonth)
103
+ * setSeconds (setUTCSeconds)
104
+ * setMilliseconds (setUTCMilliseconds)
105
+ * setTime
106
+ * setYear (setFullYear, setUTCFullYear)
107
+ * toGMTString (toUTCString)
108
+ * toLocaleString
109
+ * toString
110
+ *
111
+ *
112
+ * These Java methods are not supported
113
+ *
114
+ * setDay
115
+ * before
116
+ * after
117
+ * equals
118
+ * hashCode
119
+ */
120
+
121
+ /*
122
+ * 11/97 - jsdate.c has been rewritten to conform to the ECMA-262 language
123
+ * definition and reduce dependence on NSPR. NSPR is used to get the current
124
+ * time in milliseconds, the time zone offset, and the daylight savings time
125
+ * offset for a given time. NSPR is also used for Date.toLocaleString(), for
126
+ * locale-specific formatting, and to get a string representing the timezone.
127
+ * (Which turns out to be platform-dependent.)
128
+ *
129
+ * To do:
130
+ * (I did some performance tests by timing how long it took to run what
131
+ * I had of the js ECMA conformance tests.)
132
+ *
133
+ * - look at saving results across multiple calls to supporting
134
+ * functions; the toString functions compute some of the same values
135
+ * multiple times. Although - I took a quick stab at this, and I lost
136
+ * rather than gained. (Fractionally.) Hard to tell what compilers/processors
137
+ * are doing these days.
138
+ *
139
+ * - look at tweaking function return types to return double instead
140
+ * of int; this seems to make things run slightly faster sometimes.
141
+ * (though it could be architecture-dependent.) It'd be good to see
142
+ * how this does on win32. (Tried it on irix.) Types could use a
143
+ * general going-over.
144
+ */
145
+
146
+ /*
147
+ * Supporting functions - ECMA 15.9.1.*
148
+ */
149
+
150
+ #define HalfTimeDomain 8.64e15
151
+ #define HoursPerDay 24.0
152
+ #define MinutesPerDay (HoursPerDay * MinutesPerHour)
153
+ #define MinutesPerHour 60.0
154
+ #define SecondsPerDay (MinutesPerDay * SecondsPerMinute)
155
+ #define SecondsPerHour (MinutesPerHour * SecondsPerMinute)
156
+ #define SecondsPerMinute 60.0
157
+
158
+ #if defined(XP_WIN) || defined(XP_OS2)
159
+ /* Work around msvc double optimization bug by making these runtime values; if
160
+ * they're available at compile time, msvc optimizes division by them by
161
+ * computing the reciprocal and multiplying instead of dividing - this loses
162
+ * when the reciprocal isn't representable in a double.
163
+ */
164
+ static jsdouble msPerSecond = 1000.0;
165
+ static jsdouble msPerDay = SecondsPerDay * 1000.0;
166
+ static jsdouble msPerHour = SecondsPerHour * 1000.0;
167
+ static jsdouble msPerMinute = SecondsPerMinute * 1000.0;
168
+ #else
169
+ #define msPerDay (SecondsPerDay * msPerSecond)
170
+ #define msPerHour (SecondsPerHour * msPerSecond)
171
+ #define msPerMinute (SecondsPerMinute * msPerSecond)
172
+ #define msPerSecond 1000.0
173
+ #endif
174
+
175
+ #define Day(t) floor((t) / msPerDay)
176
+
177
+ static jsdouble
178
+ TimeWithinDay(jsdouble t)
179
+ {
180
+ jsdouble result;
181
+ result = fmod(t, msPerDay);
182
+ if (result < 0)
183
+ result += msPerDay;
184
+ return result;
185
+ }
186
+
187
+ #define DaysInYear(y) ((y) % 4 == 0 && ((y) % 100 || ((y) % 400 == 0)) \
188
+ ? 366 : 365)
189
+
190
+ /* math here has to be f.p, because we need
191
+ * floor((1968 - 1969) / 4) == -1
192
+ */
193
+ #define DayFromYear(y) (365 * ((y)-1970) + floor(((y)-1969)/4.0) \
194
+ - floor(((y)-1901)/100.0) + floor(((y)-1601)/400.0))
195
+ #define TimeFromYear(y) (DayFromYear(y) * msPerDay)
196
+
197
+ static jsint
198
+ YearFromTime(jsdouble t)
199
+ {
200
+ jsint y = (jsint) floor(t /(msPerDay*365.2425)) + 1970;
201
+ jsdouble t2 = (jsdouble) TimeFromYear(y);
202
+
203
+ if (t2 > t) {
204
+ y--;
205
+ } else {
206
+ if (t2 + msPerDay * DaysInYear(y) <= t)
207
+ y++;
208
+ }
209
+ return y;
210
+ }
211
+
212
+ #define InLeapYear(t) (JSBool) (DaysInYear(YearFromTime(t)) == 366)
213
+
214
+ #define DayWithinYear(t, year) ((intN) (Day(t) - DayFromYear(year)))
215
+
216
+ /*
217
+ * The following array contains the day of year for the first day of
218
+ * each month, where index 0 is January, and day 0 is January 1.
219
+ */
220
+ static jsdouble firstDayOfMonth[2][12] = {
221
+ {0.0, 31.0, 59.0, 90.0, 120.0, 151.0, 181.0, 212.0, 243.0, 273.0, 304.0, 334.0},
222
+ {0.0, 31.0, 60.0, 91.0, 121.0, 152.0, 182.0, 213.0, 244.0, 274.0, 305.0, 335.0}
223
+ };
224
+
225
+ #define DayFromMonth(m, leap) firstDayOfMonth[leap][(intN)m];
226
+
227
+ static intN
228
+ MonthFromTime(jsdouble t)
229
+ {
230
+ intN d, step;
231
+ jsint year = YearFromTime(t);
232
+ d = DayWithinYear(t, year);
233
+
234
+ if (d < (step = 31))
235
+ return 0;
236
+ step += (InLeapYear(t) ? 29 : 28);
237
+ if (d < step)
238
+ return 1;
239
+ if (d < (step += 31))
240
+ return 2;
241
+ if (d < (step += 30))
242
+ return 3;
243
+ if (d < (step += 31))
244
+ return 4;
245
+ if (d < (step += 30))
246
+ return 5;
247
+ if (d < (step += 31))
248
+ return 6;
249
+ if (d < (step += 31))
250
+ return 7;
251
+ if (d < (step += 30))
252
+ return 8;
253
+ if (d < (step += 31))
254
+ return 9;
255
+ if (d < (step += 30))
256
+ return 10;
257
+ return 11;
258
+ }
259
+
260
+ static intN
261
+ DateFromTime(jsdouble t)
262
+ {
263
+ intN d, step, next;
264
+ jsint year = YearFromTime(t);
265
+ d = DayWithinYear(t, year);
266
+
267
+ if (d <= (next = 30))
268
+ return d + 1;
269
+ step = next;
270
+ next += (InLeapYear(t) ? 29 : 28);
271
+ if (d <= next)
272
+ return d - step;
273
+ step = next;
274
+ if (d <= (next += 31))
275
+ return d - step;
276
+ step = next;
277
+ if (d <= (next += 30))
278
+ return d - step;
279
+ step = next;
280
+ if (d <= (next += 31))
281
+ return d - step;
282
+ step = next;
283
+ if (d <= (next += 30))
284
+ return d - step;
285
+ step = next;
286
+ if (d <= (next += 31))
287
+ return d - step;
288
+ step = next;
289
+ if (d <= (next += 31))
290
+ return d - step;
291
+ step = next;
292
+ if (d <= (next += 30))
293
+ return d - step;
294
+ step = next;
295
+ if (d <= (next += 31))
296
+ return d - step;
297
+ step = next;
298
+ if (d <= (next += 30))
299
+ return d - step;
300
+ step = next;
301
+ return d - step;
302
+ }
303
+
304
+ static intN
305
+ WeekDay(jsdouble t)
306
+ {
307
+ jsint result;
308
+ result = (jsint) Day(t) + 4;
309
+ result = result % 7;
310
+ if (result < 0)
311
+ result += 7;
312
+ return (intN) result;
313
+ }
314
+
315
+ #define MakeTime(hour, min, sec, ms) \
316
+ ((((hour) * MinutesPerHour + (min)) * SecondsPerMinute + (sec)) * msPerSecond + (ms))
317
+
318
+ static jsdouble
319
+ MakeDay(jsdouble year, jsdouble month, jsdouble date)
320
+ {
321
+ JSBool leap;
322
+ jsdouble yearday;
323
+ jsdouble monthday;
324
+
325
+ year += floor(month / 12);
326
+
327
+ month = fmod(month, 12.0);
328
+ if (month < 0)
329
+ month += 12;
330
+
331
+ leap = (DaysInYear((jsint) year) == 366);
332
+
333
+ yearday = floor(TimeFromYear(year) / msPerDay);
334
+ monthday = DayFromMonth(month, leap);
335
+
336
+ return yearday + monthday + date - 1;
337
+ }
338
+
339
+ #define MakeDate(day, time) ((day) * msPerDay + (time))
340
+
341
+ /*
342
+ * Years and leap years on which Jan 1 is a Sunday, Monday, etc.
343
+ *
344
+ * yearStartingWith[0][i] is an example non-leap year where
345
+ * Jan 1 appears on Sunday (i == 0), Monday (i == 1), etc.
346
+ *
347
+ * yearStartingWith[1][i] is an example leap year where
348
+ * Jan 1 appears on Sunday (i == 0), Monday (i == 1), etc.
349
+ */
350
+ static jsint yearStartingWith[2][7] = {
351
+ {1978, 1973, 1974, 1975, 1981, 1971, 1977},
352
+ {1984, 1996, 1980, 1992, 1976, 1988, 1972}
353
+ };
354
+
355
+ /*
356
+ * Find a year for which any given date will fall on the same weekday.
357
+ *
358
+ * This function should be used with caution when used other than
359
+ * for determining DST; it hasn't been proven not to produce an
360
+ * incorrect year for times near year boundaries.
361
+ */
362
+ static jsint
363
+ EquivalentYearForDST(jsint year)
364
+ {
365
+ jsint day;
366
+ JSBool isLeapYear;
367
+
368
+ day = (jsint) DayFromYear(year) + 4;
369
+ day = day % 7;
370
+ if (day < 0)
371
+ day += 7;
372
+
373
+ isLeapYear = (DaysInYear(year) == 366);
374
+
375
+ return yearStartingWith[isLeapYear][day];
376
+ }
377
+
378
+ /* LocalTZA gets set by js_InitDateClass() */
379
+ static jsdouble LocalTZA;
380
+
381
+ static jsdouble
382
+ DaylightSavingTA(jsdouble t)
383
+ {
384
+ volatile int64 PR_t;
385
+ int64 ms2us;
386
+ int64 offset;
387
+ jsdouble result;
388
+
389
+ /* abort if NaN */
390
+ if (JSDOUBLE_IS_NaN(t))
391
+ return t;
392
+
393
+ /*
394
+ * If earlier than 1970 or after 2038, potentially beyond the ken of
395
+ * many OSes, map it to an equivalent year before asking.
396
+ */
397
+ if (t < 0.0 || t > 2145916800000.0) {
398
+ jsint year;
399
+ jsdouble day;
400
+
401
+ year = EquivalentYearForDST(YearFromTime(t));
402
+ day = MakeDay(year, MonthFromTime(t), DateFromTime(t));
403
+ t = MakeDate(day, TimeWithinDay(t));
404
+ }
405
+
406
+ /* put our t in an LL, and map it to usec for prtime */
407
+ JSLL_D2L(PR_t, t);
408
+ JSLL_I2L(ms2us, PRMJ_USEC_PER_MSEC);
409
+ JSLL_MUL(PR_t, PR_t, ms2us);
410
+
411
+ offset = PRMJ_DSTOffset(PR_t);
412
+
413
+ JSLL_DIV(offset, offset, ms2us);
414
+ JSLL_L2D(result, offset);
415
+ return result;
416
+ }
417
+
418
+
419
+ #define AdjustTime(t) fmod(LocalTZA + DaylightSavingTA(t), msPerDay)
420
+
421
+ #define LocalTime(t) ((t) + AdjustTime(t))
422
+
423
+ static jsdouble
424
+ UTC(jsdouble t)
425
+ {
426
+ return t - AdjustTime(t - LocalTZA);
427
+ }
428
+
429
+ static intN
430
+ HourFromTime(jsdouble t)
431
+ {
432
+ intN result = (intN) fmod(floor(t/msPerHour), HoursPerDay);
433
+ if (result < 0)
434
+ result += (intN)HoursPerDay;
435
+ return result;
436
+ }
437
+
438
+ static intN
439
+ MinFromTime(jsdouble t)
440
+ {
441
+ intN result = (intN) fmod(floor(t / msPerMinute), MinutesPerHour);
442
+ if (result < 0)
443
+ result += (intN)MinutesPerHour;
444
+ return result;
445
+ }
446
+
447
+ static intN
448
+ SecFromTime(jsdouble t)
449
+ {
450
+ intN result = (intN) fmod(floor(t / msPerSecond), SecondsPerMinute);
451
+ if (result < 0)
452
+ result += (intN)SecondsPerMinute;
453
+ return result;
454
+ }
455
+
456
+ static intN
457
+ msFromTime(jsdouble t)
458
+ {
459
+ intN result = (intN) fmod(t, msPerSecond);
460
+ if (result < 0)
461
+ result += (intN)msPerSecond;
462
+ return result;
463
+ }
464
+
465
+ #define TIMECLIP(d) ((JSDOUBLE_IS_FINITE(d) \
466
+ && !((d < 0 ? -d : d) > HalfTimeDomain)) \
467
+ ? js_DoubleToInteger(d + (+0.)) : *cx->runtime->jsNaN)
468
+
469
+ /**
470
+ * end of ECMA 'support' functions
471
+ */
472
+
473
+ /*
474
+ * Other Support routines and definitions
475
+ */
476
+
477
+ /*
478
+ * We use the first reseved slot to store UTC time, and the second for caching
479
+ * the local time. The initial value of the cache entry is NaN.
480
+ */
481
+ #define UTC_TIME_SLOT 0
482
+ #define LOCAL_TIME_SLOT 1
483
+
484
+ JSClass js_DateClass = {
485
+ js_Date_str,
486
+ JSCLASS_HAS_RESERVED_SLOTS(2) | JSCLASS_HAS_CACHED_PROTO(JSProto_Date),
487
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
488
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
489
+ JSCLASS_NO_OPTIONAL_MEMBERS
490
+ };
491
+
492
+ /* for use by date_parse */
493
+
494
+ static const char* wtb[] = {
495
+ "am", "pm",
496
+ "monday", "tuesday", "wednesday", "thursday", "friday",
497
+ "saturday", "sunday",
498
+ "january", "february", "march", "april", "may", "june",
499
+ "july", "august", "september", "october", "november", "december",
500
+ "gmt", "ut", "utc",
501
+ "est", "edt",
502
+ "cst", "cdt",
503
+ "mst", "mdt",
504
+ "pst", "pdt"
505
+ /* time zone table needs to be expanded */
506
+ };
507
+
508
+ static int ttb[] = {
509
+ -1, -2, 0, 0, 0, 0, 0, 0, 0, /* AM/PM */
510
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
511
+ 10000 + 0, 10000 + 0, 10000 + 0, /* GMT/UT/UTC */
512
+ 10000 + 5 * 60, 10000 + 4 * 60, /* EST/EDT */
513
+ 10000 + 6 * 60, 10000 + 5 * 60, /* CST/CDT */
514
+ 10000 + 7 * 60, 10000 + 6 * 60, /* MST/MDT */
515
+ 10000 + 8 * 60, 10000 + 7 * 60 /* PST/PDT */
516
+ };
517
+
518
+ /* helper for date_parse */
519
+ static JSBool
520
+ date_regionMatches(const char* s1, int s1off, const jschar* s2, int s2off,
521
+ int count, int ignoreCase)
522
+ {
523
+ JSBool result = JS_FALSE;
524
+ /* return true if matches, otherwise, false */
525
+
526
+ while (count > 0 && s1[s1off] && s2[s2off]) {
527
+ if (ignoreCase) {
528
+ if (JS_TOLOWER((jschar)s1[s1off]) != JS_TOLOWER(s2[s2off])) {
529
+ break;
530
+ }
531
+ } else {
532
+ if ((jschar)s1[s1off] != s2[s2off]) {
533
+ break;
534
+ }
535
+ }
536
+ s1off++;
537
+ s2off++;
538
+ count--;
539
+ }
540
+
541
+ if (count == 0) {
542
+ result = JS_TRUE;
543
+ }
544
+
545
+ return result;
546
+ }
547
+
548
+ /* find UTC time from given date... no 1900 correction! */
549
+ static jsdouble
550
+ date_msecFromDate(jsdouble year, jsdouble mon, jsdouble mday, jsdouble hour,
551
+ jsdouble min, jsdouble sec, jsdouble msec)
552
+ {
553
+ jsdouble day;
554
+ jsdouble msec_time;
555
+ jsdouble result;
556
+
557
+ day = MakeDay(year, mon, mday);
558
+ msec_time = MakeTime(hour, min, sec, msec);
559
+ result = MakeDate(day, msec_time);
560
+ return result;
561
+ }
562
+
563
+ /* compute the time in msec (unclipped) from the given args */
564
+ #define MAXARGS 7
565
+
566
+ static JSBool
567
+ date_msecFromArgs(JSContext *cx, uintN argc, jsval *argv, jsdouble *rval)
568
+ {
569
+ uintN loop;
570
+ jsdouble array[MAXARGS];
571
+ jsdouble d;
572
+ jsdouble msec_time;
573
+
574
+ for (loop = 0; loop < MAXARGS; loop++) {
575
+ if (loop < argc) {
576
+ d = js_ValueToNumber(cx, &argv[loop]);
577
+ if (JSVAL_IS_NULL(argv[loop]))
578
+ return JS_FALSE;
579
+ /* return NaN if any arg is not finite */
580
+ if (!JSDOUBLE_IS_FINITE(d)) {
581
+ *rval = *cx->runtime->jsNaN;
582
+ return JS_TRUE;
583
+ }
584
+ array[loop] = js_DoubleToInteger(d);
585
+ } else {
586
+ if (loop == 2) {
587
+ array[loop] = 1; /* Default the date argument to 1. */
588
+ } else {
589
+ array[loop] = 0;
590
+ }
591
+ }
592
+ }
593
+
594
+ /* adjust 2-digit years into the 20th century */
595
+ if (array[0] >= 0 && array[0] <= 99)
596
+ array[0] += 1900;
597
+
598
+ msec_time = date_msecFromDate(array[0], array[1], array[2],
599
+ array[3], array[4], array[5], array[6]);
600
+ *rval = msec_time;
601
+ return JS_TRUE;
602
+ }
603
+
604
+
605
+ /*
606
+ * See ECMA 15.9.4.[3-10];
607
+ */
608
+ static JSBool
609
+ date_UTC(JSContext *cx, uintN argc, jsval *vp)
610
+ {
611
+ jsdouble msec_time;
612
+
613
+ if (!date_msecFromArgs(cx, argc, vp + 2, &msec_time))
614
+ return JS_FALSE;
615
+
616
+ msec_time = TIMECLIP(msec_time);
617
+
618
+ return js_NewNumberInRootedValue(cx, msec_time, vp);
619
+ }
620
+
621
+ static JSBool
622
+ date_parseString(JSString *str, jsdouble *result)
623
+ {
624
+ jsdouble msec;
625
+
626
+ const jschar *s;
627
+ size_t limit;
628
+ size_t i = 0;
629
+ int year = -1;
630
+ int mon = -1;
631
+ int mday = -1;
632
+ int hour = -1;
633
+ int min = -1;
634
+ int sec = -1;
635
+ int c = -1;
636
+ int n = -1;
637
+ int tzoffset = -1;
638
+ int prevc = 0;
639
+ JSBool seenplusminus = JS_FALSE;
640
+ int temp;
641
+ JSBool seenmonthname = JS_FALSE;
642
+
643
+ JSSTRING_CHARS_AND_LENGTH(str, s, limit);
644
+ if (limit == 0)
645
+ goto syntax;
646
+ while (i < limit) {
647
+ c = s[i];
648
+ i++;
649
+ if (c <= ' ' || c == ',' || c == '-') {
650
+ if (c == '-' && '0' <= s[i] && s[i] <= '9') {
651
+ prevc = c;
652
+ }
653
+ continue;
654
+ }
655
+ if (c == '(') { /* comments) */
656
+ int depth = 1;
657
+ while (i < limit) {
658
+ c = s[i];
659
+ i++;
660
+ if (c == '(') depth++;
661
+ else if (c == ')')
662
+ if (--depth <= 0)
663
+ break;
664
+ }
665
+ continue;
666
+ }
667
+ if ('0' <= c && c <= '9') {
668
+ n = c - '0';
669
+ while (i < limit && '0' <= (c = s[i]) && c <= '9') {
670
+ n = n * 10 + c - '0';
671
+ i++;
672
+ }
673
+
674
+ /* allow TZA before the year, so
675
+ * 'Wed Nov 05 21:49:11 GMT-0800 1997'
676
+ * works */
677
+
678
+ /* uses of seenplusminus allow : in TZA, so Java
679
+ * no-timezone style of GMT+4:30 works
680
+ */
681
+
682
+ if ((prevc == '+' || prevc == '-')/* && year>=0 */) {
683
+ /* make ':' case below change tzoffset */
684
+ seenplusminus = JS_TRUE;
685
+
686
+ /* offset */
687
+ if (n < 24)
688
+ n = n * 60; /* EG. "GMT-3" */
689
+ else
690
+ n = n % 100 + n / 100 * 60; /* eg "GMT-0430" */
691
+ if (prevc == '+') /* plus means east of GMT */
692
+ n = -n;
693
+ if (tzoffset != 0 && tzoffset != -1)
694
+ goto syntax;
695
+ tzoffset = n;
696
+ } else if (prevc == '/' && mon >= 0 && mday >= 0 && year < 0) {
697
+ if (c <= ' ' || c == ',' || c == '/' || i >= limit)
698
+ year = n;
699
+ else
700
+ goto syntax;
701
+ } else if (c == ':') {
702
+ if (hour < 0)
703
+ hour = /*byte*/ n;
704
+ else if (min < 0)
705
+ min = /*byte*/ n;
706
+ else
707
+ goto syntax;
708
+ } else if (c == '/') {
709
+ /* until it is determined that mon is the actual
710
+ month, keep it as 1-based rather than 0-based */
711
+ if (mon < 0)
712
+ mon = /*byte*/ n;
713
+ else if (mday < 0)
714
+ mday = /*byte*/ n;
715
+ else
716
+ goto syntax;
717
+ } else if (i < limit && c != ',' && c > ' ' && c != '-' && c != '(') {
718
+ goto syntax;
719
+ } else if (seenplusminus && n < 60) { /* handle GMT-3:30 */
720
+ if (tzoffset < 0)
721
+ tzoffset -= n;
722
+ else
723
+ tzoffset += n;
724
+ } else if (hour >= 0 && min < 0) {
725
+ min = /*byte*/ n;
726
+ } else if (prevc == ':' && min >= 0 && sec < 0) {
727
+ sec = /*byte*/ n;
728
+ } else if (mon < 0) {
729
+ mon = /*byte*/n;
730
+ } else if (mon >= 0 && mday < 0) {
731
+ mday = /*byte*/ n;
732
+ } else if (mon >= 0 && mday >= 0 && year < 0) {
733
+ year = n;
734
+ } else {
735
+ goto syntax;
736
+ }
737
+ prevc = 0;
738
+ } else if (c == '/' || c == ':' || c == '+' || c == '-') {
739
+ prevc = c;
740
+ } else {
741
+ size_t st = i - 1;
742
+ int k;
743
+ while (i < limit) {
744
+ c = s[i];
745
+ if (!(('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z')))
746
+ break;
747
+ i++;
748
+ }
749
+ if (i <= st + 1)
750
+ goto syntax;
751
+ for (k = JS_ARRAY_LENGTH(wtb); --k >= 0;)
752
+ if (date_regionMatches(wtb[k], 0, s, st, i-st, 1)) {
753
+ int action = ttb[k];
754
+ if (action != 0) {
755
+ if (action < 0) {
756
+ /*
757
+ * AM/PM. Count 12:30 AM as 00:30, 12:30 PM as
758
+ * 12:30, instead of blindly adding 12 if PM.
759
+ */
760
+ JS_ASSERT(action == -1 || action == -2);
761
+ if (hour > 12 || hour < 0) {
762
+ goto syntax;
763
+ } else {
764
+ if (action == -1 && hour == 12) { /* am */
765
+ hour = 0;
766
+ } else if (action == -2 && hour != 12) { /* pm */
767
+ hour += 12;
768
+ }
769
+ }
770
+ } else if (action <= 13) { /* month! */
771
+ /* Adjust mon to be 1-based until the final values
772
+ for mon, mday and year are adjusted below */
773
+ if (seenmonthname) {
774
+ goto syntax;
775
+ }
776
+ seenmonthname = JS_TRUE;
777
+ temp = /*byte*/ (action - 2) + 1;
778
+
779
+ if (mon < 0) {
780
+ mon = temp;
781
+ } else if (mday < 0) {
782
+ mday = mon;
783
+ mon = temp;
784
+ } else if (year < 0) {
785
+ year = mon;
786
+ mon = temp;
787
+ } else {
788
+ goto syntax;
789
+ }
790
+ } else {
791
+ tzoffset = action - 10000;
792
+ }
793
+ }
794
+ break;
795
+ }
796
+ if (k < 0)
797
+ goto syntax;
798
+ prevc = 0;
799
+ }
800
+ }
801
+ if (year < 0 || mon < 0 || mday < 0)
802
+ goto syntax;
803
+ /*
804
+ Case 1. The input string contains an English month name.
805
+ The form of the string can be month f l, or f month l, or
806
+ f l month which each evaluate to the same date.
807
+ If f and l are both greater than or equal to 70, or
808
+ both less than 70, the date is invalid.
809
+ The year is taken to be the greater of the values f, l.
810
+ If the year is greater than or equal to 70 and less than 100,
811
+ it is considered to be the number of years after 1900.
812
+ Case 2. The input string is of the form "f/m/l" where f, m and l are
813
+ integers, e.g. 7/16/45.
814
+ Adjust the mon, mday and year values to achieve 100% MSIE
815
+ compatibility.
816
+ a. If 0 <= f < 70, f/m/l is interpreted as month/day/year.
817
+ i. If year < 100, it is the number of years after 1900
818
+ ii. If year >= 100, it is the number of years after 0.
819
+ b. If 70 <= f < 100
820
+ i. If m < 70, f/m/l is interpreted as
821
+ year/month/day where year is the number of years after
822
+ 1900.
823
+ ii. If m >= 70, the date is invalid.
824
+ c. If f >= 100
825
+ i. If m < 70, f/m/l is interpreted as
826
+ year/month/day where year is the number of years after 0.
827
+ ii. If m >= 70, the date is invalid.
828
+ */
829
+ if (seenmonthname) {
830
+ if ((mday >= 70 && year >= 70) || (mday < 70 && year < 70)) {
831
+ goto syntax;
832
+ }
833
+ if (mday > year) {
834
+ temp = year;
835
+ year = mday;
836
+ mday = temp;
837
+ }
838
+ if (year >= 70 && year < 100) {
839
+ year += 1900;
840
+ }
841
+ } else if (mon < 70) { /* (a) month/day/year */
842
+ if (year < 100) {
843
+ year += 1900;
844
+ }
845
+ } else if (mon < 100) { /* (b) year/month/day */
846
+ if (mday < 70) {
847
+ temp = year;
848
+ year = mon + 1900;
849
+ mon = mday;
850
+ mday = temp;
851
+ } else {
852
+ goto syntax;
853
+ }
854
+ } else { /* (c) year/month/day */
855
+ if (mday < 70) {
856
+ temp = year;
857
+ year = mon;
858
+ mon = mday;
859
+ mday = temp;
860
+ } else {
861
+ goto syntax;
862
+ }
863
+ }
864
+ mon -= 1; /* convert month to 0-based */
865
+ if (sec < 0)
866
+ sec = 0;
867
+ if (min < 0)
868
+ min = 0;
869
+ if (hour < 0)
870
+ hour = 0;
871
+ if (tzoffset == -1) { /* no time zone specified, have to use local */
872
+ jsdouble msec_time;
873
+ msec_time = date_msecFromDate(year, mon, mday, hour, min, sec, 0);
874
+
875
+ *result = UTC(msec_time);
876
+ return JS_TRUE;
877
+ }
878
+
879
+ msec = date_msecFromDate(year, mon, mday, hour, min, sec, 0);
880
+ msec += tzoffset * msPerMinute;
881
+ *result = msec;
882
+ return JS_TRUE;
883
+
884
+ syntax:
885
+ /* syntax error */
886
+ *result = 0;
887
+ return JS_FALSE;
888
+ }
889
+
890
+ static JSBool
891
+ date_parse(JSContext *cx, uintN argc, jsval *vp)
892
+ {
893
+ JSString *str;
894
+ jsdouble result;
895
+
896
+ str = js_ValueToString(cx, vp[2]);
897
+ if (!str)
898
+ return JS_FALSE;
899
+ if (!date_parseString(str, &result)) {
900
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
901
+ return JS_TRUE;
902
+ }
903
+
904
+ result = TIMECLIP(result);
905
+ return js_NewNumberInRootedValue(cx, result, vp);
906
+ }
907
+
908
+ static JSBool
909
+ date_now(JSContext *cx, uintN argc, jsval *vp)
910
+ {
911
+ int64 us, ms, us2ms;
912
+ jsdouble msec_time;
913
+
914
+ us = PRMJ_Now();
915
+ JSLL_UI2L(us2ms, PRMJ_USEC_PER_MSEC);
916
+ JSLL_DIV(ms, us, us2ms);
917
+ JSLL_L2D(msec_time, ms);
918
+
919
+ return js_NewDoubleInRootedValue(cx, msec_time, vp);
920
+ }
921
+
922
+ /*
923
+ * Get UTC time from the date object. Returns false if the object is not
924
+ * Date type.
925
+ */
926
+ static JSBool
927
+ GetUTCTime(JSContext *cx, JSObject *obj, jsval *vp, jsdouble *dp)
928
+ {
929
+ jsval v;
930
+
931
+ if (vp && !JS_InstanceOf(cx, obj, &js_DateClass, vp + 2))
932
+ return JS_FALSE;
933
+ if (!JS_GetReservedSlot(cx, obj, UTC_TIME_SLOT, &v))
934
+ return JS_FALSE;
935
+
936
+ *dp = *JSVAL_TO_DOUBLE(v);
937
+ return JS_TRUE;
938
+ }
939
+
940
+ /*
941
+ * Set UTC time slot with a pointer pointing to a jsdouble. This function is
942
+ * used only for setting UTC time to some predefined values, such as NaN.
943
+ *
944
+ * It also invalidates cached local time.
945
+ */
946
+ static JSBool
947
+ SetUTCTimePtr(JSContext *cx, JSObject *obj, jsval *vp, jsdouble *dp)
948
+ {
949
+ if (vp && !JS_InstanceOf(cx, obj, &js_DateClass, vp + 2))
950
+ return JS_FALSE;
951
+
952
+ /* Invalidate local time cache. */
953
+ if (!JS_SetReservedSlot(cx, obj, LOCAL_TIME_SLOT,
954
+ DOUBLE_TO_JSVAL(cx->runtime->jsNaN))) {
955
+ return JS_FALSE;
956
+ }
957
+
958
+ return JS_SetReservedSlot(cx, obj, UTC_TIME_SLOT, DOUBLE_TO_JSVAL(dp));
959
+ }
960
+
961
+ /*
962
+ * Set UTC time to a given time.
963
+ */
964
+ static JSBool
965
+ SetUTCTime(JSContext *cx, JSObject *obj, jsval *vp, jsdouble t)
966
+ {
967
+ jsdouble *dp = js_NewWeaklyRootedDouble(cx, t);
968
+ if (!dp)
969
+ return JS_FALSE;
970
+ return SetUTCTimePtr(cx, obj, vp, dp);
971
+ }
972
+
973
+ /*
974
+ * Get the local time, cache it if necessary. If UTC time is not finite
975
+ * (e.g., NaN), the local time slot is set to the UTC time without conversion.
976
+ */
977
+ static JSBool
978
+ GetAndCacheLocalTime(JSContext *cx, JSObject *obj, jsval *vp, jsdouble *dp)
979
+ {
980
+ jsval v;
981
+ jsdouble result;
982
+ jsdouble *cached;
983
+
984
+ if (!obj || !JS_GetReservedSlot(cx, obj, LOCAL_TIME_SLOT, &v))
985
+ return JS_FALSE;
986
+
987
+ result = *JSVAL_TO_DOUBLE(v);
988
+
989
+ if (JSDOUBLE_IS_NaN(result)) {
990
+ if (!GetUTCTime(cx, obj, vp, &result))
991
+ return JS_FALSE;
992
+
993
+ /* if result is NaN, it couldn't be finite. */
994
+ if (JSDOUBLE_IS_FINITE(result))
995
+ result = LocalTime(result);
996
+
997
+ cached = js_NewWeaklyRootedDouble(cx, result);
998
+ if (!cached)
999
+ return JS_FALSE;
1000
+
1001
+ if (!JS_SetReservedSlot(cx, obj, LOCAL_TIME_SLOT,
1002
+ DOUBLE_TO_JSVAL(cached))) {
1003
+ return JS_FALSE;
1004
+ }
1005
+ }
1006
+
1007
+ *dp = result;
1008
+ return JS_TRUE;
1009
+ }
1010
+
1011
+ /*
1012
+ * See ECMA 15.9.5.4 thru 15.9.5.23
1013
+ */
1014
+ static JSBool
1015
+ date_getTime(JSContext *cx, uintN argc, jsval *vp)
1016
+ {
1017
+ jsdouble result;
1018
+
1019
+ return GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result) &&
1020
+ js_NewNumberInRootedValue(cx, result, vp);
1021
+ }
1022
+
1023
+ static JSBool
1024
+ GetYear(JSContext *cx, JSBool fullyear, jsval *vp)
1025
+ {
1026
+ jsdouble result;
1027
+
1028
+ if (!GetAndCacheLocalTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
1029
+ return JS_FALSE;
1030
+
1031
+ if (JSDOUBLE_IS_FINITE(result)) {
1032
+ result = YearFromTime(result);
1033
+
1034
+ /* Follow ECMA-262 to the letter, contrary to IE JScript. */
1035
+ if (!fullyear)
1036
+ result -= 1900;
1037
+ }
1038
+
1039
+ return js_NewNumberInRootedValue(cx, result, vp);
1040
+ }
1041
+
1042
+ static JSBool
1043
+ date_getYear(JSContext *cx, uintN argc, jsval *vp)
1044
+ {
1045
+ return GetYear(cx, JS_FALSE, vp);
1046
+ }
1047
+
1048
+ static JSBool
1049
+ date_getFullYear(JSContext *cx, uintN argc, jsval *vp)
1050
+ {
1051
+ return GetYear(cx, JS_TRUE, vp);
1052
+ }
1053
+
1054
+ static JSBool
1055
+ date_getUTCFullYear(JSContext *cx, uintN argc, jsval *vp)
1056
+ {
1057
+ jsdouble result;
1058
+
1059
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
1060
+ return JS_FALSE;
1061
+
1062
+ if (JSDOUBLE_IS_FINITE(result))
1063
+ result = YearFromTime(result);
1064
+
1065
+ return js_NewNumberInRootedValue(cx, result, vp);
1066
+ }
1067
+
1068
+ static JSBool
1069
+ date_getMonth(JSContext *cx, uintN argc, jsval *vp)
1070
+ {
1071
+ jsdouble result;
1072
+
1073
+ if (!GetAndCacheLocalTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
1074
+ return JS_FALSE;
1075
+
1076
+ if (JSDOUBLE_IS_FINITE(result))
1077
+ result = MonthFromTime(result);
1078
+
1079
+ return js_NewNumberInRootedValue(cx, result, vp);
1080
+ }
1081
+
1082
+ static JSBool
1083
+ date_getUTCMonth(JSContext *cx, uintN argc, jsval *vp)
1084
+ {
1085
+ jsdouble result;
1086
+
1087
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
1088
+ return JS_FALSE;
1089
+
1090
+ if (JSDOUBLE_IS_FINITE(result))
1091
+ result = MonthFromTime(result);
1092
+
1093
+ return js_NewNumberInRootedValue(cx, result, vp);
1094
+ }
1095
+
1096
+ static JSBool
1097
+ date_getDate(JSContext *cx, uintN argc, jsval *vp)
1098
+ {
1099
+ jsdouble result;
1100
+
1101
+ if (!GetAndCacheLocalTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
1102
+ return JS_FALSE;
1103
+
1104
+ if (JSDOUBLE_IS_FINITE(result))
1105
+ result = DateFromTime(result);
1106
+
1107
+ return js_NewNumberInRootedValue(cx, result, vp);
1108
+ }
1109
+
1110
+ static JSBool
1111
+ date_getUTCDate(JSContext *cx, uintN argc, jsval *vp)
1112
+ {
1113
+ jsdouble result;
1114
+
1115
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
1116
+ return JS_FALSE;
1117
+
1118
+ if (JSDOUBLE_IS_FINITE(result))
1119
+ result = DateFromTime(result);
1120
+
1121
+ return js_NewNumberInRootedValue(cx, result, vp);
1122
+ }
1123
+
1124
+ static JSBool
1125
+ date_getDay(JSContext *cx, uintN argc, jsval *vp)
1126
+ {
1127
+ jsdouble result;
1128
+
1129
+ if (!GetAndCacheLocalTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
1130
+ return JS_FALSE;
1131
+
1132
+ if (JSDOUBLE_IS_FINITE(result))
1133
+ result = WeekDay(result);
1134
+
1135
+ return js_NewNumberInRootedValue(cx, result, vp);
1136
+ }
1137
+
1138
+ static JSBool
1139
+ date_getUTCDay(JSContext *cx, uintN argc, jsval *vp)
1140
+ {
1141
+ jsdouble result;
1142
+
1143
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
1144
+ return JS_FALSE;
1145
+
1146
+ if (JSDOUBLE_IS_FINITE(result))
1147
+ result = WeekDay(result);
1148
+
1149
+ return js_NewNumberInRootedValue(cx, result, vp);
1150
+ }
1151
+
1152
+ static JSBool
1153
+ date_getHours(JSContext *cx, uintN argc, jsval *vp)
1154
+ {
1155
+ jsdouble result;
1156
+
1157
+ if (!GetAndCacheLocalTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
1158
+ return JS_FALSE;
1159
+
1160
+ if (JSDOUBLE_IS_FINITE(result))
1161
+ result = HourFromTime(result);
1162
+
1163
+ return js_NewNumberInRootedValue(cx, result, vp);
1164
+ }
1165
+
1166
+ static JSBool
1167
+ date_getUTCHours(JSContext *cx, uintN argc, jsval *vp)
1168
+ {
1169
+ jsdouble result;
1170
+
1171
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
1172
+ return JS_FALSE;
1173
+
1174
+ if (JSDOUBLE_IS_FINITE(result))
1175
+ result = HourFromTime(result);
1176
+
1177
+ return js_NewNumberInRootedValue(cx, result, vp);
1178
+ }
1179
+
1180
+ static JSBool
1181
+ date_getMinutes(JSContext *cx, uintN argc, jsval *vp)
1182
+ {
1183
+ jsdouble result;
1184
+
1185
+ if (!GetAndCacheLocalTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
1186
+ return JS_FALSE;
1187
+
1188
+ if (JSDOUBLE_IS_FINITE(result))
1189
+ result = MinFromTime(result);
1190
+
1191
+ return js_NewNumberInRootedValue(cx, result, vp);
1192
+ }
1193
+
1194
+ static JSBool
1195
+ date_getUTCMinutes(JSContext *cx, uintN argc, jsval *vp)
1196
+ {
1197
+ jsdouble result;
1198
+
1199
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
1200
+ return JS_FALSE;
1201
+
1202
+ if (JSDOUBLE_IS_FINITE(result))
1203
+ result = MinFromTime(result);
1204
+
1205
+ return js_NewNumberInRootedValue(cx, result, vp);
1206
+ }
1207
+
1208
+ /* Date.getSeconds is mapped to getUTCSeconds */
1209
+
1210
+ static JSBool
1211
+ date_getUTCSeconds(JSContext *cx, uintN argc, jsval *vp)
1212
+ {
1213
+ jsdouble result;
1214
+
1215
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
1216
+ return JS_FALSE;
1217
+
1218
+ if (JSDOUBLE_IS_FINITE(result))
1219
+ result = SecFromTime(result);
1220
+
1221
+ return js_NewNumberInRootedValue(cx, result, vp);
1222
+ }
1223
+
1224
+ /* Date.getMilliseconds is mapped to getUTCMilliseconds */
1225
+
1226
+ static JSBool
1227
+ date_getUTCMilliseconds(JSContext *cx, uintN argc, jsval *vp)
1228
+ {
1229
+ jsdouble result;
1230
+
1231
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
1232
+ return JS_FALSE;
1233
+
1234
+ if (JSDOUBLE_IS_FINITE(result))
1235
+ result = msFromTime(result);
1236
+
1237
+ return js_NewNumberInRootedValue(cx, result, vp);
1238
+ }
1239
+
1240
+ static JSBool
1241
+ date_getTimezoneOffset(JSContext *cx, uintN argc, jsval *vp)
1242
+ {
1243
+ JSObject *obj;
1244
+ jsdouble utctime, localtime, result;
1245
+
1246
+ obj = JS_THIS_OBJECT(cx, vp);
1247
+ if (!GetUTCTime(cx, obj, vp, &utctime))
1248
+ return JS_FALSE;
1249
+ if (!GetAndCacheLocalTime(cx, obj, NULL, &localtime))
1250
+ return JS_FALSE;
1251
+
1252
+ /*
1253
+ * Return the time zone offset in minutes for the current locale that is
1254
+ * appropriate for this time. This value would be a constant except for
1255
+ * daylight savings time.
1256
+ */
1257
+ result = (utctime - localtime) / msPerMinute;
1258
+ return js_NewNumberInRootedValue(cx, result, vp);
1259
+ }
1260
+
1261
+ static JSBool
1262
+ date_setTime(JSContext *cx, uintN argc, jsval *vp)
1263
+ {
1264
+ jsdouble result;
1265
+
1266
+ result = js_ValueToNumber(cx, &vp[2]);
1267
+ if (JSVAL_IS_NULL(vp[2]))
1268
+ return JS_FALSE;
1269
+
1270
+ result = TIMECLIP(result);
1271
+
1272
+ if (!SetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, result))
1273
+ return JS_FALSE;
1274
+
1275
+ return js_NewNumberInRootedValue(cx, result, vp);
1276
+ }
1277
+
1278
+ static JSBool
1279
+ date_makeTime(JSContext *cx, uintN maxargs, JSBool local, uintN argc, jsval *vp)
1280
+ {
1281
+ JSObject *obj;
1282
+ jsval *argv;
1283
+ uintN i;
1284
+ jsdouble args[4], *argp, *stop;
1285
+ jsdouble hour, min, sec, msec;
1286
+ jsdouble lorutime; /* Local or UTC version of *date */
1287
+
1288
+ jsdouble msec_time;
1289
+ jsdouble result;
1290
+
1291
+ obj = JS_THIS_OBJECT(cx, vp);
1292
+ if (!GetUTCTime(cx, obj, vp, &result))
1293
+ return JS_FALSE;
1294
+
1295
+ /* just return NaN if the date is already NaN */
1296
+ if (!JSDOUBLE_IS_FINITE(result))
1297
+ return js_NewNumberInRootedValue(cx, result, vp);
1298
+
1299
+ /*
1300
+ * Satisfy the ECMA rule that if a function is called with
1301
+ * fewer arguments than the specified formal arguments, the
1302
+ * remaining arguments are set to undefined. Seems like all
1303
+ * the Date.setWhatever functions in ECMA are only varargs
1304
+ * beyond the first argument; this should be set to undefined
1305
+ * if it's not given. This means that "d = new Date();
1306
+ * d.setMilliseconds()" returns NaN. Blech.
1307
+ */
1308
+ if (argc == 0)
1309
+ argc = 1; /* should be safe, because length of all setters is 1 */
1310
+ else if (argc > maxargs)
1311
+ argc = maxargs; /* clamp argc */
1312
+ JS_ASSERT(1 <= argc && argc <= 4);
1313
+
1314
+ argv = vp + 2;
1315
+ for (i = 0; i < argc; i++) {
1316
+ args[i] = js_ValueToNumber(cx, &argv[i]);
1317
+ if (JSVAL_IS_NULL(argv[i]))
1318
+ return JS_FALSE;
1319
+ if (!JSDOUBLE_IS_FINITE(args[i])) {
1320
+ if (!SetUTCTimePtr(cx, obj, NULL, cx->runtime->jsNaN))
1321
+ return JS_FALSE;
1322
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
1323
+ return JS_TRUE;
1324
+ }
1325
+ args[i] = js_DoubleToInteger(args[i]);
1326
+ }
1327
+
1328
+ if (local)
1329
+ lorutime = LocalTime(result);
1330
+ else
1331
+ lorutime = result;
1332
+
1333
+ argp = args;
1334
+ stop = argp + argc;
1335
+ if (maxargs >= 4 && argp < stop)
1336
+ hour = *argp++;
1337
+ else
1338
+ hour = HourFromTime(lorutime);
1339
+
1340
+ if (maxargs >= 3 && argp < stop)
1341
+ min = *argp++;
1342
+ else
1343
+ min = MinFromTime(lorutime);
1344
+
1345
+ if (maxargs >= 2 && argp < stop)
1346
+ sec = *argp++;
1347
+ else
1348
+ sec = SecFromTime(lorutime);
1349
+
1350
+ if (maxargs >= 1 && argp < stop)
1351
+ msec = *argp;
1352
+ else
1353
+ msec = msFromTime(lorutime);
1354
+
1355
+ msec_time = MakeTime(hour, min, sec, msec);
1356
+ result = MakeDate(Day(lorutime), msec_time);
1357
+
1358
+ /* fprintf(stderr, "%f\n", result); */
1359
+
1360
+ if (local)
1361
+ result = UTC(result);
1362
+
1363
+ /* fprintf(stderr, "%f\n", result); */
1364
+
1365
+ result = TIMECLIP(result);
1366
+ if (!SetUTCTime(cx, obj, NULL, result))
1367
+ return JS_FALSE;
1368
+
1369
+ return js_NewNumberInRootedValue(cx, result, vp);
1370
+ }
1371
+
1372
+ static JSBool
1373
+ date_setMilliseconds(JSContext *cx, uintN argc, jsval *vp)
1374
+ {
1375
+ return date_makeTime(cx, 1, JS_TRUE, argc, vp);
1376
+ }
1377
+
1378
+ static JSBool
1379
+ date_setUTCMilliseconds(JSContext *cx, uintN argc, jsval *vp)
1380
+ {
1381
+ return date_makeTime(cx, 1, JS_FALSE, argc, vp);
1382
+ }
1383
+
1384
+ static JSBool
1385
+ date_setSeconds(JSContext *cx, uintN argc, jsval *vp)
1386
+ {
1387
+ return date_makeTime(cx, 2, JS_TRUE, argc, vp);
1388
+ }
1389
+
1390
+ static JSBool
1391
+ date_setUTCSeconds(JSContext *cx, uintN argc, jsval *vp)
1392
+ {
1393
+ return date_makeTime(cx, 2, JS_FALSE, argc, vp);
1394
+ }
1395
+
1396
+ static JSBool
1397
+ date_setMinutes(JSContext *cx, uintN argc, jsval *vp)
1398
+ {
1399
+ return date_makeTime(cx, 3, JS_TRUE, argc, vp);
1400
+ }
1401
+
1402
+ static JSBool
1403
+ date_setUTCMinutes(JSContext *cx, uintN argc, jsval *vp)
1404
+ {
1405
+ return date_makeTime(cx, 3, JS_FALSE, argc, vp);
1406
+ }
1407
+
1408
+ static JSBool
1409
+ date_setHours(JSContext *cx, uintN argc, jsval *vp)
1410
+ {
1411
+ return date_makeTime(cx, 4, JS_TRUE, argc, vp);
1412
+ }
1413
+
1414
+ static JSBool
1415
+ date_setUTCHours(JSContext *cx, uintN argc, jsval *vp)
1416
+ {
1417
+ return date_makeTime(cx, 4, JS_FALSE, argc, vp);
1418
+ }
1419
+
1420
+ static JSBool
1421
+ date_makeDate(JSContext *cx, uintN maxargs, JSBool local, uintN argc, jsval *vp)
1422
+ {
1423
+ JSObject *obj;
1424
+ jsval *argv;
1425
+ uintN i;
1426
+ jsdouble lorutime; /* local or UTC version of *date */
1427
+ jsdouble args[3], *argp, *stop;
1428
+ jsdouble year, month, day;
1429
+ jsdouble result;
1430
+
1431
+ obj = JS_THIS_OBJECT(cx, vp);
1432
+ if (!GetUTCTime(cx, obj, vp, &result))
1433
+ return JS_FALSE;
1434
+
1435
+ /* see complaint about ECMA in date_MakeTime */
1436
+ if (argc == 0)
1437
+ argc = 1; /* should be safe, because length of all setters is 1 */
1438
+ else if (argc > maxargs)
1439
+ argc = maxargs; /* clamp argc */
1440
+ JS_ASSERT(1 <= argc && argc <= 3);
1441
+
1442
+ argv = vp + 2;
1443
+ for (i = 0; i < argc; i++) {
1444
+ args[i] = js_ValueToNumber(cx, &argv[i]);
1445
+ if (JSVAL_IS_NULL(argv[i]))
1446
+ return JS_FALSE;
1447
+ if (!JSDOUBLE_IS_FINITE(args[i])) {
1448
+ if (!SetUTCTimePtr(cx, obj, NULL, cx->runtime->jsNaN))
1449
+ return JS_FALSE;
1450
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
1451
+ return JS_TRUE;
1452
+ }
1453
+ args[i] = js_DoubleToInteger(args[i]);
1454
+ }
1455
+
1456
+ /* return NaN if date is NaN and we're not setting the year,
1457
+ * If we are, use 0 as the time. */
1458
+ if (!(JSDOUBLE_IS_FINITE(result))) {
1459
+ if (maxargs < 3)
1460
+ return js_NewNumberInRootedValue(cx, result, vp);
1461
+ lorutime = +0.;
1462
+ } else {
1463
+ lorutime = local ? LocalTime(result) : result;
1464
+ }
1465
+
1466
+ argp = args;
1467
+ stop = argp + argc;
1468
+ if (maxargs >= 3 && argp < stop)
1469
+ year = *argp++;
1470
+ else
1471
+ year = YearFromTime(lorutime);
1472
+
1473
+ if (maxargs >= 2 && argp < stop)
1474
+ month = *argp++;
1475
+ else
1476
+ month = MonthFromTime(lorutime);
1477
+
1478
+ if (maxargs >= 1 && argp < stop)
1479
+ day = *argp++;
1480
+ else
1481
+ day = DateFromTime(lorutime);
1482
+
1483
+ day = MakeDay(year, month, day); /* day within year */
1484
+ result = MakeDate(day, TimeWithinDay(lorutime));
1485
+
1486
+ if (local)
1487
+ result = UTC(result);
1488
+
1489
+ result = TIMECLIP(result);
1490
+ if (!SetUTCTime(cx, obj, NULL, result))
1491
+ return JS_FALSE;
1492
+
1493
+ return js_NewNumberInRootedValue(cx, result, vp);
1494
+ }
1495
+
1496
+ static JSBool
1497
+ date_setDate(JSContext *cx, uintN argc, jsval *vp)
1498
+ {
1499
+ return date_makeDate(cx, 1, JS_TRUE, argc, vp);
1500
+ }
1501
+
1502
+ static JSBool
1503
+ date_setUTCDate(JSContext *cx, uintN argc, jsval *vp)
1504
+ {
1505
+ return date_makeDate(cx, 1, JS_FALSE, argc, vp);
1506
+ }
1507
+
1508
+ static JSBool
1509
+ date_setMonth(JSContext *cx, uintN argc, jsval *vp)
1510
+ {
1511
+ return date_makeDate(cx, 2, JS_TRUE, argc, vp);
1512
+ }
1513
+
1514
+ static JSBool
1515
+ date_setUTCMonth(JSContext *cx, uintN argc, jsval *vp)
1516
+ {
1517
+ return date_makeDate(cx, 2, JS_FALSE, argc, vp);
1518
+ }
1519
+
1520
+ static JSBool
1521
+ date_setFullYear(JSContext *cx, uintN argc, jsval *vp)
1522
+ {
1523
+ return date_makeDate(cx, 3, JS_TRUE, argc, vp);
1524
+ }
1525
+
1526
+ static JSBool
1527
+ date_setUTCFullYear(JSContext *cx, uintN argc, jsval *vp)
1528
+ {
1529
+ return date_makeDate(cx, 3, JS_FALSE, argc, vp);
1530
+ }
1531
+
1532
+ static JSBool
1533
+ date_setYear(JSContext *cx, uintN argc, jsval *vp)
1534
+ {
1535
+ JSObject *obj;
1536
+ jsdouble t;
1537
+ jsdouble year;
1538
+ jsdouble day;
1539
+ jsdouble result;
1540
+
1541
+ obj = JS_THIS_OBJECT(cx, vp);
1542
+ if (!GetUTCTime(cx, obj, vp, &result))
1543
+ return JS_FALSE;
1544
+
1545
+ year = js_ValueToNumber(cx, &vp[2]);
1546
+ if (JSVAL_IS_NULL(vp[2]))
1547
+ return JS_FALSE;
1548
+ if (!JSDOUBLE_IS_FINITE(year)) {
1549
+ if (!SetUTCTimePtr(cx, obj, NULL, cx->runtime->jsNaN))
1550
+ return JS_FALSE;
1551
+ return js_NewNumberInRootedValue(cx, *cx->runtime->jsNaN, vp);
1552
+ }
1553
+
1554
+ year = js_DoubleToInteger(year);
1555
+
1556
+ if (!JSDOUBLE_IS_FINITE(result)) {
1557
+ t = +0.0;
1558
+ } else {
1559
+ t = LocalTime(result);
1560
+ }
1561
+
1562
+ if (year >= 0 && year <= 99)
1563
+ year += 1900;
1564
+
1565
+ day = MakeDay(year, MonthFromTime(t), DateFromTime(t));
1566
+ result = MakeDate(day, TimeWithinDay(t));
1567
+ result = UTC(result);
1568
+
1569
+ result = TIMECLIP(result);
1570
+ if (!SetUTCTime(cx, obj, NULL, result))
1571
+ return JS_FALSE;
1572
+
1573
+ return js_NewNumberInRootedValue(cx, result, vp);
1574
+ }
1575
+
1576
+ /* constants for toString, toUTCString */
1577
+ static char js_NaN_date_str[] = "Invalid Date";
1578
+ static const char* days[] =
1579
+ {
1580
+ "Sun","Mon","Tue","Wed","Thu","Fri","Sat"
1581
+ };
1582
+ static const char* months[] =
1583
+ {
1584
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
1585
+ };
1586
+
1587
+ static JSBool
1588
+ date_toGMTString(JSContext *cx, uintN argc, jsval *vp)
1589
+ {
1590
+ char buf[100];
1591
+ JSString *str;
1592
+ jsdouble utctime;
1593
+
1594
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &utctime))
1595
+ return JS_FALSE;
1596
+
1597
+ if (!JSDOUBLE_IS_FINITE(utctime)) {
1598
+ JS_snprintf(buf, sizeof buf, js_NaN_date_str);
1599
+ } else {
1600
+ /* Avoid dependence on PRMJ_FormatTimeUSEnglish, because it
1601
+ * requires a PRMJTime... which only has 16-bit years. Sub-ECMA.
1602
+ */
1603
+ JS_snprintf(buf, sizeof buf, "%s, %.2d %s %.4d %.2d:%.2d:%.2d GMT",
1604
+ days[WeekDay(utctime)],
1605
+ DateFromTime(utctime),
1606
+ months[MonthFromTime(utctime)],
1607
+ YearFromTime(utctime),
1608
+ HourFromTime(utctime),
1609
+ MinFromTime(utctime),
1610
+ SecFromTime(utctime));
1611
+ }
1612
+ str = JS_NewStringCopyZ(cx, buf);
1613
+ if (!str)
1614
+ return JS_FALSE;
1615
+ *vp = STRING_TO_JSVAL(str);
1616
+ return JS_TRUE;
1617
+ }
1618
+
1619
+ /* for Date.toLocaleString; interface to PRMJTime date struct.
1620
+ */
1621
+ static void
1622
+ new_explode(jsdouble timeval, PRMJTime *split)
1623
+ {
1624
+ jsint year = YearFromTime(timeval);
1625
+
1626
+ split->tm_usec = (int32) msFromTime(timeval) * 1000;
1627
+ split->tm_sec = (int8) SecFromTime(timeval);
1628
+ split->tm_min = (int8) MinFromTime(timeval);
1629
+ split->tm_hour = (int8) HourFromTime(timeval);
1630
+ split->tm_mday = (int8) DateFromTime(timeval);
1631
+ split->tm_mon = (int8) MonthFromTime(timeval);
1632
+ split->tm_wday = (int8) WeekDay(timeval);
1633
+ split->tm_year = year;
1634
+ split->tm_yday = (int16) DayWithinYear(timeval, year);
1635
+
1636
+ /* not sure how this affects things, but it doesn't seem
1637
+ to matter. */
1638
+ split->tm_isdst = (DaylightSavingTA(timeval) != 0);
1639
+ }
1640
+
1641
+ typedef enum formatspec {
1642
+ FORMATSPEC_FULL, FORMATSPEC_DATE, FORMATSPEC_TIME
1643
+ } formatspec;
1644
+
1645
+ /* helper function */
1646
+ static JSBool
1647
+ date_format(JSContext *cx, jsdouble date, formatspec format, jsval *rval)
1648
+ {
1649
+ char buf[100];
1650
+ JSString *str;
1651
+ char tzbuf[100];
1652
+ JSBool usetz;
1653
+ size_t i, tzlen;
1654
+ PRMJTime split;
1655
+
1656
+ if (!JSDOUBLE_IS_FINITE(date)) {
1657
+ JS_snprintf(buf, sizeof buf, js_NaN_date_str);
1658
+ } else {
1659
+ jsdouble local = LocalTime(date);
1660
+
1661
+ /* offset from GMT in minutes. The offset includes daylight savings,
1662
+ if it applies. */
1663
+ jsint minutes = (jsint) floor(AdjustTime(date) / msPerMinute);
1664
+
1665
+ /* map 510 minutes to 0830 hours */
1666
+ intN offset = (minutes / 60) * 100 + minutes % 60;
1667
+
1668
+ /* print as "Wed Nov 05 19:38:03 GMT-0800 (PST) 1997" The TZA is
1669
+ * printed as 'GMT-0800' rather than as 'PST' to avoid
1670
+ * operating-system dependence on strftime (which
1671
+ * PRMJ_FormatTimeUSEnglish calls, for %Z only.) win32 prints
1672
+ * PST as 'Pacific Standard Time.' This way we always know
1673
+ * what we're getting, and can parse it if we produce it.
1674
+ * The OS TZA string is included as a comment.
1675
+ */
1676
+
1677
+ /* get a timezone string from the OS to include as a
1678
+ comment. */
1679
+ new_explode(date, &split);
1680
+ if (PRMJ_FormatTime(tzbuf, sizeof tzbuf, "(%Z)", &split) != 0) {
1681
+
1682
+ /* Decide whether to use the resulting timezone string.
1683
+ *
1684
+ * Reject it if it contains any non-ASCII, non-alphanumeric
1685
+ * characters. It's then likely in some other character
1686
+ * encoding, and we probably won't display it correctly.
1687
+ */
1688
+ usetz = JS_TRUE;
1689
+ tzlen = strlen(tzbuf);
1690
+ if (tzlen > 100) {
1691
+ usetz = JS_FALSE;
1692
+ } else {
1693
+ for (i = 0; i < tzlen; i++) {
1694
+ jschar c = tzbuf[i];
1695
+ if (c > 127 ||
1696
+ !(isalpha(c) || isdigit(c) ||
1697
+ c == ' ' || c == '(' || c == ')')) {
1698
+ usetz = JS_FALSE;
1699
+ }
1700
+ }
1701
+ }
1702
+
1703
+ /* Also reject it if it's not parenthesized or if it's '()'. */
1704
+ if (tzbuf[0] != '(' || tzbuf[1] == ')')
1705
+ usetz = JS_FALSE;
1706
+ } else
1707
+ usetz = JS_FALSE;
1708
+
1709
+ switch (format) {
1710
+ case FORMATSPEC_FULL:
1711
+ /*
1712
+ * Avoid dependence on PRMJ_FormatTimeUSEnglish, because it
1713
+ * requires a PRMJTime... which only has 16-bit years. Sub-ECMA.
1714
+ */
1715
+ /* Tue Oct 31 2000 09:41:40 GMT-0800 (PST) */
1716
+ JS_snprintf(buf, sizeof buf,
1717
+ "%s %s %.2d %.4d %.2d:%.2d:%.2d GMT%+.4d%s%s",
1718
+ days[WeekDay(local)],
1719
+ months[MonthFromTime(local)],
1720
+ DateFromTime(local),
1721
+ YearFromTime(local),
1722
+ HourFromTime(local),
1723
+ MinFromTime(local),
1724
+ SecFromTime(local),
1725
+ offset,
1726
+ usetz ? " " : "",
1727
+ usetz ? tzbuf : "");
1728
+ break;
1729
+ case FORMATSPEC_DATE:
1730
+ /* Tue Oct 31 2000 */
1731
+ JS_snprintf(buf, sizeof buf,
1732
+ "%s %s %.2d %.4d",
1733
+ days[WeekDay(local)],
1734
+ months[MonthFromTime(local)],
1735
+ DateFromTime(local),
1736
+ YearFromTime(local));
1737
+ break;
1738
+ case FORMATSPEC_TIME:
1739
+ /* 09:41:40 GMT-0800 (PST) */
1740
+ JS_snprintf(buf, sizeof buf,
1741
+ "%.2d:%.2d:%.2d GMT%+.4d%s%s",
1742
+ HourFromTime(local),
1743
+ MinFromTime(local),
1744
+ SecFromTime(local),
1745
+ offset,
1746
+ usetz ? " " : "",
1747
+ usetz ? tzbuf : "");
1748
+ break;
1749
+ }
1750
+ }
1751
+
1752
+ str = JS_NewStringCopyZ(cx, buf);
1753
+ if (!str)
1754
+ return JS_FALSE;
1755
+ *rval = STRING_TO_JSVAL(str);
1756
+ return JS_TRUE;
1757
+ }
1758
+
1759
+ static JSBool
1760
+ date_toLocaleHelper(JSContext *cx, const char *format, jsval *vp)
1761
+ {
1762
+ JSObject *obj;
1763
+ char buf[100];
1764
+ JSString *str;
1765
+ PRMJTime split;
1766
+ jsdouble utctime;
1767
+
1768
+ obj = JS_THIS_OBJECT(cx, vp);
1769
+ if (!GetUTCTime(cx, obj, vp, &utctime))
1770
+ return JS_FALSE;
1771
+
1772
+ if (!JSDOUBLE_IS_FINITE(utctime)) {
1773
+ JS_snprintf(buf, sizeof buf, js_NaN_date_str);
1774
+ } else {
1775
+ intN result_len;
1776
+ jsdouble local = LocalTime(utctime);
1777
+ new_explode(local, &split);
1778
+
1779
+ /* let PRMJTime format it. */
1780
+ result_len = PRMJ_FormatTime(buf, sizeof buf, format, &split);
1781
+
1782
+ /* If it failed, default to toString. */
1783
+ if (result_len == 0)
1784
+ return date_format(cx, utctime, FORMATSPEC_FULL, vp);
1785
+
1786
+ /* Hacked check against undesired 2-digit year 00/00/00 form. */
1787
+ if (strcmp(format, "%x") == 0 && result_len >= 6 &&
1788
+ /* Format %x means use OS settings, which may have 2-digit yr, so
1789
+ hack end of 3/11/22 or 11.03.22 or 11Mar22 to use 4-digit yr...*/
1790
+ !isdigit(buf[result_len - 3]) &&
1791
+ isdigit(buf[result_len - 2]) && isdigit(buf[result_len - 1]) &&
1792
+ /* ...but not if starts with 4-digit year, like 2022/3/11. */
1793
+ !(isdigit(buf[0]) && isdigit(buf[1]) &&
1794
+ isdigit(buf[2]) && isdigit(buf[3]))) {
1795
+ JS_snprintf(buf + (result_len - 2), (sizeof buf) - (result_len - 2),
1796
+ "%d", js_DateGetYear(cx, obj));
1797
+ }
1798
+
1799
+ }
1800
+
1801
+ if (cx->localeCallbacks && cx->localeCallbacks->localeToUnicode)
1802
+ return cx->localeCallbacks->localeToUnicode(cx, buf, vp);
1803
+
1804
+ str = JS_NewStringCopyZ(cx, buf);
1805
+ if (!str)
1806
+ return JS_FALSE;
1807
+ *vp = STRING_TO_JSVAL(str);
1808
+ return JS_TRUE;
1809
+ }
1810
+
1811
+ static JSBool
1812
+ date_toLocaleString(JSContext *cx, uintN argc, jsval *vp)
1813
+ {
1814
+ /* Use '%#c' for windows, because '%c' is
1815
+ * backward-compatible and non-y2k with msvc; '%#c' requests that a
1816
+ * full year be used in the result string.
1817
+ */
1818
+ return date_toLocaleHelper(cx,
1819
+ #if defined(_WIN32) && !defined(__MWERKS__)
1820
+ "%#c"
1821
+ #else
1822
+ "%c"
1823
+ #endif
1824
+ , vp);
1825
+ }
1826
+
1827
+ static JSBool
1828
+ date_toLocaleDateString(JSContext *cx, uintN argc, jsval *vp)
1829
+ {
1830
+ /* Use '%#x' for windows, because '%x' is
1831
+ * backward-compatible and non-y2k with msvc; '%#x' requests that a
1832
+ * full year be used in the result string.
1833
+ */
1834
+ return date_toLocaleHelper(cx,
1835
+ #if defined(_WIN32) && !defined(__MWERKS__)
1836
+ "%#x"
1837
+ #else
1838
+ "%x"
1839
+ #endif
1840
+ , vp);
1841
+ }
1842
+
1843
+ static JSBool
1844
+ date_toLocaleTimeString(JSContext *cx, uintN argc, jsval *vp)
1845
+ {
1846
+ return date_toLocaleHelper(cx, "%X", vp);
1847
+ }
1848
+
1849
+ static JSBool
1850
+ date_toLocaleFormat(JSContext *cx, uintN argc, jsval *vp)
1851
+ {
1852
+ JSString *fmt;
1853
+ const char *fmtbytes;
1854
+
1855
+ if (argc == 0)
1856
+ return date_toLocaleString(cx, argc, vp);
1857
+
1858
+ fmt = js_ValueToString(cx, vp[2]);
1859
+ if (!fmt)
1860
+ return JS_FALSE;
1861
+ vp[2] = STRING_TO_JSVAL(fmt);
1862
+ fmtbytes = js_GetStringBytes(cx, fmt);
1863
+ if (!fmtbytes)
1864
+ return JS_FALSE;
1865
+
1866
+ return date_toLocaleHelper(cx, fmtbytes, vp);
1867
+ }
1868
+
1869
+ static JSBool
1870
+ date_toTimeString(JSContext *cx, uintN argc, jsval *vp)
1871
+ {
1872
+ jsdouble utctime;
1873
+
1874
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &utctime))
1875
+ return JS_FALSE;
1876
+ return date_format(cx, utctime, FORMATSPEC_TIME, vp);
1877
+ }
1878
+
1879
+ static JSBool
1880
+ date_toDateString(JSContext *cx, uintN argc, jsval *vp)
1881
+ {
1882
+ jsdouble utctime;
1883
+
1884
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &utctime))
1885
+ return JS_FALSE;
1886
+ return date_format(cx, utctime, FORMATSPEC_DATE, vp);
1887
+ }
1888
+
1889
+ #if JS_HAS_TOSOURCE
1890
+ #include <string.h>
1891
+ #include "jsdtoa.h"
1892
+
1893
+ static JSBool
1894
+ date_toSource(JSContext *cx, uintN argc, jsval *vp)
1895
+ {
1896
+ jsdouble utctime;
1897
+ char buf[DTOSTR_STANDARD_BUFFER_SIZE], *numStr, *bytes;
1898
+ JSString *str;
1899
+
1900
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &utctime))
1901
+ return JS_FALSE;
1902
+
1903
+ numStr = JS_dtostr(buf, sizeof buf, DTOSTR_STANDARD, 0, utctime);
1904
+ if (!numStr) {
1905
+ JS_ReportOutOfMemory(cx);
1906
+ return JS_FALSE;
1907
+ }
1908
+
1909
+ bytes = JS_smprintf("(new %s(%s))", js_Date_str, numStr);
1910
+ if (!bytes) {
1911
+ JS_ReportOutOfMemory(cx);
1912
+ return JS_FALSE;
1913
+ }
1914
+
1915
+ str = JS_NewString(cx, bytes, strlen(bytes));
1916
+ if (!str) {
1917
+ free(bytes);
1918
+ return JS_FALSE;
1919
+ }
1920
+ *vp = STRING_TO_JSVAL(str);
1921
+ return JS_TRUE;
1922
+ }
1923
+ #endif
1924
+
1925
+ static JSBool
1926
+ date_toString(JSContext *cx, uintN argc, jsval *vp)
1927
+ {
1928
+ jsdouble utctime;
1929
+
1930
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &utctime))
1931
+ return JS_FALSE;
1932
+ return date_format(cx, utctime, FORMATSPEC_FULL, vp);
1933
+ }
1934
+
1935
+ static JSBool
1936
+ date_valueOf(JSContext *cx, uintN argc, jsval *vp)
1937
+ {
1938
+ JSString *str, *str2;
1939
+
1940
+ /* It is an error to call date_valueOf on a non-date object, but we don't
1941
+ * need to check for that explicitly here because every path calls
1942
+ * GetUTCTime, which does the check.
1943
+ */
1944
+
1945
+ /* If called directly with no arguments, convert to a time number. */
1946
+ if (argc == 0)
1947
+ return date_getTime(cx, argc, vp);
1948
+
1949
+ /* Convert to number only if the hint was given, otherwise favor string. */
1950
+ str = js_ValueToString(cx, vp[2]);
1951
+ if (!str)
1952
+ return JS_FALSE;
1953
+ str2 = ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[JSTYPE_NUMBER]);
1954
+ if (js_EqualStrings(str, str2))
1955
+ return date_getTime(cx, argc, vp);
1956
+ return date_toString(cx, argc, vp);
1957
+ }
1958
+
1959
+
1960
+ /*
1961
+ * creation and destruction
1962
+ */
1963
+
1964
+ static JSFunctionSpec date_static_methods[] = {
1965
+ JS_FN("UTC", date_UTC, 2,MAXARGS,0),
1966
+ JS_FN("parse", date_parse, 1,1,0),
1967
+ JS_FN("now", date_now, 0,0,0),
1968
+ JS_FS_END
1969
+ };
1970
+
1971
+ static JSFunctionSpec date_methods[] = {
1972
+ JS_FN("getTime", date_getTime, 0,0,0),
1973
+ JS_FN("getTimezoneOffset", date_getTimezoneOffset, 0,0,0),
1974
+ JS_FN("getYear", date_getYear, 0,0,0),
1975
+ JS_FN("getFullYear", date_getFullYear, 0,0,0),
1976
+ JS_FN("getUTCFullYear", date_getUTCFullYear, 0,0,0),
1977
+ JS_FN("getMonth", date_getMonth, 0,0,0),
1978
+ JS_FN("getUTCMonth", date_getUTCMonth, 0,0,0),
1979
+ JS_FN("getDate", date_getDate, 0,0,0),
1980
+ JS_FN("getUTCDate", date_getUTCDate, 0,0,0),
1981
+ JS_FN("getDay", date_getDay, 0,0,0),
1982
+ JS_FN("getUTCDay", date_getUTCDay, 0,0,0),
1983
+ JS_FN("getHours", date_getHours, 0,0,0),
1984
+ JS_FN("getUTCHours", date_getUTCHours, 0,0,0),
1985
+ JS_FN("getMinutes", date_getMinutes, 0,0,0),
1986
+ JS_FN("getUTCMinutes", date_getUTCMinutes, 0,0,0),
1987
+ JS_FN("getSeconds", date_getUTCSeconds, 0,0,0),
1988
+ JS_FN("getUTCSeconds", date_getUTCSeconds, 0,0,0),
1989
+ JS_FN("getMilliseconds", date_getUTCMilliseconds, 0,0,0),
1990
+ JS_FN("getUTCMilliseconds", date_getUTCMilliseconds, 0,0,0),
1991
+ JS_FN("setTime", date_setTime, 1,1,0),
1992
+ JS_FN("setYear", date_setYear, 1,1,0),
1993
+ JS_FN("setFullYear", date_setFullYear, 1,3,0),
1994
+ JS_FN("setUTCFullYear", date_setUTCFullYear, 1,3,0),
1995
+ JS_FN("setMonth", date_setMonth, 1,2,0),
1996
+ JS_FN("setUTCMonth", date_setUTCMonth, 1,2,0),
1997
+ JS_FN("setDate", date_setDate, 1,1,0),
1998
+ JS_FN("setUTCDate", date_setUTCDate, 1,1,0),
1999
+ JS_FN("setHours", date_setHours, 1,4,0),
2000
+ JS_FN("setUTCHours", date_setUTCHours, 1,4,0),
2001
+ JS_FN("setMinutes", date_setMinutes, 1,3,0),
2002
+ JS_FN("setUTCMinutes", date_setUTCMinutes, 1,3,0),
2003
+ JS_FN("setSeconds", date_setSeconds, 1,2,0),
2004
+ JS_FN("setUTCSeconds", date_setUTCSeconds, 1,2,0),
2005
+ JS_FN("setMilliseconds", date_setMilliseconds, 1,1,0),
2006
+ JS_FN("setUTCMilliseconds", date_setUTCMilliseconds, 1,1,0),
2007
+ JS_FN("toUTCString", date_toGMTString, 0,0,0),
2008
+ JS_FN(js_toLocaleString_str, date_toLocaleString, 0,0,0),
2009
+ JS_FN("toLocaleDateString", date_toLocaleDateString, 0,0,0),
2010
+ JS_FN("toLocaleTimeString", date_toLocaleTimeString, 0,0,0),
2011
+ JS_FN("toLocaleFormat", date_toLocaleFormat, 0,0,0),
2012
+ JS_FN("toDateString", date_toDateString, 0,0,0),
2013
+ JS_FN("toTimeString", date_toTimeString, 0,0,0),
2014
+ #if JS_HAS_TOSOURCE
2015
+ JS_FN(js_toSource_str, date_toSource, 0,0,0),
2016
+ #endif
2017
+ JS_FN(js_toString_str, date_toString, 0,0,0),
2018
+ JS_FN(js_valueOf_str, date_valueOf, 0,0,0),
2019
+ JS_FS_END
2020
+ };
2021
+
2022
+ static jsdouble *
2023
+ date_constructor(JSContext *cx, JSObject* obj)
2024
+ {
2025
+ jsdouble *date;
2026
+
2027
+ date = js_NewWeaklyRootedDouble(cx, 0.0);
2028
+ if (!date)
2029
+ return NULL;
2030
+
2031
+ JS_SetReservedSlot(cx, obj, UTC_TIME_SLOT,
2032
+ DOUBLE_TO_JSVAL(date));
2033
+ JS_SetReservedSlot(cx, obj, LOCAL_TIME_SLOT,
2034
+ DOUBLE_TO_JSVAL(cx->runtime->jsNaN));
2035
+ return date;
2036
+ }
2037
+
2038
+ static JSBool
2039
+ Date(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2040
+ {
2041
+ jsdouble *date;
2042
+ JSString *str;
2043
+ jsdouble d;
2044
+
2045
+ /* Date called as function. */
2046
+ if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {
2047
+ int64 us, ms, us2ms;
2048
+ jsdouble msec_time;
2049
+
2050
+ /* NSPR 2.0 docs say 'We do not support PRMJ_NowMS and PRMJ_NowS',
2051
+ * so compute ms from PRMJ_Now.
2052
+ */
2053
+ us = PRMJ_Now();
2054
+ JSLL_UI2L(us2ms, PRMJ_USEC_PER_MSEC);
2055
+ JSLL_DIV(ms, us, us2ms);
2056
+ JSLL_L2D(msec_time, ms);
2057
+
2058
+ return date_format(cx, msec_time, FORMATSPEC_FULL, rval);
2059
+ }
2060
+
2061
+ /* Date called as constructor. */
2062
+ if (argc == 0) {
2063
+ int64 us, ms, us2ms;
2064
+ jsdouble msec_time;
2065
+
2066
+ date = date_constructor(cx, obj);
2067
+ if (!date)
2068
+ return JS_FALSE;
2069
+
2070
+ us = PRMJ_Now();
2071
+ JSLL_UI2L(us2ms, PRMJ_USEC_PER_MSEC);
2072
+ JSLL_DIV(ms, us, us2ms);
2073
+ JSLL_L2D(msec_time, ms);
2074
+
2075
+ *date = msec_time;
2076
+ } else if (argc == 1) {
2077
+ if (!JSVAL_IS_STRING(argv[0])) {
2078
+ /* the argument is a millisecond number */
2079
+ d = js_ValueToNumber(cx, &argv[0]);
2080
+ if (JSVAL_IS_NULL(argv[0]))
2081
+ return JS_FALSE;
2082
+ date = date_constructor(cx, obj);
2083
+ if (!date)
2084
+ return JS_FALSE;
2085
+ *date = TIMECLIP(d);
2086
+ } else {
2087
+ /* the argument is a string; parse it. */
2088
+ date = date_constructor(cx, obj);
2089
+ if (!date)
2090
+ return JS_FALSE;
2091
+
2092
+ str = js_ValueToString(cx, argv[0]);
2093
+ if (!str)
2094
+ return JS_FALSE;
2095
+
2096
+ if (!date_parseString(str, date))
2097
+ *date = *cx->runtime->jsNaN;
2098
+ *date = TIMECLIP(*date);
2099
+ }
2100
+ } else {
2101
+ jsdouble *date;
2102
+ jsdouble msec_time;
2103
+
2104
+ if (!date_msecFromArgs(cx, argc, argv, &msec_time))
2105
+ return JS_FALSE;
2106
+
2107
+ date = date_constructor(cx, obj);
2108
+ if (!date)
2109
+ return JS_FALSE;
2110
+
2111
+ if (JSDOUBLE_IS_FINITE(msec_time)) {
2112
+ msec_time = UTC(msec_time);
2113
+ msec_time = TIMECLIP(msec_time);
2114
+ }
2115
+
2116
+ *date = msec_time;
2117
+ }
2118
+ return JS_TRUE;
2119
+ }
2120
+
2121
+ JSObject *
2122
+ js_InitDateClass(JSContext *cx, JSObject *obj)
2123
+ {
2124
+ JSObject *proto;
2125
+ jsdouble *proto_date;
2126
+
2127
+ /* set static LocalTZA */
2128
+ LocalTZA = -(PRMJ_LocalGMTDifference() * msPerSecond);
2129
+ proto = JS_InitClass(cx, obj, NULL, &js_DateClass, Date, MAXARGS,
2130
+ NULL, date_methods, NULL, date_static_methods);
2131
+ if (!proto)
2132
+ return NULL;
2133
+
2134
+ /* Alias toUTCString with toGMTString. (ECMA B.2.6) */
2135
+ if (!JS_AliasProperty(cx, proto, "toUTCString", "toGMTString"))
2136
+ return NULL;
2137
+
2138
+ /* Set the value of the Date.prototype date to NaN */
2139
+ proto_date = date_constructor(cx, proto);
2140
+ if (!proto_date)
2141
+ return NULL;
2142
+ *proto_date = *cx->runtime->jsNaN;
2143
+
2144
+ return proto;
2145
+ }
2146
+
2147
+ JS_FRIEND_API(JSObject *)
2148
+ js_NewDateObjectMsec(JSContext *cx, jsdouble msec_time)
2149
+ {
2150
+ JSObject *obj;
2151
+ jsdouble *date;
2152
+
2153
+ obj = js_NewObject(cx, &js_DateClass, NULL, NULL, 0);
2154
+ if (!obj)
2155
+ return NULL;
2156
+
2157
+ date = date_constructor(cx, obj);
2158
+ if (!date)
2159
+ return NULL;
2160
+
2161
+ *date = msec_time;
2162
+ return obj;
2163
+ }
2164
+
2165
+ JS_FRIEND_API(JSObject *)
2166
+ js_NewDateObject(JSContext* cx, int year, int mon, int mday,
2167
+ int hour, int min, int sec)
2168
+ {
2169
+ JSObject *obj;
2170
+ jsdouble msec_time;
2171
+
2172
+ JS_ASSERT(mon < 12);
2173
+ msec_time = date_msecFromDate(year, mon, mday, hour, min, sec, 0);
2174
+ obj = js_NewDateObjectMsec(cx, UTC(msec_time));
2175
+ return obj;
2176
+ }
2177
+
2178
+ JS_FRIEND_API(JSBool)
2179
+ js_DateIsValid(JSContext *cx, JSObject* obj)
2180
+ {
2181
+ jsdouble utctime;
2182
+ return GetUTCTime(cx, obj, NULL, &utctime) && !JSDOUBLE_IS_NaN(utctime);
2183
+ }
2184
+
2185
+ JS_FRIEND_API(int)
2186
+ js_DateGetYear(JSContext *cx, JSObject* obj)
2187
+ {
2188
+ jsdouble localtime;
2189
+
2190
+ /* Preserve legacy API behavior of returning 0 for invalid dates. */
2191
+ if (!GetAndCacheLocalTime(cx, obj, NULL, &localtime) ||
2192
+ JSDOUBLE_IS_NaN(localtime)) {
2193
+ return 0;
2194
+ }
2195
+
2196
+ return (int) YearFromTime(localtime);
2197
+ }
2198
+
2199
+ JS_FRIEND_API(int)
2200
+ js_DateGetMonth(JSContext *cx, JSObject* obj)
2201
+ {
2202
+ jsdouble localtime;
2203
+
2204
+ if (!GetAndCacheLocalTime(cx, obj, NULL, &localtime) ||
2205
+ JSDOUBLE_IS_NaN(localtime)) {
2206
+ return 0;
2207
+ }
2208
+
2209
+ return (int) MonthFromTime(localtime);
2210
+ }
2211
+
2212
+ JS_FRIEND_API(int)
2213
+ js_DateGetDate(JSContext *cx, JSObject* obj)
2214
+ {
2215
+ jsdouble localtime;
2216
+
2217
+ if (!GetAndCacheLocalTime(cx, obj, NULL, &localtime) ||
2218
+ JSDOUBLE_IS_NaN(localtime)) {
2219
+ return 0;
2220
+ }
2221
+
2222
+ return (int) DateFromTime(localtime);
2223
+ }
2224
+
2225
+ JS_FRIEND_API(int)
2226
+ js_DateGetHours(JSContext *cx, JSObject* obj)
2227
+ {
2228
+ jsdouble localtime;
2229
+
2230
+ if (!GetAndCacheLocalTime(cx, obj, NULL, &localtime) ||
2231
+ JSDOUBLE_IS_NaN(localtime)) {
2232
+ return 0;
2233
+ }
2234
+
2235
+ return (int) HourFromTime(localtime);
2236
+ }
2237
+
2238
+ JS_FRIEND_API(int)
2239
+ js_DateGetMinutes(JSContext *cx, JSObject* obj)
2240
+ {
2241
+ jsdouble localtime;
2242
+
2243
+ if (!GetAndCacheLocalTime(cx, obj, NULL, &localtime) ||
2244
+ JSDOUBLE_IS_NaN(localtime)) {
2245
+ return 0;
2246
+ }
2247
+
2248
+ return (int) MinFromTime(localtime);
2249
+ }
2250
+
2251
+ JS_FRIEND_API(int)
2252
+ js_DateGetSeconds(JSContext *cx, JSObject* obj)
2253
+ {
2254
+ jsdouble utctime;
2255
+
2256
+ if (!GetUTCTime(cx, obj, NULL, &utctime) || JSDOUBLE_IS_NaN(utctime))
2257
+ return 0;
2258
+
2259
+ return (int) SecFromTime(utctime);
2260
+ }
2261
+
2262
+ JS_FRIEND_API(void)
2263
+ js_DateSetYear(JSContext *cx, JSObject *obj, int year)
2264
+ {
2265
+ jsdouble local;
2266
+
2267
+ if (!GetAndCacheLocalTime(cx, obj, NULL, &local))
2268
+ return;
2269
+
2270
+ /* reset date if it was NaN */
2271
+ if (JSDOUBLE_IS_NaN(local))
2272
+ local = 0;
2273
+
2274
+ local = date_msecFromDate(year,
2275
+ MonthFromTime(local),
2276
+ DateFromTime(local),
2277
+ HourFromTime(local),
2278
+ MinFromTime(local),
2279
+ SecFromTime(local),
2280
+ msFromTime(local));
2281
+
2282
+ /* SetUTCTime also invalidates local time cache. */
2283
+ SetUTCTime(cx, obj, NULL, UTC(local));
2284
+ }
2285
+
2286
+ JS_FRIEND_API(void)
2287
+ js_DateSetMonth(JSContext *cx, JSObject *obj, int month)
2288
+ {
2289
+ jsdouble local;
2290
+
2291
+ JS_ASSERT(month < 12);
2292
+
2293
+ if (!GetAndCacheLocalTime(cx, obj, NULL, &local))
2294
+ return;
2295
+
2296
+ /* bail if date was NaN */
2297
+ if (JSDOUBLE_IS_NaN(local))
2298
+ return;
2299
+
2300
+ local = date_msecFromDate(YearFromTime(local),
2301
+ month,
2302
+ DateFromTime(local),
2303
+ HourFromTime(local),
2304
+ MinFromTime(local),
2305
+ SecFromTime(local),
2306
+ msFromTime(local));
2307
+ SetUTCTime(cx, obj, NULL, UTC(local));
2308
+ }
2309
+
2310
+ JS_FRIEND_API(void)
2311
+ js_DateSetDate(JSContext *cx, JSObject *obj, int date)
2312
+ {
2313
+ jsdouble local;
2314
+
2315
+ if (!GetAndCacheLocalTime(cx, obj, NULL, &local))
2316
+ return;
2317
+
2318
+ if (JSDOUBLE_IS_NaN(local))
2319
+ return;
2320
+
2321
+ local = date_msecFromDate(YearFromTime(local),
2322
+ MonthFromTime(local),
2323
+ date,
2324
+ HourFromTime(local),
2325
+ MinFromTime(local),
2326
+ SecFromTime(local),
2327
+ msFromTime(local));
2328
+ SetUTCTime(cx, obj, NULL, UTC(local));
2329
+ }
2330
+
2331
+ JS_FRIEND_API(void)
2332
+ js_DateSetHours(JSContext *cx, JSObject *obj, int hours)
2333
+ {
2334
+ jsdouble local;
2335
+
2336
+ if (!GetAndCacheLocalTime(cx, obj, NULL, &local))
2337
+ return;
2338
+
2339
+ if (JSDOUBLE_IS_NaN(local))
2340
+ return;
2341
+ local = date_msecFromDate(YearFromTime(local),
2342
+ MonthFromTime(local),
2343
+ DateFromTime(local),
2344
+ hours,
2345
+ MinFromTime(local),
2346
+ SecFromTime(local),
2347
+ msFromTime(local));
2348
+ SetUTCTime(cx, obj, NULL, UTC(local));
2349
+ }
2350
+
2351
+ JS_FRIEND_API(void)
2352
+ js_DateSetMinutes(JSContext *cx, JSObject *obj, int minutes)
2353
+ {
2354
+ jsdouble local;
2355
+
2356
+ if (!GetAndCacheLocalTime(cx, obj, NULL, &local))
2357
+ return;
2358
+
2359
+ if (JSDOUBLE_IS_NaN(local))
2360
+ return;
2361
+ local = date_msecFromDate(YearFromTime(local),
2362
+ MonthFromTime(local),
2363
+ DateFromTime(local),
2364
+ HourFromTime(local),
2365
+ minutes,
2366
+ SecFromTime(local),
2367
+ msFromTime(local));
2368
+ SetUTCTime(cx, obj, NULL, UTC(local));
2369
+ }
2370
+
2371
+ JS_FRIEND_API(void)
2372
+ js_DateSetSeconds(JSContext *cx, JSObject *obj, int seconds)
2373
+ {
2374
+ jsdouble local;
2375
+
2376
+ if (!GetAndCacheLocalTime(cx, obj, NULL, &local))
2377
+ return;
2378
+
2379
+ if (JSDOUBLE_IS_NaN(local))
2380
+ return;
2381
+ local = date_msecFromDate(YearFromTime(local),
2382
+ MonthFromTime(local),
2383
+ DateFromTime(local),
2384
+ HourFromTime(local),
2385
+ MinFromTime(local),
2386
+ seconds,
2387
+ msFromTime(local));
2388
+ SetUTCTime(cx, obj, NULL, UTC(local));
2389
+ }
2390
+
2391
+ JS_FRIEND_API(jsdouble)
2392
+ js_DateGetMsecSinceEpoch(JSContext *cx, JSObject *obj)
2393
+ {
2394
+ jsdouble utctime;
2395
+ if (!GetUTCTime(cx, obj, NULL, &utctime))
2396
+ return 0;
2397
+ return utctime;
2398
+ }