johnson 2.0.0.pre1 → 2.0.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (311) hide show
  1. data/CHANGELOG.rdoc +12 -0
  2. data/Manifest.txt +4 -285
  3. data/Rakefile +13 -20
  4. data/ext/tracemonkey/global.cc +4 -1
  5. data/ext/tracemonkey/js.cc +30 -33
  6. data/ext/tracemonkey/runtime.cc +96 -6
  7. data/ext/tracemonkey/split_global.cc +0 -5
  8. data/ext/tracemonkey/tracemonkey.h +2 -2
  9. data/lib/johnson.rb +2 -2
  10. data/lib/johnson/runtime.rb +25 -15
  11. data/lib/johnson/tracemonkey/runtime.rb +6 -3
  12. data/vendor/tracemonkey/config/system-headers +1 -3
  13. data/vendor/tracemonkey/jscntxt.h +5 -2
  14. data/vendor/tracemonkey/jsdbgapi.cpp +9 -1
  15. data/vendor/tracemonkey/jsdbgapi.h +4 -0
  16. data/vendor/tracemonkey/tests/ecma/NativeObjects/browser.js +0 -0
  17. data/vendor/tracemonkey/tests/ecma/NativeObjects/jstests.list +0 -0
  18. data/vendor/tracemonkey/tests/ecma_3_1/Object/jstests.list +1 -1
  19. data/vendor/tracemonkey/tests/js1_3/misc/browser.js +0 -0
  20. data/vendor/tracemonkey/tests/js1_3/misc/jstests.list +0 -0
  21. data/vendor/tracemonkey/tests/js1_5/Regress/jstests.list +4 -4
  22. data/vendor/tracemonkey/tests/js1_5/Scope/jstests.list +1 -1
  23. data/vendor/tracemonkey/tests/js1_5/decompilation/jstests.list +2 -2
  24. data/vendor/tracemonkey/tests/js1_7/decompilation/jstests.list +1 -1
  25. data/vendor/tracemonkey/tests/shell.js +2 -1
  26. metadata +51 -309
  27. data/ext/spidermonkey/context.c +0 -116
  28. data/ext/spidermonkey/context.h +0 -19
  29. data/ext/spidermonkey/conversions.c +0 -361
  30. data/ext/spidermonkey/conversions.h +0 -31
  31. data/ext/spidermonkey/debugger.c +0 -234
  32. data/ext/spidermonkey/debugger.h +0 -10
  33. data/ext/spidermonkey/extconf.rb +0 -32
  34. data/ext/spidermonkey/extensions.c +0 -37
  35. data/ext/spidermonkey/extensions.h +0 -12
  36. data/ext/spidermonkey/global.c +0 -40
  37. data/ext/spidermonkey/global.h +0 -11
  38. data/ext/spidermonkey/idhash.c +0 -16
  39. data/ext/spidermonkey/idhash.h +0 -8
  40. data/ext/spidermonkey/immutable_node.c +0 -1153
  41. data/ext/spidermonkey/immutable_node.c.erb +0 -523
  42. data/ext/spidermonkey/immutable_node.h +0 -22
  43. data/ext/spidermonkey/jroot.h +0 -197
  44. data/ext/spidermonkey/js_land_proxy.c +0 -620
  45. data/ext/spidermonkey/js_land_proxy.h +0 -20
  46. data/ext/spidermonkey/ruby_land_proxy.c +0 -618
  47. data/ext/spidermonkey/ruby_land_proxy.h +0 -38
  48. data/ext/spidermonkey/runtime.c +0 -396
  49. data/ext/spidermonkey/runtime.h +0 -27
  50. data/ext/spidermonkey/spidermonkey.c +0 -22
  51. data/ext/spidermonkey/spidermonkey.h +0 -29
  52. data/lib/johnson/spidermonkey.rb +0 -12
  53. data/lib/johnson/spidermonkey/context.rb +0 -10
  54. data/lib/johnson/spidermonkey/debugger.rb +0 -67
  55. data/lib/johnson/spidermonkey/immutable_node.rb +0 -282
  56. data/lib/johnson/spidermonkey/js_land_proxy.rb +0 -64
  57. data/lib/johnson/spidermonkey/mutable_tree_visitor.rb +0 -242
  58. data/lib/johnson/spidermonkey/ruby_land_proxy.rb +0 -17
  59. data/lib/johnson/spidermonkey/runtime.rb +0 -74
  60. data/test/johnson/spidermonkey/context_test.rb +0 -21
  61. data/test/johnson/spidermonkey/immutable_node_test.rb +0 -34
  62. data/test/johnson/spidermonkey/js_land_proxy_test.rb +0 -273
  63. data/test/johnson/spidermonkey/ruby_land_proxy_test.rb +0 -274
  64. data/test/johnson/spidermonkey/runtime_test.rb +0 -41
  65. data/vendor/spidermonkey/.cvsignore +0 -9
  66. data/vendor/spidermonkey/Makefile.in +0 -449
  67. data/vendor/spidermonkey/Makefile.ref +0 -365
  68. data/vendor/spidermonkey/README.html +0 -820
  69. data/vendor/spidermonkey/SpiderMonkey.rsp +0 -12
  70. data/vendor/spidermonkey/Y.js +0 -19
  71. data/vendor/spidermonkey/build.mk +0 -43
  72. data/vendor/spidermonkey/config.mk +0 -192
  73. data/vendor/spidermonkey/config/AIX4.1.mk +0 -65
  74. data/vendor/spidermonkey/config/AIX4.2.mk +0 -64
  75. data/vendor/spidermonkey/config/AIX4.3.mk +0 -65
  76. data/vendor/spidermonkey/config/Darwin.mk +0 -83
  77. data/vendor/spidermonkey/config/Darwin1.3.mk +0 -81
  78. data/vendor/spidermonkey/config/Darwin1.4.mk +0 -41
  79. data/vendor/spidermonkey/config/Darwin5.2.mk +0 -81
  80. data/vendor/spidermonkey/config/Darwin5.3.mk +0 -81
  81. data/vendor/spidermonkey/config/HP-UXB.10.10.mk +0 -77
  82. data/vendor/spidermonkey/config/HP-UXB.10.20.mk +0 -77
  83. data/vendor/spidermonkey/config/HP-UXB.11.00.mk +0 -80
  84. data/vendor/spidermonkey/config/IRIX.mk +0 -87
  85. data/vendor/spidermonkey/config/IRIX5.3.mk +0 -44
  86. data/vendor/spidermonkey/config/IRIX6.1.mk +0 -44
  87. data/vendor/spidermonkey/config/IRIX6.2.mk +0 -44
  88. data/vendor/spidermonkey/config/IRIX6.3.mk +0 -44
  89. data/vendor/spidermonkey/config/IRIX6.5.mk +0 -44
  90. data/vendor/spidermonkey/config/Linux_All.mk +0 -103
  91. data/vendor/spidermonkey/config/Mac_OS10.0.mk +0 -82
  92. data/vendor/spidermonkey/config/OSF1V4.0.mk +0 -72
  93. data/vendor/spidermonkey/config/OSF1V5.0.mk +0 -69
  94. data/vendor/spidermonkey/config/SunOS4.1.4.mk +0 -101
  95. data/vendor/spidermonkey/config/SunOS5.10.mk +0 -50
  96. data/vendor/spidermonkey/config/SunOS5.3.mk +0 -91
  97. data/vendor/spidermonkey/config/SunOS5.4.mk +0 -92
  98. data/vendor/spidermonkey/config/SunOS5.5.1.mk +0 -44
  99. data/vendor/spidermonkey/config/SunOS5.5.mk +0 -87
  100. data/vendor/spidermonkey/config/SunOS5.6.mk +0 -89
  101. data/vendor/spidermonkey/config/SunOS5.7.mk +0 -44
  102. data/vendor/spidermonkey/config/SunOS5.8.mk +0 -44
  103. data/vendor/spidermonkey/config/SunOS5.9.mk +0 -44
  104. data/vendor/spidermonkey/config/WINNT4.0.mk +0 -117
  105. data/vendor/spidermonkey/config/WINNT5.0.mk +0 -117
  106. data/vendor/spidermonkey/config/WINNT5.1.mk +0 -117
  107. data/vendor/spidermonkey/config/WINNT5.2.mk +0 -117
  108. data/vendor/spidermonkey/config/WINNT6.0.mk +0 -117
  109. data/vendor/spidermonkey/config/dgux.mk +0 -64
  110. data/vendor/spidermonkey/editline/Makefile.ref +0 -144
  111. data/vendor/spidermonkey/editline/README +0 -83
  112. data/vendor/spidermonkey/editline/editline.3 +0 -175
  113. data/vendor/spidermonkey/editline/editline.c +0 -1369
  114. data/vendor/spidermonkey/editline/editline.h +0 -135
  115. data/vendor/spidermonkey/editline/sysunix.c +0 -182
  116. data/vendor/spidermonkey/editline/unix.h +0 -82
  117. data/vendor/spidermonkey/fdlibm/.cvsignore +0 -7
  118. data/vendor/spidermonkey/fdlibm/Makefile.in +0 -127
  119. data/vendor/spidermonkey/fdlibm/Makefile.ref +0 -192
  120. data/vendor/spidermonkey/fdlibm/e_acos.c +0 -147
  121. data/vendor/spidermonkey/fdlibm/e_acosh.c +0 -105
  122. data/vendor/spidermonkey/fdlibm/e_asin.c +0 -156
  123. data/vendor/spidermonkey/fdlibm/e_atan2.c +0 -165
  124. data/vendor/spidermonkey/fdlibm/e_atanh.c +0 -110
  125. data/vendor/spidermonkey/fdlibm/e_cosh.c +0 -133
  126. data/vendor/spidermonkey/fdlibm/e_exp.c +0 -202
  127. data/vendor/spidermonkey/fdlibm/e_fmod.c +0 -184
  128. data/vendor/spidermonkey/fdlibm/e_gamma.c +0 -71
  129. data/vendor/spidermonkey/fdlibm/e_gamma_r.c +0 -70
  130. data/vendor/spidermonkey/fdlibm/e_hypot.c +0 -173
  131. data/vendor/spidermonkey/fdlibm/e_j0.c +0 -524
  132. data/vendor/spidermonkey/fdlibm/e_j1.c +0 -523
  133. data/vendor/spidermonkey/fdlibm/e_jn.c +0 -315
  134. data/vendor/spidermonkey/fdlibm/e_lgamma.c +0 -71
  135. data/vendor/spidermonkey/fdlibm/e_lgamma_r.c +0 -347
  136. data/vendor/spidermonkey/fdlibm/e_log.c +0 -184
  137. data/vendor/spidermonkey/fdlibm/e_log10.c +0 -134
  138. data/vendor/spidermonkey/fdlibm/e_pow.c +0 -386
  139. data/vendor/spidermonkey/fdlibm/e_rem_pio2.c +0 -222
  140. data/vendor/spidermonkey/fdlibm/e_remainder.c +0 -120
  141. data/vendor/spidermonkey/fdlibm/e_scalb.c +0 -89
  142. data/vendor/spidermonkey/fdlibm/e_sinh.c +0 -122
  143. data/vendor/spidermonkey/fdlibm/e_sqrt.c +0 -497
  144. data/vendor/spidermonkey/fdlibm/fdlibm.h +0 -273
  145. data/vendor/spidermonkey/fdlibm/fdlibm.mak +0 -1453
  146. data/vendor/spidermonkey/fdlibm/fdlibm.mdp +0 -0
  147. data/vendor/spidermonkey/fdlibm/k_cos.c +0 -135
  148. data/vendor/spidermonkey/fdlibm/k_rem_pio2.c +0 -354
  149. data/vendor/spidermonkey/fdlibm/k_sin.c +0 -114
  150. data/vendor/spidermonkey/fdlibm/k_standard.c +0 -785
  151. data/vendor/spidermonkey/fdlibm/k_tan.c +0 -170
  152. data/vendor/spidermonkey/fdlibm/s_asinh.c +0 -101
  153. data/vendor/spidermonkey/fdlibm/s_atan.c +0 -175
  154. data/vendor/spidermonkey/fdlibm/s_cbrt.c +0 -133
  155. data/vendor/spidermonkey/fdlibm/s_ceil.c +0 -120
  156. data/vendor/spidermonkey/fdlibm/s_copysign.c +0 -72
  157. data/vendor/spidermonkey/fdlibm/s_cos.c +0 -118
  158. data/vendor/spidermonkey/fdlibm/s_erf.c +0 -356
  159. data/vendor/spidermonkey/fdlibm/s_expm1.c +0 -267
  160. data/vendor/spidermonkey/fdlibm/s_fabs.c +0 -70
  161. data/vendor/spidermonkey/fdlibm/s_finite.c +0 -71
  162. data/vendor/spidermonkey/fdlibm/s_floor.c +0 -121
  163. data/vendor/spidermonkey/fdlibm/s_frexp.c +0 -99
  164. data/vendor/spidermonkey/fdlibm/s_ilogb.c +0 -85
  165. data/vendor/spidermonkey/fdlibm/s_isnan.c +0 -74
  166. data/vendor/spidermonkey/fdlibm/s_ldexp.c +0 -66
  167. data/vendor/spidermonkey/fdlibm/s_lib_version.c +0 -73
  168. data/vendor/spidermonkey/fdlibm/s_log1p.c +0 -211
  169. data/vendor/spidermonkey/fdlibm/s_logb.c +0 -79
  170. data/vendor/spidermonkey/fdlibm/s_matherr.c +0 -64
  171. data/vendor/spidermonkey/fdlibm/s_modf.c +0 -132
  172. data/vendor/spidermonkey/fdlibm/s_nextafter.c +0 -124
  173. data/vendor/spidermonkey/fdlibm/s_rint.c +0 -131
  174. data/vendor/spidermonkey/fdlibm/s_scalbn.c +0 -107
  175. data/vendor/spidermonkey/fdlibm/s_signgam.c +0 -40
  176. data/vendor/spidermonkey/fdlibm/s_significand.c +0 -68
  177. data/vendor/spidermonkey/fdlibm/s_sin.c +0 -118
  178. data/vendor/spidermonkey/fdlibm/s_tan.c +0 -112
  179. data/vendor/spidermonkey/fdlibm/s_tanh.c +0 -122
  180. data/vendor/spidermonkey/fdlibm/w_acos.c +0 -78
  181. data/vendor/spidermonkey/fdlibm/w_acosh.c +0 -78
  182. data/vendor/spidermonkey/fdlibm/w_asin.c +0 -80
  183. data/vendor/spidermonkey/fdlibm/w_atan2.c +0 -79
  184. data/vendor/spidermonkey/fdlibm/w_atanh.c +0 -81
  185. data/vendor/spidermonkey/fdlibm/w_cosh.c +0 -77
  186. data/vendor/spidermonkey/fdlibm/w_exp.c +0 -88
  187. data/vendor/spidermonkey/fdlibm/w_fmod.c +0 -78
  188. data/vendor/spidermonkey/fdlibm/w_gamma.c +0 -85
  189. data/vendor/spidermonkey/fdlibm/w_gamma_r.c +0 -81
  190. data/vendor/spidermonkey/fdlibm/w_hypot.c +0 -78
  191. data/vendor/spidermonkey/fdlibm/w_j0.c +0 -105
  192. data/vendor/spidermonkey/fdlibm/w_j1.c +0 -106
  193. data/vendor/spidermonkey/fdlibm/w_jn.c +0 -128
  194. data/vendor/spidermonkey/fdlibm/w_lgamma.c +0 -85
  195. data/vendor/spidermonkey/fdlibm/w_lgamma_r.c +0 -81
  196. data/vendor/spidermonkey/fdlibm/w_log.c +0 -78
  197. data/vendor/spidermonkey/fdlibm/w_log10.c +0 -81
  198. data/vendor/spidermonkey/fdlibm/w_pow.c +0 -99
  199. data/vendor/spidermonkey/fdlibm/w_remainder.c +0 -77
  200. data/vendor/spidermonkey/fdlibm/w_scalb.c +0 -95
  201. data/vendor/spidermonkey/fdlibm/w_sinh.c +0 -77
  202. data/vendor/spidermonkey/fdlibm/w_sqrt.c +0 -77
  203. data/vendor/spidermonkey/javascript-trace.d +0 -73
  204. data/vendor/spidermonkey/js.c +0 -3951
  205. data/vendor/spidermonkey/js.mdp +0 -0
  206. data/vendor/spidermonkey/js.msg +0 -308
  207. data/vendor/spidermonkey/js.pkg +0 -2
  208. data/vendor/spidermonkey/js3240.rc +0 -79
  209. data/vendor/spidermonkey/jsOS240.def +0 -654
  210. data/vendor/spidermonkey/jsapi.c +0 -5836
  211. data/vendor/spidermonkey/jsapi.h +0 -2624
  212. data/vendor/spidermonkey/jsarena.c +0 -450
  213. data/vendor/spidermonkey/jsarena.h +0 -318
  214. data/vendor/spidermonkey/jsarray.c +0 -2996
  215. data/vendor/spidermonkey/jsarray.h +0 -127
  216. data/vendor/spidermonkey/jsatom.c +0 -1045
  217. data/vendor/spidermonkey/jsatom.h +0 -442
  218. data/vendor/spidermonkey/jsbit.h +0 -253
  219. data/vendor/spidermonkey/jsbool.c +0 -176
  220. data/vendor/spidermonkey/jsbool.h +0 -73
  221. data/vendor/spidermonkey/jsclist.h +0 -139
  222. data/vendor/spidermonkey/jscntxt.c +0 -1348
  223. data/vendor/spidermonkey/jscntxt.h +0 -1120
  224. data/vendor/spidermonkey/jscompat.h +0 -57
  225. data/vendor/spidermonkey/jsconfig.h +0 -248
  226. data/vendor/spidermonkey/jsconfig.mk +0 -181
  227. data/vendor/spidermonkey/jscpucfg.c +0 -396
  228. data/vendor/spidermonkey/jscpucfg.h +0 -212
  229. data/vendor/spidermonkey/jsdate.c +0 -2390
  230. data/vendor/spidermonkey/jsdate.h +0 -124
  231. data/vendor/spidermonkey/jsdbgapi.c +0 -1802
  232. data/vendor/spidermonkey/jsdbgapi.h +0 -464
  233. data/vendor/spidermonkey/jsdhash.c +0 -868
  234. data/vendor/spidermonkey/jsdhash.h +0 -592
  235. data/vendor/spidermonkey/jsdtoa.c +0 -3167
  236. data/vendor/spidermonkey/jsdtoa.h +0 -130
  237. data/vendor/spidermonkey/jsdtracef.c +0 -317
  238. data/vendor/spidermonkey/jsdtracef.h +0 -77
  239. data/vendor/spidermonkey/jsemit.c +0 -6909
  240. data/vendor/spidermonkey/jsemit.h +0 -741
  241. data/vendor/spidermonkey/jsexn.c +0 -1371
  242. data/vendor/spidermonkey/jsexn.h +0 -96
  243. data/vendor/spidermonkey/jsfile.c +0 -2736
  244. data/vendor/spidermonkey/jsfile.h +0 -56
  245. data/vendor/spidermonkey/jsfile.msg +0 -90
  246. data/vendor/spidermonkey/jsfun.c +0 -2634
  247. data/vendor/spidermonkey/jsfun.h +0 -254
  248. data/vendor/spidermonkey/jsgc.c +0 -3562
  249. data/vendor/spidermonkey/jsgc.h +0 -403
  250. data/vendor/spidermonkey/jshash.c +0 -476
  251. data/vendor/spidermonkey/jshash.h +0 -151
  252. data/vendor/spidermonkey/jsify.pl +0 -485
  253. data/vendor/spidermonkey/jsinterp.c +0 -7007
  254. data/vendor/spidermonkey/jsinterp.h +0 -525
  255. data/vendor/spidermonkey/jsinvoke.c +0 -43
  256. data/vendor/spidermonkey/jsiter.c +0 -1067
  257. data/vendor/spidermonkey/jsiter.h +0 -122
  258. data/vendor/spidermonkey/jskeyword.tbl +0 -124
  259. data/vendor/spidermonkey/jskwgen.c +0 -460
  260. data/vendor/spidermonkey/jslibmath.h +0 -266
  261. data/vendor/spidermonkey/jslock.c +0 -1309
  262. data/vendor/spidermonkey/jslock.h +0 -313
  263. data/vendor/spidermonkey/jslocko.asm +0 -60
  264. data/vendor/spidermonkey/jslog2.c +0 -94
  265. data/vendor/spidermonkey/jslong.c +0 -264
  266. data/vendor/spidermonkey/jslong.h +0 -412
  267. data/vendor/spidermonkey/jsmath.c +0 -567
  268. data/vendor/spidermonkey/jsmath.h +0 -57
  269. data/vendor/spidermonkey/jsnum.c +0 -1239
  270. data/vendor/spidermonkey/jsnum.h +0 -283
  271. data/vendor/spidermonkey/jsobj.c +0 -5282
  272. data/vendor/spidermonkey/jsobj.h +0 -709
  273. data/vendor/spidermonkey/jsopcode.c +0 -5245
  274. data/vendor/spidermonkey/jsopcode.h +0 -394
  275. data/vendor/spidermonkey/jsopcode.tbl +0 -523
  276. data/vendor/spidermonkey/jsotypes.h +0 -202
  277. data/vendor/spidermonkey/jsparse.c +0 -6704
  278. data/vendor/spidermonkey/jsparse.h +0 -511
  279. data/vendor/spidermonkey/jsprf.c +0 -1264
  280. data/vendor/spidermonkey/jsprf.h +0 -150
  281. data/vendor/spidermonkey/jsproto.tbl +0 -128
  282. data/vendor/spidermonkey/jsprvtd.h +0 -267
  283. data/vendor/spidermonkey/jspubtd.h +0 -744
  284. data/vendor/spidermonkey/jsregexp.c +0 -4364
  285. data/vendor/spidermonkey/jsregexp.h +0 -183
  286. data/vendor/spidermonkey/jsreops.tbl +0 -145
  287. data/vendor/spidermonkey/jsscan.c +0 -2012
  288. data/vendor/spidermonkey/jsscan.h +0 -387
  289. data/vendor/spidermonkey/jsscope.c +0 -1957
  290. data/vendor/spidermonkey/jsscope.h +0 -418
  291. data/vendor/spidermonkey/jsscript.c +0 -1832
  292. data/vendor/spidermonkey/jsscript.h +0 -287
  293. data/vendor/spidermonkey/jsshell.msg +0 -50
  294. data/vendor/spidermonkey/jsstddef.h +0 -83
  295. data/vendor/spidermonkey/jsstr.c +0 -5005
  296. data/vendor/spidermonkey/jsstr.h +0 -641
  297. data/vendor/spidermonkey/jstypes.h +0 -475
  298. data/vendor/spidermonkey/jsutil.c +0 -345
  299. data/vendor/spidermonkey/jsutil.h +0 -157
  300. data/vendor/spidermonkey/jsxdrapi.c +0 -800
  301. data/vendor/spidermonkey/jsxdrapi.h +0 -218
  302. data/vendor/spidermonkey/jsxml.c +0 -8476
  303. data/vendor/spidermonkey/jsxml.h +0 -349
  304. data/vendor/spidermonkey/lock_SunOS.s +0 -119
  305. data/vendor/spidermonkey/perfect.js +0 -39
  306. data/vendor/spidermonkey/plify_jsdhash.sed +0 -36
  307. data/vendor/spidermonkey/prmjtime.c +0 -846
  308. data/vendor/spidermonkey/prmjtime.h +0 -103
  309. data/vendor/spidermonkey/resource.h +0 -15
  310. data/vendor/spidermonkey/rules.mk +0 -197
  311. data/vendor/spidermonkey/win32.order +0 -384
@@ -1,56 +0,0 @@
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__ */
@@ -1,90 +0,0 @@
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
-
@@ -1,2634 +0,0 @@
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
- }