johnson 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (371) hide show
  1. data/.autotest +14 -0
  2. data/CHANGELOG.rdoc +11 -0
  3. data/Manifest.txt +370 -0
  4. data/README.rdoc +60 -0
  5. data/Rakefile +42 -0
  6. data/bin/johnson +108 -0
  7. data/docs/MINGW32.mk +124 -0
  8. data/docs/cross-compile.txt +38 -0
  9. data/ext/spidermonkey/context.c +115 -0
  10. data/ext/spidermonkey/context.h +19 -0
  11. data/ext/spidermonkey/conversions.c +320 -0
  12. data/ext/spidermonkey/conversions.h +18 -0
  13. data/ext/spidermonkey/debugger.c +226 -0
  14. data/ext/spidermonkey/debugger.h +9 -0
  15. data/ext/spidermonkey/extconf.rb +30 -0
  16. data/ext/spidermonkey/extensions.c +37 -0
  17. data/ext/spidermonkey/extensions.h +12 -0
  18. data/ext/spidermonkey/global.c +40 -0
  19. data/ext/spidermonkey/global.h +11 -0
  20. data/ext/spidermonkey/idhash.c +16 -0
  21. data/ext/spidermonkey/idhash.h +8 -0
  22. data/ext/spidermonkey/immutable_node.c +1153 -0
  23. data/ext/spidermonkey/immutable_node.c.erb +523 -0
  24. data/ext/spidermonkey/immutable_node.h +22 -0
  25. data/ext/spidermonkey/jroot.h +187 -0
  26. data/ext/spidermonkey/js_land_proxy.c +610 -0
  27. data/ext/spidermonkey/js_land_proxy.h +20 -0
  28. data/ext/spidermonkey/ruby_land_proxy.c +543 -0
  29. data/ext/spidermonkey/ruby_land_proxy.h +17 -0
  30. data/ext/spidermonkey/runtime.c +330 -0
  31. data/ext/spidermonkey/runtime.h +25 -0
  32. data/ext/spidermonkey/spidermonkey.c +20 -0
  33. data/ext/spidermonkey/spidermonkey.h +29 -0
  34. data/johnson.gemspec +44 -0
  35. data/js/johnson/cli.js +30 -0
  36. data/js/johnson/prelude.js +80 -0
  37. data/lib/johnson.rb +55 -0
  38. data/lib/johnson/cli.rb +7 -0
  39. data/lib/johnson/cli/options.rb +67 -0
  40. data/lib/johnson/error.rb +4 -0
  41. data/lib/johnson/nodes.rb +7 -0
  42. data/lib/johnson/nodes/binary_node.rb +65 -0
  43. data/lib/johnson/nodes/for.rb +14 -0
  44. data/lib/johnson/nodes/for_in.rb +12 -0
  45. data/lib/johnson/nodes/function.rb +13 -0
  46. data/lib/johnson/nodes/list.rb +28 -0
  47. data/lib/johnson/nodes/node.rb +68 -0
  48. data/lib/johnson/nodes/ternary_node.rb +20 -0
  49. data/lib/johnson/parser.rb +21 -0
  50. data/lib/johnson/parser/syntax_error.rb +13 -0
  51. data/lib/johnson/runtime.rb +63 -0
  52. data/lib/johnson/spidermonkey/context.rb +10 -0
  53. data/lib/johnson/spidermonkey/debugger.rb +67 -0
  54. data/lib/johnson/spidermonkey/immutable_node.rb +282 -0
  55. data/lib/johnson/spidermonkey/js_land_proxy.rb +62 -0
  56. data/lib/johnson/spidermonkey/mutable_tree_visitor.rb +242 -0
  57. data/lib/johnson/spidermonkey/ruby_land_proxy.rb +54 -0
  58. data/lib/johnson/spidermonkey/runtime.rb +103 -0
  59. data/lib/johnson/version.rb +3 -0
  60. data/lib/johnson/visitable.rb +16 -0
  61. data/lib/johnson/visitors.rb +5 -0
  62. data/lib/johnson/visitors/dot_visitor.rb +169 -0
  63. data/lib/johnson/visitors/ecma_visitor.rb +323 -0
  64. data/lib/johnson/visitors/enumerating_visitor.rb +15 -0
  65. data/lib/johnson/visitors/sexp_visitor.rb +174 -0
  66. data/lib/johnson/visitors/visitor.rb +91 -0
  67. data/lib/rails/init.rb +37 -0
  68. data/lib/tasks/gem.rake +9 -0
  69. data/lib/tasks/parsing.rake +37 -0
  70. data/lib/tasks/testing.rake +36 -0
  71. data/lib/tasks/vendor.rake +20 -0
  72. data/test/helper.rb +55 -0
  73. data/test/johnson/browser_test.rb +43 -0
  74. data/test/johnson/conversions/array_test.rb +32 -0
  75. data/test/johnson/conversions/boolean_test.rb +17 -0
  76. data/test/johnson/conversions/callable_test.rb +34 -0
  77. data/test/johnson/conversions/file_test.rb +15 -0
  78. data/test/johnson/conversions/nil_test.rb +20 -0
  79. data/test/johnson/conversions/number_test.rb +34 -0
  80. data/test/johnson/conversions/regexp_test.rb +24 -0
  81. data/test/johnson/conversions/string_test.rb +26 -0
  82. data/test/johnson/conversions/struct_test.rb +15 -0
  83. data/test/johnson/conversions/symbol_test.rb +19 -0
  84. data/test/johnson/conversions/thread_test.rb +24 -0
  85. data/test/johnson/error_test.rb +9 -0
  86. data/test/johnson/extensions_test.rb +56 -0
  87. data/test/johnson/nodes/array_literal_test.rb +57 -0
  88. data/test/johnson/nodes/array_node_test.rb +26 -0
  89. data/test/johnson/nodes/binary_node_test.rb +61 -0
  90. data/test/johnson/nodes/bracket_access_test.rb +16 -0
  91. data/test/johnson/nodes/delete_test.rb +11 -0
  92. data/test/johnson/nodes/do_while_test.rb +12 -0
  93. data/test/johnson/nodes/dot_accessor_test.rb +15 -0
  94. data/test/johnson/nodes/export_test.rb +9 -0
  95. data/test/johnson/nodes/for_test.rb +54 -0
  96. data/test/johnson/nodes/function_test.rb +71 -0
  97. data/test/johnson/nodes/if_test.rb +41 -0
  98. data/test/johnson/nodes/import_test.rb +13 -0
  99. data/test/johnson/nodes/label_test.rb +19 -0
  100. data/test/johnson/nodes/let_test.rb +31 -0
  101. data/test/johnson/nodes/object_literal_test.rb +110 -0
  102. data/test/johnson/nodes/return_test.rb +16 -0
  103. data/test/johnson/nodes/semi_test.rb +8 -0
  104. data/test/johnson/nodes/switch_test.rb +55 -0
  105. data/test/johnson/nodes/ternary_test.rb +25 -0
  106. data/test/johnson/nodes/throw_test.rb +9 -0
  107. data/test/johnson/nodes/try_node_test.rb +59 -0
  108. data/test/johnson/nodes/typeof_test.rb +11 -0
  109. data/test/johnson/nodes/unary_node_test.rb +23 -0
  110. data/test/johnson/nodes/void_test.rb +11 -0
  111. data/test/johnson/nodes/while_test.rb +26 -0
  112. data/test/johnson/nodes/with_test.rb +10 -0
  113. data/test/johnson/prelude_test.rb +56 -0
  114. data/test/johnson/runtime_test.rb +64 -0
  115. data/test/johnson/spidermonkey/context_test.rb +21 -0
  116. data/test/johnson/spidermonkey/immutable_node_test.rb +34 -0
  117. data/test/johnson/spidermonkey/js_land_proxy_test.rb +236 -0
  118. data/test/johnson/spidermonkey/ruby_land_proxy_test.rb +240 -0
  119. data/test/johnson/spidermonkey/runtime_test.rb +17 -0
  120. data/test/johnson/version_test.rb +13 -0
  121. data/test/johnson/visitors/dot_visitor_test.rb +39 -0
  122. data/test/johnson/visitors/enumerating_visitor_test.rb +12 -0
  123. data/test/johnson_test.rb +16 -0
  124. data/test/parser_test.rb +276 -0
  125. data/vendor/spidermonkey/.cvsignore +9 -0
  126. data/vendor/spidermonkey/Makefile.in +449 -0
  127. data/vendor/spidermonkey/Makefile.ref +365 -0
  128. data/vendor/spidermonkey/README.html +820 -0
  129. data/vendor/spidermonkey/SpiderMonkey.rsp +12 -0
  130. data/vendor/spidermonkey/Y.js +19 -0
  131. data/vendor/spidermonkey/build.mk +43 -0
  132. data/vendor/spidermonkey/config.mk +192 -0
  133. data/vendor/spidermonkey/config/AIX4.1.mk +65 -0
  134. data/vendor/spidermonkey/config/AIX4.2.mk +64 -0
  135. data/vendor/spidermonkey/config/AIX4.3.mk +65 -0
  136. data/vendor/spidermonkey/config/Darwin.mk +83 -0
  137. data/vendor/spidermonkey/config/Darwin1.3.mk +81 -0
  138. data/vendor/spidermonkey/config/Darwin1.4.mk +41 -0
  139. data/vendor/spidermonkey/config/Darwin5.2.mk +81 -0
  140. data/vendor/spidermonkey/config/Darwin5.3.mk +81 -0
  141. data/vendor/spidermonkey/config/HP-UXB.10.10.mk +77 -0
  142. data/vendor/spidermonkey/config/HP-UXB.10.20.mk +77 -0
  143. data/vendor/spidermonkey/config/HP-UXB.11.00.mk +80 -0
  144. data/vendor/spidermonkey/config/IRIX.mk +87 -0
  145. data/vendor/spidermonkey/config/IRIX5.3.mk +44 -0
  146. data/vendor/spidermonkey/config/IRIX6.1.mk +44 -0
  147. data/vendor/spidermonkey/config/IRIX6.2.mk +44 -0
  148. data/vendor/spidermonkey/config/IRIX6.3.mk +44 -0
  149. data/vendor/spidermonkey/config/IRIX6.5.mk +44 -0
  150. data/vendor/spidermonkey/config/Linux_All.mk +103 -0
  151. data/vendor/spidermonkey/config/Mac_OS10.0.mk +82 -0
  152. data/vendor/spidermonkey/config/OSF1V4.0.mk +72 -0
  153. data/vendor/spidermonkey/config/OSF1V5.0.mk +69 -0
  154. data/vendor/spidermonkey/config/SunOS4.1.4.mk +101 -0
  155. data/vendor/spidermonkey/config/SunOS5.10.mk +50 -0
  156. data/vendor/spidermonkey/config/SunOS5.3.mk +91 -0
  157. data/vendor/spidermonkey/config/SunOS5.4.mk +92 -0
  158. data/vendor/spidermonkey/config/SunOS5.5.1.mk +44 -0
  159. data/vendor/spidermonkey/config/SunOS5.5.mk +87 -0
  160. data/vendor/spidermonkey/config/SunOS5.6.mk +89 -0
  161. data/vendor/spidermonkey/config/SunOS5.7.mk +44 -0
  162. data/vendor/spidermonkey/config/SunOS5.8.mk +44 -0
  163. data/vendor/spidermonkey/config/SunOS5.9.mk +44 -0
  164. data/vendor/spidermonkey/config/WINNT4.0.mk +117 -0
  165. data/vendor/spidermonkey/config/WINNT5.0.mk +117 -0
  166. data/vendor/spidermonkey/config/WINNT5.1.mk +117 -0
  167. data/vendor/spidermonkey/config/WINNT5.2.mk +117 -0
  168. data/vendor/spidermonkey/config/WINNT6.0.mk +117 -0
  169. data/vendor/spidermonkey/config/dgux.mk +64 -0
  170. data/vendor/spidermonkey/editline/Makefile.ref +144 -0
  171. data/vendor/spidermonkey/editline/README +83 -0
  172. data/vendor/spidermonkey/editline/editline.3 +175 -0
  173. data/vendor/spidermonkey/editline/editline.c +1369 -0
  174. data/vendor/spidermonkey/editline/editline.h +135 -0
  175. data/vendor/spidermonkey/editline/sysunix.c +182 -0
  176. data/vendor/spidermonkey/editline/unix.h +82 -0
  177. data/vendor/spidermonkey/fdlibm/.cvsignore +7 -0
  178. data/vendor/spidermonkey/fdlibm/Makefile.in +127 -0
  179. data/vendor/spidermonkey/fdlibm/Makefile.ref +192 -0
  180. data/vendor/spidermonkey/fdlibm/e_acos.c +147 -0
  181. data/vendor/spidermonkey/fdlibm/e_acosh.c +105 -0
  182. data/vendor/spidermonkey/fdlibm/e_asin.c +156 -0
  183. data/vendor/spidermonkey/fdlibm/e_atan2.c +165 -0
  184. data/vendor/spidermonkey/fdlibm/e_atanh.c +110 -0
  185. data/vendor/spidermonkey/fdlibm/e_cosh.c +133 -0
  186. data/vendor/spidermonkey/fdlibm/e_exp.c +202 -0
  187. data/vendor/spidermonkey/fdlibm/e_fmod.c +184 -0
  188. data/vendor/spidermonkey/fdlibm/e_gamma.c +71 -0
  189. data/vendor/spidermonkey/fdlibm/e_gamma_r.c +70 -0
  190. data/vendor/spidermonkey/fdlibm/e_hypot.c +173 -0
  191. data/vendor/spidermonkey/fdlibm/e_j0.c +524 -0
  192. data/vendor/spidermonkey/fdlibm/e_j1.c +523 -0
  193. data/vendor/spidermonkey/fdlibm/e_jn.c +315 -0
  194. data/vendor/spidermonkey/fdlibm/e_lgamma.c +71 -0
  195. data/vendor/spidermonkey/fdlibm/e_lgamma_r.c +347 -0
  196. data/vendor/spidermonkey/fdlibm/e_log.c +184 -0
  197. data/vendor/spidermonkey/fdlibm/e_log10.c +134 -0
  198. data/vendor/spidermonkey/fdlibm/e_pow.c +386 -0
  199. data/vendor/spidermonkey/fdlibm/e_rem_pio2.c +222 -0
  200. data/vendor/spidermonkey/fdlibm/e_remainder.c +120 -0
  201. data/vendor/spidermonkey/fdlibm/e_scalb.c +89 -0
  202. data/vendor/spidermonkey/fdlibm/e_sinh.c +122 -0
  203. data/vendor/spidermonkey/fdlibm/e_sqrt.c +497 -0
  204. data/vendor/spidermonkey/fdlibm/fdlibm.h +273 -0
  205. data/vendor/spidermonkey/fdlibm/fdlibm.mak +1453 -0
  206. data/vendor/spidermonkey/fdlibm/fdlibm.mdp +0 -0
  207. data/vendor/spidermonkey/fdlibm/k_cos.c +135 -0
  208. data/vendor/spidermonkey/fdlibm/k_rem_pio2.c +354 -0
  209. data/vendor/spidermonkey/fdlibm/k_sin.c +114 -0
  210. data/vendor/spidermonkey/fdlibm/k_standard.c +785 -0
  211. data/vendor/spidermonkey/fdlibm/k_tan.c +170 -0
  212. data/vendor/spidermonkey/fdlibm/s_asinh.c +101 -0
  213. data/vendor/spidermonkey/fdlibm/s_atan.c +175 -0
  214. data/vendor/spidermonkey/fdlibm/s_cbrt.c +133 -0
  215. data/vendor/spidermonkey/fdlibm/s_ceil.c +120 -0
  216. data/vendor/spidermonkey/fdlibm/s_copysign.c +72 -0
  217. data/vendor/spidermonkey/fdlibm/s_cos.c +118 -0
  218. data/vendor/spidermonkey/fdlibm/s_erf.c +356 -0
  219. data/vendor/spidermonkey/fdlibm/s_expm1.c +267 -0
  220. data/vendor/spidermonkey/fdlibm/s_fabs.c +70 -0
  221. data/vendor/spidermonkey/fdlibm/s_finite.c +71 -0
  222. data/vendor/spidermonkey/fdlibm/s_floor.c +121 -0
  223. data/vendor/spidermonkey/fdlibm/s_frexp.c +99 -0
  224. data/vendor/spidermonkey/fdlibm/s_ilogb.c +85 -0
  225. data/vendor/spidermonkey/fdlibm/s_isnan.c +74 -0
  226. data/vendor/spidermonkey/fdlibm/s_ldexp.c +66 -0
  227. data/vendor/spidermonkey/fdlibm/s_lib_version.c +73 -0
  228. data/vendor/spidermonkey/fdlibm/s_log1p.c +211 -0
  229. data/vendor/spidermonkey/fdlibm/s_logb.c +79 -0
  230. data/vendor/spidermonkey/fdlibm/s_matherr.c +64 -0
  231. data/vendor/spidermonkey/fdlibm/s_modf.c +132 -0
  232. data/vendor/spidermonkey/fdlibm/s_nextafter.c +124 -0
  233. data/vendor/spidermonkey/fdlibm/s_rint.c +131 -0
  234. data/vendor/spidermonkey/fdlibm/s_scalbn.c +107 -0
  235. data/vendor/spidermonkey/fdlibm/s_signgam.c +40 -0
  236. data/vendor/spidermonkey/fdlibm/s_significand.c +68 -0
  237. data/vendor/spidermonkey/fdlibm/s_sin.c +118 -0
  238. data/vendor/spidermonkey/fdlibm/s_tan.c +112 -0
  239. data/vendor/spidermonkey/fdlibm/s_tanh.c +122 -0
  240. data/vendor/spidermonkey/fdlibm/w_acos.c +78 -0
  241. data/vendor/spidermonkey/fdlibm/w_acosh.c +78 -0
  242. data/vendor/spidermonkey/fdlibm/w_asin.c +80 -0
  243. data/vendor/spidermonkey/fdlibm/w_atan2.c +79 -0
  244. data/vendor/spidermonkey/fdlibm/w_atanh.c +81 -0
  245. data/vendor/spidermonkey/fdlibm/w_cosh.c +77 -0
  246. data/vendor/spidermonkey/fdlibm/w_exp.c +88 -0
  247. data/vendor/spidermonkey/fdlibm/w_fmod.c +78 -0
  248. data/vendor/spidermonkey/fdlibm/w_gamma.c +85 -0
  249. data/vendor/spidermonkey/fdlibm/w_gamma_r.c +81 -0
  250. data/vendor/spidermonkey/fdlibm/w_hypot.c +78 -0
  251. data/vendor/spidermonkey/fdlibm/w_j0.c +105 -0
  252. data/vendor/spidermonkey/fdlibm/w_j1.c +106 -0
  253. data/vendor/spidermonkey/fdlibm/w_jn.c +128 -0
  254. data/vendor/spidermonkey/fdlibm/w_lgamma.c +85 -0
  255. data/vendor/spidermonkey/fdlibm/w_lgamma_r.c +81 -0
  256. data/vendor/spidermonkey/fdlibm/w_log.c +78 -0
  257. data/vendor/spidermonkey/fdlibm/w_log10.c +81 -0
  258. data/vendor/spidermonkey/fdlibm/w_pow.c +99 -0
  259. data/vendor/spidermonkey/fdlibm/w_remainder.c +77 -0
  260. data/vendor/spidermonkey/fdlibm/w_scalb.c +95 -0
  261. data/vendor/spidermonkey/fdlibm/w_sinh.c +77 -0
  262. data/vendor/spidermonkey/fdlibm/w_sqrt.c +77 -0
  263. data/vendor/spidermonkey/javascript-trace.d +73 -0
  264. data/vendor/spidermonkey/js.c +3951 -0
  265. data/vendor/spidermonkey/js.mdp +0 -0
  266. data/vendor/spidermonkey/js.msg +308 -0
  267. data/vendor/spidermonkey/js3240.rc +79 -0
  268. data/vendor/spidermonkey/jsOS240.def +654 -0
  269. data/vendor/spidermonkey/jsapi.c +5836 -0
  270. data/vendor/spidermonkey/jsapi.h +2624 -0
  271. data/vendor/spidermonkey/jsarena.c +450 -0
  272. data/vendor/spidermonkey/jsarena.h +318 -0
  273. data/vendor/spidermonkey/jsarray.c +2996 -0
  274. data/vendor/spidermonkey/jsarray.h +127 -0
  275. data/vendor/spidermonkey/jsatom.c +1045 -0
  276. data/vendor/spidermonkey/jsatom.h +442 -0
  277. data/vendor/spidermonkey/jsbit.h +253 -0
  278. data/vendor/spidermonkey/jsbool.c +176 -0
  279. data/vendor/spidermonkey/jsbool.h +73 -0
  280. data/vendor/spidermonkey/jsclist.h +139 -0
  281. data/vendor/spidermonkey/jscntxt.c +1348 -0
  282. data/vendor/spidermonkey/jscntxt.h +1120 -0
  283. data/vendor/spidermonkey/jscompat.h +57 -0
  284. data/vendor/spidermonkey/jsconfig.h +248 -0
  285. data/vendor/spidermonkey/jsconfig.mk +181 -0
  286. data/vendor/spidermonkey/jscpucfg.c +396 -0
  287. data/vendor/spidermonkey/jscpucfg.h +212 -0
  288. data/vendor/spidermonkey/jsdate.c +2390 -0
  289. data/vendor/spidermonkey/jsdate.h +124 -0
  290. data/vendor/spidermonkey/jsdbgapi.c +1802 -0
  291. data/vendor/spidermonkey/jsdbgapi.h +464 -0
  292. data/vendor/spidermonkey/jsdhash.c +868 -0
  293. data/vendor/spidermonkey/jsdhash.h +592 -0
  294. data/vendor/spidermonkey/jsdtoa.c +3167 -0
  295. data/vendor/spidermonkey/jsdtoa.h +130 -0
  296. data/vendor/spidermonkey/jsdtracef.c +317 -0
  297. data/vendor/spidermonkey/jsdtracef.h +77 -0
  298. data/vendor/spidermonkey/jsemit.c +6909 -0
  299. data/vendor/spidermonkey/jsemit.h +741 -0
  300. data/vendor/spidermonkey/jsexn.c +1371 -0
  301. data/vendor/spidermonkey/jsexn.h +96 -0
  302. data/vendor/spidermonkey/jsfile.c +2736 -0
  303. data/vendor/spidermonkey/jsfile.h +56 -0
  304. data/vendor/spidermonkey/jsfile.msg +90 -0
  305. data/vendor/spidermonkey/jsfun.c +2634 -0
  306. data/vendor/spidermonkey/jsfun.h +254 -0
  307. data/vendor/spidermonkey/jsgc.c +3562 -0
  308. data/vendor/spidermonkey/jsgc.h +403 -0
  309. data/vendor/spidermonkey/jshash.c +476 -0
  310. data/vendor/spidermonkey/jshash.h +151 -0
  311. data/vendor/spidermonkey/jsify.pl +485 -0
  312. data/vendor/spidermonkey/jsinterp.c +7007 -0
  313. data/vendor/spidermonkey/jsinterp.h +525 -0
  314. data/vendor/spidermonkey/jsinvoke.c +43 -0
  315. data/vendor/spidermonkey/jsiter.c +1067 -0
  316. data/vendor/spidermonkey/jsiter.h +122 -0
  317. data/vendor/spidermonkey/jskeyword.tbl +124 -0
  318. data/vendor/spidermonkey/jskwgen.c +460 -0
  319. data/vendor/spidermonkey/jslibmath.h +266 -0
  320. data/vendor/spidermonkey/jslock.c +1309 -0
  321. data/vendor/spidermonkey/jslock.h +313 -0
  322. data/vendor/spidermonkey/jslocko.asm +60 -0
  323. data/vendor/spidermonkey/jslog2.c +94 -0
  324. data/vendor/spidermonkey/jslong.c +264 -0
  325. data/vendor/spidermonkey/jslong.h +412 -0
  326. data/vendor/spidermonkey/jsmath.c +567 -0
  327. data/vendor/spidermonkey/jsmath.h +57 -0
  328. data/vendor/spidermonkey/jsnum.c +1239 -0
  329. data/vendor/spidermonkey/jsnum.h +283 -0
  330. data/vendor/spidermonkey/jsobj.c +5282 -0
  331. data/vendor/spidermonkey/jsobj.h +709 -0
  332. data/vendor/spidermonkey/jsopcode.c +5245 -0
  333. data/vendor/spidermonkey/jsopcode.h +394 -0
  334. data/vendor/spidermonkey/jsopcode.tbl +523 -0
  335. data/vendor/spidermonkey/jsotypes.h +202 -0
  336. data/vendor/spidermonkey/jsparse.c +6704 -0
  337. data/vendor/spidermonkey/jsparse.h +511 -0
  338. data/vendor/spidermonkey/jsprf.c +1262 -0
  339. data/vendor/spidermonkey/jsprf.h +150 -0
  340. data/vendor/spidermonkey/jsproto.tbl +128 -0
  341. data/vendor/spidermonkey/jsprvtd.h +267 -0
  342. data/vendor/spidermonkey/jspubtd.h +744 -0
  343. data/vendor/spidermonkey/jsregexp.c +4364 -0
  344. data/vendor/spidermonkey/jsregexp.h +183 -0
  345. data/vendor/spidermonkey/jsreops.tbl +145 -0
  346. data/vendor/spidermonkey/jsscan.c +2012 -0
  347. data/vendor/spidermonkey/jsscan.h +387 -0
  348. data/vendor/spidermonkey/jsscope.c +1957 -0
  349. data/vendor/spidermonkey/jsscope.h +418 -0
  350. data/vendor/spidermonkey/jsscript.c +1832 -0
  351. data/vendor/spidermonkey/jsscript.h +287 -0
  352. data/vendor/spidermonkey/jsshell.msg +50 -0
  353. data/vendor/spidermonkey/jsstddef.h +83 -0
  354. data/vendor/spidermonkey/jsstr.c +5005 -0
  355. data/vendor/spidermonkey/jsstr.h +641 -0
  356. data/vendor/spidermonkey/jstypes.h +475 -0
  357. data/vendor/spidermonkey/jsutil.c +345 -0
  358. data/vendor/spidermonkey/jsutil.h +157 -0
  359. data/vendor/spidermonkey/jsxdrapi.c +800 -0
  360. data/vendor/spidermonkey/jsxdrapi.h +218 -0
  361. data/vendor/spidermonkey/jsxml.c +8476 -0
  362. data/vendor/spidermonkey/jsxml.h +349 -0
  363. data/vendor/spidermonkey/lock_SunOS.s +119 -0
  364. data/vendor/spidermonkey/perfect.js +39 -0
  365. data/vendor/spidermonkey/plify_jsdhash.sed +36 -0
  366. data/vendor/spidermonkey/prmjtime.c +846 -0
  367. data/vendor/spidermonkey/prmjtime.h +103 -0
  368. data/vendor/spidermonkey/resource.h +15 -0
  369. data/vendor/spidermonkey/rules.mk +197 -0
  370. data/vendor/spidermonkey/win32.order +384 -0
  371. metadata +513 -0
@@ -0,0 +1,77 @@
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
+ * Sun Microsystems, Inc.
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
+ /* @(#)w_sqrt.c 1.3 95/01/18 */
41
+ /*
42
+ * ====================================================
43
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
44
+ *
45
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
46
+ * Permission to use, copy, modify, and distribute this
47
+ * software is freely granted, provided that this notice
48
+ * is preserved.
49
+ * ====================================================
50
+ */
51
+
52
+ /*
53
+ * wrapper sqrt(x)
54
+ */
55
+
56
+ #include "fdlibm.h"
57
+
58
+ #ifdef __STDC__
59
+ double fd_sqrt(double x) /* wrapper sqrt */
60
+ #else
61
+ double fd_sqrt(x) /* wrapper sqrt */
62
+ double x;
63
+ #endif
64
+ {
65
+ #ifdef _IEEE_LIBM
66
+ return __ieee754_sqrt(x);
67
+ #else
68
+ double z;
69
+ z = __ieee754_sqrt(x);
70
+ if(_LIB_VERSION == _IEEE_ || fd_isnan(x)) return z;
71
+ if(x<0.0) {
72
+ int err;
73
+ return __kernel_standard(x,x,26,&err); /* sqrt(negative) */
74
+ } else
75
+ return z;
76
+ #endif
77
+ }
@@ -0,0 +1,73 @@
1
+ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
+ /* ***** BEGIN LICENSE BLOCK *****
3
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4
+ *
5
+ * The contents of this file are subject to the Mozilla Public License Version
6
+ * 1.1 (the "License"); you may not use this file except in compliance with
7
+ * the License. You may obtain a copy of the License at
8
+ * http://www.mozilla.org/MPL/
9
+ *
10
+ * Software distributed under the License is distributed on an "AS IS" basis,
11
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12
+ * for the specific language governing rights and limitations under the
13
+ * License.
14
+ *
15
+ * Copyright (C) 2007 Sun Microsystems, Inc. All Rights Reserved.
16
+ *
17
+ * Alternatively, the contents of this file may be used under the terms of
18
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
19
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
20
+ * in which case the provisions of the GPL or the LGPL are applicable instead
21
+ * of those above. If you wish to allow use of your version of this file only
22
+ * under the terms of either the GPL or the LGPL, and not to allow others to
23
+ * use your version of this file under the terms of the MPL, indicate your
24
+ * decision by deleting the provisions above and replace them with the notice
25
+ * and other provisions required by the GPL or the LGPL. If you do not delete
26
+ * the provisions above, a recipient may use your version of this file under
27
+ * the terms of any one of the MPL, the GPL or the LGPL.
28
+ *
29
+ * ***** END LICENSE BLOCK ***** */
30
+
31
+ /*
32
+ * javascript provider probes
33
+ *
34
+ * function-entry (filename, classname, funcname)
35
+ * function-info (filename, classname, funcname, lineno,
36
+ * runfilename, runlineno)
37
+ * function-args (filename, classname, funcname, argc, argv, argv0,
38
+ * argv1, argv2, argv3, argv4)
39
+ * function-rval (filename, classname, funcname, lineno, rval, rval0)
40
+ * function-return (filename, classname, funcname)
41
+ * object-create-start (filename, classname)
42
+ * object-create (filename, classname, *object, rlineno)
43
+ * object-create-done (filename, classname)
44
+ * object-finalize (NULL, classname, *object)
45
+ * execute-start (filename, lineno)
46
+ * execute-done (filename, lineno)
47
+ */
48
+
49
+ provider javascript {
50
+ probe function__entry(char *, char *, char *);
51
+ probe function__info(char *, char *, char *, int, char *, int);
52
+ probe function__args(char *, char *, char *, int, void *, void *, void *,
53
+ void *, void *, void *);
54
+ probe function__rval(char *, char *, char *, int, void *, void *);
55
+ probe function__return(char *, char *, char *);
56
+ probe object__create__start(char *, char *);
57
+ probe object__create__done(char *, char *);
58
+ /* XXX must use unsigned longs here instead of uintptr_t for OS X
59
+ (Apple radar: 5194316 & 5565198) */
60
+ probe object__create(char *, char *, unsigned long, int);
61
+ probe object__finalize(char *, char *, unsigned long);
62
+ probe execute__start(char *, int);
63
+ probe execute__done(char *, int);
64
+ };
65
+
66
+ /*
67
+ #pragma D attributes Unstable/Unstable/Common provider mozilla provider
68
+ #pragma D attributes Private/Private/Unknown provider mozilla module
69
+ #pragma D attributes Private/Private/Unknown provider mozilla function
70
+ #pragma D attributes Unstable/Unstable/Common provider mozilla name
71
+ #pragma D attributes Unstable/Unstable/Common provider mozilla args
72
+ */
73
+
@@ -0,0 +1,3951 @@
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 shell.
43
+ */
44
+ #include "jsstddef.h"
45
+ #include <errno.h>
46
+ #include <stdio.h>
47
+ #include <stdlib.h>
48
+ #include <string.h>
49
+ #include <locale.h>
50
+ #include "jstypes.h"
51
+ #include "jsarena.h"
52
+ #include "jsutil.h"
53
+ #include "jsprf.h"
54
+ #include "jsapi.h"
55
+ #include "jsarray.h"
56
+ #include "jsatom.h"
57
+ #include "jscntxt.h"
58
+ #include "jsdbgapi.h"
59
+ #include "jsemit.h"
60
+ #include "jsfun.h"
61
+ #include "jsgc.h"
62
+ #include "jslock.h"
63
+ #include "jsnum.h"
64
+ #include "jsobj.h"
65
+ #include "jsparse.h"
66
+ #include "jsscope.h"
67
+ #include "jsscript.h"
68
+
69
+ #ifdef LIVECONNECT
70
+ #include "jsjava.h"
71
+ #endif
72
+
73
+ #ifdef JSDEBUGGER
74
+ #include "jsdebug.h"
75
+ #ifdef JSDEBUGGER_JAVA_UI
76
+ #include "jsdjava.h"
77
+ #endif /* JSDEBUGGER_JAVA_UI */
78
+ #ifdef JSDEBUGGER_C_UI
79
+ #include "jsdb.h"
80
+ #endif /* JSDEBUGGER_C_UI */
81
+ #endif /* JSDEBUGGER */
82
+
83
+ #ifdef XP_UNIX
84
+ #include <unistd.h>
85
+ #include <sys/types.h>
86
+ #include <sys/wait.h>
87
+ #endif
88
+
89
+ #if defined(XP_WIN) || defined(XP_OS2)
90
+ #include <io.h> /* for isatty() */
91
+ #endif
92
+
93
+ typedef enum JSShellExitCode {
94
+ EXITCODE_RUNTIME_ERROR = 3,
95
+ EXITCODE_FILE_NOT_FOUND = 4,
96
+ EXITCODE_OUT_OF_MEMORY = 5
97
+ } JSShellExitCode;
98
+
99
+ size_t gStackChunkSize = 8192;
100
+
101
+ /* Assume that we can not use more than 5e5 bytes of C stack by default. */
102
+ static size_t gMaxStackSize = 500000;
103
+ static jsuword gStackBase;
104
+
105
+ static size_t gScriptStackQuota = JS_DEFAULT_SCRIPT_STACK_QUOTA;
106
+
107
+ static JSBool gEnableBranchCallback = JS_FALSE;
108
+ static uint32 gBranchCount;
109
+ static uint32 gBranchLimit;
110
+
111
+ int gExitCode = 0;
112
+ JSBool gQuitting = JS_FALSE;
113
+ FILE *gErrFile = NULL;
114
+ FILE *gOutFile = NULL;
115
+
116
+ static JSBool reportWarnings = JS_TRUE;
117
+ static JSBool compileOnly = JS_FALSE;
118
+
119
+ typedef enum JSShellErrNum {
120
+ #define MSG_DEF(name, number, count, exception, format) \
121
+ name = number,
122
+ #include "jsshell.msg"
123
+ #undef MSG_DEF
124
+ JSShellErr_Limit
125
+ #undef MSGDEF
126
+ } JSShellErrNum;
127
+
128
+ static const JSErrorFormatString *
129
+ my_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber);
130
+ static JSObject *
131
+ split_setup(JSContext *cx);
132
+
133
+ #ifdef EDITLINE
134
+ JS_BEGIN_EXTERN_C
135
+ extern char *readline(const char *prompt);
136
+ extern void add_history(char *line);
137
+ JS_END_EXTERN_C
138
+ #endif
139
+
140
+ static JSBool
141
+ GetLine(JSContext *cx, char *bufp, FILE *file, const char *prompt) {
142
+ #ifdef EDITLINE
143
+ /*
144
+ * Use readline only if file is stdin, because there's no way to specify
145
+ * another handle. Are other filehandles interactive?
146
+ */
147
+ if (file == stdin) {
148
+ char *linep = readline(prompt);
149
+ if (!linep)
150
+ return JS_FALSE;
151
+ if (linep[0] != '\0')
152
+ add_history(linep);
153
+ strcpy(bufp, linep);
154
+ JS_free(cx, linep);
155
+ bufp += strlen(bufp);
156
+ *bufp++ = '\n';
157
+ *bufp = '\0';
158
+ } else
159
+ #endif
160
+ {
161
+ char line[256];
162
+ fprintf(gOutFile, prompt);
163
+ fflush(gOutFile);
164
+ if (!fgets(line, sizeof line, file))
165
+ return JS_FALSE;
166
+ strcpy(bufp, line);
167
+ }
168
+ return JS_TRUE;
169
+ }
170
+
171
+ static JSBool
172
+ my_BranchCallback(JSContext *cx, JSScript *script)
173
+ {
174
+ if (++gBranchCount == gBranchLimit) {
175
+ if (script) {
176
+ if (script->filename)
177
+ fprintf(gErrFile, "%s:", script->filename);
178
+ fprintf(gErrFile, "%u: script branch callback (%u callbacks)\n",
179
+ script->lineno, gBranchLimit);
180
+ } else {
181
+ fprintf(gErrFile, "native branch callback (%u callbacks)\n",
182
+ gBranchLimit);
183
+ }
184
+ gBranchCount = 0;
185
+ return JS_FALSE;
186
+ }
187
+ #ifdef JS_THREADSAFE
188
+ if ((gBranchCount & 0xff) == 1) {
189
+ #endif
190
+ if ((gBranchCount & 0x3fff) == 1)
191
+ JS_MaybeGC(cx);
192
+ #ifdef JS_THREADSAFE
193
+ else
194
+ JS_YieldRequest(cx);
195
+ }
196
+ #endif
197
+ return JS_TRUE;
198
+ }
199
+
200
+ static void
201
+ SetContextOptions(JSContext *cx)
202
+ {
203
+ jsuword stackLimit;
204
+
205
+ if (gMaxStackSize == 0) {
206
+ /*
207
+ * Disable checking for stack overflow if limit is zero.
208
+ */
209
+ stackLimit = 0;
210
+ } else {
211
+ #if JS_STACK_GROWTH_DIRECTION > 0
212
+ stackLimit = gStackBase + gMaxStackSize;
213
+ #else
214
+ stackLimit = gStackBase - gMaxStackSize;
215
+ #endif
216
+ }
217
+ JS_SetThreadStackLimit(cx, stackLimit);
218
+ JS_SetScriptStackQuota(cx, gScriptStackQuota);
219
+ if (gEnableBranchCallback) {
220
+ JS_SetBranchCallback(cx, my_BranchCallback);
221
+ JS_ToggleOptions(cx, JSOPTION_NATIVE_BRANCH_CALLBACK);
222
+ }
223
+ }
224
+
225
+ static void
226
+ Process(JSContext *cx, JSObject *obj, char *filename, JSBool forceTTY)
227
+ {
228
+ JSBool ok, hitEOF;
229
+ JSScript *script;
230
+ jsval result;
231
+ JSString *str;
232
+ char buffer[4096];
233
+ char *bufp;
234
+ int lineno;
235
+ int startline;
236
+ FILE *file;
237
+
238
+ if (forceTTY || !filename || strcmp(filename, "-") == 0) {
239
+ file = stdin;
240
+ } else {
241
+ file = fopen(filename, "r");
242
+ if (!file) {
243
+ JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL,
244
+ JSSMSG_CANT_OPEN, filename, strerror(errno));
245
+ gExitCode = EXITCODE_FILE_NOT_FOUND;
246
+ return;
247
+ }
248
+ }
249
+
250
+ SetContextOptions(cx);
251
+
252
+ if (!forceTTY && !isatty(fileno(file))) {
253
+ /*
254
+ * It's not interactive - just execute it.
255
+ *
256
+ * Support the UNIX #! shell hack; gobble the first line if it starts
257
+ * with '#'. TODO - this isn't quite compatible with sharp variables,
258
+ * as a legal js program (using sharp variables) might start with '#'.
259
+ * But that would require multi-character lookahead.
260
+ */
261
+ int ch = fgetc(file);
262
+ if (ch == '#') {
263
+ while((ch = fgetc(file)) != EOF) {
264
+ if (ch == '\n' || ch == '\r')
265
+ break;
266
+ }
267
+ }
268
+ ungetc(ch, file);
269
+ script = JS_CompileFileHandle(cx, obj, filename, file);
270
+ if (script) {
271
+ if (!compileOnly)
272
+ (void)JS_ExecuteScript(cx, obj, script, &result);
273
+ JS_DestroyScript(cx, script);
274
+ }
275
+
276
+ if (file != stdin)
277
+ fclose(file);
278
+ return;
279
+ }
280
+
281
+ /* It's an interactive filehandle; drop into read-eval-print loop. */
282
+ lineno = 1;
283
+ hitEOF = JS_FALSE;
284
+ do {
285
+ bufp = buffer;
286
+ *bufp = '\0';
287
+
288
+ /*
289
+ * Accumulate lines until we get a 'compilable unit' - one that either
290
+ * generates an error (before running out of source) or that compiles
291
+ * cleanly. This should be whenever we get a complete statement that
292
+ * coincides with the end of a line.
293
+ */
294
+ startline = lineno;
295
+ do {
296
+ if (!GetLine(cx, bufp, file, startline == lineno ? "js> " : "")) {
297
+ hitEOF = JS_TRUE;
298
+ break;
299
+ }
300
+ bufp += strlen(bufp);
301
+ lineno++;
302
+ } while (!JS_BufferIsCompilableUnit(cx, obj, buffer, strlen(buffer)));
303
+
304
+ /* Clear any pending exception from previous failed compiles. */
305
+ JS_ClearPendingException(cx);
306
+ script = JS_CompileScript(cx, obj, buffer, strlen(buffer), "typein",
307
+ startline);
308
+ if (script) {
309
+ if (!compileOnly) {
310
+ ok = JS_ExecuteScript(cx, obj, script, &result);
311
+ if (ok && result != JSVAL_VOID) {
312
+ str = JS_ValueToString(cx, result);
313
+ if (str)
314
+ fprintf(gOutFile, "%s\n", JS_GetStringBytes(str));
315
+ else
316
+ ok = JS_FALSE;
317
+ }
318
+ }
319
+ JS_DestroyScript(cx, script);
320
+ }
321
+ } while (!hitEOF && !gQuitting);
322
+ fprintf(gOutFile, "\n");
323
+ if (file != stdin)
324
+ fclose(file);
325
+ return;
326
+ }
327
+
328
+ static int
329
+ usage(void)
330
+ {
331
+ fprintf(gErrFile, "%s\n", JS_GetImplementationVersion());
332
+ fprintf(gErrFile, "usage: js [-zKPswWxCi] [-b branchlimit] [-c stackchunksize] [-o option] [-v version] [-f scriptfile] [-e script] [-S maxstacksize] "
333
+ #ifdef JS_GC_ZEAL
334
+ "[-Z gczeal] "
335
+ #endif
336
+ "[scriptfile] [scriptarg...]\n");
337
+ return 2;
338
+ }
339
+
340
+ static struct {
341
+ const char *name;
342
+ uint32 flag;
343
+ } js_options[] = {
344
+ {"strict", JSOPTION_STRICT},
345
+ {"werror", JSOPTION_WERROR},
346
+ {"atline", JSOPTION_ATLINE},
347
+ {"xml", JSOPTION_XML},
348
+ {"relimit", JSOPTION_RELIMIT},
349
+ {"anonfunfix", JSOPTION_ANONFUNFIX},
350
+ {NULL, 0}
351
+ };
352
+
353
+ extern JSClass global_class;
354
+
355
+ static int
356
+ ProcessArgs(JSContext *cx, JSObject *obj, char **argv, int argc)
357
+ {
358
+ int i, j, length;
359
+ JSObject *argsObj;
360
+ char *filename = NULL;
361
+ JSBool isInteractive = JS_TRUE;
362
+ JSBool forceTTY = JS_FALSE;
363
+
364
+ /*
365
+ * Scan past all optional arguments so we can create the arguments object
366
+ * before processing any -f options, which must interleave properly with
367
+ * -v and -w options. This requires two passes, and without getopt, we'll
368
+ * have to keep the option logic here and in the second for loop in sync.
369
+ */
370
+ for (i = 0; i < argc; i++) {
371
+ if (argv[i][0] != '-' || argv[i][1] == '\0') {
372
+ ++i;
373
+ break;
374
+ }
375
+ switch (argv[i][1]) {
376
+ case 'b':
377
+ case 'c':
378
+ case 'f':
379
+ case 'e':
380
+ case 'v':
381
+ case 'S':
382
+ #ifdef JS_GC_ZEAL
383
+ case 'Z':
384
+ #endif
385
+ ++i;
386
+ break;
387
+ default:;
388
+ }
389
+ }
390
+
391
+ /*
392
+ * Create arguments early and define it to root it, so it's safe from any
393
+ * GC calls nested below, and so it is available to -f <file> arguments.
394
+ */
395
+ argsObj = JS_NewArrayObject(cx, 0, NULL);
396
+ if (!argsObj)
397
+ return 1;
398
+ if (!JS_DefineProperty(cx, obj, "arguments", OBJECT_TO_JSVAL(argsObj),
399
+ NULL, NULL, 0)) {
400
+ return 1;
401
+ }
402
+
403
+ length = argc - i;
404
+ for (j = 0; j < length; j++) {
405
+ JSString *str = JS_NewStringCopyZ(cx, argv[i++]);
406
+ if (!str)
407
+ return 1;
408
+ if (!JS_DefineElement(cx, argsObj, j, STRING_TO_JSVAL(str),
409
+ NULL, NULL, JSPROP_ENUMERATE)) {
410
+ return 1;
411
+ }
412
+ }
413
+
414
+ for (i = 0; i < argc; i++) {
415
+ if (argv[i][0] != '-' || argv[i][1] == '\0') {
416
+ filename = argv[i++];
417
+ isInteractive = JS_FALSE;
418
+ break;
419
+ }
420
+
421
+ switch (argv[i][1]) {
422
+ case 'v':
423
+ if (++i == argc)
424
+ return usage();
425
+
426
+ JS_SetVersion(cx, (JSVersion) atoi(argv[i]));
427
+ break;
428
+
429
+ #ifdef JS_GC_ZEAL
430
+ case 'Z':
431
+ if (++i == argc)
432
+ return usage();
433
+ JS_SetGCZeal(cx, atoi(argv[i]));
434
+ break;
435
+ #endif
436
+
437
+ case 'w':
438
+ reportWarnings = JS_TRUE;
439
+ break;
440
+
441
+ case 'W':
442
+ reportWarnings = JS_FALSE;
443
+ break;
444
+
445
+ case 's':
446
+ JS_ToggleOptions(cx, JSOPTION_STRICT);
447
+ break;
448
+
449
+ case 'E':
450
+ JS_ToggleOptions(cx, JSOPTION_RELIMIT);
451
+ break;
452
+
453
+ case 'x':
454
+ JS_ToggleOptions(cx, JSOPTION_XML);
455
+ break;
456
+
457
+ case 'o':
458
+ if (++i == argc)
459
+ return usage();
460
+
461
+ for (j = 0; js_options[j].name; ++j) {
462
+ if (strcmp(js_options[j].name, argv[i]) == 0) {
463
+ JS_ToggleOptions(cx, js_options[j].flag);
464
+ break;
465
+ }
466
+ }
467
+ break;
468
+
469
+ case 'P':
470
+ if (JS_GET_CLASS(cx, JS_GetPrototype(cx, obj)) != &global_class) {
471
+ JSObject *gobj;
472
+
473
+ if (!JS_SealObject(cx, obj, JS_TRUE))
474
+ return JS_FALSE;
475
+ gobj = JS_NewObject(cx, &global_class, NULL, NULL);
476
+ if (!gobj)
477
+ return JS_FALSE;
478
+ if (!JS_SetPrototype(cx, gobj, obj))
479
+ return JS_FALSE;
480
+ JS_SetParent(cx, gobj, NULL);
481
+ JS_SetGlobalObject(cx, gobj);
482
+ obj = gobj;
483
+ }
484
+ break;
485
+
486
+ case 'b':
487
+ gBranchLimit = atoi(argv[++i]);
488
+ gEnableBranchCallback = (gBranchLimit != 0);
489
+ break;
490
+
491
+ case 'c':
492
+ /* set stack chunk size */
493
+ gStackChunkSize = atoi(argv[++i]);
494
+ break;
495
+
496
+ case 'f':
497
+ if (++i == argc)
498
+ return usage();
499
+
500
+ Process(cx, obj, argv[i], JS_FALSE);
501
+
502
+ /*
503
+ * XXX: js -f foo.js should interpret foo.js and then
504
+ * drop into interactive mode, but that breaks the test
505
+ * harness. Just execute foo.js for now.
506
+ */
507
+ isInteractive = JS_FALSE;
508
+ break;
509
+
510
+ case 'e':
511
+ {
512
+ jsval rval;
513
+
514
+ if (++i == argc)
515
+ return usage();
516
+
517
+ /* Pass a filename of -e to imitate PERL */
518
+ JS_EvaluateScript(cx, obj, argv[i], strlen(argv[i]),
519
+ "-e", 1, &rval);
520
+
521
+ isInteractive = JS_FALSE;
522
+ break;
523
+
524
+ }
525
+ case 'C':
526
+ compileOnly = JS_TRUE;
527
+ isInteractive = JS_FALSE;
528
+ break;
529
+
530
+ case 'i':
531
+ isInteractive = forceTTY = JS_TRUE;
532
+ break;
533
+
534
+ case 'S':
535
+ if (++i == argc)
536
+ return usage();
537
+
538
+ /* Set maximum stack size. */
539
+ gMaxStackSize = atoi(argv[i]);
540
+ break;
541
+
542
+ case 'z':
543
+ obj = split_setup(cx);
544
+ break;
545
+ #ifdef MOZ_SHARK
546
+ case 'k':
547
+ JS_ConnectShark();
548
+ break;
549
+ #endif
550
+ default:
551
+ return usage();
552
+ }
553
+ }
554
+
555
+ if (filename || isInteractive)
556
+ Process(cx, obj, filename, forceTTY);
557
+ return gExitCode;
558
+ }
559
+
560
+ static JSBool
561
+ Version(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
562
+ {
563
+ if (argc > 0 && JSVAL_IS_INT(argv[0]))
564
+ *rval = INT_TO_JSVAL(JS_SetVersion(cx, (JSVersion) JSVAL_TO_INT(argv[0])));
565
+ else
566
+ *rval = INT_TO_JSVAL(JS_GetVersion(cx));
567
+ return JS_TRUE;
568
+ }
569
+
570
+ static JSBool
571
+ Options(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
572
+ {
573
+ uint32 optset, flag;
574
+ uintN i, j, found;
575
+ JSString *str;
576
+ const char *opt;
577
+ char *names;
578
+
579
+ optset = 0;
580
+ for (i = 0; i < argc; i++) {
581
+ str = JS_ValueToString(cx, argv[i]);
582
+ if (!str)
583
+ return JS_FALSE;
584
+ opt = JS_GetStringBytes(str);
585
+ for (j = 0; js_options[j].name; j++) {
586
+ if (strcmp(js_options[j].name, opt) == 0) {
587
+ optset |= js_options[j].flag;
588
+ break;
589
+ }
590
+ }
591
+ }
592
+ optset = JS_ToggleOptions(cx, optset);
593
+
594
+ names = NULL;
595
+ found = 0;
596
+ while (optset != 0) {
597
+ flag = optset;
598
+ optset &= optset - 1;
599
+ flag &= ~optset;
600
+ for (j = 0; js_options[j].name; j++) {
601
+ if (js_options[j].flag == flag) {
602
+ names = JS_sprintf_append(names, "%s%s",
603
+ names ? "," : "", js_options[j].name);
604
+ found++;
605
+ break;
606
+ }
607
+ }
608
+ }
609
+ if (!found)
610
+ names = strdup("");
611
+ if (!names) {
612
+ JS_ReportOutOfMemory(cx);
613
+ return JS_FALSE;
614
+ }
615
+
616
+ str = JS_NewString(cx, names, strlen(names));
617
+ if (!str) {
618
+ free(names);
619
+ return JS_FALSE;
620
+ }
621
+ *rval = STRING_TO_JSVAL(str);
622
+ return JS_TRUE;
623
+ }
624
+
625
+ static JSBool
626
+ Load(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
627
+ {
628
+ uintN i;
629
+ JSString *str;
630
+ const char *filename;
631
+ JSScript *script;
632
+ JSBool ok;
633
+ jsval result;
634
+ uint32 oldopts;
635
+
636
+ for (i = 0; i < argc; i++) {
637
+ str = JS_ValueToString(cx, argv[i]);
638
+ if (!str)
639
+ return JS_FALSE;
640
+ argv[i] = STRING_TO_JSVAL(str);
641
+ filename = JS_GetStringBytes(str);
642
+ errno = 0;
643
+ oldopts = JS_GetOptions(cx);
644
+ JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO);
645
+ script = JS_CompileFile(cx, obj, filename);
646
+ if (!script) {
647
+ ok = JS_FALSE;
648
+ } else {
649
+ ok = !compileOnly
650
+ ? JS_ExecuteScript(cx, obj, script, &result)
651
+ : JS_TRUE;
652
+ JS_DestroyScript(cx, script);
653
+ }
654
+ JS_SetOptions(cx, oldopts);
655
+ if (!ok)
656
+ return JS_FALSE;
657
+ }
658
+
659
+ return JS_TRUE;
660
+ }
661
+
662
+ /*
663
+ * function readline()
664
+ * Provides a hook for scripts to read a line from stdin.
665
+ */
666
+ static JSBool
667
+ ReadLine(JSContext *cx, uintN argc, jsval *vp)
668
+ {
669
+ #define BUFSIZE 256
670
+ FILE *from;
671
+ char *buf, *tmp;
672
+ size_t bufsize, buflength, gotlength;
673
+ JSBool sawNewline;
674
+ JSString *str;
675
+
676
+ from = stdin;
677
+ buflength = 0;
678
+ bufsize = BUFSIZE;
679
+ buf = (char *) JS_malloc(cx, bufsize);
680
+ if (!buf)
681
+ return JS_FALSE;
682
+
683
+ sawNewline = JS_FALSE;
684
+ while ((gotlength =
685
+ js_fgets(buf + buflength, bufsize - buflength, from)) > 0) {
686
+ buflength += gotlength;
687
+
688
+ /* Are we done? */
689
+ if (buf[buflength - 1] == '\n') {
690
+ buf[buflength - 1] = '\0';
691
+ sawNewline = JS_TRUE;
692
+ break;
693
+ } else if (buflength < bufsize - 1) {
694
+ break;
695
+ }
696
+
697
+ /* Else, grow our buffer for another pass. */
698
+ bufsize *= 2;
699
+ if (bufsize > buflength) {
700
+ tmp = (char *) JS_realloc(cx, buf, bufsize);
701
+ } else {
702
+ JS_ReportOutOfMemory(cx);
703
+ tmp = NULL;
704
+ }
705
+
706
+ if (!tmp) {
707
+ JS_free(cx, buf);
708
+ return JS_FALSE;
709
+ }
710
+
711
+ buf = tmp;
712
+ }
713
+
714
+ /* Treat the empty string specially. */
715
+ if (buflength == 0) {
716
+ *vp = feof(from) ? JSVAL_NULL : JS_GetEmptyStringValue(cx);
717
+ JS_free(cx, buf);
718
+ return JS_TRUE;
719
+ }
720
+
721
+ /* Shrink the buffer to the real size. */
722
+ tmp = (char *) JS_realloc(cx, buf, buflength);
723
+ if (!tmp) {
724
+ JS_free(cx, buf);
725
+ return JS_FALSE;
726
+ }
727
+
728
+ buf = tmp;
729
+
730
+ /*
731
+ * Turn buf into a JSString. Note that buflength includes the trailing null
732
+ * character.
733
+ */
734
+ str = JS_NewString(cx, buf, sawNewline ? buflength - 1 : buflength);
735
+ if (!str) {
736
+ JS_free(cx, buf);
737
+ return JS_FALSE;
738
+ }
739
+
740
+ *vp = STRING_TO_JSVAL(str);
741
+ return JS_TRUE;
742
+ }
743
+
744
+ static JSBool
745
+ Print(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
746
+ {
747
+ uintN i;
748
+ JSString *str;
749
+ char *bytes;
750
+
751
+ for (i = 0; i < argc; i++) {
752
+ str = JS_ValueToString(cx, argv[i]);
753
+ if (!str)
754
+ return JS_FALSE;
755
+ bytes = JS_EncodeString(cx, str);
756
+ if (!bytes)
757
+ return JS_FALSE;
758
+ fprintf(gOutFile, "%s%s", i ? " " : "", bytes);
759
+ JS_free(cx, bytes);
760
+ }
761
+
762
+ fputc('\n', gOutFile);
763
+ fflush(gOutFile);
764
+
765
+ return JS_TRUE;
766
+ }
767
+
768
+ static JSBool
769
+ Help(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
770
+
771
+ static JSBool
772
+ Quit(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
773
+ {
774
+ #ifdef LIVECONNECT
775
+ JSJ_SimpleShutdown();
776
+ #endif
777
+
778
+ JS_ConvertArguments(cx, argc, argv,"/ i", &gExitCode);
779
+
780
+ gQuitting = JS_TRUE;
781
+ return JS_FALSE;
782
+ }
783
+
784
+ static JSBool
785
+ GC(JSContext *cx, uintN argc, jsval *vp)
786
+ {
787
+ JSRuntime *rt;
788
+ uint32 preBytes;
789
+
790
+ rt = cx->runtime;
791
+ preBytes = rt->gcBytes;
792
+ JS_GC(cx);
793
+
794
+ fprintf(gOutFile, "before %lu, after %lu, break %08lx\n",
795
+ (unsigned long)preBytes, (unsigned long)rt->gcBytes,
796
+ #ifdef XP_UNIX
797
+ (unsigned long)sbrk(0)
798
+ #else
799
+ 0
800
+ #endif
801
+ );
802
+ #ifdef JS_GCMETER
803
+ js_DumpGCStats(rt, stdout);
804
+ #endif
805
+ *vp = JSVAL_VOID;
806
+ return JS_TRUE;
807
+ }
808
+
809
+ static JSBool
810
+ GCParameter(JSContext *cx, uintN argc, jsval *vp)
811
+ {
812
+ jsval *argv;
813
+ JSString *str;
814
+ const char *paramName;
815
+ JSGCParamKey param;
816
+ uint32 value;
817
+
818
+ argv = JS_ARGV(cx, vp);
819
+ str = JS_ValueToString(cx, argv[0]);
820
+ if (!str)
821
+ return JS_FALSE;
822
+ argv[0] = STRING_TO_JSVAL(str);
823
+ paramName = JS_GetStringBytes(str);
824
+ if (!paramName)
825
+ return JS_FALSE;
826
+ if (strcmp(paramName, "maxBytes") == 0) {
827
+ param = JSGC_MAX_BYTES;
828
+ } else if (strcmp(paramName, "maxMallocBytes") == 0) {
829
+ param = JSGC_MAX_MALLOC_BYTES;
830
+ } else {
831
+ JS_ReportError(cx,
832
+ "the first argument argument must be either maxBytes "
833
+ "or maxMallocBytes");
834
+ return JS_FALSE;
835
+ }
836
+
837
+ if (!JS_ValueToECMAUint32(cx, argv[1], &value))
838
+ return JS_FALSE;
839
+ if (value == 0) {
840
+ JS_ReportError(cx,
841
+ "the second argument must be convertable to uint32 with "
842
+ "non-zero value");
843
+ return JS_FALSE;
844
+ }
845
+ JS_SetGCParameter(cx->runtime, param, value);
846
+ *vp = JSVAL_VOID;
847
+ return JS_TRUE;
848
+ }
849
+
850
+ #ifdef JS_GC_ZEAL
851
+ static JSBool
852
+ GCZeal(JSContext *cx, uintN argc, jsval *vp)
853
+ {
854
+ uintN zeal;
855
+
856
+ if (!JS_ValueToECMAUint32(cx, vp[2], &zeal))
857
+ return JS_FALSE;
858
+ JS_SetGCZeal(cx, zeal);
859
+ *vp = JSVAL_VOID;
860
+ return JS_TRUE;
861
+ }
862
+ #endif /* JS_GC_ZEAL */
863
+
864
+ typedef struct JSCountHeapNode JSCountHeapNode;
865
+
866
+ struct JSCountHeapNode {
867
+ void *thing;
868
+ uint32 kind;
869
+ JSCountHeapNode *next;
870
+ };
871
+
872
+ typedef struct JSCountHeapTracer {
873
+ JSTracer base;
874
+ JSDHashTable visited;
875
+ JSBool ok;
876
+ JSCountHeapNode *traceList;
877
+ JSCountHeapNode *recycleList;
878
+ } JSCountHeapTracer;
879
+
880
+ static void
881
+ CountHeapNotify(JSTracer *trc, void *thing, uint32 kind)
882
+ {
883
+ JSCountHeapTracer *countTracer;
884
+ JSDHashEntryStub *entry;
885
+ JSCountHeapNode *node;
886
+
887
+ JS_ASSERT(trc->callback == CountHeapNotify);
888
+ countTracer = (JSCountHeapTracer *)trc;
889
+ if (!countTracer->ok)
890
+ return;
891
+
892
+ entry = (JSDHashEntryStub *)
893
+ JS_DHashTableOperate(&countTracer->visited, thing, JS_DHASH_ADD);
894
+ if (!entry) {
895
+ JS_ReportOutOfMemory(trc->context);
896
+ countTracer->ok = JS_FALSE;
897
+ return;
898
+ }
899
+ if (entry->key)
900
+ return;
901
+ entry->key = thing;
902
+
903
+ node = countTracer->recycleList;
904
+ if (node) {
905
+ countTracer->recycleList = node->next;
906
+ } else {
907
+ node = (JSCountHeapNode *) JS_malloc(trc->context, sizeof *node);
908
+ if (!node) {
909
+ countTracer->ok = JS_FALSE;
910
+ return;
911
+ }
912
+ }
913
+ node->thing = thing;
914
+ node->kind = kind;
915
+ node->next = countTracer->traceList;
916
+ countTracer->traceList = node;
917
+ }
918
+
919
+ static JSBool
920
+ CountHeap(JSContext *cx, uintN argc, jsval *vp)
921
+ {
922
+ void* startThing;
923
+ int32 startTraceKind;
924
+ jsval v;
925
+ int32 traceKind, i;
926
+ JSString *str;
927
+ char *bytes;
928
+ JSCountHeapTracer countTracer;
929
+ JSCountHeapNode *node;
930
+ size_t counter;
931
+
932
+ static const struct {
933
+ const char *name;
934
+ int32 kind;
935
+ } traceKindNames[] = {
936
+ { "all", -1 },
937
+ { "object", JSTRACE_OBJECT },
938
+ { "double", JSTRACE_DOUBLE },
939
+ { "string", JSTRACE_STRING },
940
+ #if JS_HAS_XML_SUPPORT
941
+ { "namespace", JSTRACE_NAMESPACE },
942
+ { "qname", JSTRACE_QNAME },
943
+ { "xml", JSTRACE_XML },
944
+ #endif
945
+ };
946
+
947
+ startThing = NULL;
948
+ startTraceKind = 0;
949
+ if (argc > 0) {
950
+ v = JS_ARGV(cx, vp)[0];
951
+ if (JSVAL_IS_TRACEABLE(v)) {
952
+ startThing = JSVAL_TO_TRACEABLE(v);
953
+ startTraceKind = JSVAL_TRACE_KIND(v);
954
+ } else if (v != JSVAL_NULL) {
955
+ JS_ReportError(cx,
956
+ "the first argument is not null or a heap-allocated "
957
+ "thing");
958
+ return JS_FALSE;
959
+ }
960
+ }
961
+
962
+ traceKind = -1;
963
+ if (argc > 1) {
964
+ str = JS_ValueToString(cx, JS_ARGV(cx, vp)[1]);
965
+ if (!str)
966
+ return JS_FALSE;
967
+ bytes = JS_GetStringBytes(str);
968
+ if (!bytes)
969
+ return JS_FALSE;
970
+ for (i = 0; ;) {
971
+ if (strcmp(bytes, traceKindNames[i].name) == 0) {
972
+ traceKind = traceKindNames[i].kind;
973
+ break;
974
+ }
975
+ if (++i == JS_ARRAY_LENGTH(traceKindNames)) {
976
+ JS_ReportError(cx, "trace kind name '%s' is unknown", bytes);
977
+ return JS_FALSE;
978
+ }
979
+ }
980
+ }
981
+
982
+ JS_TRACER_INIT(&countTracer.base, cx, CountHeapNotify);
983
+ if (!JS_DHashTableInit(&countTracer.visited, JS_DHashGetStubOps(),
984
+ NULL, sizeof(JSDHashEntryStub),
985
+ JS_DHASH_DEFAULT_CAPACITY(100))) {
986
+ JS_ReportOutOfMemory(cx);
987
+ return JS_FALSE;
988
+ }
989
+ countTracer.ok = JS_TRUE;
990
+ countTracer.traceList = NULL;
991
+ countTracer.recycleList = NULL;
992
+
993
+ if (!startThing) {
994
+ JS_TraceRuntime(&countTracer.base);
995
+ } else {
996
+ JS_SET_TRACING_NAME(&countTracer.base, "root");
997
+ JS_CallTracer(&countTracer.base, startThing, startTraceKind);
998
+ }
999
+
1000
+ counter = 0;
1001
+ while ((node = countTracer.traceList) != NULL) {
1002
+ if (traceKind == -1 || node->kind == traceKind)
1003
+ counter++;
1004
+ countTracer.traceList = node->next;
1005
+ node->next = countTracer.recycleList;
1006
+ countTracer.recycleList = node;
1007
+ JS_TraceChildren(&countTracer.base, node->thing, node->kind);
1008
+ }
1009
+ while ((node = countTracer.recycleList) != NULL) {
1010
+ countTracer.recycleList = node->next;
1011
+ JS_free(cx, node);
1012
+ }
1013
+ JS_DHashTableFinish(&countTracer.visited);
1014
+
1015
+ return countTracer.ok && JS_NewNumberValue(cx, (jsdouble) counter, vp);
1016
+ }
1017
+
1018
+ static JSScript *
1019
+ ValueToScript(JSContext *cx, jsval v)
1020
+ {
1021
+ JSScript *script;
1022
+ JSFunction *fun;
1023
+
1024
+ if (!JSVAL_IS_PRIMITIVE(v) &&
1025
+ JS_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == &js_ScriptClass) {
1026
+ script = (JSScript *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(v));
1027
+ } else {
1028
+ fun = JS_ValueToFunction(cx, v);
1029
+ if (!fun)
1030
+ return NULL;
1031
+ script = FUN_SCRIPT(fun);
1032
+ }
1033
+ return script;
1034
+ }
1035
+
1036
+ static JSBool
1037
+ GetTrapArgs(JSContext *cx, uintN argc, jsval *argv, JSScript **scriptp,
1038
+ int32 *ip)
1039
+ {
1040
+ jsval v;
1041
+ uintN intarg;
1042
+ JSScript *script;
1043
+
1044
+ *scriptp = cx->fp->down->script;
1045
+ *ip = 0;
1046
+ if (argc != 0) {
1047
+ v = argv[0];
1048
+ intarg = 0;
1049
+ if (!JSVAL_IS_PRIMITIVE(v) &&
1050
+ (JS_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == &js_FunctionClass ||
1051
+ JS_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == &js_ScriptClass)) {
1052
+ script = ValueToScript(cx, v);
1053
+ if (!script)
1054
+ return JS_FALSE;
1055
+ *scriptp = script;
1056
+ intarg++;
1057
+ }
1058
+ if (argc > intarg) {
1059
+ if (!JS_ValueToInt32(cx, argv[intarg], ip))
1060
+ return JS_FALSE;
1061
+ }
1062
+ }
1063
+ return JS_TRUE;
1064
+ }
1065
+
1066
+ static JSTrapStatus
1067
+ TrapHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
1068
+ void *closure)
1069
+ {
1070
+ JSString *str;
1071
+ JSStackFrame *caller;
1072
+
1073
+ str = (JSString *) closure;
1074
+ caller = JS_GetScriptedCaller(cx, NULL);
1075
+ if (!JS_EvaluateScript(cx, caller->scopeChain,
1076
+ JS_GetStringBytes(str), JS_GetStringLength(str),
1077
+ caller->script->filename, caller->script->lineno,
1078
+ rval)) {
1079
+ return JSTRAP_ERROR;
1080
+ }
1081
+ if (*rval != JSVAL_VOID)
1082
+ return JSTRAP_RETURN;
1083
+ return JSTRAP_CONTINUE;
1084
+ }
1085
+
1086
+ static JSBool
1087
+ Trap(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1088
+ {
1089
+ JSString *str;
1090
+ JSScript *script;
1091
+ int32 i;
1092
+
1093
+ if (argc == 0) {
1094
+ JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_TRAP_USAGE);
1095
+ return JS_FALSE;
1096
+ }
1097
+ argc--;
1098
+ str = JS_ValueToString(cx, argv[argc]);
1099
+ if (!str)
1100
+ return JS_FALSE;
1101
+ argv[argc] = STRING_TO_JSVAL(str);
1102
+ if (!GetTrapArgs(cx, argc, argv, &script, &i))
1103
+ return JS_FALSE;
1104
+ return JS_SetTrap(cx, script, script->code + i, TrapHandler, str);
1105
+ }
1106
+
1107
+ static JSBool
1108
+ Untrap(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1109
+ {
1110
+ JSScript *script;
1111
+ int32 i;
1112
+
1113
+ if (!GetTrapArgs(cx, argc, argv, &script, &i))
1114
+ return JS_FALSE;
1115
+ JS_ClearTrap(cx, script, script->code + i, NULL, NULL);
1116
+ return JS_TRUE;
1117
+ }
1118
+
1119
+ static JSBool
1120
+ LineToPC(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1121
+ {
1122
+ JSScript *script;
1123
+ int32 i;
1124
+ uintN lineno;
1125
+ jsbytecode *pc;
1126
+
1127
+ if (argc == 0) {
1128
+ JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_LINE2PC_USAGE);
1129
+ return JS_FALSE;
1130
+ }
1131
+ script = cx->fp->down->script;
1132
+ if (!GetTrapArgs(cx, argc, argv, &script, &i))
1133
+ return JS_FALSE;
1134
+ lineno = (i == 0) ? script->lineno : (uintN)i;
1135
+ pc = JS_LineNumberToPC(cx, script, lineno);
1136
+ if (!pc)
1137
+ return JS_FALSE;
1138
+ *rval = INT_TO_JSVAL(PTRDIFF(pc, script->code, jsbytecode));
1139
+ return JS_TRUE;
1140
+ }
1141
+
1142
+ static JSBool
1143
+ PCToLine(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1144
+ {
1145
+ JSScript *script;
1146
+ int32 i;
1147
+ uintN lineno;
1148
+
1149
+ if (!GetTrapArgs(cx, argc, argv, &script, &i))
1150
+ return JS_FALSE;
1151
+ lineno = JS_PCToLineNumber(cx, script, script->code + i);
1152
+ if (!lineno)
1153
+ return JS_FALSE;
1154
+ *rval = INT_TO_JSVAL(lineno);
1155
+ return JS_TRUE;
1156
+ }
1157
+
1158
+ #ifdef DEBUG
1159
+
1160
+ static void
1161
+ UpdateSwitchTableBounds(JSScript *script, uintN offset,
1162
+ uintN *start, uintN *end)
1163
+ {
1164
+ jsbytecode *pc;
1165
+ JSOp op;
1166
+ ptrdiff_t jmplen;
1167
+ jsint low, high, n;
1168
+
1169
+ pc = script->code + offset;
1170
+ op = (JSOp) *pc;
1171
+ switch (op) {
1172
+ case JSOP_TABLESWITCHX:
1173
+ jmplen = JUMPX_OFFSET_LEN;
1174
+ goto jump_table;
1175
+ case JSOP_TABLESWITCH:
1176
+ jmplen = JUMP_OFFSET_LEN;
1177
+ jump_table:
1178
+ pc += jmplen;
1179
+ low = GET_JUMP_OFFSET(pc);
1180
+ pc += JUMP_OFFSET_LEN;
1181
+ high = GET_JUMP_OFFSET(pc);
1182
+ pc += JUMP_OFFSET_LEN;
1183
+ n = high - low + 1;
1184
+ break;
1185
+
1186
+ case JSOP_LOOKUPSWITCHX:
1187
+ jmplen = JUMPX_OFFSET_LEN;
1188
+ goto lookup_table;
1189
+ case JSOP_LOOKUPSWITCH:
1190
+ jmplen = JUMP_OFFSET_LEN;
1191
+ lookup_table:
1192
+ pc += jmplen;
1193
+ n = GET_INDEX(pc);
1194
+ pc += INDEX_LEN;
1195
+ jmplen += JUMP_OFFSET_LEN;
1196
+ break;
1197
+
1198
+ default:
1199
+ /* [condswitch] switch does not have any jump or lookup tables. */
1200
+ JS_ASSERT(op == JSOP_CONDSWITCH);
1201
+ return;
1202
+ }
1203
+
1204
+ *start = (uintN)(pc - script->code);
1205
+ *end = *start + (uintN)(n * jmplen);
1206
+ }
1207
+
1208
+ static void
1209
+ SrcNotes(JSContext *cx, JSScript *script)
1210
+ {
1211
+ uintN offset, delta, caseOff, switchTableStart, switchTableEnd;
1212
+ jssrcnote *notes, *sn;
1213
+ JSSrcNoteType type;
1214
+ const char *name;
1215
+ uint32 index;
1216
+ JSAtom *atom;
1217
+ JSString *str;
1218
+
1219
+ fprintf(gOutFile, "\nSource notes:\n");
1220
+ offset = 0;
1221
+ notes = SCRIPT_NOTES(script);
1222
+ switchTableEnd = switchTableStart = 0;
1223
+ for (sn = notes; !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) {
1224
+ delta = SN_DELTA(sn);
1225
+ offset += delta;
1226
+ type = (JSSrcNoteType) SN_TYPE(sn);
1227
+ name = js_SrcNoteSpec[type].name;
1228
+ if (type == SRC_LABEL) {
1229
+ /* Check if the source note is for a switch case. */
1230
+ if (switchTableStart <= offset && offset < switchTableEnd) {
1231
+ name = "case";
1232
+ } else {
1233
+ JS_ASSERT(script->code[offset] == JSOP_NOP);
1234
+ }
1235
+ }
1236
+ fprintf(gOutFile, "%3u: %5u [%4u] %-8s",
1237
+ PTRDIFF(sn, notes, jssrcnote), offset, delta, name);
1238
+ switch (type) {
1239
+ case SRC_SETLINE:
1240
+ fprintf(gOutFile, " lineno %u", (uintN) js_GetSrcNoteOffset(sn, 0));
1241
+ break;
1242
+ case SRC_FOR:
1243
+ fprintf(gOutFile, " cond %u update %u tail %u",
1244
+ (uintN) js_GetSrcNoteOffset(sn, 0),
1245
+ (uintN) js_GetSrcNoteOffset(sn, 1),
1246
+ (uintN) js_GetSrcNoteOffset(sn, 2));
1247
+ break;
1248
+ case SRC_IF_ELSE:
1249
+ fprintf(gOutFile, " else %u elseif %u",
1250
+ (uintN) js_GetSrcNoteOffset(sn, 0),
1251
+ (uintN) js_GetSrcNoteOffset(sn, 1));
1252
+ break;
1253
+ case SRC_COND:
1254
+ case SRC_WHILE:
1255
+ case SRC_PCBASE:
1256
+ case SRC_PCDELTA:
1257
+ case SRC_DECL:
1258
+ case SRC_BRACE:
1259
+ fprintf(gOutFile, " offset %u", (uintN) js_GetSrcNoteOffset(sn, 0));
1260
+ break;
1261
+ case SRC_LABEL:
1262
+ case SRC_LABELBRACE:
1263
+ case SRC_BREAK2LABEL:
1264
+ case SRC_CONT2LABEL:
1265
+ index = js_GetSrcNoteOffset(sn, 0);
1266
+ JS_GET_SCRIPT_ATOM(script, index, atom);
1267
+ JS_ASSERT(ATOM_IS_STRING(atom));
1268
+ str = ATOM_TO_STRING(atom);
1269
+ fprintf(gOutFile, " atom %u (", index);
1270
+ js_FileEscapedString(gOutFile, str, 0);
1271
+ putc(')', gOutFile);
1272
+ break;
1273
+ case SRC_FUNCDEF: {
1274
+ const char *bytes;
1275
+ JSObject *obj;
1276
+ JSFunction *fun;
1277
+
1278
+ index = js_GetSrcNoteOffset(sn, 0);
1279
+ JS_GET_SCRIPT_OBJECT(script, index, obj);
1280
+ fun = (JSFunction *) JS_GetPrivate(cx, obj);
1281
+ str = JS_DecompileFunction(cx, fun, JS_DONT_PRETTY_PRINT);
1282
+ bytes = str ? JS_GetStringBytes(str) : "N/A";
1283
+ fprintf(gOutFile, " function %u (%s)", index, bytes);
1284
+ break;
1285
+ }
1286
+ case SRC_SWITCH:
1287
+ fprintf(gOutFile, " length %u", (uintN) js_GetSrcNoteOffset(sn, 0));
1288
+ caseOff = (uintN) js_GetSrcNoteOffset(sn, 1);
1289
+ if (caseOff)
1290
+ fprintf(gOutFile, " first case offset %u", caseOff);
1291
+ UpdateSwitchTableBounds(script, offset,
1292
+ &switchTableStart, &switchTableEnd);
1293
+ break;
1294
+ case SRC_CATCH:
1295
+ delta = (uintN) js_GetSrcNoteOffset(sn, 0);
1296
+ if (delta) {
1297
+ if (script->main[offset] == JSOP_LEAVEBLOCK)
1298
+ fprintf(gOutFile, " stack depth %u", delta);
1299
+ else
1300
+ fprintf(gOutFile, " guard delta %u", delta);
1301
+ }
1302
+ break;
1303
+ default:;
1304
+ }
1305
+ fputc('\n', gOutFile);
1306
+ }
1307
+ }
1308
+
1309
+ static JSBool
1310
+ Notes(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1311
+ {
1312
+ uintN i;
1313
+ JSScript *script;
1314
+
1315
+ for (i = 0; i < argc; i++) {
1316
+ script = ValueToScript(cx, argv[i]);
1317
+ if (!script)
1318
+ continue;
1319
+
1320
+ SrcNotes(cx, script);
1321
+ }
1322
+ return JS_TRUE;
1323
+ }
1324
+
1325
+ JS_STATIC_ASSERT(JSTN_CATCH == 0);
1326
+ JS_STATIC_ASSERT(JSTN_FINALLY == 1);
1327
+ JS_STATIC_ASSERT(JSTN_ITER == 2);
1328
+
1329
+ static const char* const TryNoteNames[] = { "catch", "finally", "iter" };
1330
+
1331
+ static JSBool
1332
+ TryNotes(JSContext *cx, JSScript *script)
1333
+ {
1334
+ JSTryNote *tn, *tnlimit;
1335
+
1336
+ if (script->trynotesOffset == 0)
1337
+ return JS_TRUE;
1338
+
1339
+ tn = JS_SCRIPT_TRYNOTES(script)->vector;
1340
+ tnlimit = tn + JS_SCRIPT_TRYNOTES(script)->length;
1341
+ fprintf(gOutFile, "\nException table:\n"
1342
+ "kind stack start end\n");
1343
+ do {
1344
+ JS_ASSERT(tn->kind < JS_ARRAY_LENGTH(TryNoteNames));
1345
+ fprintf(gOutFile, " %-7s %6u %8u %8u\n",
1346
+ TryNoteNames[tn->kind], tn->stackDepth,
1347
+ tn->start, tn->start + tn->length);
1348
+ } while (++tn != tnlimit);
1349
+ return JS_TRUE;
1350
+ }
1351
+
1352
+ static JSBool
1353
+ Disassemble(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1354
+ {
1355
+ JSBool lines;
1356
+ uintN i;
1357
+ JSScript *script;
1358
+
1359
+ if (argc > 0 &&
1360
+ JSVAL_IS_STRING(argv[0]) &&
1361
+ !strcmp(JS_GetStringBytes(JSVAL_TO_STRING(argv[0])), "-l")) {
1362
+ lines = JS_TRUE;
1363
+ argv++, argc--;
1364
+ } else {
1365
+ lines = JS_FALSE;
1366
+ }
1367
+ for (i = 0; i < argc; i++) {
1368
+ script = ValueToScript(cx, argv[i]);
1369
+ if (!script)
1370
+ return JS_FALSE;
1371
+
1372
+ if (VALUE_IS_FUNCTION(cx, argv[i])) {
1373
+ JSFunction *fun = JS_ValueToFunction(cx, argv[i]);
1374
+ if (fun && (fun->flags & JSFUN_FLAGS_MASK)) {
1375
+ uint16 flags = fun->flags;
1376
+ fputs("flags:", stdout);
1377
+
1378
+ #define SHOW_FLAG(flag) if (flags & JSFUN_##flag) fputs(" " #flag, stdout);
1379
+
1380
+ SHOW_FLAG(LAMBDA);
1381
+ SHOW_FLAG(SETTER);
1382
+ SHOW_FLAG(GETTER);
1383
+ SHOW_FLAG(BOUND_METHOD);
1384
+ SHOW_FLAG(HEAVYWEIGHT);
1385
+ SHOW_FLAG(THISP_STRING);
1386
+ SHOW_FLAG(THISP_NUMBER);
1387
+ SHOW_FLAG(THISP_BOOLEAN);
1388
+ SHOW_FLAG(EXPR_CLOSURE);
1389
+ SHOW_FLAG(INTERPRETED);
1390
+
1391
+ #undef SHOW_FLAG
1392
+ putchar('\n');
1393
+ }
1394
+ }
1395
+
1396
+ if (!js_Disassemble(cx, script, lines, stdout))
1397
+ return JS_FALSE;
1398
+ SrcNotes(cx, script);
1399
+ TryNotes(cx, script);
1400
+ }
1401
+ return JS_TRUE;
1402
+ }
1403
+
1404
+ static JSBool
1405
+ DisassWithSrc(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
1406
+ jsval *rval)
1407
+ {
1408
+ #define LINE_BUF_LEN 512
1409
+ uintN i, len, line1, line2, bupline;
1410
+ JSScript *script;
1411
+ FILE *file;
1412
+ char linebuf[LINE_BUF_LEN];
1413
+ jsbytecode *pc, *end;
1414
+ static char sep[] = ";-------------------------";
1415
+
1416
+ for (i = 0; i < argc; i++) {
1417
+ script = ValueToScript(cx, argv[i]);
1418
+ if (!script)
1419
+ return JS_FALSE;
1420
+
1421
+ if (!script || !script->filename) {
1422
+ JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL,
1423
+ JSSMSG_FILE_SCRIPTS_ONLY);
1424
+ return JS_FALSE;
1425
+ }
1426
+
1427
+ file = fopen(script->filename, "r");
1428
+ if (!file) {
1429
+ JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL,
1430
+ JSSMSG_CANT_OPEN,
1431
+ script->filename, strerror(errno));
1432
+ return JS_FALSE;
1433
+ }
1434
+
1435
+ pc = script->code;
1436
+ end = pc + script->length;
1437
+
1438
+ /* burn the leading lines */
1439
+ line2 = JS_PCToLineNumber(cx, script, pc);
1440
+ for (line1 = 0; line1 < line2 - 1; line1++)
1441
+ fgets(linebuf, LINE_BUF_LEN, file);
1442
+
1443
+ bupline = 0;
1444
+ while (pc < end) {
1445
+ line2 = JS_PCToLineNumber(cx, script, pc);
1446
+
1447
+ if (line2 < line1) {
1448
+ if (bupline != line2) {
1449
+ bupline = line2;
1450
+ fprintf(gOutFile, "%s %3u: BACKUP\n", sep, line2);
1451
+ }
1452
+ } else {
1453
+ if (bupline && line1 == line2)
1454
+ fprintf(gOutFile, "%s %3u: RESTORE\n", sep, line2);
1455
+ bupline = 0;
1456
+ while (line1 < line2) {
1457
+ if (!fgets(linebuf, LINE_BUF_LEN, file)) {
1458
+ JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL,
1459
+ JSSMSG_UNEXPECTED_EOF,
1460
+ script->filename);
1461
+ goto bail;
1462
+ }
1463
+ line1++;
1464
+ fprintf(gOutFile, "%s %3u: %s", sep, line1, linebuf);
1465
+ }
1466
+ }
1467
+
1468
+ len = js_Disassemble1(cx, script, pc,
1469
+ PTRDIFF(pc, script->code, jsbytecode),
1470
+ JS_TRUE, stdout);
1471
+ if (!len)
1472
+ return JS_FALSE;
1473
+ pc += len;
1474
+ }
1475
+
1476
+ bail:
1477
+ fclose(file);
1478
+ }
1479
+ return JS_TRUE;
1480
+ #undef LINE_BUF_LEN
1481
+ }
1482
+
1483
+ static JSBool
1484
+ Tracing(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1485
+ {
1486
+ JSBool bval;
1487
+ JSString *str;
1488
+
1489
+ #if JS_THREADED_INTERP
1490
+ JS_ReportError(cx, "tracing not supported in JS_THREADED_INTERP builds");
1491
+ return JS_FALSE;
1492
+ #else
1493
+ if (argc == 0) {
1494
+ *rval = BOOLEAN_TO_JSVAL(cx->tracefp != 0);
1495
+ return JS_TRUE;
1496
+ }
1497
+
1498
+ switch (JS_TypeOfValue(cx, argv[0])) {
1499
+ case JSTYPE_NUMBER:
1500
+ bval = JSVAL_IS_INT(argv[0])
1501
+ ? JSVAL_TO_INT(argv[0])
1502
+ : (jsint) *JSVAL_TO_DOUBLE(argv[0]);
1503
+ break;
1504
+ case JSTYPE_BOOLEAN:
1505
+ bval = JSVAL_TO_BOOLEAN(argv[0]);
1506
+ break;
1507
+ default:
1508
+ str = JS_ValueToString(cx, argv[0]);
1509
+ if (!str)
1510
+ return JS_FALSE;
1511
+ JS_ReportError(cx, "tracing: illegal argument %s",
1512
+ JS_GetStringBytes(str));
1513
+ return JS_FALSE;
1514
+ }
1515
+ cx->tracefp = bval ? stderr : NULL;
1516
+ return JS_TRUE;
1517
+ #endif
1518
+ }
1519
+
1520
+ static void
1521
+ DumpScope(JSContext *cx, JSObject *obj, FILE *fp)
1522
+ {
1523
+ uintN i;
1524
+ JSScope *scope;
1525
+ JSScopeProperty *sprop;
1526
+ jsval v;
1527
+ JSString *str;
1528
+
1529
+ i = 0;
1530
+ scope = OBJ_SCOPE(obj);
1531
+ for (sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent) {
1532
+ if (SCOPE_HAD_MIDDLE_DELETE(scope) && !SCOPE_HAS_PROPERTY(scope, sprop))
1533
+ continue;
1534
+ fprintf(fp, "%3u %p ", i, (void *)sprop);
1535
+
1536
+ v = ID_TO_VALUE(sprop->id);
1537
+ if (JSID_IS_INT(sprop->id)) {
1538
+ fprintf(fp, "[%ld]", (long)JSVAL_TO_INT(v));
1539
+ } else {
1540
+ if (JSID_IS_ATOM(sprop->id)) {
1541
+ str = JSVAL_TO_STRING(v);
1542
+ } else {
1543
+ JS_ASSERT(JSID_IS_OBJECT(sprop->id));
1544
+ str = js_ValueToString(cx, v);
1545
+ fputs("object ", fp);
1546
+ }
1547
+ if (!str)
1548
+ fputs("<error>", fp);
1549
+ else
1550
+ js_FileEscapedString(fp, str, '"');
1551
+ }
1552
+ #define DUMP_ATTR(name) if (sprop->attrs & JSPROP_##name) fputs(" " #name, fp)
1553
+ DUMP_ATTR(ENUMERATE);
1554
+ DUMP_ATTR(READONLY);
1555
+ DUMP_ATTR(PERMANENT);
1556
+ DUMP_ATTR(EXPORTED);
1557
+ DUMP_ATTR(GETTER);
1558
+ DUMP_ATTR(SETTER);
1559
+ #undef DUMP_ATTR
1560
+
1561
+ fprintf(fp, " slot %lu flags %x shortid %d\n",
1562
+ (unsigned long)sprop->slot, sprop->flags, sprop->shortid);
1563
+ }
1564
+ }
1565
+
1566
+ static JSBool
1567
+ DumpStats(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1568
+ {
1569
+ uintN i;
1570
+ JSString *str;
1571
+ const char *bytes;
1572
+ jsid id;
1573
+ JSObject *obj2;
1574
+ JSProperty *prop;
1575
+ jsval value;
1576
+
1577
+ for (i = 0; i < argc; i++) {
1578
+ str = JS_ValueToString(cx, argv[i]);
1579
+ if (!str)
1580
+ return JS_FALSE;
1581
+ argv[i] = STRING_TO_JSVAL(str);
1582
+ bytes = JS_GetStringBytes(str);
1583
+ if (strcmp(bytes, "arena") == 0) {
1584
+ #ifdef JS_ARENAMETER
1585
+ JS_DumpArenaStats(stdout);
1586
+ #endif
1587
+ } else if (strcmp(bytes, "atom") == 0) {
1588
+ js_DumpAtoms(cx, gOutFile);
1589
+ } else if (strcmp(bytes, "global") == 0) {
1590
+ DumpScope(cx, cx->globalObject, stdout);
1591
+ } else {
1592
+ if (!JS_ValueToId(cx, STRING_TO_JSVAL(str), &id))
1593
+ return JS_FALSE;
1594
+ if (!js_FindProperty(cx, id, &obj, &obj2, &prop))
1595
+ return JS_FALSE;
1596
+ if (prop) {
1597
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
1598
+ if (!OBJ_GET_PROPERTY(cx, obj, id, &value))
1599
+ return JS_FALSE;
1600
+ }
1601
+ if (!prop || !JSVAL_IS_OBJECT(value)) {
1602
+ fprintf(gErrFile, "js: invalid stats argument %s\n",
1603
+ bytes);
1604
+ continue;
1605
+ }
1606
+ obj = JSVAL_TO_OBJECT(value);
1607
+ if (obj)
1608
+ DumpScope(cx, obj, stdout);
1609
+ }
1610
+ }
1611
+ return JS_TRUE;
1612
+ }
1613
+
1614
+ static JSBool
1615
+ DumpHeap(JSContext *cx, uintN argc, jsval *vp)
1616
+ {
1617
+ char *fileName;
1618
+ jsval v;
1619
+ void* startThing;
1620
+ uint32 startTraceKind;
1621
+ const char *badTraceArg;
1622
+ void *thingToFind;
1623
+ size_t maxDepth;
1624
+ void *thingToIgnore;
1625
+ FILE *dumpFile;
1626
+ JSBool ok;
1627
+
1628
+ fileName = NULL;
1629
+ if (argc > 0) {
1630
+ v = JS_ARGV(cx, vp)[0];
1631
+ if (v != JSVAL_NULL) {
1632
+ JSString *str;
1633
+
1634
+ str = JS_ValueToString(cx, v);
1635
+ if (!str)
1636
+ return JS_FALSE;
1637
+ JS_ARGV(cx, vp)[0] = STRING_TO_JSVAL(str);
1638
+ fileName = JS_GetStringBytes(str);
1639
+ }
1640
+ }
1641
+
1642
+ startThing = NULL;
1643
+ startTraceKind = 0;
1644
+ if (argc > 1) {
1645
+ v = JS_ARGV(cx, vp)[1];
1646
+ if (JSVAL_IS_TRACEABLE(v)) {
1647
+ startThing = JSVAL_TO_TRACEABLE(v);
1648
+ startTraceKind = JSVAL_TRACE_KIND(v);
1649
+ } else if (v != JSVAL_NULL) {
1650
+ badTraceArg = "start";
1651
+ goto not_traceable_arg;
1652
+ }
1653
+ }
1654
+
1655
+ thingToFind = NULL;
1656
+ if (argc > 2) {
1657
+ v = JS_ARGV(cx, vp)[2];
1658
+ if (JSVAL_IS_TRACEABLE(v)) {
1659
+ thingToFind = JSVAL_TO_TRACEABLE(v);
1660
+ } else if (v != JSVAL_NULL) {
1661
+ badTraceArg = "toFind";
1662
+ goto not_traceable_arg;
1663
+ }
1664
+ }
1665
+
1666
+ maxDepth = (size_t)-1;
1667
+ if (argc > 3) {
1668
+ v = JS_ARGV(cx, vp)[3];
1669
+ if (v != JSVAL_NULL) {
1670
+ uint32 depth;
1671
+
1672
+ if (!JS_ValueToECMAUint32(cx, v, &depth))
1673
+ return JS_FALSE;
1674
+ maxDepth = depth;
1675
+ }
1676
+ }
1677
+
1678
+ thingToIgnore = NULL;
1679
+ if (argc > 4) {
1680
+ v = JS_ARGV(cx, vp)[4];
1681
+ if (JSVAL_IS_TRACEABLE(v)) {
1682
+ thingToIgnore = JSVAL_TO_TRACEABLE(v);
1683
+ } else if (v != JSVAL_NULL) {
1684
+ badTraceArg = "toIgnore";
1685
+ goto not_traceable_arg;
1686
+ }
1687
+ }
1688
+
1689
+ if (!fileName) {
1690
+ dumpFile = stdout;
1691
+ } else {
1692
+ dumpFile = fopen(fileName, "w");
1693
+ if (!dumpFile) {
1694
+ JS_ReportError(cx, "can't open %s: %s", fileName, strerror(errno));
1695
+ return JS_FALSE;
1696
+ }
1697
+ }
1698
+
1699
+ ok = JS_DumpHeap(cx, dumpFile, startThing, startTraceKind, thingToFind,
1700
+ maxDepth, thingToIgnore);
1701
+ if (dumpFile != stdout)
1702
+ fclose(dumpFile);
1703
+ return ok;
1704
+
1705
+ not_traceable_arg:
1706
+ JS_ReportError(cx, "argument '%s' is not null or a heap-allocated thing",
1707
+ badTraceArg);
1708
+ return JS_FALSE;
1709
+ }
1710
+
1711
+ #endif /* DEBUG */
1712
+
1713
+ #ifdef TEST_EXPORT
1714
+ static JSBool
1715
+ DoExport(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1716
+ {
1717
+ jsid id;
1718
+ JSObject *obj2;
1719
+ JSProperty *prop;
1720
+ JSBool ok;
1721
+ uintN attrs;
1722
+
1723
+ if (argc != 2) {
1724
+ JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_DOEXP_USAGE);
1725
+ return JS_FALSE;
1726
+ }
1727
+ if (!JS_ValueToObject(cx, argv[0], &obj))
1728
+ return JS_FALSE;
1729
+ argv[0] = OBJECT_TO_JSVAL(obj);
1730
+ if (!js_ValueToStringId(cx, argv[1], &id))
1731
+ return JS_FALSE;
1732
+ if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))
1733
+ return JS_FALSE;
1734
+ if (!prop) {
1735
+ ok = OBJ_DEFINE_PROPERTY(cx, obj, id, JSVAL_VOID, NULL, NULL,
1736
+ JSPROP_EXPORTED, NULL);
1737
+ } else {
1738
+ ok = OBJ_GET_ATTRIBUTES(cx, obj, id, prop, &attrs);
1739
+ if (ok) {
1740
+ attrs |= JSPROP_EXPORTED;
1741
+ ok = OBJ_SET_ATTRIBUTES(cx, obj, id, prop, &attrs);
1742
+ }
1743
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
1744
+ }
1745
+ return ok;
1746
+ }
1747
+ #endif
1748
+
1749
+ #ifdef TEST_CVTARGS
1750
+ #include <ctype.h>
1751
+
1752
+ static const char *
1753
+ EscapeWideString(jschar *w)
1754
+ {
1755
+ static char enuf[80];
1756
+ static char hex[] = "0123456789abcdef";
1757
+ jschar u;
1758
+ unsigned char b, c;
1759
+ int i, j;
1760
+
1761
+ if (!w)
1762
+ return "";
1763
+ for (i = j = 0; i < sizeof enuf - 1; i++, j++) {
1764
+ u = w[j];
1765
+ if (u == 0)
1766
+ break;
1767
+ b = (unsigned char)(u >> 8);
1768
+ c = (unsigned char)(u);
1769
+ if (b) {
1770
+ if (i >= sizeof enuf - 6)
1771
+ break;
1772
+ enuf[i++] = '\\';
1773
+ enuf[i++] = 'u';
1774
+ enuf[i++] = hex[b >> 4];
1775
+ enuf[i++] = hex[b & 15];
1776
+ enuf[i++] = hex[c >> 4];
1777
+ enuf[i] = hex[c & 15];
1778
+ } else if (!isprint(c)) {
1779
+ if (i >= sizeof enuf - 4)
1780
+ break;
1781
+ enuf[i++] = '\\';
1782
+ enuf[i++] = 'x';
1783
+ enuf[i++] = hex[c >> 4];
1784
+ enuf[i] = hex[c & 15];
1785
+ } else {
1786
+ enuf[i] = (char)c;
1787
+ }
1788
+ }
1789
+ enuf[i] = 0;
1790
+ return enuf;
1791
+ }
1792
+
1793
+ #include <stdarg.h>
1794
+
1795
+ static JSBool
1796
+ ZZ_formatter(JSContext *cx, const char *format, JSBool fromJS, jsval **vpp,
1797
+ va_list *app)
1798
+ {
1799
+ jsval *vp;
1800
+ va_list ap;
1801
+ jsdouble re, im;
1802
+
1803
+ printf("entering ZZ_formatter");
1804
+ vp = *vpp;
1805
+ ap = *app;
1806
+ if (fromJS) {
1807
+ if (!JS_ValueToNumber(cx, vp[0], &re))
1808
+ return JS_FALSE;
1809
+ if (!JS_ValueToNumber(cx, vp[1], &im))
1810
+ return JS_FALSE;
1811
+ *va_arg(ap, jsdouble *) = re;
1812
+ *va_arg(ap, jsdouble *) = im;
1813
+ } else {
1814
+ re = va_arg(ap, jsdouble);
1815
+ im = va_arg(ap, jsdouble);
1816
+ if (!JS_NewNumberValue(cx, re, &vp[0]))
1817
+ return JS_FALSE;
1818
+ if (!JS_NewNumberValue(cx, im, &vp[1]))
1819
+ return JS_FALSE;
1820
+ }
1821
+ *vpp = vp + 2;
1822
+ *app = ap;
1823
+ printf("leaving ZZ_formatter");
1824
+ return JS_TRUE;
1825
+ }
1826
+
1827
+ static JSBool
1828
+ ConvertArgs(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1829
+ {
1830
+ JSBool b = JS_FALSE;
1831
+ jschar c = 0;
1832
+ int32 i = 0, j = 0;
1833
+ uint32 u = 0;
1834
+ jsdouble d = 0, I = 0, re = 0, im = 0;
1835
+ char *s = NULL;
1836
+ JSString *str = NULL;
1837
+ jschar *w = NULL;
1838
+ JSObject *obj2 = NULL;
1839
+ JSFunction *fun = NULL;
1840
+ jsval v = JSVAL_VOID;
1841
+ JSBool ok;
1842
+
1843
+ if (!JS_AddArgumentFormatter(cx, "ZZ", ZZ_formatter))
1844
+ return JS_FALSE;;
1845
+ ok = JS_ConvertArguments(cx, argc, argv, "b/ciujdIsSWofvZZ*",
1846
+ &b, &c, &i, &u, &j, &d, &I, &s, &str, &w, &obj2,
1847
+ &fun, &v, &re, &im);
1848
+ JS_RemoveArgumentFormatter(cx, "ZZ");
1849
+ if (!ok)
1850
+ return JS_FALSE;
1851
+ fprintf(gOutFile,
1852
+ "b %u, c %x (%c), i %ld, u %lu, j %ld\n",
1853
+ b, c, (char)c, i, u, j);
1854
+ fprintf(gOutFile,
1855
+ "d %g, I %g, s %s, S %s, W %s, obj %s, fun %s\n"
1856
+ "v %s, re %g, im %g\n",
1857
+ d, I, s, str ? JS_GetStringBytes(str) : "", EscapeWideString(w),
1858
+ JS_GetStringBytes(JS_ValueToString(cx, OBJECT_TO_JSVAL(obj2))),
1859
+ fun ? JS_GetStringBytes(JS_DecompileFunction(cx, fun, 4)) : "",
1860
+ JS_GetStringBytes(JS_ValueToString(cx, v)), re, im);
1861
+ return JS_TRUE;
1862
+ }
1863
+ #endif
1864
+
1865
+ static JSBool
1866
+ BuildDate(JSContext *cx, uintN argc, jsval *vp)
1867
+ {
1868
+ char version[20] = "\n";
1869
+ #if JS_VERSION < 150
1870
+ sprintf(version, " for version %d\n", JS_VERSION);
1871
+ #endif
1872
+ fprintf(gOutFile, "built on %s at %s%s", __DATE__, __TIME__, version);
1873
+ *vp = JSVAL_VOID;
1874
+ return JS_TRUE;
1875
+ }
1876
+
1877
+ static JSBool
1878
+ Clear(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1879
+ {
1880
+ if (argc != 0 && !JS_ValueToObject(cx, argv[0], &obj))
1881
+ return JS_FALSE;
1882
+ JS_ClearScope(cx, obj);
1883
+ return JS_TRUE;
1884
+ }
1885
+
1886
+ static JSBool
1887
+ Intern(JSContext *cx, uintN argc, jsval *vp)
1888
+ {
1889
+ JSString *str;
1890
+
1891
+ str = JS_ValueToString(cx, vp[2]);
1892
+ if (!str)
1893
+ return JS_FALSE;
1894
+ if (!JS_InternUCStringN(cx, JS_GetStringChars(str),
1895
+ JS_GetStringLength(str))) {
1896
+ return JS_FALSE;
1897
+ }
1898
+ *vp = JSVAL_VOID;
1899
+ return JS_TRUE;
1900
+ }
1901
+
1902
+ static JSBool
1903
+ Clone(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1904
+ {
1905
+ JSFunction *fun;
1906
+ JSObject *funobj, *parent, *clone;
1907
+
1908
+ fun = JS_ValueToFunction(cx, argv[0]);
1909
+ if (!fun)
1910
+ return JS_FALSE;
1911
+ funobj = JS_GetFunctionObject(fun);
1912
+ if (argc > 1) {
1913
+ if (!JS_ValueToObject(cx, argv[1], &parent))
1914
+ return JS_FALSE;
1915
+ } else {
1916
+ parent = JS_GetParent(cx, funobj);
1917
+ }
1918
+ clone = JS_CloneFunctionObject(cx, funobj, parent);
1919
+ if (!clone)
1920
+ return JS_FALSE;
1921
+ *rval = OBJECT_TO_JSVAL(clone);
1922
+ return JS_TRUE;
1923
+ }
1924
+
1925
+ static JSBool
1926
+ Seal(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1927
+ {
1928
+ JSObject *target;
1929
+ JSBool deep = JS_FALSE;
1930
+
1931
+ if (!JS_ConvertArguments(cx, argc, argv, "o/b", &target, &deep))
1932
+ return JS_FALSE;
1933
+ if (!target)
1934
+ return JS_TRUE;
1935
+ return JS_SealObject(cx, target, deep);
1936
+ }
1937
+
1938
+ static JSBool
1939
+ GetPDA(JSContext *cx, uintN argc, jsval *vp)
1940
+ {
1941
+ JSObject *vobj, *aobj, *pdobj;
1942
+ JSBool ok;
1943
+ JSPropertyDescArray pda;
1944
+ JSPropertyDesc *pd;
1945
+ uint32 i;
1946
+ jsval v;
1947
+
1948
+ if (!JS_ValueToObject(cx, vp[2], &vobj))
1949
+ return JS_FALSE;
1950
+ if (!vobj)
1951
+ return JS_TRUE;
1952
+
1953
+ aobj = JS_NewArrayObject(cx, 0, NULL);
1954
+ if (!aobj)
1955
+ return JS_FALSE;
1956
+ *vp = OBJECT_TO_JSVAL(aobj);
1957
+
1958
+ ok = JS_GetPropertyDescArray(cx, vobj, &pda);
1959
+ if (!ok)
1960
+ return JS_FALSE;
1961
+ pd = pda.array;
1962
+ for (i = 0; i < pda.length; i++) {
1963
+ pdobj = JS_NewObject(cx, NULL, NULL, NULL);
1964
+ if (!pdobj) {
1965
+ ok = JS_FALSE;
1966
+ break;
1967
+ }
1968
+
1969
+ /* Protect pdobj from GC by setting it as an element of aobj now */
1970
+ v = OBJECT_TO_JSVAL(pdobj);
1971
+ ok = JS_SetElement(cx, aobj, i, &v);
1972
+ if (!ok)
1973
+ break;
1974
+
1975
+ ok = JS_SetProperty(cx, pdobj, "id", &pd->id) &&
1976
+ JS_SetProperty(cx, pdobj, "value", &pd->value) &&
1977
+ (v = INT_TO_JSVAL(pd->flags),
1978
+ JS_SetProperty(cx, pdobj, "flags", &v)) &&
1979
+ (v = INT_TO_JSVAL(pd->slot),
1980
+ JS_SetProperty(cx, pdobj, "slot", &v)) &&
1981
+ JS_SetProperty(cx, pdobj, "alias", &pd->alias);
1982
+ if (!ok)
1983
+ break;
1984
+ }
1985
+ JS_PutPropertyDescArray(cx, &pda);
1986
+ return ok;
1987
+ }
1988
+
1989
+ static JSBool
1990
+ GetSLX(JSContext *cx, uintN argc, jsval *vp)
1991
+ {
1992
+ JSScript *script;
1993
+
1994
+ script = ValueToScript(cx, vp[2]);
1995
+ if (!script)
1996
+ return JS_FALSE;
1997
+ *vp = INT_TO_JSVAL(js_GetScriptLineExtent(script));
1998
+ return JS_TRUE;
1999
+ }
2000
+
2001
+ static JSBool
2002
+ ToInt32(JSContext *cx, uintN argc, jsval *vp)
2003
+ {
2004
+ int32 i;
2005
+
2006
+ if (!JS_ValueToInt32(cx, vp[2], &i))
2007
+ return JS_FALSE;
2008
+ return JS_NewNumberValue(cx, i, vp);
2009
+ }
2010
+
2011
+ static JSBool
2012
+ StringsAreUTF8(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
2013
+ jsval *rval)
2014
+ {
2015
+ *rval = JS_CStringsAreUTF8() ? JSVAL_TRUE : JSVAL_FALSE;
2016
+ return JS_TRUE;
2017
+ }
2018
+
2019
+ static JSBool
2020
+ StackQuota(JSContext *cx, uintN argc, jsval *vp)
2021
+ {
2022
+ uint32 n;
2023
+
2024
+ if (argc == 0)
2025
+ return JS_NewNumberValue(cx, (double) gScriptStackQuota, vp);
2026
+ if (!JS_ValueToECMAUint32(cx, JS_ARGV(cx, vp)[0], &n))
2027
+ return JS_FALSE;
2028
+ gScriptStackQuota = n;
2029
+ JS_SetScriptStackQuota(cx, gScriptStackQuota);
2030
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
2031
+ return JS_TRUE;
2032
+ }
2033
+
2034
+ static const char* badUTF8 = "...\xC0...";
2035
+ static const char* bigUTF8 = "...\xFB\xBF\xBF\xBF\xBF...";
2036
+ static const jschar badSurrogate[] = { 'A', 'B', 'C', 0xDEEE, 'D', 'E', 0 };
2037
+
2038
+ static JSBool
2039
+ TestUTF8(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2040
+ {
2041
+ intN mode = 1;
2042
+ jschar chars[20];
2043
+ size_t charsLength = 5;
2044
+ char bytes[20];
2045
+ size_t bytesLength = 20;
2046
+ if (argc && !JS_ValueToInt32(cx, *argv, &mode))
2047
+ return JS_FALSE;
2048
+
2049
+ /* The following throw errors if compiled with UTF-8. */
2050
+ switch (mode) {
2051
+ /* mode 1: malformed UTF-8 string. */
2052
+ case 1:
2053
+ JS_NewStringCopyZ(cx, badUTF8);
2054
+ break;
2055
+ /* mode 2: big UTF-8 character. */
2056
+ case 2:
2057
+ JS_NewStringCopyZ(cx, bigUTF8);
2058
+ break;
2059
+ /* mode 3: bad surrogate character. */
2060
+ case 3:
2061
+ JS_EncodeCharacters(cx, badSurrogate, 6, bytes, &bytesLength);
2062
+ break;
2063
+ /* mode 4: use a too small buffer. */
2064
+ case 4:
2065
+ JS_DecodeBytes(cx, "1234567890", 10, chars, &charsLength);
2066
+ break;
2067
+ default:
2068
+ JS_ReportError(cx, "invalid mode parameter");
2069
+ return JS_FALSE;
2070
+ }
2071
+ return !JS_IsExceptionPending (cx);
2072
+ }
2073
+
2074
+ static JSBool
2075
+ ThrowError(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2076
+ {
2077
+ JS_ReportError(cx, "This is an error");
2078
+ return JS_FALSE;
2079
+ }
2080
+
2081
+ #define LAZY_STANDARD_CLASSES
2082
+
2083
+ /* A class for easily testing the inner/outer object callbacks. */
2084
+ typedef struct ComplexObject {
2085
+ JSBool isInner;
2086
+ JSObject *inner;
2087
+ JSObject *outer;
2088
+ } ComplexObject;
2089
+
2090
+ static JSObject *
2091
+ split_create_outer(JSContext *cx);
2092
+
2093
+ static JSObject *
2094
+ split_create_inner(JSContext *cx, JSObject *outer);
2095
+
2096
+ static ComplexObject *
2097
+ split_get_private(JSContext *cx, JSObject *obj);
2098
+
2099
+ JS_STATIC_DLL_CALLBACK(JSBool)
2100
+ split_addProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
2101
+ {
2102
+ ComplexObject *cpx;
2103
+ jsid asId;
2104
+
2105
+ cpx = split_get_private(cx, obj);
2106
+ if (!cpx)
2107
+ return JS_TRUE;
2108
+ if (!cpx->isInner && cpx->inner) {
2109
+ /* Make sure to define this property on the inner object. */
2110
+ if (!JS_ValueToId(cx, *vp, &asId))
2111
+ return JS_FALSE;
2112
+ return OBJ_DEFINE_PROPERTY(cx, cpx->inner, asId, *vp, NULL, NULL,
2113
+ JSPROP_ENUMERATE, NULL);
2114
+ }
2115
+ return JS_TRUE;
2116
+ }
2117
+
2118
+ JS_STATIC_DLL_CALLBACK(JSBool)
2119
+ split_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
2120
+ {
2121
+ ComplexObject *cpx;
2122
+
2123
+ cpx = split_get_private(cx, obj);
2124
+ if (!cpx)
2125
+ return JS_TRUE;
2126
+ if (!cpx->isInner && cpx->inner) {
2127
+ if (JSVAL_IS_STRING(id)) {
2128
+ JSString *str;
2129
+
2130
+ str = JSVAL_TO_STRING(id);
2131
+ return JS_GetUCProperty(cx, cpx->inner, JS_GetStringChars(str),
2132
+ JS_GetStringLength(str), vp);
2133
+ }
2134
+ if (JSVAL_IS_INT(id))
2135
+ return JS_GetElement(cx, cpx->inner, JSVAL_TO_INT(id), vp);
2136
+ return JS_TRUE;
2137
+ }
2138
+
2139
+ return JS_TRUE;
2140
+ }
2141
+
2142
+ JS_STATIC_DLL_CALLBACK(JSBool)
2143
+ split_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
2144
+ {
2145
+ ComplexObject *cpx;
2146
+
2147
+ cpx = split_get_private(cx, obj);
2148
+ if (!cpx)
2149
+ return JS_TRUE;
2150
+ if (!cpx->isInner && cpx->inner) {
2151
+ if (JSVAL_IS_STRING(id)) {
2152
+ JSString *str;
2153
+
2154
+ str = JSVAL_TO_STRING(id);
2155
+ return JS_SetUCProperty(cx, cpx->inner, JS_GetStringChars(str),
2156
+ JS_GetStringLength(str), vp);
2157
+ }
2158
+ if (JSVAL_IS_INT(id))
2159
+ return JS_SetElement(cx, cpx->inner, JSVAL_TO_INT(id), vp);
2160
+ return JS_TRUE;
2161
+ }
2162
+
2163
+ return JS_TRUE;
2164
+ }
2165
+
2166
+ JS_STATIC_DLL_CALLBACK(JSBool)
2167
+ split_delProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
2168
+ {
2169
+ ComplexObject *cpx;
2170
+ jsid asId;
2171
+
2172
+ cpx = split_get_private(cx, obj);
2173
+ if (!cpx)
2174
+ return JS_TRUE;
2175
+ if (!cpx->isInner && cpx->inner) {
2176
+ /* Make sure to define this property on the inner object. */
2177
+ if (!JS_ValueToId(cx, *vp, &asId))
2178
+ return JS_FALSE;
2179
+ return OBJ_DELETE_PROPERTY(cx, cpx->inner, asId, vp);
2180
+ }
2181
+ return JS_TRUE;
2182
+ }
2183
+
2184
+ JS_STATIC_DLL_CALLBACK(JSBool)
2185
+ split_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
2186
+ jsval *statep, jsid *idp)
2187
+ {
2188
+ ComplexObject *cpx;
2189
+ JSObject *iterator;
2190
+
2191
+ switch (enum_op) {
2192
+ case JSENUMERATE_INIT:
2193
+ cpx = (ComplexObject *) JS_GetPrivate(cx, obj);
2194
+
2195
+ if (!cpx->isInner && cpx->inner)
2196
+ obj = cpx->inner;
2197
+
2198
+ iterator = JS_NewPropertyIterator(cx, obj);
2199
+ if (!iterator)
2200
+ return JS_FALSE;
2201
+
2202
+ *statep = OBJECT_TO_JSVAL(iterator);
2203
+ if (idp)
2204
+ *idp = JSVAL_ZERO;
2205
+ break;
2206
+
2207
+ case JSENUMERATE_NEXT:
2208
+ iterator = (JSObject*)JSVAL_TO_OBJECT(*statep);
2209
+ if (!JS_NextProperty(cx, iterator, idp))
2210
+ return JS_FALSE;
2211
+
2212
+ if (*idp != JSVAL_VOID)
2213
+ break;
2214
+ /* Fall through. */
2215
+
2216
+ case JSENUMERATE_DESTROY:
2217
+ /* Let GC at our iterator object. */
2218
+ *statep = JSVAL_NULL;
2219
+ break;
2220
+ }
2221
+
2222
+ return JS_TRUE;
2223
+ }
2224
+
2225
+ JS_STATIC_DLL_CALLBACK(JSBool)
2226
+ split_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
2227
+ JSObject **objp)
2228
+ {
2229
+ ComplexObject *cpx;
2230
+
2231
+ cpx = split_get_private(cx, obj);
2232
+ if (!cpx)
2233
+ return JS_TRUE;
2234
+ if (!cpx->isInner && cpx->inner) {
2235
+ jsid asId;
2236
+ JSProperty *prop;
2237
+
2238
+ if (!JS_ValueToId(cx, id, &asId))
2239
+ return JS_FALSE;
2240
+
2241
+ if (!OBJ_LOOKUP_PROPERTY(cx, cpx->inner, asId, objp, &prop))
2242
+ return JS_FALSE;
2243
+ if (prop)
2244
+ OBJ_DROP_PROPERTY(cx, cpx->inner, prop);
2245
+
2246
+ return JS_TRUE;
2247
+ }
2248
+
2249
+ #ifdef LAZY_STANDARD_CLASSES
2250
+ if (!(flags & JSRESOLVE_ASSIGNING)) {
2251
+ JSBool resolved;
2252
+
2253
+ if (!JS_ResolveStandardClass(cx, obj, id, &resolved))
2254
+ return JS_FALSE;
2255
+
2256
+ if (resolved) {
2257
+ *objp = obj;
2258
+ return JS_TRUE;
2259
+ }
2260
+ }
2261
+ #endif
2262
+
2263
+ /* XXX For additional realism, let's resolve some random property here. */
2264
+ return JS_TRUE;
2265
+ }
2266
+
2267
+ JS_STATIC_DLL_CALLBACK(void)
2268
+ split_finalize(JSContext *cx, JSObject *obj)
2269
+ {
2270
+ JS_free(cx, JS_GetPrivate(cx, obj));
2271
+ }
2272
+
2273
+ JS_STATIC_DLL_CALLBACK(uint32)
2274
+ split_mark(JSContext *cx, JSObject *obj, void *arg)
2275
+ {
2276
+ ComplexObject *cpx;
2277
+
2278
+ cpx = (ComplexObject *) JS_GetPrivate(cx, obj);
2279
+
2280
+ if (!cpx->isInner && cpx->inner) {
2281
+ /* Mark the inner object. */
2282
+ JS_MarkGCThing(cx, cpx->inner, "ComplexObject.inner", arg);
2283
+ }
2284
+
2285
+ return 0;
2286
+ }
2287
+
2288
+ JS_STATIC_DLL_CALLBACK(JSObject *)
2289
+ split_outerObject(JSContext *cx, JSObject *obj)
2290
+ {
2291
+ ComplexObject *cpx;
2292
+
2293
+ cpx = (ComplexObject *) JS_GetPrivate(cx, obj);
2294
+ return cpx->isInner ? cpx->outer : obj;
2295
+ }
2296
+
2297
+ JS_STATIC_DLL_CALLBACK(JSObject *)
2298
+ split_innerObject(JSContext *cx, JSObject *obj)
2299
+ {
2300
+ ComplexObject *cpx;
2301
+
2302
+ cpx = (ComplexObject *) JS_GetPrivate(cx, obj);
2303
+ return !cpx->isInner ? cpx->inner : obj;
2304
+ }
2305
+
2306
+ static JSExtendedClass split_global_class = {
2307
+ {"split_global",
2308
+ JSCLASS_NEW_RESOLVE | JSCLASS_HAS_PRIVATE | JSCLASS_IS_EXTENDED,
2309
+ split_addProperty, split_delProperty,
2310
+ split_getProperty, split_setProperty,
2311
+ (JSEnumerateOp)split_enumerate,
2312
+ (JSResolveOp)split_resolve,
2313
+ JS_ConvertStub, split_finalize,
2314
+ NULL, NULL, NULL, NULL, NULL, NULL,
2315
+ split_mark, NULL},
2316
+ NULL, split_outerObject, split_innerObject,
2317
+ NULL, NULL, NULL, NULL, NULL
2318
+ };
2319
+
2320
+ JSObject *
2321
+ split_create_outer(JSContext *cx)
2322
+ {
2323
+ ComplexObject *cpx;
2324
+ JSObject *obj;
2325
+
2326
+ cpx = (ComplexObject *) JS_malloc(cx, sizeof *obj);
2327
+ if (!cpx)
2328
+ return NULL;
2329
+ cpx->outer = NULL;
2330
+ cpx->inner = NULL;
2331
+ cpx->isInner = JS_FALSE;
2332
+
2333
+ obj = JS_NewObject(cx, &split_global_class.base, NULL, NULL);
2334
+ if (!obj) {
2335
+ JS_free(cx, cpx);
2336
+ return NULL;
2337
+ }
2338
+
2339
+ JS_ASSERT(!JS_GetParent(cx, obj));
2340
+ if (!JS_SetPrivate(cx, obj, cpx)) {
2341
+ JS_free(cx, cpx);
2342
+ return NULL;
2343
+ }
2344
+
2345
+ return obj;
2346
+ }
2347
+
2348
+ static JSObject *
2349
+ split_create_inner(JSContext *cx, JSObject *outer)
2350
+ {
2351
+ ComplexObject *cpx, *outercpx;
2352
+ JSObject *obj;
2353
+
2354
+ JS_ASSERT(JS_GET_CLASS(cx, outer) == &split_global_class.base);
2355
+
2356
+ cpx = (ComplexObject *) JS_malloc(cx, sizeof *cpx);
2357
+ if (!cpx)
2358
+ return NULL;
2359
+ cpx->outer = outer;
2360
+ cpx->inner = NULL;
2361
+ cpx->isInner = JS_TRUE;
2362
+
2363
+ obj = JS_NewObject(cx, &split_global_class.base, NULL, NULL);
2364
+ if (!obj || !JS_SetParent(cx, obj, NULL) || !JS_SetPrivate(cx, obj, cpx)) {
2365
+ JS_free(cx, cpx);
2366
+ return NULL;
2367
+ }
2368
+
2369
+ outercpx = (ComplexObject *) JS_GetPrivate(cx, outer);
2370
+ outercpx->inner = obj;
2371
+
2372
+ return obj;
2373
+ }
2374
+
2375
+ static ComplexObject *
2376
+ split_get_private(JSContext *cx, JSObject *obj)
2377
+ {
2378
+ do {
2379
+ if (JS_GET_CLASS(cx, obj) == &split_global_class.base)
2380
+ return (ComplexObject *) JS_GetPrivate(cx, obj);
2381
+ obj = JS_GetParent(cx, obj);
2382
+ } while (obj);
2383
+
2384
+ return NULL;
2385
+ }
2386
+
2387
+ static JSBool
2388
+ sandbox_enumerate(JSContext *cx, JSObject *obj)
2389
+ {
2390
+ jsval v;
2391
+ JSBool b;
2392
+
2393
+ if (!JS_GetProperty(cx, obj, "lazy", &v) || !JS_ValueToBoolean(cx, v, &b))
2394
+ return JS_FALSE;
2395
+ return !b || JS_EnumerateStandardClasses(cx, obj);
2396
+ }
2397
+
2398
+ static JSBool
2399
+ sandbox_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
2400
+ JSObject **objp)
2401
+ {
2402
+ jsval v;
2403
+ JSBool b, resolved;
2404
+
2405
+ if (!JS_GetProperty(cx, obj, "lazy", &v) || !JS_ValueToBoolean(cx, v, &b))
2406
+ return JS_FALSE;
2407
+ if (b && (flags & JSRESOLVE_ASSIGNING) == 0) {
2408
+ if (!JS_ResolveStandardClass(cx, obj, id, &resolved))
2409
+ return JS_FALSE;
2410
+ if (resolved) {
2411
+ *objp = obj;
2412
+ return JS_TRUE;
2413
+ }
2414
+ }
2415
+ *objp = NULL;
2416
+ return JS_TRUE;
2417
+ }
2418
+
2419
+ static JSClass sandbox_class = {
2420
+ "sandbox",
2421
+ JSCLASS_NEW_RESOLVE,
2422
+ JS_PropertyStub, JS_PropertyStub,
2423
+ JS_PropertyStub, JS_PropertyStub,
2424
+ sandbox_enumerate, (JSResolveOp)sandbox_resolve,
2425
+ JS_ConvertStub, JS_FinalizeStub,
2426
+ JSCLASS_NO_OPTIONAL_MEMBERS
2427
+ };
2428
+
2429
+ static JSBool
2430
+ EvalInContext(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
2431
+ jsval *rval)
2432
+ {
2433
+ JSString *str;
2434
+ JSObject *sobj;
2435
+ JSContext *scx;
2436
+ const jschar *src;
2437
+ size_t srclen;
2438
+ JSBool lazy, ok;
2439
+ jsval v;
2440
+ JSStackFrame *fp;
2441
+
2442
+ sobj = NULL;
2443
+ if (!JS_ConvertArguments(cx, argc, argv, "S / o", &str, &sobj))
2444
+ return JS_FALSE;
2445
+
2446
+ scx = JS_NewContext(JS_GetRuntime(cx), gStackChunkSize);
2447
+ if (!scx) {
2448
+ JS_ReportOutOfMemory(cx);
2449
+ return JS_FALSE;
2450
+ }
2451
+
2452
+ #ifdef JS_THREADSAFE
2453
+ JS_BeginRequest(scx);
2454
+ #endif
2455
+ src = JS_GetStringChars(str);
2456
+ srclen = JS_GetStringLength(str);
2457
+ lazy = JS_FALSE;
2458
+ if (srclen == 4 &&
2459
+ src[0] == 'l' && src[1] == 'a' && src[2] == 'z' && src[3] == 'y') {
2460
+ lazy = JS_TRUE;
2461
+ srclen = 0;
2462
+ }
2463
+
2464
+ if (!sobj) {
2465
+ sobj = JS_NewObject(scx, &sandbox_class, NULL, NULL);
2466
+ if (!sobj || (!lazy && !JS_InitStandardClasses(scx, sobj))) {
2467
+ ok = JS_FALSE;
2468
+ goto out;
2469
+ }
2470
+ v = BOOLEAN_TO_JSVAL(lazy);
2471
+ ok = JS_SetProperty(cx, sobj, "lazy", &v);
2472
+ if (!ok)
2473
+ goto out;
2474
+ }
2475
+
2476
+ if (srclen == 0) {
2477
+ *rval = OBJECT_TO_JSVAL(sobj);
2478
+ ok = JS_TRUE;
2479
+ } else {
2480
+ fp = JS_GetScriptedCaller(cx, NULL);
2481
+ JS_SetGlobalObject(scx, sobj);
2482
+ JS_ToggleOptions(scx, JSOPTION_DONT_REPORT_UNCAUGHT);
2483
+ ok = JS_EvaluateUCScript(scx, sobj, src, srclen,
2484
+ fp->script->filename,
2485
+ JS_PCToLineNumber(cx, fp->script,
2486
+ fp->regs->pc),
2487
+ rval);
2488
+ if (!ok) {
2489
+ if (JS_GetPendingException(scx, &v))
2490
+ JS_SetPendingException(cx, v);
2491
+ else
2492
+ JS_ReportOutOfMemory(cx);
2493
+ }
2494
+ }
2495
+
2496
+ out:
2497
+ #ifdef JS_THREADSAFE
2498
+ JS_EndRequest(scx);
2499
+ #endif
2500
+ JS_DestroyContext(scx);
2501
+ return ok;
2502
+ }
2503
+
2504
+ #ifdef JS_THREADSAFE
2505
+
2506
+ static JSBool
2507
+ Sleep(JSContext *cx, uintN argc, jsval *vp)
2508
+ {
2509
+ jsdouble t_secs;
2510
+ PRUint32 t_ticks;
2511
+ jsrefcount rc;
2512
+
2513
+ if (!JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "d", &t_secs))
2514
+ return JS_FALSE;
2515
+
2516
+ if (t_secs < 0 || JSDOUBLE_IS_NaN(t_secs))
2517
+ t_secs = 0;
2518
+
2519
+ rc = JS_SuspendRequest(cx);
2520
+ t_ticks = (PRUint32)(PR_TicksPerSecond() * t_secs);
2521
+ if (PR_Sleep(t_ticks) == PR_SUCCESS)
2522
+ *vp = JSVAL_TRUE;
2523
+ else
2524
+ *vp = JSVAL_FALSE;
2525
+ JS_ResumeRequest(cx, rc);
2526
+ return JS_TRUE;
2527
+ }
2528
+
2529
+ typedef struct ScatterThreadData ScatterThreadData;
2530
+ typedef struct ScatterData ScatterData;
2531
+ typedef enum ScatterStatus ScatterStatus;
2532
+
2533
+ enum ScatterStatus {
2534
+ SCATTER_WAIT,
2535
+ SCATTER_GO,
2536
+ SCATTER_CANCEL
2537
+ };
2538
+
2539
+ struct ScatterData {
2540
+ ScatterThreadData *threads;
2541
+ jsval *results;
2542
+ PRLock *lock;
2543
+ PRCondVar *cvar;
2544
+ ScatterStatus status;
2545
+ };
2546
+
2547
+ struct ScatterThreadData {
2548
+ jsint index;
2549
+ ScatterData *shared;
2550
+ PRThread *thr;
2551
+ JSContext *cx;
2552
+ jsval fn;
2553
+ };
2554
+
2555
+ static void
2556
+ DoScatteredWork(JSContext *cx, ScatterThreadData *td)
2557
+ {
2558
+ jsval *rval = &td->shared->results[td->index];
2559
+
2560
+ if (!JS_CallFunctionValue(cx, NULL, td->fn, 0, NULL, rval)) {
2561
+ *rval = JSVAL_VOID;
2562
+ JS_GetPendingException(cx, rval);
2563
+ JS_ClearPendingException(cx);
2564
+ }
2565
+ }
2566
+
2567
+ static void
2568
+ RunScatterThread(void *arg)
2569
+ {
2570
+ ScatterThreadData *td;
2571
+ ScatterStatus st;
2572
+ JSContext *cx;
2573
+
2574
+ td = (ScatterThreadData *)arg;
2575
+ cx = td->cx;
2576
+
2577
+ /* Wait for go signal. */
2578
+ PR_Lock(td->shared->lock);
2579
+ while ((st = td->shared->status) == SCATTER_WAIT)
2580
+ PR_WaitCondVar(td->shared->cvar, PR_INTERVAL_NO_TIMEOUT);
2581
+ PR_Unlock(td->shared->lock);
2582
+
2583
+ if (st == SCATTER_CANCEL)
2584
+ return;
2585
+
2586
+ /* We are go. */
2587
+ JS_SetContextThread(cx);
2588
+ JS_SetThreadStackLimit(cx, 0);
2589
+ JS_BeginRequest(cx);
2590
+ DoScatteredWork(cx, td);
2591
+ JS_EndRequest(cx);
2592
+ JS_ClearContextThread(cx);
2593
+ }
2594
+
2595
+ /*
2596
+ * scatter(fnArray) - Call each function in `fnArray` without arguments, each
2597
+ * in a different thread. When all threads have finished, return an array: the
2598
+ * return values. Errors are not propagated; if any of the function calls
2599
+ * fails, the corresponding element in the results array gets the exception
2600
+ * object, if any, else (undefined).
2601
+ */
2602
+ static JSBool
2603
+ Scatter(JSContext *cx, uintN argc, jsval *vp)
2604
+ {
2605
+ jsuint i;
2606
+ jsuint n; /* number of threads */
2607
+ JSObject *inArr;
2608
+ JSObject *arr;
2609
+ ScatterData sd;
2610
+ JSBool ok;
2611
+ jsrefcount rc;
2612
+
2613
+ if (!gEnableBranchCallback) {
2614
+ /* Enable the branch callback, for periodic scope-sharing. */
2615
+ gEnableBranchCallback = JS_TRUE;
2616
+ JS_SetBranchCallback(cx, my_BranchCallback);
2617
+ JS_ToggleOptions(cx, JSOPTION_NATIVE_BRANCH_CALLBACK);
2618
+ }
2619
+
2620
+ sd.lock = NULL;
2621
+ sd.cvar = NULL;
2622
+ sd.results = NULL;
2623
+ sd.threads = NULL;
2624
+ sd.status = SCATTER_WAIT;
2625
+
2626
+ if (JSVAL_IS_PRIMITIVE(JS_ARGV(cx, vp)[0]))
2627
+ goto fail;
2628
+
2629
+ inArr = JSVAL_TO_OBJECT(JS_ARGV(cx, vp)[0]);
2630
+ ok = JS_GetArrayLength(cx, inArr, &n);
2631
+ if (!ok)
2632
+ goto out;
2633
+ if (n == 0)
2634
+ goto success;
2635
+
2636
+ sd.lock = PR_NewLock();
2637
+ if (!sd.lock)
2638
+ goto fail;
2639
+
2640
+ sd.cvar = PR_NewCondVar(sd.lock);
2641
+ if (!sd.cvar)
2642
+ goto fail;
2643
+
2644
+ sd.results = (jsval *) malloc(n * sizeof(jsval));
2645
+ if (!sd.results)
2646
+ goto fail;
2647
+ for (i = 0; i < n; i++) {
2648
+ sd.results[i] = JSVAL_VOID;
2649
+ ok = JS_AddRoot(cx, &sd.results[i]);
2650
+ if (!ok) {
2651
+ while (i-- > 0)
2652
+ JS_RemoveRoot(cx, &sd.results[i]);
2653
+ free(sd.results);
2654
+ sd.results = NULL;
2655
+ goto fail;
2656
+ }
2657
+ }
2658
+
2659
+ sd.threads = (ScatterThreadData *) malloc(n * sizeof(ScatterThreadData));
2660
+ if (!sd.threads)
2661
+ goto fail;
2662
+ for (i = 0; i < n; i++) {
2663
+ sd.threads[i].index = i;
2664
+ sd.threads[i].shared = &sd;
2665
+ sd.threads[i].thr = NULL;
2666
+ sd.threads[i].cx = NULL;
2667
+ sd.threads[i].fn = JSVAL_NULL;
2668
+
2669
+ ok = JS_AddRoot(cx, &sd.threads[i].fn);
2670
+ if (ok && !JS_GetElement(cx, inArr, (jsint) i, &sd.threads[i].fn)) {
2671
+ JS_RemoveRoot(cx, &sd.threads[i].fn);
2672
+ ok = JS_FALSE;
2673
+ }
2674
+ if (!ok) {
2675
+ while (i-- > 0)
2676
+ JS_RemoveRoot(cx, &sd.threads[i].fn);
2677
+ free(sd.threads);
2678
+ sd.threads = NULL;
2679
+ goto fail;
2680
+ }
2681
+ }
2682
+
2683
+ for (i = 1; i < n; i++) {
2684
+ JSContext *newcx = JS_NewContext(JS_GetRuntime(cx), 8192);
2685
+ if (!newcx)
2686
+ goto fail;
2687
+ JS_SetGlobalObject(newcx, JS_GetGlobalObject(cx));
2688
+ JS_ClearContextThread(newcx);
2689
+ sd.threads[i].cx = newcx;
2690
+ }
2691
+
2692
+ for (i = 1; i < n; i++) {
2693
+ PRThread *t = PR_CreateThread(PR_USER_THREAD,
2694
+ RunScatterThread,
2695
+ &sd.threads[i],
2696
+ PR_PRIORITY_NORMAL,
2697
+ PR_GLOBAL_THREAD,
2698
+ PR_JOINABLE_THREAD,
2699
+ 0);
2700
+ if (!t) {
2701
+ /* Failed to start thread. */
2702
+ PR_Lock(sd.lock);
2703
+ sd.status = SCATTER_CANCEL;
2704
+ PR_NotifyAllCondVar(sd.cvar);
2705
+ PR_Unlock(sd.lock);
2706
+ while (i-- > 1)
2707
+ PR_JoinThread(sd.threads[i].thr);
2708
+ goto fail;
2709
+ }
2710
+
2711
+ sd.threads[i].thr = t;
2712
+ }
2713
+ PR_Lock(sd.lock);
2714
+ sd.status = SCATTER_GO;
2715
+ PR_NotifyAllCondVar(sd.cvar);
2716
+ PR_Unlock(sd.lock);
2717
+
2718
+ DoScatteredWork(cx, &sd.threads[0]);
2719
+
2720
+ rc = JS_SuspendRequest(cx);
2721
+ for (i = 1; i < n; i++) {
2722
+ PR_JoinThread(sd.threads[i].thr);
2723
+ }
2724
+ JS_ResumeRequest(cx, rc);
2725
+
2726
+ success:
2727
+ arr = JS_NewArrayObject(cx, n, sd.results);
2728
+ if (!arr)
2729
+ goto fail;
2730
+ *vp = OBJECT_TO_JSVAL(arr);
2731
+ ok = JS_TRUE;
2732
+
2733
+ out:
2734
+ if (sd.threads) {
2735
+ JSContext *acx;
2736
+
2737
+ for (i = 0; i < n; i++) {
2738
+ JS_RemoveRoot(cx, &sd.threads[i].fn);
2739
+ acx = sd.threads[i].cx;
2740
+ if (acx) {
2741
+ JS_SetContextThread(acx);
2742
+ JS_DestroyContext(acx);
2743
+ }
2744
+ }
2745
+ free(sd.threads);
2746
+ }
2747
+ if (sd.results) {
2748
+ for (i = 0; i < n; i++)
2749
+ JS_RemoveRoot(cx, &sd.results[i]);
2750
+ free(sd.results);
2751
+ }
2752
+ if (sd.cvar)
2753
+ PR_DestroyCondVar(sd.cvar);
2754
+ if (sd.lock)
2755
+ PR_DestroyLock(sd.lock);
2756
+
2757
+ return ok;
2758
+
2759
+ fail:
2760
+ ok = JS_FALSE;
2761
+ goto out;
2762
+ }
2763
+
2764
+ #endif
2765
+
2766
+ /* We use a mix of JS_FS and JS_FN to test both kinds of natives. */
2767
+ static JSFunctionSpec shell_functions[] = {
2768
+ JS_FS("version", Version, 0,0,0),
2769
+ JS_FS("options", Options, 0,0,0),
2770
+ JS_FS("load", Load, 1,0,0),
2771
+ JS_FN("readline", ReadLine, 0,0,0),
2772
+ JS_FS("print", Print, 0,0,0),
2773
+ JS_FS("help", Help, 0,0,0),
2774
+ JS_FS("quit", Quit, 0,0,0),
2775
+ JS_FN("gc", GC, 0,0,0),
2776
+ JS_FN("gcparam", GCParameter, 2,2,0),
2777
+ JS_FN("countHeap", CountHeap, 0,0,0),
2778
+ #ifdef JS_GC_ZEAL
2779
+ JS_FN("gczeal", GCZeal, 1,1,0),
2780
+ #endif
2781
+ JS_FS("trap", Trap, 3,0,0),
2782
+ JS_FS("untrap", Untrap, 2,0,0),
2783
+ JS_FS("line2pc", LineToPC, 0,0,0),
2784
+ JS_FS("pc2line", PCToLine, 0,0,0),
2785
+ JS_FN("stackQuota", StackQuota, 0,0,0),
2786
+ JS_FS("stringsAreUTF8", StringsAreUTF8, 0,0,0),
2787
+ JS_FS("testUTF8", TestUTF8, 1,0,0),
2788
+ JS_FS("throwError", ThrowError, 0,0,0),
2789
+ #ifdef DEBUG
2790
+ JS_FS("dis", Disassemble, 1,0,0),
2791
+ JS_FS("dissrc", DisassWithSrc, 1,0,0),
2792
+ JS_FN("dumpHeap", DumpHeap, 0,0,0),
2793
+ JS_FS("notes", Notes, 1,0,0),
2794
+ JS_FS("tracing", Tracing, 0,0,0),
2795
+ JS_FS("stats", DumpStats, 1,0,0),
2796
+ #endif
2797
+ #ifdef TEST_EXPORT
2798
+ JS_FS("xport", DoExport, 2,0,0),
2799
+ #endif
2800
+ #ifdef TEST_CVTARGS
2801
+ JS_FS("cvtargs", ConvertArgs, 0,0,12),
2802
+ #endif
2803
+ JS_FN("build", BuildDate, 0,0,0),
2804
+ JS_FS("clear", Clear, 0,0,0),
2805
+ JS_FN("intern", Intern, 1,1,0),
2806
+ JS_FS("clone", Clone, 1,0,0),
2807
+ JS_FS("seal", Seal, 1,0,1),
2808
+ JS_FN("getpda", GetPDA, 1,1,0),
2809
+ JS_FN("getslx", GetSLX, 1,1,0),
2810
+ JS_FN("toint32", ToInt32, 1,1,0),
2811
+ JS_FS("evalcx", EvalInContext, 1,0,0),
2812
+ #ifdef MOZ_SHARK
2813
+ JS_FS("startShark", js_StartShark, 0,0,0),
2814
+ JS_FS("stopShark", js_StopShark, 0,0,0),
2815
+ JS_FS("connectShark", js_ConnectShark, 0,0,0),
2816
+ JS_FS("disconnectShark", js_DisconnectShark, 0,0,0),
2817
+ #endif
2818
+ #ifdef DEBUG_ARRAYS
2819
+ JS_FS("arrayInfo", js_ArrayInfo, 1,0,0),
2820
+ #endif
2821
+ #ifdef JS_THREADSAFE
2822
+ JS_FN("sleep", Sleep, 1,1,0),
2823
+ JS_FN("scatter", Scatter, 1,1,0),
2824
+ #endif
2825
+ JS_FS_END
2826
+ };
2827
+
2828
+ static const char shell_help_header[] =
2829
+ "Command Description\n"
2830
+ "======= ===========\n";
2831
+
2832
+ static const char *const shell_help_messages[] = {
2833
+ "version([number]) Get or set JavaScript version number",
2834
+ "options([option ...]) Get or toggle JavaScript options",
2835
+ "load(['foo.js' ...]) Load files named by string arguments",
2836
+ "readline() Read a single line from stdin",
2837
+ "print([exp ...]) Evaluate and print expressions",
2838
+ "help([name ...]) Display usage and help messages",
2839
+ "quit() Quit the shell",
2840
+ "gc() Run the garbage collector",
2841
+ "gcparam(name, value)\n"
2842
+ " Wrapper for JS_SetGCParameter. The name must be either 'maxBytes' or\n"
2843
+ " 'maxMallocBytes' and the value must be convertable to a positive uint32",
2844
+ "countHeap([start[, kind]])\n"
2845
+ " Count the number of live GC things in the heap or things reachable from\n"
2846
+ " start when it is given and is not null. kind is either 'all' (default) to\n"
2847
+ " count all things or one of 'object', 'double', 'string', 'function',\n"
2848
+ " 'qname', 'namespace', 'xml' to count only things of that kind",
2849
+ #ifdef JS_GC_ZEAL
2850
+ "gczeal(level) How zealous the garbage collector should be",
2851
+ #endif
2852
+ "trap([fun, [pc,]] exp) Trap bytecode execution",
2853
+ "untrap(fun[, pc]) Remove a trap",
2854
+ "line2pc([fun,] line) Map line number to PC",
2855
+ "pc2line(fun[, pc]) Map PC to line number",
2856
+ "stackQuota([number]) Query/set script stack quota",
2857
+ "stringsAreUTF8() Check if strings are UTF-8 encoded",
2858
+ "testUTF8(mode) Perform UTF-8 tests (modes are 1 to 4)",
2859
+ "throwError() Throw an error from JS_ReportError",
2860
+ #ifdef DEBUG
2861
+ "dis([fun]) Disassemble functions into bytecodes",
2862
+ "dissrc([fun]) Disassemble functions with source lines",
2863
+ "dumpHeap([fileName[, start[, toFind[, maxDepth[, toIgnore]]]]])\n"
2864
+ " Interface to JS_DumpHeap with output sent to file",
2865
+ "notes([fun]) Show source notes for functions",
2866
+ "tracing([toggle]) Turn tracing on or off",
2867
+ "stats([string ...]) Dump 'arena', 'atom', 'global' stats",
2868
+ #endif
2869
+ #ifdef TEST_EXPORT
2870
+ "xport(obj, property) Export the given property of obj",
2871
+ #endif
2872
+ #ifdef TEST_CVTARGS
2873
+ "cvtargs(arg1..., arg12) Test argument formater",
2874
+ #endif
2875
+ "build() Show build date and time",
2876
+ "clear([obj]) Clear properties of object",
2877
+ "intern(str) Internalize str in the atom table",
2878
+ "clone(fun[, scope]) Clone function object",
2879
+ "seal(obj[, deep]) Seal object, or object graph if deep",
2880
+ "getpda(obj) Get the property descriptors for obj",
2881
+ "getslx(obj) Get script line extent",
2882
+ "toint32(n) Testing hook for JS_ValueToInt32",
2883
+ "evalcx(s[, o])\n"
2884
+ " Evaluate s in optional sandbox object o\n"
2885
+ " if (s == '' && !o) return new o with eager standard classes\n"
2886
+ " if (s == 'lazy' && !o) return new o with lazy standard classes",
2887
+ #ifdef MOZ_SHARK
2888
+ "startShark() Start a Shark session.\n"
2889
+ " Shark must be running with programatic sampling.",
2890
+ "stopShark() Stop a running Shark session.",
2891
+ "connectShark() Connect to Shark.\n"
2892
+ " The -k switch does this automatically.",
2893
+ "disconnectShark() Disconnect from Shark.",
2894
+ #endif
2895
+ #ifdef DEBUG_ARRAYS
2896
+ "arrayInfo(a1, a2, ...) Report statistics about arrays.",
2897
+ #endif
2898
+ #ifdef JS_THREADSAFE
2899
+ "sleep(dt) Sleep for dt seconds",
2900
+ "scatter(fns) Call functions concurrently (ignoring errors)",
2901
+ #endif
2902
+ };
2903
+
2904
+ /* Help messages must match shell functions. */
2905
+ JS_STATIC_ASSERT(JS_ARRAY_LENGTH(shell_help_messages) + 1 ==
2906
+ JS_ARRAY_LENGTH(shell_functions));
2907
+
2908
+ #ifdef DEBUG
2909
+ static void
2910
+ CheckHelpMessages()
2911
+ {
2912
+ const char *const *m;
2913
+ const char *lp;
2914
+
2915
+ /* Each message must begin with "function_name(" prefix. */
2916
+ for (m = shell_help_messages; m != JS_ARRAY_END(shell_help_messages); ++m) {
2917
+ lp = strchr(*m, '(');
2918
+ JS_ASSERT(lp);
2919
+ JS_ASSERT(memcmp(shell_functions[m - shell_help_messages].name,
2920
+ *m, lp - *m) == 0);
2921
+ }
2922
+ }
2923
+ #else
2924
+ # define CheckHelpMessages() ((void) 0)
2925
+ #endif
2926
+
2927
+ static JSBool
2928
+ Help(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2929
+ {
2930
+ uintN i, j;
2931
+ int did_header, did_something;
2932
+ JSType type;
2933
+ JSFunction *fun;
2934
+ JSString *str;
2935
+ const char *bytes;
2936
+
2937
+ fprintf(gOutFile, "%s\n", JS_GetImplementationVersion());
2938
+ if (argc == 0) {
2939
+ fputs(shell_help_header, gOutFile);
2940
+ for (i = 0; shell_functions[i].name; i++)
2941
+ fprintf(gOutFile, "%s\n", shell_help_messages[i]);
2942
+ } else {
2943
+ did_header = 0;
2944
+ for (i = 0; i < argc; i++) {
2945
+ did_something = 0;
2946
+ type = JS_TypeOfValue(cx, argv[i]);
2947
+ if (type == JSTYPE_FUNCTION) {
2948
+ fun = JS_ValueToFunction(cx, argv[i]);
2949
+ str = fun->atom ? ATOM_TO_STRING(fun->atom) : NULL;
2950
+ } else if (type == JSTYPE_STRING) {
2951
+ str = JSVAL_TO_STRING(argv[i]);
2952
+ } else {
2953
+ str = NULL;
2954
+ }
2955
+ if (str) {
2956
+ bytes = JS_GetStringBytes(str);
2957
+ for (j = 0; shell_functions[j].name; j++) {
2958
+ if (!strcmp(bytes, shell_functions[j].name)) {
2959
+ if (!did_header) {
2960
+ did_header = 1;
2961
+ fputs(shell_help_header, gOutFile);
2962
+ }
2963
+ did_something = 1;
2964
+ fprintf(gOutFile, "%s\n", shell_help_messages[j]);
2965
+ break;
2966
+ }
2967
+ }
2968
+ }
2969
+ if (!did_something) {
2970
+ str = JS_ValueToString(cx, argv[i]);
2971
+ if (!str)
2972
+ return JS_FALSE;
2973
+ fprintf(gErrFile, "Sorry, no help for %s\n",
2974
+ JS_GetStringBytes(str));
2975
+ }
2976
+ }
2977
+ }
2978
+ return JS_TRUE;
2979
+ }
2980
+
2981
+ static JSObject *
2982
+ split_setup(JSContext *cx)
2983
+ {
2984
+ JSObject *outer, *inner, *arguments;
2985
+
2986
+ outer = split_create_outer(cx);
2987
+ if (!outer)
2988
+ return NULL;
2989
+ JS_SetGlobalObject(cx, outer);
2990
+
2991
+ inner = split_create_inner(cx, outer);
2992
+ if (!inner)
2993
+ return NULL;
2994
+
2995
+ if (!JS_DefineFunctions(cx, inner, shell_functions))
2996
+ return NULL;
2997
+ JS_ClearScope(cx, outer);
2998
+
2999
+ /* Create a dummy arguments object. */
3000
+ arguments = JS_NewArrayObject(cx, 0, NULL);
3001
+ if (!arguments ||
3002
+ !JS_DefineProperty(cx, inner, "arguments", OBJECT_TO_JSVAL(arguments),
3003
+ NULL, NULL, 0)) {
3004
+ return NULL;
3005
+ }
3006
+
3007
+ #ifndef LAZY_STANDARD_CLASSES
3008
+ if (!JS_InitStandardClasses(cx, inner))
3009
+ return NULL;
3010
+ #endif
3011
+
3012
+ return inner;
3013
+ }
3014
+
3015
+ /*
3016
+ * Define a JS object called "it". Give it class operations that printf why
3017
+ * they're being called for tutorial purposes.
3018
+ */
3019
+ enum its_tinyid {
3020
+ ITS_COLOR, ITS_HEIGHT, ITS_WIDTH, ITS_FUNNY, ITS_ARRAY, ITS_RDONLY
3021
+ };
3022
+
3023
+ static JSPropertySpec its_props[] = {
3024
+ {"color", ITS_COLOR, JSPROP_ENUMERATE, NULL, NULL},
3025
+ {"height", ITS_HEIGHT, JSPROP_ENUMERATE, NULL, NULL},
3026
+ {"width", ITS_WIDTH, JSPROP_ENUMERATE, NULL, NULL},
3027
+ {"funny", ITS_FUNNY, JSPROP_ENUMERATE, NULL, NULL},
3028
+ {"array", ITS_ARRAY, JSPROP_ENUMERATE, NULL, NULL},
3029
+ {"rdonly", ITS_RDONLY, JSPROP_READONLY, NULL, NULL},
3030
+ {NULL,0,0,NULL,NULL}
3031
+ };
3032
+
3033
+ static JSBool
3034
+ its_item(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
3035
+ {
3036
+ *rval = OBJECT_TO_JSVAL(obj);
3037
+ if (argc != 0)
3038
+ JS_SetCallReturnValue2(cx, argv[0]);
3039
+ return JS_TRUE;
3040
+ }
3041
+
3042
+ static JSBool
3043
+ its_bindMethod(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
3044
+ jsval *rval)
3045
+ {
3046
+ char *name;
3047
+ JSObject *method;
3048
+
3049
+ if (!JS_ConvertArguments(cx, argc, argv, "so", &name, &method))
3050
+ return JS_FALSE;
3051
+
3052
+ *rval = OBJECT_TO_JSVAL(method);
3053
+
3054
+ if (JS_TypeOfValue(cx, *rval) != JSTYPE_FUNCTION) {
3055
+ JSString *valstr = JS_ValueToString(cx, *rval);
3056
+ if (valstr) {
3057
+ JS_ReportError(cx, "can't bind method %s to non-callable object %s",
3058
+ name, JS_GetStringBytes(valstr));
3059
+ }
3060
+ return JS_FALSE;
3061
+ }
3062
+
3063
+ if (!JS_DefineProperty(cx, obj, name, *rval, NULL, NULL, JSPROP_ENUMERATE))
3064
+ return JS_FALSE;
3065
+
3066
+ return JS_SetParent(cx, method, obj);
3067
+ }
3068
+
3069
+ static JSFunctionSpec its_methods[] = {
3070
+ {"item", its_item, 0,0,0},
3071
+ {"bindMethod", its_bindMethod, 2,0,0},
3072
+ {NULL,NULL,0,0,0}
3073
+ };
3074
+
3075
+ #ifdef JSD_LOWLEVEL_SOURCE
3076
+ /*
3077
+ * This facilitates sending source to JSD (the debugger system) in the shell
3078
+ * where the source is loaded using the JSFILE hack in jsscan. The function
3079
+ * below is used as a callback for the jsdbgapi JS_SetSourceHandler hook.
3080
+ * A more normal embedding (e.g. mozilla) loads source itself and can send
3081
+ * source directly to JSD without using this hook scheme.
3082
+ */
3083
+ static void
3084
+ SendSourceToJSDebugger(const char *filename, uintN lineno,
3085
+ jschar *str, size_t length,
3086
+ void **listenerTSData, JSDContext* jsdc)
3087
+ {
3088
+ JSDSourceText *jsdsrc = (JSDSourceText *) *listenerTSData;
3089
+
3090
+ if (!jsdsrc) {
3091
+ if (!filename)
3092
+ filename = "typein";
3093
+ if (1 == lineno) {
3094
+ jsdsrc = JSD_NewSourceText(jsdc, filename);
3095
+ } else {
3096
+ jsdsrc = JSD_FindSourceForURL(jsdc, filename);
3097
+ if (jsdsrc && JSD_SOURCE_PARTIAL !=
3098
+ JSD_GetSourceStatus(jsdc, jsdsrc)) {
3099
+ jsdsrc = NULL;
3100
+ }
3101
+ }
3102
+ }
3103
+ if (jsdsrc) {
3104
+ jsdsrc = JSD_AppendUCSourceText(jsdc,jsdsrc, str, length,
3105
+ JSD_SOURCE_PARTIAL);
3106
+ }
3107
+ *listenerTSData = jsdsrc;
3108
+ }
3109
+ #endif /* JSD_LOWLEVEL_SOURCE */
3110
+
3111
+ static JSBool its_noisy; /* whether to be noisy when finalizing it */
3112
+ static JSBool its_enum_fail;/* whether to fail when enumerating it */
3113
+
3114
+ static JSBool
3115
+ its_addProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
3116
+ {
3117
+ if (its_noisy) {
3118
+ fprintf(gOutFile, "adding its property %s,",
3119
+ JS_GetStringBytes(JS_ValueToString(cx, id)));
3120
+ fprintf(gOutFile, " initial value %s\n",
3121
+ JS_GetStringBytes(JS_ValueToString(cx, *vp)));
3122
+ }
3123
+ return JS_TRUE;
3124
+ }
3125
+
3126
+ static JSBool
3127
+ its_delProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
3128
+ {
3129
+ if (its_noisy) {
3130
+ fprintf(gOutFile, "deleting its property %s,",
3131
+ JS_GetStringBytes(JS_ValueToString(cx, id)));
3132
+ fprintf(gOutFile, " current value %s\n",
3133
+ JS_GetStringBytes(JS_ValueToString(cx, *vp)));
3134
+ }
3135
+ return JS_TRUE;
3136
+ }
3137
+
3138
+ static JSBool
3139
+ its_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
3140
+ {
3141
+ if (its_noisy) {
3142
+ fprintf(gOutFile, "getting its property %s,",
3143
+ JS_GetStringBytes(JS_ValueToString(cx, id)));
3144
+ fprintf(gOutFile, " current value %s\n",
3145
+ JS_GetStringBytes(JS_ValueToString(cx, *vp)));
3146
+ }
3147
+ return JS_TRUE;
3148
+ }
3149
+
3150
+ static JSBool
3151
+ its_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
3152
+ {
3153
+ char *str;
3154
+ if (its_noisy) {
3155
+ fprintf(gOutFile, "setting its property %s,",
3156
+ JS_GetStringBytes(JS_ValueToString(cx, id)));
3157
+ fprintf(gOutFile, " new value %s\n",
3158
+ JS_GetStringBytes(JS_ValueToString(cx, *vp)));
3159
+ }
3160
+
3161
+ if (!JSVAL_IS_STRING(id))
3162
+ return JS_TRUE;
3163
+
3164
+ str = JS_GetStringBytes(JSVAL_TO_STRING(id));
3165
+ if (!strcmp(str, "noisy"))
3166
+ return JS_ValueToBoolean(cx, *vp, &its_noisy);
3167
+ else if (!strcmp(str, "enum_fail"))
3168
+ return JS_ValueToBoolean(cx, *vp, &its_enum_fail);
3169
+
3170
+ return JS_TRUE;
3171
+ }
3172
+
3173
+ /*
3174
+ * Its enumerator, implemented using the "new" enumerate API,
3175
+ * see class flags.
3176
+ */
3177
+ static JSBool
3178
+ its_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
3179
+ jsval *statep, jsid *idp)
3180
+ {
3181
+ JSObject *iterator;
3182
+
3183
+ switch (enum_op) {
3184
+ case JSENUMERATE_INIT:
3185
+ if (its_noisy)
3186
+ fprintf(gOutFile, "enumerate its properties\n");
3187
+
3188
+ iterator = JS_NewPropertyIterator(cx, obj);
3189
+ if (!iterator)
3190
+ return JS_FALSE;
3191
+
3192
+ *statep = OBJECT_TO_JSVAL(iterator);
3193
+ if (idp)
3194
+ *idp = JSVAL_ZERO;
3195
+ break;
3196
+
3197
+ case JSENUMERATE_NEXT:
3198
+ if (its_enum_fail) {
3199
+ JS_ReportError(cx, "its enumeration failed");
3200
+ return JS_FALSE;
3201
+ }
3202
+
3203
+ iterator = (JSObject *) JSVAL_TO_OBJECT(*statep);
3204
+ if (!JS_NextProperty(cx, iterator, idp))
3205
+ return JS_FALSE;
3206
+
3207
+ if (*idp != JSVAL_VOID)
3208
+ break;
3209
+ /* Fall through. */
3210
+
3211
+ case JSENUMERATE_DESTROY:
3212
+ /* Allow our iterator object to be GC'd. */
3213
+ *statep = JSVAL_NULL;
3214
+ break;
3215
+ }
3216
+
3217
+ return JS_TRUE;
3218
+ }
3219
+
3220
+ static JSBool
3221
+ its_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
3222
+ JSObject **objp)
3223
+ {
3224
+ if (its_noisy) {
3225
+ fprintf(gOutFile, "resolving its property %s, flags {%s,%s,%s}\n",
3226
+ JS_GetStringBytes(JS_ValueToString(cx, id)),
3227
+ (flags & JSRESOLVE_QUALIFIED) ? "qualified" : "",
3228
+ (flags & JSRESOLVE_ASSIGNING) ? "assigning" : "",
3229
+ (flags & JSRESOLVE_DETECTING) ? "detecting" : "");
3230
+ }
3231
+ return JS_TRUE;
3232
+ }
3233
+
3234
+ static JSBool
3235
+ its_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
3236
+ {
3237
+ if (its_noisy)
3238
+ fprintf(gOutFile, "converting it to %s type\n", JS_GetTypeName(cx, type));
3239
+ return JS_TRUE;
3240
+ }
3241
+
3242
+ static void
3243
+ its_finalize(JSContext *cx, JSObject *obj)
3244
+ {
3245
+ if (its_noisy)
3246
+ fprintf(gOutFile, "finalizing it\n");
3247
+ }
3248
+
3249
+ static JSClass its_class = {
3250
+ "It", JSCLASS_NEW_RESOLVE | JSCLASS_NEW_ENUMERATE,
3251
+ its_addProperty, its_delProperty, its_getProperty, its_setProperty,
3252
+ (JSEnumerateOp)its_enumerate, (JSResolveOp)its_resolve,
3253
+ its_convert, its_finalize,
3254
+ JSCLASS_NO_OPTIONAL_MEMBERS
3255
+ };
3256
+
3257
+ JSErrorFormatString jsShell_ErrorFormatString[JSErr_Limit] = {
3258
+ #define MSG_DEF(name, number, count, exception, format) \
3259
+ { format, count, JSEXN_ERR } ,
3260
+ #include "jsshell.msg"
3261
+ #undef MSG_DEF
3262
+ };
3263
+
3264
+ static const JSErrorFormatString *
3265
+ my_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber)
3266
+ {
3267
+ if ((errorNumber > 0) && (errorNumber < JSShellErr_Limit))
3268
+ return &jsShell_ErrorFormatString[errorNumber];
3269
+ return NULL;
3270
+ }
3271
+
3272
+ static void
3273
+ my_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
3274
+ {
3275
+ int i, j, k, n;
3276
+ char *prefix, *tmp;
3277
+ const char *ctmp;
3278
+
3279
+ if (!report) {
3280
+ fprintf(gErrFile, "%s\n", message);
3281
+ return;
3282
+ }
3283
+
3284
+ /* Conditionally ignore reported warnings. */
3285
+ if (JSREPORT_IS_WARNING(report->flags) && !reportWarnings)
3286
+ return;
3287
+
3288
+ prefix = NULL;
3289
+ if (report->filename)
3290
+ prefix = JS_smprintf("%s:", report->filename);
3291
+ if (report->lineno) {
3292
+ tmp = prefix;
3293
+ prefix = JS_smprintf("%s%u: ", tmp ? tmp : "", report->lineno);
3294
+ JS_free(cx, tmp);
3295
+ }
3296
+ if (JSREPORT_IS_WARNING(report->flags)) {
3297
+ tmp = prefix;
3298
+ prefix = JS_smprintf("%s%swarning: ",
3299
+ tmp ? tmp : "",
3300
+ JSREPORT_IS_STRICT(report->flags) ? "strict " : "");
3301
+ JS_free(cx, tmp);
3302
+ }
3303
+
3304
+ /* embedded newlines -- argh! */
3305
+ while ((ctmp = strchr(message, '\n')) != 0) {
3306
+ ctmp++;
3307
+ if (prefix)
3308
+ fputs(prefix, gErrFile);
3309
+ fwrite(message, 1, ctmp - message, gErrFile);
3310
+ message = ctmp;
3311
+ }
3312
+
3313
+ /* If there were no filename or lineno, the prefix might be empty */
3314
+ if (prefix)
3315
+ fputs(prefix, gErrFile);
3316
+ fputs(message, gErrFile);
3317
+
3318
+ if (!report->linebuf) {
3319
+ fputc('\n', gErrFile);
3320
+ goto out;
3321
+ }
3322
+
3323
+ /* report->linebuf usually ends with a newline. */
3324
+ n = strlen(report->linebuf);
3325
+ fprintf(gErrFile, ":\n%s%s%s%s",
3326
+ prefix,
3327
+ report->linebuf,
3328
+ (n > 0 && report->linebuf[n-1] == '\n') ? "" : "\n",
3329
+ prefix);
3330
+ n = PTRDIFF(report->tokenptr, report->linebuf, char);
3331
+ for (i = j = 0; i < n; i++) {
3332
+ if (report->linebuf[i] == '\t') {
3333
+ for (k = (j + 8) & ~7; j < k; j++) {
3334
+ fputc('.', gErrFile);
3335
+ }
3336
+ continue;
3337
+ }
3338
+ fputc('.', gErrFile);
3339
+ j++;
3340
+ }
3341
+ fputs("^\n", gErrFile);
3342
+ out:
3343
+ if (!JSREPORT_IS_WARNING(report->flags)) {
3344
+ if (report->errorNumber == JSMSG_OUT_OF_MEMORY) {
3345
+ gExitCode = EXITCODE_OUT_OF_MEMORY;
3346
+ } else {
3347
+ gExitCode = EXITCODE_RUNTIME_ERROR;
3348
+ }
3349
+ }
3350
+ JS_free(cx, prefix);
3351
+ }
3352
+
3353
+ #if defined(SHELL_HACK) && defined(DEBUG) && defined(XP_UNIX)
3354
+ static JSBool
3355
+ Exec(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
3356
+ {
3357
+ JSFunction *fun;
3358
+ const char *name, **nargv;
3359
+ uintN i, nargc;
3360
+ JSString *str;
3361
+ pid_t pid;
3362
+ int status;
3363
+
3364
+ fun = JS_ValueToFunction(cx, argv[-2]);
3365
+ if (!fun)
3366
+ return JS_FALSE;
3367
+ if (!fun->atom)
3368
+ return JS_TRUE;
3369
+ name = JS_GetStringBytes(ATOM_TO_STRING(fun->atom));
3370
+ nargc = 1 + argc;
3371
+ nargv = JS_malloc(cx, (nargc + 1) * sizeof(char *));
3372
+ if (!nargv)
3373
+ return JS_FALSE;
3374
+ nargv[0] = name;
3375
+ for (i = 1; i < nargc; i++) {
3376
+ str = JS_ValueToString(cx, argv[i-1]);
3377
+ if (!str) {
3378
+ JS_free(cx, nargv);
3379
+ return JS_FALSE;
3380
+ }
3381
+ nargv[i] = JS_GetStringBytes(str);
3382
+ }
3383
+ nargv[nargc] = 0;
3384
+ pid = fork();
3385
+ switch (pid) {
3386
+ case -1:
3387
+ perror("js");
3388
+ break;
3389
+ case 0:
3390
+ (void) execvp(name, (char **)nargv);
3391
+ perror("js");
3392
+ exit(127);
3393
+ default:
3394
+ while (waitpid(pid, &status, 0) < 0 && errno == EINTR)
3395
+ continue;
3396
+ break;
3397
+ }
3398
+ JS_free(cx, nargv);
3399
+ return JS_TRUE;
3400
+ }
3401
+ #endif
3402
+
3403
+ static JSBool
3404
+ global_enumerate(JSContext *cx, JSObject *obj)
3405
+ {
3406
+ #ifdef LAZY_STANDARD_CLASSES
3407
+ return JS_EnumerateStandardClasses(cx, obj);
3408
+ #else
3409
+ return JS_TRUE;
3410
+ #endif
3411
+ }
3412
+
3413
+ static JSBool
3414
+ global_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
3415
+ JSObject **objp)
3416
+ {
3417
+ #ifdef LAZY_STANDARD_CLASSES
3418
+ if ((flags & JSRESOLVE_ASSIGNING) == 0) {
3419
+ JSBool resolved;
3420
+
3421
+ if (!JS_ResolveStandardClass(cx, obj, id, &resolved))
3422
+ return JS_FALSE;
3423
+ if (resolved) {
3424
+ *objp = obj;
3425
+ return JS_TRUE;
3426
+ }
3427
+ }
3428
+ #endif
3429
+
3430
+ #if defined(SHELL_HACK) && defined(DEBUG) && defined(XP_UNIX)
3431
+ if ((flags & (JSRESOLVE_QUALIFIED | JSRESOLVE_ASSIGNING)) == 0) {
3432
+ /*
3433
+ * Do this expensive hack only for unoptimized Unix builds, which are
3434
+ * not used for benchmarking.
3435
+ */
3436
+ char *path, *comp, *full;
3437
+ const char *name;
3438
+ JSBool ok, found;
3439
+ JSFunction *fun;
3440
+
3441
+ if (!JSVAL_IS_STRING(id))
3442
+ return JS_TRUE;
3443
+ path = getenv("PATH");
3444
+ if (!path)
3445
+ return JS_TRUE;
3446
+ path = JS_strdup(cx, path);
3447
+ if (!path)
3448
+ return JS_FALSE;
3449
+ name = JS_GetStringBytes(JSVAL_TO_STRING(id));
3450
+ ok = JS_TRUE;
3451
+ for (comp = strtok(path, ":"); comp; comp = strtok(NULL, ":")) {
3452
+ if (*comp != '\0') {
3453
+ full = JS_smprintf("%s/%s", comp, name);
3454
+ if (!full) {
3455
+ JS_ReportOutOfMemory(cx);
3456
+ ok = JS_FALSE;
3457
+ break;
3458
+ }
3459
+ } else {
3460
+ full = (char *)name;
3461
+ }
3462
+ found = (access(full, X_OK) == 0);
3463
+ if (*comp != '\0')
3464
+ free(full);
3465
+ if (found) {
3466
+ fun = JS_DefineFunction(cx, obj, name, Exec, 0,
3467
+ JSPROP_ENUMERATE);
3468
+ ok = (fun != NULL);
3469
+ if (ok)
3470
+ *objp = obj;
3471
+ break;
3472
+ }
3473
+ }
3474
+ JS_free(cx, path);
3475
+ return ok;
3476
+ }
3477
+ #else
3478
+ return JS_TRUE;
3479
+ #endif
3480
+ }
3481
+
3482
+ JSClass global_class = {
3483
+ "global", JSCLASS_NEW_RESOLVE | JSCLASS_GLOBAL_FLAGS,
3484
+ JS_PropertyStub, JS_PropertyStub,
3485
+ JS_PropertyStub, JS_PropertyStub,
3486
+ global_enumerate, (JSResolveOp) global_resolve,
3487
+ JS_ConvertStub, JS_FinalizeStub,
3488
+ JSCLASS_NO_OPTIONAL_MEMBERS
3489
+ };
3490
+
3491
+ static JSBool
3492
+ env_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
3493
+ {
3494
+ /* XXX porting may be easy, but these don't seem to supply setenv by default */
3495
+ #if !defined XP_BEOS && !defined XP_OS2 && !defined SOLARIS
3496
+ JSString *idstr, *valstr;
3497
+ const char *name, *value;
3498
+ int rv;
3499
+
3500
+ idstr = JS_ValueToString(cx, id);
3501
+ valstr = JS_ValueToString(cx, *vp);
3502
+ if (!idstr || !valstr)
3503
+ return JS_FALSE;
3504
+ name = JS_GetStringBytes(idstr);
3505
+ value = JS_GetStringBytes(valstr);
3506
+ #if defined XP_WIN || defined HPUX || defined OSF1 || defined IRIX
3507
+ {
3508
+ char *waste = JS_smprintf("%s=%s", name, value);
3509
+ if (!waste) {
3510
+ JS_ReportOutOfMemory(cx);
3511
+ return JS_FALSE;
3512
+ }
3513
+ rv = putenv(waste);
3514
+ #ifdef XP_WIN
3515
+ /*
3516
+ * HPUX9 at least still has the bad old non-copying putenv.
3517
+ *
3518
+ * Per mail from <s.shanmuganathan@digital.com>, OSF1 also has a putenv
3519
+ * that will crash if you pass it an auto char array (so it must place
3520
+ * its argument directly in the char *environ[] array).
3521
+ */
3522
+ free(waste);
3523
+ #endif
3524
+ }
3525
+ #else
3526
+ rv = setenv(name, value, 1);
3527
+ #endif
3528
+ if (rv < 0) {
3529
+ JS_ReportError(cx, "can't set envariable %s to %s", name, value);
3530
+ return JS_FALSE;
3531
+ }
3532
+ *vp = STRING_TO_JSVAL(valstr);
3533
+ #endif /* !defined XP_BEOS && !defined XP_OS2 && !defined SOLARIS */
3534
+ return JS_TRUE;
3535
+ }
3536
+
3537
+ static JSBool
3538
+ env_enumerate(JSContext *cx, JSObject *obj)
3539
+ {
3540
+ static JSBool reflected;
3541
+ char **evp, *name, *value;
3542
+ JSString *valstr;
3543
+ JSBool ok;
3544
+
3545
+ if (reflected)
3546
+ return JS_TRUE;
3547
+
3548
+ for (evp = (char **)JS_GetPrivate(cx, obj); (name = *evp) != NULL; evp++) {
3549
+ value = strchr(name, '=');
3550
+ if (!value)
3551
+ continue;
3552
+ *value++ = '\0';
3553
+ valstr = JS_NewStringCopyZ(cx, value);
3554
+ if (!valstr) {
3555
+ ok = JS_FALSE;
3556
+ } else {
3557
+ ok = JS_DefineProperty(cx, obj, name, STRING_TO_JSVAL(valstr),
3558
+ NULL, NULL, JSPROP_ENUMERATE);
3559
+ }
3560
+ value[-1] = '=';
3561
+ if (!ok)
3562
+ return JS_FALSE;
3563
+ }
3564
+
3565
+ reflected = JS_TRUE;
3566
+ return JS_TRUE;
3567
+ }
3568
+
3569
+ static JSBool
3570
+ env_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
3571
+ JSObject **objp)
3572
+ {
3573
+ JSString *idstr, *valstr;
3574
+ const char *name, *value;
3575
+
3576
+ if (flags & JSRESOLVE_ASSIGNING)
3577
+ return JS_TRUE;
3578
+
3579
+ idstr = JS_ValueToString(cx, id);
3580
+ if (!idstr)
3581
+ return JS_FALSE;
3582
+ name = JS_GetStringBytes(idstr);
3583
+ value = getenv(name);
3584
+ if (value) {
3585
+ valstr = JS_NewStringCopyZ(cx, value);
3586
+ if (!valstr)
3587
+ return JS_FALSE;
3588
+ if (!JS_DefineProperty(cx, obj, name, STRING_TO_JSVAL(valstr),
3589
+ NULL, NULL, JSPROP_ENUMERATE)) {
3590
+ return JS_FALSE;
3591
+ }
3592
+ *objp = obj;
3593
+ }
3594
+ return JS_TRUE;
3595
+ }
3596
+
3597
+ static JSClass env_class = {
3598
+ "environment", JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE,
3599
+ JS_PropertyStub, JS_PropertyStub,
3600
+ JS_PropertyStub, env_setProperty,
3601
+ env_enumerate, (JSResolveOp) env_resolve,
3602
+ JS_ConvertStub, JS_FinalizeStub,
3603
+ JSCLASS_NO_OPTIONAL_MEMBERS
3604
+ };
3605
+
3606
+ #ifdef NARCISSUS
3607
+
3608
+ static JSBool
3609
+ defineProperty(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
3610
+ jsval *rval)
3611
+ {
3612
+ JSString *str;
3613
+ jsval value;
3614
+ JSBool dontDelete, readOnly, dontEnum;
3615
+ const jschar *chars;
3616
+ size_t length;
3617
+ uintN attrs;
3618
+
3619
+ dontDelete = readOnly = dontEnum = JS_FALSE;
3620
+ if (!JS_ConvertArguments(cx, argc, argv, "Sv/bbb",
3621
+ &str, &value, &dontDelete, &readOnly, &dontEnum)) {
3622
+ return JS_FALSE;
3623
+ }
3624
+ chars = JS_GetStringChars(str);
3625
+ length = JS_GetStringLength(str);
3626
+ attrs = dontEnum ? 0 : JSPROP_ENUMERATE;
3627
+ if (dontDelete)
3628
+ attrs |= JSPROP_PERMANENT;
3629
+ if (readOnly)
3630
+ attrs |= JSPROP_READONLY;
3631
+ return JS_DefineUCProperty(cx, obj, chars, length, value, NULL, NULL,
3632
+ attrs);
3633
+ }
3634
+
3635
+ static JSBool
3636
+ Evaluate(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
3637
+ {
3638
+ /* function evaluate(source, filename, lineno) { ... } */
3639
+ JSString *source;
3640
+ const char *filename = "";
3641
+ jsuint lineno = 0;
3642
+ uint32 oldopts;
3643
+ JSBool ok;
3644
+
3645
+ if (argc == 0) {
3646
+ *rval = JSVAL_VOID;
3647
+ return JS_TRUE;
3648
+ }
3649
+
3650
+ if (!JS_ConvertArguments(cx, argc, argv, "S/su",
3651
+ &source, &filename, &lineno)) {
3652
+ return JS_FALSE;
3653
+ }
3654
+
3655
+ oldopts = JS_GetOptions(cx);
3656
+ JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO);
3657
+ ok = JS_EvaluateUCScript(cx, obj, JS_GetStringChars(source),
3658
+ JS_GetStringLength(source), filename,
3659
+ lineno, rval);
3660
+ JS_SetOptions(cx, oldopts);
3661
+
3662
+ return ok;
3663
+ }
3664
+
3665
+ #include <fcntl.h>
3666
+ #include <sys/stat.h>
3667
+
3668
+ /*
3669
+ * Returns a JS_malloc'd string (that the caller needs to JS_free)
3670
+ * containing the directory (non-leaf) part of |from| prepended to |leaf|.
3671
+ * If |from| is empty or a leaf, MakeAbsolutePathname returns a copy of leaf.
3672
+ * Returns NULL to indicate an error.
3673
+ */
3674
+ static char *
3675
+ MakeAbsolutePathname(JSContext *cx, const char *from, const char *leaf)
3676
+ {
3677
+ size_t dirlen;
3678
+ char *dir;
3679
+ const char *slash = NULL, *cp;
3680
+
3681
+ cp = from;
3682
+ while (*cp) {
3683
+ if (*cp == '/'
3684
+ #ifdef XP_WIN
3685
+ || *cp == '\\'
3686
+ #endif
3687
+ ) {
3688
+ slash = cp;
3689
+ }
3690
+
3691
+ ++cp;
3692
+ }
3693
+
3694
+ if (!slash) {
3695
+ /* We were given a leaf or |from| was empty. */
3696
+ return JS_strdup(cx, leaf);
3697
+ }
3698
+
3699
+ /* Else, we were given a real pathname, return that + the leaf. */
3700
+ dirlen = slash - from + 1;
3701
+ dir = JS_malloc(cx, dirlen + strlen(leaf) + 1);
3702
+ if (!dir)
3703
+ return NULL;
3704
+
3705
+ strncpy(dir, from, dirlen);
3706
+ strcpy(dir + dirlen, leaf); /* Note: we can't use strcat here. */
3707
+
3708
+ return dir;
3709
+ }
3710
+
3711
+ static JSBool
3712
+ snarf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
3713
+ {
3714
+ JSString *str;
3715
+ const char *filename;
3716
+ char *pathname;
3717
+ JSStackFrame *fp;
3718
+ JSBool ok;
3719
+ off_t cc, len;
3720
+ char *buf;
3721
+ FILE *file;
3722
+
3723
+ str = JS_ValueToString(cx, argv[0]);
3724
+ if (!str)
3725
+ return JS_FALSE;
3726
+ filename = JS_GetStringBytes(str);
3727
+
3728
+ /* Get the currently executing script's name. */
3729
+ fp = JS_GetScriptedCaller(cx, NULL);
3730
+ JS_ASSERT(fp && fp->script->filename);
3731
+ pathname = MakeAbsolutePathname(cx, fp->script->filename, filename);
3732
+ if (!pathname)
3733
+ return JS_FALSE;
3734
+
3735
+ ok = JS_FALSE;
3736
+ len = 0;
3737
+ buf = NULL;
3738
+ file = fopen(pathname, "rb");
3739
+ if (!file) {
3740
+ JS_ReportError(cx, "can't open %s: %s", pathname, strerror(errno));
3741
+ } else {
3742
+ if (fseek(file, 0, SEEK_END) == EOF) {
3743
+ JS_ReportError(cx, "can't seek end of %s", pathname);
3744
+ } else {
3745
+ len = ftell(file);
3746
+ if (len == -1 || fseek(file, 0, SEEK_SET) == EOF) {
3747
+ JS_ReportError(cx, "can't seek start of %s", pathname);
3748
+ } else {
3749
+ buf = JS_malloc(cx, len + 1);
3750
+ if (buf) {
3751
+ cc = fread(buf, 1, len, file);
3752
+ if (cc != len) {
3753
+ JS_free(cx, buf);
3754
+ JS_ReportError(cx, "can't read %s: %s", pathname,
3755
+ (cc < 0) ? strerror(errno)
3756
+ : "short read");
3757
+ } else {
3758
+ len = (size_t)cc;
3759
+ ok = JS_TRUE;
3760
+ }
3761
+ }
3762
+ }
3763
+ }
3764
+ fclose(file);
3765
+ }
3766
+ JS_free(cx, pathname);
3767
+ if (!ok) {
3768
+ JS_free(cx, buf);
3769
+ return ok;
3770
+ }
3771
+
3772
+ buf[len] = '\0';
3773
+ str = JS_NewString(cx, buf, len);
3774
+ if (!str) {
3775
+ JS_free(cx, buf);
3776
+ return JS_FALSE;
3777
+ }
3778
+ *rval = STRING_TO_JSVAL(str);
3779
+ return JS_TRUE;
3780
+ }
3781
+
3782
+ #endif /* NARCISSUS */
3783
+
3784
+ static JSBool
3785
+ ContextCallback(JSContext *cx, uintN contextOp)
3786
+ {
3787
+ if (contextOp == JSCONTEXT_NEW) {
3788
+ JS_SetErrorReporter(cx, my_ErrorReporter);
3789
+ JS_SetVersion(cx, JSVERSION_LATEST);
3790
+ SetContextOptions(cx);
3791
+ }
3792
+ return JS_TRUE;
3793
+ }
3794
+
3795
+ int
3796
+ main(int argc, char **argv, char **envp)
3797
+ {
3798
+ int stackDummy;
3799
+ JSRuntime *rt;
3800
+ JSContext *cx;
3801
+ JSObject *glob, *it, *envobj;
3802
+ int result;
3803
+ #ifdef LIVECONNECT
3804
+ JavaVM *java_vm = NULL;
3805
+ #endif
3806
+ #ifdef JSDEBUGGER
3807
+ JSDContext *jsdc;
3808
+ #ifdef JSDEBUGGER_JAVA_UI
3809
+ JNIEnv *java_env;
3810
+ JSDJContext *jsdjc;
3811
+ #endif
3812
+ #ifdef JSDEBUGGER_C_UI
3813
+ JSBool jsdbc;
3814
+ #endif /* JSDEBUGGER_C_UI */
3815
+ #endif /* JSDEBUGGER */
3816
+
3817
+ CheckHelpMessages();
3818
+ setlocale(LC_ALL, "");
3819
+
3820
+ gStackBase = (jsuword)&stackDummy;
3821
+
3822
+ #ifdef XP_OS2
3823
+ /* these streams are normally line buffered on OS/2 and need a \n, *
3824
+ * so we need to unbuffer then to get a reasonable prompt */
3825
+ setbuf(stdout,0);
3826
+ setbuf(stderr,0);
3827
+ #endif
3828
+
3829
+ gErrFile = stderr;
3830
+ gOutFile = stdout;
3831
+
3832
+ argc--;
3833
+ argv++;
3834
+
3835
+ rt = JS_NewRuntime(64L * 1024L * 1024L);
3836
+ if (!rt)
3837
+ return 1;
3838
+ JS_SetContextCallback(rt, ContextCallback);
3839
+
3840
+ cx = JS_NewContext(rt, gStackChunkSize);
3841
+ if (!cx)
3842
+ return 1;
3843
+
3844
+ #ifdef JS_THREADSAFE
3845
+ JS_BeginRequest(cx);
3846
+ #endif
3847
+
3848
+ glob = JS_NewObject(cx, &global_class, NULL, NULL);
3849
+ if (!glob)
3850
+ return 1;
3851
+ #ifdef LAZY_STANDARD_CLASSES
3852
+ JS_SetGlobalObject(cx, glob);
3853
+ #else
3854
+ if (!JS_InitStandardClasses(cx, glob))
3855
+ return 1;
3856
+ #endif
3857
+ if (!JS_DefineFunctions(cx, glob, shell_functions))
3858
+ return 1;
3859
+
3860
+ it = JS_DefineObject(cx, glob, "it", &its_class, NULL, 0);
3861
+ if (!it)
3862
+ return 1;
3863
+ if (!JS_DefineProperties(cx, it, its_props))
3864
+ return 1;
3865
+ if (!JS_DefineFunctions(cx, it, its_methods))
3866
+ return 1;
3867
+
3868
+ #ifdef JSDEBUGGER
3869
+ /*
3870
+ * XXX A command line option to enable debugging (or not) would be good
3871
+ */
3872
+ jsdc = JSD_DebuggerOnForUser(rt, NULL, NULL);
3873
+ if (!jsdc)
3874
+ return 1;
3875
+ JSD_JSContextInUse(jsdc, cx);
3876
+ #ifdef JSD_LOWLEVEL_SOURCE
3877
+ JS_SetSourceHandler(rt, SendSourceToJSDebugger, jsdc);
3878
+ #endif /* JSD_LOWLEVEL_SOURCE */
3879
+ #ifdef JSDEBUGGER_JAVA_UI
3880
+ jsdjc = JSDJ_CreateContext();
3881
+ if (! jsdjc)
3882
+ return 1;
3883
+ JSDJ_SetJSDContext(jsdjc, jsdc);
3884
+ java_env = JSDJ_CreateJavaVMAndStartDebugger(jsdjc);
3885
+ #ifdef LIVECONNECT
3886
+ if (java_env)
3887
+ (*java_env)->GetJavaVM(java_env, &java_vm);
3888
+ #endif
3889
+ /*
3890
+ * XXX This would be the place to wait for the debugger to start.
3891
+ * Waiting would be nice in general, but especially when a js file
3892
+ * is passed on the cmd line.
3893
+ */
3894
+ #endif /* JSDEBUGGER_JAVA_UI */
3895
+ #ifdef JSDEBUGGER_C_UI
3896
+ jsdbc = JSDB_InitDebugger(rt, jsdc, 0);
3897
+ #endif /* JSDEBUGGER_C_UI */
3898
+ #endif /* JSDEBUGGER */
3899
+
3900
+ #ifdef LIVECONNECT
3901
+ if (!JSJ_SimpleInit(cx, glob, java_vm, getenv("CLASSPATH")))
3902
+ return 1;
3903
+ #endif
3904
+
3905
+ envobj = JS_DefineObject(cx, glob, "environment", &env_class, NULL, 0);
3906
+ if (!envobj || !JS_SetPrivate(cx, envobj, envp))
3907
+ return 1;
3908
+
3909
+ #ifdef NARCISSUS
3910
+ {
3911
+ jsval v;
3912
+ static const char Object_prototype[] = "Object.prototype";
3913
+
3914
+ if (!JS_DefineFunction(cx, glob, "snarf", snarf, 1, 0))
3915
+ return 1;
3916
+ if (!JS_DefineFunction(cx, glob, "evaluate", Evaluate, 3, 0))
3917
+ return 1;
3918
+
3919
+ if (!JS_EvaluateScript(cx, glob,
3920
+ Object_prototype, sizeof Object_prototype - 1,
3921
+ NULL, 0, &v)) {
3922
+ return 1;
3923
+ }
3924
+ if (!JS_DefineFunction(cx, JSVAL_TO_OBJECT(v), "__defineProperty__",
3925
+ defineProperty, 5, 0)) {
3926
+ return 1;
3927
+ }
3928
+ }
3929
+ #endif
3930
+
3931
+ result = ProcessArgs(cx, glob, argv, argc);
3932
+
3933
+ #ifdef JSDEBUGGER
3934
+ if (jsdc) {
3935
+ #ifdef JSDEBUGGER_C_UI
3936
+ if (jsdbc)
3937
+ JSDB_TermDebugger(jsdc);
3938
+ #endif /* JSDEBUGGER_C_UI */
3939
+ JSD_DebuggerOff(jsdc);
3940
+ }
3941
+ #endif /* JSDEBUGGER */
3942
+
3943
+ #ifdef JS_THREADSAFE
3944
+ JS_EndRequest(cx);
3945
+ #endif
3946
+
3947
+ JS_DestroyContext(cx);
3948
+ JS_DestroyRuntime(rt);
3949
+ JS_ShutDown();
3950
+ return result;
3951
+ }