jbarnette-johnson 1.0.0.200806240111 → 1.0.0.200807291507

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,56 @@
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
+ *
26
+ * Alternatively, the contents of this file may be used under the terms of
27
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
28
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29
+ * in which case the provisions of the GPL or the LGPL are applicable instead
30
+ * of those above. If you wish to allow use of your version of this file only
31
+ * under the terms of either the GPL or the LGPL, and not to allow others to
32
+ * use your version of this file under the terms of the MPL, indicate your
33
+ * decision by deleting the provisions above and replace them with the notice
34
+ * and other provisions required by the GPL or the LGPL. If you do not delete
35
+ * the provisions above, a recipient may use your version of this file under
36
+ * the terms of any one of the MPL, the GPL or the LGPL.
37
+ *
38
+ * ***** END LICENSE BLOCK ***** */
39
+
40
+ #ifndef _jsfile_h__
41
+ #define _jsfile_h__
42
+
43
+ #if JS_HAS_FILE_OBJECT
44
+
45
+ #include "jsobj.h"
46
+
47
+ extern JS_PUBLIC_API(JSObject*)
48
+ js_InitFileClass(JSContext *cx, JSObject* obj);
49
+
50
+ extern JS_PUBLIC_API(JSObject*)
51
+ js_NewFileObject(JSContext *cx, char *bytes);
52
+
53
+ extern JSClass js_FileClass;
54
+
55
+ #endif /* JS_HAS_FILE_OBJECT */
56
+ #endif /* _jsfile_h__ */
@@ -0,0 +1,90 @@
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
+ *
26
+ * Alternatively, the contents of this file may be used under the terms of
27
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
28
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29
+ * in which case the provisions of the GPL or the LGPL are applicable instead
30
+ * of those above. If you wish to allow use of your version of this file only
31
+ * under the terms of either the GPL or the LGPL, and not to allow others to
32
+ * use your version of this file under the terms of the MPL, indicate your
33
+ * decision by deleting the provisions above and replace them with the notice
34
+ * and other provisions required by the GPL or the LGPL. If you do not delete
35
+ * the provisions above, a recipient may use your version of this file under
36
+ * the terms of any one of the MPL, the GPL or the LGPL.
37
+ *
38
+ * ***** END LICENSE BLOCK ***** */
39
+
40
+ /*
41
+ Error messages for jsfile.c. See js.msg for format specification.
42
+ */
43
+
44
+ MSG_DEF(JSFILEMSG_NOT_AN_ERROR, 0, 0, JSEXN_NONE, "<Error #0 is reserved>")
45
+ MSG_DEF(JSFILEMSG_FILE_CONSTRUCTOR_UNDEFINED_ERROR, 1, 0, JSEXN_NONE, "File constructor is undefined")
46
+ MSG_DEF(JSFILEMSG_FILE_CURRENTDIR_UNDEFINED_ERROR, 2, 0, JSEXN_NONE, "File.currentDir is undefined")
47
+ MSG_DEF(JSFILEMSG_FIRST_ARGUMENT_OPEN_NOT_STRING_ERROR, 3, 1, JSEXN_NONE, "The first argument {0} to file.open must be a string")
48
+ MSG_DEF(JSFILEMSG_SECOND_ARGUMENT_OPEN_NOT_STRING_ERROR, 4, 0, JSEXN_NONE, "The second argument to file.open must be a string")
49
+ MSG_DEF(JSFILEMSG_CANNOT_COPY_FILE_OPEN_FOR_WRITING_ERROR, 5, 1, JSEXN_NONE, "Cannot copy file {0} open for writing")
50
+ MSG_DEF(JSFILEMSG_CANNOT_ACCESS_FILE_INFO_ERROR, 6, 1, JSEXN_NONE, "Cannot access file information for {0}")
51
+ MSG_DEF(JSFILEMSG_COPY_READ_ERROR, 7, 1, JSEXN_NONE, "An error occured while attempting to read a file {0} to copy")
52
+ MSG_DEF(JSFILEMSG_COPY_WRITE_ERROR, 8, 1, JSEXN_NONE, "An error occured while attempting to copy into file {0}")
53
+ MSG_DEF(JSFILEMSG_EXPECTS_ONE_ARG_ERROR, 9, 0, JSEXN_NONE, "Operation {0} expects one argument, not {1}")
54
+ MSG_DEF(JSFILEMSG_CANNOT_FLUSH_CLOSE_FILE_ERROR, 10, 1, JSEXN_NONE, "Cannot flush closed file {0}")
55
+ MSG_DEF(JSFILEMSG_CANNOT_OPEN_WRITING_ERROR, 11, 1, JSEXN_NONE, "Cannot open file {0} for writing")
56
+ MSG_DEF(JSFILEMSG_WRITEALL_EXPECTS_ONE_ARG_ERROR, 12, 0, JSEXN_NONE, "writeAll expects one argument")
57
+ MSG_DEF(JSFILEMSG_FIRST_ARGUMENT_WRITEALL_NOT_ARRAY_ERROR, 13, 0, JSEXN_NONE, "writeAll expects an array as an argument")
58
+ MSG_DEF(JSFILEMSG_UNUSED0, 14, 0, JSEXN_NONE, "Unused error message slot")
59
+ MSG_DEF(JSFILEMSG_CANNOT_OPEN_FILE_ERROR, 15, 1, JSEXN_NONE, "Cannot open file {0}")
60
+ MSG_DEF(JSFILEMSG_FIRST_ARGUMENT_CONSTRUCTOR_NOT_STRING_ERROR, 16, 1, JSEXN_NONE, "The argument to the File constructor {0} must be a string")
61
+ MSG_DEF(JSFILEMSG_BIDIRECTIONAL_PIPE_NOT_SUPPORTED, 17, 0, JSEXN_NONE, "Bidirectional pipes are not supported")
62
+ MSG_DEF(JSFILEMSG_OPEN_MODE_NOT_SUPPORTED_WITH_PIPES, 18, 2, JSEXN_NONE, "The opening mode you have chosen {0} is not supported by the pipe you are trying to open: {1}")
63
+ MSG_DEF(JSFILEMSG_OPEN_FAILED, 19, 1, JSEXN_NONE, "open on file {0} failed")
64
+ MSG_DEF(JSFILEMSG_CLOSE_FAILED, 20, 1, JSEXN_NONE, "close on file {0} failed")
65
+ MSG_DEF(JSFILEMSG_PCLOSE_FAILED, 21, 1, JSEXN_NONE, "pclose on file {0} failed")
66
+ MSG_DEF(JSFILEMSG_REMOVE_FAILED, 22, 1, JSEXN_NONE, "remove on file {0} failed")
67
+ MSG_DEF(JSFILEMSG_CANNOT_ACCESS_FILE_STATUS, 23, 1, JSEXN_NONE, "Cannot access file status for {0}")
68
+ MSG_DEF(JSFILEMSG_RENAME_FAILED, 24, 2, JSEXN_NONE, "Cannot rename {0} to {1}")
69
+ MSG_DEF(JSFILEMSG_WRITE_FAILED, 25, 1, JSEXN_NONE, "Write failed on file {0}")
70
+ MSG_DEF(JSFILEMSG_READ_FAILED, 26, 1, JSEXN_NONE, "Read failed on file {0}")
71
+ MSG_DEF(JSFILEMSG_SKIP_FAILED, 27, 1, JSEXN_NONE, "Skip failed on file {0}")
72
+ MSG_DEF(JSFILEMSG_FIRST_ARGUMENT_MUST_BE_A_FUNCTION_OR_REGEX, 28, 1, JSEXN_NONE, "The first argument to file.list must be a function or a regex")
73
+ MSG_DEF(JSFILEMSG_CANNOT_DO_LIST_ON_A_FILE, 29, 1, JSEXN_NONE, "{0} must be a directory, cannot do list")
74
+ MSG_DEF(JSFILEMSG_NATIVE_OPERATION_IS_NOT_SUPPORTED, 30, 2, JSEXN_NONE, "Native operation {0} is not supported on {1}")
75
+ MSG_DEF(JSFILEMSG_CANNOT_SET_PRIVATE_FILE, 31, 1, JSEXN_NONE, "Cannot set private data for file {0}")
76
+ MSG_DEF(JSFILEMSG_FIRST_ARGUMENT_MUST_BE_A_NUMBER, 32, 2, JSEXN_NONE, "First argument to {0} must be a number, not {1}")
77
+ MSG_DEF(JSFILEMSG_CANNOT_WRITE, 33, 1, JSEXN_NONE, "Cannot write to {0}, file mode is different")
78
+ MSG_DEF(JSFILEMSG_CANNOT_READ, 34, 1, JSEXN_NONE, "Cannot read from {0}, file mode is different")
79
+ MSG_DEF(JSFILEMSG_CANNOT_FLUSH, 35, 1, JSEXN_NONE, "Flush failed on {0}")
80
+ MSG_DEF(JSFILEMSG_OP_FAILED, 36, 1, JSEXN_NONE, "File operation {0} failed")
81
+ MSG_DEF(JSFILEMSG_FILE_MUST_BE_OPEN, 37, 1, JSEXN_NONE, "File must be open for {0}")
82
+ MSG_DEF(JSFILEMSG_FILE_MUST_BE_CLOSED, 38, 1, JSEXN_NONE, "File must be closed for {0}")
83
+ MSG_DEF(JSFILEMSG_NO_RANDOM_ACCESS, 39, 1, JSEXN_NONE, "File {0} doesn't allow random access")
84
+ MSG_DEF(JSFILEMSG_OBJECT_CREATION_FAILED, 40, 1, JSEXN_NONE, "Couldn't create {0}")
85
+ MSG_DEF(JSFILEMSG_CANNOT_OPEN_DIR, 41, 1, JSEXN_NONE, "Couldn't open directory {0}")
86
+ MSG_DEF(JSFILEMSG_CANNOT_REPORT_POSITION, 42, 1, JSEXN_NONE, "Couldn't report position for {0}")
87
+ MSG_DEF(JSFILEMSG_CANNOT_SET_POSITION, 43, 1, JSEXN_NONE, "Couldn't set position for {0}")
88
+ MSG_DEF(JSFILEMSG_INIT_FAILED, 44, 0, JSEXN_NONE, "File class initialization failed")
89
+
90
+
@@ -0,0 +1,2634 @@
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 function support.
43
+ */
44
+ #include "jsstddef.h"
45
+ #include <string.h>
46
+ #include "jstypes.h"
47
+ #include "jsbit.h"
48
+ #include "jsutil.h" /* Added by JSIFY */
49
+ #include "jsapi.h"
50
+ #include "jsarray.h"
51
+ #include "jsatom.h"
52
+ #include "jscntxt.h"
53
+ #include "jsconfig.h"
54
+ #include "jsdbgapi.h"
55
+ #include "jsfun.h"
56
+ #include "jsgc.h"
57
+ #include "jsinterp.h"
58
+ #include "jslock.h"
59
+ #include "jsnum.h"
60
+ #include "jsobj.h"
61
+ #include "jsopcode.h"
62
+ #include "jsparse.h"
63
+ #include "jsscan.h"
64
+ #include "jsscope.h"
65
+ #include "jsscript.h"
66
+ #include "jsstr.h"
67
+ #include "jsexn.h"
68
+
69
+ #if JS_HAS_GENERATORS
70
+ # include "jsiter.h"
71
+ #endif
72
+
73
+ #if JS_HAS_XDR
74
+ # include "jsxdrapi.h"
75
+ #endif
76
+
77
+ /* Generic function/call/arguments tinyids -- also reflected bit numbers. */
78
+ enum {
79
+ CALL_ARGUMENTS = -1, /* predefined arguments local variable */
80
+ ARGS_LENGTH = -2, /* number of actual args, arity if inactive */
81
+ ARGS_CALLEE = -3, /* reference from arguments to active funobj */
82
+ FUN_ARITY = -4, /* number of formal parameters; desired argc */
83
+ FUN_NAME = -5, /* function name, "" if anonymous */
84
+ FUN_CALLER = -6 /* Function.prototype.caller, backward compat */
85
+ };
86
+
87
+ #if JSFRAME_OVERRIDE_BITS < 8
88
+ # error "not enough override bits in JSStackFrame.flags!"
89
+ #endif
90
+
91
+ #define TEST_OVERRIDE_BIT(fp, tinyid) \
92
+ ((fp)->flags & JS_BIT(JSFRAME_OVERRIDE_SHIFT - ((tinyid) + 1)))
93
+
94
+ #define SET_OVERRIDE_BIT(fp, tinyid) \
95
+ ((fp)->flags |= JS_BIT(JSFRAME_OVERRIDE_SHIFT - ((tinyid) + 1)))
96
+
97
+ JSBool
98
+ js_GetArgsValue(JSContext *cx, JSStackFrame *fp, jsval *vp)
99
+ {
100
+ JSObject *argsobj;
101
+
102
+ if (TEST_OVERRIDE_BIT(fp, CALL_ARGUMENTS)) {
103
+ JS_ASSERT(fp->callobj);
104
+ return OBJ_GET_PROPERTY(cx, fp->callobj,
105
+ ATOM_TO_JSID(cx->runtime->atomState
106
+ .argumentsAtom),
107
+ vp);
108
+ }
109
+ argsobj = js_GetArgsObject(cx, fp);
110
+ if (!argsobj)
111
+ return JS_FALSE;
112
+ *vp = OBJECT_TO_JSVAL(argsobj);
113
+ return JS_TRUE;
114
+ }
115
+
116
+ static JSBool
117
+ MarkArgDeleted(JSContext *cx, JSStackFrame *fp, uintN slot)
118
+ {
119
+ JSObject *argsobj;
120
+ jsval bmapval, bmapint;
121
+ size_t nbits, nbytes;
122
+ jsbitmap *bitmap;
123
+
124
+ argsobj = fp->argsobj;
125
+ (void) JS_GetReservedSlot(cx, argsobj, 0, &bmapval);
126
+ nbits = fp->argc;
127
+ JS_ASSERT(slot < nbits);
128
+ if (JSVAL_IS_VOID(bmapval)) {
129
+ if (nbits <= JSVAL_INT_BITS) {
130
+ bmapint = 0;
131
+ bitmap = (jsbitmap *) &bmapint;
132
+ } else {
133
+ nbytes = JS_HOWMANY(nbits, JS_BITS_PER_WORD) * sizeof(jsbitmap);
134
+ bitmap = (jsbitmap *) JS_malloc(cx, nbytes);
135
+ if (!bitmap)
136
+ return JS_FALSE;
137
+ memset(bitmap, 0, nbytes);
138
+ bmapval = PRIVATE_TO_JSVAL(bitmap);
139
+ JS_SetReservedSlot(cx, argsobj, 0, bmapval);
140
+ }
141
+ } else {
142
+ if (nbits <= JSVAL_INT_BITS) {
143
+ bmapint = JSVAL_TO_INT(bmapval);
144
+ bitmap = (jsbitmap *) &bmapint;
145
+ } else {
146
+ bitmap = (jsbitmap *) JSVAL_TO_PRIVATE(bmapval);
147
+ }
148
+ }
149
+ JS_SET_BIT(bitmap, slot);
150
+ if (bitmap == (jsbitmap *) &bmapint) {
151
+ bmapval = INT_TO_JSVAL(bmapint);
152
+ JS_SetReservedSlot(cx, argsobj, 0, bmapval);
153
+ }
154
+ return JS_TRUE;
155
+ }
156
+
157
+ /* NB: Infallible predicate, false does not mean error/exception. */
158
+ static JSBool
159
+ ArgWasDeleted(JSContext *cx, JSStackFrame *fp, uintN slot)
160
+ {
161
+ JSObject *argsobj;
162
+ jsval bmapval, bmapint;
163
+ jsbitmap *bitmap;
164
+
165
+ argsobj = fp->argsobj;
166
+ (void) JS_GetReservedSlot(cx, argsobj, 0, &bmapval);
167
+ if (JSVAL_IS_VOID(bmapval))
168
+ return JS_FALSE;
169
+ if (fp->argc <= JSVAL_INT_BITS) {
170
+ bmapint = JSVAL_TO_INT(bmapval);
171
+ bitmap = (jsbitmap *) &bmapint;
172
+ } else {
173
+ bitmap = (jsbitmap *) JSVAL_TO_PRIVATE(bmapval);
174
+ }
175
+ return JS_TEST_BIT(bitmap, slot) != 0;
176
+ }
177
+
178
+ JSBool
179
+ js_GetArgsProperty(JSContext *cx, JSStackFrame *fp, jsid id, jsval *vp)
180
+ {
181
+ jsval val;
182
+ JSObject *obj;
183
+ uintN slot;
184
+
185
+ if (TEST_OVERRIDE_BIT(fp, CALL_ARGUMENTS)) {
186
+ JS_ASSERT(fp->callobj);
187
+ if (!OBJ_GET_PROPERTY(cx, fp->callobj,
188
+ ATOM_TO_JSID(cx->runtime->atomState
189
+ .argumentsAtom),
190
+ &val)) {
191
+ return JS_FALSE;
192
+ }
193
+ if (JSVAL_IS_PRIMITIVE(val)) {
194
+ obj = js_ValueToNonNullObject(cx, val);
195
+ if (!obj)
196
+ return JS_FALSE;
197
+ } else {
198
+ obj = JSVAL_TO_OBJECT(val);
199
+ }
200
+ return OBJ_GET_PROPERTY(cx, obj, id, vp);
201
+ }
202
+
203
+ *vp = JSVAL_VOID;
204
+ if (JSID_IS_INT(id)) {
205
+ slot = (uintN) JSID_TO_INT(id);
206
+ if (slot < fp->argc) {
207
+ if (fp->argsobj && ArgWasDeleted(cx, fp, slot))
208
+ return OBJ_GET_PROPERTY(cx, fp->argsobj, id, vp);
209
+ *vp = fp->argv[slot];
210
+ } else {
211
+ /*
212
+ * Per ECMA-262 Ed. 3, 10.1.8, last bulleted item, do not share
213
+ * storage between the formal parameter and arguments[k] for all
214
+ * fp->argc <= k && k < fp->fun->nargs. For example, in
215
+ *
216
+ * function f(x) { x = 42; return arguments[0]; }
217
+ * f();
218
+ *
219
+ * the call to f should return undefined, not 42. If fp->argsobj
220
+ * is null at this point, as it would be in the example, return
221
+ * undefined in *vp.
222
+ */
223
+ if (fp->argsobj)
224
+ return OBJ_GET_PROPERTY(cx, fp->argsobj, id, vp);
225
+ }
226
+ } else {
227
+ if (id == ATOM_TO_JSID(cx->runtime->atomState.lengthAtom)) {
228
+ if (fp->argsobj && TEST_OVERRIDE_BIT(fp, ARGS_LENGTH))
229
+ return OBJ_GET_PROPERTY(cx, fp->argsobj, id, vp);
230
+ *vp = INT_TO_JSVAL((jsint) fp->argc);
231
+ }
232
+ }
233
+ return JS_TRUE;
234
+ }
235
+
236
+ JSObject *
237
+ js_GetArgsObject(JSContext *cx, JSStackFrame *fp)
238
+ {
239
+ JSObject *argsobj, *global, *parent;
240
+
241
+ /*
242
+ * We must be in a function activation; the function must be lightweight
243
+ * or else fp must have a variable object.
244
+ */
245
+ JS_ASSERT(fp->fun && (!(fp->fun->flags & JSFUN_HEAVYWEIGHT) || fp->varobj));
246
+
247
+ /* Skip eval and debugger frames. */
248
+ while (fp->flags & JSFRAME_SPECIAL)
249
+ fp = fp->down;
250
+
251
+ /* Create an arguments object for fp only if it lacks one. */
252
+ argsobj = fp->argsobj;
253
+ if (argsobj)
254
+ return argsobj;
255
+
256
+ /* Link the new object to fp so it can get actual argument values. */
257
+ argsobj = js_NewObject(cx, &js_ArgumentsClass, NULL, NULL, 0);
258
+ if (!argsobj || !JS_SetPrivate(cx, argsobj, fp)) {
259
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL;
260
+ return NULL;
261
+ }
262
+
263
+ /*
264
+ * Give arguments an intrinsic scope chain link to fp's global object.
265
+ * Since the arguments object lacks a prototype because js_ArgumentsClass
266
+ * is not initialized, js_NewObject won't assign a default parent to it.
267
+ *
268
+ * Therefore if arguments is used as the head of an eval scope chain (via
269
+ * a direct or indirect call to eval(program, arguments)), any reference
270
+ * to a standard class object in the program will fail to resolve due to
271
+ * js_GetClassPrototype not being able to find a global object containing
272
+ * the standard prototype by starting from arguments and following parent.
273
+ */
274
+ global = fp->scopeChain;
275
+ while ((parent = OBJ_GET_PARENT(cx, global)) != NULL)
276
+ global = parent;
277
+ STOBJ_SET_PARENT(argsobj, global);
278
+ fp->argsobj = argsobj;
279
+ return argsobj;
280
+ }
281
+
282
+ static JSBool
283
+ args_enumerate(JSContext *cx, JSObject *obj);
284
+
285
+ JS_FRIEND_API(JSBool)
286
+ js_PutArgsObject(JSContext *cx, JSStackFrame *fp)
287
+ {
288
+ JSObject *argsobj;
289
+ jsval bmapval, rval;
290
+ JSBool ok;
291
+ JSRuntime *rt;
292
+
293
+ /*
294
+ * Reuse args_enumerate here to reflect fp's actual arguments as indexed
295
+ * elements of argsobj. Do this first, before clearing and freeing the
296
+ * deleted argument slot bitmap, because args_enumerate depends on that.
297
+ */
298
+ argsobj = fp->argsobj;
299
+ ok = args_enumerate(cx, argsobj);
300
+
301
+ /*
302
+ * Now clear the deleted argument number bitmap slot and free the bitmap,
303
+ * if one was actually created due to 'delete arguments[0]' or similar.
304
+ */
305
+ (void) JS_GetReservedSlot(cx, argsobj, 0, &bmapval);
306
+ if (!JSVAL_IS_VOID(bmapval)) {
307
+ JS_SetReservedSlot(cx, argsobj, 0, JSVAL_VOID);
308
+ if (fp->argc > JSVAL_INT_BITS)
309
+ JS_free(cx, JSVAL_TO_PRIVATE(bmapval));
310
+ }
311
+
312
+ /*
313
+ * Now get the prototype properties so we snapshot fp->fun and fp->argc
314
+ * before fp goes away.
315
+ */
316
+ rt = cx->runtime;
317
+ ok &= js_GetProperty(cx, argsobj, ATOM_TO_JSID(rt->atomState.calleeAtom),
318
+ &rval);
319
+ ok &= js_SetProperty(cx, argsobj, ATOM_TO_JSID(rt->atomState.calleeAtom),
320
+ &rval);
321
+ ok &= js_GetProperty(cx, argsobj, ATOM_TO_JSID(rt->atomState.lengthAtom),
322
+ &rval);
323
+ ok &= js_SetProperty(cx, argsobj, ATOM_TO_JSID(rt->atomState.lengthAtom),
324
+ &rval);
325
+
326
+ /*
327
+ * Clear the private pointer to fp, which is about to go away (js_Invoke).
328
+ * Do this last because the args_enumerate and js_GetProperty calls above
329
+ * need to follow the private slot to find fp.
330
+ */
331
+ ok &= JS_SetPrivate(cx, argsobj, NULL);
332
+ fp->argsobj = NULL;
333
+ return ok;
334
+ }
335
+
336
+ static JSBool
337
+ args_delProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
338
+ {
339
+ jsint slot;
340
+ JSStackFrame *fp;
341
+
342
+ if (!JSVAL_IS_INT(id))
343
+ return JS_TRUE;
344
+ fp = (JSStackFrame *)
345
+ JS_GetInstancePrivate(cx, obj, &js_ArgumentsClass, NULL);
346
+ if (!fp)
347
+ return JS_TRUE;
348
+ JS_ASSERT(fp->argsobj);
349
+
350
+ slot = JSVAL_TO_INT(id);
351
+ switch (slot) {
352
+ case ARGS_CALLEE:
353
+ case ARGS_LENGTH:
354
+ SET_OVERRIDE_BIT(fp, slot);
355
+ break;
356
+
357
+ default:
358
+ if ((uintN)slot < fp->argc && !MarkArgDeleted(cx, fp, slot))
359
+ return JS_FALSE;
360
+ break;
361
+ }
362
+ return JS_TRUE;
363
+ }
364
+
365
+ static JSBool
366
+ args_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
367
+ {
368
+ jsint slot;
369
+ JSStackFrame *fp;
370
+
371
+ if (!JSVAL_IS_INT(id))
372
+ return JS_TRUE;
373
+ fp = (JSStackFrame *)
374
+ JS_GetInstancePrivate(cx, obj, &js_ArgumentsClass, NULL);
375
+ if (!fp)
376
+ return JS_TRUE;
377
+ JS_ASSERT(fp->argsobj);
378
+
379
+ slot = JSVAL_TO_INT(id);
380
+ switch (slot) {
381
+ case ARGS_CALLEE:
382
+ if (!TEST_OVERRIDE_BIT(fp, slot))
383
+ *vp = OBJECT_TO_JSVAL(fp->callee);
384
+ break;
385
+
386
+ case ARGS_LENGTH:
387
+ if (!TEST_OVERRIDE_BIT(fp, slot))
388
+ *vp = INT_TO_JSVAL((jsint)fp->argc);
389
+ break;
390
+
391
+ default:
392
+ if ((uintN)slot < fp->argc && !ArgWasDeleted(cx, fp, slot))
393
+ *vp = fp->argv[slot];
394
+ break;
395
+ }
396
+ return JS_TRUE;
397
+ }
398
+
399
+ static JSBool
400
+ args_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
401
+ {
402
+ JSStackFrame *fp;
403
+ jsint slot;
404
+
405
+ if (!JSVAL_IS_INT(id))
406
+ return JS_TRUE;
407
+ fp = (JSStackFrame *)
408
+ JS_GetInstancePrivate(cx, obj, &js_ArgumentsClass, NULL);
409
+ if (!fp)
410
+ return JS_TRUE;
411
+ JS_ASSERT(fp->argsobj);
412
+
413
+ slot = JSVAL_TO_INT(id);
414
+ switch (slot) {
415
+ case ARGS_CALLEE:
416
+ case ARGS_LENGTH:
417
+ SET_OVERRIDE_BIT(fp, slot);
418
+ break;
419
+
420
+ default:
421
+ if (FUN_INTERPRETED(fp->fun) &&
422
+ (uintN)slot < fp->argc &&
423
+ !ArgWasDeleted(cx, fp, slot)) {
424
+ fp->argv[slot] = *vp;
425
+ }
426
+ break;
427
+ }
428
+ return JS_TRUE;
429
+ }
430
+
431
+ static JSBool
432
+ args_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
433
+ JSObject **objp)
434
+ {
435
+ JSStackFrame *fp;
436
+ uintN slot;
437
+ JSString *str;
438
+ JSAtom *atom;
439
+ intN tinyid;
440
+ jsval value;
441
+
442
+ *objp = NULL;
443
+ fp = (JSStackFrame *)
444
+ JS_GetInstancePrivate(cx, obj, &js_ArgumentsClass, NULL);
445
+ if (!fp)
446
+ return JS_TRUE;
447
+ JS_ASSERT(fp->argsobj);
448
+
449
+ if (JSVAL_IS_INT(id)) {
450
+ slot = JSVAL_TO_INT(id);
451
+ if (slot < fp->argc && !ArgWasDeleted(cx, fp, slot)) {
452
+ /* XXX ECMA specs DontEnum, contrary to other array-like objects */
453
+ if (!js_DefineProperty(cx, obj, INT_JSVAL_TO_JSID(id),
454
+ fp->argv[slot],
455
+ args_getProperty, args_setProperty,
456
+ 0, NULL)) {
457
+ return JS_FALSE;
458
+ }
459
+ *objp = obj;
460
+ }
461
+ } else {
462
+ str = JSVAL_TO_STRING(id);
463
+ atom = cx->runtime->atomState.lengthAtom;
464
+ if (str == ATOM_TO_STRING(atom)) {
465
+ tinyid = ARGS_LENGTH;
466
+ value = INT_TO_JSVAL(fp->argc);
467
+ } else {
468
+ atom = cx->runtime->atomState.calleeAtom;
469
+ if (str == ATOM_TO_STRING(atom)) {
470
+ tinyid = ARGS_CALLEE;
471
+ value = OBJECT_TO_JSVAL(fp->callee);
472
+ } else {
473
+ atom = NULL;
474
+
475
+ /* Quell GCC overwarnings. */
476
+ tinyid = 0;
477
+ value = JSVAL_NULL;
478
+ }
479
+ }
480
+
481
+ if (atom && !TEST_OVERRIDE_BIT(fp, tinyid)) {
482
+ if (!js_DefineNativeProperty(cx, obj, ATOM_TO_JSID(atom), value,
483
+ args_getProperty, args_setProperty, 0,
484
+ SPROP_HAS_SHORTID, tinyid, NULL)) {
485
+ return JS_FALSE;
486
+ }
487
+ *objp = obj;
488
+ }
489
+ }
490
+
491
+ return JS_TRUE;
492
+ }
493
+
494
+ static JSBool
495
+ args_enumerate(JSContext *cx, JSObject *obj)
496
+ {
497
+ JSStackFrame *fp;
498
+ JSObject *pobj;
499
+ JSProperty *prop;
500
+ uintN slot, argc;
501
+
502
+ fp = (JSStackFrame *)
503
+ JS_GetInstancePrivate(cx, obj, &js_ArgumentsClass, NULL);
504
+ if (!fp)
505
+ return JS_TRUE;
506
+ JS_ASSERT(fp->argsobj);
507
+
508
+ /*
509
+ * Trigger reflection with value snapshot in args_resolve using a series
510
+ * of js_LookupProperty calls. We handle length, callee, and the indexed
511
+ * argument properties. We know that args_resolve covers all these cases
512
+ * and creates direct properties of obj, but that it may fail to resolve
513
+ * length or callee if overridden.
514
+ */
515
+ if (!js_LookupProperty(cx, obj,
516
+ ATOM_TO_JSID(cx->runtime->atomState.lengthAtom),
517
+ &pobj, &prop)) {
518
+ return JS_FALSE;
519
+ }
520
+ if (prop)
521
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
522
+
523
+ if (!js_LookupProperty(cx, obj,
524
+ ATOM_TO_JSID(cx->runtime->atomState.calleeAtom),
525
+ &pobj, &prop)) {
526
+ return JS_FALSE;
527
+ }
528
+ if (prop)
529
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
530
+
531
+ argc = fp->argc;
532
+ for (slot = 0; slot < argc; slot++) {
533
+ if (!js_LookupProperty(cx, obj, INT_TO_JSID((jsint)slot), &pobj, &prop))
534
+ return JS_FALSE;
535
+ if (prop)
536
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
537
+ }
538
+ return JS_TRUE;
539
+ }
540
+
541
+ #if JS_HAS_GENERATORS
542
+ /*
543
+ * If a generator-iterator's arguments or call object escapes, it needs to
544
+ * mark its generator object.
545
+ */
546
+ static void
547
+ args_or_call_trace(JSTracer *trc, JSObject *obj)
548
+ {
549
+ JSStackFrame *fp;
550
+
551
+ fp = (JSStackFrame *) JS_GetPrivate(trc->context, obj);
552
+ if (fp && (fp->flags & JSFRAME_GENERATOR)) {
553
+ JS_CALL_OBJECT_TRACER(trc, FRAME_TO_GENERATOR(fp)->obj,
554
+ "FRAME_TO_GENERATOR(fp)->obj");
555
+ }
556
+ }
557
+ #else
558
+ # define args_or_call_trace NULL
559
+ #endif
560
+
561
+ /*
562
+ * The Arguments class is not initialized via JS_InitClass, and must not be,
563
+ * because its name is "Object". Per ECMA, that causes instances of it to
564
+ * delegate to the object named by Object.prototype. It also ensures that
565
+ * arguments.toString() returns "[object Object]".
566
+ *
567
+ * The JSClass functions below collaborate to lazily reflect and synchronize
568
+ * actual argument values, argument count, and callee function object stored
569
+ * in a JSStackFrame with their corresponding property values in the frame's
570
+ * arguments object.
571
+ */
572
+ JSClass js_ArgumentsClass = {
573
+ js_Object_str,
574
+ JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_HAS_RESERVED_SLOTS(1) |
575
+ JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Object),
576
+ JS_PropertyStub, args_delProperty,
577
+ args_getProperty, args_setProperty,
578
+ args_enumerate, (JSResolveOp) args_resolve,
579
+ JS_ConvertStub, JS_FinalizeStub,
580
+ NULL, NULL,
581
+ NULL, NULL,
582
+ NULL, NULL,
583
+ JS_CLASS_TRACE(args_or_call_trace), NULL
584
+ };
585
+
586
+ JSObject *
587
+ js_GetCallObject(JSContext *cx, JSStackFrame *fp, JSObject *parent)
588
+ {
589
+ JSObject *callobj, *funobj;
590
+
591
+ /* Create a call object for fp only if it lacks one. */
592
+ JS_ASSERT(fp->fun);
593
+ callobj = fp->callobj;
594
+ if (callobj)
595
+ return callobj;
596
+
597
+ /* The default call parent is its function's parent (static link). */
598
+ if (!parent) {
599
+ funobj = fp->callee;
600
+ if (funobj)
601
+ parent = OBJ_GET_PARENT(cx, funobj);
602
+ }
603
+
604
+ /* Create the call object and link it to its stack frame. */
605
+ callobj = js_NewObject(cx, &js_CallClass, NULL, parent, 0);
606
+ if (!callobj || !JS_SetPrivate(cx, callobj, fp)) {
607
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL;
608
+ return NULL;
609
+ }
610
+ fp->callobj = callobj;
611
+
612
+ /* Make callobj be the scope chain and the variables object. */
613
+ JS_ASSERT(fp->scopeChain == parent);
614
+ fp->scopeChain = callobj;
615
+ fp->varobj = callobj;
616
+ return callobj;
617
+ }
618
+
619
+ static JSBool
620
+ call_enumerate(JSContext *cx, JSObject *obj);
621
+
622
+ JS_FRIEND_API(JSBool)
623
+ js_PutCallObject(JSContext *cx, JSStackFrame *fp)
624
+ {
625
+ JSObject *callobj;
626
+ JSBool ok;
627
+ jsid argsid;
628
+ jsval aval;
629
+
630
+ /*
631
+ * Reuse call_enumerate here to reflect all actual args and vars into the
632
+ * call object from fp.
633
+ */
634
+ callobj = fp->callobj;
635
+ if (!callobj)
636
+ return JS_TRUE;
637
+ ok = call_enumerate(cx, callobj);
638
+
639
+ /*
640
+ * Get the arguments object to snapshot fp's actual argument values.
641
+ */
642
+ if (fp->argsobj) {
643
+ if (!TEST_OVERRIDE_BIT(fp, CALL_ARGUMENTS)) {
644
+ argsid = ATOM_TO_JSID(cx->runtime->atomState.argumentsAtom);
645
+ aval = OBJECT_TO_JSVAL(fp->argsobj);
646
+ ok &= js_SetProperty(cx, callobj, argsid, &aval);
647
+ }
648
+ ok &= js_PutArgsObject(cx, fp);
649
+ }
650
+
651
+ /*
652
+ * Clear the private pointer to fp, which is about to go away (js_Invoke).
653
+ * Do this last because the call_enumerate and js_GetProperty calls above
654
+ * need to follow the private slot to find fp.
655
+ */
656
+ ok &= JS_SetPrivate(cx, callobj, NULL);
657
+ fp->callobj = NULL;
658
+ return ok;
659
+ }
660
+
661
+ static JSBool
662
+ call_enumerate(JSContext *cx, JSObject *obj)
663
+ {
664
+ JSStackFrame *fp;
665
+ JSFunction *fun;
666
+ uintN n, i, slot;
667
+ void *mark;
668
+ jsuword *names;
669
+ JSBool ok;
670
+ JSAtom *name;
671
+ JSObject *pobj;
672
+ JSProperty *prop;
673
+ jsval v;
674
+
675
+ fp = (JSStackFrame *) JS_GetPrivate(cx, obj);
676
+ if (!fp)
677
+ return JS_TRUE;
678
+ JS_ASSERT(GET_FUNCTION_PRIVATE(cx, fp->callee) == fp->fun);
679
+
680
+ /*
681
+ * Reflect actual args from fp->argv for formal parameters, and local vars
682
+ * and functions in fp->vars for declared variables and nested-at-top-level
683
+ * local functions.
684
+ */
685
+ fun = fp->fun;
686
+ n = JS_GET_LOCAL_NAME_COUNT(fun);
687
+ if (n == 0)
688
+ return JS_TRUE;
689
+
690
+ mark = JS_ARENA_MARK(&cx->tempPool);
691
+
692
+ /* From this point the control must flow through the label out. */
693
+ names = js_GetLocalNameArray(cx, fun, &cx->tempPool);
694
+ if (!names) {
695
+ ok = JS_FALSE;
696
+ goto out;
697
+ }
698
+
699
+ for (i = 0; i != n; ++i) {
700
+ name = JS_LOCAL_NAME_TO_ATOM(names[i]);
701
+ if (!name)
702
+ continue;
703
+
704
+ /*
705
+ * Trigger reflection by looking up the name of the argument or
706
+ * variable.
707
+ */
708
+ ok = js_LookupProperty(cx, obj, ATOM_TO_JSID(name), &pobj, &prop);
709
+ if (!ok)
710
+ goto out;
711
+
712
+ /*
713
+ * At this point the call object always has a property corresponding
714
+ * to the local name because call_resolve creates the property using
715
+ * JSPROP_PERMANENT.
716
+ */
717
+ JS_ASSERT(prop && pobj == obj);
718
+ slot = ((JSScopeProperty *) prop)->slot;
719
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
720
+
721
+ v = (i < fun->nargs) ? fp->argv[i] : fp->vars[i - fun->nargs];
722
+ LOCKED_OBJ_SET_SLOT(obj, slot, v);
723
+ }
724
+ ok = JS_TRUE;
725
+
726
+ out:
727
+ JS_ARENA_RELEASE(&cx->tempPool, mark);
728
+ return ok;
729
+ }
730
+
731
+ typedef enum JSCallPropertyKind {
732
+ JSCPK_ARGUMENTS,
733
+ JSCPK_ARG,
734
+ JSCPK_VAR
735
+ } JSCallPropertyKind;
736
+
737
+ static JSBool
738
+ CallPropertyOp(JSContext *cx, JSObject *obj, jsid id, jsval *vp,
739
+ JSCallPropertyKind kind, JSBool setter)
740
+ {
741
+ JSStackFrame *fp;
742
+ JSFunction *fun;
743
+ uintN i;
744
+ jsval *array;
745
+
746
+ fp = (JSStackFrame *) JS_GetPrivate(cx, obj);
747
+ if (!fp)
748
+ return JS_TRUE;
749
+ fun = fp->fun;
750
+ JS_ASSERT(fun && FUN_INTERPRETED(fun));
751
+
752
+ if (kind == JSCPK_ARGUMENTS) {
753
+ if (setter) {
754
+ SET_OVERRIDE_BIT(fp, CALL_ARGUMENTS);
755
+ } else if (!TEST_OVERRIDE_BIT(fp, CALL_ARGUMENTS)) {
756
+ JSObject *argsobj;
757
+
758
+ argsobj = js_GetArgsObject(cx, fp);
759
+ if (!argsobj)
760
+ return JS_FALSE;
761
+ *vp = OBJECT_TO_JSVAL(argsobj);
762
+ }
763
+ return JS_TRUE;
764
+ }
765
+
766
+ JS_ASSERT((int16) JSVAL_TO_INT(id) == JSVAL_TO_INT(id));
767
+ i = (uint16) JSVAL_TO_INT(id);
768
+ JS_ASSERT_IF(kind == JSCPK_ARG, i < fun->nargs);
769
+ JS_ASSERT_IF(kind == JSCPK_VAR, i < fun->u.i.nvars);
770
+
771
+ JS_ASSERT(fun->u.i.nvars == fp->nvars);
772
+ if (kind == JSCPK_ARG) {
773
+ array = fp->argv;
774
+ } else {
775
+ JS_ASSERT(kind == JSCPK_VAR);
776
+ array = fp->vars;
777
+ }
778
+ if (setter)
779
+ array[i] = *vp;
780
+ else
781
+ *vp = array[i];
782
+ return JS_TRUE;
783
+ }
784
+
785
+ static JSBool
786
+ GetCallArguments(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
787
+ {
788
+ return CallPropertyOp(cx, obj, id, vp, JSCPK_ARGUMENTS, JS_FALSE);
789
+ }
790
+
791
+ static JSBool
792
+ SetCallArguments(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
793
+ {
794
+ return CallPropertyOp(cx, obj, id, vp, JSCPK_ARGUMENTS, JS_TRUE);
795
+ }
796
+
797
+ JSBool
798
+ js_GetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
799
+ {
800
+ return CallPropertyOp(cx, obj, id, vp, JSCPK_ARG, JS_FALSE);
801
+ }
802
+
803
+ static JSBool
804
+ SetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
805
+ {
806
+ return CallPropertyOp(cx, obj, id, vp, JSCPK_ARG, JS_TRUE);
807
+ }
808
+
809
+ JSBool
810
+ js_GetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
811
+ {
812
+ return CallPropertyOp(cx, obj, id, vp, JSCPK_VAR, JS_FALSE);
813
+ }
814
+
815
+ static JSBool
816
+ SetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
817
+ {
818
+ return CallPropertyOp(cx, obj, id, vp, JSCPK_VAR, JS_TRUE);
819
+ }
820
+
821
+ static JSBool
822
+ call_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags,
823
+ JSObject **objp)
824
+ {
825
+ JSStackFrame *fp;
826
+ JSFunction *fun;
827
+ jsid id;
828
+ JSLocalKind localKind;
829
+ JSPropertyOp getter, setter;
830
+ uintN slot, attrs;
831
+ jsval *vp;
832
+
833
+ fp = (JSStackFrame *) JS_GetPrivate(cx, obj);
834
+ if (!fp)
835
+ return JS_TRUE;
836
+ fun = fp->fun;
837
+ JS_ASSERT(fun);
838
+ JS_ASSERT(GET_FUNCTION_PRIVATE(cx, fp->callee) == fun);
839
+
840
+ if (!JSVAL_IS_STRING(idval))
841
+ return JS_TRUE;
842
+
843
+ if (!js_ValueToStringId(cx, idval, &id))
844
+ return JS_FALSE;
845
+
846
+ localKind = js_LookupLocal(cx, fun, JSID_TO_ATOM(id), &slot);
847
+ if (localKind != JSLOCAL_NONE) {
848
+ JS_ASSERT((uint16) slot == slot);
849
+ if (localKind == JSLOCAL_ARG) {
850
+ JS_ASSERT(slot < fun->nargs);
851
+ vp = fp->argv;
852
+ getter = js_GetCallArg;
853
+ setter = SetCallArg;
854
+ attrs = JSPROP_PERMANENT;
855
+ } else {
856
+ JS_ASSERT(localKind == JSLOCAL_VAR || localKind == JSLOCAL_CONST);
857
+ JS_ASSERT(fun->u.i.nvars == fp->nvars);
858
+ JS_ASSERT(slot < fun->u.i.nvars);
859
+ vp = fp->vars;
860
+ getter = js_GetCallVar;
861
+ setter = SetCallVar;
862
+ attrs = (localKind == JSLOCAL_CONST)
863
+ ? JSPROP_PERMANENT | JSPROP_READONLY
864
+ : JSPROP_PERMANENT;
865
+ }
866
+ if (!js_DefineNativeProperty(cx, obj, id, vp[slot], getter, setter,
867
+ attrs, SPROP_HAS_SHORTID, (int16) slot,
868
+ NULL)) {
869
+ return JS_FALSE;
870
+ }
871
+ *objp = obj;
872
+ return JS_TRUE;
873
+ }
874
+
875
+ /*
876
+ * Resolve arguments so that we never store a particular Call object's
877
+ * arguments object reference in a Call prototype's |arguments| slot.
878
+ */
879
+ if (id == ATOM_TO_JSID(cx->runtime->atomState.argumentsAtom)) {
880
+ if (!js_DefineNativeProperty(cx, obj, id, JSVAL_VOID,
881
+ GetCallArguments, SetCallArguments,
882
+ JSPROP_PERMANENT, 0, 0, NULL)) {
883
+ return JS_FALSE;
884
+ }
885
+ *objp = obj;
886
+ return JS_TRUE;
887
+ }
888
+ return JS_TRUE;
889
+ }
890
+
891
+ static JSBool
892
+ call_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
893
+ {
894
+ JSStackFrame *fp;
895
+
896
+ if (type == JSTYPE_FUNCTION) {
897
+ fp = (JSStackFrame *) JS_GetPrivate(cx, obj);
898
+ if (fp) {
899
+ JS_ASSERT(fp->fun);
900
+ *vp = OBJECT_TO_JSVAL(fp->callee);
901
+ }
902
+ }
903
+ return JS_TRUE;
904
+ }
905
+
906
+ JS_FRIEND_DATA(JSClass) js_CallClass = {
907
+ js_Call_str,
908
+ JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_IS_ANONYMOUS |
909
+ JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Call),
910
+ JS_PropertyStub, JS_PropertyStub,
911
+ JS_PropertyStub, JS_PropertyStub,
912
+ call_enumerate, (JSResolveOp)call_resolve,
913
+ call_convert, JS_FinalizeStub,
914
+ NULL, NULL,
915
+ NULL, NULL,
916
+ NULL, NULL,
917
+ JS_CLASS_TRACE(args_or_call_trace), NULL,
918
+ };
919
+
920
+ /*
921
+ * ECMA-262 specifies that length is a property of function object instances,
922
+ * but we can avoid that space cost by delegating to a prototype property that
923
+ * is JSPROP_PERMANENT and JSPROP_SHARED. Each fun_getProperty call computes
924
+ * a fresh length value based on the arity of the individual function object's
925
+ * private data.
926
+ *
927
+ * The extensions below other than length, i.e., the ones not in ECMA-262,
928
+ * are neither JSPROP_READONLY nor JSPROP_SHARED, because for compatibility
929
+ * with ECMA we must allow a delegating object to override them. Therefore to
930
+ * avoid entraining garbage in Function.prototype slots, they must be resolved
931
+ * in non-prototype function objects, wherefore the lazy_function_props table
932
+ * and fun_resolve's use of it.
933
+ */
934
+ #define LENGTH_PROP_ATTRS (JSPROP_READONLY|JSPROP_PERMANENT|JSPROP_SHARED)
935
+
936
+ static JSPropertySpec function_props[] = {
937
+ {js_length_str, ARGS_LENGTH, LENGTH_PROP_ATTRS, 0,0},
938
+ {0,0,0,0,0}
939
+ };
940
+
941
+ typedef struct LazyFunctionProp {
942
+ uint16 atomOffset;
943
+ int8 tinyid;
944
+ uint8 attrs;
945
+ } LazyFunctionProp;
946
+
947
+ /* NB: no sentinel at the end -- use JS_ARRAY_LENGTH to bound loops. */
948
+ static LazyFunctionProp lazy_function_props[] = {
949
+ {ATOM_OFFSET(arguments), CALL_ARGUMENTS, JSPROP_PERMANENT},
950
+ {ATOM_OFFSET(arity), FUN_ARITY, JSPROP_PERMANENT},
951
+ {ATOM_OFFSET(caller), FUN_CALLER, JSPROP_PERMANENT},
952
+ {ATOM_OFFSET(name), FUN_NAME, JSPROP_PERMANENT},
953
+ };
954
+
955
+ static JSBool
956
+ fun_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
957
+ {
958
+ jsint slot;
959
+ JSFunction *fun;
960
+ JSStackFrame *fp;
961
+
962
+ if (!JSVAL_IS_INT(id))
963
+ return JS_TRUE;
964
+ slot = JSVAL_TO_INT(id);
965
+
966
+ /*
967
+ * Loop because getter and setter can be delegated from another class,
968
+ * but loop only for ARGS_LENGTH because we must pretend that f.length
969
+ * is in each function instance f, per ECMA-262, instead of only in the
970
+ * Function.prototype object (we use JSPROP_PERMANENT with JSPROP_SHARED
971
+ * to make it appear so).
972
+ *
973
+ * This code couples tightly to the attributes for the function_props[]
974
+ * initializers above, and to js_SetProperty and js_HasOwnPropertyHelper.
975
+ *
976
+ * It's important to allow delegating objects, even though they inherit
977
+ * this getter (fun_getProperty), to override arguments, arity, caller,
978
+ * and name. If we didn't return early for slot != ARGS_LENGTH, we would
979
+ * clobber *vp with the native property value, instead of letting script
980
+ * override that value in delegating objects.
981
+ *
982
+ * Note how that clobbering is what simulates JSPROP_READONLY for all of
983
+ * the non-standard properties when the directly addressed object (obj)
984
+ * is a function object (i.e., when this loop does not iterate).
985
+ */
986
+ while (!(fun = (JSFunction *)
987
+ JS_GetInstancePrivate(cx, obj, &js_FunctionClass, NULL))) {
988
+ if (slot != ARGS_LENGTH)
989
+ return JS_TRUE;
990
+ obj = OBJ_GET_PROTO(cx, obj);
991
+ if (!obj)
992
+ return JS_TRUE;
993
+ }
994
+
995
+ /* Find fun's top-most activation record. */
996
+ for (fp = cx->fp; fp && (fp->fun != fun || (fp->flags & JSFRAME_SPECIAL));
997
+ fp = fp->down) {
998
+ continue;
999
+ }
1000
+
1001
+ switch (slot) {
1002
+ case CALL_ARGUMENTS:
1003
+ /* Warn if strict about f.arguments or equivalent unqualified uses. */
1004
+ if (!JS_ReportErrorFlagsAndNumber(cx,
1005
+ JSREPORT_WARNING | JSREPORT_STRICT,
1006
+ js_GetErrorMessage, NULL,
1007
+ JSMSG_DEPRECATED_USAGE,
1008
+ js_arguments_str)) {
1009
+ return JS_FALSE;
1010
+ }
1011
+ if (fp) {
1012
+ if (!js_GetArgsValue(cx, fp, vp))
1013
+ return JS_FALSE;
1014
+ } else {
1015
+ *vp = JSVAL_NULL;
1016
+ }
1017
+ break;
1018
+
1019
+ case ARGS_LENGTH:
1020
+ case FUN_ARITY:
1021
+ *vp = INT_TO_JSVAL((jsint)fun->nargs);
1022
+ break;
1023
+
1024
+ case FUN_NAME:
1025
+ *vp = fun->atom
1026
+ ? ATOM_KEY(fun->atom)
1027
+ : STRING_TO_JSVAL(cx->runtime->emptyString);
1028
+ break;
1029
+
1030
+ case FUN_CALLER:
1031
+ if (fp && fp->down && fp->down->fun)
1032
+ *vp = OBJECT_TO_JSVAL(fp->down->callee);
1033
+ else
1034
+ *vp = JSVAL_NULL;
1035
+ if (!JSVAL_IS_PRIMITIVE(*vp) && cx->runtime->checkObjectAccess) {
1036
+ id = ATOM_KEY(cx->runtime->atomState.callerAtom);
1037
+ if (!cx->runtime->checkObjectAccess(cx, obj, id, JSACC_READ, vp))
1038
+ return JS_FALSE;
1039
+ }
1040
+ break;
1041
+
1042
+ default:
1043
+ /* XXX fun[0] and fun.arguments[0] are equivalent. */
1044
+ if (fp && fp->fun && (uintN)slot < fp->fun->nargs)
1045
+ *vp = fp->argv[slot];
1046
+ break;
1047
+ }
1048
+
1049
+ return JS_TRUE;
1050
+ }
1051
+
1052
+ static JSBool
1053
+ fun_enumerate(JSContext *cx, JSObject *obj)
1054
+ {
1055
+ jsid prototypeId;
1056
+ JSObject *pobj;
1057
+ JSProperty *prop;
1058
+
1059
+ prototypeId = ATOM_TO_JSID(cx->runtime->atomState.classPrototypeAtom);
1060
+ if (!OBJ_LOOKUP_PROPERTY(cx, obj, prototypeId, &pobj, &prop))
1061
+ return JS_FALSE;
1062
+ if (prop)
1063
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
1064
+ return JS_TRUE;
1065
+ }
1066
+
1067
+ static JSBool
1068
+ fun_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
1069
+ JSObject **objp)
1070
+ {
1071
+ JSFunction *fun;
1072
+ JSAtom *atom;
1073
+ uintN i;
1074
+
1075
+ if (!JSVAL_IS_STRING(id))
1076
+ return JS_TRUE;
1077
+
1078
+ fun = GET_FUNCTION_PRIVATE(cx, obj);
1079
+
1080
+ /*
1081
+ * No need to reflect fun.prototype in 'fun.prototype = ... '.
1082
+ *
1083
+ * This is not just an optimization, because we must not resolve when
1084
+ * defining hidden properties during compilation. The setup code for the
1085
+ * prototype and the lazy properties below eventually calls the property
1086
+ * hooks for the function object. That in turn calls fun_reserveSlots to
1087
+ * get the number of the reserved slots which is just the number of
1088
+ * regular expressions literals in the function. When compiling, that
1089
+ * number is not yet ready so we must make sure that fun_resolve does
1090
+ * nothing until the code for the function is generated.
1091
+ */
1092
+ if (flags & JSRESOLVE_ASSIGNING)
1093
+ return JS_TRUE;
1094
+
1095
+ /*
1096
+ * Ok, check whether id is 'prototype' and bootstrap the function object's
1097
+ * prototype property.
1098
+ */
1099
+ atom = cx->runtime->atomState.classPrototypeAtom;
1100
+ if (id == ATOM_KEY(atom)) {
1101
+ JSObject *proto;
1102
+
1103
+ /*
1104
+ * Beware of the wacky case of a user function named Object -- trying
1105
+ * to find a prototype for that will recur back here _ad perniciem_.
1106
+ */
1107
+ if (fun->atom == CLASS_ATOM(cx, Object))
1108
+ return JS_TRUE;
1109
+
1110
+ /*
1111
+ * Make the prototype object to have the same parent as the function
1112
+ * object itself.
1113
+ */
1114
+ proto = js_NewObject(cx, &js_ObjectClass, NULL, OBJ_GET_PARENT(cx, obj),
1115
+ 0);
1116
+ if (!proto)
1117
+ return JS_FALSE;
1118
+
1119
+ /*
1120
+ * ECMA (15.3.5.2) says that constructor.prototype is DontDelete for
1121
+ * user-defined functions, but DontEnum | ReadOnly | DontDelete for
1122
+ * native "system" constructors such as Object or Function. So lazily
1123
+ * set the former here in fun_resolve, but eagerly define the latter
1124
+ * in JS_InitClass, with the right attributes.
1125
+ */
1126
+ if (!js_SetClassPrototype(cx, obj, proto,
1127
+ JSPROP_ENUMERATE | JSPROP_PERMANENT)) {
1128
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL;
1129
+ return JS_FALSE;
1130
+ }
1131
+ *objp = obj;
1132
+ return JS_TRUE;
1133
+ }
1134
+
1135
+ for (i = 0; i < JS_ARRAY_LENGTH(lazy_function_props); i++) {
1136
+ LazyFunctionProp *lfp = &lazy_function_props[i];
1137
+
1138
+ atom = OFFSET_TO_ATOM(cx->runtime, lfp->atomOffset);
1139
+ if (id == ATOM_KEY(atom)) {
1140
+ if (!js_DefineNativeProperty(cx, obj,
1141
+ ATOM_TO_JSID(atom), JSVAL_VOID,
1142
+ NULL, NULL, lfp->attrs,
1143
+ SPROP_HAS_SHORTID, lfp->tinyid,
1144
+ NULL)) {
1145
+ return JS_FALSE;
1146
+ }
1147
+ *objp = obj;
1148
+ return JS_TRUE;
1149
+ }
1150
+ }
1151
+
1152
+ return JS_TRUE;
1153
+ }
1154
+
1155
+ static JSBool
1156
+ fun_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
1157
+ {
1158
+ switch (type) {
1159
+ case JSTYPE_FUNCTION:
1160
+ *vp = OBJECT_TO_JSVAL(obj);
1161
+ return JS_TRUE;
1162
+ default:
1163
+ return js_TryValueOf(cx, obj, type, vp);
1164
+ }
1165
+ }
1166
+
1167
+ #if JS_HAS_XDR
1168
+
1169
+ /* XXX store parent and proto, if defined */
1170
+ static JSBool
1171
+ fun_xdrObject(JSXDRState *xdr, JSObject **objp)
1172
+ {
1173
+ JSContext *cx;
1174
+ JSFunction *fun;
1175
+ uint32 nullAtom; /* flag to indicate if fun->atom is NULL */
1176
+ uintN nargs, nvars, n;
1177
+ uint32 localsword; /* word to xdr argument and variable counts */
1178
+ uint32 flagsword; /* originally only flags was JS_XDRUint8'd */
1179
+ JSTempValueRooter tvr;
1180
+ JSBool ok;
1181
+
1182
+ cx = xdr->cx;
1183
+ if (xdr->mode == JSXDR_ENCODE) {
1184
+ fun = GET_FUNCTION_PRIVATE(cx, *objp);
1185
+ if (!FUN_INTERPRETED(fun)) {
1186
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
1187
+ JSMSG_NOT_SCRIPTED_FUNCTION,
1188
+ JS_GetFunctionName(fun));
1189
+ return JS_FALSE;
1190
+ }
1191
+ nullAtom = !fun->atom;
1192
+ nargs = fun->nargs;
1193
+ nvars = fun->u.i.nvars;
1194
+ localsword = (nargs << 16) | nvars;
1195
+ flagsword = fun->flags;
1196
+ } else {
1197
+ fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, NULL, NULL);
1198
+ if (!fun)
1199
+ return JS_FALSE;
1200
+ STOBJ_SET_PARENT(FUN_OBJECT(fun), NULL);
1201
+ STOBJ_SET_PROTO(FUN_OBJECT(fun), NULL);
1202
+ #ifdef __GNUC__
1203
+ nvars = nargs = 0; /* quell GCC uninitialized warning */
1204
+ #endif
1205
+ }
1206
+
1207
+ /* From here on, control flow must flow through label out. */
1208
+ JS_PUSH_TEMP_ROOT_OBJECT(cx, FUN_OBJECT(fun), &tvr);
1209
+ ok = JS_TRUE;
1210
+
1211
+ if (!JS_XDRUint32(xdr, &nullAtom))
1212
+ goto bad;
1213
+ if (!nullAtom && !js_XDRStringAtom(xdr, &fun->atom))
1214
+ goto bad;
1215
+ if (!JS_XDRUint32(xdr, &localsword) ||
1216
+ !JS_XDRUint32(xdr, &flagsword)) {
1217
+ goto bad;
1218
+ }
1219
+
1220
+ if (xdr->mode == JSXDR_DECODE) {
1221
+ nargs = localsword >> 16;
1222
+ nvars = localsword & JS_BITMASK(16);
1223
+ JS_ASSERT(flagsword | JSFUN_INTERPRETED);
1224
+ fun->flags = (uint16) flagsword;
1225
+ }
1226
+
1227
+ /* do arguments and local vars */
1228
+ n = nargs + nvars;
1229
+ if (n != 0) {
1230
+ void *mark;
1231
+ uintN i;
1232
+ uintN bitmapLength;
1233
+ uint32 *bitmap;
1234
+ jsuword *names;
1235
+ JSAtom *name;
1236
+ JSLocalKind localKind;
1237
+
1238
+ mark = JS_ARENA_MARK(&xdr->cx->tempPool);
1239
+
1240
+ /*
1241
+ * From this point the control must flow via the label release_mark.
1242
+ *
1243
+ * To xdr the names we prefix the names with a bitmap descriptor and
1244
+ * then xdr the names as strings. For argument names (indexes below
1245
+ * nargs) the corresponding bit in the bitmap is unset when the name
1246
+ * is null. Such null names are not encoded or decoded. For variable
1247
+ * names (indexes starting from nargs) bitmap's bit is set when the
1248
+ * name is declared as const, not as ordinary var.
1249
+ * */
1250
+ bitmapLength = JS_HOWMANY(n, JS_BITS_PER_UINT32);
1251
+ JS_ARENA_ALLOCATE_CAST(bitmap, uint32 *, &xdr->cx->tempPool,
1252
+ bitmapLength * sizeof *bitmap);
1253
+ if (!bitmap) {
1254
+ js_ReportOutOfScriptQuota(xdr->cx);
1255
+ ok = JS_FALSE;
1256
+ goto release_mark;
1257
+ }
1258
+ if (xdr->mode == JSXDR_ENCODE) {
1259
+ names = js_GetLocalNameArray(xdr->cx, fun, &xdr->cx->tempPool);
1260
+ if (!names) {
1261
+ ok = JS_FALSE;
1262
+ goto release_mark;
1263
+ }
1264
+ memset(bitmap, 0, bitmapLength * sizeof *bitmap);
1265
+ for (i = 0; i != n; ++i) {
1266
+ if (i < fun->nargs
1267
+ ? JS_LOCAL_NAME_TO_ATOM(names[i]) != NULL
1268
+ : JS_LOCAL_NAME_IS_CONST(names[i])) {
1269
+ bitmap[i >> JS_BITS_PER_UINT32_LOG2] |=
1270
+ JS_BIT(i & (JS_BITS_PER_UINT32 - 1));
1271
+ }
1272
+ }
1273
+ }
1274
+ #ifdef __GNUC__
1275
+ else {
1276
+ names = NULL; /* quell GCC uninitialized warning */
1277
+ }
1278
+ #endif
1279
+ for (i = 0; i != bitmapLength; ++i) {
1280
+ ok = JS_XDRUint32(xdr, &bitmap[i]);
1281
+ if (!ok)
1282
+ goto release_mark;
1283
+ }
1284
+ for (i = 0; i != n; ++i) {
1285
+ if (i < nargs &&
1286
+ !(bitmap[i >> JS_BITS_PER_UINT32_LOG2] &
1287
+ JS_BIT(i & (JS_BITS_PER_UINT32 - 1)))) {
1288
+ if (xdr->mode == JSXDR_DECODE) {
1289
+ ok = js_AddLocal(xdr->cx, fun, NULL, JSLOCAL_ARG);
1290
+ if (!ok)
1291
+ goto release_mark;
1292
+ } else {
1293
+ JS_ASSERT(!JS_LOCAL_NAME_TO_ATOM(names[i]));
1294
+ }
1295
+ continue;
1296
+ }
1297
+ if (xdr->mode == JSXDR_ENCODE)
1298
+ name = JS_LOCAL_NAME_TO_ATOM(names[i]);
1299
+ ok = js_XDRStringAtom(xdr, &name);
1300
+ if (!ok)
1301
+ goto release_mark;
1302
+ if (xdr->mode == JSXDR_DECODE) {
1303
+ localKind = (i < nargs)
1304
+ ? JSLOCAL_ARG
1305
+ : bitmap[i >> JS_BITS_PER_UINT32_LOG2] &
1306
+ JS_BIT(i & (JS_BITS_PER_UINT32 - 1))
1307
+ ? JSLOCAL_CONST
1308
+ : JSLOCAL_VAR;
1309
+ ok = js_AddLocal(xdr->cx, fun, name, localKind);
1310
+ if (!ok)
1311
+ goto release_mark;
1312
+ }
1313
+ }
1314
+ ok = JS_TRUE;
1315
+
1316
+ release_mark:
1317
+ JS_ARENA_RELEASE(&xdr->cx->tempPool, mark);
1318
+ if (!ok)
1319
+ goto out;
1320
+
1321
+ if (xdr->mode == JSXDR_DECODE)
1322
+ js_FreezeLocalNames(cx, fun);
1323
+ }
1324
+
1325
+ if (!js_XDRScript(xdr, &fun->u.i.script, NULL))
1326
+ goto bad;
1327
+
1328
+ if (xdr->mode == JSXDR_DECODE) {
1329
+ *objp = FUN_OBJECT(fun);
1330
+ #ifdef CHECK_SCRIPT_OWNER
1331
+ fun->u.i.script->owner = NULL;
1332
+ #endif
1333
+ js_CallNewScriptHook(cx, fun->u.i.script, fun);
1334
+ }
1335
+
1336
+ out:
1337
+ JS_POP_TEMP_ROOT(cx, &tvr);
1338
+ return ok;
1339
+
1340
+ bad:
1341
+ ok = JS_FALSE;
1342
+ goto out;
1343
+ }
1344
+
1345
+ #else /* !JS_HAS_XDR */
1346
+
1347
+ #define fun_xdrObject NULL
1348
+
1349
+ #endif /* !JS_HAS_XDR */
1350
+
1351
+ /*
1352
+ * [[HasInstance]] internal method for Function objects: fetch the .prototype
1353
+ * property of its 'this' parameter, and walks the prototype chain of v (only
1354
+ * if v is an object) returning true if .prototype is found.
1355
+ */
1356
+ static JSBool
1357
+ fun_hasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
1358
+ {
1359
+ jsval pval;
1360
+
1361
+ if (!OBJ_GET_PROPERTY(cx, obj,
1362
+ ATOM_TO_JSID(cx->runtime->atomState
1363
+ .classPrototypeAtom),
1364
+ &pval)) {
1365
+ return JS_FALSE;
1366
+ }
1367
+
1368
+ if (JSVAL_IS_PRIMITIVE(pval)) {
1369
+ /*
1370
+ * Throw a runtime error if instanceof is called on a function that
1371
+ * has a non-object as its .prototype value.
1372
+ */
1373
+ js_ReportValueError(cx, JSMSG_BAD_PROTOTYPE,
1374
+ -1, OBJECT_TO_JSVAL(obj), NULL);
1375
+ return JS_FALSE;
1376
+ }
1377
+
1378
+ return js_IsDelegate(cx, JSVAL_TO_OBJECT(pval), v, bp);
1379
+ }
1380
+
1381
+ static void
1382
+ TraceLocalNames(JSTracer *trc, JSFunction *fun);
1383
+
1384
+ static void
1385
+ DestroyLocalNames(JSContext *cx, JSFunction *fun);
1386
+
1387
+ static void
1388
+ fun_trace(JSTracer *trc, JSObject *obj)
1389
+ {
1390
+ JSFunction *fun;
1391
+
1392
+ /* A newborn function object may have a not yet initialized private slot. */
1393
+ fun = (JSFunction *) JS_GetPrivate(trc->context, obj);
1394
+ if (!fun)
1395
+ return;
1396
+
1397
+ if (FUN_OBJECT(fun) != obj) {
1398
+ /* obj is cloned function object, trace the original. */
1399
+ JS_CALL_TRACER(trc, FUN_OBJECT(fun), JSTRACE_OBJECT, "private");
1400
+ return;
1401
+ }
1402
+ if (fun->atom)
1403
+ JS_CALL_STRING_TRACER(trc, ATOM_TO_STRING(fun->atom), "atom");
1404
+ if (FUN_INTERPRETED(fun)) {
1405
+ if (fun->u.i.script)
1406
+ js_TraceScript(trc, fun->u.i.script);
1407
+ TraceLocalNames(trc, fun);
1408
+ }
1409
+ }
1410
+
1411
+ static void
1412
+ fun_finalize(JSContext *cx, JSObject *obj)
1413
+ {
1414
+ JSFunction *fun;
1415
+
1416
+ /* Ignore newborn and cloned function objects. */
1417
+ fun = (JSFunction *) JS_GetPrivate(cx, obj);
1418
+ if (!fun || FUN_OBJECT(fun) != obj)
1419
+ return;
1420
+
1421
+ /*
1422
+ * Null-check of u.i.script is required since the parser sets interpreted
1423
+ * very early.
1424
+ */
1425
+ if (FUN_INTERPRETED(fun)) {
1426
+ if (fun->u.i.script)
1427
+ js_DestroyScript(cx, fun->u.i.script);
1428
+ DestroyLocalNames(cx, fun);
1429
+ }
1430
+ }
1431
+
1432
+ static uint32
1433
+ fun_reserveSlots(JSContext *cx, JSObject *obj)
1434
+ {
1435
+ JSFunction *fun;
1436
+
1437
+ /*
1438
+ * We use JS_GetPrivate and not GET_FUNCTION_PRIVATE because during
1439
+ * js_InitFunctionClass invocation the function is called before the
1440
+ * private slot of the function object is set.
1441
+ */
1442
+ fun = (JSFunction *) JS_GetPrivate(cx, obj);
1443
+ return (fun && FUN_INTERPRETED(fun) &&
1444
+ fun->u.i.script && fun->u.i.script->regexpsOffset != 0)
1445
+ ? JS_SCRIPT_REGEXPS(fun->u.i.script)->length
1446
+ : 0;
1447
+ }
1448
+
1449
+ /*
1450
+ * Reserve two slots in all function objects for XPConnect. Note that this
1451
+ * does not bloat every instance, only those on which reserved slots are set,
1452
+ * and those on which ad-hoc properties are defined.
1453
+ */
1454
+ JS_FRIEND_DATA(JSClass) js_FunctionClass = {
1455
+ js_Function_str,
1456
+ JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_HAS_RESERVED_SLOTS(2) |
1457
+ JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Function),
1458
+ JS_PropertyStub, JS_PropertyStub,
1459
+ fun_getProperty, JS_PropertyStub,
1460
+ fun_enumerate, (JSResolveOp)fun_resolve,
1461
+ fun_convert, fun_finalize,
1462
+ NULL, NULL,
1463
+ NULL, NULL,
1464
+ fun_xdrObject, fun_hasInstance,
1465
+ JS_CLASS_TRACE(fun_trace), fun_reserveSlots
1466
+ };
1467
+
1468
+ static JSBool
1469
+ fun_toStringHelper(JSContext *cx, uint32 indent, uintN argc, jsval *vp)
1470
+ {
1471
+ jsval fval;
1472
+ JSObject *obj;
1473
+ JSFunction *fun;
1474
+ JSString *str;
1475
+
1476
+ fval = JS_THIS(cx, vp);
1477
+ if (JSVAL_IS_NULL(fval))
1478
+ return JS_FALSE;
1479
+
1480
+ if (!VALUE_IS_FUNCTION(cx, fval)) {
1481
+ /*
1482
+ * If we don't have a function to start off with, try converting the
1483
+ * object to a function. If that doesn't work, complain.
1484
+ */
1485
+ if (!JSVAL_IS_PRIMITIVE(fval)) {
1486
+ obj = JSVAL_TO_OBJECT(fval);
1487
+ if (!OBJ_GET_CLASS(cx, obj)->convert(cx, obj, JSTYPE_FUNCTION,
1488
+ &fval)) {
1489
+ return JS_FALSE;
1490
+ }
1491
+ vp[1] = fval;
1492
+ }
1493
+ if (!VALUE_IS_FUNCTION(cx, fval)) {
1494
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
1495
+ JSMSG_INCOMPATIBLE_PROTO,
1496
+ js_Function_str, js_toString_str,
1497
+ JS_GetTypeName(cx, JS_TypeOfValue(cx, fval)));
1498
+ return JS_FALSE;
1499
+ }
1500
+ }
1501
+
1502
+ obj = JSVAL_TO_OBJECT(fval);
1503
+ if (argc != 0) {
1504
+ indent = js_ValueToECMAUint32(cx, &vp[2]);
1505
+ if (JSVAL_IS_NULL(vp[2]))
1506
+ return JS_FALSE;
1507
+ }
1508
+
1509
+ JS_ASSERT(JS_ObjectIsFunction(cx, obj));
1510
+ fun = GET_FUNCTION_PRIVATE(cx, obj);
1511
+ if (!fun)
1512
+ return JS_TRUE;
1513
+ str = JS_DecompileFunction(cx, fun, (uintN)indent);
1514
+ if (!str)
1515
+ return JS_FALSE;
1516
+ *vp = STRING_TO_JSVAL(str);
1517
+ return JS_TRUE;
1518
+ }
1519
+
1520
+ static JSBool
1521
+ fun_toString(JSContext *cx, uintN argc, jsval *vp)
1522
+ {
1523
+ return fun_toStringHelper(cx, 0, argc, vp);
1524
+ }
1525
+
1526
+ #if JS_HAS_TOSOURCE
1527
+ static JSBool
1528
+ fun_toSource(JSContext *cx, uintN argc, jsval *vp)
1529
+ {
1530
+ return fun_toStringHelper(cx, JS_DONT_PRETTY_PRINT, argc, vp);
1531
+ }
1532
+ #endif
1533
+
1534
+ static const char call_str[] = "call";
1535
+
1536
+ static JSBool
1537
+ fun_call(JSContext *cx, uintN argc, jsval *vp)
1538
+ {
1539
+ JSObject *obj;
1540
+ jsval fval, *argv, *invokevp;
1541
+ JSString *str;
1542
+ void *mark;
1543
+ JSBool ok;
1544
+
1545
+ obj = JS_THIS_OBJECT(cx, vp);
1546
+ if (!obj || !OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_FUNCTION, &vp[1]))
1547
+ return JS_FALSE;
1548
+ fval = vp[1];
1549
+
1550
+ if (!VALUE_IS_FUNCTION(cx, fval)) {
1551
+ str = JS_ValueToString(cx, fval);
1552
+ if (str) {
1553
+ const char *bytes = js_GetStringBytes(cx, str);
1554
+
1555
+ if (bytes) {
1556
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
1557
+ JSMSG_INCOMPATIBLE_PROTO,
1558
+ js_Function_str, call_str,
1559
+ bytes);
1560
+ }
1561
+ }
1562
+ return JS_FALSE;
1563
+ }
1564
+
1565
+ argv = vp + 2;
1566
+ if (argc == 0) {
1567
+ /* Call fun with its global object as the 'this' param if no args. */
1568
+ obj = NULL;
1569
+ } else {
1570
+ /* Otherwise convert the first arg to 'this' and skip over it. */
1571
+ if (!JSVAL_IS_PRIMITIVE(argv[0]))
1572
+ obj = JSVAL_TO_OBJECT(argv[0]);
1573
+ else if (!js_ValueToObject(cx, argv[0], &obj))
1574
+ return JS_FALSE;
1575
+ argc--;
1576
+ argv++;
1577
+ }
1578
+
1579
+ /* Allocate stack space for fval, obj, and the args. */
1580
+ invokevp = js_AllocStack(cx, 2 + argc, &mark);
1581
+ if (!invokevp)
1582
+ return JS_FALSE;
1583
+
1584
+ /* Push fval, obj, and the args. */
1585
+ invokevp[0] = fval;
1586
+ invokevp[1] = OBJECT_TO_JSVAL(obj);
1587
+ memcpy(invokevp + 2, argv, argc * sizeof *argv);
1588
+
1589
+ ok = js_Invoke(cx, argc, invokevp, 0);
1590
+ *vp = *invokevp;
1591
+ js_FreeStack(cx, mark);
1592
+ return ok;
1593
+ }
1594
+
1595
+ static JSBool
1596
+ fun_apply(JSContext *cx, uintN argc, jsval *vp)
1597
+ {
1598
+ JSObject *obj, *aobj;
1599
+ jsval fval, *invokevp, *sp;
1600
+ JSString *str;
1601
+ jsuint length;
1602
+ JSBool arraylike, ok;
1603
+ void *mark;
1604
+ uintN i;
1605
+
1606
+ if (argc == 0) {
1607
+ /* Will get globalObject as 'this' and no other arguments. */
1608
+ return fun_call(cx, argc, vp);
1609
+ }
1610
+
1611
+ obj = JS_THIS_OBJECT(cx, vp);
1612
+ if (!obj || !OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_FUNCTION, &vp[1]))
1613
+ return JS_FALSE;
1614
+ fval = vp[1];
1615
+
1616
+ if (!VALUE_IS_FUNCTION(cx, fval)) {
1617
+ str = JS_ValueToString(cx, fval);
1618
+ if (str) {
1619
+ const char *bytes = js_GetStringBytes(cx, str);
1620
+
1621
+ if (bytes) {
1622
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
1623
+ JSMSG_INCOMPATIBLE_PROTO,
1624
+ js_Function_str, "apply",
1625
+ bytes);
1626
+ }
1627
+ }
1628
+ return JS_FALSE;
1629
+ }
1630
+
1631
+ /* Quell GCC overwarnings. */
1632
+ aobj = NULL;
1633
+ length = 0;
1634
+
1635
+ if (argc >= 2) {
1636
+ /* If the 2nd arg is null or void, call the function with 0 args. */
1637
+ if (JSVAL_IS_NULL(vp[3]) || JSVAL_IS_VOID(vp[3])) {
1638
+ argc = 0;
1639
+ } else {
1640
+ /* The second arg must be an array (or arguments object). */
1641
+ arraylike = JS_FALSE;
1642
+ if (!JSVAL_IS_PRIMITIVE(vp[3])) {
1643
+ aobj = JSVAL_TO_OBJECT(vp[3]);
1644
+ if (!js_IsArrayLike(cx, aobj, &arraylike, &length))
1645
+ return JS_FALSE;
1646
+ }
1647
+ if (!arraylike) {
1648
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
1649
+ JSMSG_BAD_APPLY_ARGS, "apply");
1650
+ return JS_FALSE;
1651
+ }
1652
+ }
1653
+ }
1654
+
1655
+ /* Convert the first arg to 'this' and skip over it. */
1656
+ if (!JSVAL_IS_PRIMITIVE(vp[2]))
1657
+ obj = JSVAL_TO_OBJECT(vp[2]);
1658
+ else if (!js_ValueToObject(cx, vp[2], &obj))
1659
+ return JS_FALSE;
1660
+
1661
+ /* Allocate stack space for fval, obj, and the args. */
1662
+ argc = (uintN)JS_MIN(length, ARRAY_INIT_LIMIT - 1);
1663
+ invokevp = js_AllocStack(cx, 2 + argc, &mark);
1664
+ if (!invokevp)
1665
+ return JS_FALSE;
1666
+
1667
+ /* Push fval, obj, and aobj's elements as args. */
1668
+ sp = invokevp;
1669
+ *sp++ = fval;
1670
+ *sp++ = OBJECT_TO_JSVAL(obj);
1671
+ for (i = 0; i < argc; i++) {
1672
+ ok = JS_GetElement(cx, aobj, (jsint)i, sp);
1673
+ if (!ok)
1674
+ goto out;
1675
+ sp++;
1676
+ }
1677
+
1678
+ ok = js_Invoke(cx, argc, invokevp, 0);
1679
+ *vp = *invokevp;
1680
+ out:
1681
+ js_FreeStack(cx, mark);
1682
+ return ok;
1683
+ }
1684
+
1685
+ #ifdef NARCISSUS
1686
+ static JSBool
1687
+ fun_applyConstructor(JSContext *cx, uintN argc, jsval *vp)
1688
+ {
1689
+ JSObject *aobj;
1690
+ uintN length, i;
1691
+ void *mark;
1692
+ jsval *invokevp, *sp;
1693
+ JSBool ok;
1694
+
1695
+ if (JSVAL_IS_PRIMITIVE(vp[2]) ||
1696
+ (aobj = JSVAL_TO_OBJECT(vp[2]),
1697
+ OBJ_GET_CLASS(cx, aobj) != &js_ArrayClass &&
1698
+ OBJ_GET_CLASS(cx, aobj) != &js_ArgumentsClass)) {
1699
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
1700
+ JSMSG_BAD_APPLY_ARGS, "__applyConstruct__");
1701
+ return JS_FALSE;
1702
+ }
1703
+
1704
+ if (!js_GetLengthProperty(cx, aobj, &length))
1705
+ return JS_FALSE;
1706
+
1707
+ if (length >= ARRAY_INIT_LIMIT)
1708
+ length = ARRAY_INIT_LIMIT - 1;
1709
+ invokevp = js_AllocStack(cx, 2 + length, &mark);
1710
+ if (!invokevp)
1711
+ return JS_FALSE;
1712
+
1713
+ sp = invokevp;
1714
+ *sp++ = vp[1];
1715
+ *sp++ = JSVAL_NULL; /* this is filled automagically */
1716
+ for (i = 0; i < length; i++) {
1717
+ ok = JS_GetElement(cx, aobj, (jsint)i, sp);
1718
+ if (!ok)
1719
+ goto out;
1720
+ sp++;
1721
+ }
1722
+
1723
+ ok = js_InvokeConstructor(cx, length, invokevp);
1724
+ *vp = *invokevp;
1725
+ out:
1726
+ js_FreeStack(cx, mark);
1727
+ return ok;
1728
+ }
1729
+ #endif
1730
+
1731
+ static JSFunctionSpec function_methods[] = {
1732
+ #if JS_HAS_TOSOURCE
1733
+ JS_FN(js_toSource_str, fun_toSource, 0,0,0),
1734
+ #endif
1735
+ JS_FN(js_toString_str, fun_toString, 0,0,0),
1736
+ JS_FN("apply", fun_apply, 0,2,0),
1737
+ JS_FN(call_str, fun_call, 0,1,0),
1738
+ #ifdef NARCISSUS
1739
+ JS_FN("__applyConstructor__", fun_applyConstructor, 0,1,0),
1740
+ #endif
1741
+ JS_FS_END
1742
+ };
1743
+
1744
+ static JSBool
1745
+ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1746
+ {
1747
+ JSStackFrame *fp, *caller;
1748
+ JSFunction *fun;
1749
+ JSObject *parent;
1750
+ uintN i, n, lineno;
1751
+ JSAtom *atom;
1752
+ const char *filename;
1753
+ JSBool ok;
1754
+ JSString *str, *arg;
1755
+ JSTokenStream ts;
1756
+ JSPrincipals *principals;
1757
+ jschar *collected_args, *cp;
1758
+ void *mark;
1759
+ size_t arg_length, args_length, old_args_length;
1760
+ JSTokenType tt;
1761
+
1762
+ fp = cx->fp;
1763
+ if (!(fp->flags & JSFRAME_CONSTRUCTING)) {
1764
+ obj = js_NewObject(cx, &js_FunctionClass, NULL, NULL, 0);
1765
+ if (!obj)
1766
+ return JS_FALSE;
1767
+ *rval = OBJECT_TO_JSVAL(obj);
1768
+ } else {
1769
+ /*
1770
+ * The constructor is called before the private slot is initialized so
1771
+ * we must use JS_GetPrivate, not GET_FUNCTION_PRIVATE here.
1772
+ */
1773
+ if (JS_GetPrivate(cx, obj))
1774
+ return JS_TRUE;
1775
+ }
1776
+
1777
+ /*
1778
+ * NB: (new Function) is not lexically closed by its caller, it's just an
1779
+ * anonymous function in the top-level scope that its constructor inhabits.
1780
+ * Thus 'var x = 42; f = new Function("return x"); print(f())' prints 42,
1781
+ * and so would a call to f from another top-level's script or function.
1782
+ *
1783
+ * In older versions, before call objects, a new Function was adopted by
1784
+ * its running context's globalObject, which might be different from the
1785
+ * top-level reachable from scopeChain (in HTML frames, e.g.).
1786
+ */
1787
+ parent = OBJ_GET_PARENT(cx, JSVAL_TO_OBJECT(argv[-2]));
1788
+
1789
+ fun = js_NewFunction(cx, obj, NULL, 0, JSFUN_LAMBDA | JSFUN_INTERPRETED,
1790
+ parent, cx->runtime->atomState.anonymousAtom);
1791
+
1792
+ if (!fun)
1793
+ return JS_FALSE;
1794
+
1795
+ /*
1796
+ * Function is static and not called directly by other functions in this
1797
+ * file, therefore it is callable only as a native function by js_Invoke.
1798
+ * Find the scripted caller, possibly skipping other native frames such as
1799
+ * are built for Function.prototype.call or .apply activations that invoke
1800
+ * Function indirectly from a script.
1801
+ */
1802
+ JS_ASSERT(!fp->script && fp->fun && fp->fun->u.n.native == Function);
1803
+ caller = JS_GetScriptedCaller(cx, fp);
1804
+ if (caller) {
1805
+ principals = JS_EvalFramePrincipals(cx, fp, caller);
1806
+ filename = js_ComputeFilename(cx, caller, principals, &lineno);
1807
+ } else {
1808
+ filename = NULL;
1809
+ lineno = 0;
1810
+ principals = NULL;
1811
+ }
1812
+
1813
+ /* Belt-and-braces: check that the caller has access to parent. */
1814
+ if (!js_CheckPrincipalsAccess(cx, parent, principals,
1815
+ CLASS_ATOM(cx, Function))) {
1816
+ return JS_FALSE;
1817
+ }
1818
+
1819
+ n = argc ? argc - 1 : 0;
1820
+ if (n > 0) {
1821
+ enum { OK, BAD, BAD_FORMAL } state;
1822
+
1823
+ /*
1824
+ * Collect the function-argument arguments into one string, separated
1825
+ * by commas, then make a tokenstream from that string, and scan it to
1826
+ * get the arguments. We need to throw the full scanner at the
1827
+ * problem, because the argument string can legitimately contain
1828
+ * comments and linefeeds. XXX It might be better to concatenate
1829
+ * everything up into a function definition and pass it to the
1830
+ * compiler, but doing it this way is less of a delta from the old
1831
+ * code. See ECMA 15.3.2.1.
1832
+ */
1833
+ state = BAD_FORMAL;
1834
+ args_length = 0;
1835
+ for (i = 0; i < n; i++) {
1836
+ /* Collect the lengths for all the function-argument arguments. */
1837
+ arg = js_ValueToString(cx, argv[i]);
1838
+ if (!arg)
1839
+ return JS_FALSE;
1840
+ argv[i] = STRING_TO_JSVAL(arg);
1841
+
1842
+ /*
1843
+ * Check for overflow. The < test works because the maximum
1844
+ * JSString length fits in 2 fewer bits than size_t has.
1845
+ */
1846
+ old_args_length = args_length;
1847
+ args_length = old_args_length + JSSTRING_LENGTH(arg);
1848
+ if (args_length < old_args_length) {
1849
+ js_ReportAllocationOverflow(cx);
1850
+ return JS_FALSE;
1851
+ }
1852
+ }
1853
+
1854
+ /* Add 1 for each joining comma and check for overflow (two ways). */
1855
+ old_args_length = args_length;
1856
+ args_length = old_args_length + n - 1;
1857
+ if (args_length < old_args_length ||
1858
+ args_length >= ~(size_t)0 / sizeof(jschar)) {
1859
+ js_ReportAllocationOverflow(cx);
1860
+ return JS_FALSE;
1861
+ }
1862
+
1863
+ /*
1864
+ * Allocate a string to hold the concatenated arguments, including room
1865
+ * for a terminating 0. Mark cx->tempPool for later release, to free
1866
+ * collected_args and its tokenstream in one swoop.
1867
+ */
1868
+ mark = JS_ARENA_MARK(&cx->tempPool);
1869
+ JS_ARENA_ALLOCATE_CAST(cp, jschar *, &cx->tempPool,
1870
+ (args_length+1) * sizeof(jschar));
1871
+ if (!cp) {
1872
+ js_ReportOutOfScriptQuota(cx);
1873
+ return JS_FALSE;
1874
+ }
1875
+ collected_args = cp;
1876
+
1877
+ /*
1878
+ * Concatenate the arguments into the new string, separated by commas.
1879
+ */
1880
+ for (i = 0; i < n; i++) {
1881
+ arg = JSVAL_TO_STRING(argv[i]);
1882
+ arg_length = JSSTRING_LENGTH(arg);
1883
+ (void) js_strncpy(cp, JSSTRING_CHARS(arg), arg_length);
1884
+ cp += arg_length;
1885
+
1886
+ /* Add separating comma or terminating 0. */
1887
+ *cp++ = (i + 1 < n) ? ',' : 0;
1888
+ }
1889
+
1890
+ /* Initialize a tokenstream that reads from the given string. */
1891
+ if (!js_InitTokenStream(cx, &ts, collected_args, args_length,
1892
+ NULL, filename, lineno)) {
1893
+ JS_ARENA_RELEASE(&cx->tempPool, mark);
1894
+ return JS_FALSE;
1895
+ }
1896
+
1897
+ /* The argument string may be empty or contain no tokens. */
1898
+ tt = js_GetToken(cx, &ts);
1899
+ if (tt != TOK_EOF) {
1900
+ for (;;) {
1901
+ /*
1902
+ * Check that it's a name. This also implicitly guards against
1903
+ * TOK_ERROR, which was already reported.
1904
+ */
1905
+ if (tt != TOK_NAME)
1906
+ goto after_args;
1907
+
1908
+ /*
1909
+ * Get the atom corresponding to the name from the token
1910
+ * stream; we're assured at this point that it's a valid
1911
+ * identifier.
1912
+ */
1913
+ atom = CURRENT_TOKEN(&ts).t_atom;
1914
+
1915
+ /* Check for a duplicate parameter name. */
1916
+ if (js_LookupLocal(cx, fun, atom, NULL) != JSLOCAL_NONE) {
1917
+ const char *name;
1918
+
1919
+ name = js_AtomToPrintableString(cx, atom);
1920
+ ok = name &&
1921
+ js_ReportCompileErrorNumber(cx, &ts, NULL,
1922
+ JSREPORT_WARNING |
1923
+ JSREPORT_STRICT,
1924
+ JSMSG_DUPLICATE_FORMAL,
1925
+ name);
1926
+ if (!ok)
1927
+ goto after_args;
1928
+ }
1929
+ if (!js_AddLocal(cx, fun, atom, JSLOCAL_ARG))
1930
+ goto after_args;
1931
+
1932
+ /*
1933
+ * Get the next token. Stop on end of stream. Otherwise
1934
+ * insist on a comma, get another name, and iterate.
1935
+ */
1936
+ tt = js_GetToken(cx, &ts);
1937
+ if (tt == TOK_EOF)
1938
+ break;
1939
+ if (tt != TOK_COMMA)
1940
+ goto after_args;
1941
+ tt = js_GetToken(cx, &ts);
1942
+ }
1943
+ }
1944
+
1945
+ state = OK;
1946
+ after_args:
1947
+ if (state == BAD_FORMAL && !(ts.flags & TSF_ERROR)) {
1948
+ /*
1949
+ * Report "malformed formal parameter" iff no illegal char or
1950
+ * similar scanner error was already reported.
1951
+ */
1952
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
1953
+ JSMSG_BAD_FORMAL);
1954
+ }
1955
+ js_CloseTokenStream(cx, &ts);
1956
+ JS_ARENA_RELEASE(&cx->tempPool, mark);
1957
+ if (state != OK)
1958
+ return JS_FALSE;
1959
+ }
1960
+
1961
+ if (argc) {
1962
+ str = js_ValueToString(cx, argv[argc-1]);
1963
+ if (!str)
1964
+ return JS_FALSE;
1965
+ argv[argc-1] = STRING_TO_JSVAL(str);
1966
+ } else {
1967
+ str = cx->runtime->emptyString;
1968
+ }
1969
+
1970
+ return js_CompileFunctionBody(cx, fun, principals,
1971
+ JSSTRING_CHARS(str), JSSTRING_LENGTH(str),
1972
+ filename, lineno);
1973
+ }
1974
+
1975
+ JSObject *
1976
+ js_InitFunctionClass(JSContext *cx, JSObject *obj)
1977
+ {
1978
+ JSObject *proto;
1979
+ JSFunction *fun;
1980
+
1981
+ proto = JS_InitClass(cx, obj, NULL, &js_FunctionClass, Function, 1,
1982
+ function_props, function_methods, NULL, NULL);
1983
+ if (!proto)
1984
+ return NULL;
1985
+ fun = js_NewFunction(cx, proto, NULL, 0, JSFUN_INTERPRETED, obj, NULL);
1986
+ if (!fun)
1987
+ goto bad;
1988
+ fun->u.i.script = js_NewScript(cx, 1, 0, 0, 0, 0, 0);
1989
+ if (!fun->u.i.script)
1990
+ goto bad;
1991
+ fun->u.i.script->code[0] = JSOP_STOP;
1992
+ #ifdef CHECK_SCRIPT_OWNER
1993
+ fun->u.i.script->owner = NULL;
1994
+ #endif
1995
+ return proto;
1996
+
1997
+ bad:
1998
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL;
1999
+ return NULL;
2000
+ }
2001
+
2002
+ JSObject *
2003
+ js_InitCallClass(JSContext *cx, JSObject *obj)
2004
+ {
2005
+ JSObject *proto;
2006
+
2007
+ proto = JS_InitClass(cx, obj, NULL, &js_CallClass, NULL, 0,
2008
+ NULL, NULL, NULL, NULL);
2009
+ if (!proto)
2010
+ return NULL;
2011
+
2012
+ /*
2013
+ * Null Call.prototype's proto slot so that Object.prototype.* does not
2014
+ * pollute the scope of heavyweight functions.
2015
+ */
2016
+ OBJ_SET_PROTO(cx, proto, NULL);
2017
+ return proto;
2018
+ }
2019
+
2020
+ JSFunction *
2021
+ js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, uintN nargs,
2022
+ uintN flags, JSObject *parent, JSAtom *atom)
2023
+ {
2024
+ JSFunction *fun;
2025
+
2026
+ if (funobj) {
2027
+ JS_ASSERT(HAS_FUNCTION_CLASS(funobj));
2028
+ OBJ_SET_PARENT(cx, funobj, parent);
2029
+ } else {
2030
+ funobj = js_NewObject(cx, &js_FunctionClass, NULL, parent, 0);
2031
+ if (!funobj)
2032
+ return NULL;
2033
+ }
2034
+ JS_ASSERT(funobj->fslots[JSSLOT_PRIVATE] == JSVAL_VOID);
2035
+ fun = (JSFunction *) funobj;
2036
+
2037
+ /* Initialize all function members. */
2038
+ fun->nargs = nargs;
2039
+ fun->flags = flags & (JSFUN_FLAGS_MASK | JSFUN_INTERPRETED);
2040
+ if (flags & JSFUN_INTERPRETED) {
2041
+ JS_ASSERT(!native);
2042
+ JS_ASSERT(nargs == 0);
2043
+ fun->u.i.nvars = 0;
2044
+ fun->u.i.spare = 0;
2045
+ fun->u.i.script = NULL;
2046
+ #ifdef DEBUG
2047
+ fun->u.i.names.taggedAtom = 0;
2048
+ #endif
2049
+ } else {
2050
+ fun->u.n.native = native;
2051
+ fun->u.n.extra = 0;
2052
+ fun->u.n.minargs = 0;
2053
+ fun->u.n.clasp = NULL;
2054
+ }
2055
+ fun->atom = atom;
2056
+
2057
+ /* Set private to self to indicate non-cloned fully initialized function. */
2058
+ FUN_OBJECT(fun)->fslots[JSSLOT_PRIVATE] = PRIVATE_TO_JSVAL(fun);
2059
+ return fun;
2060
+ }
2061
+
2062
+ JSObject *
2063
+ js_CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent)
2064
+ {
2065
+ JSObject *clone;
2066
+
2067
+ /*
2068
+ * The cloned function object does not need the extra fields beyond
2069
+ * JSObject as it points to fun via the private slot.
2070
+ */
2071
+ clone = js_NewObject(cx, &js_FunctionClass, NULL, parent,
2072
+ sizeof(JSObject));
2073
+ if (!clone)
2074
+ return NULL;
2075
+ clone->fslots[JSSLOT_PRIVATE] = PRIVATE_TO_JSVAL(fun);
2076
+ return clone;
2077
+ }
2078
+
2079
+ JSFunction *
2080
+ js_DefineFunction(JSContext *cx, JSObject *obj, JSAtom *atom, JSNative native,
2081
+ uintN nargs, uintN attrs)
2082
+ {
2083
+ JSFunction *fun;
2084
+ JSPropertyOp gsop;
2085
+
2086
+ fun = js_NewFunction(cx, NULL, native, nargs, attrs, obj, atom);
2087
+ if (!fun)
2088
+ return NULL;
2089
+ gsop = (attrs & JSFUN_STUB_GSOPS) ? JS_PropertyStub : NULL;
2090
+ if (!OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom),
2091
+ OBJECT_TO_JSVAL(FUN_OBJECT(fun)),
2092
+ gsop, gsop,
2093
+ attrs & ~JSFUN_FLAGS_MASK, NULL)) {
2094
+ return NULL;
2095
+ }
2096
+ return fun;
2097
+ }
2098
+
2099
+ #if (JSV2F_CONSTRUCT & JSV2F_SEARCH_STACK)
2100
+ # error "JSINVOKE_CONSTRUCT and JSV2F_SEARCH_STACK are not disjoint!"
2101
+ #endif
2102
+
2103
+ JSFunction *
2104
+ js_ValueToFunction(JSContext *cx, jsval *vp, uintN flags)
2105
+ {
2106
+ jsval v;
2107
+ JSObject *obj;
2108
+
2109
+ v = *vp;
2110
+ obj = NULL;
2111
+ if (JSVAL_IS_OBJECT(v)) {
2112
+ obj = JSVAL_TO_OBJECT(v);
2113
+ if (obj && OBJ_GET_CLASS(cx, obj) != &js_FunctionClass) {
2114
+ if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_FUNCTION, &v))
2115
+ return NULL;
2116
+ obj = VALUE_IS_FUNCTION(cx, v) ? JSVAL_TO_OBJECT(v) : NULL;
2117
+ }
2118
+ }
2119
+ if (!obj) {
2120
+ js_ReportIsNotFunction(cx, vp, flags);
2121
+ return NULL;
2122
+ }
2123
+ return GET_FUNCTION_PRIVATE(cx, obj);
2124
+ }
2125
+
2126
+ JSObject *
2127
+ js_ValueToFunctionObject(JSContext *cx, jsval *vp, uintN flags)
2128
+ {
2129
+ JSFunction *fun;
2130
+ JSStackFrame *caller;
2131
+ JSPrincipals *principals;
2132
+
2133
+ if (VALUE_IS_FUNCTION(cx, *vp))
2134
+ return JSVAL_TO_OBJECT(*vp);
2135
+
2136
+ fun = js_ValueToFunction(cx, vp, flags);
2137
+ if (!fun)
2138
+ return NULL;
2139
+ *vp = OBJECT_TO_JSVAL(FUN_OBJECT(fun));
2140
+
2141
+ caller = JS_GetScriptedCaller(cx, cx->fp);
2142
+ if (caller) {
2143
+ principals = JS_StackFramePrincipals(cx, caller);
2144
+ } else {
2145
+ /* No scripted caller, don't allow access. */
2146
+ principals = NULL;
2147
+ }
2148
+
2149
+ if (!js_CheckPrincipalsAccess(cx, FUN_OBJECT(fun), principals,
2150
+ fun->atom
2151
+ ? fun->atom
2152
+ : cx->runtime->atomState.anonymousAtom)) {
2153
+ return NULL;
2154
+ }
2155
+ return FUN_OBJECT(fun);
2156
+ }
2157
+
2158
+ JSObject *
2159
+ js_ValueToCallableObject(JSContext *cx, jsval *vp, uintN flags)
2160
+ {
2161
+ JSObject *callable;
2162
+
2163
+ callable = JSVAL_IS_PRIMITIVE(*vp) ? NULL : JSVAL_TO_OBJECT(*vp);
2164
+ if (callable &&
2165
+ ((callable->map->ops == &js_ObjectOps)
2166
+ ? OBJ_GET_CLASS(cx, callable)->call
2167
+ : callable->map->ops->call)) {
2168
+ *vp = OBJECT_TO_JSVAL(callable);
2169
+ } else {
2170
+ callable = js_ValueToFunctionObject(cx, vp, flags);
2171
+ }
2172
+ return callable;
2173
+ }
2174
+
2175
+ void
2176
+ js_ReportIsNotFunction(JSContext *cx, jsval *vp, uintN flags)
2177
+ {
2178
+ JSStackFrame *fp;
2179
+ uintN error;
2180
+ const char *name, *source;
2181
+ JSTempValueRooter tvr;
2182
+
2183
+ for (fp = cx->fp; fp && !fp->regs; fp = fp->down)
2184
+ continue;
2185
+ name = source = NULL;
2186
+ JS_PUSH_TEMP_ROOT_STRING(cx, NULL, &tvr);
2187
+ if (flags & JSV2F_ITERATOR) {
2188
+ error = JSMSG_BAD_ITERATOR;
2189
+ name = js_iterator_str;
2190
+ tvr.u.string = js_ValueToSource(cx, *vp);
2191
+ if (!tvr.u.string)
2192
+ goto out;
2193
+ tvr.u.string = js_QuoteString(cx, tvr.u.string, 0);
2194
+ if (!tvr.u.string)
2195
+ goto out;
2196
+ source = js_GetStringBytes(cx, tvr.u.string);
2197
+ if (!source)
2198
+ goto out;
2199
+ } else if (flags & JSV2F_CONSTRUCT) {
2200
+ error = JSMSG_NOT_CONSTRUCTOR;
2201
+ } else {
2202
+ error = JSMSG_NOT_FUNCTION;
2203
+ }
2204
+
2205
+ js_ReportValueError3(cx, error,
2206
+ (fp && fp->regs &&
2207
+ fp->spbase <= vp && vp < fp->regs->sp)
2208
+ ? vp - fp->regs->sp
2209
+ : (flags & JSV2F_SEARCH_STACK)
2210
+ ? JSDVG_SEARCH_STACK
2211
+ : JSDVG_IGNORE_STACK,
2212
+ *vp, NULL,
2213
+ name, source);
2214
+
2215
+ out:
2216
+ JS_POP_TEMP_ROOT(cx, &tvr);
2217
+ }
2218
+
2219
+ /*
2220
+ * When a function has between 2 and MAX_ARRAY_LOCALS arguments and variables,
2221
+ * their name are stored as the JSLocalNames.array.
2222
+ */
2223
+ #define MAX_ARRAY_LOCALS 8
2224
+
2225
+ JS_STATIC_ASSERT(2 <= MAX_ARRAY_LOCALS);
2226
+ JS_STATIC_ASSERT(MAX_ARRAY_LOCALS < JS_BITMASK(16));
2227
+
2228
+ /*
2229
+ * We use the lowest bit of the string atom to distinguish const from var
2230
+ * name when there is only single name or when names are stored as an array.
2231
+ */
2232
+ JS_STATIC_ASSERT((JSVAL_STRING & 1) == 0);
2233
+
2234
+ /*
2235
+ * When we use a hash table to store the local names, we use a singly linked
2236
+ * list to record the indexes of duplicated parameter names to preserve the
2237
+ * duplicates for the decompiler.
2238
+ */
2239
+ typedef struct JSNameIndexPair JSNameIndexPair;
2240
+
2241
+ struct JSNameIndexPair {
2242
+ JSAtom *name;
2243
+ uint16 index;
2244
+ JSNameIndexPair *link;
2245
+ };
2246
+
2247
+ struct JSLocalNameMap {
2248
+ JSDHashTable names;
2249
+ JSNameIndexPair *lastdup;
2250
+ };
2251
+
2252
+ typedef struct JSLocalNameHashEntry {
2253
+ JSDHashEntryHdr hdr;
2254
+ JSAtom *name;
2255
+ uint16 index;
2256
+ uint8 localKind;
2257
+ } JSLocalNameHashEntry;
2258
+
2259
+ static void
2260
+ FreeLocalNameHash(JSContext *cx, JSLocalNameMap *map)
2261
+ {
2262
+ JSNameIndexPair *dup, *next;
2263
+
2264
+ for (dup = map->lastdup; dup; dup = next) {
2265
+ next = dup->link;
2266
+ JS_free(cx, dup);
2267
+ }
2268
+ JS_DHashTableFinish(&map->names);
2269
+ JS_free(cx, map);
2270
+ }
2271
+
2272
+ static JSBool
2273
+ HashLocalName(JSContext *cx, JSLocalNameMap *map, JSAtom *name,
2274
+ JSLocalKind localKind, uintN index)
2275
+ {
2276
+ JSLocalNameHashEntry *entry;
2277
+ JSNameIndexPair *dup;
2278
+
2279
+ JS_ASSERT(index <= JS_BITMASK(16));
2280
+ #if JS_HAS_DESTRUCTURING
2281
+ if (!name) {
2282
+ /* A destructuring pattern does not need a hash entry. */
2283
+ JS_ASSERT(localKind == JSLOCAL_ARG);
2284
+ return JS_TRUE;
2285
+ }
2286
+ #endif
2287
+ JS_ASSERT(ATOM_IS_STRING(name));
2288
+ entry = (JSLocalNameHashEntry *)
2289
+ JS_DHashTableOperate(&map->names, name, JS_DHASH_ADD);
2290
+ if (!entry) {
2291
+ JS_ReportOutOfMemory(cx);
2292
+ return JS_FALSE;
2293
+ }
2294
+ if (entry->name) {
2295
+ JS_ASSERT(entry->name == name);
2296
+ JS_ASSERT(entry->localKind == JSLOCAL_ARG);
2297
+ dup = (JSNameIndexPair *) JS_malloc(cx, sizeof *dup);
2298
+ if (!dup)
2299
+ return JS_FALSE;
2300
+ dup->name = entry->name;
2301
+ dup->index = entry->index;
2302
+ dup->link = map->lastdup;
2303
+ map->lastdup = dup;
2304
+ }
2305
+ entry->name = name;
2306
+ entry->index = (uint16) index;
2307
+ entry->localKind = (uint8) localKind;
2308
+ return JS_TRUE;
2309
+ }
2310
+
2311
+ JSBool
2312
+ js_AddLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, JSLocalKind kind)
2313
+ {
2314
+ jsuword taggedAtom;
2315
+ uint16 *indexp;
2316
+ uintN n, i;
2317
+ jsuword *array;
2318
+ JSLocalNameMap *map;
2319
+
2320
+ JS_ASSERT(FUN_INTERPRETED(fun));
2321
+ JS_ASSERT(!fun->u.i.script);
2322
+ JS_ASSERT(((jsuword) atom & 1) == 0);
2323
+ taggedAtom = (jsuword) atom;
2324
+ if (kind == JSLOCAL_ARG) {
2325
+ indexp = &fun->nargs;
2326
+ } else {
2327
+ indexp = &fun->u.i.nvars;
2328
+ if (kind == JSLOCAL_CONST)
2329
+ taggedAtom |= 1;
2330
+ else
2331
+ JS_ASSERT(kind == JSLOCAL_VAR);
2332
+ }
2333
+ n = JS_GET_LOCAL_NAME_COUNT(fun);
2334
+ if (n == 0) {
2335
+ JS_ASSERT(fun->u.i.names.taggedAtom == 0);
2336
+ fun->u.i.names.taggedAtom = taggedAtom;
2337
+ } else if (n < MAX_ARRAY_LOCALS) {
2338
+ if (n > 1) {
2339
+ array = fun->u.i.names.array;
2340
+ } else {
2341
+ array = (jsuword *) JS_malloc(cx, MAX_ARRAY_LOCALS * sizeof *array);
2342
+ if (!array)
2343
+ return JS_FALSE;
2344
+ array[0] = fun->u.i.names.taggedAtom;
2345
+ fun->u.i.names.array = array;
2346
+ }
2347
+ if (kind == JSLOCAL_ARG) {
2348
+ /*
2349
+ * A destructuring argument pattern adds variables, not arguments,
2350
+ * so for the following arguments nvars != 0.
2351
+ */
2352
+ #if JS_HAS_DESTRUCTURING
2353
+ if (fun->u.i.nvars != 0) {
2354
+ memmove(array + fun->nargs + 1, array + fun->nargs,
2355
+ fun->u.i.nvars * sizeof *array);
2356
+ }
2357
+ #else
2358
+ JS_ASSERT(fun->u.i.nvars == 0);
2359
+ #endif
2360
+ array[fun->nargs] = taggedAtom;
2361
+ } else {
2362
+ array[n] = taggedAtom;
2363
+ }
2364
+ } else if (n == MAX_ARRAY_LOCALS) {
2365
+ array = fun->u.i.names.array;
2366
+ map = (JSLocalNameMap *) JS_malloc(cx, sizeof *map);
2367
+ if (!map)
2368
+ return JS_FALSE;
2369
+ if (!JS_DHashTableInit(&map->names, JS_DHashGetStubOps(),
2370
+ NULL, sizeof(JSLocalNameHashEntry),
2371
+ JS_DHASH_DEFAULT_CAPACITY(MAX_ARRAY_LOCALS
2372
+ * 2))) {
2373
+ JS_ReportOutOfMemory(cx);
2374
+ JS_free(cx, map);
2375
+ return JS_FALSE;
2376
+ }
2377
+
2378
+ map->lastdup = NULL;
2379
+ for (i = 0; i != MAX_ARRAY_LOCALS; ++i) {
2380
+ taggedAtom = array[i];
2381
+ if (!HashLocalName(cx, map, (JSAtom *) (taggedAtom & ~1),
2382
+ (i < fun->nargs)
2383
+ ? JSLOCAL_ARG
2384
+ : (taggedAtom & 1) ? JSLOCAL_CONST : JSLOCAL_VAR,
2385
+ (i < fun->nargs) ? i : i - fun->nargs)) {
2386
+ FreeLocalNameHash(cx, map);
2387
+ return JS_FALSE;
2388
+ }
2389
+ }
2390
+ if (!HashLocalName(cx, map, atom, kind, *indexp)) {
2391
+ FreeLocalNameHash(cx, map);
2392
+ return JS_FALSE;
2393
+ }
2394
+
2395
+ /*
2396
+ * At this point the entry is added and we cannot fail. It is time
2397
+ * to replace fun->u.i.names with the built map.
2398
+ */
2399
+ fun->u.i.names.map = map;
2400
+ JS_free(cx, array);
2401
+ } else {
2402
+ if (*indexp == JS_BITMASK(16)) {
2403
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
2404
+ (kind == JSLOCAL_ARG)
2405
+ ? JSMSG_TOO_MANY_FUN_ARGS
2406
+ : JSMSG_TOO_MANY_FUN_VARS);
2407
+ return JS_FALSE;
2408
+ }
2409
+ if (!HashLocalName(cx, fun->u.i.names.map, atom, kind, *indexp))
2410
+ return JS_FALSE;
2411
+ }
2412
+
2413
+ /* Update the argument or variable counter. */
2414
+ ++*indexp;
2415
+ return JS_TRUE;
2416
+ }
2417
+
2418
+ JSLocalKind
2419
+ js_LookupLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, uintN *indexp)
2420
+ {
2421
+ uintN n, i;
2422
+ jsuword *array;
2423
+ JSLocalNameHashEntry *entry;
2424
+
2425
+ JS_ASSERT(FUN_INTERPRETED(fun));
2426
+ n = JS_GET_LOCAL_NAME_COUNT(fun);
2427
+ if (n == 0)
2428
+ return JSLOCAL_NONE;
2429
+ if (n <= MAX_ARRAY_LOCALS) {
2430
+ array = (n == 1) ? &fun->u.i.names.taggedAtom : fun->u.i.names.array;
2431
+
2432
+ /* Search from the tail to pick up the last duplicated name. */
2433
+ i = n;
2434
+ do {
2435
+ --i;
2436
+ if (atom == JS_LOCAL_NAME_TO_ATOM(array[i])) {
2437
+ if (i < fun->nargs) {
2438
+ if (indexp)
2439
+ *indexp = i;
2440
+ return JSLOCAL_ARG;
2441
+ }
2442
+ if (indexp)
2443
+ *indexp = i - fun->nargs;
2444
+ return JS_LOCAL_NAME_IS_CONST(array[i])
2445
+ ? JSLOCAL_CONST
2446
+ : JSLOCAL_VAR;
2447
+ }
2448
+ } while (i != 0);
2449
+ } else {
2450
+ entry = (JSLocalNameHashEntry *)
2451
+ JS_DHashTableOperate(&fun->u.i.names.map->names, atom,
2452
+ JS_DHASH_LOOKUP);
2453
+ if (JS_DHASH_ENTRY_IS_BUSY(&entry->hdr)) {
2454
+ JS_ASSERT(entry->localKind != JSLOCAL_NONE);
2455
+ if (indexp)
2456
+ *indexp = entry->index;
2457
+ return (JSLocalKind) entry->localKind;
2458
+ }
2459
+ }
2460
+ return JSLOCAL_NONE;
2461
+ }
2462
+
2463
+ typedef struct JSLocalNameEnumeratorArgs {
2464
+ JSFunction *fun;
2465
+ jsuword *names;
2466
+ #ifdef DEBUG
2467
+ uintN nCopiedArgs;
2468
+ uintN nCopiedVars;
2469
+ #endif
2470
+ } JSLocalNameEnumeratorArgs;
2471
+
2472
+ JS_STATIC_DLL_CALLBACK(JSDHashOperator)
2473
+ get_local_names_enumerator(JSDHashTable *table, JSDHashEntryHdr *hdr,
2474
+ uint32 number, void *arg)
2475
+ {
2476
+ JSLocalNameHashEntry *entry;
2477
+ JSLocalNameEnumeratorArgs *args;
2478
+ uint i;
2479
+ jsuword constFlag;
2480
+
2481
+ entry = (JSLocalNameHashEntry *) hdr;
2482
+ args = (JSLocalNameEnumeratorArgs *) arg;
2483
+ JS_ASSERT(entry->name);
2484
+ if (entry->localKind == JSLOCAL_ARG) {
2485
+ JS_ASSERT(entry->index < args->fun->nargs);
2486
+ JS_ASSERT(args->nCopiedArgs++ < args->fun->nargs);
2487
+ i = entry->index;
2488
+ constFlag = 0;
2489
+ } else {
2490
+ JS_ASSERT(entry->localKind == JSLOCAL_VAR ||
2491
+ entry->localKind == JSLOCAL_CONST);
2492
+ JS_ASSERT(entry->index < args->fun->u.i.nvars);
2493
+ JS_ASSERT(args->nCopiedVars++ < args->fun->u.i.nvars);
2494
+ i = args->fun->nargs + entry->index;
2495
+ constFlag = (entry->localKind == JSLOCAL_CONST);
2496
+ }
2497
+ args->names[i] = (jsuword) entry->name | constFlag;
2498
+ return JS_DHASH_NEXT;
2499
+ }
2500
+
2501
+ jsuword *
2502
+ js_GetLocalNameArray(JSContext *cx, JSFunction *fun, JSArenaPool *pool)
2503
+ {
2504
+ uintN n;
2505
+ jsuword *names;
2506
+ JSLocalNameMap *map;
2507
+ JSLocalNameEnumeratorArgs args;
2508
+ JSNameIndexPair *dup;
2509
+
2510
+ JS_ASSERT(FUN_INTERPRETED(fun));
2511
+ n = JS_GET_LOCAL_NAME_COUNT(fun);
2512
+ JS_ASSERT(n != 0);
2513
+
2514
+ if (n <= MAX_ARRAY_LOCALS)
2515
+ return (n == 1) ? &fun->u.i.names.taggedAtom : fun->u.i.names.array;
2516
+
2517
+ /*
2518
+ * No need to check for overflow of the allocation size as we are making a
2519
+ * copy of already allocated data. As such it must fit size_t.
2520
+ */
2521
+ JS_ARENA_ALLOCATE_CAST(names, jsuword *, pool, (size_t) n * sizeof *names);
2522
+ if (!names) {
2523
+ js_ReportOutOfScriptQuota(cx);
2524
+ return NULL;
2525
+ }
2526
+
2527
+ #if JS_HAS_DESTRUCTURING
2528
+ /* Some parameter names can be NULL due to destructuring patterns. */
2529
+ memset(names, 0, fun->nargs * sizeof *names);
2530
+ #endif
2531
+ map = fun->u.i.names.map;
2532
+ args.fun = fun;
2533
+ args.names = names;
2534
+ #ifdef DEBUG
2535
+ args.nCopiedArgs = 0;
2536
+ args.nCopiedVars = 0;
2537
+ #endif
2538
+ JS_DHashTableEnumerate(&map->names, get_local_names_enumerator, &args);
2539
+ for (dup = map->lastdup; dup; dup = dup->link) {
2540
+ JS_ASSERT(dup->index < fun->nargs);
2541
+ JS_ASSERT(args.nCopiedArgs++ < fun->nargs);
2542
+ names[dup->index] = (jsuword) dup->name;
2543
+ }
2544
+ #if !JS_HAS_DESTRUCTURING
2545
+ JS_ASSERT(args.nCopiedArgs == fun->nargs);
2546
+ #endif
2547
+ JS_ASSERT(args.nCopiedVars == fun->u.i.nvars);
2548
+
2549
+ return names;
2550
+ }
2551
+
2552
+ JS_STATIC_DLL_CALLBACK(JSDHashOperator)
2553
+ trace_local_names_enumerator(JSDHashTable *table, JSDHashEntryHdr *hdr,
2554
+ uint32 number, void *arg)
2555
+ {
2556
+ JSLocalNameHashEntry *entry;
2557
+ JSTracer *trc;
2558
+
2559
+ entry = (JSLocalNameHashEntry *) hdr;
2560
+ JS_ASSERT(entry->name);
2561
+ trc = (JSTracer *) arg;
2562
+ JS_SET_TRACING_INDEX(trc,
2563
+ entry->localKind == JSLOCAL_ARG ? "arg" : "var",
2564
+ entry->index);
2565
+ JS_CallTracer(trc, ATOM_TO_STRING(entry->name), JSTRACE_STRING);
2566
+ return JS_DHASH_NEXT;
2567
+ }
2568
+
2569
+ static void
2570
+ TraceLocalNames(JSTracer *trc, JSFunction *fun)
2571
+ {
2572
+ uintN n, i;
2573
+ JSAtom *atom;
2574
+ jsuword *array;
2575
+
2576
+ JS_ASSERT(FUN_INTERPRETED(fun));
2577
+ n = JS_GET_LOCAL_NAME_COUNT(fun);
2578
+ if (n == 0)
2579
+ return;
2580
+ if (n <= MAX_ARRAY_LOCALS) {
2581
+ array = (n == 1) ? &fun->u.i.names.taggedAtom : fun->u.i.names.array;
2582
+ i = n;
2583
+ do {
2584
+ --i;
2585
+ atom = (JSAtom *) (array[i] & ~1);
2586
+ if (atom) {
2587
+ JS_SET_TRACING_INDEX(trc,
2588
+ i < fun->nargs ? "arg" : "var",
2589
+ i < fun->nargs ? i : i - fun->nargs);
2590
+ JS_CallTracer(trc, ATOM_TO_STRING(atom), JSTRACE_STRING);
2591
+ }
2592
+ } while (i != 0);
2593
+ } else {
2594
+ JS_DHashTableEnumerate(&fun->u.i.names.map->names,
2595
+ trace_local_names_enumerator, trc);
2596
+
2597
+ /*
2598
+ * No need to trace the list of duplicates in map->lastdup as the
2599
+ * names there are traced when enumerating the hash table.
2600
+ */
2601
+ }
2602
+ }
2603
+
2604
+ void
2605
+ DestroyLocalNames(JSContext *cx, JSFunction *fun)
2606
+ {
2607
+ uintN n;
2608
+
2609
+ n = fun->nargs + fun->u.i.nvars;
2610
+ if (n <= 1)
2611
+ return;
2612
+ if (n <= MAX_ARRAY_LOCALS)
2613
+ JS_free(cx, fun->u.i.names.array);
2614
+ else
2615
+ FreeLocalNameHash(cx, fun->u.i.names.map);
2616
+ }
2617
+
2618
+ void
2619
+ js_FreezeLocalNames(JSContext *cx, JSFunction *fun)
2620
+ {
2621
+ uintN n;
2622
+ jsuword *array;
2623
+
2624
+ JS_ASSERT(FUN_INTERPRETED(fun));
2625
+ JS_ASSERT(!fun->u.i.script);
2626
+ n = fun->nargs + fun->u.i.nvars;
2627
+ if (2 <= n && n < MAX_ARRAY_LOCALS) {
2628
+ /* Shrink over-allocated array ignoring realloc failures. */
2629
+ array = (jsuword *) JS_realloc(cx, fun->u.i.names.array,
2630
+ n * sizeof *array);
2631
+ if (array)
2632
+ fun->u.i.names.array = array;
2633
+ }
2634
+ }