johnson 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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
+ }