johnson 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (371) hide show
  1. data/.autotest +14 -0
  2. data/CHANGELOG.rdoc +11 -0
  3. data/Manifest.txt +370 -0
  4. data/README.rdoc +60 -0
  5. data/Rakefile +42 -0
  6. data/bin/johnson +108 -0
  7. data/docs/MINGW32.mk +124 -0
  8. data/docs/cross-compile.txt +38 -0
  9. data/ext/spidermonkey/context.c +115 -0
  10. data/ext/spidermonkey/context.h +19 -0
  11. data/ext/spidermonkey/conversions.c +320 -0
  12. data/ext/spidermonkey/conversions.h +18 -0
  13. data/ext/spidermonkey/debugger.c +226 -0
  14. data/ext/spidermonkey/debugger.h +9 -0
  15. data/ext/spidermonkey/extconf.rb +30 -0
  16. data/ext/spidermonkey/extensions.c +37 -0
  17. data/ext/spidermonkey/extensions.h +12 -0
  18. data/ext/spidermonkey/global.c +40 -0
  19. data/ext/spidermonkey/global.h +11 -0
  20. data/ext/spidermonkey/idhash.c +16 -0
  21. data/ext/spidermonkey/idhash.h +8 -0
  22. data/ext/spidermonkey/immutable_node.c +1153 -0
  23. data/ext/spidermonkey/immutable_node.c.erb +523 -0
  24. data/ext/spidermonkey/immutable_node.h +22 -0
  25. data/ext/spidermonkey/jroot.h +187 -0
  26. data/ext/spidermonkey/js_land_proxy.c +610 -0
  27. data/ext/spidermonkey/js_land_proxy.h +20 -0
  28. data/ext/spidermonkey/ruby_land_proxy.c +543 -0
  29. data/ext/spidermonkey/ruby_land_proxy.h +17 -0
  30. data/ext/spidermonkey/runtime.c +330 -0
  31. data/ext/spidermonkey/runtime.h +25 -0
  32. data/ext/spidermonkey/spidermonkey.c +20 -0
  33. data/ext/spidermonkey/spidermonkey.h +29 -0
  34. data/johnson.gemspec +44 -0
  35. data/js/johnson/cli.js +30 -0
  36. data/js/johnson/prelude.js +80 -0
  37. data/lib/johnson.rb +55 -0
  38. data/lib/johnson/cli.rb +7 -0
  39. data/lib/johnson/cli/options.rb +67 -0
  40. data/lib/johnson/error.rb +4 -0
  41. data/lib/johnson/nodes.rb +7 -0
  42. data/lib/johnson/nodes/binary_node.rb +65 -0
  43. data/lib/johnson/nodes/for.rb +14 -0
  44. data/lib/johnson/nodes/for_in.rb +12 -0
  45. data/lib/johnson/nodes/function.rb +13 -0
  46. data/lib/johnson/nodes/list.rb +28 -0
  47. data/lib/johnson/nodes/node.rb +68 -0
  48. data/lib/johnson/nodes/ternary_node.rb +20 -0
  49. data/lib/johnson/parser.rb +21 -0
  50. data/lib/johnson/parser/syntax_error.rb +13 -0
  51. data/lib/johnson/runtime.rb +63 -0
  52. data/lib/johnson/spidermonkey/context.rb +10 -0
  53. data/lib/johnson/spidermonkey/debugger.rb +67 -0
  54. data/lib/johnson/spidermonkey/immutable_node.rb +282 -0
  55. data/lib/johnson/spidermonkey/js_land_proxy.rb +62 -0
  56. data/lib/johnson/spidermonkey/mutable_tree_visitor.rb +242 -0
  57. data/lib/johnson/spidermonkey/ruby_land_proxy.rb +54 -0
  58. data/lib/johnson/spidermonkey/runtime.rb +103 -0
  59. data/lib/johnson/version.rb +3 -0
  60. data/lib/johnson/visitable.rb +16 -0
  61. data/lib/johnson/visitors.rb +5 -0
  62. data/lib/johnson/visitors/dot_visitor.rb +169 -0
  63. data/lib/johnson/visitors/ecma_visitor.rb +323 -0
  64. data/lib/johnson/visitors/enumerating_visitor.rb +15 -0
  65. data/lib/johnson/visitors/sexp_visitor.rb +174 -0
  66. data/lib/johnson/visitors/visitor.rb +91 -0
  67. data/lib/rails/init.rb +37 -0
  68. data/lib/tasks/gem.rake +9 -0
  69. data/lib/tasks/parsing.rake +37 -0
  70. data/lib/tasks/testing.rake +36 -0
  71. data/lib/tasks/vendor.rake +20 -0
  72. data/test/helper.rb +55 -0
  73. data/test/johnson/browser_test.rb +43 -0
  74. data/test/johnson/conversions/array_test.rb +32 -0
  75. data/test/johnson/conversions/boolean_test.rb +17 -0
  76. data/test/johnson/conversions/callable_test.rb +34 -0
  77. data/test/johnson/conversions/file_test.rb +15 -0
  78. data/test/johnson/conversions/nil_test.rb +20 -0
  79. data/test/johnson/conversions/number_test.rb +34 -0
  80. data/test/johnson/conversions/regexp_test.rb +24 -0
  81. data/test/johnson/conversions/string_test.rb +26 -0
  82. data/test/johnson/conversions/struct_test.rb +15 -0
  83. data/test/johnson/conversions/symbol_test.rb +19 -0
  84. data/test/johnson/conversions/thread_test.rb +24 -0
  85. data/test/johnson/error_test.rb +9 -0
  86. data/test/johnson/extensions_test.rb +56 -0
  87. data/test/johnson/nodes/array_literal_test.rb +57 -0
  88. data/test/johnson/nodes/array_node_test.rb +26 -0
  89. data/test/johnson/nodes/binary_node_test.rb +61 -0
  90. data/test/johnson/nodes/bracket_access_test.rb +16 -0
  91. data/test/johnson/nodes/delete_test.rb +11 -0
  92. data/test/johnson/nodes/do_while_test.rb +12 -0
  93. data/test/johnson/nodes/dot_accessor_test.rb +15 -0
  94. data/test/johnson/nodes/export_test.rb +9 -0
  95. data/test/johnson/nodes/for_test.rb +54 -0
  96. data/test/johnson/nodes/function_test.rb +71 -0
  97. data/test/johnson/nodes/if_test.rb +41 -0
  98. data/test/johnson/nodes/import_test.rb +13 -0
  99. data/test/johnson/nodes/label_test.rb +19 -0
  100. data/test/johnson/nodes/let_test.rb +31 -0
  101. data/test/johnson/nodes/object_literal_test.rb +110 -0
  102. data/test/johnson/nodes/return_test.rb +16 -0
  103. data/test/johnson/nodes/semi_test.rb +8 -0
  104. data/test/johnson/nodes/switch_test.rb +55 -0
  105. data/test/johnson/nodes/ternary_test.rb +25 -0
  106. data/test/johnson/nodes/throw_test.rb +9 -0
  107. data/test/johnson/nodes/try_node_test.rb +59 -0
  108. data/test/johnson/nodes/typeof_test.rb +11 -0
  109. data/test/johnson/nodes/unary_node_test.rb +23 -0
  110. data/test/johnson/nodes/void_test.rb +11 -0
  111. data/test/johnson/nodes/while_test.rb +26 -0
  112. data/test/johnson/nodes/with_test.rb +10 -0
  113. data/test/johnson/prelude_test.rb +56 -0
  114. data/test/johnson/runtime_test.rb +64 -0
  115. data/test/johnson/spidermonkey/context_test.rb +21 -0
  116. data/test/johnson/spidermonkey/immutable_node_test.rb +34 -0
  117. data/test/johnson/spidermonkey/js_land_proxy_test.rb +236 -0
  118. data/test/johnson/spidermonkey/ruby_land_proxy_test.rb +240 -0
  119. data/test/johnson/spidermonkey/runtime_test.rb +17 -0
  120. data/test/johnson/version_test.rb +13 -0
  121. data/test/johnson/visitors/dot_visitor_test.rb +39 -0
  122. data/test/johnson/visitors/enumerating_visitor_test.rb +12 -0
  123. data/test/johnson_test.rb +16 -0
  124. data/test/parser_test.rb +276 -0
  125. data/vendor/spidermonkey/.cvsignore +9 -0
  126. data/vendor/spidermonkey/Makefile.in +449 -0
  127. data/vendor/spidermonkey/Makefile.ref +365 -0
  128. data/vendor/spidermonkey/README.html +820 -0
  129. data/vendor/spidermonkey/SpiderMonkey.rsp +12 -0
  130. data/vendor/spidermonkey/Y.js +19 -0
  131. data/vendor/spidermonkey/build.mk +43 -0
  132. data/vendor/spidermonkey/config.mk +192 -0
  133. data/vendor/spidermonkey/config/AIX4.1.mk +65 -0
  134. data/vendor/spidermonkey/config/AIX4.2.mk +64 -0
  135. data/vendor/spidermonkey/config/AIX4.3.mk +65 -0
  136. data/vendor/spidermonkey/config/Darwin.mk +83 -0
  137. data/vendor/spidermonkey/config/Darwin1.3.mk +81 -0
  138. data/vendor/spidermonkey/config/Darwin1.4.mk +41 -0
  139. data/vendor/spidermonkey/config/Darwin5.2.mk +81 -0
  140. data/vendor/spidermonkey/config/Darwin5.3.mk +81 -0
  141. data/vendor/spidermonkey/config/HP-UXB.10.10.mk +77 -0
  142. data/vendor/spidermonkey/config/HP-UXB.10.20.mk +77 -0
  143. data/vendor/spidermonkey/config/HP-UXB.11.00.mk +80 -0
  144. data/vendor/spidermonkey/config/IRIX.mk +87 -0
  145. data/vendor/spidermonkey/config/IRIX5.3.mk +44 -0
  146. data/vendor/spidermonkey/config/IRIX6.1.mk +44 -0
  147. data/vendor/spidermonkey/config/IRIX6.2.mk +44 -0
  148. data/vendor/spidermonkey/config/IRIX6.3.mk +44 -0
  149. data/vendor/spidermonkey/config/IRIX6.5.mk +44 -0
  150. data/vendor/spidermonkey/config/Linux_All.mk +103 -0
  151. data/vendor/spidermonkey/config/Mac_OS10.0.mk +82 -0
  152. data/vendor/spidermonkey/config/OSF1V4.0.mk +72 -0
  153. data/vendor/spidermonkey/config/OSF1V5.0.mk +69 -0
  154. data/vendor/spidermonkey/config/SunOS4.1.4.mk +101 -0
  155. data/vendor/spidermonkey/config/SunOS5.10.mk +50 -0
  156. data/vendor/spidermonkey/config/SunOS5.3.mk +91 -0
  157. data/vendor/spidermonkey/config/SunOS5.4.mk +92 -0
  158. data/vendor/spidermonkey/config/SunOS5.5.1.mk +44 -0
  159. data/vendor/spidermonkey/config/SunOS5.5.mk +87 -0
  160. data/vendor/spidermonkey/config/SunOS5.6.mk +89 -0
  161. data/vendor/spidermonkey/config/SunOS5.7.mk +44 -0
  162. data/vendor/spidermonkey/config/SunOS5.8.mk +44 -0
  163. data/vendor/spidermonkey/config/SunOS5.9.mk +44 -0
  164. data/vendor/spidermonkey/config/WINNT4.0.mk +117 -0
  165. data/vendor/spidermonkey/config/WINNT5.0.mk +117 -0
  166. data/vendor/spidermonkey/config/WINNT5.1.mk +117 -0
  167. data/vendor/spidermonkey/config/WINNT5.2.mk +117 -0
  168. data/vendor/spidermonkey/config/WINNT6.0.mk +117 -0
  169. data/vendor/spidermonkey/config/dgux.mk +64 -0
  170. data/vendor/spidermonkey/editline/Makefile.ref +144 -0
  171. data/vendor/spidermonkey/editline/README +83 -0
  172. data/vendor/spidermonkey/editline/editline.3 +175 -0
  173. data/vendor/spidermonkey/editline/editline.c +1369 -0
  174. data/vendor/spidermonkey/editline/editline.h +135 -0
  175. data/vendor/spidermonkey/editline/sysunix.c +182 -0
  176. data/vendor/spidermonkey/editline/unix.h +82 -0
  177. data/vendor/spidermonkey/fdlibm/.cvsignore +7 -0
  178. data/vendor/spidermonkey/fdlibm/Makefile.in +127 -0
  179. data/vendor/spidermonkey/fdlibm/Makefile.ref +192 -0
  180. data/vendor/spidermonkey/fdlibm/e_acos.c +147 -0
  181. data/vendor/spidermonkey/fdlibm/e_acosh.c +105 -0
  182. data/vendor/spidermonkey/fdlibm/e_asin.c +156 -0
  183. data/vendor/spidermonkey/fdlibm/e_atan2.c +165 -0
  184. data/vendor/spidermonkey/fdlibm/e_atanh.c +110 -0
  185. data/vendor/spidermonkey/fdlibm/e_cosh.c +133 -0
  186. data/vendor/spidermonkey/fdlibm/e_exp.c +202 -0
  187. data/vendor/spidermonkey/fdlibm/e_fmod.c +184 -0
  188. data/vendor/spidermonkey/fdlibm/e_gamma.c +71 -0
  189. data/vendor/spidermonkey/fdlibm/e_gamma_r.c +70 -0
  190. data/vendor/spidermonkey/fdlibm/e_hypot.c +173 -0
  191. data/vendor/spidermonkey/fdlibm/e_j0.c +524 -0
  192. data/vendor/spidermonkey/fdlibm/e_j1.c +523 -0
  193. data/vendor/spidermonkey/fdlibm/e_jn.c +315 -0
  194. data/vendor/spidermonkey/fdlibm/e_lgamma.c +71 -0
  195. data/vendor/spidermonkey/fdlibm/e_lgamma_r.c +347 -0
  196. data/vendor/spidermonkey/fdlibm/e_log.c +184 -0
  197. data/vendor/spidermonkey/fdlibm/e_log10.c +134 -0
  198. data/vendor/spidermonkey/fdlibm/e_pow.c +386 -0
  199. data/vendor/spidermonkey/fdlibm/e_rem_pio2.c +222 -0
  200. data/vendor/spidermonkey/fdlibm/e_remainder.c +120 -0
  201. data/vendor/spidermonkey/fdlibm/e_scalb.c +89 -0
  202. data/vendor/spidermonkey/fdlibm/e_sinh.c +122 -0
  203. data/vendor/spidermonkey/fdlibm/e_sqrt.c +497 -0
  204. data/vendor/spidermonkey/fdlibm/fdlibm.h +273 -0
  205. data/vendor/spidermonkey/fdlibm/fdlibm.mak +1453 -0
  206. data/vendor/spidermonkey/fdlibm/fdlibm.mdp +0 -0
  207. data/vendor/spidermonkey/fdlibm/k_cos.c +135 -0
  208. data/vendor/spidermonkey/fdlibm/k_rem_pio2.c +354 -0
  209. data/vendor/spidermonkey/fdlibm/k_sin.c +114 -0
  210. data/vendor/spidermonkey/fdlibm/k_standard.c +785 -0
  211. data/vendor/spidermonkey/fdlibm/k_tan.c +170 -0
  212. data/vendor/spidermonkey/fdlibm/s_asinh.c +101 -0
  213. data/vendor/spidermonkey/fdlibm/s_atan.c +175 -0
  214. data/vendor/spidermonkey/fdlibm/s_cbrt.c +133 -0
  215. data/vendor/spidermonkey/fdlibm/s_ceil.c +120 -0
  216. data/vendor/spidermonkey/fdlibm/s_copysign.c +72 -0
  217. data/vendor/spidermonkey/fdlibm/s_cos.c +118 -0
  218. data/vendor/spidermonkey/fdlibm/s_erf.c +356 -0
  219. data/vendor/spidermonkey/fdlibm/s_expm1.c +267 -0
  220. data/vendor/spidermonkey/fdlibm/s_fabs.c +70 -0
  221. data/vendor/spidermonkey/fdlibm/s_finite.c +71 -0
  222. data/vendor/spidermonkey/fdlibm/s_floor.c +121 -0
  223. data/vendor/spidermonkey/fdlibm/s_frexp.c +99 -0
  224. data/vendor/spidermonkey/fdlibm/s_ilogb.c +85 -0
  225. data/vendor/spidermonkey/fdlibm/s_isnan.c +74 -0
  226. data/vendor/spidermonkey/fdlibm/s_ldexp.c +66 -0
  227. data/vendor/spidermonkey/fdlibm/s_lib_version.c +73 -0
  228. data/vendor/spidermonkey/fdlibm/s_log1p.c +211 -0
  229. data/vendor/spidermonkey/fdlibm/s_logb.c +79 -0
  230. data/vendor/spidermonkey/fdlibm/s_matherr.c +64 -0
  231. data/vendor/spidermonkey/fdlibm/s_modf.c +132 -0
  232. data/vendor/spidermonkey/fdlibm/s_nextafter.c +124 -0
  233. data/vendor/spidermonkey/fdlibm/s_rint.c +131 -0
  234. data/vendor/spidermonkey/fdlibm/s_scalbn.c +107 -0
  235. data/vendor/spidermonkey/fdlibm/s_signgam.c +40 -0
  236. data/vendor/spidermonkey/fdlibm/s_significand.c +68 -0
  237. data/vendor/spidermonkey/fdlibm/s_sin.c +118 -0
  238. data/vendor/spidermonkey/fdlibm/s_tan.c +112 -0
  239. data/vendor/spidermonkey/fdlibm/s_tanh.c +122 -0
  240. data/vendor/spidermonkey/fdlibm/w_acos.c +78 -0
  241. data/vendor/spidermonkey/fdlibm/w_acosh.c +78 -0
  242. data/vendor/spidermonkey/fdlibm/w_asin.c +80 -0
  243. data/vendor/spidermonkey/fdlibm/w_atan2.c +79 -0
  244. data/vendor/spidermonkey/fdlibm/w_atanh.c +81 -0
  245. data/vendor/spidermonkey/fdlibm/w_cosh.c +77 -0
  246. data/vendor/spidermonkey/fdlibm/w_exp.c +88 -0
  247. data/vendor/spidermonkey/fdlibm/w_fmod.c +78 -0
  248. data/vendor/spidermonkey/fdlibm/w_gamma.c +85 -0
  249. data/vendor/spidermonkey/fdlibm/w_gamma_r.c +81 -0
  250. data/vendor/spidermonkey/fdlibm/w_hypot.c +78 -0
  251. data/vendor/spidermonkey/fdlibm/w_j0.c +105 -0
  252. data/vendor/spidermonkey/fdlibm/w_j1.c +106 -0
  253. data/vendor/spidermonkey/fdlibm/w_jn.c +128 -0
  254. data/vendor/spidermonkey/fdlibm/w_lgamma.c +85 -0
  255. data/vendor/spidermonkey/fdlibm/w_lgamma_r.c +81 -0
  256. data/vendor/spidermonkey/fdlibm/w_log.c +78 -0
  257. data/vendor/spidermonkey/fdlibm/w_log10.c +81 -0
  258. data/vendor/spidermonkey/fdlibm/w_pow.c +99 -0
  259. data/vendor/spidermonkey/fdlibm/w_remainder.c +77 -0
  260. data/vendor/spidermonkey/fdlibm/w_scalb.c +95 -0
  261. data/vendor/spidermonkey/fdlibm/w_sinh.c +77 -0
  262. data/vendor/spidermonkey/fdlibm/w_sqrt.c +77 -0
  263. data/vendor/spidermonkey/javascript-trace.d +73 -0
  264. data/vendor/spidermonkey/js.c +3951 -0
  265. data/vendor/spidermonkey/js.mdp +0 -0
  266. data/vendor/spidermonkey/js.msg +308 -0
  267. data/vendor/spidermonkey/js3240.rc +79 -0
  268. data/vendor/spidermonkey/jsOS240.def +654 -0
  269. data/vendor/spidermonkey/jsapi.c +5836 -0
  270. data/vendor/spidermonkey/jsapi.h +2624 -0
  271. data/vendor/spidermonkey/jsarena.c +450 -0
  272. data/vendor/spidermonkey/jsarena.h +318 -0
  273. data/vendor/spidermonkey/jsarray.c +2996 -0
  274. data/vendor/spidermonkey/jsarray.h +127 -0
  275. data/vendor/spidermonkey/jsatom.c +1045 -0
  276. data/vendor/spidermonkey/jsatom.h +442 -0
  277. data/vendor/spidermonkey/jsbit.h +253 -0
  278. data/vendor/spidermonkey/jsbool.c +176 -0
  279. data/vendor/spidermonkey/jsbool.h +73 -0
  280. data/vendor/spidermonkey/jsclist.h +139 -0
  281. data/vendor/spidermonkey/jscntxt.c +1348 -0
  282. data/vendor/spidermonkey/jscntxt.h +1120 -0
  283. data/vendor/spidermonkey/jscompat.h +57 -0
  284. data/vendor/spidermonkey/jsconfig.h +248 -0
  285. data/vendor/spidermonkey/jsconfig.mk +181 -0
  286. data/vendor/spidermonkey/jscpucfg.c +396 -0
  287. data/vendor/spidermonkey/jscpucfg.h +212 -0
  288. data/vendor/spidermonkey/jsdate.c +2390 -0
  289. data/vendor/spidermonkey/jsdate.h +124 -0
  290. data/vendor/spidermonkey/jsdbgapi.c +1802 -0
  291. data/vendor/spidermonkey/jsdbgapi.h +464 -0
  292. data/vendor/spidermonkey/jsdhash.c +868 -0
  293. data/vendor/spidermonkey/jsdhash.h +592 -0
  294. data/vendor/spidermonkey/jsdtoa.c +3167 -0
  295. data/vendor/spidermonkey/jsdtoa.h +130 -0
  296. data/vendor/spidermonkey/jsdtracef.c +317 -0
  297. data/vendor/spidermonkey/jsdtracef.h +77 -0
  298. data/vendor/spidermonkey/jsemit.c +6909 -0
  299. data/vendor/spidermonkey/jsemit.h +741 -0
  300. data/vendor/spidermonkey/jsexn.c +1371 -0
  301. data/vendor/spidermonkey/jsexn.h +96 -0
  302. data/vendor/spidermonkey/jsfile.c +2736 -0
  303. data/vendor/spidermonkey/jsfile.h +56 -0
  304. data/vendor/spidermonkey/jsfile.msg +90 -0
  305. data/vendor/spidermonkey/jsfun.c +2634 -0
  306. data/vendor/spidermonkey/jsfun.h +254 -0
  307. data/vendor/spidermonkey/jsgc.c +3562 -0
  308. data/vendor/spidermonkey/jsgc.h +403 -0
  309. data/vendor/spidermonkey/jshash.c +476 -0
  310. data/vendor/spidermonkey/jshash.h +151 -0
  311. data/vendor/spidermonkey/jsify.pl +485 -0
  312. data/vendor/spidermonkey/jsinterp.c +7007 -0
  313. data/vendor/spidermonkey/jsinterp.h +525 -0
  314. data/vendor/spidermonkey/jsinvoke.c +43 -0
  315. data/vendor/spidermonkey/jsiter.c +1067 -0
  316. data/vendor/spidermonkey/jsiter.h +122 -0
  317. data/vendor/spidermonkey/jskeyword.tbl +124 -0
  318. data/vendor/spidermonkey/jskwgen.c +460 -0
  319. data/vendor/spidermonkey/jslibmath.h +266 -0
  320. data/vendor/spidermonkey/jslock.c +1309 -0
  321. data/vendor/spidermonkey/jslock.h +313 -0
  322. data/vendor/spidermonkey/jslocko.asm +60 -0
  323. data/vendor/spidermonkey/jslog2.c +94 -0
  324. data/vendor/spidermonkey/jslong.c +264 -0
  325. data/vendor/spidermonkey/jslong.h +412 -0
  326. data/vendor/spidermonkey/jsmath.c +567 -0
  327. data/vendor/spidermonkey/jsmath.h +57 -0
  328. data/vendor/spidermonkey/jsnum.c +1239 -0
  329. data/vendor/spidermonkey/jsnum.h +283 -0
  330. data/vendor/spidermonkey/jsobj.c +5282 -0
  331. data/vendor/spidermonkey/jsobj.h +709 -0
  332. data/vendor/spidermonkey/jsopcode.c +5245 -0
  333. data/vendor/spidermonkey/jsopcode.h +394 -0
  334. data/vendor/spidermonkey/jsopcode.tbl +523 -0
  335. data/vendor/spidermonkey/jsotypes.h +202 -0
  336. data/vendor/spidermonkey/jsparse.c +6704 -0
  337. data/vendor/spidermonkey/jsparse.h +511 -0
  338. data/vendor/spidermonkey/jsprf.c +1262 -0
  339. data/vendor/spidermonkey/jsprf.h +150 -0
  340. data/vendor/spidermonkey/jsproto.tbl +128 -0
  341. data/vendor/spidermonkey/jsprvtd.h +267 -0
  342. data/vendor/spidermonkey/jspubtd.h +744 -0
  343. data/vendor/spidermonkey/jsregexp.c +4364 -0
  344. data/vendor/spidermonkey/jsregexp.h +183 -0
  345. data/vendor/spidermonkey/jsreops.tbl +145 -0
  346. data/vendor/spidermonkey/jsscan.c +2012 -0
  347. data/vendor/spidermonkey/jsscan.h +387 -0
  348. data/vendor/spidermonkey/jsscope.c +1957 -0
  349. data/vendor/spidermonkey/jsscope.h +418 -0
  350. data/vendor/spidermonkey/jsscript.c +1832 -0
  351. data/vendor/spidermonkey/jsscript.h +287 -0
  352. data/vendor/spidermonkey/jsshell.msg +50 -0
  353. data/vendor/spidermonkey/jsstddef.h +83 -0
  354. data/vendor/spidermonkey/jsstr.c +5005 -0
  355. data/vendor/spidermonkey/jsstr.h +641 -0
  356. data/vendor/spidermonkey/jstypes.h +475 -0
  357. data/vendor/spidermonkey/jsutil.c +345 -0
  358. data/vendor/spidermonkey/jsutil.h +157 -0
  359. data/vendor/spidermonkey/jsxdrapi.c +800 -0
  360. data/vendor/spidermonkey/jsxdrapi.h +218 -0
  361. data/vendor/spidermonkey/jsxml.c +8476 -0
  362. data/vendor/spidermonkey/jsxml.h +349 -0
  363. data/vendor/spidermonkey/lock_SunOS.s +119 -0
  364. data/vendor/spidermonkey/perfect.js +39 -0
  365. data/vendor/spidermonkey/plify_jsdhash.sed +36 -0
  366. data/vendor/spidermonkey/prmjtime.c +846 -0
  367. data/vendor/spidermonkey/prmjtime.h +103 -0
  368. data/vendor/spidermonkey/resource.h +15 -0
  369. data/vendor/spidermonkey/rules.mk +197 -0
  370. data/vendor/spidermonkey/win32.order +384 -0
  371. metadata +513 -0
@@ -0,0 +1,176 @@
1
+ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2
+ *
3
+ * ***** BEGIN LICENSE BLOCK *****
4
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5
+ *
6
+ * The contents of this file are subject to the Mozilla Public License Version
7
+ * 1.1 (the "License"); you may not use this file except in compliance with
8
+ * the License. You may obtain a copy of the License at
9
+ * http://www.mozilla.org/MPL/
10
+ *
11
+ * Software distributed under the License is distributed on an "AS IS" basis,
12
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13
+ * for the specific language governing rights and limitations under the
14
+ * License.
15
+ *
16
+ * The Original Code is Mozilla Communicator client code, released
17
+ * March 31, 1998.
18
+ *
19
+ * The Initial Developer of the Original Code is
20
+ * Netscape Communications Corporation.
21
+ * Portions created by the Initial Developer are Copyright (C) 1998
22
+ * the Initial Developer. All Rights Reserved.
23
+ *
24
+ * Contributor(s):
25
+ *
26
+ * Alternatively, the contents of this file may be used under the terms of
27
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
28
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29
+ * in which case the provisions of the GPL or the LGPL are applicable instead
30
+ * of those above. If you wish to allow use of your version of this file only
31
+ * under the terms of either the GPL or the LGPL, and not to allow others to
32
+ * use your version of this file under the terms of the MPL, indicate your
33
+ * decision by deleting the provisions above and replace them with the notice
34
+ * and other provisions required by the GPL or the LGPL. If you do not delete
35
+ * the provisions above, a recipient may use your version of this file under
36
+ * the terms of any one of the MPL, the GPL or the LGPL.
37
+ *
38
+ * ***** END LICENSE BLOCK ***** */
39
+
40
+ /*
41
+ * JS boolean implementation.
42
+ */
43
+ #include "jsstddef.h"
44
+ #include "jstypes.h"
45
+ #include "jsutil.h" /* Added by JSIFY */
46
+ #include "jsapi.h"
47
+ #include "jsatom.h"
48
+ #include "jsbool.h"
49
+ #include "jscntxt.h"
50
+ #include "jsconfig.h"
51
+ #include "jsinterp.h"
52
+ #include "jslock.h"
53
+ #include "jsnum.h"
54
+ #include "jsobj.h"
55
+ #include "jsstr.h"
56
+
57
+ JSClass js_BooleanClass = {
58
+ "Boolean",
59
+ JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_Boolean),
60
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
61
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
62
+ JSCLASS_NO_OPTIONAL_MEMBERS
63
+ };
64
+
65
+ #if JS_HAS_TOSOURCE
66
+ #include "jsprf.h"
67
+
68
+ static JSBool
69
+ bool_toSource(JSContext *cx, uintN argc, jsval *vp)
70
+ {
71
+ jsval v;
72
+ char buf[32];
73
+ JSString *str;
74
+
75
+ if (!js_GetPrimitiveThis(cx, vp, &js_BooleanClass, &v))
76
+ return JS_FALSE;
77
+ JS_ASSERT(JSVAL_IS_BOOLEAN(v));
78
+ JS_snprintf(buf, sizeof buf, "(new %s(%s))",
79
+ js_BooleanClass.name,
80
+ JS_BOOLEAN_STR(JSVAL_TO_BOOLEAN(v)));
81
+ str = JS_NewStringCopyZ(cx, buf);
82
+ if (!str)
83
+ return JS_FALSE;
84
+ *vp = STRING_TO_JSVAL(str);
85
+ return JS_TRUE;
86
+ }
87
+ #endif
88
+
89
+ static JSBool
90
+ bool_toString(JSContext *cx, uintN argc, jsval *vp)
91
+ {
92
+ jsval v;
93
+ JSAtom *atom;
94
+ JSString *str;
95
+
96
+ if (!js_GetPrimitiveThis(cx, vp, &js_BooleanClass, &v))
97
+ return JS_FALSE;
98
+ JS_ASSERT(JSVAL_IS_BOOLEAN(v));
99
+ atom = cx->runtime->atomState.booleanAtoms[JSVAL_TO_BOOLEAN(v) ? 1 : 0];
100
+ str = ATOM_TO_STRING(atom);
101
+ if (!str)
102
+ return JS_FALSE;
103
+ *vp = STRING_TO_JSVAL(str);
104
+ return JS_TRUE;
105
+ }
106
+
107
+ static JSBool
108
+ bool_valueOf(JSContext *cx, uintN argc, jsval *vp)
109
+ {
110
+ return js_GetPrimitiveThis(cx, vp, &js_BooleanClass, vp);
111
+ }
112
+
113
+ static JSFunctionSpec boolean_methods[] = {
114
+ #if JS_HAS_TOSOURCE
115
+ JS_FN(js_toSource_str, bool_toSource, 0, 0, JSFUN_THISP_BOOLEAN),
116
+ #endif
117
+ JS_FN(js_toString_str, bool_toString, 0, 0, JSFUN_THISP_BOOLEAN),
118
+ JS_FN(js_valueOf_str, bool_valueOf, 0, 0, JSFUN_THISP_BOOLEAN),
119
+ JS_FS_END
120
+ };
121
+
122
+ static JSBool
123
+ Boolean(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
124
+ {
125
+ jsval bval;
126
+
127
+ bval = (argc != 0)
128
+ ? BOOLEAN_TO_JSVAL(js_ValueToBoolean(argv[0]))
129
+ : JSVAL_FALSE;
130
+ if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {
131
+ *rval = bval;
132
+ return JS_TRUE;
133
+ }
134
+ STOBJ_SET_SLOT(obj, JSSLOT_PRIVATE, bval);
135
+ return JS_TRUE;
136
+ }
137
+
138
+ JSObject *
139
+ js_InitBooleanClass(JSContext *cx, JSObject *obj)
140
+ {
141
+ JSObject *proto;
142
+
143
+ proto = JS_InitClass(cx, obj, NULL, &js_BooleanClass, Boolean, 1,
144
+ NULL, boolean_methods, NULL, NULL);
145
+ if (!proto)
146
+ return NULL;
147
+ STOBJ_SET_SLOT(proto, JSSLOT_PRIVATE, JSVAL_FALSE);
148
+ return proto;
149
+ }
150
+
151
+ JSString *
152
+ js_BooleanToString(JSContext *cx, JSBool b)
153
+ {
154
+ return ATOM_TO_STRING(cx->runtime->atomState.booleanAtoms[b ? 1 : 0]);
155
+ }
156
+
157
+ JSBool
158
+ js_ValueToBoolean(jsval v)
159
+ {
160
+ if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v))
161
+ return JS_FALSE;
162
+ if (JSVAL_IS_OBJECT(v))
163
+ return JS_TRUE;
164
+ if (JSVAL_IS_STRING(v))
165
+ return JSSTRING_LENGTH(JSVAL_TO_STRING(v)) != 0;
166
+ if (JSVAL_IS_INT(v))
167
+ return JSVAL_TO_INT(v) != 0;
168
+ if (JSVAL_IS_DOUBLE(v)) {
169
+ jsdouble d;
170
+
171
+ d = *JSVAL_TO_DOUBLE(v);
172
+ return !JSDOUBLE_IS_NaN(d) && d != 0;
173
+ }
174
+ JS_ASSERT(JSVAL_IS_BOOLEAN(v));
175
+ return JSVAL_TO_BOOLEAN(v);
176
+ }
@@ -0,0 +1,73 @@
1
+ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2
+ *
3
+ * ***** BEGIN LICENSE BLOCK *****
4
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5
+ *
6
+ * The contents of this file are subject to the Mozilla Public License Version
7
+ * 1.1 (the "License"); you may not use this file except in compliance with
8
+ * the License. You may obtain a copy of the License at
9
+ * http://www.mozilla.org/MPL/
10
+ *
11
+ * Software distributed under the License is distributed on an "AS IS" basis,
12
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13
+ * for the specific language governing rights and limitations under the
14
+ * License.
15
+ *
16
+ * The Original Code is Mozilla Communicator client code, released
17
+ * March 31, 1998.
18
+ *
19
+ * The Initial Developer of the Original Code is
20
+ * Netscape Communications Corporation.
21
+ * Portions created by the Initial Developer are Copyright (C) 1998
22
+ * the Initial Developer. All Rights Reserved.
23
+ *
24
+ * Contributor(s):
25
+ *
26
+ * Alternatively, the contents of this file may be used under the terms of
27
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
28
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29
+ * in which case the provisions of the GPL or the LGPL are applicable instead
30
+ * of those above. If you wish to allow use of your version of this file only
31
+ * under the terms of either the GPL or the LGPL, and not to allow others to
32
+ * use your version of this file under the terms of the MPL, indicate your
33
+ * decision by deleting the provisions above and replace them with the notice
34
+ * and other provisions required by the GPL or the LGPL. If you do not delete
35
+ * the provisions above, a recipient may use your version of this file under
36
+ * the terms of any one of the MPL, the GPL or the LGPL.
37
+ *
38
+ * ***** END LICENSE BLOCK ***** */
39
+
40
+ #ifndef jsbool_h___
41
+ #define jsbool_h___
42
+ /*
43
+ * JS boolean interface.
44
+ */
45
+
46
+ JS_BEGIN_EXTERN_C
47
+
48
+ /*
49
+ * Crypto-booleans, not visible to script but used internally by the engine.
50
+ *
51
+ * JSVAL_HOLE is a useful value for identifying a hole in an array. It's also
52
+ * used in the interpreter to represent "no exception pending". In general it
53
+ * can be used to represent "no value".
54
+ *
55
+ * JSVAL_ARETURN is used to throw asynchronous return for generator.close().
56
+ */
57
+ #define JSVAL_HOLE BOOLEAN_TO_JSVAL(2)
58
+ #define JSVAL_ARETURN BOOLEAN_TO_JSVAL(3)
59
+
60
+ extern JSClass js_BooleanClass;
61
+
62
+ extern JSObject *
63
+ js_InitBooleanClass(JSContext *cx, JSObject *obj);
64
+
65
+ extern JSString *
66
+ js_BooleanToString(JSContext *cx, JSBool b);
67
+
68
+ extern JSBool
69
+ js_ValueToBoolean(jsval v);
70
+
71
+ JS_END_EXTERN_C
72
+
73
+ #endif /* jsbool_h___ */
@@ -0,0 +1,139 @@
1
+ /* -*- Mode: C++; tab-width: 4; 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
+ * The Original Code is Mozilla Communicator client code, released
16
+ * March 31, 1998.
17
+ *
18
+ * The Initial Developer of the Original Code is
19
+ * Netscape Communications Corporation.
20
+ * Portions created by the Initial Developer are Copyright (C) 1998
21
+ * the Initial Developer. All Rights Reserved.
22
+ *
23
+ * Contributor(s):
24
+ *
25
+ * Alternatively, the contents of this file may be used under the terms of
26
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
27
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28
+ * in which case the provisions of the GPL or the LGPL are applicable instead
29
+ * of those above. If you wish to allow use of your version of this file only
30
+ * under the terms of either the GPL or the LGPL, and not to allow others to
31
+ * use your version of this file under the terms of the MPL, indicate your
32
+ * decision by deleting the provisions above and replace them with the notice
33
+ * and other provisions required by the GPL or the LGPL. If you do not delete
34
+ * the provisions above, a recipient may use your version of this file under
35
+ * the terms of any one of the MPL, the GPL or the LGPL.
36
+ *
37
+ * ***** END LICENSE BLOCK ***** */
38
+
39
+ #ifndef jsclist_h___
40
+ #define jsclist_h___
41
+
42
+ #include "jstypes.h"
43
+
44
+ /*
45
+ ** Circular linked list
46
+ */
47
+ typedef struct JSCListStr {
48
+ struct JSCListStr *next;
49
+ struct JSCListStr *prev;
50
+ } JSCList;
51
+
52
+ /*
53
+ ** Insert element "_e" into the list, before "_l".
54
+ */
55
+ #define JS_INSERT_BEFORE(_e,_l) \
56
+ JS_BEGIN_MACRO \
57
+ (_e)->next = (_l); \
58
+ (_e)->prev = (_l)->prev; \
59
+ (_l)->prev->next = (_e); \
60
+ (_l)->prev = (_e); \
61
+ JS_END_MACRO
62
+
63
+ /*
64
+ ** Insert element "_e" into the list, after "_l".
65
+ */
66
+ #define JS_INSERT_AFTER(_e,_l) \
67
+ JS_BEGIN_MACRO \
68
+ (_e)->next = (_l)->next; \
69
+ (_e)->prev = (_l); \
70
+ (_l)->next->prev = (_e); \
71
+ (_l)->next = (_e); \
72
+ JS_END_MACRO
73
+
74
+ /*
75
+ ** Return the element following element "_e"
76
+ */
77
+ #define JS_NEXT_LINK(_e) \
78
+ ((_e)->next)
79
+ /*
80
+ ** Return the element preceding element "_e"
81
+ */
82
+ #define JS_PREV_LINK(_e) \
83
+ ((_e)->prev)
84
+
85
+ /*
86
+ ** Append an element "_e" to the end of the list "_l"
87
+ */
88
+ #define JS_APPEND_LINK(_e,_l) JS_INSERT_BEFORE(_e,_l)
89
+
90
+ /*
91
+ ** Insert an element "_e" at the head of the list "_l"
92
+ */
93
+ #define JS_INSERT_LINK(_e,_l) JS_INSERT_AFTER(_e,_l)
94
+
95
+ /* Return the head/tail of the list */
96
+ #define JS_LIST_HEAD(_l) (_l)->next
97
+ #define JS_LIST_TAIL(_l) (_l)->prev
98
+
99
+ /*
100
+ ** Remove the element "_e" from it's circular list.
101
+ */
102
+ #define JS_REMOVE_LINK(_e) \
103
+ JS_BEGIN_MACRO \
104
+ (_e)->prev->next = (_e)->next; \
105
+ (_e)->next->prev = (_e)->prev; \
106
+ JS_END_MACRO
107
+
108
+ /*
109
+ ** Remove the element "_e" from it's circular list. Also initializes the
110
+ ** linkage.
111
+ */
112
+ #define JS_REMOVE_AND_INIT_LINK(_e) \
113
+ JS_BEGIN_MACRO \
114
+ (_e)->prev->next = (_e)->next; \
115
+ (_e)->next->prev = (_e)->prev; \
116
+ (_e)->next = (_e); \
117
+ (_e)->prev = (_e); \
118
+ JS_END_MACRO
119
+
120
+ /*
121
+ ** Return non-zero if the given circular list "_l" is empty, zero if the
122
+ ** circular list is not empty
123
+ */
124
+ #define JS_CLIST_IS_EMPTY(_l) \
125
+ ((_l)->next == (_l))
126
+
127
+ /*
128
+ ** Initialize a circular list
129
+ */
130
+ #define JS_INIT_CLIST(_l) \
131
+ JS_BEGIN_MACRO \
132
+ (_l)->next = (_l); \
133
+ (_l)->prev = (_l); \
134
+ JS_END_MACRO
135
+
136
+ #define JS_INIT_STATIC_CLIST(_l) \
137
+ {(_l), (_l)}
138
+
139
+ #endif /* jsclist_h___ */
@@ -0,0 +1,1348 @@
1
+ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2
+ * vim: set ts=8 sw=4 et tw=80:
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 execution context.
43
+ */
44
+ #include "jsstddef.h"
45
+ #include <stdarg.h>
46
+ #include <stdlib.h>
47
+ #include <string.h>
48
+ #include "jstypes.h"
49
+ #include "jsarena.h" /* Added by JSIFY */
50
+ #include "jsutil.h" /* Added by JSIFY */
51
+ #include "jsclist.h"
52
+ #include "jsprf.h"
53
+ #include "jsatom.h"
54
+ #include "jscntxt.h"
55
+ #include "jsconfig.h"
56
+ #include "jsdbgapi.h"
57
+ #include "jsexn.h"
58
+ #include "jsgc.h"
59
+ #include "jslock.h"
60
+ #include "jsnum.h"
61
+ #include "jsobj.h"
62
+ #include "jsopcode.h"
63
+ #include "jsscan.h"
64
+ #include "jsscope.h"
65
+ #include "jsscript.h"
66
+ #include "jsstr.h"
67
+
68
+ #ifdef JS_THREADSAFE
69
+ #include "prtypes.h"
70
+
71
+ /*
72
+ * The index for JSThread info, returned by PR_NewThreadPrivateIndex. The
73
+ * index value is visible and shared by all threads, but the data associated
74
+ * with it is private to each thread.
75
+ */
76
+ static PRUintn threadTPIndex;
77
+ static JSBool tpIndexInited = JS_FALSE;
78
+
79
+ JSBool
80
+ js_InitThreadPrivateIndex(void (JS_DLL_CALLBACK *ptr)(void *))
81
+ {
82
+ PRStatus status;
83
+
84
+ if (tpIndexInited)
85
+ return JS_TRUE;
86
+
87
+ status = PR_NewThreadPrivateIndex(&threadTPIndex, ptr);
88
+
89
+ if (status == PR_SUCCESS)
90
+ tpIndexInited = JS_TRUE;
91
+ return status == PR_SUCCESS;
92
+ }
93
+
94
+ /*
95
+ * Callback function to delete a JSThread info when the thread that owns it
96
+ * is destroyed.
97
+ */
98
+ void JS_DLL_CALLBACK
99
+ js_ThreadDestructorCB(void *ptr)
100
+ {
101
+ JSThread *thread = (JSThread *)ptr;
102
+
103
+ if (!thread)
104
+ return;
105
+
106
+ /*
107
+ * Check that this thread properly called either JS_DestroyContext or
108
+ * JS_ClearContextThread on each JSContext it created or used.
109
+ */
110
+ JS_ASSERT(JS_CLIST_IS_EMPTY(&thread->contextList));
111
+ GSN_CACHE_CLEAR(&thread->gsnCache);
112
+ free(thread);
113
+ }
114
+
115
+ /*
116
+ * Get current thread-local JSThread info, creating one if it doesn't exist.
117
+ * Each thread has a unique JSThread pointer.
118
+ *
119
+ * Since we are dealing with thread-local data, no lock is needed.
120
+ *
121
+ * Return a pointer to the thread local info, NULL if the system runs out
122
+ * of memory, or it failed to set thread private data (neither case is very
123
+ * likely; both are probably due to out-of-memory). It is up to the caller
124
+ * to report an error, if possible.
125
+ */
126
+ JSThread *
127
+ js_GetCurrentThread(JSRuntime *rt)
128
+ {
129
+ JSThread *thread;
130
+
131
+ thread = (JSThread *)PR_GetThreadPrivate(threadTPIndex);
132
+ if (!thread) {
133
+ thread = (JSThread *) malloc(sizeof(JSThread));
134
+ if (!thread)
135
+ return NULL;
136
+ #ifdef DEBUG
137
+ memset(thread, JS_FREE_PATTERN, sizeof(JSThread));
138
+ #endif
139
+ if (PR_FAILURE == PR_SetThreadPrivate(threadTPIndex, thread)) {
140
+ free(thread);
141
+ return NULL;
142
+ }
143
+
144
+ JS_INIT_CLIST(&thread->contextList);
145
+ thread->id = js_CurrentThreadId();
146
+ thread->gcMallocBytes = 0;
147
+
148
+ /*
149
+ * js_SetContextThread initializes the remaining fields as necessary.
150
+ */
151
+ }
152
+ return thread;
153
+ }
154
+
155
+ /*
156
+ * Sets current thread as owning thread of a context by assigning the
157
+ * thread-private info to the context. If the current thread doesn't have
158
+ * private JSThread info, create one.
159
+ */
160
+ JSBool
161
+ js_SetContextThread(JSContext *cx)
162
+ {
163
+ JSThread *thread = js_GetCurrentThread(cx->runtime);
164
+
165
+ if (!thread) {
166
+ JS_ReportOutOfMemory(cx);
167
+ return JS_FALSE;
168
+ }
169
+
170
+ /*
171
+ * Clear gcFreeLists and caches on each transition from 0 to 1 context
172
+ * active on the current thread. See bug 351602 and bug 425828.
173
+ */
174
+ if (JS_CLIST_IS_EMPTY(&thread->contextList)) {
175
+ memset(thread->gcFreeLists, 0, sizeof(thread->gcFreeLists));
176
+ memset(&thread->gsnCache, 0, sizeof(thread->gsnCache));
177
+ memset(&thread->propertyCache, 0, sizeof(thread->propertyCache));
178
+ }
179
+
180
+ /* Assert that the previous cx->thread called JS_ClearContextThread(). */
181
+ JS_ASSERT(!cx->thread || cx->thread == thread);
182
+ if (!cx->thread)
183
+ JS_APPEND_LINK(&cx->threadLinks, &thread->contextList);
184
+ cx->thread = thread;
185
+ return JS_TRUE;
186
+ }
187
+
188
+ /* Remove the owning thread info of a context. */
189
+ void
190
+ js_ClearContextThread(JSContext *cx)
191
+ {
192
+ /*
193
+ * If cx is associated with a thread, this must be called only from that
194
+ * thread. If not, this is a harmless no-op.
195
+ */
196
+ JS_ASSERT(cx->thread == js_GetCurrentThread(cx->runtime) || !cx->thread);
197
+ JS_REMOVE_AND_INIT_LINK(&cx->threadLinks);
198
+ #ifdef DEBUG
199
+ if (JS_CLIST_IS_EMPTY(&cx->thread->contextList)) {
200
+ memset(cx->thread->gcFreeLists, JS_FREE_PATTERN,
201
+ sizeof(cx->thread->gcFreeLists));
202
+ }
203
+ #endif
204
+ cx->thread = NULL;
205
+ }
206
+
207
+ #endif /* JS_THREADSAFE */
208
+
209
+ void
210
+ js_OnVersionChange(JSContext *cx)
211
+ {
212
+ #ifdef DEBUG
213
+ JSVersion version = JSVERSION_NUMBER(cx);
214
+
215
+ JS_ASSERT(version == JSVERSION_DEFAULT || version >= JSVERSION_ECMA_3);
216
+ #endif
217
+ }
218
+
219
+ void
220
+ js_SetVersion(JSContext *cx, JSVersion version)
221
+ {
222
+ cx->version = version;
223
+ js_OnVersionChange(cx);
224
+ }
225
+
226
+ JSContext *
227
+ js_NewContext(JSRuntime *rt, size_t stackChunkSize)
228
+ {
229
+ JSContext *cx;
230
+ JSBool ok, first;
231
+ JSContextCallback cxCallback;
232
+
233
+ cx = (JSContext *) malloc(sizeof *cx);
234
+ if (!cx)
235
+ return NULL;
236
+ memset(cx, 0, sizeof *cx);
237
+
238
+ cx->runtime = rt;
239
+ JS_ClearOperationCallback(cx);
240
+ cx->debugHooks = &rt->globalDebugHooks;
241
+ #if JS_STACK_GROWTH_DIRECTION > 0
242
+ cx->stackLimit = (jsuword)-1;
243
+ #endif
244
+ cx->scriptStackQuota = JS_DEFAULT_SCRIPT_STACK_QUOTA;
245
+ #ifdef JS_THREADSAFE
246
+ JS_INIT_CLIST(&cx->threadLinks);
247
+ js_SetContextThread(cx);
248
+ #endif
249
+
250
+ JS_LOCK_GC(rt);
251
+ for (;;) {
252
+ first = (rt->contextList.next == &rt->contextList);
253
+ if (rt->state == JSRTS_UP) {
254
+ JS_ASSERT(!first);
255
+ break;
256
+ }
257
+ if (rt->state == JSRTS_DOWN) {
258
+ JS_ASSERT(first);
259
+ rt->state = JSRTS_LAUNCHING;
260
+ break;
261
+ }
262
+ JS_WAIT_CONDVAR(rt->stateChange, JS_NO_TIMEOUT);
263
+ }
264
+ JS_APPEND_LINK(&cx->links, &rt->contextList);
265
+ JS_UNLOCK_GC(rt);
266
+
267
+ /*
268
+ * First we do the infallible, every-time per-context initializations.
269
+ * Should a later, fallible initialization (js_InitRegExpStatics, e.g.,
270
+ * or the stuff under 'if (first)' below) fail, at least the version
271
+ * and arena-pools will be valid and safe to use (say, from the last GC
272
+ * done by js_DestroyContext).
273
+ */
274
+ cx->version = JSVERSION_DEFAULT;
275
+ JS_INIT_ARENA_POOL(&cx->stackPool, "stack", stackChunkSize, sizeof(jsval),
276
+ &cx->scriptStackQuota);
277
+ JS_INIT_ARENA_POOL(&cx->tempPool, "temp", 1024, sizeof(jsdouble),
278
+ &cx->scriptStackQuota);
279
+
280
+ if (!js_InitRegExpStatics(cx, &cx->regExpStatics)) {
281
+ js_DestroyContext(cx, JSDCM_NEW_FAILED);
282
+ return NULL;
283
+ }
284
+
285
+ /*
286
+ * If cx is the first context on this runtime, initialize well-known atoms,
287
+ * keywords, numbers, and strings. If one of these steps should fail, the
288
+ * runtime will be left in a partially initialized state, with zeroes and
289
+ * nulls stored in the default-initialized remainder of the struct. We'll
290
+ * clean the runtime up under js_DestroyContext, because cx will be "last"
291
+ * as well as "first".
292
+ */
293
+ if (first) {
294
+ #ifdef JS_THREADSAFE
295
+ JS_BeginRequest(cx);
296
+ #endif
297
+ ok = js_InitCommonAtoms(cx);
298
+
299
+ /*
300
+ * scriptFilenameTable may be left over from a previous episode of
301
+ * non-zero contexts alive in rt, so don't re-init the table if it's
302
+ * not necessary.
303
+ */
304
+ if (ok && !rt->scriptFilenameTable)
305
+ ok = js_InitRuntimeScriptState(rt);
306
+ if (ok)
307
+ ok = js_InitRuntimeNumberState(cx);
308
+ if (ok)
309
+ ok = js_InitRuntimeStringState(cx);
310
+ #ifdef JS_THREADSAFE
311
+ JS_EndRequest(cx);
312
+ #endif
313
+ if (!ok) {
314
+ js_DestroyContext(cx, JSDCM_NEW_FAILED);
315
+ return NULL;
316
+ }
317
+
318
+ JS_LOCK_GC(rt);
319
+ rt->state = JSRTS_UP;
320
+ JS_NOTIFY_ALL_CONDVAR(rt->stateChange);
321
+ JS_UNLOCK_GC(rt);
322
+ }
323
+
324
+ cxCallback = rt->cxCallback;
325
+ if (cxCallback && !cxCallback(cx, JSCONTEXT_NEW)) {
326
+ js_DestroyContext(cx, JSDCM_NEW_FAILED);
327
+ return NULL;
328
+ }
329
+ return cx;
330
+ }
331
+
332
+ void
333
+ js_DestroyContext(JSContext *cx, JSDestroyContextMode mode)
334
+ {
335
+ JSRuntime *rt;
336
+ JSContextCallback cxCallback;
337
+ JSBool last;
338
+ JSArgumentFormatMap *map;
339
+ JSLocalRootStack *lrs;
340
+ JSLocalRootChunk *lrc;
341
+
342
+ rt = cx->runtime;
343
+
344
+ if (mode != JSDCM_NEW_FAILED) {
345
+ cxCallback = rt->cxCallback;
346
+ if (cxCallback) {
347
+ /*
348
+ * JSCONTEXT_DESTROY callback is not allowed to fail and must
349
+ * return true.
350
+ */
351
+ #ifdef DEBUG
352
+ JSBool callbackStatus =
353
+ #endif
354
+ cxCallback(cx, JSCONTEXT_DESTROY);
355
+ JS_ASSERT(callbackStatus);
356
+ }
357
+ }
358
+
359
+ /* Remove cx from context list first. */
360
+ JS_LOCK_GC(rt);
361
+ JS_ASSERT(rt->state == JSRTS_UP || rt->state == JSRTS_LAUNCHING);
362
+ JS_REMOVE_LINK(&cx->links);
363
+ last = (rt->contextList.next == &rt->contextList);
364
+ if (last)
365
+ rt->state = JSRTS_LANDING;
366
+ JS_UNLOCK_GC(rt);
367
+
368
+ if (last) {
369
+ #ifdef JS_THREADSAFE
370
+ /*
371
+ * If cx is not in a request already, begin one now so that we wait
372
+ * for any racing GC started on a not-last context to finish, before
373
+ * we plow ahead and unpin atoms. Note that even though we begin a
374
+ * request here if necessary, we end all requests on cx below before
375
+ * forcing a final GC. This lets any not-last context destruction
376
+ * racing in another thread try to force or maybe run the GC, but by
377
+ * that point, rt->state will not be JSRTS_UP, and that GC attempt
378
+ * will return early.
379
+ */
380
+ if (cx->requestDepth == 0)
381
+ JS_BeginRequest(cx);
382
+ #endif
383
+
384
+ /* Unlock and clear GC things held by runtime pointers. */
385
+ js_FinishRuntimeNumberState(cx);
386
+ js_FinishRuntimeStringState(cx);
387
+
388
+ /* Unpin all common atoms before final GC. */
389
+ js_FinishCommonAtoms(cx);
390
+
391
+ /* Clear debugging state to remove GC roots. */
392
+ JS_ClearAllTraps(cx);
393
+ JS_ClearAllWatchPoints(cx);
394
+ }
395
+
396
+ /*
397
+ * Remove more GC roots in regExpStatics, then collect garbage.
398
+ * XXX anti-modularity alert: we rely on the call to js_RemoveRoot within
399
+ * XXX this function call to wait for any racing GC to complete, in the
400
+ * XXX case where JS_DestroyContext is called outside of a request on cx
401
+ */
402
+ js_FreeRegExpStatics(cx, &cx->regExpStatics);
403
+
404
+ #ifdef JS_THREADSAFE
405
+ /*
406
+ * Destroying a context implicitly calls JS_EndRequest(). Also, we must
407
+ * end our request here in case we are "last" -- in that event, another
408
+ * js_DestroyContext that was not last might be waiting in the GC for our
409
+ * request to end. We'll let it run below, just before we do the truly
410
+ * final GC and then free atom state.
411
+ *
412
+ * At this point, cx must be inaccessible to other threads. It's off the
413
+ * rt->contextList, and it should not be reachable via any object private
414
+ * data structure.
415
+ */
416
+ while (cx->requestDepth != 0)
417
+ JS_EndRequest(cx);
418
+ #endif
419
+
420
+ if (last) {
421
+ js_GC(cx, GC_LAST_CONTEXT);
422
+
423
+ /*
424
+ * Free the script filename table if it exists and is empty. Do this
425
+ * after the last GC to avoid finalizers tripping on free memory.
426
+ */
427
+ if (rt->scriptFilenameTable && rt->scriptFilenameTable->nentries == 0)
428
+ js_FinishRuntimeScriptState(rt);
429
+
430
+ /* Take the runtime down, now that it has no contexts or atoms. */
431
+ JS_LOCK_GC(rt);
432
+ rt->state = JSRTS_DOWN;
433
+ JS_NOTIFY_ALL_CONDVAR(rt->stateChange);
434
+ JS_UNLOCK_GC(rt);
435
+ } else {
436
+ if (mode == JSDCM_FORCE_GC)
437
+ js_GC(cx, GC_NORMAL);
438
+ else if (mode == JSDCM_MAYBE_GC)
439
+ JS_MaybeGC(cx);
440
+ }
441
+
442
+ /* Free the stuff hanging off of cx. */
443
+ JS_FinishArenaPool(&cx->stackPool);
444
+ JS_FinishArenaPool(&cx->tempPool);
445
+
446
+ if (cx->lastMessage)
447
+ free(cx->lastMessage);
448
+
449
+ /* Remove any argument formatters. */
450
+ map = cx->argumentFormatMap;
451
+ while (map) {
452
+ JSArgumentFormatMap *temp = map;
453
+ map = map->next;
454
+ JS_free(cx, temp);
455
+ }
456
+
457
+ /* Destroy the resolve recursion damper. */
458
+ if (cx->resolvingTable) {
459
+ JS_DHashTableDestroy(cx->resolvingTable);
460
+ cx->resolvingTable = NULL;
461
+ }
462
+
463
+ lrs = cx->localRootStack;
464
+ if (lrs) {
465
+ while ((lrc = lrs->topChunk) != &lrs->firstChunk) {
466
+ lrs->topChunk = lrc->down;
467
+ JS_free(cx, lrc);
468
+ }
469
+ JS_free(cx, lrs);
470
+ }
471
+
472
+ #ifdef JS_THREADSAFE
473
+ js_ClearContextThread(cx);
474
+ #endif
475
+
476
+ /* Finally, free cx itself. */
477
+ free(cx);
478
+ }
479
+
480
+ JSBool
481
+ js_ValidContextPointer(JSRuntime *rt, JSContext *cx)
482
+ {
483
+ JSCList *cl;
484
+
485
+ for (cl = rt->contextList.next; cl != &rt->contextList; cl = cl->next) {
486
+ if (cl == &cx->links)
487
+ return JS_TRUE;
488
+ }
489
+ JS_RUNTIME_METER(rt, deadContexts);
490
+ return JS_FALSE;
491
+ }
492
+
493
+ JSContext *
494
+ js_ContextIterator(JSRuntime *rt, JSBool unlocked, JSContext **iterp)
495
+ {
496
+ JSContext *cx = *iterp;
497
+
498
+ if (unlocked)
499
+ JS_LOCK_GC(rt);
500
+ if (!cx)
501
+ cx = (JSContext *)&rt->contextList;
502
+ cx = (JSContext *)cx->links.next;
503
+ if (&cx->links == &rt->contextList)
504
+ cx = NULL;
505
+ *iterp = cx;
506
+ if (unlocked)
507
+ JS_UNLOCK_GC(rt);
508
+ return cx;
509
+ }
510
+
511
+ JS_STATIC_DLL_CALLBACK(JSDHashNumber)
512
+ resolving_HashKey(JSDHashTable *table, const void *ptr)
513
+ {
514
+ const JSResolvingKey *key = (const JSResolvingKey *)ptr;
515
+
516
+ return ((JSDHashNumber)JS_PTR_TO_UINT32(key->obj) >> JSVAL_TAGBITS) ^ key->id;
517
+ }
518
+
519
+ JS_PUBLIC_API(JSBool)
520
+ resolving_MatchEntry(JSDHashTable *table,
521
+ const JSDHashEntryHdr *hdr,
522
+ const void *ptr)
523
+ {
524
+ const JSResolvingEntry *entry = (const JSResolvingEntry *)hdr;
525
+ const JSResolvingKey *key = (const JSResolvingKey *)ptr;
526
+
527
+ return entry->key.obj == key->obj && entry->key.id == key->id;
528
+ }
529
+
530
+ static const JSDHashTableOps resolving_dhash_ops = {
531
+ JS_DHashAllocTable,
532
+ JS_DHashFreeTable,
533
+ resolving_HashKey,
534
+ resolving_MatchEntry,
535
+ JS_DHashMoveEntryStub,
536
+ JS_DHashClearEntryStub,
537
+ JS_DHashFinalizeStub,
538
+ NULL
539
+ };
540
+
541
+ JSBool
542
+ js_StartResolving(JSContext *cx, JSResolvingKey *key, uint32 flag,
543
+ JSResolvingEntry **entryp)
544
+ {
545
+ JSDHashTable *table;
546
+ JSResolvingEntry *entry;
547
+
548
+ table = cx->resolvingTable;
549
+ if (!table) {
550
+ table = JS_NewDHashTable(&resolving_dhash_ops, NULL,
551
+ sizeof(JSResolvingEntry),
552
+ JS_DHASH_MIN_SIZE);
553
+ if (!table)
554
+ goto outofmem;
555
+ cx->resolvingTable = table;
556
+ }
557
+
558
+ entry = (JSResolvingEntry *)
559
+ JS_DHashTableOperate(table, key, JS_DHASH_ADD);
560
+ if (!entry)
561
+ goto outofmem;
562
+
563
+ if (entry->flags & flag) {
564
+ /* An entry for (key, flag) exists already -- dampen recursion. */
565
+ entry = NULL;
566
+ } else {
567
+ /* Fill in key if we were the first to add entry, then set flag. */
568
+ if (!entry->key.obj)
569
+ entry->key = *key;
570
+ entry->flags |= flag;
571
+ }
572
+ *entryp = entry;
573
+ return JS_TRUE;
574
+
575
+ outofmem:
576
+ JS_ReportOutOfMemory(cx);
577
+ return JS_FALSE;
578
+ }
579
+
580
+ void
581
+ js_StopResolving(JSContext *cx, JSResolvingKey *key, uint32 flag,
582
+ JSResolvingEntry *entry, uint32 generation)
583
+ {
584
+ JSDHashTable *table;
585
+
586
+ /*
587
+ * Clear flag from entry->flags and return early if other flags remain.
588
+ * We must take care to re-lookup entry if the table has changed since
589
+ * it was found by js_StartResolving.
590
+ */
591
+ table = cx->resolvingTable;
592
+ if (!entry || table->generation != generation) {
593
+ entry = (JSResolvingEntry *)
594
+ JS_DHashTableOperate(table, key, JS_DHASH_LOOKUP);
595
+ }
596
+ JS_ASSERT(JS_DHASH_ENTRY_IS_BUSY(&entry->hdr));
597
+ entry->flags &= ~flag;
598
+ if (entry->flags)
599
+ return;
600
+
601
+ /*
602
+ * Do a raw remove only if fewer entries were removed than would cause
603
+ * alpha to be less than .5 (alpha is at most .75). Otherwise, we just
604
+ * call JS_DHashTableOperate to re-lookup the key and remove its entry,
605
+ * compressing or shrinking the table as needed.
606
+ */
607
+ if (table->removedCount < JS_DHASH_TABLE_SIZE(table) >> 2)
608
+ JS_DHashTableRawRemove(table, &entry->hdr);
609
+ else
610
+ JS_DHashTableOperate(table, key, JS_DHASH_REMOVE);
611
+ }
612
+
613
+ JSBool
614
+ js_EnterLocalRootScope(JSContext *cx)
615
+ {
616
+ JSLocalRootStack *lrs;
617
+ int mark;
618
+
619
+ lrs = cx->localRootStack;
620
+ if (!lrs) {
621
+ lrs = (JSLocalRootStack *) JS_malloc(cx, sizeof *lrs);
622
+ if (!lrs)
623
+ return JS_FALSE;
624
+ lrs->scopeMark = JSLRS_NULL_MARK;
625
+ lrs->rootCount = 0;
626
+ lrs->topChunk = &lrs->firstChunk;
627
+ lrs->firstChunk.down = NULL;
628
+ cx->localRootStack = lrs;
629
+ }
630
+
631
+ /* Push lrs->scopeMark to save it for restore when leaving. */
632
+ mark = js_PushLocalRoot(cx, lrs, INT_TO_JSVAL(lrs->scopeMark));
633
+ if (mark < 0)
634
+ return JS_FALSE;
635
+ lrs->scopeMark = (uint32) mark;
636
+ return JS_TRUE;
637
+ }
638
+
639
+ void
640
+ js_LeaveLocalRootScopeWithResult(JSContext *cx, jsval rval)
641
+ {
642
+ JSLocalRootStack *lrs;
643
+ uint32 mark, m, n;
644
+ JSLocalRootChunk *lrc;
645
+
646
+ /* Defend against buggy native callers. */
647
+ lrs = cx->localRootStack;
648
+ JS_ASSERT(lrs && lrs->rootCount != 0);
649
+ if (!lrs || lrs->rootCount == 0)
650
+ return;
651
+
652
+ mark = lrs->scopeMark;
653
+ JS_ASSERT(mark != JSLRS_NULL_MARK);
654
+ if (mark == JSLRS_NULL_MARK)
655
+ return;
656
+
657
+ /* Free any chunks being popped by this leave operation. */
658
+ m = mark >> JSLRS_CHUNK_SHIFT;
659
+ n = (lrs->rootCount - 1) >> JSLRS_CHUNK_SHIFT;
660
+ while (n > m) {
661
+ lrc = lrs->topChunk;
662
+ JS_ASSERT(lrc != &lrs->firstChunk);
663
+ lrs->topChunk = lrc->down;
664
+ JS_free(cx, lrc);
665
+ --n;
666
+ }
667
+
668
+ /*
669
+ * Pop the scope, restoring lrs->scopeMark. If rval is a GC-thing, push
670
+ * it on the caller's scope, or store it in lastInternalResult if we are
671
+ * leaving the outermost scope. We don't need to allocate a new lrc
672
+ * because we can overwrite the old mark's slot with rval.
673
+ */
674
+ lrc = lrs->topChunk;
675
+ m = mark & JSLRS_CHUNK_MASK;
676
+ lrs->scopeMark = (uint32) JSVAL_TO_INT(lrc->roots[m]);
677
+ if (JSVAL_IS_GCTHING(rval) && !JSVAL_IS_NULL(rval)) {
678
+ if (mark == 0) {
679
+ cx->weakRoots.lastInternalResult = rval;
680
+ } else {
681
+ /*
682
+ * Increment m to avoid the "else if (m == 0)" case below. If
683
+ * rval is not a GC-thing, that case would take care of freeing
684
+ * any chunk that contained only the old mark. Since rval *is*
685
+ * a GC-thing here, we want to reuse that old mark's slot.
686
+ */
687
+ lrc->roots[m++] = rval;
688
+ ++mark;
689
+ }
690
+ }
691
+ lrs->rootCount = (uint32) mark;
692
+
693
+ /*
694
+ * Free the stack eagerly, risking malloc churn. The alternative would
695
+ * require an lrs->entryCount member, maintained by Enter and Leave, and
696
+ * tested by the GC in addition to the cx->localRootStack non-null test.
697
+ *
698
+ * That approach would risk hoarding 264 bytes (net) per context. Right
699
+ * now it seems better to give fresh (dirty in CPU write-back cache, and
700
+ * the data is no longer needed) memory back to the malloc heap.
701
+ */
702
+ if (mark == 0) {
703
+ cx->localRootStack = NULL;
704
+ JS_free(cx, lrs);
705
+ } else if (m == 0) {
706
+ lrs->topChunk = lrc->down;
707
+ JS_free(cx, lrc);
708
+ }
709
+ }
710
+
711
+ void
712
+ js_ForgetLocalRoot(JSContext *cx, jsval v)
713
+ {
714
+ JSLocalRootStack *lrs;
715
+ uint32 i, j, m, n, mark;
716
+ JSLocalRootChunk *lrc, *lrc2;
717
+ jsval top;
718
+
719
+ lrs = cx->localRootStack;
720
+ JS_ASSERT(lrs && lrs->rootCount);
721
+ if (!lrs || lrs->rootCount == 0)
722
+ return;
723
+
724
+ /* Prepare to pop the top-most value from the stack. */
725
+ n = lrs->rootCount - 1;
726
+ m = n & JSLRS_CHUNK_MASK;
727
+ lrc = lrs->topChunk;
728
+ top = lrc->roots[m];
729
+
730
+ /* Be paranoid about calls on an empty scope. */
731
+ mark = lrs->scopeMark;
732
+ JS_ASSERT(mark < n);
733
+ if (mark >= n)
734
+ return;
735
+
736
+ /* If v was not the last root pushed in the top scope, find it. */
737
+ if (top != v) {
738
+ /* Search downward in case v was recently pushed. */
739
+ i = n;
740
+ j = m;
741
+ lrc2 = lrc;
742
+ while (--i > mark) {
743
+ if (j == 0)
744
+ lrc2 = lrc2->down;
745
+ j = i & JSLRS_CHUNK_MASK;
746
+ if (lrc2->roots[j] == v)
747
+ break;
748
+ }
749
+
750
+ /* If we didn't find v in this scope, assert and bail out. */
751
+ JS_ASSERT(i != mark);
752
+ if (i == mark)
753
+ return;
754
+
755
+ /* Swap top and v so common tail code can pop v. */
756
+ lrc2->roots[j] = top;
757
+ }
758
+
759
+ /* Pop the last value from the stack. */
760
+ lrc->roots[m] = JSVAL_NULL;
761
+ lrs->rootCount = n;
762
+ if (m == 0) {
763
+ JS_ASSERT(n != 0);
764
+ JS_ASSERT(lrc != &lrs->firstChunk);
765
+ lrs->topChunk = lrc->down;
766
+ JS_free(cx, lrc);
767
+ }
768
+ }
769
+
770
+ int
771
+ js_PushLocalRoot(JSContext *cx, JSLocalRootStack *lrs, jsval v)
772
+ {
773
+ uint32 n, m;
774
+ JSLocalRootChunk *lrc;
775
+
776
+ n = lrs->rootCount;
777
+ m = n & JSLRS_CHUNK_MASK;
778
+ if (n == 0 || m != 0) {
779
+ /*
780
+ * At start of first chunk, or not at start of a non-first top chunk.
781
+ * Check for lrs->rootCount overflow.
782
+ */
783
+ if ((uint32)(n + 1) == 0) {
784
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
785
+ JSMSG_TOO_MANY_LOCAL_ROOTS);
786
+ return -1;
787
+ }
788
+ lrc = lrs->topChunk;
789
+ JS_ASSERT(n != 0 || lrc == &lrs->firstChunk);
790
+ } else {
791
+ /*
792
+ * After lrs->firstChunk, trying to index at a power-of-two chunk
793
+ * boundary: need a new chunk.
794
+ */
795
+ lrc = (JSLocalRootChunk *) JS_malloc(cx, sizeof *lrc);
796
+ if (!lrc)
797
+ return -1;
798
+ lrc->down = lrs->topChunk;
799
+ lrs->topChunk = lrc;
800
+ }
801
+ lrs->rootCount = n + 1;
802
+ lrc->roots[m] = v;
803
+ return (int) n;
804
+ }
805
+
806
+ void
807
+ js_TraceLocalRoots(JSTracer *trc, JSLocalRootStack *lrs)
808
+ {
809
+ uint32 n, m, mark;
810
+ JSLocalRootChunk *lrc;
811
+ jsval v;
812
+
813
+ n = lrs->rootCount;
814
+ if (n == 0)
815
+ return;
816
+
817
+ mark = lrs->scopeMark;
818
+ lrc = lrs->topChunk;
819
+ do {
820
+ while (--n > mark) {
821
+ m = n & JSLRS_CHUNK_MASK;
822
+ v = lrc->roots[m];
823
+ JS_ASSERT(JSVAL_IS_GCTHING(v) && v != JSVAL_NULL);
824
+ JS_SET_TRACING_INDEX(trc, "local_root", n);
825
+ js_CallValueTracerIfGCThing(trc, v);
826
+ if (m == 0)
827
+ lrc = lrc->down;
828
+ }
829
+ m = n & JSLRS_CHUNK_MASK;
830
+ mark = JSVAL_TO_INT(lrc->roots[m]);
831
+ if (m == 0)
832
+ lrc = lrc->down;
833
+ } while (n != 0);
834
+ JS_ASSERT(!lrc);
835
+ }
836
+
837
+ static void
838
+ ReportError(JSContext *cx, const char *message, JSErrorReport *reportp)
839
+ {
840
+ /*
841
+ * Check the error report, and set a JavaScript-catchable exception
842
+ * if the error is defined to have an associated exception. If an
843
+ * exception is thrown, then the JSREPORT_EXCEPTION flag will be set
844
+ * on the error report, and exception-aware hosts should ignore it.
845
+ */
846
+ JS_ASSERT(reportp);
847
+ if (reportp->errorNumber == JSMSG_UNCAUGHT_EXCEPTION)
848
+ reportp->flags |= JSREPORT_EXCEPTION;
849
+
850
+ /*
851
+ * Call the error reporter only if an exception wasn't raised.
852
+ *
853
+ * If an exception was raised, then we call the debugErrorHook
854
+ * (if present) to give it a chance to see the error before it
855
+ * propagates out of scope. This is needed for compatability
856
+ * with the old scheme.
857
+ */
858
+ if (!js_ErrorToException(cx, message, reportp)) {
859
+ js_ReportErrorAgain(cx, message, reportp);
860
+ } else if (cx->debugHooks->debugErrorHook && cx->errorReporter) {
861
+ JSDebugErrorHook hook = cx->debugHooks->debugErrorHook;
862
+ /* test local in case debugErrorHook changed on another thread */
863
+ if (hook)
864
+ hook(cx, message, reportp, cx->debugHooks->debugErrorHookData);
865
+ }
866
+ }
867
+
868
+ /*
869
+ * We don't post an exception in this case, since doing so runs into
870
+ * complications of pre-allocating an exception object which required
871
+ * running the Exception class initializer early etc.
872
+ * Instead we just invoke the errorReporter with an "Out Of Memory"
873
+ * type message, and then hope the process ends swiftly.
874
+ */
875
+ void
876
+ js_ReportOutOfMemory(JSContext *cx)
877
+ {
878
+ JSStackFrame *fp;
879
+ JSErrorReport report;
880
+ JSErrorReporter onError = cx->errorReporter;
881
+
882
+ /* Get the message for this error, but we won't expand any arguments. */
883
+ const JSErrorFormatString *efs =
884
+ js_GetLocalizedErrorMessage(cx, NULL, NULL, JSMSG_OUT_OF_MEMORY);
885
+ const char *msg = efs ? efs->format : "Out of memory";
886
+
887
+ /* Fill out the report, but don't do anything that requires allocation. */
888
+ memset(&report, 0, sizeof (struct JSErrorReport));
889
+ report.flags = JSREPORT_ERROR;
890
+ report.errorNumber = JSMSG_OUT_OF_MEMORY;
891
+
892
+ /*
893
+ * Walk stack until we find a frame that is associated with some script
894
+ * rather than a native frame.
895
+ */
896
+ for (fp = cx->fp; fp; fp = fp->down) {
897
+ if (fp->regs) {
898
+ report.filename = fp->script->filename;
899
+ report.lineno = js_PCToLineNumber(cx, fp->script, fp->regs->pc);
900
+ break;
901
+ }
902
+ }
903
+
904
+ /*
905
+ * If debugErrorHook is present then we give it a chance to veto sending
906
+ * the error on to the regular ErrorReporter. We also clear a pending
907
+ * exception if any now so the hooks can replace the out-of-memory error
908
+ * by a script-catchable exception.
909
+ */
910
+ cx->throwing = JS_FALSE;
911
+ if (onError) {
912
+ JSDebugErrorHook hook = cx->debugHooks->debugErrorHook;
913
+ if (hook &&
914
+ !hook(cx, msg, &report, cx->debugHooks->debugErrorHookData)) {
915
+ onError = NULL;
916
+ }
917
+ }
918
+
919
+ if (onError)
920
+ onError(cx, msg, &report);
921
+ }
922
+
923
+ void
924
+ js_ReportOutOfScriptQuota(JSContext *cx)
925
+ {
926
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
927
+ JSMSG_SCRIPT_STACK_QUOTA);
928
+ }
929
+
930
+ void
931
+ js_ReportOverRecursed(JSContext *cx)
932
+ {
933
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_OVER_RECURSED);
934
+ }
935
+
936
+ void
937
+ js_ReportAllocationOverflow(JSContext *cx)
938
+ {
939
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_ALLOC_OVERFLOW);
940
+ }
941
+
942
+ JSBool
943
+ js_ReportErrorVA(JSContext *cx, uintN flags, const char *format, va_list ap)
944
+ {
945
+ char *message;
946
+ jschar *ucmessage;
947
+ size_t messagelen;
948
+ JSStackFrame *fp;
949
+ JSErrorReport report;
950
+ JSBool warning;
951
+
952
+ if ((flags & JSREPORT_STRICT) && !JS_HAS_STRICT_OPTION(cx))
953
+ return JS_TRUE;
954
+
955
+ message = JS_vsmprintf(format, ap);
956
+ if (!message)
957
+ return JS_FALSE;
958
+ messagelen = strlen(message);
959
+
960
+ memset(&report, 0, sizeof (struct JSErrorReport));
961
+ report.flags = flags;
962
+ report.errorNumber = JSMSG_USER_DEFINED_ERROR;
963
+ report.ucmessage = ucmessage = js_InflateString(cx, message, &messagelen);
964
+
965
+ /* Find the top-most active script frame, for best line number blame. */
966
+ for (fp = cx->fp; fp; fp = fp->down) {
967
+ if (fp->regs) {
968
+ report.filename = fp->script->filename;
969
+ report.lineno = js_PCToLineNumber(cx, fp->script, fp->regs->pc);
970
+ break;
971
+ }
972
+ }
973
+
974
+ warning = JSREPORT_IS_WARNING(report.flags);
975
+ if (warning && JS_HAS_WERROR_OPTION(cx)) {
976
+ report.flags &= ~JSREPORT_WARNING;
977
+ warning = JS_FALSE;
978
+ }
979
+
980
+ ReportError(cx, message, &report);
981
+ free(message);
982
+ JS_free(cx, ucmessage);
983
+ return warning;
984
+ }
985
+
986
+ /*
987
+ * The arguments from ap need to be packaged up into an array and stored
988
+ * into the report struct.
989
+ *
990
+ * The format string addressed by the error number may contain operands
991
+ * identified by the format {N}, where N is a decimal digit. Each of these
992
+ * is to be replaced by the Nth argument from the va_list. The complete
993
+ * message is placed into reportp->ucmessage converted to a JSString.
994
+ *
995
+ * Returns true if the expansion succeeds (can fail if out of memory).
996
+ */
997
+ JSBool
998
+ js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback,
999
+ void *userRef, const uintN errorNumber,
1000
+ char **messagep, JSErrorReport *reportp,
1001
+ JSBool *warningp, JSBool charArgs, va_list ap)
1002
+ {
1003
+ const JSErrorFormatString *efs;
1004
+ int i;
1005
+ int argCount;
1006
+
1007
+ *warningp = JSREPORT_IS_WARNING(reportp->flags);
1008
+ if (*warningp && JS_HAS_WERROR_OPTION(cx)) {
1009
+ reportp->flags &= ~JSREPORT_WARNING;
1010
+ *warningp = JS_FALSE;
1011
+ }
1012
+
1013
+ *messagep = NULL;
1014
+
1015
+ /* Most calls supply js_GetErrorMessage; if this is so, assume NULL. */
1016
+ if (!callback || callback == js_GetErrorMessage)
1017
+ efs = js_GetLocalizedErrorMessage(cx, userRef, NULL, errorNumber);
1018
+ else
1019
+ efs = callback(userRef, NULL, errorNumber);
1020
+ if (efs) {
1021
+ size_t totalArgsLength = 0;
1022
+ size_t argLengths[10]; /* only {0} thru {9} supported */
1023
+ argCount = efs->argCount;
1024
+ JS_ASSERT(argCount <= 10);
1025
+ if (argCount > 0) {
1026
+ /*
1027
+ * Gather the arguments into an array, and accumulate
1028
+ * their sizes. We allocate 1 more than necessary and
1029
+ * null it out to act as the caboose when we free the
1030
+ * pointers later.
1031
+ */
1032
+ reportp->messageArgs = (const jschar **)
1033
+ JS_malloc(cx, sizeof(jschar *) * (argCount + 1));
1034
+ if (!reportp->messageArgs)
1035
+ return JS_FALSE;
1036
+ reportp->messageArgs[argCount] = NULL;
1037
+ for (i = 0; i < argCount; i++) {
1038
+ if (charArgs) {
1039
+ char *charArg = va_arg(ap, char *);
1040
+ size_t charArgLength = strlen(charArg);
1041
+ reportp->messageArgs[i]
1042
+ = js_InflateString(cx, charArg, &charArgLength);
1043
+ if (!reportp->messageArgs[i])
1044
+ goto error;
1045
+ } else {
1046
+ reportp->messageArgs[i] = va_arg(ap, jschar *);
1047
+ }
1048
+ argLengths[i] = js_strlen(reportp->messageArgs[i]);
1049
+ totalArgsLength += argLengths[i];
1050
+ }
1051
+ /* NULL-terminate for easy copying. */
1052
+ reportp->messageArgs[i] = NULL;
1053
+ }
1054
+ /*
1055
+ * Parse the error format, substituting the argument X
1056
+ * for {X} in the format.
1057
+ */
1058
+ if (argCount > 0) {
1059
+ if (efs->format) {
1060
+ jschar *buffer, *fmt, *out;
1061
+ int expandedArgs = 0;
1062
+ size_t expandedLength;
1063
+ size_t len = strlen(efs->format);
1064
+
1065
+ buffer = fmt = js_InflateString (cx, efs->format, &len);
1066
+ if (!buffer)
1067
+ goto error;
1068
+ expandedLength = len
1069
+ - (3 * argCount) /* exclude the {n} */
1070
+ + totalArgsLength;
1071
+
1072
+ /*
1073
+ * Note - the above calculation assumes that each argument
1074
+ * is used once and only once in the expansion !!!
1075
+ */
1076
+ reportp->ucmessage = out = (jschar *)
1077
+ JS_malloc(cx, (expandedLength + 1) * sizeof(jschar));
1078
+ if (!out) {
1079
+ JS_free (cx, buffer);
1080
+ goto error;
1081
+ }
1082
+ while (*fmt) {
1083
+ if (*fmt == '{') {
1084
+ if (isdigit(fmt[1])) {
1085
+ int d = JS7_UNDEC(fmt[1]);
1086
+ JS_ASSERT(d < argCount);
1087
+ js_strncpy(out, reportp->messageArgs[d],
1088
+ argLengths[d]);
1089
+ out += argLengths[d];
1090
+ fmt += 3;
1091
+ expandedArgs++;
1092
+ continue;
1093
+ }
1094
+ }
1095
+ *out++ = *fmt++;
1096
+ }
1097
+ JS_ASSERT(expandedArgs == argCount);
1098
+ *out = 0;
1099
+ JS_free (cx, buffer);
1100
+ *messagep =
1101
+ js_DeflateString(cx, reportp->ucmessage,
1102
+ (size_t)(out - reportp->ucmessage));
1103
+ if (!*messagep)
1104
+ goto error;
1105
+ }
1106
+ } else {
1107
+ /*
1108
+ * Zero arguments: the format string (if it exists) is the
1109
+ * entire message.
1110
+ */
1111
+ if (efs->format) {
1112
+ size_t len;
1113
+ *messagep = JS_strdup(cx, efs->format);
1114
+ if (!*messagep)
1115
+ goto error;
1116
+ len = strlen(*messagep);
1117
+ reportp->ucmessage = js_InflateString(cx, *messagep, &len);
1118
+ if (!reportp->ucmessage)
1119
+ goto error;
1120
+ }
1121
+ }
1122
+ }
1123
+ if (*messagep == NULL) {
1124
+ /* where's the right place for this ??? */
1125
+ const char *defaultErrorMessage
1126
+ = "No error message available for error number %d";
1127
+ size_t nbytes = strlen(defaultErrorMessage) + 16;
1128
+ *messagep = (char *)JS_malloc(cx, nbytes);
1129
+ if (!*messagep)
1130
+ goto error;
1131
+ JS_snprintf(*messagep, nbytes, defaultErrorMessage, errorNumber);
1132
+ }
1133
+ return JS_TRUE;
1134
+
1135
+ error:
1136
+ if (reportp->messageArgs) {
1137
+ /* free the arguments only if we allocated them */
1138
+ if (charArgs) {
1139
+ i = 0;
1140
+ while (reportp->messageArgs[i])
1141
+ JS_free(cx, (void *)reportp->messageArgs[i++]);
1142
+ }
1143
+ JS_free(cx, (void *)reportp->messageArgs);
1144
+ reportp->messageArgs = NULL;
1145
+ }
1146
+ if (reportp->ucmessage) {
1147
+ JS_free(cx, (void *)reportp->ucmessage);
1148
+ reportp->ucmessage = NULL;
1149
+ }
1150
+ if (*messagep) {
1151
+ JS_free(cx, (void *)*messagep);
1152
+ *messagep = NULL;
1153
+ }
1154
+ return JS_FALSE;
1155
+ }
1156
+
1157
+ JSBool
1158
+ js_ReportErrorNumberVA(JSContext *cx, uintN flags, JSErrorCallback callback,
1159
+ void *userRef, const uintN errorNumber,
1160
+ JSBool charArgs, va_list ap)
1161
+ {
1162
+ JSStackFrame *fp;
1163
+ JSErrorReport report;
1164
+ char *message;
1165
+ JSBool warning;
1166
+
1167
+ if ((flags & JSREPORT_STRICT) && !JS_HAS_STRICT_OPTION(cx))
1168
+ return JS_TRUE;
1169
+
1170
+ memset(&report, 0, sizeof (struct JSErrorReport));
1171
+ report.flags = flags;
1172
+ report.errorNumber = errorNumber;
1173
+
1174
+ /*
1175
+ * If we can't find out where the error was based on the current frame,
1176
+ * see if the next frame has a script/pc combo we can use.
1177
+ */
1178
+ for (fp = cx->fp; fp; fp = fp->down) {
1179
+ if (fp->regs) {
1180
+ report.filename = fp->script->filename;
1181
+ report.lineno = js_PCToLineNumber(cx, fp->script, fp->regs->pc);
1182
+ break;
1183
+ }
1184
+ }
1185
+
1186
+ if (!js_ExpandErrorArguments(cx, callback, userRef, errorNumber,
1187
+ &message, &report, &warning, charArgs, ap)) {
1188
+ return JS_FALSE;
1189
+ }
1190
+
1191
+ ReportError(cx, message, &report);
1192
+
1193
+ if (message)
1194
+ JS_free(cx, message);
1195
+ if (report.messageArgs) {
1196
+ /*
1197
+ * js_ExpandErrorArguments owns its messageArgs only if it had to
1198
+ * inflate the arguments (from regular |char *|s).
1199
+ */
1200
+ if (charArgs) {
1201
+ int i = 0;
1202
+ while (report.messageArgs[i])
1203
+ JS_free(cx, (void *)report.messageArgs[i++]);
1204
+ }
1205
+ JS_free(cx, (void *)report.messageArgs);
1206
+ }
1207
+ if (report.ucmessage)
1208
+ JS_free(cx, (void *)report.ucmessage);
1209
+
1210
+ return warning;
1211
+ }
1212
+
1213
+ JS_FRIEND_API(void)
1214
+ js_ReportErrorAgain(JSContext *cx, const char *message, JSErrorReport *reportp)
1215
+ {
1216
+ JSErrorReporter onError;
1217
+
1218
+ if (!message)
1219
+ return;
1220
+
1221
+ if (cx->lastMessage)
1222
+ free(cx->lastMessage);
1223
+ cx->lastMessage = JS_strdup(cx, message);
1224
+ if (!cx->lastMessage)
1225
+ return;
1226
+ onError = cx->errorReporter;
1227
+
1228
+ /*
1229
+ * If debugErrorHook is present then we give it a chance to veto
1230
+ * sending the error on to the regular ErrorReporter.
1231
+ */
1232
+ if (onError) {
1233
+ JSDebugErrorHook hook = cx->debugHooks->debugErrorHook;
1234
+ if (hook &&
1235
+ !hook(cx, cx->lastMessage, reportp,
1236
+ cx->debugHooks->debugErrorHookData)) {
1237
+ onError = NULL;
1238
+ }
1239
+ }
1240
+ if (onError)
1241
+ onError(cx, cx->lastMessage, reportp);
1242
+ }
1243
+
1244
+ void
1245
+ js_ReportIsNotDefined(JSContext *cx, const char *name)
1246
+ {
1247
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_DEFINED, name);
1248
+ }
1249
+
1250
+ JSBool
1251
+ js_ReportIsNullOrUndefined(JSContext *cx, intN spindex, jsval v,
1252
+ JSString *fallback)
1253
+ {
1254
+ char *bytes;
1255
+ JSBool ok;
1256
+
1257
+ bytes = js_DecompileValueGenerator(cx, spindex, v, fallback);
1258
+ if (!bytes)
1259
+ return JS_FALSE;
1260
+
1261
+ if (strcmp(bytes, js_undefined_str) == 0 ||
1262
+ strcmp(bytes, js_null_str) == 0) {
1263
+ ok = JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR,
1264
+ js_GetErrorMessage, NULL,
1265
+ JSMSG_NO_PROPERTIES, bytes,
1266
+ NULL, NULL);
1267
+ } else if (JSVAL_IS_VOID(v)) {
1268
+ ok = JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR,
1269
+ js_GetErrorMessage, NULL,
1270
+ JSMSG_NULL_OR_UNDEFINED, bytes,
1271
+ js_undefined_str, NULL);
1272
+ } else {
1273
+ JS_ASSERT(JSVAL_IS_NULL(v));
1274
+ ok = JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR,
1275
+ js_GetErrorMessage, NULL,
1276
+ JSMSG_NULL_OR_UNDEFINED, bytes,
1277
+ js_null_str, NULL);
1278
+ }
1279
+
1280
+ JS_free(cx, bytes);
1281
+ return ok;
1282
+ }
1283
+
1284
+ JSBool
1285
+ js_ReportValueErrorFlags(JSContext *cx, uintN flags, const uintN errorNumber,
1286
+ intN spindex, jsval v, JSString *fallback,
1287
+ const char *arg1, const char *arg2)
1288
+ {
1289
+ char *bytes;
1290
+ JSBool ok;
1291
+
1292
+ JS_ASSERT(js_ErrorFormatString[errorNumber].argCount >= 1);
1293
+ JS_ASSERT(js_ErrorFormatString[errorNumber].argCount <= 3);
1294
+ bytes = js_DecompileValueGenerator(cx, spindex, v, fallback);
1295
+ if (!bytes)
1296
+ return JS_FALSE;
1297
+
1298
+ ok = JS_ReportErrorFlagsAndNumber(cx, flags, js_GetErrorMessage,
1299
+ NULL, errorNumber, bytes, arg1, arg2);
1300
+ JS_free(cx, bytes);
1301
+ return ok;
1302
+ }
1303
+
1304
+ #if defined DEBUG && defined XP_UNIX
1305
+ /* For gdb usage. */
1306
+ void js_traceon(JSContext *cx) { cx->tracefp = stderr; }
1307
+ void js_traceoff(JSContext *cx) { cx->tracefp = NULL; }
1308
+ #endif
1309
+
1310
+ JSErrorFormatString js_ErrorFormatString[JSErr_Limit] = {
1311
+ #define MSG_DEF(name, number, count, exception, format) \
1312
+ { format, count, exception } ,
1313
+ #include "js.msg"
1314
+ #undef MSG_DEF
1315
+ };
1316
+
1317
+ const JSErrorFormatString *
1318
+ js_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber)
1319
+ {
1320
+ if ((errorNumber > 0) && (errorNumber < JSErr_Limit))
1321
+ return &js_ErrorFormatString[errorNumber];
1322
+ return NULL;
1323
+ }
1324
+
1325
+ JSBool
1326
+ js_ResetOperationCount(JSContext *cx)
1327
+ {
1328
+ JSScript *script;
1329
+
1330
+ JS_ASSERT(cx->operationCount <= 0);
1331
+ JS_ASSERT(cx->operationLimit > 0);
1332
+
1333
+ cx->operationCount = (int32) cx->operationLimit;
1334
+ if (cx->operationCallbackIsSet)
1335
+ return cx->operationCallback(cx);
1336
+
1337
+ if (cx->operationCallback) {
1338
+ /*
1339
+ * Invoke the deprecated branch callback. It may be called only when
1340
+ * the top-most frame is scripted or JSOPTION_NATIVE_BRANCH_CALLBACK
1341
+ * is set.
1342
+ */
1343
+ script = cx->fp ? cx->fp->script : NULL;
1344
+ if (script || JS_HAS_OPTION(cx, JSOPTION_NATIVE_BRANCH_CALLBACK))
1345
+ return ((JSBranchCallback) cx->operationCallback)(cx, script);
1346
+ }
1347
+ return JS_TRUE;
1348
+ }