distil 0.7.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 (552) hide show
  1. data/Rakefile +28 -0
  2. data/VERSION +1 -0
  3. data/bin/distil +45 -0
  4. data/distil.gemspec +586 -0
  5. data/lib/bootstrap-template.js +56 -0
  6. data/lib/configurable.rb +125 -0
  7. data/lib/file-set.rb +42 -0
  8. data/lib/file-types/css-file.rb +75 -0
  9. data/lib/file-types/html-file.rb +11 -0
  10. data/lib/file-types/javascript-file.rb +98 -0
  11. data/lib/file-types/json-file.rb +14 -0
  12. data/lib/file-types/nib-file.rb +9 -0
  13. data/lib/jsdoc.conf +18 -0
  14. data/lib/jsl.conf +121 -0
  15. data/lib/project.rb +96 -0
  16. data/lib/source-file.rb +181 -0
  17. data/lib/target.rb +96 -0
  18. data/lib/task.rb +239 -0
  19. data/lib/tasks/copy-task.rb +21 -0
  20. data/lib/tasks/css-task.rb +18 -0
  21. data/lib/tasks/javascript-task.rb +125 -0
  22. data/lib/tasks/multiple-output-task.rb +134 -0
  23. data/lib/tasks/nib-task.rb +83 -0
  24. data/lib/tasks/output-task.rb +73 -0
  25. data/lib/tasks/single-output-task.rb +83 -0
  26. data/lib/tasks/test-task.rb +280 -0
  27. data/lib/test/HtmlTestReporter.js +127 -0
  28. data/lib/test/Test.js +248 -0
  29. data/lib/test/TestReporter.js +79 -0
  30. data/lib/test/TestRunner.js +132 -0
  31. data/lib/test/browser.rb +97 -0
  32. data/lib/test/scriptwrapper.html +10 -0
  33. data/lib/test/unittest.html +127 -0
  34. data/vendor/Makefile +35 -0
  35. data/vendor/extconf.rb +3 -0
  36. data/vendor/jsdoc-extras/plugins/distil-plugin.js +142 -0
  37. data/vendor/jsdoc-extras/plugins/interface-plugin.js +36 -0
  38. data/vendor/jsdoc-extras/templates/coherent/allclasses.tmpl +17 -0
  39. data/vendor/jsdoc-extras/templates/coherent/allfiles.tmpl +53 -0
  40. data/vendor/jsdoc-extras/templates/coherent/class.tmpl +803 -0
  41. data/vendor/jsdoc-extras/templates/coherent/index.tmpl +37 -0
  42. data/vendor/jsdoc-extras/templates/coherent/publish.js +242 -0
  43. data/vendor/jsdoc-extras/templates/coherent/showdown.js +421 -0
  44. data/vendor/jsdoc-extras/templates/coherent/static/code-footer.html +3 -0
  45. data/vendor/jsdoc-extras/templates/coherent/static/code-header.html +7 -0
  46. data/vendor/jsdoc-extras/templates/coherent/static/default.css +297 -0
  47. data/vendor/jsdoc-extras/templates/coherent/static/header.html +2 -0
  48. data/vendor/jsdoc-extras/templates/coherent/static/index.html +19 -0
  49. data/vendor/jsdoc-extras/templates/coherent/symbol.tmpl +35 -0
  50. data/vendor/jsdoc-toolkit/README.txt +183 -0
  51. data/vendor/jsdoc-toolkit/app/frame/Chain.js +102 -0
  52. data/vendor/jsdoc-toolkit/app/frame/Dumper.js +144 -0
  53. data/vendor/jsdoc-toolkit/app/frame/Hash.js +84 -0
  54. data/vendor/jsdoc-toolkit/app/frame/Link.js +171 -0
  55. data/vendor/jsdoc-toolkit/app/frame/Namespace.js +10 -0
  56. data/vendor/jsdoc-toolkit/app/frame/Opt.js +134 -0
  57. data/vendor/jsdoc-toolkit/app/frame/Reflection.js +26 -0
  58. data/vendor/jsdoc-toolkit/app/frame/String.js +93 -0
  59. data/vendor/jsdoc-toolkit/app/frame/Testrun.js +129 -0
  60. data/vendor/jsdoc-toolkit/app/frame.js +33 -0
  61. data/vendor/jsdoc-toolkit/app/handlers/FOODOC.js +26 -0
  62. data/vendor/jsdoc-toolkit/app/handlers/XMLDOC/DomReader.js +159 -0
  63. data/vendor/jsdoc-toolkit/app/handlers/XMLDOC/XMLDoc.js +16 -0
  64. data/vendor/jsdoc-toolkit/app/handlers/XMLDOC/XMLParse.js +292 -0
  65. data/vendor/jsdoc-toolkit/app/handlers/XMLDOC.js +26 -0
  66. data/vendor/jsdoc-toolkit/app/lib/JSDOC/DocComment.js +204 -0
  67. data/vendor/jsdoc-toolkit/app/lib/JSDOC/DocTag.js +300 -0
  68. data/vendor/jsdoc-toolkit/app/lib/JSDOC/JsDoc.js +126 -0
  69. data/vendor/jsdoc-toolkit/app/lib/JSDOC/JsPlate.js +109 -0
  70. data/vendor/jsdoc-toolkit/app/lib/JSDOC/Lang.js +144 -0
  71. data/vendor/jsdoc-toolkit/app/lib/JSDOC/Parser.js +144 -0
  72. data/vendor/jsdoc-toolkit/app/lib/JSDOC/PluginManager.js +33 -0
  73. data/vendor/jsdoc-toolkit/app/lib/JSDOC/Symbol.js +644 -0
  74. data/vendor/jsdoc-toolkit/app/lib/JSDOC/SymbolSet.js +241 -0
  75. data/vendor/jsdoc-toolkit/app/lib/JSDOC/TextStream.js +41 -0
  76. data/vendor/jsdoc-toolkit/app/lib/JSDOC/Token.js +18 -0
  77. data/vendor/jsdoc-toolkit/app/lib/JSDOC/TokenReader.js +332 -0
  78. data/vendor/jsdoc-toolkit/app/lib/JSDOC/TokenStream.js +133 -0
  79. data/vendor/jsdoc-toolkit/app/lib/JSDOC/Util.js +32 -0
  80. data/vendor/jsdoc-toolkit/app/lib/JSDOC/Walker.js +499 -0
  81. data/vendor/jsdoc-toolkit/app/lib/JSDOC.js +106 -0
  82. data/vendor/jsdoc-toolkit/app/main.js +129 -0
  83. data/vendor/jsdoc-toolkit/app/plugins/commentSrcJson.js +20 -0
  84. data/vendor/jsdoc-toolkit/app/plugins/frameworkPrototype.js +16 -0
  85. data/vendor/jsdoc-toolkit/app/plugins/functionCall.js +10 -0
  86. data/vendor/jsdoc-toolkit/app/plugins/publishSrcHilite.js +54 -0
  87. data/vendor/jsdoc-toolkit/app/plugins/symbolLink.js +10 -0
  88. data/vendor/jsdoc-toolkit/app/plugins/tagParamConfig.js +31 -0
  89. data/vendor/jsdoc-toolkit/app/plugins/tagSynonyms.js +43 -0
  90. data/vendor/jsdoc-toolkit/app/run.js +348 -0
  91. data/vendor/jsdoc-toolkit/app/t/TestDoc.js +144 -0
  92. data/vendor/jsdoc-toolkit/app/t/runner.js +13 -0
  93. data/vendor/jsdoc-toolkit/app/test/addon.js +24 -0
  94. data/vendor/jsdoc-toolkit/app/test/anon_inner.js +14 -0
  95. data/vendor/jsdoc-toolkit/app/test/augments.js +31 -0
  96. data/vendor/jsdoc-toolkit/app/test/augments2.js +26 -0
  97. data/vendor/jsdoc-toolkit/app/test/borrows.js +46 -0
  98. data/vendor/jsdoc-toolkit/app/test/borrows2.js +23 -0
  99. data/vendor/jsdoc-toolkit/app/test/config.js +22 -0
  100. data/vendor/jsdoc-toolkit/app/test/constructs.js +18 -0
  101. data/vendor/jsdoc-toolkit/app/test/encoding.js +10 -0
  102. data/vendor/jsdoc-toolkit/app/test/encoding_other.js +12 -0
  103. data/vendor/jsdoc-toolkit/app/test/event.js +54 -0
  104. data/vendor/jsdoc-toolkit/app/test/exports.js +14 -0
  105. data/vendor/jsdoc-toolkit/app/test/functions_anon.js +39 -0
  106. data/vendor/jsdoc-toolkit/app/test/functions_nested.js +33 -0
  107. data/vendor/jsdoc-toolkit/app/test/global.js +13 -0
  108. data/vendor/jsdoc-toolkit/app/test/globals.js +25 -0
  109. data/vendor/jsdoc-toolkit/app/test/ignore.js +10 -0
  110. data/vendor/jsdoc-toolkit/app/test/inner.js +16 -0
  111. data/vendor/jsdoc-toolkit/app/test/jsdoc_test.js +477 -0
  112. data/vendor/jsdoc-toolkit/app/test/lend.js +33 -0
  113. data/vendor/jsdoc-toolkit/app/test/memberof.js +19 -0
  114. data/vendor/jsdoc-toolkit/app/test/memberof2.js +38 -0
  115. data/vendor/jsdoc-toolkit/app/test/memberof3.js +33 -0
  116. data/vendor/jsdoc-toolkit/app/test/memberof_constructor.js +17 -0
  117. data/vendor/jsdoc-toolkit/app/test/module.js +17 -0
  118. data/vendor/jsdoc-toolkit/app/test/name.js +19 -0
  119. data/vendor/jsdoc-toolkit/app/test/namespace_nested.js +23 -0
  120. data/vendor/jsdoc-toolkit/app/test/nocode.js +13 -0
  121. data/vendor/jsdoc-toolkit/app/test/oblit_anon.js +20 -0
  122. data/vendor/jsdoc-toolkit/app/test/overview.js +20 -0
  123. data/vendor/jsdoc-toolkit/app/test/param_inline.js +37 -0
  124. data/vendor/jsdoc-toolkit/app/test/params_optional.js +8 -0
  125. data/vendor/jsdoc-toolkit/app/test/prototype.js +17 -0
  126. data/vendor/jsdoc-toolkit/app/test/prototype_nested.js +9 -0
  127. data/vendor/jsdoc-toolkit/app/test/prototype_oblit.js +13 -0
  128. data/vendor/jsdoc-toolkit/app/test/prototype_oblit_constructor.js +24 -0
  129. data/vendor/jsdoc-toolkit/app/test/public.js +10 -0
  130. data/vendor/jsdoc-toolkit/app/test/scripts/code.js +5 -0
  131. data/vendor/jsdoc-toolkit/app/test/scripts/notcode.txt +5 -0
  132. data/vendor/jsdoc-toolkit/app/test/shared.js +42 -0
  133. data/vendor/jsdoc-toolkit/app/test/shared2.js +2 -0
  134. data/vendor/jsdoc-toolkit/app/test/shortcuts.js +22 -0
  135. data/vendor/jsdoc-toolkit/app/test/static_this.js +13 -0
  136. data/vendor/jsdoc-toolkit/app/test/synonyms.js +31 -0
  137. data/vendor/jsdoc-toolkit/app/test/tosource.js +23 -0
  138. data/vendor/jsdoc-toolkit/app/test/variable_redefine.js +14 -0
  139. data/vendor/jsdoc-toolkit/app/test.js +342 -0
  140. data/vendor/jsdoc-toolkit/changes.txt +116 -0
  141. data/vendor/jsdoc-toolkit/conf/sample.conf +31 -0
  142. data/vendor/jsdoc-toolkit/java/build.xml +36 -0
  143. data/vendor/jsdoc-toolkit/java/build_1.4.xml +36 -0
  144. data/vendor/jsdoc-toolkit/java/classes/js.jar +0 -0
  145. data/vendor/jsdoc-toolkit/java/src/JsDebugRun.java +21 -0
  146. data/vendor/jsdoc-toolkit/java/src/JsRun.java +21 -0
  147. data/vendor/jsdoc-toolkit/jsdebug.jar +0 -0
  148. data/vendor/jsdoc-toolkit/jsrun.jar +0 -0
  149. data/vendor/jsdoc-toolkit/jsrun.sh +53 -0
  150. data/vendor/jsdoc-toolkit/templates/jsdoc/allclasses.tmpl +17 -0
  151. data/vendor/jsdoc-toolkit/templates/jsdoc/allfiles.tmpl +56 -0
  152. data/vendor/jsdoc-toolkit/templates/jsdoc/class.tmpl +649 -0
  153. data/vendor/jsdoc-toolkit/templates/jsdoc/index.tmpl +39 -0
  154. data/vendor/jsdoc-toolkit/templates/jsdoc/publish.js +201 -0
  155. data/vendor/jsdoc-toolkit/templates/jsdoc/static/code-footer.html +3 -0
  156. data/vendor/jsdoc-toolkit/templates/jsdoc/static/code-header.html +14 -0
  157. data/vendor/jsdoc-toolkit/templates/jsdoc/static/default.css +162 -0
  158. data/vendor/jsdoc-toolkit/templates/jsdoc/static/header.html +2 -0
  159. data/vendor/jsdoc-toolkit/templates/jsdoc/static/index.html +19 -0
  160. data/vendor/jsdoc-toolkit/templates/jsdoc/symbol.tmpl +35 -0
  161. data/vendor/jsl-0.3.0/src/JavaScriptLintAPI.cpp +333 -0
  162. data/vendor/jsl-0.3.0/src/JavaScriptLintAPI.h +86 -0
  163. data/vendor/jsl-0.3.0/src/Makefile.in +375 -0
  164. data/vendor/jsl-0.3.0/src/Makefile.ref +372 -0
  165. data/vendor/jsl-0.3.0/src/README.html +826 -0
  166. data/vendor/jsl-0.3.0/src/SpiderMonkey.rsp +12 -0
  167. data/vendor/jsl-0.3.0/src/_jsl_online.php +223 -0
  168. data/vendor/jsl-0.3.0/src/config/AIX4.1.mk +65 -0
  169. data/vendor/jsl-0.3.0/src/config/AIX4.2.mk +64 -0
  170. data/vendor/jsl-0.3.0/src/config/AIX4.3.mk +65 -0
  171. data/vendor/jsl-0.3.0/src/config/Darwin.mk +81 -0
  172. data/vendor/jsl-0.3.0/src/config/Darwin1.3.mk +81 -0
  173. data/vendor/jsl-0.3.0/src/config/Darwin1.4.mk +41 -0
  174. data/vendor/jsl-0.3.0/src/config/Darwin5.2.mk +81 -0
  175. data/vendor/jsl-0.3.0/src/config/Darwin5.3.mk +81 -0
  176. data/vendor/jsl-0.3.0/src/config/HP-UXB.10.10.mk +77 -0
  177. data/vendor/jsl-0.3.0/src/config/HP-UXB.10.20.mk +77 -0
  178. data/vendor/jsl-0.3.0/src/config/HP-UXB.11.00.mk +80 -0
  179. data/vendor/jsl-0.3.0/src/config/IRIX.mk +87 -0
  180. data/vendor/jsl-0.3.0/src/config/IRIX5.3.mk +44 -0
  181. data/vendor/jsl-0.3.0/src/config/IRIX6.1.mk +44 -0
  182. data/vendor/jsl-0.3.0/src/config/IRIX6.2.mk +44 -0
  183. data/vendor/jsl-0.3.0/src/config/IRIX6.3.mk +44 -0
  184. data/vendor/jsl-0.3.0/src/config/IRIX6.5.mk +44 -0
  185. data/vendor/jsl-0.3.0/src/config/Linux_All.mk +103 -0
  186. data/vendor/jsl-0.3.0/src/config/Mac_OS10.0.mk +82 -0
  187. data/vendor/jsl-0.3.0/src/config/OSF1V4.0.mk +72 -0
  188. data/vendor/jsl-0.3.0/src/config/OSF1V5.0.mk +69 -0
  189. data/vendor/jsl-0.3.0/src/config/SunOS4.1.4.mk +101 -0
  190. data/vendor/jsl-0.3.0/src/config/SunOS5.3.mk +91 -0
  191. data/vendor/jsl-0.3.0/src/config/SunOS5.4.mk +92 -0
  192. data/vendor/jsl-0.3.0/src/config/SunOS5.5.1.mk +44 -0
  193. data/vendor/jsl-0.3.0/src/config/SunOS5.5.mk +87 -0
  194. data/vendor/jsl-0.3.0/src/config/SunOS5.6.mk +89 -0
  195. data/vendor/jsl-0.3.0/src/config/SunOS5.7.mk +44 -0
  196. data/vendor/jsl-0.3.0/src/config/SunOS5.8.mk +44 -0
  197. data/vendor/jsl-0.3.0/src/config/SunOS5.9.mk +44 -0
  198. data/vendor/jsl-0.3.0/src/config/WINNT4.0.mk +112 -0
  199. data/vendor/jsl-0.3.0/src/config/WINNT5.0.mk +112 -0
  200. data/vendor/jsl-0.3.0/src/config/WINNT5.1.mk +112 -0
  201. data/vendor/jsl-0.3.0/src/config/WINNT5.2.mk +112 -0
  202. data/vendor/jsl-0.3.0/src/config/dgux.mk +64 -0
  203. data/vendor/jsl-0.3.0/src/config.mk +166 -0
  204. data/vendor/jsl-0.3.0/src/editline/Makefile.ref +144 -0
  205. data/vendor/jsl-0.3.0/src/editline/README +83 -0
  206. data/vendor/jsl-0.3.0/src/editline/editline.3 +175 -0
  207. data/vendor/jsl-0.3.0/src/editline/editline.c +1369 -0
  208. data/vendor/jsl-0.3.0/src/editline/editline.h +135 -0
  209. data/vendor/jsl-0.3.0/src/editline/sysunix.c +182 -0
  210. data/vendor/jsl-0.3.0/src/editline/unix.h +82 -0
  211. data/vendor/jsl-0.3.0/src/fdlibm/Makefile.in +127 -0
  212. data/vendor/jsl-0.3.0/src/fdlibm/Makefile.ref +192 -0
  213. data/vendor/jsl-0.3.0/src/fdlibm/e_acos.c +147 -0
  214. data/vendor/jsl-0.3.0/src/fdlibm/e_acosh.c +105 -0
  215. data/vendor/jsl-0.3.0/src/fdlibm/e_asin.c +156 -0
  216. data/vendor/jsl-0.3.0/src/fdlibm/e_atan2.c +165 -0
  217. data/vendor/jsl-0.3.0/src/fdlibm/e_atanh.c +110 -0
  218. data/vendor/jsl-0.3.0/src/fdlibm/e_cosh.c +133 -0
  219. data/vendor/jsl-0.3.0/src/fdlibm/e_exp.c +202 -0
  220. data/vendor/jsl-0.3.0/src/fdlibm/e_fmod.c +184 -0
  221. data/vendor/jsl-0.3.0/src/fdlibm/e_gamma.c +71 -0
  222. data/vendor/jsl-0.3.0/src/fdlibm/e_gamma_r.c +70 -0
  223. data/vendor/jsl-0.3.0/src/fdlibm/e_hypot.c +173 -0
  224. data/vendor/jsl-0.3.0/src/fdlibm/e_j0.c +524 -0
  225. data/vendor/jsl-0.3.0/src/fdlibm/e_j1.c +523 -0
  226. data/vendor/jsl-0.3.0/src/fdlibm/e_jn.c +315 -0
  227. data/vendor/jsl-0.3.0/src/fdlibm/e_lgamma.c +71 -0
  228. data/vendor/jsl-0.3.0/src/fdlibm/e_lgamma_r.c +347 -0
  229. data/vendor/jsl-0.3.0/src/fdlibm/e_log.c +184 -0
  230. data/vendor/jsl-0.3.0/src/fdlibm/e_log10.c +134 -0
  231. data/vendor/jsl-0.3.0/src/fdlibm/e_pow.c +386 -0
  232. data/vendor/jsl-0.3.0/src/fdlibm/e_rem_pio2.c +221 -0
  233. data/vendor/jsl-0.3.0/src/fdlibm/e_remainder.c +120 -0
  234. data/vendor/jsl-0.3.0/src/fdlibm/e_scalb.c +89 -0
  235. data/vendor/jsl-0.3.0/src/fdlibm/e_sinh.c +122 -0
  236. data/vendor/jsl-0.3.0/src/fdlibm/e_sqrt.c +497 -0
  237. data/vendor/jsl-0.3.0/src/fdlibm/fdlibm.dsp +160 -0
  238. data/vendor/jsl-0.3.0/src/fdlibm/fdlibm.h +273 -0
  239. data/vendor/jsl-0.3.0/src/fdlibm/fdlibm.mak +1453 -0
  240. data/vendor/jsl-0.3.0/src/fdlibm/fdlibm.mdp +0 -0
  241. data/vendor/jsl-0.3.0/src/fdlibm/k_cos.c +134 -0
  242. data/vendor/jsl-0.3.0/src/fdlibm/k_rem_pio2.c +354 -0
  243. data/vendor/jsl-0.3.0/src/fdlibm/k_sin.c +114 -0
  244. data/vendor/jsl-0.3.0/src/fdlibm/k_standard.c +785 -0
  245. data/vendor/jsl-0.3.0/src/fdlibm/k_tan.c +170 -0
  246. data/vendor/jsl-0.3.0/src/fdlibm/s_asinh.c +101 -0
  247. data/vendor/jsl-0.3.0/src/fdlibm/s_atan.c +175 -0
  248. data/vendor/jsl-0.3.0/src/fdlibm/s_cbrt.c +133 -0
  249. data/vendor/jsl-0.3.0/src/fdlibm/s_ceil.c +120 -0
  250. data/vendor/jsl-0.3.0/src/fdlibm/s_copysign.c +72 -0
  251. data/vendor/jsl-0.3.0/src/fdlibm/s_cos.c +118 -0
  252. data/vendor/jsl-0.3.0/src/fdlibm/s_erf.c +356 -0
  253. data/vendor/jsl-0.3.0/src/fdlibm/s_expm1.c +267 -0
  254. data/vendor/jsl-0.3.0/src/fdlibm/s_fabs.c +70 -0
  255. data/vendor/jsl-0.3.0/src/fdlibm/s_finite.c +71 -0
  256. data/vendor/jsl-0.3.0/src/fdlibm/s_floor.c +121 -0
  257. data/vendor/jsl-0.3.0/src/fdlibm/s_frexp.c +99 -0
  258. data/vendor/jsl-0.3.0/src/fdlibm/s_ilogb.c +85 -0
  259. data/vendor/jsl-0.3.0/src/fdlibm/s_isnan.c +74 -0
  260. data/vendor/jsl-0.3.0/src/fdlibm/s_ldexp.c +66 -0
  261. data/vendor/jsl-0.3.0/src/fdlibm/s_lib_version.c +73 -0
  262. data/vendor/jsl-0.3.0/src/fdlibm/s_log1p.c +211 -0
  263. data/vendor/jsl-0.3.0/src/fdlibm/s_logb.c +79 -0
  264. data/vendor/jsl-0.3.0/src/fdlibm/s_matherr.c +64 -0
  265. data/vendor/jsl-0.3.0/src/fdlibm/s_modf.c +132 -0
  266. data/vendor/jsl-0.3.0/src/fdlibm/s_nextafter.c +124 -0
  267. data/vendor/jsl-0.3.0/src/fdlibm/s_rint.c +131 -0
  268. data/vendor/jsl-0.3.0/src/fdlibm/s_scalbn.c +107 -0
  269. data/vendor/jsl-0.3.0/src/fdlibm/s_signgam.c +40 -0
  270. data/vendor/jsl-0.3.0/src/fdlibm/s_significand.c +68 -0
  271. data/vendor/jsl-0.3.0/src/fdlibm/s_sin.c +118 -0
  272. data/vendor/jsl-0.3.0/src/fdlibm/s_tan.c +112 -0
  273. data/vendor/jsl-0.3.0/src/fdlibm/s_tanh.c +122 -0
  274. data/vendor/jsl-0.3.0/src/fdlibm/w_acos.c +78 -0
  275. data/vendor/jsl-0.3.0/src/fdlibm/w_acosh.c +78 -0
  276. data/vendor/jsl-0.3.0/src/fdlibm/w_asin.c +80 -0
  277. data/vendor/jsl-0.3.0/src/fdlibm/w_atan2.c +79 -0
  278. data/vendor/jsl-0.3.0/src/fdlibm/w_atanh.c +81 -0
  279. data/vendor/jsl-0.3.0/src/fdlibm/w_cosh.c +77 -0
  280. data/vendor/jsl-0.3.0/src/fdlibm/w_exp.c +88 -0
  281. data/vendor/jsl-0.3.0/src/fdlibm/w_fmod.c +78 -0
  282. data/vendor/jsl-0.3.0/src/fdlibm/w_gamma.c +85 -0
  283. data/vendor/jsl-0.3.0/src/fdlibm/w_gamma_r.c +81 -0
  284. data/vendor/jsl-0.3.0/src/fdlibm/w_hypot.c +78 -0
  285. data/vendor/jsl-0.3.0/src/fdlibm/w_j0.c +105 -0
  286. data/vendor/jsl-0.3.0/src/fdlibm/w_j1.c +106 -0
  287. data/vendor/jsl-0.3.0/src/fdlibm/w_jn.c +128 -0
  288. data/vendor/jsl-0.3.0/src/fdlibm/w_lgamma.c +85 -0
  289. data/vendor/jsl-0.3.0/src/fdlibm/w_lgamma_r.c +81 -0
  290. data/vendor/jsl-0.3.0/src/fdlibm/w_log.c +78 -0
  291. data/vendor/jsl-0.3.0/src/fdlibm/w_log10.c +81 -0
  292. data/vendor/jsl-0.3.0/src/fdlibm/w_pow.c +99 -0
  293. data/vendor/jsl-0.3.0/src/fdlibm/w_remainder.c +77 -0
  294. data/vendor/jsl-0.3.0/src/fdlibm/w_scalb.c +95 -0
  295. data/vendor/jsl-0.3.0/src/fdlibm/w_sinh.c +77 -0
  296. data/vendor/jsl-0.3.0/src/fdlibm/w_sqrt.c +77 -0
  297. data/vendor/jsl-0.3.0/src/js.c +2447 -0
  298. data/vendor/jsl-0.3.0/src/js.dsp +420 -0
  299. data/vendor/jsl-0.3.0/src/js.mak +4025 -0
  300. data/vendor/jsl-0.3.0/src/js.mdp +0 -0
  301. data/vendor/jsl-0.3.0/src/js.msg +291 -0
  302. data/vendor/jsl-0.3.0/src/js.pkg +2 -0
  303. data/vendor/jsl-0.3.0/src/js3240.rc +79 -0
  304. data/vendor/jsl-0.3.0/src/jsOS240.def +654 -0
  305. data/vendor/jsl-0.3.0/src/jsapi.c +4405 -0
  306. data/vendor/jsl-0.3.0/src/jsapi.h +1856 -0
  307. data/vendor/jsl-0.3.0/src/jsarena.c +567 -0
  308. data/vendor/jsl-0.3.0/src/jsarena.h +302 -0
  309. data/vendor/jsl-0.3.0/src/jsarray.c +1428 -0
  310. data/vendor/jsl-0.3.0/src/jsarray.h +77 -0
  311. data/vendor/jsl-0.3.0/src/jsatom.c +927 -0
  312. data/vendor/jsl-0.3.0/src/jsatom.h +426 -0
  313. data/vendor/jsl-0.3.0/src/jsbit.h +113 -0
  314. data/vendor/jsl-0.3.0/src/jsbool.c +220 -0
  315. data/vendor/jsl-0.3.0/src/jsbool.h +62 -0
  316. data/vendor/jsl-0.3.0/src/jsclist.h +139 -0
  317. data/vendor/jsl-0.3.0/src/jscntxt.c +1036 -0
  318. data/vendor/jsl-0.3.0/src/jscntxt.h +608 -0
  319. data/vendor/jsl-0.3.0/src/jscompat.h +57 -0
  320. data/vendor/jsl-0.3.0/src/jsconfig.h +489 -0
  321. data/vendor/jsl-0.3.0/src/jsconfig.mk +181 -0
  322. data/vendor/jsl-0.3.0/src/jscpucfg.c +377 -0
  323. data/vendor/jsl-0.3.0/src/jscpucfg.h +204 -0
  324. data/vendor/jsl-0.3.0/src/jsdate.c +2238 -0
  325. data/vendor/jsl-0.3.0/src/jsdate.h +118 -0
  326. data/vendor/jsl-0.3.0/src/jsdbgapi.c +1260 -0
  327. data/vendor/jsl-0.3.0/src/jsdbgapi.h +345 -0
  328. data/vendor/jsl-0.3.0/src/jsdhash.c +763 -0
  329. data/vendor/jsl-0.3.0/src/jsdhash.h +579 -0
  330. data/vendor/jsl-0.3.0/src/jsdtoa.c +3135 -0
  331. data/vendor/jsl-0.3.0/src/jsdtoa.h +130 -0
  332. data/vendor/jsl-0.3.0/src/jsemit.c +4851 -0
  333. data/vendor/jsl-0.3.0/src/jsemit.h +576 -0
  334. data/vendor/jsl-0.3.0/src/jsexn.c +1084 -0
  335. data/vendor/jsl-0.3.0/src/jsexn.h +102 -0
  336. data/vendor/jsl-0.3.0/src/jsfile.c +2610 -0
  337. data/vendor/jsl-0.3.0/src/jsfile.h +50 -0
  338. data/vendor/jsl-0.3.0/src/jsfile.msg +89 -0
  339. data/vendor/jsl-0.3.0/src/jsfun.c +2015 -0
  340. data/vendor/jsl-0.3.0/src/jsfun.h +158 -0
  341. data/vendor/jsl-0.3.0/src/jsgc.c +1441 -0
  342. data/vendor/jsl-0.3.0/src/jsgc.h +230 -0
  343. data/vendor/jsl-0.3.0/src/jshash.c +471 -0
  344. data/vendor/jsl-0.3.0/src/jshash.h +152 -0
  345. data/vendor/jsl-0.3.0/src/jsify.pl +485 -0
  346. data/vendor/jsl-0.3.0/src/jsinterp.c +4797 -0
  347. data/vendor/jsl-0.3.0/src/jsinterp.h +302 -0
  348. data/vendor/jsl-0.3.0/src/jsl-test.js +28 -0
  349. data/vendor/jsl-0.3.0/src/jsl.c +2371 -0
  350. data/vendor/jsl-0.3.0/src/jsl.conf +127 -0
  351. data/vendor/jsl-0.3.0/src/jsl.conf.old +124 -0
  352. data/vendor/jsl-0.3.0/src/jsl.dsp +242 -0
  353. data/vendor/jsl-0.3.0/src/jsl.dsw +59 -0
  354. data/vendor/jsl-0.3.0/src/jslibmath.h +290 -0
  355. data/vendor/jsl-0.3.0/src/jslock.c +1261 -0
  356. data/vendor/jsl-0.3.0/src/jslock.h +289 -0
  357. data/vendor/jsl-0.3.0/src/jslocko.asm +59 -0
  358. data/vendor/jsl-0.3.0/src/jslog2.c +83 -0
  359. data/vendor/jsl-0.3.0/src/jslong.c +281 -0
  360. data/vendor/jsl-0.3.0/src/jslong.h +437 -0
  361. data/vendor/jsl-0.3.0/src/jsmath.c +477 -0
  362. data/vendor/jsl-0.3.0/src/jsmath.h +55 -0
  363. data/vendor/jsl-0.3.0/src/jsnum.c +1148 -0
  364. data/vendor/jsl-0.3.0/src/jsnum.h +257 -0
  365. data/vendor/jsl-0.3.0/src/jsobj.c +4066 -0
  366. data/vendor/jsl-0.3.0/src/jsobj.h +475 -0
  367. data/vendor/jsl-0.3.0/src/jsopcode.c +2730 -0
  368. data/vendor/jsl-0.3.0/src/jsopcode.h +275 -0
  369. data/vendor/jsl-0.3.0/src/jsopcode.tbl +344 -0
  370. data/vendor/jsl-0.3.0/src/jsosdep.h +127 -0
  371. data/vendor/jsl-0.3.0/src/jsotypes.h +211 -0
  372. data/vendor/jsl-0.3.0/src/jsparse.c +4438 -0
  373. data/vendor/jsl-0.3.0/src/jsparse.h +345 -0
  374. data/vendor/jsl-0.3.0/src/jsprf.c +1212 -0
  375. data/vendor/jsl-0.3.0/src/jsprf.h +148 -0
  376. data/vendor/jsl-0.3.0/src/jsprvtd.h +174 -0
  377. data/vendor/jsl-0.3.0/src/jspubtd.h +586 -0
  378. data/vendor/jsl-0.3.0/src/jsregexp.c +3831 -0
  379. data/vendor/jsl-0.3.0/src/jsregexp.h +180 -0
  380. data/vendor/jsl-0.3.0/src/jsscan.c +1814 -0
  381. data/vendor/jsl-0.3.0/src/jsscan.h +267 -0
  382. data/vendor/jsl-0.3.0/src/jsscope.c +1639 -0
  383. data/vendor/jsl-0.3.0/src/jsscope.h +389 -0
  384. data/vendor/jsl-0.3.0/src/jsscript.c +1284 -0
  385. data/vendor/jsl-0.3.0/src/jsscript.h +179 -0
  386. data/vendor/jsl-0.3.0/src/jsshell.msg +50 -0
  387. data/vendor/jsl-0.3.0/src/jsstddef.h +83 -0
  388. data/vendor/jsl-0.3.0/src/jsstr.c +4502 -0
  389. data/vendor/jsl-0.3.0/src/jsstr.h +448 -0
  390. data/vendor/jsl-0.3.0/src/jstypes.h +391 -0
  391. data/vendor/jsl-0.3.0/src/jsutil.c +157 -0
  392. data/vendor/jsl-0.3.0/src/jsutil.h +75 -0
  393. data/vendor/jsl-0.3.0/src/jsxdrapi.c +686 -0
  394. data/vendor/jsl-0.3.0/src/jsxdrapi.h +193 -0
  395. data/vendor/jsl-0.3.0/src/liveconnect/LiveConnect.dsp +157 -0
  396. data/vendor/jsl-0.3.0/src/liveconnect/LiveConnectShell.dsp +120 -0
  397. data/vendor/jsl-0.3.0/src/liveconnect/LiveConnectShell.dsw +44 -0
  398. data/vendor/jsl-0.3.0/src/liveconnect/Makefile.in +106 -0
  399. data/vendor/jsl-0.3.0/src/liveconnect/Makefile.ref +169 -0
  400. data/vendor/jsl-0.3.0/src/liveconnect/README.html +719 -0
  401. data/vendor/jsl-0.3.0/src/liveconnect/_jni/netscape_javascript_JSException.h +14 -0
  402. data/vendor/jsl-0.3.0/src/liveconnect/_jni/netscape_javascript_JSObject.h +155 -0
  403. data/vendor/jsl-0.3.0/src/liveconnect/classes/Makefile.in +89 -0
  404. data/vendor/jsl-0.3.0/src/liveconnect/classes/Makefile.ref +57 -0
  405. data/vendor/jsl-0.3.0/src/liveconnect/classes/netscape/Makefile.ref +47 -0
  406. data/vendor/jsl-0.3.0/src/liveconnect/classes/netscape/javascript/JSException.java +140 -0
  407. data/vendor/jsl-0.3.0/src/liveconnect/classes/netscape/javascript/JSObject.java +183 -0
  408. data/vendor/jsl-0.3.0/src/liveconnect/classes/netscape/javascript/JSProxy.java +58 -0
  409. data/vendor/jsl-0.3.0/src/liveconnect/classes/netscape/javascript/JSRunnable.java +70 -0
  410. data/vendor/jsl-0.3.0/src/liveconnect/classes/netscape/javascript/JSUtil.java +59 -0
  411. data/vendor/jsl-0.3.0/src/liveconnect/classes/netscape/javascript/Makefile.ref +53 -0
  412. data/vendor/jsl-0.3.0/src/liveconnect/config/AIX4.1.mk +45 -0
  413. data/vendor/jsl-0.3.0/src/liveconnect/config/AIX4.2.mk +45 -0
  414. data/vendor/jsl-0.3.0/src/liveconnect/config/AIX4.3.mk +50 -0
  415. data/vendor/jsl-0.3.0/src/liveconnect/config/HP-UXB.10.10.mk +43 -0
  416. data/vendor/jsl-0.3.0/src/liveconnect/config/HP-UXB.10.20.mk +43 -0
  417. data/vendor/jsl-0.3.0/src/liveconnect/config/HP-UXB.11.00.mk +43 -0
  418. data/vendor/jsl-0.3.0/src/liveconnect/config/IRIX6.2.mk +43 -0
  419. data/vendor/jsl-0.3.0/src/liveconnect/config/IRIX6.3.mk +43 -0
  420. data/vendor/jsl-0.3.0/src/liveconnect/config/IRIX6.5.mk +43 -0
  421. data/vendor/jsl-0.3.0/src/liveconnect/config/Linux_All.mk +73 -0
  422. data/vendor/jsl-0.3.0/src/liveconnect/config/OSF1V4.0.mk +65 -0
  423. data/vendor/jsl-0.3.0/src/liveconnect/config/OSF1V5.0.mk +62 -0
  424. data/vendor/jsl-0.3.0/src/liveconnect/config/SunOS5.5.1.mk +55 -0
  425. data/vendor/jsl-0.3.0/src/liveconnect/config/SunOS5.6.mk +39 -0
  426. data/vendor/jsl-0.3.0/src/liveconnect/config/SunOS5.7.mk +39 -0
  427. data/vendor/jsl-0.3.0/src/liveconnect/config/SunOS5.8.mk +39 -0
  428. data/vendor/jsl-0.3.0/src/liveconnect/config/WINNT4.0.mk +53 -0
  429. data/vendor/jsl-0.3.0/src/liveconnect/jsj.c +884 -0
  430. data/vendor/jsl-0.3.0/src/liveconnect/jsj.msg +98 -0
  431. data/vendor/jsl-0.3.0/src/liveconnect/jsj_JSObject.c +1379 -0
  432. data/vendor/jsl-0.3.0/src/liveconnect/jsj_JavaArray.c +481 -0
  433. data/vendor/jsl-0.3.0/src/liveconnect/jsj_JavaClass.c +749 -0
  434. data/vendor/jsl-0.3.0/src/liveconnect/jsj_JavaMember.c +186 -0
  435. data/vendor/jsl-0.3.0/src/liveconnect/jsj_JavaObject.c +1099 -0
  436. data/vendor/jsl-0.3.0/src/liveconnect/jsj_JavaPackage.c +548 -0
  437. data/vendor/jsl-0.3.0/src/liveconnect/jsj_array.c +207 -0
  438. data/vendor/jsl-0.3.0/src/liveconnect/jsj_class.c +765 -0
  439. data/vendor/jsl-0.3.0/src/liveconnect/jsj_convert.c +954 -0
  440. data/vendor/jsl-0.3.0/src/liveconnect/jsj_field.c +421 -0
  441. data/vendor/jsl-0.3.0/src/liveconnect/jsj_hash.c +504 -0
  442. data/vendor/jsl-0.3.0/src/liveconnect/jsj_hash.h +161 -0
  443. data/vendor/jsl-0.3.0/src/liveconnect/jsj_method.c +1823 -0
  444. data/vendor/jsl-0.3.0/src/liveconnect/jsj_nodl.c +1 -0
  445. data/vendor/jsl-0.3.0/src/liveconnect/jsj_private.h +689 -0
  446. data/vendor/jsl-0.3.0/src/liveconnect/jsj_simpleapi.c +219 -0
  447. data/vendor/jsl-0.3.0/src/liveconnect/jsj_utils.c +513 -0
  448. data/vendor/jsl-0.3.0/src/liveconnect/jsjava.h +313 -0
  449. data/vendor/jsl-0.3.0/src/liveconnect/liveconnect.pkg +3 -0
  450. data/vendor/jsl-0.3.0/src/liveconnect/netscape_javascript_JSObject.h +155 -0
  451. data/vendor/jsl-0.3.0/src/liveconnect/nsCLiveconnect.cpp +785 -0
  452. data/vendor/jsl-0.3.0/src/liveconnect/nsCLiveconnect.h +197 -0
  453. data/vendor/jsl-0.3.0/src/liveconnect/nsCLiveconnectFactory.cpp +163 -0
  454. data/vendor/jsl-0.3.0/src/liveconnect/nsCLiveconnectFactory.h +76 -0
  455. data/vendor/jsl-0.3.0/src/liveconnect/nsILiveconnect.h +195 -0
  456. data/vendor/jsl-0.3.0/src/liveconnect/nsISecureLiveconnect.h +84 -0
  457. data/vendor/jsl-0.3.0/src/liveconnect/nsISecurityContext.h +135 -0
  458. data/vendor/jsl-0.3.0/src/liveconnect/win32.order +6 -0
  459. data/vendor/jsl-0.3.0/src/lock_SunOS.s +114 -0
  460. data/vendor/jsl-0.3.0/src/perfect.js +39 -0
  461. data/vendor/jsl-0.3.0/src/perlconnect/JS.def +6 -0
  462. data/vendor/jsl-0.3.0/src/perlconnect/JS.dsp +107 -0
  463. data/vendor/jsl-0.3.0/src/perlconnect/JS.pm +318 -0
  464. data/vendor/jsl-0.3.0/src/perlconnect/JS.xs +1050 -0
  465. data/vendor/jsl-0.3.0/src/perlconnect/Makefile.PL +67 -0
  466. data/vendor/jsl-0.3.0/src/perlconnect/Makefile.ref +152 -0
  467. data/vendor/jsl-0.3.0/src/perlconnect/PerlConnect.dsp +103 -0
  468. data/vendor/jsl-0.3.0/src/perlconnect/PerlConnect.dsw +59 -0
  469. data/vendor/jsl-0.3.0/src/perlconnect/PerlConnect.pm +126 -0
  470. data/vendor/jsl-0.3.0/src/perlconnect/PerlConnectShell.dsp +89 -0
  471. data/vendor/jsl-0.3.0/src/perlconnect/README.html +345 -0
  472. data/vendor/jsl-0.3.0/src/perlconnect/bg.jpg +0 -0
  473. data/vendor/jsl-0.3.0/src/perlconnect/jsperl.c +1100 -0
  474. data/vendor/jsl-0.3.0/src/perlconnect/jsperl.h +52 -0
  475. data/vendor/jsl-0.3.0/src/perlconnect/jsperlbuild.pl +81 -0
  476. data/vendor/jsl-0.3.0/src/perlconnect/jsperlpvt.h +57 -0
  477. data/vendor/jsl-0.3.0/src/perlconnect/test.js +73 -0
  478. data/vendor/jsl-0.3.0/src/perlconnect/test.pl +244 -0
  479. data/vendor/jsl-0.3.0/src/perlconnect/typemap +121 -0
  480. data/vendor/jsl-0.3.0/src/plify_jsdhash.sed +31 -0
  481. data/vendor/jsl-0.3.0/src/prmjtime.c +646 -0
  482. data/vendor/jsl-0.3.0/src/prmjtime.h +95 -0
  483. data/vendor/jsl-0.3.0/src/resource.h +15 -0
  484. data/vendor/jsl-0.3.0/src/rules.mk +193 -0
  485. data/vendor/jsl-0.3.0/src/win32.order +391 -0
  486. data/vendor/jsl-0.3.0/tests/conf/always_use_option_explicit.js +4 -0
  487. data/vendor/jsl-0.3.0/tests/conf/define.js +8 -0
  488. data/vendor/jsl-0.3.0/tests/conf/jscript_function_extensions-1.js +7 -0
  489. data/vendor/jsl-0.3.0/tests/conf/jscript_function_extensions-2.js +8 -0
  490. data/vendor/jsl-0.3.0/tests/conf/jscript_function_extensions-3.js +27 -0
  491. data/vendor/jsl-0.3.0/tests/conf/jscript_function_extensions-4.js +4 -0
  492. data/vendor/jsl-0.3.0/tests/conf/lambda_assign_requires_semicolon.js +24 -0
  493. data/vendor/jsl-0.3.0/tests/conf/legacy_control_comments.js +8 -0
  494. data/vendor/jsl-0.3.0/tests/control_comments/control_comments.js +33 -0
  495. data/vendor/jsl-0.3.0/tests/control_comments/declare.js +26 -0
  496. data/vendor/jsl-0.3.0/tests/control_comments/import-overflow.js +9 -0
  497. data/vendor/jsl-0.3.0/tests/control_comments/import.js +5 -0
  498. data/vendor/jsl-0.3.0/tests/control_comments/import2.js +2 -0
  499. data/vendor/jsl-0.3.0/tests/control_comments/invalid_fallthru.js +13 -0
  500. data/vendor/jsl-0.3.0/tests/control_comments/option_explicit-with.js +12 -0
  501. data/vendor/jsl-0.3.0/tests/control_comments/option_explicit.js +64 -0
  502. data/vendor/jsl-0.3.0/tests/errors/unterminated_comment.js +8 -0
  503. data/vendor/jsl-0.3.0/tests/html/script_tag_in_js_literal.html +14 -0
  504. data/vendor/jsl-0.3.0/tests/run_tests.pl +71 -0
  505. data/vendor/jsl-0.3.0/tests/warnings/ambiguous_else_stmt.js +21 -0
  506. data/vendor/jsl-0.3.0/tests/warnings/ambiguous_nested_stmt.js +66 -0
  507. data/vendor/jsl-0.3.0/tests/warnings/ambiguous_newline.js +261 -0
  508. data/vendor/jsl-0.3.0/tests/warnings/anon_no_return_value.js +26 -0
  509. data/vendor/jsl-0.3.0/tests/warnings/assign_to_function_call.js +16 -0
  510. data/vendor/jsl-0.3.0/tests/warnings/block_without_braces.js +13 -0
  511. data/vendor/jsl-0.3.0/tests/warnings/comma_separated_stmts.js +17 -0
  512. data/vendor/jsl-0.3.0/tests/warnings/comparison_type_conv.js +44 -0
  513. data/vendor/jsl-0.3.0/tests/warnings/default_not_at_end.js +15 -0
  514. data/vendor/jsl-0.3.0/tests/warnings/dup_option_explicit.js +5 -0
  515. data/vendor/jsl-0.3.0/tests/warnings/duplicate_case_in_switch.js +62 -0
  516. data/vendor/jsl-0.3.0/tests/warnings/duplicate_formal.js +5 -0
  517. data/vendor/jsl-0.3.0/tests/warnings/empty_statement.js +29 -0
  518. data/vendor/jsl-0.3.0/tests/warnings/equal_as_assign.js +7 -0
  519. data/vendor/jsl-0.3.0/tests/warnings/inc_dec_within_stmt-ignore.js +21 -0
  520. data/vendor/jsl-0.3.0/tests/warnings/inc_dec_within_stmt.js +63 -0
  521. data/vendor/jsl-0.3.0/tests/warnings/jsl_cc_not_understood.js +5 -0
  522. data/vendor/jsl-0.3.0/tests/warnings/leading_decimal_point.js +7 -0
  523. data/vendor/jsl-0.3.0/tests/warnings/legacy_cc_not_understood.js +9 -0
  524. data/vendor/jsl-0.3.0/tests/warnings/meaningless_block.js +12 -0
  525. data/vendor/jsl-0.3.0/tests/warnings/misplaced_regex.js +20 -0
  526. data/vendor/jsl-0.3.0/tests/warnings/missing_break.js +87 -0
  527. data/vendor/jsl-0.3.0/tests/warnings/missing_break_for_last_case.js +19 -0
  528. data/vendor/jsl-0.3.0/tests/warnings/missing_default_case.js +51 -0
  529. data/vendor/jsl-0.3.0/tests/warnings/missing_option_explicit.js +5 -0
  530. data/vendor/jsl-0.3.0/tests/warnings/missing_semicolon.js +19 -0
  531. data/vendor/jsl-0.3.0/tests/warnings/multiple_plus_minus.js +10 -0
  532. data/vendor/jsl-0.3.0/tests/warnings/nested_comment.js +6 -0
  533. data/vendor/jsl-0.3.0/tests/warnings/no_return_value.js +25 -0
  534. data/vendor/jsl-0.3.0/tests/warnings/octal_number.js +5 -0
  535. data/vendor/jsl-0.3.0/tests/warnings/parseint_missing_radix.js +15 -0
  536. data/vendor/jsl-0.3.0/tests/warnings/partial_option_explicit.js +5 -0
  537. data/vendor/jsl-0.3.0/tests/warnings/redeclared_var.js +10 -0
  538. data/vendor/jsl-0.3.0/tests/warnings/spidermonkey/bad_backref.js +5 -0
  539. data/vendor/jsl-0.3.0/tests/warnings/spidermonkey/deprecated_usage.js +11 -0
  540. data/vendor/jsl-0.3.0/tests/warnings/spidermonkey/invalid_backref.js +5 -0
  541. data/vendor/jsl-0.3.0/tests/warnings/spidermonkey/trailing_comma.js +5 -0
  542. data/vendor/jsl-0.3.0/tests/warnings/trailing_comma_in_array.js +8 -0
  543. data/vendor/jsl-0.3.0/tests/warnings/trailing_decimal_point.js +7 -0
  544. data/vendor/jsl-0.3.0/tests/warnings/unreachable_code.js +29 -0
  545. data/vendor/jsl-0.3.0/tests/warnings/use_of_label.js +19 -0
  546. data/vendor/jsl-0.3.0/tests/warnings/useless_assign.js +20 -0
  547. data/vendor/jsl-0.3.0/tests/warnings/useless_comparison.js +55 -0
  548. data/vendor/jsl-0.3.0/tests/warnings/useless_void.js +6 -0
  549. data/vendor/jsl-0.3.0/tests/warnings/var_hides_arg.js +4 -0
  550. data/vendor/jsl-0.3.0/tests/warnings/with_statement.js +7 -0
  551. data/vendor/yuicompressor-2.4.2.jar +0 -0
  552. metadata +605 -0
@@ -0,0 +1,4797 @@
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
+ /* build on macs with low memory */
41
+ #if defined(XP_MAC) && defined(MOZ_MAC_LOWMEM)
42
+ #pragma optimization_level 1
43
+ #endif
44
+
45
+ /*
46
+ * JavaScript bytecode interpreter.
47
+ */
48
+ #include "jsstddef.h"
49
+ #include <stdio.h>
50
+ #include <string.h>
51
+ #include <math.h>
52
+ #include "jstypes.h"
53
+ #include "jsarena.h" /* Added by JSIFY */
54
+ #include "jsutil.h" /* Added by JSIFY */
55
+ #include "jsprf.h"
56
+ #include "jsapi.h"
57
+ #include "jsarray.h"
58
+ #include "jsatom.h"
59
+ #include "jsbool.h"
60
+ #include "jscntxt.h"
61
+ #include "jsconfig.h"
62
+ #include "jsdbgapi.h"
63
+ #include "jsfun.h"
64
+ #include "jsgc.h"
65
+ #include "jsinterp.h"
66
+ #include "jslock.h"
67
+ #include "jsnum.h"
68
+ #include "jsobj.h"
69
+ #include "jsopcode.h"
70
+ #include "jsscope.h"
71
+ #include "jsscript.h"
72
+ #include "jsstr.h"
73
+
74
+ #if JS_HAS_JIT
75
+ #include "jsjit.h"
76
+ #endif
77
+
78
+ #ifdef DEBUG
79
+ #define ASSERT_CACHE_IS_EMPTY(cache) \
80
+ JS_BEGIN_MACRO \
81
+ JSPropertyCacheEntry *end_, *pce_, entry_; \
82
+ JSPropertyCache *cache_ = (cache); \
83
+ JS_ASSERT(cache_->empty); \
84
+ end_ = &cache_->table[PROPERTY_CACHE_SIZE]; \
85
+ for (pce_ = &cache_->table[0]; pce_ < end_; pce_++) { \
86
+ PCE_LOAD(cache_, pce_, entry_); \
87
+ JS_ASSERT(!PCE_OBJECT(entry_)); \
88
+ JS_ASSERT(!PCE_PROPERTY(entry_)); \
89
+ } \
90
+ JS_END_MACRO
91
+ #else
92
+ #define ASSERT_CACHE_IS_EMPTY(cache) ((void)0)
93
+ #endif
94
+
95
+ void
96
+ js_FlushPropertyCache(JSContext *cx)
97
+ {
98
+ JSPropertyCache *cache;
99
+
100
+ cache = &cx->runtime->propertyCache;
101
+ if (cache->empty) {
102
+ ASSERT_CACHE_IS_EMPTY(cache);
103
+ return;
104
+ }
105
+ memset(cache->table, 0, sizeof cache->table);
106
+ cache->empty = JS_TRUE;
107
+ #ifdef JS_PROPERTY_CACHE_METERING
108
+ cache->flushes++;
109
+ #endif
110
+ }
111
+
112
+ void
113
+ js_DisablePropertyCache(JSContext *cx)
114
+ {
115
+ JS_ASSERT(!cx->runtime->propertyCache.disabled);
116
+ cx->runtime->propertyCache.disabled = JS_TRUE;
117
+ }
118
+
119
+ void
120
+ js_EnablePropertyCache(JSContext *cx)
121
+ {
122
+ JS_ASSERT(cx->runtime->propertyCache.disabled);
123
+ ASSERT_CACHE_IS_EMPTY(&cx->runtime->propertyCache);
124
+ cx->runtime->propertyCache.disabled = JS_FALSE;
125
+ }
126
+
127
+ /*
128
+ * Class for for/in loop property iterator objects.
129
+ */
130
+ #define JSSLOT_ITER_STATE JSSLOT_PRIVATE
131
+
132
+ static void
133
+ prop_iterator_finalize(JSContext *cx, JSObject *obj)
134
+ {
135
+ jsval iter_state;
136
+ jsval iteratee;
137
+
138
+ /* Protect against stillborn iterators. */
139
+ iter_state = obj->slots[JSSLOT_ITER_STATE];
140
+ iteratee = obj->slots[JSSLOT_PARENT];
141
+ if (!JSVAL_IS_NULL(iter_state) && !JSVAL_IS_PRIMITIVE(iteratee)) {
142
+ OBJ_ENUMERATE(cx, JSVAL_TO_OBJECT(iteratee), JSENUMERATE_DESTROY,
143
+ &iter_state, NULL);
144
+ }
145
+ js_RemoveRoot(cx->runtime, &obj->slots[JSSLOT_PARENT]);
146
+
147
+ /* XXX force the GC to restart so we can collect iteratee, if possible,
148
+ during the current collector activation */
149
+ cx->runtime->gcLevel++;
150
+ }
151
+
152
+ static JSClass prop_iterator_class = {
153
+ "PropertyIterator",
154
+ 0,
155
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
156
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, prop_iterator_finalize,
157
+ JSCLASS_NO_OPTIONAL_MEMBERS
158
+ };
159
+
160
+ /*
161
+ * Stack macros and functions. These all use a local variable, jsval *sp, to
162
+ * point to the next free stack slot. SAVE_SP must be called before any call
163
+ * to a function that may invoke the interpreter. RESTORE_SP must be called
164
+ * only after return from js_Invoke, because only js_Invoke changes fp->sp.
165
+ */
166
+ #define PUSH(v) (*sp++ = (v))
167
+ #define POP() (*--sp)
168
+ #ifdef DEBUG
169
+ #define SAVE_SP(fp) \
170
+ (JS_ASSERT((fp)->script || !(fp)->spbase || (sp) == (fp)->spbase), \
171
+ (fp)->sp = sp)
172
+ #else
173
+ #define SAVE_SP(fp) ((fp)->sp = sp)
174
+ #endif
175
+ #define RESTORE_SP(fp) (sp = (fp)->sp)
176
+
177
+ /*
178
+ * Push the generating bytecode's pc onto the parallel pc stack that runs
179
+ * depth slots below the operands.
180
+ *
181
+ * NB: PUSH_OPND uses sp, depth, and pc from its lexical environment. See
182
+ * js_Interpret for these local variables' declarations and uses.
183
+ */
184
+ #define PUSH_OPND(v) (sp[-depth] = (jsval)pc, PUSH(v))
185
+ #define STORE_OPND(n,v) (sp[(n)-depth] = (jsval)pc, sp[n] = (v))
186
+ #define POP_OPND() POP()
187
+ #define FETCH_OPND(n) (sp[n])
188
+
189
+ /*
190
+ * Push the jsdouble d using sp, depth, and pc from the lexical environment.
191
+ * Try to convert d to a jsint that fits in a jsval, otherwise GC-alloc space
192
+ * for it and push a reference.
193
+ */
194
+ #define STORE_NUMBER(cx, n, d) \
195
+ JS_BEGIN_MACRO \
196
+ jsint i_; \
197
+ jsval v_; \
198
+ \
199
+ if (JSDOUBLE_IS_INT(d, i_) && INT_FITS_IN_JSVAL(i_)) { \
200
+ v_ = INT_TO_JSVAL(i_); \
201
+ } else { \
202
+ ok = js_NewDoubleValue(cx, d, &v_); \
203
+ if (!ok) \
204
+ goto out; \
205
+ } \
206
+ STORE_OPND(n, v_); \
207
+ JS_END_MACRO
208
+
209
+ #define FETCH_NUMBER(cx, n, d) \
210
+ JS_BEGIN_MACRO \
211
+ jsval v_; \
212
+ \
213
+ v_ = FETCH_OPND(n); \
214
+ VALUE_TO_NUMBER(cx, v_, d); \
215
+ JS_END_MACRO
216
+
217
+ #define FETCH_INT(cx, n, i) \
218
+ JS_BEGIN_MACRO \
219
+ jsval v_ = FETCH_OPND(n); \
220
+ if (JSVAL_IS_INT(v_)) { \
221
+ i = JSVAL_TO_INT(v_); \
222
+ } else { \
223
+ SAVE_SP(fp); \
224
+ ok = js_ValueToECMAInt32(cx, v_, &i); \
225
+ if (!ok) \
226
+ goto out; \
227
+ } \
228
+ JS_END_MACRO
229
+
230
+ #define FETCH_UINT(cx, n, ui) \
231
+ JS_BEGIN_MACRO \
232
+ jsval v_ = FETCH_OPND(n); \
233
+ jsint i_; \
234
+ if (JSVAL_IS_INT(v_) && (i_ = JSVAL_TO_INT(v_)) >= 0) { \
235
+ ui = (uint32) i_; \
236
+ } else { \
237
+ SAVE_SP(fp); \
238
+ ok = js_ValueToECMAUint32(cx, v_, &ui); \
239
+ if (!ok) \
240
+ goto out; \
241
+ } \
242
+ JS_END_MACRO
243
+
244
+ /*
245
+ * Optimized conversion macros that test for the desired type in v before
246
+ * homing sp and calling a conversion function.
247
+ */
248
+ #define VALUE_TO_NUMBER(cx, v, d) \
249
+ JS_BEGIN_MACRO \
250
+ if (JSVAL_IS_INT(v)) { \
251
+ d = (jsdouble)JSVAL_TO_INT(v); \
252
+ } else if (JSVAL_IS_DOUBLE(v)) { \
253
+ d = *JSVAL_TO_DOUBLE(v); \
254
+ } else { \
255
+ SAVE_SP(fp); \
256
+ ok = js_ValueToNumber(cx, v, &d); \
257
+ if (!ok) \
258
+ goto out; \
259
+ } \
260
+ JS_END_MACRO
261
+
262
+ #define POP_BOOLEAN(cx, v, b) \
263
+ JS_BEGIN_MACRO \
264
+ v = FETCH_OPND(-1); \
265
+ if (v == JSVAL_NULL) { \
266
+ b = JS_FALSE; \
267
+ } else if (JSVAL_IS_BOOLEAN(v)) { \
268
+ b = JSVAL_TO_BOOLEAN(v); \
269
+ } else { \
270
+ SAVE_SP(fp); \
271
+ ok = js_ValueToBoolean(cx, v, &b); \
272
+ if (!ok) \
273
+ goto out; \
274
+ } \
275
+ sp--; \
276
+ JS_END_MACRO
277
+
278
+ #define VALUE_TO_OBJECT(cx, v, obj) \
279
+ JS_BEGIN_MACRO \
280
+ if (JSVAL_IS_OBJECT(v) && v != JSVAL_NULL) { \
281
+ obj = JSVAL_TO_OBJECT(v); \
282
+ } else { \
283
+ SAVE_SP(fp); \
284
+ obj = js_ValueToNonNullObject(cx, v); \
285
+ if (!obj) { \
286
+ ok = JS_FALSE; \
287
+ goto out; \
288
+ } \
289
+ } \
290
+ JS_END_MACRO
291
+
292
+ #if JS_BUG_VOID_TOSTRING
293
+ #define CHECK_VOID_TOSTRING(cx, v) \
294
+ if (JSVAL_IS_VOID(v)) { \
295
+ JSString *str_; \
296
+ str_ = ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[JSTYPE_VOID]); \
297
+ v = STRING_TO_JSVAL(str_); \
298
+ }
299
+ #else
300
+ #define CHECK_VOID_TOSTRING(cx, v) ((void)0)
301
+ #endif
302
+
303
+ #if JS_BUG_EAGER_TOSTRING
304
+ #define CHECK_EAGER_TOSTRING(hint) (hint = JSTYPE_STRING)
305
+ #else
306
+ #define CHECK_EAGER_TOSTRING(hint) ((void)0)
307
+ #endif
308
+
309
+ #define VALUE_TO_PRIMITIVE(cx, v, hint, vp) \
310
+ JS_BEGIN_MACRO \
311
+ if (JSVAL_IS_PRIMITIVE(v)) { \
312
+ CHECK_VOID_TOSTRING(cx, v); \
313
+ *vp = v; \
314
+ } else { \
315
+ SAVE_SP(fp); \
316
+ CHECK_EAGER_TOSTRING(hint); \
317
+ ok = OBJ_DEFAULT_VALUE(cx, JSVAL_TO_OBJECT(v), hint, vp); \
318
+ if (!ok) \
319
+ goto out; \
320
+ } \
321
+ JS_END_MACRO
322
+
323
+ JS_FRIEND_API(jsval *)
324
+ js_AllocRawStack(JSContext *cx, uintN nslots, void **markp)
325
+ {
326
+ jsval *sp;
327
+
328
+ if (markp)
329
+ *markp = JS_ARENA_MARK(&cx->stackPool);
330
+ JS_ARENA_ALLOCATE_CAST(sp, jsval *, &cx->stackPool, nslots * sizeof(jsval));
331
+ if (!sp) {
332
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_STACK_OVERFLOW,
333
+ (cx->fp && cx->fp->fun)
334
+ ? JS_GetFunctionName(cx->fp->fun)
335
+ : "script");
336
+ }
337
+ return sp;
338
+ }
339
+
340
+ JS_FRIEND_API(void)
341
+ js_FreeRawStack(JSContext *cx, void *mark)
342
+ {
343
+ JS_ARENA_RELEASE(&cx->stackPool, mark);
344
+ }
345
+
346
+ JS_FRIEND_API(jsval *)
347
+ js_AllocStack(JSContext *cx, uintN nslots, void **markp)
348
+ {
349
+ jsval *sp, *vp, *end;
350
+ JSArena *a;
351
+ JSStackHeader *sh;
352
+ JSStackFrame *fp;
353
+
354
+ /* Callers don't check for zero nslots: we do to avoid empty segments. */
355
+ if (nslots == 0) {
356
+ *markp = NULL;
357
+ return JS_ARENA_MARK(&cx->stackPool);
358
+ }
359
+
360
+ /* Allocate 2 extra slots for the stack segment header we'll likely need. */
361
+ sp = js_AllocRawStack(cx, 2 + nslots, markp);
362
+ if (!sp)
363
+ return NULL;
364
+
365
+ /* Try to avoid another header if we can piggyback on the last segment. */
366
+ a = cx->stackPool.current;
367
+ sh = cx->stackHeaders;
368
+ if (sh && JS_STACK_SEGMENT(sh) + sh->nslots == sp) {
369
+ /* Extend the last stack segment, give back the 2 header slots. */
370
+ sh->nslots += nslots;
371
+ a->avail -= 2 * sizeof(jsval);
372
+ } else {
373
+ /*
374
+ * Need a new stack segment, so we must initialize unused slots in the
375
+ * current frame. See js_GC, just before marking the "operand" jsvals,
376
+ * where we scan from fp->spbase to fp->sp or through fp->script->depth
377
+ * (whichever covers fewer slots).
378
+ */
379
+ fp = cx->fp;
380
+ if (fp && fp->script && fp->spbase) {
381
+ #ifdef DEBUG
382
+ jsuword depthdiff = fp->script->depth * sizeof(jsval);
383
+ JS_ASSERT(JS_UPTRDIFF(fp->sp, fp->spbase) <= depthdiff);
384
+ JS_ASSERT(JS_UPTRDIFF(*markp, fp->spbase) >= depthdiff);
385
+ #endif
386
+ end = fp->spbase + fp->script->depth;
387
+ for (vp = fp->sp; vp < end; vp++)
388
+ *vp = JSVAL_VOID;
389
+ }
390
+
391
+ /* Allocate and push a stack segment header from the 2 extra slots. */
392
+ sh = (JSStackHeader *)sp;
393
+ sh->nslots = nslots;
394
+ sh->down = cx->stackHeaders;
395
+ cx->stackHeaders = sh;
396
+ sp += 2;
397
+ }
398
+
399
+ return sp;
400
+ }
401
+
402
+ JS_FRIEND_API(void)
403
+ js_FreeStack(JSContext *cx, void *mark)
404
+ {
405
+ JSStackHeader *sh;
406
+ jsuword slotdiff;
407
+
408
+ /* Check for zero nslots allocation special case. */
409
+ if (!mark)
410
+ return;
411
+
412
+ /* We can assert because js_FreeStack always balances js_AllocStack. */
413
+ sh = cx->stackHeaders;
414
+ JS_ASSERT(sh);
415
+
416
+ /* If mark is in the current segment, reduce sh->nslots, else pop sh. */
417
+ slotdiff = JS_UPTRDIFF(mark, JS_STACK_SEGMENT(sh)) / sizeof(jsval);
418
+ if (slotdiff < (jsuword)sh->nslots)
419
+ sh->nslots = slotdiff;
420
+ else
421
+ cx->stackHeaders = sh->down;
422
+
423
+ /* Release the stackPool space allocated since mark was set. */
424
+ JS_ARENA_RELEASE(&cx->stackPool, mark);
425
+ }
426
+
427
+ /*
428
+ * To economize on slots space in functions, the compiler records arguments and
429
+ * local variables as shared (JSPROP_SHARED) properties with well-known getters
430
+ * and setters: js_{Get,Set}Argument, js_{Get,Set}LocalVariable. Now, we could
431
+ * record args and vars in lists or hash tables in function-private data, but
432
+ * that means more duplication in code, and more data at runtime in the hash
433
+ * table case due to round-up to powers of two, just to recapitulate the scope
434
+ * machinery in the function object.
435
+ *
436
+ * What's more, for a long time (to the dawn of "Mocha" in 1995), these getters
437
+ * and setters knew how to search active stack frames in a context to find the
438
+ * top activation of the function f, in order to satisfy a get or set of f.a,
439
+ * for argument a, or f.x, for local variable x. You could use f.a instead of
440
+ * just a in function f(a) { return f.a }, for example, to return the actual
441
+ * parameter.
442
+ *
443
+ * ECMA requires that we give up on this ancient extension, because it is not
444
+ * compatible with the standard as used by real-world scripts. While Chapter
445
+ * 16 does allow for additional properties to be defined on native objects by
446
+ * a conforming implementation, these magic getters and setters cause f.a's
447
+ * meaning to vary unexpectedly. Real-world scripts set f.A = 42 to define
448
+ * "class static" (after Java) constants, for example, but if A also names an
449
+ * arg or var in f, the constant is not available while f is active, and any
450
+ * non-constant class-static can't be set while f is active.
451
+ *
452
+ * So, to label arg and var properties in functions without giving them magic
453
+ * abilities to affect active frame stack slots, while keeping the properties
454
+ * shared (slot-less) to save space in the common case (where no assignment
455
+ * sets a function property with the same name as an arg or var), the setters
456
+ * for args and vars must handle two special cases here.
457
+ *
458
+ * XXX functions tend to have few args and vars, so we risk O(n^2) growth here
459
+ * XXX ECMA *really* wants args and vars to be stored in function-private data,
460
+ * not as function object properties.
461
+ */
462
+ static JSBool
463
+ SetFunctionSlot(JSContext *cx, JSObject *obj, JSPropertyOp setter, jsid id,
464
+ jsval v)
465
+ {
466
+ uintN slot;
467
+ JSObject *origobj;
468
+ JSScope *scope;
469
+ JSScopeProperty *sprop;
470
+ JSString *str;
471
+ JSBool ok;
472
+
473
+ slot = (uintN) JSVAL_TO_INT(id);
474
+ if (OBJ_GET_CLASS(cx, obj) != &js_FunctionClass) {
475
+ /*
476
+ * Given a non-function object obj that has a function object in its
477
+ * prototype chain, where an argument or local variable property named
478
+ * by (setter, slot) is being set, override the shared property in the
479
+ * prototype with an unshared property in obj. This situation arises
480
+ * in real-world JS due to .prototype setting and collisions among a
481
+ * function's "static property" names and arg or var names, believe it
482
+ * or not.
483
+ */
484
+ origobj = obj;
485
+ do {
486
+ obj = OBJ_GET_PROTO(cx, obj);
487
+ if (!obj)
488
+ return JS_TRUE;
489
+ } while (OBJ_GET_CLASS(cx, obj) != &js_FunctionClass);
490
+
491
+ JS_LOCK_OBJ(cx, obj);
492
+ scope = OBJ_SCOPE(obj);
493
+ for (sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent) {
494
+ if (sprop->setter == setter) {
495
+ JS_ASSERT(!JSVAL_IS_INT(sprop->id) &&
496
+ ATOM_IS_STRING((JSAtom *)sprop->id) &&
497
+ (sprop->flags & SPROP_HAS_SHORTID));
498
+
499
+ if ((uintN) sprop->shortid == slot) {
500
+ str = ATOM_TO_STRING((JSAtom *)sprop->id);
501
+ JS_UNLOCK_SCOPE(cx, scope);
502
+
503
+ return JS_DefineUCProperty(cx, origobj,
504
+ JSSTRING_CHARS(str),
505
+ JSSTRING_LENGTH(str),
506
+ v, NULL, NULL,
507
+ JSPROP_ENUMERATE);
508
+ }
509
+ }
510
+ }
511
+ JS_UNLOCK_SCOPE(cx, scope);
512
+ return JS_TRUE;
513
+ }
514
+
515
+ /*
516
+ * Argument and local variable properties of function objects are shared
517
+ * by default (JSPROP_SHARED), therefore slot-less. But if for function
518
+ * f(a) {}, f.a = 42 is evaluated, f.a should be 42 after the assignment,
519
+ * whether or not f is active. So js_SetArgument and js_SetLocalVariable
520
+ * must be prepared to change an arg or var from shared to unshared status,
521
+ * allocating a slot in obj to hold v.
522
+ */
523
+ ok = JS_TRUE;
524
+ JS_LOCK_OBJ(cx, obj);
525
+ scope = OBJ_SCOPE(obj);
526
+ for (sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent) {
527
+ if (sprop->setter == setter && (uintN) sprop->shortid == slot) {
528
+ if (sprop->attrs & JSPROP_SHARED) {
529
+ sprop = js_ChangeScopePropertyAttrs(cx, scope, sprop,
530
+ 0, ~JSPROP_SHARED,
531
+ sprop->getter, setter);
532
+ if (!sprop) {
533
+ ok = JS_FALSE;
534
+ } else {
535
+ /* See js_SetProperty, near the bottom. */
536
+ GC_POKE(cx, pval);
537
+ LOCKED_OBJ_SET_SLOT(obj, sprop->slot, v);
538
+ }
539
+ }
540
+ break;
541
+ }
542
+ }
543
+ JS_UNLOCK_SCOPE(cx, scope);
544
+ return ok;
545
+ }
546
+
547
+ JSBool
548
+ js_GetArgument(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
549
+ {
550
+ return JS_TRUE;
551
+ }
552
+
553
+ JSBool
554
+ js_SetArgument(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
555
+ {
556
+ return SetFunctionSlot(cx, obj, js_SetArgument, id, *vp);
557
+ }
558
+
559
+ JSBool
560
+ js_GetLocalVariable(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
561
+ {
562
+ return JS_TRUE;
563
+ }
564
+
565
+ JSBool
566
+ js_SetLocalVariable(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
567
+ {
568
+ return SetFunctionSlot(cx, obj, js_SetLocalVariable, id, *vp);
569
+ }
570
+
571
+ /*
572
+ * Compute the 'this' parameter and store it in frame as frame.thisp.
573
+ * Activation objects ("Call" objects not created with "new Call()", i.e.,
574
+ * "Call" objects that have private data) may not be referred to by 'this',
575
+ * as dictated by ECMA.
576
+ *
577
+ * N.B.: fp->argv must be set, fp->argv[-1] the nominal 'this' paramter as
578
+ * a jsval, and fp->argv[-2] must be the callee object reference, usually a
579
+ * function object. Also, fp->flags must contain JSFRAME_CONSTRUCTING if we
580
+ * are preparing for a constructor call.
581
+ */
582
+ static JSBool
583
+ ComputeThis(JSContext *cx, JSObject *thisp, JSStackFrame *fp)
584
+ {
585
+ JSObject *parent;
586
+
587
+ if (thisp && OBJ_GET_CLASS(cx, thisp) != &js_CallClass) {
588
+ /* Some objects (e.g., With) delegate 'this' to another object. */
589
+ thisp = OBJ_THIS_OBJECT(cx, thisp);
590
+ if (!thisp)
591
+ return JS_FALSE;
592
+
593
+ /* Default return value for a constructor is the new object. */
594
+ if (fp->flags & JSFRAME_CONSTRUCTING)
595
+ fp->rval = OBJECT_TO_JSVAL(thisp);
596
+ } else {
597
+ /*
598
+ * ECMA requires "the global object", but in the presence of multiple
599
+ * top-level objects (windows, frames, or certain layers in the client
600
+ * object model), we prefer fun's parent. An example that causes this
601
+ * code to run:
602
+ *
603
+ * // in window w1
604
+ * function f() { return this }
605
+ * function g() { return f }
606
+ *
607
+ * // in window w2
608
+ * var h = w1.g()
609
+ * alert(h() == w1)
610
+ *
611
+ * The alert should display "true".
612
+ */
613
+ JS_ASSERT(!(fp->flags & JSFRAME_CONSTRUCTING));
614
+ if (JSVAL_IS_PRIMITIVE(fp->argv[-2]) ||
615
+ !(parent = OBJ_GET_PARENT(cx, JSVAL_TO_OBJECT(fp->argv[-2])))) {
616
+ thisp = cx->globalObject;
617
+ } else {
618
+ /* walk up to find the top-level object */
619
+ thisp = parent;
620
+ while ((parent = OBJ_GET_PARENT(cx, thisp)) != NULL)
621
+ thisp = parent;
622
+ }
623
+ }
624
+ fp->thisp = thisp;
625
+ fp->argv[-1] = OBJECT_TO_JSVAL(thisp);
626
+ return JS_TRUE;
627
+ }
628
+
629
+ #ifdef DUMP_CALL_TABLE
630
+
631
+ #include "jsclist.h"
632
+ #include "jshash.h"
633
+ #include "jsdtoa.h"
634
+
635
+ typedef struct CallKey {
636
+ jsval callee; /* callee value */
637
+ const char *filename; /* function filename or null */
638
+ uintN lineno; /* function lineno or 0 */
639
+ } CallKey;
640
+
641
+ /* Compensate for typeof null == "object" brain damage. */
642
+ #define JSTYPE_NULL JSTYPE_LIMIT
643
+ #define TYPEOF(cx,v) (JSVAL_IS_NULL(v) ? JSTYPE_NULL : JS_TypeOfValue(cx,v))
644
+ #define TYPENAME(t) (((t) == JSTYPE_NULL) ? js_null_str : js_type_str[t])
645
+ #define NTYPEHIST (JSTYPE_LIMIT + 1)
646
+
647
+ typedef struct CallValue {
648
+ uint32 total; /* total call count */
649
+ uint32 recycled; /* LRU-recycled calls lost */
650
+ uint16 minargc; /* minimum argument count */
651
+ uint16 maxargc; /* maximum argument count */
652
+ struct ArgInfo {
653
+ uint32 typeHist[NTYPEHIST]; /* histogram by type */
654
+ JSCList lruList; /* top 10 values LRU list */
655
+ struct ArgValCount {
656
+ JSCList lruLink; /* LRU list linkage */
657
+ jsval value; /* recently passed value */
658
+ uint32 count; /* number of times passed */
659
+ char strbuf[112]; /* string conversion buffer */
660
+ } topValCounts[10]; /* top 10 value storage */
661
+ } argInfo[8];
662
+ } CallValue;
663
+
664
+ typedef struct CallEntry {
665
+ JSHashEntry entry;
666
+ CallKey key;
667
+ CallValue value;
668
+ char name[32]; /* function name copy */
669
+ } CallEntry;
670
+
671
+ static void *
672
+ AllocCallTable(void *pool, size_t size)
673
+ {
674
+ return malloc(size);
675
+ }
676
+
677
+ static void
678
+ FreeCallTable(void *pool, void *item)
679
+ {
680
+ free(item);
681
+ }
682
+
683
+ static JSHashEntry *
684
+ AllocCallEntry(void *pool, const void *key)
685
+ {
686
+ return (JSHashEntry*) calloc(1, sizeof(CallEntry));
687
+ }
688
+
689
+ static void
690
+ FreeCallEntry(void *pool, JSHashEntry *he, uintN flag)
691
+ {
692
+ JS_ASSERT(flag == HT_FREE_ENTRY);
693
+ free(he);
694
+ }
695
+
696
+ static JSHashAllocOps callTableAllocOps = {
697
+ AllocCallTable, FreeCallTable,
698
+ AllocCallEntry, FreeCallEntry
699
+ };
700
+
701
+ JS_STATIC_DLL_CALLBACK(JSHashNumber)
702
+ js_hash_call_key(const void *key)
703
+ {
704
+ CallKey *ck = (CallKey *) key;
705
+ JSHashNumber hash = (jsuword)ck->callee >> 3;
706
+
707
+ if (ck->filename) {
708
+ hash = (hash << 4) ^ JS_HashString(ck->filename);
709
+ hash = (hash << 4) ^ ck->lineno;
710
+ }
711
+ return hash;
712
+ }
713
+
714
+ JS_STATIC_DLL_CALLBACK(intN)
715
+ js_compare_call_keys(const void *k1, const void *k2)
716
+ {
717
+ CallKey *ck1 = (CallKey *)k1, *ck2 = (CallKey *)k2;
718
+
719
+ return ck1->callee == ck2->callee &&
720
+ ((ck1->filename && ck2->filename)
721
+ ? strcmp(ck1->filename, ck2->filename) == 0
722
+ : ck1->filename == ck2->filename) &&
723
+ ck1->lineno == ck2->lineno;
724
+ }
725
+
726
+ JSHashTable *js_CallTable;
727
+ size_t js_LogCallToSourceLimit;
728
+
729
+ JS_STATIC_DLL_CALLBACK(intN)
730
+ CallTableDumper(JSHashEntry *he, intN k, void *arg)
731
+ {
732
+ CallEntry *ce = (CallEntry *)he;
733
+ FILE *fp = (FILE *)arg;
734
+ uintN argc, i, n;
735
+ struct ArgInfo *ai;
736
+ JSType save, type;
737
+ JSCList *cl;
738
+ struct ArgValCount *avc;
739
+ jsval argval;
740
+
741
+ if (ce->key.filename) {
742
+ /* We're called at the end of the mark phase, so mark our filenames. */
743
+ js_MarkScriptFilename(ce->key.filename);
744
+ fprintf(fp, "%s:%u ", ce->key.filename, ce->key.lineno);
745
+ } else {
746
+ fprintf(fp, "@%p ", (void *) ce->key.callee);
747
+ }
748
+
749
+ if (ce->name[0])
750
+ fprintf(fp, "name %s ", ce->name);
751
+ fprintf(fp, "calls %lu (%lu) argc %u/%u\n",
752
+ (unsigned long) ce->value.total,
753
+ (unsigned long) ce->value.recycled,
754
+ ce->value.minargc, ce->value.maxargc);
755
+
756
+ argc = JS_MIN(ce->value.maxargc, 8);
757
+ for (i = 0; i < argc; i++) {
758
+ ai = &ce->value.argInfo[i];
759
+
760
+ n = 0;
761
+ save = -1;
762
+ for (type = JSTYPE_VOID; type <= JSTYPE_LIMIT; type++) {
763
+ if (ai->typeHist[type]) {
764
+ save = type;
765
+ ++n;
766
+ }
767
+ }
768
+ if (n == 1) {
769
+ fprintf(fp, " arg %u type %s: %lu\n",
770
+ i, TYPENAME(save), (unsigned long) ai->typeHist[save]);
771
+ } else {
772
+ fprintf(fp, " arg %u type histogram:\n", i);
773
+ for (type = JSTYPE_VOID; type <= JSTYPE_LIMIT; type++) {
774
+ fprintf(fp, " %9s: %8lu ",
775
+ TYPENAME(type), (unsigned long) ai->typeHist[type]);
776
+ for (n = (uintN) JS_HOWMANY(ai->typeHist[type], 10); n > 0; --n)
777
+ fputc('*', fp);
778
+ fputc('\n', fp);
779
+ }
780
+ }
781
+
782
+ fprintf(fp, " arg %u top 10 values:\n", i);
783
+ n = 1;
784
+ for (cl = ai->lruList.prev; cl != &ai->lruList; cl = cl->prev) {
785
+ avc = (struct ArgValCount *)cl;
786
+ if (!avc->count)
787
+ break;
788
+ argval = avc->value;
789
+ fprintf(fp, " %9u: %8lu %.*s (%#lx)\n",
790
+ n, (unsigned long) avc->count,
791
+ sizeof avc->strbuf, avc->strbuf, argval);
792
+ ++n;
793
+ }
794
+ }
795
+
796
+ return HT_ENUMERATE_NEXT;
797
+ }
798
+
799
+ void
800
+ js_DumpCallTable(JSContext *cx)
801
+ {
802
+ char name[24];
803
+ FILE *fp;
804
+ static uintN dumpCount;
805
+
806
+ if (!js_CallTable)
807
+ return;
808
+
809
+ JS_snprintf(name, sizeof name, "/tmp/calltable.dump.%u", dumpCount & 7);
810
+ dumpCount++;
811
+ fp = fopen(name, "w");
812
+ if (!fp)
813
+ return;
814
+
815
+ JS_HashTableEnumerateEntries(js_CallTable, CallTableDumper, fp);
816
+ fclose(fp);
817
+ }
818
+
819
+ static void
820
+ LogCall(JSContext *cx, jsval callee, uintN argc, jsval *argv)
821
+ {
822
+ CallKey key;
823
+ const char *name, *cstr;
824
+ JSFunction *fun;
825
+ JSHashNumber keyHash;
826
+ JSHashEntry **hep, *he;
827
+ CallEntry *ce;
828
+ uintN i, j;
829
+ jsval argval;
830
+ JSType type;
831
+ struct ArgInfo *ai;
832
+ struct ArgValCount *avc;
833
+ JSString *str;
834
+
835
+ if (!js_CallTable) {
836
+ js_CallTable = JS_NewHashTable(1024, js_hash_call_key,
837
+ js_compare_call_keys, NULL,
838
+ &callTableAllocOps, NULL);
839
+ if (!js_CallTable)
840
+ return;
841
+ }
842
+
843
+ key.callee = callee;
844
+ key.filename = NULL;
845
+ key.lineno = 0;
846
+ name = "";
847
+ if (JSVAL_IS_FUNCTION(cx, callee)) {
848
+ fun = (JSFunction *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(callee));
849
+ if (fun->atom)
850
+ name = js_AtomToPrintableString(cx, fun->atom);
851
+ if (fun->interpreted) {
852
+ key.filename = fun->u.script->filename;
853
+ key.lineno = fun->u.script->lineno;
854
+ }
855
+ }
856
+ keyHash = js_hash_call_key(&key);
857
+
858
+ hep = JS_HashTableRawLookup(js_CallTable, keyHash, &key);
859
+ he = *hep;
860
+ if (he) {
861
+ ce = (CallEntry *) he;
862
+ JS_ASSERT(strncmp(ce->name, name, sizeof ce->name) == 0);
863
+ } else {
864
+ he = JS_HashTableRawAdd(js_CallTable, hep, keyHash, &key, NULL);
865
+ if (!he)
866
+ return;
867
+ ce = (CallEntry *) he;
868
+ ce->entry.key = &ce->key;
869
+ ce->entry.value = &ce->value;
870
+ ce->key = key;
871
+ for (i = 0; i < 8; i++) {
872
+ ai = &ce->value.argInfo[i];
873
+ JS_INIT_CLIST(&ai->lruList);
874
+ for (j = 0; j < 10; j++)
875
+ JS_APPEND_LINK(&ai->topValCounts[j].lruLink, &ai->lruList);
876
+ }
877
+ strncpy(ce->name, name, sizeof ce->name);
878
+ }
879
+
880
+ ++ce->value.total;
881
+ if (ce->value.minargc < argc)
882
+ ce->value.minargc = argc;
883
+ if (ce->value.maxargc < argc)
884
+ ce->value.maxargc = argc;
885
+ if (argc > 8)
886
+ argc = 8;
887
+ for (i = 0; i < argc; i++) {
888
+ ai = &ce->value.argInfo[i];
889
+ argval = argv[i];
890
+ type = TYPEOF(cx, argval);
891
+ ++ai->typeHist[type];
892
+
893
+ for (j = 0; ; j++) {
894
+ if (j == 10) {
895
+ avc = (struct ArgValCount *) ai->lruList.next;
896
+ ce->value.recycled += avc->count;
897
+ avc->value = argval;
898
+ avc->count = 1;
899
+ break;
900
+ }
901
+ avc = &ai->topValCounts[j];
902
+ if (avc->value == argval) {
903
+ ++avc->count;
904
+ break;
905
+ }
906
+ }
907
+
908
+ /* Move avc to the back of the LRU list. */
909
+ JS_REMOVE_LINK(&avc->lruLink);
910
+ JS_APPEND_LINK(&avc->lruLink, &ai->lruList);
911
+
912
+ str = NULL;
913
+ cstr = "";
914
+ switch (TYPEOF(cx, argval)) {
915
+ case JSTYPE_VOID:
916
+ cstr = js_type_str[JSTYPE_VOID];
917
+ break;
918
+ case JSTYPE_NULL:
919
+ cstr = js_null_str;
920
+ break;
921
+ case JSTYPE_BOOLEAN:
922
+ cstr = js_boolean_str[JSVAL_TO_BOOLEAN(argval)];
923
+ break;
924
+ case JSTYPE_NUMBER:
925
+ if (JSVAL_IS_INT(argval)) {
926
+ JS_snprintf(avc->strbuf, sizeof avc->strbuf, "%ld",
927
+ JSVAL_TO_INT(argval));
928
+ } else {
929
+ JS_dtostr(avc->strbuf, sizeof avc->strbuf, DTOSTR_STANDARD, 0,
930
+ *JSVAL_TO_DOUBLE(argval));
931
+ }
932
+ continue;
933
+ case JSTYPE_STRING:
934
+ str = js_QuoteString(cx, JSVAL_TO_STRING(argval), (jschar)'"');
935
+ break;
936
+ case JSTYPE_FUNCTION:
937
+ if (JSVAL_IS_FUNCTION(cx, argval)) {
938
+ fun = (JSFunction *)JS_GetPrivate(cx, JSVAL_TO_OBJECT(argval));
939
+ if (fun && fun->atom) {
940
+ str = ATOM_TO_STRING(fun->atom);
941
+ break;
942
+ }
943
+ }
944
+ /* FALL THROUGH */
945
+ case JSTYPE_OBJECT:
946
+ js_LogCallToSourceLimit = sizeof avc->strbuf;
947
+ cx->options |= JSOPTION_LOGCALL_TOSOURCE;
948
+ str = js_ValueToSource(cx, argval);
949
+ cx->options &= ~JSOPTION_LOGCALL_TOSOURCE;
950
+ break;
951
+ }
952
+ if (str)
953
+ cstr = JS_GetStringBytes(str);
954
+ strncpy(avc->strbuf, cstr, sizeof avc->strbuf);
955
+ }
956
+ }
957
+
958
+ #endif /* DUMP_CALL_TABLE */
959
+
960
+ /*
961
+ * Find a function reference and its 'this' object implicit first parameter
962
+ * under argc arguments on cx's stack, and call the function. Push missing
963
+ * required arguments, allocate declared local variables, and pop everything
964
+ * when done. Then push the return value.
965
+ */
966
+ JS_FRIEND_API(JSBool)
967
+ js_Invoke(JSContext *cx, uintN argc, uintN flags)
968
+ {
969
+ void *mark;
970
+ JSStackFrame *fp, frame;
971
+ jsval *sp, *newsp, *limit;
972
+ jsval *vp, v;
973
+ JSObject *funobj, *parent, *thisp;
974
+ JSBool ok;
975
+ JSClass *clasp;
976
+ JSObjectOps *ops;
977
+ JSNative native;
978
+ JSFunction *fun;
979
+ JSScript *script;
980
+ uintN minargs, nvars;
981
+ intN nslots, nalloc, surplus;
982
+ JSInterpreterHook hook;
983
+ void *hookData;
984
+
985
+ /* Mark the top of stack and load frequently-used registers. */
986
+ mark = JS_ARENA_MARK(&cx->stackPool);
987
+ fp = cx->fp;
988
+ sp = fp->sp;
989
+
990
+ /*
991
+ * Set vp to the callee value's stack slot (it's where rval goes).
992
+ * Once vp is set, control should flow through label out2: to return.
993
+ * Set frame.rval early so native class and object ops can throw and
994
+ * return false, causing a goto out2 with ok set to false. Also set
995
+ * frame.flags to flags so that ComputeThis can test bits in it.
996
+ */
997
+ vp = sp - (2 + argc);
998
+ v = *vp;
999
+ frame.rval = JSVAL_VOID;
1000
+ frame.flags = flags;
1001
+ thisp = JSVAL_TO_OBJECT(vp[1]);
1002
+
1003
+ /*
1004
+ * A callee must be an object reference, unless its |this| parameter
1005
+ * implements the __noSuchMethod__ method, in which case that method will
1006
+ * be called like so:
1007
+ *
1008
+ * thisp.__noSuchMethod__(id, args)
1009
+ *
1010
+ * where id is the name of the method that this invocation attempted to
1011
+ * call by name, and args is an Array containing this invocation's actual
1012
+ * parameters.
1013
+ */
1014
+ if (JSVAL_IS_PRIMITIVE(v)) {
1015
+ #if JS_HAS_NO_SUCH_METHOD
1016
+ jsbytecode *pc;
1017
+ jsatomid atomIndex;
1018
+ JSAtom *atom;
1019
+ JSObject *argsobj;
1020
+ JSArena *a;
1021
+
1022
+ if (!fp->script || (flags & JSINVOKE_INTERNAL))
1023
+ goto bad;
1024
+
1025
+ /*
1026
+ * We must ComputeThis here to censor Call objects; performance hit,
1027
+ * but at least it's idempotent.
1028
+ *
1029
+ * Normally, we call ComputeThis after all frame members have been
1030
+ * set, and in particular, after any revision of the callee value at
1031
+ * *vp due to clasp->convert (see below). This matters because
1032
+ * ComputeThis may access *vp via fp->argv[-2], to follow the parent
1033
+ * chain to a global object to use as the |this| parameter.
1034
+ *
1035
+ * Obviously, here in the JSVAL_IS_PRIMITIVE(v) case, there can't be
1036
+ * any such defaulting of |this| to callee (v, *vp) ancestor.
1037
+ */
1038
+ frame.argv = vp + 2;
1039
+ ok = ComputeThis(cx, thisp, &frame);
1040
+ if (!ok)
1041
+ goto out2;
1042
+ thisp = frame.thisp;
1043
+
1044
+ ok = OBJ_GET_PROPERTY(cx, thisp,
1045
+ (jsid)cx->runtime->atomState.noSuchMethodAtom,
1046
+ &v);
1047
+ if (!ok)
1048
+ goto out2;
1049
+ if (JSVAL_IS_PRIMITIVE(v))
1050
+ goto bad;
1051
+
1052
+ pc = (jsbytecode *) vp[-(intN)fp->script->depth];
1053
+ switch ((JSOp) *pc) {
1054
+ case JSOP_NAME:
1055
+ case JSOP_GETPROP:
1056
+ atomIndex = GET_ATOM_INDEX(pc);
1057
+ atom = js_GetAtom(cx, &fp->script->atomMap, atomIndex);
1058
+ argsobj = js_NewArrayObject(cx, argc, vp + 2);
1059
+ if (!argsobj) {
1060
+ ok = JS_FALSE;
1061
+ goto out2;
1062
+ }
1063
+
1064
+ sp = vp + 4;
1065
+ if (argc < 2) {
1066
+ a = cx->stackPool.current;
1067
+ if ((jsuword)sp > a->limit) {
1068
+ /*
1069
+ * Arguments must be contiguous, and must include argv[-1]
1070
+ * and argv[-2], so allocate more stack, advance sp, and
1071
+ * set newsp[1] to thisp (vp[1]). The other argv elements
1072
+ * will be set below, using negative indexing from sp.
1073
+ */
1074
+ newsp = js_AllocRawStack(cx, 4, NULL);
1075
+ if (!newsp) {
1076
+ ok = JS_FALSE;
1077
+ goto out2;
1078
+ }
1079
+ newsp[1] = OBJECT_TO_JSVAL(thisp);
1080
+ sp = newsp + 4;
1081
+ } else if ((jsuword)sp > a->avail) {
1082
+ /*
1083
+ * Inline, optimized version of JS_ARENA_ALLOCATE to claim
1084
+ * the small number of words not already allocated as part
1085
+ * of the caller's operand stack.
1086
+ */
1087
+ JS_ArenaCountAllocation(&cx->stackPool,
1088
+ (jsuword)sp - a->avail);
1089
+ a->avail = (jsuword)sp;
1090
+ }
1091
+ }
1092
+
1093
+ sp[-4] = v;
1094
+ JS_ASSERT(sp[-3] == OBJECT_TO_JSVAL(thisp));
1095
+ sp[-2] = ATOM_KEY(atom);
1096
+ sp[-1] = OBJECT_TO_JSVAL(argsobj);
1097
+ fp->sp = sp;
1098
+ argc = 2;
1099
+ break;
1100
+
1101
+ default:
1102
+ goto bad;
1103
+ }
1104
+ #else
1105
+ goto bad;
1106
+ #endif
1107
+ }
1108
+
1109
+ funobj = JSVAL_TO_OBJECT(v);
1110
+ parent = OBJ_GET_PARENT(cx, funobj);
1111
+ clasp = OBJ_GET_CLASS(cx, funobj);
1112
+ if (clasp != &js_FunctionClass) {
1113
+ /* Function is inlined, all other classes use object ops. */
1114
+ ops = funobj->map->ops;
1115
+
1116
+ /*
1117
+ * XXX this makes no sense -- why convert to function if clasp->call?
1118
+ * XXX better to call that hook without converting
1119
+ * XXX the only thing that needs fixing is liveconnect
1120
+ *
1121
+ * Try converting to function, for closure and API compatibility.
1122
+ * We attempt the conversion under all circumstances for 1.2, but
1123
+ * only if there is a call op defined otherwise.
1124
+ */
1125
+ if (cx->version == JSVERSION_1_2 ||
1126
+ ((ops == &js_ObjectOps) ? clasp->call : ops->call)) {
1127
+ ok = clasp->convert(cx, funobj, JSTYPE_FUNCTION, &v);
1128
+ if (!ok)
1129
+ goto out2;
1130
+
1131
+ if (JSVAL_IS_FUNCTION(cx, v)) {
1132
+ /* Make vp refer to funobj to keep it available as argv[-2]. */
1133
+ *vp = v;
1134
+ funobj = JSVAL_TO_OBJECT(v);
1135
+ parent = OBJ_GET_PARENT(cx, funobj);
1136
+ goto have_fun;
1137
+ }
1138
+ }
1139
+ fun = NULL;
1140
+ script = NULL;
1141
+ minargs = nvars = 0;
1142
+
1143
+ /* Try a call or construct native object op. */
1144
+ native = (flags & JSINVOKE_CONSTRUCT) ? ops->construct : ops->call;
1145
+ if (!native)
1146
+ goto bad;
1147
+ } else {
1148
+ have_fun:
1149
+ /* Get private data and set derived locals from it. */
1150
+ fun = (JSFunction *) JS_GetPrivate(cx, funobj);
1151
+ if (fun->interpreted) {
1152
+ native = NULL;
1153
+ script = fun->u.script;
1154
+ } else {
1155
+ native = fun->u.native;
1156
+ script = NULL;
1157
+ }
1158
+ minargs = fun->nargs + fun->extra;
1159
+ nvars = fun->nvars;
1160
+
1161
+ /* Handle bound method special case. */
1162
+ if (fun->flags & JSFUN_BOUND_METHOD)
1163
+ thisp = parent;
1164
+ }
1165
+
1166
+ /* Initialize the rest of frame, except for sp (set by SAVE_SP later). */
1167
+ frame.varobj = NULL;
1168
+ frame.callobj = frame.argsobj = NULL;
1169
+ frame.script = script;
1170
+ frame.fun = fun;
1171
+ frame.argc = argc;
1172
+ frame.argv = sp - argc;
1173
+ frame.nvars = nvars;
1174
+ frame.vars = sp;
1175
+ frame.down = fp;
1176
+ frame.annotation = NULL;
1177
+ frame.scopeChain = NULL; /* set below for real, after cx->fp is set */
1178
+ frame.pc = NULL;
1179
+ frame.spbase = NULL;
1180
+ frame.sharpDepth = 0;
1181
+ frame.sharpArray = NULL;
1182
+ frame.dormantNext = NULL;
1183
+
1184
+ /* Compute the 'this' parameter and store it in frame as frame.thisp. */
1185
+ ok = ComputeThis(cx, thisp, &frame);
1186
+ if (!ok)
1187
+ goto out2;
1188
+
1189
+ /* From here on, control must flow through label out: to return. */
1190
+ cx->fp = &frame;
1191
+
1192
+ /* Init these now in case we goto out before first hook call. */
1193
+ hook = cx->runtime->callHook;
1194
+ hookData = NULL;
1195
+
1196
+ /* Check for missing arguments expected by the function. */
1197
+ nslots = (intN)((argc < minargs) ? minargs - argc : 0);
1198
+ if (nslots) {
1199
+ /* All arguments must be contiguous, so we may have to copy actuals. */
1200
+ nalloc = nslots;
1201
+ limit = (jsval *) cx->stackPool.current->limit;
1202
+ if (sp + nslots > limit) {
1203
+ /* Hit end of arena: we have to copy argv[-2..(argc+nslots-1)]. */
1204
+ nalloc += 2 + argc;
1205
+ } else {
1206
+ /* Take advantage of surplus slots in the caller's frame depth. */
1207
+ surplus = (jsval *)mark - sp;
1208
+ JS_ASSERT(surplus >= 0);
1209
+ nalloc -= surplus;
1210
+ }
1211
+
1212
+ /* Check whether we have enough space in the caller's frame. */
1213
+ if (nalloc > 0) {
1214
+ /* Need space for actuals plus missing formals minus surplus. */
1215
+ newsp = js_AllocRawStack(cx, (uintN)nalloc, NULL);
1216
+ if (!newsp) {
1217
+ ok = JS_FALSE;
1218
+ goto out;
1219
+ }
1220
+
1221
+ /* If we couldn't allocate contiguous args, copy actuals now. */
1222
+ if (newsp != mark) {
1223
+ JS_ASSERT(sp + nslots > limit);
1224
+ JS_ASSERT(2 + argc + nslots == (uintN)nalloc);
1225
+ *newsp++ = vp[0];
1226
+ *newsp++ = vp[1];
1227
+ if (argc)
1228
+ memcpy(newsp, frame.argv, argc * sizeof(jsval));
1229
+ frame.argv = newsp;
1230
+ sp = frame.vars = newsp + argc;
1231
+ }
1232
+ }
1233
+
1234
+ /* Advance frame.vars to make room for the missing args. */
1235
+ frame.vars += nslots;
1236
+
1237
+ /* Push void to initialize missing args. */
1238
+ while (--nslots >= 0)
1239
+ PUSH(JSVAL_VOID);
1240
+ }
1241
+
1242
+ /* Now allocate stack space for local variables. */
1243
+ nslots = (intN)frame.nvars;
1244
+ if (nslots) {
1245
+ surplus = (intN)((jsval *)cx->stackPool.current->avail - frame.vars);
1246
+ if (surplus < nslots) {
1247
+ newsp = js_AllocRawStack(cx, (uintN)nslots, NULL);
1248
+ if (!newsp) {
1249
+ ok = JS_FALSE;
1250
+ goto out;
1251
+ }
1252
+ if (newsp != sp) {
1253
+ /* NB: Discontinuity between argv and vars. */
1254
+ sp = frame.vars = newsp;
1255
+ }
1256
+ }
1257
+
1258
+ /* Push void to initialize local variables. */
1259
+ while (--nslots >= 0)
1260
+ PUSH(JSVAL_VOID);
1261
+ }
1262
+
1263
+ /* Store the current sp in frame before calling fun. */
1264
+ SAVE_SP(&frame);
1265
+
1266
+ /* call the hook if present */
1267
+ if (hook && (native || script))
1268
+ hookData = hook(cx, &frame, JS_TRUE, 0, cx->runtime->callHookData);
1269
+
1270
+ /* Call the function, either a native method or an interpreted script. */
1271
+ if (native) {
1272
+ #if JS_HAS_LVALUE_RETURN
1273
+ /* Set by JS_SetCallReturnValue2, used to return reference types. */
1274
+ cx->rval2set = JS_FALSE;
1275
+ #endif
1276
+
1277
+ /* If native, use caller varobj and scopeChain for eval. */
1278
+ frame.varobj = fp->varobj;
1279
+ frame.scopeChain = fp->scopeChain;
1280
+ ok = native(cx, frame.thisp, argc, frame.argv, &frame.rval);
1281
+ JS_RUNTIME_METER(cx->runtime, nativeCalls);
1282
+ } else if (script) {
1283
+ #ifdef DUMP_CALL_TABLE
1284
+ LogCall(cx, *vp, argc, frame.argv);
1285
+ #endif
1286
+ /* Use parent scope so js_GetCallObject can find the right "Call". */
1287
+ frame.scopeChain = parent;
1288
+ if (fun->flags & JSFUN_HEAVYWEIGHT) {
1289
+ #if JS_HAS_CALL_OBJECT
1290
+ /* Scope with a call object parented by the callee's parent. */
1291
+ if (!js_GetCallObject(cx, &frame, parent)) {
1292
+ ok = JS_FALSE;
1293
+ goto out;
1294
+ }
1295
+ #else
1296
+ /* Bad old code used the function as a proxy for all calls to it. */
1297
+ frame.scopeChain = funobj;
1298
+ #endif
1299
+ }
1300
+ ok = js_Interpret(cx, &v);
1301
+ } else {
1302
+ /* fun might be onerror trying to report a syntax error in itself. */
1303
+ frame.scopeChain = NULL;
1304
+ ok = JS_TRUE;
1305
+ }
1306
+
1307
+ out:
1308
+ if (hookData) {
1309
+ hook = cx->runtime->callHook;
1310
+ if (hook)
1311
+ hook(cx, &frame, JS_FALSE, &ok, hookData);
1312
+ }
1313
+ #if JS_HAS_CALL_OBJECT
1314
+ /* If frame has a call object, sync values and clear back-pointer. */
1315
+ if (frame.callobj)
1316
+ ok &= js_PutCallObject(cx, &frame);
1317
+ #endif
1318
+ #if JS_HAS_ARGS_OBJECT
1319
+ /* If frame has an arguments object, sync values and clear back-pointer. */
1320
+ if (frame.argsobj)
1321
+ ok &= js_PutArgsObject(cx, &frame);
1322
+ #endif
1323
+
1324
+ /* Restore cx->fp now that we're done releasing frame objects. */
1325
+ cx->fp = fp;
1326
+
1327
+ out2:
1328
+ /* Pop everything we may have allocated off the stack. */
1329
+ JS_ARENA_RELEASE(&cx->stackPool, mark);
1330
+
1331
+ /* Store the return value and restore sp just above it. */
1332
+ *vp = frame.rval;
1333
+ fp->sp = vp + 1;
1334
+
1335
+ /*
1336
+ * Store the location of the JSOP_CALL or JSOP_EVAL that generated the
1337
+ * return value, but only if this is an external (compiled from script
1338
+ * source) call that has stack budget for the generating pc.
1339
+ */
1340
+ if (fp->script && !(flags & JSINVOKE_INTERNAL))
1341
+ vp[-(intN)fp->script->depth] = (jsval)fp->pc;
1342
+ return ok;
1343
+
1344
+ bad:
1345
+ js_ReportIsNotFunction(cx, vp, flags & JSINVOKE_CONSTRUCT);
1346
+ ok = JS_FALSE;
1347
+ goto out2;
1348
+ }
1349
+
1350
+ JSBool
1351
+ js_InternalInvoke(JSContext *cx, JSObject *obj, jsval fval, uintN flags,
1352
+ uintN argc, jsval *argv, jsval *rval)
1353
+ {
1354
+ JSStackFrame *fp, *oldfp, frame;
1355
+ jsval *oldsp, *sp;
1356
+ void *mark;
1357
+ uintN i;
1358
+ JSBool ok;
1359
+
1360
+ fp = oldfp = cx->fp;
1361
+ if (!fp) {
1362
+ memset(&frame, 0, sizeof frame);
1363
+ cx->fp = fp = &frame;
1364
+ }
1365
+ oldsp = fp->sp;
1366
+ sp = js_AllocStack(cx, 2 + argc, &mark);
1367
+ if (!sp) {
1368
+ ok = JS_FALSE;
1369
+ goto out;
1370
+ }
1371
+
1372
+ PUSH(fval);
1373
+ PUSH(OBJECT_TO_JSVAL(obj));
1374
+ for (i = 0; i < argc; i++)
1375
+ PUSH(argv[i]);
1376
+ fp->sp = sp;
1377
+ ok = js_Invoke(cx, argc, flags | JSINVOKE_INTERNAL);
1378
+ if (ok) {
1379
+ RESTORE_SP(fp);
1380
+ *rval = POP_OPND();
1381
+ }
1382
+
1383
+ js_FreeStack(cx, mark);
1384
+ out:
1385
+ fp->sp = oldsp;
1386
+ if (oldfp != fp)
1387
+ cx->fp = oldfp;
1388
+
1389
+ return ok;
1390
+ }
1391
+
1392
+ JSBool
1393
+ js_InternalGetOrSet(JSContext *cx, JSObject *obj, jsid id, jsval fval,
1394
+ JSAccessMode mode, uintN argc, jsval *argv, jsval *rval)
1395
+ {
1396
+ /*
1397
+ * Check general (not object-ops/class-specific) access from the running
1398
+ * script to obj.id only if id has a scripted getter or setter that we're
1399
+ * about to invoke. If we don't check this case, nothing else will -- no
1400
+ * other native code has the chance to check.
1401
+ *
1402
+ * Contrast this non-native (scripted) case with native getter and setter
1403
+ * accesses, where the native itself must do an access check, if security
1404
+ * policies requires it. We make a checkAccess or checkObjectAccess call
1405
+ * back to the embedding program only in those cases where we're not going
1406
+ * to call an embedding-defined native function, getter, setter, or class
1407
+ * hook anyway. Where we do call such a native, there's no need for the
1408
+ * engine to impose a separate access check callback on all embeddings --
1409
+ * many embeddings have no security policy at all.
1410
+ */
1411
+ JS_ASSERT(mode == JSACC_READ || mode == JSACC_WRITE);
1412
+ if (cx->runtime->checkObjectAccess &&
1413
+ JSVAL_IS_FUNCTION(cx, fval) &&
1414
+ ((JSFunction *)JS_GetPrivate(cx, JSVAL_TO_OBJECT(fval)))->interpreted &&
1415
+ !cx->runtime->checkObjectAccess(cx, obj, ID_TO_VALUE(id), mode,
1416
+ &fval)) {
1417
+ return JS_FALSE;
1418
+ }
1419
+
1420
+ return js_InternalCall(cx, obj, fval, argc, argv, rval);
1421
+ }
1422
+
1423
+ JSBool
1424
+ js_Execute(JSContext *cx, JSObject *chain, JSScript *script,
1425
+ JSStackFrame *down, uintN flags, jsval *result)
1426
+ {
1427
+ JSInterpreterHook hook;
1428
+ void *hookData, *mark;
1429
+ JSStackFrame *oldfp, frame;
1430
+ JSObject *obj, *tmp;
1431
+ JSBool ok;
1432
+
1433
+ hook = cx->runtime->executeHook;
1434
+ hookData = mark = NULL;
1435
+ oldfp = cx->fp;
1436
+ frame.callobj = frame.argsobj = NULL;
1437
+ frame.script = script;
1438
+ if (down) {
1439
+ /* Propagate arg/var state for eval and the debugger API. */
1440
+ frame.varobj = down->varobj;
1441
+ frame.fun = down->fun;
1442
+ frame.thisp = down->thisp;
1443
+ frame.argc = down->argc;
1444
+ frame.argv = down->argv;
1445
+ frame.nvars = down->nvars;
1446
+ frame.vars = down->vars;
1447
+ frame.annotation = down->annotation;
1448
+ frame.sharpArray = down->sharpArray;
1449
+ } else {
1450
+ obj = chain;
1451
+ if (cx->options & JSOPTION_VAROBJFIX) {
1452
+ while ((tmp = OBJ_GET_PARENT(cx, obj)) != NULL)
1453
+ obj = tmp;
1454
+ }
1455
+ frame.varobj = obj;
1456
+ frame.fun = NULL;
1457
+ frame.thisp = chain;
1458
+ frame.argc = 0;
1459
+ frame.argv = NULL;
1460
+ frame.nvars = script->numGlobalVars;
1461
+ if (frame.nvars) {
1462
+ frame.vars = js_AllocRawStack(cx, frame.nvars, &mark);
1463
+ if (!frame.vars)
1464
+ return JS_FALSE;
1465
+ memset(frame.vars, 0, frame.nvars * sizeof(jsval));
1466
+ } else {
1467
+ frame.vars = NULL;
1468
+ }
1469
+ frame.annotation = NULL;
1470
+ frame.sharpArray = NULL;
1471
+ }
1472
+ frame.rval = JSVAL_VOID;
1473
+ frame.down = down;
1474
+ frame.scopeChain = chain;
1475
+ frame.pc = NULL;
1476
+ frame.sp = oldfp ? oldfp->sp : NULL;
1477
+ frame.spbase = NULL;
1478
+ frame.sharpDepth = 0;
1479
+ frame.flags = flags;
1480
+ frame.dormantNext = NULL;
1481
+
1482
+ /*
1483
+ * Here we wrap the call to js_Interpret with code to (conditionally)
1484
+ * save and restore the old stack frame chain into a chain of 'dormant'
1485
+ * frame chains. Since we are replacing cx->fp, we were running into
1486
+ * the problem that if GC was called under this frame, some of the GC
1487
+ * things associated with the old frame chain (available here only in
1488
+ * the C variable 'oldfp') were not rooted and were being collected.
1489
+ *
1490
+ * So, now we preserve the links to these 'dormant' frame chains in cx
1491
+ * before calling js_Interpret and cleanup afterwards. The GC walks
1492
+ * these dormant chains and marks objects in the same way that it marks
1493
+ * objects in the primary cx->fp chain.
1494
+ */
1495
+ if (oldfp && oldfp != down) {
1496
+ JS_ASSERT(!oldfp->dormantNext);
1497
+ oldfp->dormantNext = cx->dormantFrameChain;
1498
+ cx->dormantFrameChain = oldfp;
1499
+ }
1500
+
1501
+ cx->fp = &frame;
1502
+ if (hook)
1503
+ hookData = hook(cx, &frame, JS_TRUE, 0, cx->runtime->executeHookData);
1504
+
1505
+ /*
1506
+ * Use frame.rval, not result, so the last result stays rooted across any
1507
+ * GC activations nested within this js_Interpret.
1508
+ */
1509
+ ok = js_Interpret(cx, &frame.rval);
1510
+ *result = frame.rval;
1511
+
1512
+ if (hookData) {
1513
+ hook = cx->runtime->executeHook;
1514
+ if (hook)
1515
+ hook(cx, &frame, JS_FALSE, &ok, hookData);
1516
+ }
1517
+ if (mark)
1518
+ js_FreeRawStack(cx, mark);
1519
+ cx->fp = oldfp;
1520
+
1521
+ if (oldfp && oldfp != down) {
1522
+ JS_ASSERT(cx->dormantFrameChain == oldfp);
1523
+ cx->dormantFrameChain = oldfp->dormantNext;
1524
+ oldfp->dormantNext = NULL;
1525
+ }
1526
+
1527
+ return ok;
1528
+ }
1529
+
1530
+ #if JS_HAS_EXPORT_IMPORT
1531
+ /*
1532
+ * If id is JSVAL_VOID, import all exported properties from obj.
1533
+ */
1534
+ static JSBool
1535
+ ImportProperty(JSContext *cx, JSObject *obj, jsid id)
1536
+ {
1537
+ JSBool ok;
1538
+ JSIdArray *ida;
1539
+ JSProperty *prop;
1540
+ JSObject *obj2, *target, *funobj, *closure;
1541
+ JSString *str;
1542
+ uintN attrs;
1543
+ jsint i;
1544
+ jsval value;
1545
+
1546
+ if (JSVAL_IS_VOID(id)) {
1547
+ ida = JS_Enumerate(cx, obj);
1548
+ if (!ida)
1549
+ return JS_FALSE;
1550
+ ok = JS_TRUE;
1551
+ if (ida->length == 0)
1552
+ goto out;
1553
+ } else {
1554
+ ida = NULL;
1555
+ if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))
1556
+ return JS_FALSE;
1557
+ if (!prop) {
1558
+ str = js_DecompileValueGenerator(cx, JSDVG_IGNORE_STACK,
1559
+ ID_TO_VALUE(id), NULL);
1560
+ if (str)
1561
+ js_ReportIsNotDefined(cx, JS_GetStringBytes(str));
1562
+ return JS_FALSE;
1563
+ }
1564
+ ok = OBJ_GET_ATTRIBUTES(cx, obj, id, prop, &attrs);
1565
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
1566
+ if (!ok)
1567
+ return JS_FALSE;
1568
+ if (!(attrs & JSPROP_EXPORTED)) {
1569
+ str = js_DecompileValueGenerator(cx, JSDVG_IGNORE_STACK,
1570
+ ID_TO_VALUE(id), NULL);
1571
+ if (str) {
1572
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
1573
+ JSMSG_NOT_EXPORTED,
1574
+ JS_GetStringBytes(str));
1575
+ }
1576
+ return JS_FALSE;
1577
+ }
1578
+ }
1579
+
1580
+ target = cx->fp->varobj;
1581
+ i = 0;
1582
+ do {
1583
+ if (ida) {
1584
+ id = ida->vector[i];
1585
+ ok = OBJ_GET_ATTRIBUTES(cx, obj, id, NULL, &attrs);
1586
+ if (!ok)
1587
+ goto out;
1588
+ if (!(attrs & JSPROP_EXPORTED))
1589
+ continue;
1590
+ }
1591
+ ok = OBJ_CHECK_ACCESS(cx, obj, id, JSACC_IMPORT, &value, &attrs);
1592
+ if (!ok)
1593
+ goto out;
1594
+ if (JSVAL_IS_FUNCTION(cx, value)) {
1595
+ funobj = JSVAL_TO_OBJECT(value);
1596
+ closure = js_CloneFunctionObject(cx, funobj, obj);
1597
+ if (!closure) {
1598
+ ok = JS_FALSE;
1599
+ goto out;
1600
+ }
1601
+ value = OBJECT_TO_JSVAL(closure);
1602
+ }
1603
+
1604
+ /*
1605
+ * Handle the case of importing a property that refers to a local
1606
+ * variable or formal parameter of a function activation. These
1607
+ * properties are accessed by opcodes using stack slot numbers
1608
+ * generated by the compiler rather than runtime name-lookup. These
1609
+ * local references, therefore, bypass the normal scope chain lookup.
1610
+ * So, instead of defining a new property in the activation object,
1611
+ * modify the existing value in the stack slot.
1612
+ */
1613
+ if (OBJ_GET_CLASS(cx, target) == &js_CallClass) {
1614
+ ok = OBJ_LOOKUP_PROPERTY(cx, target, id, &obj2, &prop);
1615
+ if (!ok)
1616
+ goto out;
1617
+ } else {
1618
+ prop = NULL;
1619
+ }
1620
+ if (prop && target == obj2) {
1621
+ ok = OBJ_SET_PROPERTY(cx, target, id, &value);
1622
+ } else {
1623
+ ok = OBJ_DEFINE_PROPERTY(cx, target, id, value, NULL, NULL,
1624
+ attrs & ~JSPROP_EXPORTED,
1625
+ NULL);
1626
+ }
1627
+ if (prop)
1628
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
1629
+ if (!ok)
1630
+ goto out;
1631
+ } while (ida && ++i < ida->length);
1632
+
1633
+ out:
1634
+ if (ida)
1635
+ JS_DestroyIdArray(cx, ida);
1636
+ return ok;
1637
+ }
1638
+ #endif /* JS_HAS_EXPORT_IMPORT */
1639
+
1640
+ JSBool
1641
+ js_CheckRedeclaration(JSContext *cx, JSObject *obj, jsid id, uintN attrs,
1642
+ JSObject **objp, JSProperty **propp)
1643
+ {
1644
+ JSObject *obj2;
1645
+ JSProperty *prop;
1646
+ uintN oldAttrs, report;
1647
+ JSBool isFunction;
1648
+ jsval value;
1649
+ const char *type, *name;
1650
+
1651
+ if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))
1652
+ return JS_FALSE;
1653
+ if (propp) {
1654
+ *objp = obj2;
1655
+ *propp = prop;
1656
+ }
1657
+ if (!prop)
1658
+ return JS_TRUE;
1659
+
1660
+ /* From here, return true, or goto bad on failure to drop prop. */
1661
+ if (!OBJ_GET_ATTRIBUTES(cx, obj2, id, prop, &oldAttrs))
1662
+ goto bad;
1663
+
1664
+ /* If either property is readonly, we have an error. */
1665
+ report = ((oldAttrs | attrs) & JSPROP_READONLY)
1666
+ ? JSREPORT_ERROR
1667
+ : JSREPORT_WARNING | JSREPORT_STRICT;
1668
+
1669
+ if (report != JSREPORT_ERROR) {
1670
+ /*
1671
+ * Allow redeclaration of variables and functions, but insist that the
1672
+ * new value is not a getter if the old value was, ditto for setters --
1673
+ * unless prop is impermanent (in which case anyone could delete it and
1674
+ * redefine it, willy-nilly).
1675
+ */
1676
+ if (!(attrs & (JSPROP_GETTER | JSPROP_SETTER)))
1677
+ return JS_TRUE;
1678
+ if ((~(oldAttrs ^ attrs) & (JSPROP_GETTER | JSPROP_SETTER)) == 0)
1679
+ return JS_TRUE;
1680
+ if (!(oldAttrs & JSPROP_PERMANENT))
1681
+ return JS_TRUE;
1682
+ report = JSREPORT_ERROR;
1683
+ }
1684
+
1685
+ isFunction = (oldAttrs & (JSPROP_GETTER | JSPROP_SETTER)) != 0;
1686
+ if (!isFunction) {
1687
+ if (!OBJ_GET_PROPERTY(cx, obj, id, &value))
1688
+ goto bad;
1689
+ isFunction = JSVAL_IS_FUNCTION(cx, value);
1690
+ }
1691
+ type = (oldAttrs & attrs & JSPROP_GETTER)
1692
+ ? js_getter_str
1693
+ : (oldAttrs & attrs & JSPROP_SETTER)
1694
+ ? js_setter_str
1695
+ : (oldAttrs & JSPROP_READONLY)
1696
+ ? js_const_str
1697
+ : isFunction
1698
+ ? js_function_str
1699
+ : js_var_str;
1700
+ name = js_AtomToPrintableString(cx, (JSAtom *)id);
1701
+ if (!name)
1702
+ goto bad;
1703
+ return JS_ReportErrorFlagsAndNumber(cx, report,
1704
+ js_GetErrorMessage, NULL,
1705
+ JSMSG_REDECLARED_VAR,
1706
+ type, name);
1707
+
1708
+ bad:
1709
+ if (propp) {
1710
+ *objp = NULL;
1711
+ *propp = NULL;
1712
+ }
1713
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
1714
+ return JS_FALSE;
1715
+ }
1716
+
1717
+ #ifndef MAX_INTERP_LEVEL
1718
+ #if defined(XP_OS2)
1719
+ #define MAX_INTERP_LEVEL 250
1720
+ #else
1721
+ #define MAX_INTERP_LEVEL 1000
1722
+ #endif
1723
+ #endif
1724
+
1725
+ #define MAX_INLINE_CALL_COUNT 1000
1726
+
1727
+ JSBool
1728
+ js_Interpret(JSContext *cx, jsval *result)
1729
+ {
1730
+ JSRuntime *rt;
1731
+ JSStackFrame *fp;
1732
+ JSScript *script;
1733
+ uintN inlineCallCount;
1734
+ JSObject *obj, *obj2, *proto, *parent;
1735
+ JSVersion currentVersion, originalVersion;
1736
+ JSBranchCallback onbranch;
1737
+ JSBool ok, cond;
1738
+ JSTrapHandler interruptHandler;
1739
+ jsint depth, len;
1740
+ jsval *sp, *newsp;
1741
+ void *mark;
1742
+ jsbytecode *pc, *pc2, *endpc;
1743
+ JSOp op, op2;
1744
+ const JSCodeSpec *cs;
1745
+ JSAtom *atom;
1746
+ uintN argc, slot, attrs;
1747
+ jsval *vp, lval, rval, ltmp, rtmp;
1748
+ jsid id;
1749
+ JSObject *withobj, *origobj, *propobj;
1750
+ jsval iter_state;
1751
+ JSProperty *prop;
1752
+ JSScopeProperty *sprop;
1753
+ JSString *str, *str2;
1754
+ jsint i, j;
1755
+ jsdouble d, d2;
1756
+ JSClass *clasp, *funclasp;
1757
+ JSFunction *fun;
1758
+ JSType type;
1759
+ #ifdef DEBUG
1760
+ FILE *tracefp;
1761
+ #endif
1762
+ #if JS_HAS_EXPORT_IMPORT
1763
+ JSIdArray *ida;
1764
+ #endif
1765
+ #if JS_HAS_SWITCH_STATEMENT
1766
+ jsint low, high, off, npairs;
1767
+ JSBool match;
1768
+ #endif
1769
+ #if JS_HAS_GETTER_SETTER
1770
+ JSPropertyOp getter, setter;
1771
+ #endif
1772
+ int stackDummy;
1773
+
1774
+ *result = JSVAL_VOID;
1775
+ rt = cx->runtime;
1776
+
1777
+ /* Set registerized frame pointer and derived script pointer. */
1778
+ fp = cx->fp;
1779
+ script = fp->script;
1780
+
1781
+ /* Count of JS function calls that nest in this C js_Interpret frame. */
1782
+ inlineCallCount = 0;
1783
+
1784
+ /*
1785
+ * Optimized Get and SetVersion for proper script language versioning.
1786
+ *
1787
+ * If any native method or JSClass/JSObjectOps hook calls JS_SetVersion
1788
+ * and changes cx->version, the effect will "stick" and we will stop
1789
+ * maintaining currentVersion. This is relied upon by testsuites, for
1790
+ * the most part -- web browsers select version before compiling and not
1791
+ * at run-time.
1792
+ */
1793
+ currentVersion = script->version;
1794
+ originalVersion = cx->version;
1795
+ if (currentVersion != originalVersion)
1796
+ JS_SetVersion(cx, currentVersion);
1797
+
1798
+ /*
1799
+ * Prepare to call a user-supplied branch handler, and abort the script
1800
+ * if it returns false. We reload onbranch after calling out to native
1801
+ * functions (but not to getters, setters, or other native hooks).
1802
+ */
1803
+ #define LOAD_BRANCH_CALLBACK(cx) (onbranch = (cx)->branchCallback)
1804
+
1805
+ LOAD_BRANCH_CALLBACK(cx);
1806
+ ok = JS_TRUE;
1807
+ #define CHECK_BRANCH(len) \
1808
+ JS_BEGIN_MACRO \
1809
+ if (len <= 0 && onbranch) { \
1810
+ SAVE_SP(fp); \
1811
+ if (!(ok = (*onbranch)(cx, script))) \
1812
+ goto out; \
1813
+ } \
1814
+ JS_END_MACRO
1815
+
1816
+ /*
1817
+ * Load the debugger's interrupt hook here and after calling out to native
1818
+ * functions (but not to getters, setters, or other native hooks), so we do
1819
+ * not have to reload it each time through the interpreter loop -- we hope
1820
+ * the compiler can keep it in a register.
1821
+ * XXX if it spills, we still lose
1822
+ */
1823
+ #define LOAD_INTERRUPT_HANDLER(rt) (interruptHandler = (rt)->interruptHandler)
1824
+
1825
+ LOAD_INTERRUPT_HANDLER(rt);
1826
+
1827
+ pc = script->code;
1828
+ endpc = pc + script->length;
1829
+ depth = (jsint) script->depth;
1830
+ len = -1;
1831
+
1832
+ /* Check for too much js_Interpret nesting, or too deep a C stack. */
1833
+ if (++cx->interpLevel == MAX_INTERP_LEVEL ||
1834
+ !JS_CHECK_STACK_SIZE(cx, stackDummy)) {
1835
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_OVER_RECURSED);
1836
+ ok = JS_FALSE;
1837
+ goto out;
1838
+ }
1839
+
1840
+ /*
1841
+ * Allocate operand and pc stack slots for the script's worst-case depth.
1842
+ */
1843
+ newsp = js_AllocRawStack(cx, (uintN)(2 * depth), &mark);
1844
+ if (!newsp) {
1845
+ ok = JS_FALSE;
1846
+ goto out;
1847
+ }
1848
+ sp = newsp + depth;
1849
+ fp->spbase = sp;
1850
+ SAVE_SP(fp);
1851
+
1852
+ while (pc < endpc) {
1853
+ fp->pc = pc;
1854
+ op = (JSOp) *pc;
1855
+ do_op:
1856
+ cs = &js_CodeSpec[op];
1857
+ len = cs->length;
1858
+
1859
+ #ifdef DEBUG
1860
+ tracefp = (FILE *) cx->tracefp;
1861
+ if (tracefp) {
1862
+ intN nuses, n;
1863
+
1864
+ fprintf(tracefp, "%4u: ", js_PCToLineNumber(cx, script, pc));
1865
+ js_Disassemble1(cx, script, pc,
1866
+ PTRDIFF(pc, script->code, jsbytecode), JS_FALSE,
1867
+ tracefp);
1868
+ nuses = cs->nuses;
1869
+ if (nuses) {
1870
+ SAVE_SP(fp);
1871
+ for (n = -nuses; n < 0; n++) {
1872
+ str = js_DecompileValueGenerator(cx, n, sp[n], NULL);
1873
+ if (str != NULL) {
1874
+ fprintf(tracefp, "%s %s",
1875
+ (n == -nuses) ? " inputs:" : ",",
1876
+ JS_GetStringBytes(str));
1877
+ }
1878
+ }
1879
+ fprintf(tracefp, " @ %d\n", sp - fp->spbase);
1880
+ }
1881
+ }
1882
+ #endif
1883
+
1884
+ if (interruptHandler) {
1885
+ SAVE_SP(fp);
1886
+ switch (interruptHandler(cx, script, pc, &rval,
1887
+ rt->interruptHandlerData)) {
1888
+ case JSTRAP_ERROR:
1889
+ ok = JS_FALSE;
1890
+ goto out;
1891
+ case JSTRAP_CONTINUE:
1892
+ break;
1893
+ case JSTRAP_RETURN:
1894
+ fp->rval = rval;
1895
+ goto out;
1896
+ #if JS_HAS_EXCEPTIONS
1897
+ case JSTRAP_THROW:
1898
+ cx->throwing = JS_TRUE;
1899
+ cx->exception = rval;
1900
+ ok = JS_FALSE;
1901
+ goto out;
1902
+ #endif /* JS_HAS_EXCEPTIONS */
1903
+ default:;
1904
+ }
1905
+ LOAD_INTERRUPT_HANDLER(rt);
1906
+ }
1907
+
1908
+ switch (op) {
1909
+ case JSOP_NOP:
1910
+ break;
1911
+
1912
+ case JSOP_GROUP:
1913
+ obj = NULL;
1914
+ break;
1915
+
1916
+ case JSOP_PUSH:
1917
+ PUSH_OPND(JSVAL_VOID);
1918
+ break;
1919
+
1920
+ case JSOP_POP:
1921
+ sp--;
1922
+ break;
1923
+
1924
+ case JSOP_POP2:
1925
+ sp -= 2;
1926
+ break;
1927
+
1928
+ case JSOP_SWAP:
1929
+ /*
1930
+ * N.B. JSOP_SWAP doesn't swap the corresponding generating pcs
1931
+ * for the operands it swaps.
1932
+ */
1933
+ ltmp = sp[-1];
1934
+ sp[-1] = sp[-2];
1935
+ sp[-2] = ltmp;
1936
+ break;
1937
+
1938
+ case JSOP_POPV:
1939
+ *result = POP_OPND();
1940
+ break;
1941
+
1942
+ case JSOP_ENTERWITH:
1943
+ rval = FETCH_OPND(-1);
1944
+ VALUE_TO_OBJECT(cx, rval, obj);
1945
+ withobj = js_NewObject(cx, &js_WithClass, obj, fp->scopeChain);
1946
+ if (!withobj)
1947
+ goto out;
1948
+ fp->scopeChain = withobj;
1949
+ STORE_OPND(-1, OBJECT_TO_JSVAL(withobj));
1950
+ break;
1951
+
1952
+ case JSOP_LEAVEWITH:
1953
+ rval = POP_OPND();
1954
+ JS_ASSERT(JSVAL_IS_OBJECT(rval));
1955
+ withobj = JSVAL_TO_OBJECT(rval);
1956
+ JS_ASSERT(OBJ_GET_CLASS(cx, withobj) == &js_WithClass);
1957
+
1958
+ rval = OBJ_GET_SLOT(cx, withobj, JSSLOT_PARENT);
1959
+ JS_ASSERT(JSVAL_IS_OBJECT(rval));
1960
+ fp->scopeChain = JSVAL_TO_OBJECT(rval);
1961
+ break;
1962
+
1963
+ case JSOP_SETRVAL:
1964
+ fp->rval = POP_OPND();
1965
+ break;
1966
+
1967
+ case JSOP_RETURN:
1968
+ CHECK_BRANCH(-1);
1969
+ fp->rval = POP_OPND();
1970
+ /* FALL THROUGH */
1971
+
1972
+ case JSOP_RETRVAL: /* fp->rval already set */
1973
+ if (inlineCallCount)
1974
+ inline_return:
1975
+ {
1976
+ JSInlineFrame *ifp = (JSInlineFrame *) fp;
1977
+ void *hookData = ifp->hookData;
1978
+
1979
+ if (hookData) {
1980
+ JSInterpreterHook hook = cx->runtime->callHook;
1981
+ if (hook) {
1982
+ hook(cx, fp, JS_FALSE, &ok, hookData);
1983
+ LOAD_INTERRUPT_HANDLER(rt);
1984
+ }
1985
+ }
1986
+ #if JS_HAS_ARGS_OBJECT
1987
+ if (fp->argsobj)
1988
+ ok &= js_PutArgsObject(cx, fp);
1989
+ #endif
1990
+
1991
+ /* Restore context version only if callee hasn't set version. */
1992
+ if (cx->version == currentVersion) {
1993
+ currentVersion = ifp->callerVersion;
1994
+ if (currentVersion != cx->version)
1995
+ JS_SetVersion(cx, currentVersion);
1996
+ }
1997
+
1998
+ /* Store the return value in the caller's operand frame. */
1999
+ vp = fp->argv - 2;
2000
+ *vp = fp->rval;
2001
+
2002
+ /* Restore cx->fp and release the inline frame's space. */
2003
+ cx->fp = fp = fp->down;
2004
+ JS_ARENA_RELEASE(&cx->stackPool, ifp->mark);
2005
+
2006
+ /* Restore sp to point just above the return value. */
2007
+ fp->sp = vp + 1;
2008
+ RESTORE_SP(fp);
2009
+
2010
+ /* Restore the calling script's interpreter registers. */
2011
+ script = fp->script;
2012
+ depth = (jsint) script->depth;
2013
+ pc = fp->pc;
2014
+ endpc = script->code + script->length;
2015
+
2016
+ /* Store the generating pc for the return value. */
2017
+ vp[-depth] = (jsval)pc;
2018
+
2019
+ /* Set remaining variables for 'goto advance_pc'. */
2020
+ op = (JSOp) *pc;
2021
+ cs = &js_CodeSpec[op];
2022
+ len = cs->length;
2023
+
2024
+ /* Resume execution in the calling frame. */
2025
+ inlineCallCount--;
2026
+ if (ok)
2027
+ goto advance_pc;
2028
+ }
2029
+ goto out;
2030
+
2031
+ #if JS_HAS_SWITCH_STATEMENT
2032
+ case JSOP_DEFAULT:
2033
+ (void) POP();
2034
+ /* FALL THROUGH */
2035
+ #endif
2036
+ case JSOP_GOTO:
2037
+ len = GET_JUMP_OFFSET(pc);
2038
+ CHECK_BRANCH(len);
2039
+ break;
2040
+
2041
+ case JSOP_IFEQ:
2042
+ POP_BOOLEAN(cx, rval, cond);
2043
+ if (cond == JS_FALSE) {
2044
+ len = GET_JUMP_OFFSET(pc);
2045
+ CHECK_BRANCH(len);
2046
+ }
2047
+ break;
2048
+
2049
+ case JSOP_IFNE:
2050
+ POP_BOOLEAN(cx, rval, cond);
2051
+ if (cond != JS_FALSE) {
2052
+ len = GET_JUMP_OFFSET(pc);
2053
+ CHECK_BRANCH(len);
2054
+ }
2055
+ break;
2056
+
2057
+ case JSOP_OR:
2058
+ POP_BOOLEAN(cx, rval, cond);
2059
+ if (cond == JS_TRUE) {
2060
+ len = GET_JUMP_OFFSET(pc);
2061
+ PUSH_OPND(rval);
2062
+ }
2063
+ break;
2064
+
2065
+ case JSOP_AND:
2066
+ POP_BOOLEAN(cx, rval, cond);
2067
+ if (cond == JS_FALSE) {
2068
+ len = GET_JUMP_OFFSET(pc);
2069
+ PUSH_OPND(rval);
2070
+ }
2071
+ break;
2072
+
2073
+
2074
+ #if JS_HAS_SWITCH_STATEMENT
2075
+ case JSOP_DEFAULTX:
2076
+ (void) POP();
2077
+ /* FALL THROUGH */
2078
+ #endif
2079
+ case JSOP_GOTOX:
2080
+ len = GET_JUMPX_OFFSET(pc);
2081
+ CHECK_BRANCH(len);
2082
+ break;
2083
+
2084
+ case JSOP_IFEQX:
2085
+ POP_BOOLEAN(cx, rval, cond);
2086
+ if (cond == JS_FALSE) {
2087
+ len = GET_JUMPX_OFFSET(pc);
2088
+ CHECK_BRANCH(len);
2089
+ }
2090
+ break;
2091
+
2092
+ case JSOP_IFNEX:
2093
+ POP_BOOLEAN(cx, rval, cond);
2094
+ if (cond != JS_FALSE) {
2095
+ len = GET_JUMPX_OFFSET(pc);
2096
+ CHECK_BRANCH(len);
2097
+ }
2098
+ break;
2099
+
2100
+ case JSOP_ORX:
2101
+ POP_BOOLEAN(cx, rval, cond);
2102
+ if (cond == JS_TRUE) {
2103
+ len = GET_JUMPX_OFFSET(pc);
2104
+ PUSH_OPND(rval);
2105
+ }
2106
+ break;
2107
+
2108
+ case JSOP_ANDX:
2109
+ POP_BOOLEAN(cx, rval, cond);
2110
+ if (cond == JS_FALSE) {
2111
+ len = GET_JUMPX_OFFSET(pc);
2112
+ PUSH_OPND(rval);
2113
+ }
2114
+ break;
2115
+
2116
+ case JSOP_TOOBJECT:
2117
+ SAVE_SP(fp);
2118
+ ok = js_ValueToObject(cx, FETCH_OPND(-1), &obj);
2119
+ if (!ok)
2120
+ goto out;
2121
+ STORE_OPND(-1, OBJECT_TO_JSVAL(obj));
2122
+ break;
2123
+
2124
+ #define FETCH_ELEMENT_ID(n, id) \
2125
+ JS_BEGIN_MACRO \
2126
+ /* If the index is not a jsint, atomize it. */ \
2127
+ id = (jsid) FETCH_OPND(n); \
2128
+ if (JSVAL_IS_INT(id)) { \
2129
+ atom = NULL; \
2130
+ } else { \
2131
+ SAVE_SP(fp); \
2132
+ atom = js_ValueToStringAtom(cx, (jsval)id); \
2133
+ if (!atom) { \
2134
+ ok = JS_FALSE; \
2135
+ goto out; \
2136
+ } \
2137
+ id = (jsid)atom; \
2138
+ } \
2139
+ JS_END_MACRO
2140
+
2141
+ #define POP_ELEMENT_ID(id) \
2142
+ JS_BEGIN_MACRO \
2143
+ FETCH_ELEMENT_ID(-1, id); \
2144
+ sp--; \
2145
+ JS_END_MACRO
2146
+
2147
+ #if JS_HAS_IN_OPERATOR
2148
+ case JSOP_IN:
2149
+ rval = FETCH_OPND(-1);
2150
+ if (JSVAL_IS_PRIMITIVE(rval)) {
2151
+ str = js_DecompileValueGenerator(cx, -1, rval, NULL);
2152
+ if (str) {
2153
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
2154
+ JSMSG_IN_NOT_OBJECT,
2155
+ JS_GetStringBytes(str));
2156
+ }
2157
+ ok = JS_FALSE;
2158
+ goto out;
2159
+ }
2160
+ sp--;
2161
+ obj = JSVAL_TO_OBJECT(rval);
2162
+ FETCH_ELEMENT_ID(-1, id);
2163
+ ok = OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop);
2164
+ if (!ok)
2165
+ goto out;
2166
+ STORE_OPND(-1, BOOLEAN_TO_JSVAL(prop != NULL));
2167
+ if (prop)
2168
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
2169
+ break;
2170
+ #endif /* JS_HAS_IN_OPERATOR */
2171
+
2172
+ case JSOP_FORPROP:
2173
+ /*
2174
+ * Handle JSOP_FORPROP first, so the cost of the goto do_forinloop
2175
+ * is not paid for the more common cases.
2176
+ */
2177
+ lval = FETCH_OPND(-1);
2178
+ atom = GET_ATOM(cx, script, pc);
2179
+ id = (jsid)atom;
2180
+ i = -2;
2181
+ goto do_forinloop;
2182
+
2183
+ case JSOP_FORNAME:
2184
+ atom = GET_ATOM(cx, script, pc);
2185
+ id = (jsid)atom;
2186
+
2187
+ /*
2188
+ * ECMA 12.6.3 says to eval the LHS after looking for properties
2189
+ * to enumerate, and bail without LHS eval if there are no props.
2190
+ * We do Find here to share the most code at label do_forinloop.
2191
+ * If looking for enumerable properties could have side effects,
2192
+ * then we'd have to move this into the common code and condition
2193
+ * it on op == JSOP_FORNAME.
2194
+ */
2195
+ SAVE_SP(fp);
2196
+ ok = js_FindProperty(cx, id, &obj, &obj2, &prop);
2197
+ if (!ok)
2198
+ goto out;
2199
+ if (prop)
2200
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
2201
+ lval = OBJECT_TO_JSVAL(obj);
2202
+ /* FALL THROUGH */
2203
+
2204
+ case JSOP_FORARG:
2205
+ case JSOP_FORVAR:
2206
+ /*
2207
+ * JSOP_FORARG and JSOP_FORVAR don't require any lval computation
2208
+ * here, because they address slots on the stack (in fp->args and
2209
+ * fp->vars, respectively).
2210
+ */
2211
+ /* FALL THROUGH */
2212
+
2213
+ case JSOP_FORELEM:
2214
+ /*
2215
+ * JSOP_FORELEM simply initializes or updates the iteration state
2216
+ * and leaves the index expression evaluation and assignment to the
2217
+ * enumerator until after the next property has been acquired, via
2218
+ * a JSOP_ENUMELEM bytecode.
2219
+ */
2220
+ i = -1;
2221
+
2222
+ do_forinloop:
2223
+ /*
2224
+ * ECMA-compatible for/in evals the object just once, before loop.
2225
+ * Bad old bytecodes (since removed) did it on every iteration.
2226
+ */
2227
+ obj = JSVAL_TO_OBJECT(sp[i]);
2228
+
2229
+ /* If the thing to the right of 'in' has no properties, break. */
2230
+ if (!obj) {
2231
+ rval = JSVAL_FALSE;
2232
+ goto end_forinloop;
2233
+ }
2234
+
2235
+ /*
2236
+ * Save the thing to the right of 'in' as origobj. Later on, we
2237
+ * use this variable to suppress enumeration of shadowed prototype
2238
+ * properties.
2239
+ */
2240
+ origobj = obj;
2241
+
2242
+ /*
2243
+ * Reach under the top of stack to find our property iterator, a
2244
+ * JSObject that contains the iteration state. (An object is used
2245
+ * rather than a native struct so that the iteration state is
2246
+ * cleaned up via GC if the for-in loop terminates abruptly.)
2247
+ */
2248
+ vp = &sp[i - 1];
2249
+ rval = *vp;
2250
+
2251
+ /* Is this the first iteration ? */
2252
+ if (JSVAL_IS_VOID(rval)) {
2253
+ /* Yes, create a new JSObject to hold the iterator state */
2254
+ propobj = js_NewObject(cx, &prop_iterator_class, NULL, obj);
2255
+ if (!propobj) {
2256
+ ok = JS_FALSE;
2257
+ goto out;
2258
+ }
2259
+ propobj->slots[JSSLOT_ITER_STATE] = JSVAL_NULL;
2260
+
2261
+ /*
2262
+ * Root the parent slot so we can get it even in our finalizer
2263
+ * (otherwise, it would live as long as we do, but it might be
2264
+ * finalized first).
2265
+ */
2266
+ ok = js_AddRoot(cx, &propobj->slots[JSSLOT_PARENT],
2267
+ "propobj->parent");
2268
+ if (!ok)
2269
+ goto out;
2270
+
2271
+ /*
2272
+ * Rewrite the iterator so we know to do the next case.
2273
+ * Do this before calling the enumerator, which could
2274
+ * displace cx->newborn and cause GC.
2275
+ */
2276
+ *vp = OBJECT_TO_JSVAL(propobj);
2277
+
2278
+ ok = OBJ_ENUMERATE(cx, obj, JSENUMERATE_INIT, &iter_state, 0);
2279
+
2280
+ /*
2281
+ * Stash private iteration state into property iterator object.
2282
+ * We do this before checking 'ok' to ensure that propobj is
2283
+ * in a valid state even if OBJ_ENUMERATE returned JS_FALSE.
2284
+ * NB: This code knows that the first slots are pre-allocated.
2285
+ */
2286
+ #if JS_INITIAL_NSLOTS < 5
2287
+ #error JS_INITIAL_NSLOTS must be greater than or equal to 5.
2288
+ #endif
2289
+ propobj->slots[JSSLOT_ITER_STATE] = iter_state;
2290
+ if (!ok)
2291
+ goto out;
2292
+ } else {
2293
+ /* This is not the first iteration. Recover iterator state. */
2294
+ propobj = JSVAL_TO_OBJECT(rval);
2295
+ JS_ASSERT(OBJ_GET_CLASS(cx, propobj) == &prop_iterator_class);
2296
+ obj = JSVAL_TO_OBJECT(propobj->slots[JSSLOT_PARENT]);
2297
+ iter_state = propobj->slots[JSSLOT_ITER_STATE];
2298
+ }
2299
+
2300
+ enum_next_property:
2301
+ /* Get the next jsid to be enumerated and store it in rval. */
2302
+ OBJ_ENUMERATE(cx, obj, JSENUMERATE_NEXT, &iter_state, &rval);
2303
+ propobj->slots[JSSLOT_ITER_STATE] = iter_state;
2304
+
2305
+ /* No more jsids to iterate in obj? */
2306
+ if (iter_state == JSVAL_NULL) {
2307
+ /* Enumerate the properties on obj's prototype chain. */
2308
+ obj = OBJ_GET_PROTO(cx, obj);
2309
+ if (!obj) {
2310
+ /* End of property list -- terminate loop. */
2311
+ rval = JSVAL_FALSE;
2312
+ goto end_forinloop;
2313
+ }
2314
+
2315
+ ok = OBJ_ENUMERATE(cx, obj, JSENUMERATE_INIT, &iter_state, 0);
2316
+
2317
+ /*
2318
+ * Stash private iteration state into property iterator object.
2319
+ * We do this before checking 'ok' to ensure that propobj is
2320
+ * in a valid state even if OBJ_ENUMERATE returned JS_FALSE.
2321
+ * NB: This code knows that the first slots are pre-allocated.
2322
+ */
2323
+ propobj->slots[JSSLOT_ITER_STATE] = iter_state;
2324
+ if (!ok)
2325
+ goto out;
2326
+
2327
+ /*
2328
+ * Update the iterator JSObject's parent link to refer to the
2329
+ * current object. This is used in the iterator JSObject's
2330
+ * finalizer.
2331
+ */
2332
+ propobj->slots[JSSLOT_PARENT] = OBJECT_TO_JSVAL(obj);
2333
+ goto enum_next_property;
2334
+ }
2335
+
2336
+ /* Skip properties not owned by obj, and leave next id in rval. */
2337
+ ok = OBJ_LOOKUP_PROPERTY(cx, origobj, rval, &obj2, &prop);
2338
+ if (!ok)
2339
+ goto out;
2340
+ if (prop) {
2341
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
2342
+
2343
+ /* Yes, don't enumerate again. Go to the next property. */
2344
+ if (obj2 != obj)
2345
+ goto enum_next_property;
2346
+ }
2347
+
2348
+ /* Make sure rval is a string for uniformity and compatibility. */
2349
+ if (!JSVAL_IS_INT(rval)) {
2350
+ rval = ATOM_KEY((JSAtom *)rval);
2351
+ } else if (cx->version != JSVERSION_1_2) {
2352
+ str = js_NumberToString(cx, (jsdouble) JSVAL_TO_INT(rval));
2353
+ if (!str) {
2354
+ ok = JS_FALSE;
2355
+ goto out;
2356
+ }
2357
+
2358
+ rval = STRING_TO_JSVAL(str);
2359
+ }
2360
+
2361
+ switch (op) {
2362
+ case JSOP_FORARG:
2363
+ slot = GET_ARGNO(pc);
2364
+ JS_ASSERT(slot < fp->fun->nargs);
2365
+ fp->argv[slot] = rval;
2366
+ break;
2367
+
2368
+ case JSOP_FORVAR:
2369
+ slot = GET_VARNO(pc);
2370
+ JS_ASSERT(slot < fp->fun->nvars);
2371
+ fp->vars[slot] = rval;
2372
+ break;
2373
+
2374
+ case JSOP_FORELEM:
2375
+ /* FORELEM is not a SET operation, it's more like BINDNAME. */
2376
+ PUSH_OPND(rval);
2377
+ break;
2378
+
2379
+ default:
2380
+ /* Convert lval to a non-null object containing id. */
2381
+ VALUE_TO_OBJECT(cx, lval, obj);
2382
+
2383
+ /* Set the variable obj[id] to refer to rval. */
2384
+ fp->flags |= JSFRAME_ASSIGNING;
2385
+ ok = OBJ_SET_PROPERTY(cx, obj, id, &rval);
2386
+ fp->flags &= ~JSFRAME_ASSIGNING;
2387
+ if (!ok)
2388
+ goto out;
2389
+ break;
2390
+ }
2391
+
2392
+ /* Push true to keep looping through properties. */
2393
+ rval = JSVAL_TRUE;
2394
+
2395
+ end_forinloop:
2396
+ sp += i + 1;
2397
+ PUSH_OPND(rval);
2398
+ break;
2399
+
2400
+ case JSOP_DUP:
2401
+ JS_ASSERT(sp > fp->spbase);
2402
+ rval = sp[-1];
2403
+ PUSH_OPND(rval);
2404
+ break;
2405
+
2406
+ case JSOP_DUP2:
2407
+ JS_ASSERT(sp - 1 > fp->spbase);
2408
+ lval = FETCH_OPND(-2);
2409
+ rval = FETCH_OPND(-1);
2410
+ PUSH_OPND(lval);
2411
+ PUSH_OPND(rval);
2412
+ break;
2413
+
2414
+ #define PROPERTY_OP(n, call) \
2415
+ JS_BEGIN_MACRO \
2416
+ /* Pop the left part and resolve it to a non-null object. */ \
2417
+ lval = FETCH_OPND(n); \
2418
+ VALUE_TO_OBJECT(cx, lval, obj); \
2419
+ \
2420
+ /* Get or set the property, set ok false if error, true if success. */\
2421
+ SAVE_SP(fp); \
2422
+ call; \
2423
+ if (!ok) \
2424
+ goto out; \
2425
+ JS_END_MACRO
2426
+
2427
+ #define ELEMENT_OP(n, call) \
2428
+ JS_BEGIN_MACRO \
2429
+ FETCH_ELEMENT_ID(n, id); \
2430
+ PROPERTY_OP(n-1, call); \
2431
+ JS_END_MACRO
2432
+
2433
+ /*
2434
+ * Direct callers, i.e. those who do not wrap CACHED_GET and CACHED_SET calls
2435
+ * in PROPERTY_OP or ELEMENT_OP macro calls must SAVE_SP(fp); beforehand, just
2436
+ * in case a getter or setter function is invoked.
2437
+ */
2438
+ #define CACHED_GET(call) \
2439
+ JS_BEGIN_MACRO \
2440
+ if (!OBJ_IS_NATIVE(obj)) { \
2441
+ ok = call; \
2442
+ } else { \
2443
+ JS_LOCK_OBJ(cx, obj); \
2444
+ PROPERTY_CACHE_TEST(&rt->propertyCache, obj, id, sprop); \
2445
+ if (sprop) { \
2446
+ JSScope *scope_ = OBJ_SCOPE(obj); \
2447
+ slot = (uintN)sprop->slot; \
2448
+ rval = (slot != SPROP_INVALID_SLOT) \
2449
+ ? LOCKED_OBJ_GET_SLOT(obj, slot) \
2450
+ : JSVAL_VOID; \
2451
+ JS_UNLOCK_SCOPE(cx, scope_); \
2452
+ ok = SPROP_GET(cx, sprop, obj, obj, &rval); \
2453
+ JS_LOCK_SCOPE(cx, scope_); \
2454
+ if (ok && SPROP_HAS_VALID_SLOT(sprop, scope_)) \
2455
+ LOCKED_OBJ_SET_SLOT(obj, slot, rval); \
2456
+ JS_UNLOCK_SCOPE(cx, scope_); \
2457
+ } else { \
2458
+ JS_UNLOCK_OBJ(cx, obj); \
2459
+ ok = call; \
2460
+ /* No fill here: js_GetProperty fills the cache. */ \
2461
+ } \
2462
+ } \
2463
+ JS_END_MACRO
2464
+
2465
+ #define CACHED_SET(call) \
2466
+ JS_BEGIN_MACRO \
2467
+ if (!OBJ_IS_NATIVE(obj)) { \
2468
+ ok = call; \
2469
+ } else { \
2470
+ JSScope *scope_; \
2471
+ JS_LOCK_OBJ(cx, obj); \
2472
+ PROPERTY_CACHE_TEST(&rt->propertyCache, obj, id, sprop); \
2473
+ if (sprop && \
2474
+ !(sprop->attrs & JSPROP_READONLY) && \
2475
+ (scope_ = OBJ_SCOPE(obj), !SCOPE_IS_SEALED(scope_))) { \
2476
+ JS_UNLOCK_SCOPE(cx, scope_); \
2477
+ ok = SPROP_SET(cx, sprop, obj, obj, &rval); \
2478
+ JS_LOCK_SCOPE(cx, scope_); \
2479
+ if (ok && SPROP_HAS_VALID_SLOT(sprop, scope_)) { \
2480
+ LOCKED_OBJ_SET_SLOT(obj, sprop->slot, rval); \
2481
+ GC_POKE(cx, JSVAL_NULL); /* XXX second arg ignored */ \
2482
+ } \
2483
+ JS_UNLOCK_SCOPE(cx, scope_); \
2484
+ } else { \
2485
+ JS_UNLOCK_OBJ(cx, obj); \
2486
+ ok = call; \
2487
+ /* No fill here: js_SetProperty writes through the cache. */ \
2488
+ } \
2489
+ } \
2490
+ JS_END_MACRO
2491
+
2492
+ case JSOP_SETCONST:
2493
+ obj = fp->varobj;
2494
+ atom = GET_ATOM(cx, script, pc);
2495
+ rval = FETCH_OPND(-1);
2496
+ ok = OBJ_DEFINE_PROPERTY(cx, obj, (jsid)atom, rval, NULL, NULL,
2497
+ JSPROP_ENUMERATE | JSPROP_PERMANENT |
2498
+ JSPROP_READONLY,
2499
+ NULL);
2500
+ if (!ok)
2501
+ goto out;
2502
+ STORE_OPND(-1, rval);
2503
+ break;
2504
+
2505
+ case JSOP_BINDNAME:
2506
+ atom = GET_ATOM(cx, script, pc);
2507
+ SAVE_SP(fp);
2508
+ obj = js_FindIdentifierBase(cx, (jsid)atom);
2509
+ if (!obj) {
2510
+ ok = JS_FALSE;
2511
+ goto out;
2512
+ }
2513
+ PUSH_OPND(OBJECT_TO_JSVAL(obj));
2514
+ break;
2515
+
2516
+ case JSOP_SETNAME:
2517
+ atom = GET_ATOM(cx, script, pc);
2518
+ id = (jsid)atom;
2519
+ rval = FETCH_OPND(-1);
2520
+ lval = FETCH_OPND(-2);
2521
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(lval));
2522
+ obj = JSVAL_TO_OBJECT(lval);
2523
+ SAVE_SP(fp);
2524
+ CACHED_SET(OBJ_SET_PROPERTY(cx, obj, id, &rval));
2525
+ if (!ok)
2526
+ goto out;
2527
+ sp--;
2528
+ STORE_OPND(-1, rval);
2529
+ break;
2530
+
2531
+ #define INTEGER_OP(OP, EXTRA_CODE) \
2532
+ JS_BEGIN_MACRO \
2533
+ FETCH_INT(cx, -1, j); \
2534
+ FETCH_INT(cx, -2, i); \
2535
+ if (!ok) \
2536
+ goto out; \
2537
+ EXTRA_CODE \
2538
+ d = i OP j; \
2539
+ sp--; \
2540
+ STORE_NUMBER(cx, -1, d); \
2541
+ JS_END_MACRO
2542
+
2543
+ #define BITWISE_OP(OP) INTEGER_OP(OP, (void) 0;)
2544
+ #define SIGNED_SHIFT_OP(OP) INTEGER_OP(OP, j &= 31;)
2545
+
2546
+ case JSOP_BITOR:
2547
+ BITWISE_OP(|);
2548
+ break;
2549
+
2550
+ case JSOP_BITXOR:
2551
+ BITWISE_OP(^);
2552
+ break;
2553
+
2554
+ case JSOP_BITAND:
2555
+ BITWISE_OP(&);
2556
+ break;
2557
+
2558
+ #if defined(XP_WIN)
2559
+ #define COMPARE_DOUBLES(LVAL, OP, RVAL, IFNAN) \
2560
+ ((JSDOUBLE_IS_NaN(LVAL) || JSDOUBLE_IS_NaN(RVAL)) \
2561
+ ? (IFNAN) \
2562
+ : (LVAL) OP (RVAL))
2563
+ #else
2564
+ #define COMPARE_DOUBLES(LVAL, OP, RVAL, IFNAN) ((LVAL) OP (RVAL))
2565
+ #endif
2566
+
2567
+ #define RELATIONAL_OP(OP) \
2568
+ JS_BEGIN_MACRO \
2569
+ rval = FETCH_OPND(-1); \
2570
+ lval = FETCH_OPND(-2); \
2571
+ /* Optimize for two int-tagged operands (typical loop control). */ \
2572
+ if ((lval & rval) & JSVAL_INT) { \
2573
+ ltmp = lval ^ JSVAL_VOID; \
2574
+ rtmp = rval ^ JSVAL_VOID; \
2575
+ if (ltmp && rtmp) { \
2576
+ cond = JSVAL_TO_INT(lval) OP JSVAL_TO_INT(rval); \
2577
+ } else { \
2578
+ d = ltmp ? JSVAL_TO_INT(lval) : *rt->jsNaN; \
2579
+ d2 = rtmp ? JSVAL_TO_INT(rval) : *rt->jsNaN; \
2580
+ cond = COMPARE_DOUBLES(d, OP, d2, JS_FALSE); \
2581
+ } \
2582
+ } else { \
2583
+ VALUE_TO_PRIMITIVE(cx, lval, JSTYPE_NUMBER, &lval); \
2584
+ VALUE_TO_PRIMITIVE(cx, rval, JSTYPE_NUMBER, &rval); \
2585
+ if (JSVAL_IS_STRING(lval) && JSVAL_IS_STRING(rval)) { \
2586
+ str = JSVAL_TO_STRING(lval); \
2587
+ str2 = JSVAL_TO_STRING(rval); \
2588
+ cond = js_CompareStrings(str, str2) OP 0; \
2589
+ } else { \
2590
+ VALUE_TO_NUMBER(cx, lval, d); \
2591
+ VALUE_TO_NUMBER(cx, rval, d2); \
2592
+ cond = COMPARE_DOUBLES(d, OP, d2, JS_FALSE); \
2593
+ } \
2594
+ } \
2595
+ sp--; \
2596
+ STORE_OPND(-1, BOOLEAN_TO_JSVAL(cond)); \
2597
+ JS_END_MACRO
2598
+
2599
+ #define EQUALITY_OP(OP, IFNAN) \
2600
+ JS_BEGIN_MACRO \
2601
+ rval = FETCH_OPND(-1); \
2602
+ lval = FETCH_OPND(-2); \
2603
+ ltmp = JSVAL_TAG(lval); \
2604
+ rtmp = JSVAL_TAG(rval); \
2605
+ if (ltmp == rtmp) { \
2606
+ if (ltmp == JSVAL_STRING) { \
2607
+ str = JSVAL_TO_STRING(lval); \
2608
+ str2 = JSVAL_TO_STRING(rval); \
2609
+ cond = js_CompareStrings(str, str2) OP 0; \
2610
+ } else if (ltmp == JSVAL_DOUBLE) { \
2611
+ d = *JSVAL_TO_DOUBLE(lval); \
2612
+ d2 = *JSVAL_TO_DOUBLE(rval); \
2613
+ cond = COMPARE_DOUBLES(d, OP, d2, IFNAN); \
2614
+ } else { \
2615
+ /* Handle all undefined (=>NaN) and int combinations. */ \
2616
+ cond = lval OP rval; \
2617
+ } \
2618
+ } else { \
2619
+ if (JSVAL_IS_NULL(lval) || JSVAL_IS_VOID(lval)) { \
2620
+ cond = (JSVAL_IS_NULL(rval) || JSVAL_IS_VOID(rval)) OP 1; \
2621
+ } else if (JSVAL_IS_NULL(rval) || JSVAL_IS_VOID(rval)) { \
2622
+ cond = 1 OP 0; \
2623
+ } else { \
2624
+ if (ltmp == JSVAL_OBJECT) { \
2625
+ VALUE_TO_PRIMITIVE(cx, lval, JSTYPE_VOID, &lval); \
2626
+ ltmp = JSVAL_TAG(lval); \
2627
+ } else if (rtmp == JSVAL_OBJECT) { \
2628
+ VALUE_TO_PRIMITIVE(cx, rval, JSTYPE_VOID, &rval); \
2629
+ rtmp = JSVAL_TAG(rval); \
2630
+ } \
2631
+ if (ltmp == JSVAL_STRING && rtmp == JSVAL_STRING) { \
2632
+ str = JSVAL_TO_STRING(lval); \
2633
+ str2 = JSVAL_TO_STRING(rval); \
2634
+ cond = js_CompareStrings(str, str2) OP 0; \
2635
+ } else { \
2636
+ VALUE_TO_NUMBER(cx, lval, d); \
2637
+ VALUE_TO_NUMBER(cx, rval, d2); \
2638
+ cond = COMPARE_DOUBLES(d, OP, d2, IFNAN); \
2639
+ } \
2640
+ } \
2641
+ } \
2642
+ sp--; \
2643
+ STORE_OPND(-1, BOOLEAN_TO_JSVAL(cond)); \
2644
+ JS_END_MACRO
2645
+
2646
+ case JSOP_EQ:
2647
+ EQUALITY_OP(==, JS_FALSE);
2648
+ break;
2649
+
2650
+ case JSOP_NE:
2651
+ EQUALITY_OP(!=, JS_TRUE);
2652
+ break;
2653
+
2654
+ #if !JS_BUG_FALLIBLE_EQOPS
2655
+ #define NEW_EQUALITY_OP(OP, IFNAN) \
2656
+ JS_BEGIN_MACRO \
2657
+ rval = FETCH_OPND(-1); \
2658
+ lval = FETCH_OPND(-2); \
2659
+ ltmp = JSVAL_TAG(lval); \
2660
+ rtmp = JSVAL_TAG(rval); \
2661
+ if (ltmp == rtmp) { \
2662
+ if (ltmp == JSVAL_STRING) { \
2663
+ str = JSVAL_TO_STRING(lval); \
2664
+ str2 = JSVAL_TO_STRING(rval); \
2665
+ cond = js_CompareStrings(str, str2) OP 0; \
2666
+ } else if (ltmp == JSVAL_DOUBLE) { \
2667
+ d = *JSVAL_TO_DOUBLE(lval); \
2668
+ d2 = *JSVAL_TO_DOUBLE(rval); \
2669
+ cond = COMPARE_DOUBLES(d, OP, d2, IFNAN); \
2670
+ } else { \
2671
+ cond = lval OP rval; \
2672
+ } \
2673
+ } else { \
2674
+ if (ltmp == JSVAL_DOUBLE && JSVAL_IS_INT(rval)) { \
2675
+ d = *JSVAL_TO_DOUBLE(lval); \
2676
+ d2 = JSVAL_TO_INT(rval); \
2677
+ cond = COMPARE_DOUBLES(d, OP, d2, IFNAN); \
2678
+ } else if (JSVAL_IS_INT(lval) && rtmp == JSVAL_DOUBLE) { \
2679
+ d = JSVAL_TO_INT(lval); \
2680
+ d2 = *JSVAL_TO_DOUBLE(rval); \
2681
+ cond = COMPARE_DOUBLES(d, OP, d2, IFNAN); \
2682
+ } else { \
2683
+ cond = lval OP rval; \
2684
+ } \
2685
+ } \
2686
+ sp--; \
2687
+ STORE_OPND(-1, BOOLEAN_TO_JSVAL(cond)); \
2688
+ JS_END_MACRO
2689
+
2690
+ case JSOP_NEW_EQ:
2691
+ NEW_EQUALITY_OP(==, JS_FALSE);
2692
+ break;
2693
+
2694
+ case JSOP_NEW_NE:
2695
+ NEW_EQUALITY_OP(!=, JS_TRUE);
2696
+ break;
2697
+
2698
+ #if JS_HAS_SWITCH_STATEMENT
2699
+ case JSOP_CASE:
2700
+ NEW_EQUALITY_OP(==, JS_FALSE);
2701
+ (void) POP();
2702
+ if (cond) {
2703
+ len = GET_JUMP_OFFSET(pc);
2704
+ CHECK_BRANCH(len);
2705
+ } else {
2706
+ PUSH(lval);
2707
+ }
2708
+ break;
2709
+
2710
+ case JSOP_CASEX:
2711
+ NEW_EQUALITY_OP(==, JS_FALSE);
2712
+ (void) POP();
2713
+ if (cond) {
2714
+ len = GET_JUMPX_OFFSET(pc);
2715
+ CHECK_BRANCH(len);
2716
+ } else {
2717
+ PUSH(lval);
2718
+ }
2719
+ break;
2720
+ #endif
2721
+
2722
+ #endif /* !JS_BUG_FALLIBLE_EQOPS */
2723
+
2724
+ case JSOP_LT:
2725
+ RELATIONAL_OP(<);
2726
+ break;
2727
+
2728
+ case JSOP_LE:
2729
+ RELATIONAL_OP(<=);
2730
+ break;
2731
+
2732
+ case JSOP_GT:
2733
+ RELATIONAL_OP(>);
2734
+ break;
2735
+
2736
+ case JSOP_GE:
2737
+ RELATIONAL_OP(>=);
2738
+ break;
2739
+
2740
+ #undef EQUALITY_OP
2741
+ #undef RELATIONAL_OP
2742
+
2743
+ case JSOP_LSH:
2744
+ SIGNED_SHIFT_OP(<<);
2745
+ break;
2746
+
2747
+ case JSOP_RSH:
2748
+ SIGNED_SHIFT_OP(>>);
2749
+ break;
2750
+
2751
+ case JSOP_URSH:
2752
+ {
2753
+ uint32 u;
2754
+
2755
+ FETCH_INT(cx, -1, j);
2756
+ FETCH_UINT(cx, -2, u);
2757
+ j &= 31;
2758
+ d = u >> j;
2759
+ sp--;
2760
+ STORE_NUMBER(cx, -1, d);
2761
+ break;
2762
+ }
2763
+
2764
+ #undef INTEGER_OP
2765
+ #undef BITWISE_OP
2766
+ #undef SIGNED_SHIFT_OP
2767
+
2768
+ case JSOP_ADD:
2769
+ rval = FETCH_OPND(-1);
2770
+ lval = FETCH_OPND(-2);
2771
+ VALUE_TO_PRIMITIVE(cx, lval, JSTYPE_VOID, &ltmp);
2772
+ VALUE_TO_PRIMITIVE(cx, rval, JSTYPE_VOID, &rtmp);
2773
+ if ((cond = JSVAL_IS_STRING(ltmp)) || JSVAL_IS_STRING(rtmp)) {
2774
+ SAVE_SP(fp);
2775
+ if (cond) {
2776
+ str = JSVAL_TO_STRING(ltmp);
2777
+ ok = (str2 = js_ValueToString(cx, rtmp)) != NULL;
2778
+ } else {
2779
+ str2 = JSVAL_TO_STRING(rtmp);
2780
+ ok = (str = js_ValueToString(cx, ltmp)) != NULL;
2781
+ }
2782
+ if (!ok)
2783
+ goto out;
2784
+ str = js_ConcatStrings(cx, str, str2);
2785
+ if (!str) {
2786
+ ok = JS_FALSE;
2787
+ goto out;
2788
+ }
2789
+ sp--;
2790
+ STORE_OPND(-1, STRING_TO_JSVAL(str));
2791
+ } else {
2792
+ VALUE_TO_NUMBER(cx, lval, d);
2793
+ VALUE_TO_NUMBER(cx, rval, d2);
2794
+ d += d2;
2795
+ sp--;
2796
+ STORE_NUMBER(cx, -1, d);
2797
+ }
2798
+ break;
2799
+
2800
+ #define BINARY_OP(OP) \
2801
+ JS_BEGIN_MACRO \
2802
+ FETCH_NUMBER(cx, -1, d2); \
2803
+ FETCH_NUMBER(cx, -2, d); \
2804
+ d = d OP d2; \
2805
+ sp--; \
2806
+ STORE_NUMBER(cx, -1, d); \
2807
+ JS_END_MACRO
2808
+
2809
+ case JSOP_SUB:
2810
+ BINARY_OP(-);
2811
+ break;
2812
+
2813
+ case JSOP_MUL:
2814
+ BINARY_OP(*);
2815
+ break;
2816
+
2817
+ case JSOP_DIV:
2818
+ FETCH_NUMBER(cx, -1, d2);
2819
+ FETCH_NUMBER(cx, -2, d);
2820
+ sp--;
2821
+ if (d2 == 0) {
2822
+ #if defined(XP_WIN)
2823
+ /* XXX MSVC miscompiles such that (NaN == 0) */
2824
+ if (JSDOUBLE_IS_NaN(d2))
2825
+ rval = DOUBLE_TO_JSVAL(rt->jsNaN);
2826
+ else
2827
+ #endif
2828
+ if (d == 0 || JSDOUBLE_IS_NaN(d))
2829
+ rval = DOUBLE_TO_JSVAL(rt->jsNaN);
2830
+ else if ((JSDOUBLE_HI32(d) ^ JSDOUBLE_HI32(d2)) >> 31)
2831
+ rval = DOUBLE_TO_JSVAL(rt->jsNegativeInfinity);
2832
+ else
2833
+ rval = DOUBLE_TO_JSVAL(rt->jsPositiveInfinity);
2834
+ STORE_OPND(-1, rval);
2835
+ } else {
2836
+ d /= d2;
2837
+ STORE_NUMBER(cx, -1, d);
2838
+ }
2839
+ break;
2840
+
2841
+ case JSOP_MOD:
2842
+ FETCH_NUMBER(cx, -1, d2);
2843
+ FETCH_NUMBER(cx, -2, d);
2844
+ sp--;
2845
+ if (d2 == 0) {
2846
+ STORE_OPND(-1, DOUBLE_TO_JSVAL(rt->jsNaN));
2847
+ } else {
2848
+ #if defined(XP_WIN)
2849
+ /* Workaround MS fmod bug where 42 % (1/0) => NaN, not 42. */
2850
+ if (!(JSDOUBLE_IS_FINITE(d) && JSDOUBLE_IS_INFINITE(d2)))
2851
+ #endif
2852
+ d = fmod(d, d2);
2853
+ STORE_NUMBER(cx, -1, d);
2854
+ }
2855
+ break;
2856
+
2857
+ case JSOP_NOT:
2858
+ POP_BOOLEAN(cx, rval, cond);
2859
+ PUSH_OPND(BOOLEAN_TO_JSVAL(!cond));
2860
+ break;
2861
+
2862
+ case JSOP_BITNOT:
2863
+ FETCH_INT(cx, -1, i);
2864
+ d = (jsdouble) ~i;
2865
+ STORE_NUMBER(cx, -1, d);
2866
+ break;
2867
+
2868
+ case JSOP_NEG:
2869
+ FETCH_NUMBER(cx, -1, d);
2870
+ #ifdef HPUX
2871
+ /*
2872
+ * Negation of a zero doesn't produce a negative
2873
+ * zero on HPUX. Perform the operation by bit
2874
+ * twiddling.
2875
+ */
2876
+ JSDOUBLE_HI32(d) ^= JSDOUBLE_HI32_SIGNBIT;
2877
+ #else
2878
+ d = -d;
2879
+ #endif
2880
+ STORE_NUMBER(cx, -1, d);
2881
+ break;
2882
+
2883
+ case JSOP_POS:
2884
+ FETCH_NUMBER(cx, -1, d);
2885
+ STORE_NUMBER(cx, -1, d);
2886
+ break;
2887
+
2888
+ case JSOP_NEW:
2889
+ /* Get immediate argc and find the constructor function. */
2890
+ argc = GET_ARGC(pc);
2891
+
2892
+ #if JS_HAS_INITIALIZERS
2893
+ do_new:
2894
+ #endif
2895
+ vp = sp - (2 + argc);
2896
+ JS_ASSERT(vp >= fp->spbase);
2897
+
2898
+ fun = NULL;
2899
+ obj2 = NULL;
2900
+ lval = *vp;
2901
+ if (!JSVAL_IS_OBJECT(lval) ||
2902
+ (obj2 = JSVAL_TO_OBJECT(lval)) == NULL ||
2903
+ /* XXX clean up to avoid special cases above ObjectOps layer */
2904
+ OBJ_GET_CLASS(cx, obj2) == &js_FunctionClass ||
2905
+ !obj2->map->ops->construct)
2906
+ {
2907
+ SAVE_SP(fp);
2908
+ fun = js_ValueToFunction(cx, vp, JSV2F_CONSTRUCT);
2909
+ if (!fun) {
2910
+ ok = JS_FALSE;
2911
+ goto out;
2912
+ }
2913
+ }
2914
+
2915
+ clasp = &js_ObjectClass;
2916
+ if (!obj2) {
2917
+ proto = parent = NULL;
2918
+ fun = NULL;
2919
+ } else {
2920
+ /* Get the constructor prototype object for this function. */
2921
+ ok = OBJ_GET_PROPERTY(cx, obj2,
2922
+ (jsid)rt->atomState.classPrototypeAtom,
2923
+ &rval);
2924
+ if (!ok)
2925
+ goto out;
2926
+ proto = JSVAL_IS_OBJECT(rval) ? JSVAL_TO_OBJECT(rval) : NULL;
2927
+ parent = OBJ_GET_PARENT(cx, obj2);
2928
+
2929
+ if (OBJ_GET_CLASS(cx, obj2) == &js_FunctionClass) {
2930
+ funclasp = ((JSFunction *)JS_GetPrivate(cx, obj2))->clasp;
2931
+ if (funclasp)
2932
+ clasp = funclasp;
2933
+ }
2934
+ }
2935
+ obj = js_NewObject(cx, clasp, proto, parent);
2936
+ if (!obj) {
2937
+ ok = JS_FALSE;
2938
+ goto out;
2939
+ }
2940
+
2941
+ /* Now we have an object with a constructor method; call it. */
2942
+ vp[1] = OBJECT_TO_JSVAL(obj);
2943
+ SAVE_SP(fp);
2944
+ ok = js_Invoke(cx, argc, JSINVOKE_CONSTRUCT);
2945
+ RESTORE_SP(fp);
2946
+ LOAD_BRANCH_CALLBACK(cx);
2947
+ LOAD_INTERRUPT_HANDLER(rt);
2948
+ if (!ok) {
2949
+ cx->newborn[GCX_OBJECT] = NULL;
2950
+ goto out;
2951
+ }
2952
+
2953
+ /* Check the return value and update obj from it. */
2954
+ rval = *vp;
2955
+ if (JSVAL_IS_PRIMITIVE(rval)) {
2956
+ if (fun || !JSVERSION_IS_ECMA(cx->version)) {
2957
+ *vp = OBJECT_TO_JSVAL(obj);
2958
+ break;
2959
+ }
2960
+ /* native [[Construct]] returning primitive is error */
2961
+ str = js_ValueToString(cx, rval);
2962
+ if (str) {
2963
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
2964
+ JSMSG_BAD_NEW_RESULT,
2965
+ JS_GetStringBytes(str));
2966
+ }
2967
+ ok = JS_FALSE;
2968
+ goto out;
2969
+ }
2970
+ obj = JSVAL_TO_OBJECT(rval);
2971
+ JS_RUNTIME_METER(rt, constructs);
2972
+ break;
2973
+
2974
+ case JSOP_DELNAME:
2975
+ atom = GET_ATOM(cx, script, pc);
2976
+ id = (jsid)atom;
2977
+
2978
+ SAVE_SP(fp);
2979
+ ok = js_FindProperty(cx, id, &obj, &obj2, &prop);
2980
+ if (!ok)
2981
+ goto out;
2982
+
2983
+ /* ECMA says to return true if name is undefined or inherited. */
2984
+ rval = JSVAL_TRUE;
2985
+ if (prop) {
2986
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
2987
+ ok = OBJ_DELETE_PROPERTY(cx, obj, id, &rval);
2988
+ if (!ok)
2989
+ goto out;
2990
+ }
2991
+ PUSH_OPND(rval);
2992
+ break;
2993
+
2994
+ case JSOP_DELPROP:
2995
+ atom = GET_ATOM(cx, script, pc);
2996
+ id = (jsid)atom;
2997
+ PROPERTY_OP(-1, ok = OBJ_DELETE_PROPERTY(cx, obj, id, &rval));
2998
+ STORE_OPND(-1, rval);
2999
+ break;
3000
+
3001
+ case JSOP_DELELEM:
3002
+ ELEMENT_OP(-1, ok = OBJ_DELETE_PROPERTY(cx, obj, id, &rval));
3003
+ sp--;
3004
+ STORE_OPND(-1, rval);
3005
+ break;
3006
+
3007
+ case JSOP_TYPEOF:
3008
+ rval = POP_OPND();
3009
+ type = JS_TypeOfValue(cx, rval);
3010
+ atom = rt->atomState.typeAtoms[type];
3011
+ str = ATOM_TO_STRING(atom);
3012
+ PUSH_OPND(STRING_TO_JSVAL(str));
3013
+ break;
3014
+
3015
+ case JSOP_VOID:
3016
+ (void) POP_OPND();
3017
+ PUSH_OPND(JSVAL_VOID);
3018
+ break;
3019
+
3020
+ case JSOP_INCNAME:
3021
+ case JSOP_DECNAME:
3022
+ case JSOP_NAMEINC:
3023
+ case JSOP_NAMEDEC:
3024
+ atom = GET_ATOM(cx, script, pc);
3025
+ id = (jsid)atom;
3026
+
3027
+ SAVE_SP(fp);
3028
+ ok = js_FindProperty(cx, id, &obj, &obj2, &prop);
3029
+ if (!ok)
3030
+ goto out;
3031
+ if (!prop)
3032
+ goto atom_not_defined;
3033
+
3034
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
3035
+ lval = OBJECT_TO_JSVAL(obj);
3036
+ goto do_incop;
3037
+
3038
+ case JSOP_INCPROP:
3039
+ case JSOP_DECPROP:
3040
+ case JSOP_PROPINC:
3041
+ case JSOP_PROPDEC:
3042
+ atom = GET_ATOM(cx, script, pc);
3043
+ id = (jsid)atom;
3044
+ lval = POP_OPND();
3045
+ goto do_incop;
3046
+
3047
+ case JSOP_INCELEM:
3048
+ case JSOP_DECELEM:
3049
+ case JSOP_ELEMINC:
3050
+ case JSOP_ELEMDEC:
3051
+ POP_ELEMENT_ID(id);
3052
+ lval = POP_OPND();
3053
+
3054
+ do_incop:
3055
+ VALUE_TO_OBJECT(cx, lval, obj);
3056
+
3057
+ /* The operand must contain a number. */
3058
+ SAVE_SP(fp);
3059
+ CACHED_GET(OBJ_GET_PROPERTY(cx, obj, id, &rval));
3060
+ if (!ok)
3061
+ goto out;
3062
+
3063
+ /* The expression result goes in rtmp, the updated value in rval. */
3064
+ if (JSVAL_IS_INT(rval) &&
3065
+ rval != INT_TO_JSVAL(JSVAL_INT_MIN) &&
3066
+ rval != INT_TO_JSVAL(JSVAL_INT_MAX)) {
3067
+ if (cs->format & JOF_POST) {
3068
+ rtmp = rval;
3069
+ (cs->format & JOF_INC) ? (rval += 2) : (rval -= 2);
3070
+ } else {
3071
+ (cs->format & JOF_INC) ? (rval += 2) : (rval -= 2);
3072
+ rtmp = rval;
3073
+ }
3074
+ } else {
3075
+
3076
+ /*
3077
+ * Initially, rval contains the value to increment or decrement, which is not
3078
+ * yet converted. As above, the expression result goes in rtmp, the updated
3079
+ * value goes in rval.
3080
+ */
3081
+ #define NONINT_INCREMENT_OP_MIDDLE() \
3082
+ JS_BEGIN_MACRO \
3083
+ VALUE_TO_NUMBER(cx, rval, d); \
3084
+ if (cs->format & JOF_POST) { \
3085
+ rtmp = rval; \
3086
+ if (!JSVAL_IS_NUMBER(rtmp)) { \
3087
+ ok = js_NewNumberValue(cx, d, &rtmp); \
3088
+ if (!ok) \
3089
+ goto out; \
3090
+ } \
3091
+ (cs->format & JOF_INC) ? d++ : d--; \
3092
+ ok = js_NewNumberValue(cx, d, &rval); \
3093
+ } else { \
3094
+ (cs->format & JOF_INC) ? ++d : --d; \
3095
+ ok = js_NewNumberValue(cx, d, &rval); \
3096
+ rtmp = rval; \
3097
+ } \
3098
+ if (!ok) \
3099
+ goto out; \
3100
+ JS_END_MACRO
3101
+
3102
+ NONINT_INCREMENT_OP_MIDDLE();
3103
+ }
3104
+
3105
+ CACHED_SET(OBJ_SET_PROPERTY(cx, obj, id, &rval));
3106
+ if (!ok)
3107
+ goto out;
3108
+ PUSH_OPND(rtmp);
3109
+ break;
3110
+
3111
+ /*
3112
+ * NB: This macro can't use JS_BEGIN_MACRO/JS_END_MACRO around its body because
3113
+ * it must break from the switch case that calls it, not from the do...while(0)
3114
+ * loop created by the JS_BEGIN/END_MACRO brackets.
3115
+ */
3116
+ #define FAST_INCREMENT_OP(SLOT,COUNT,BASE,PRE,OP,MINMAX) \
3117
+ slot = SLOT; \
3118
+ JS_ASSERT(slot < fp->fun->COUNT); \
3119
+ vp = fp->BASE + slot; \
3120
+ rval = *vp; \
3121
+ if (JSVAL_IS_INT(rval) && \
3122
+ rval != INT_TO_JSVAL(JSVAL_INT_##MINMAX)) { \
3123
+ PRE = rval; \
3124
+ rval OP 2; \
3125
+ *vp = rval; \
3126
+ PUSH_OPND(PRE); \
3127
+ break; \
3128
+ } \
3129
+ goto do_nonint_fast_incop;
3130
+
3131
+ case JSOP_INCARG:
3132
+ FAST_INCREMENT_OP(GET_ARGNO(pc), nargs, argv, rval, +=, MAX);
3133
+ case JSOP_DECARG:
3134
+ FAST_INCREMENT_OP(GET_ARGNO(pc), nargs, argv, rval, -=, MIN);
3135
+ case JSOP_ARGINC:
3136
+ FAST_INCREMENT_OP(GET_ARGNO(pc), nargs, argv, rtmp, +=, MAX);
3137
+ case JSOP_ARGDEC:
3138
+ FAST_INCREMENT_OP(GET_ARGNO(pc), nargs, argv, rtmp, -=, MIN);
3139
+
3140
+ case JSOP_INCVAR:
3141
+ FAST_INCREMENT_OP(GET_VARNO(pc), nvars, vars, rval, +=, MAX);
3142
+ case JSOP_DECVAR:
3143
+ FAST_INCREMENT_OP(GET_VARNO(pc), nvars, vars, rval, -=, MIN);
3144
+ case JSOP_VARINC:
3145
+ FAST_INCREMENT_OP(GET_VARNO(pc), nvars, vars, rtmp, +=, MAX);
3146
+ case JSOP_VARDEC:
3147
+ FAST_INCREMENT_OP(GET_VARNO(pc), nvars, vars, rtmp, -=, MIN);
3148
+
3149
+ #undef FAST_INCREMENT_OP
3150
+
3151
+ do_nonint_fast_incop:
3152
+ NONINT_INCREMENT_OP_MIDDLE();
3153
+ *vp = rval;
3154
+ PUSH_OPND(rtmp);
3155
+ break;
3156
+
3157
+ #define FAST_GLOBAL_INCREMENT_OP(SLOWOP,PRE,OP,MINMAX) \
3158
+ slot = GET_VARNO(pc); \
3159
+ JS_ASSERT(slot < fp->nvars); \
3160
+ lval = fp->vars[slot]; \
3161
+ if (JSVAL_IS_NULL(lval)) { \
3162
+ op = SLOWOP; \
3163
+ goto do_op; \
3164
+ } \
3165
+ slot = JSVAL_TO_INT(lval); \
3166
+ obj = fp->varobj; \
3167
+ rval = OBJ_GET_SLOT(cx, obj, slot); \
3168
+ if (JSVAL_IS_INT(rval) && \
3169
+ rval != INT_TO_JSVAL(JSVAL_INT_##MINMAX)) { \
3170
+ PRE = rval; \
3171
+ rval OP 2; \
3172
+ OBJ_SET_SLOT(cx, obj, slot, rval); \
3173
+ PUSH_OPND(PRE); \
3174
+ break; \
3175
+ } \
3176
+ goto do_nonint_fast_global_incop;
3177
+
3178
+ case JSOP_INCGVAR:
3179
+ FAST_GLOBAL_INCREMENT_OP(JSOP_INCNAME, rval, +=, MAX);
3180
+ case JSOP_DECGVAR:
3181
+ FAST_GLOBAL_INCREMENT_OP(JSOP_DECNAME, rval, -=, MIN);
3182
+ case JSOP_GVARINC:
3183
+ FAST_GLOBAL_INCREMENT_OP(JSOP_NAMEINC, rtmp, +=, MAX);
3184
+ case JSOP_GVARDEC:
3185
+ FAST_GLOBAL_INCREMENT_OP(JSOP_NAMEDEC, rtmp, -=, MIN);
3186
+
3187
+ #undef FAST_GLOBAL_INCREMENT_OP
3188
+
3189
+ do_nonint_fast_global_incop:
3190
+ NONINT_INCREMENT_OP_MIDDLE();
3191
+ OBJ_SET_SLOT(cx, obj, slot, rval);
3192
+ PUSH_OPND(rtmp);
3193
+ break;
3194
+
3195
+ case JSOP_GETPROP:
3196
+ /* Get an immediate atom naming the property. */
3197
+ atom = GET_ATOM(cx, script, pc);
3198
+ id = (jsid)atom;
3199
+ PROPERTY_OP(-1, CACHED_GET(OBJ_GET_PROPERTY(cx, obj, id, &rval)));
3200
+ STORE_OPND(-1, rval);
3201
+ break;
3202
+
3203
+ case JSOP_SETPROP:
3204
+ /* Pop the right-hand side into rval for OBJ_SET_PROPERTY. */
3205
+ rval = FETCH_OPND(-1);
3206
+
3207
+ /* Get an immediate atom naming the property. */
3208
+ atom = GET_ATOM(cx, script, pc);
3209
+ id = (jsid)atom;
3210
+ PROPERTY_OP(-2, CACHED_SET(OBJ_SET_PROPERTY(cx, obj, id, &rval)));
3211
+ sp--;
3212
+ STORE_OPND(-1, rval);
3213
+ break;
3214
+
3215
+ case JSOP_GETELEM:
3216
+ ELEMENT_OP(-1, CACHED_GET(OBJ_GET_PROPERTY(cx, obj, id, &rval)));
3217
+ sp--;
3218
+ STORE_OPND(-1, rval);
3219
+ break;
3220
+
3221
+ case JSOP_SETELEM:
3222
+ rval = FETCH_OPND(-1);
3223
+ ELEMENT_OP(-2, CACHED_SET(OBJ_SET_PROPERTY(cx, obj, id, &rval)));
3224
+ sp -= 2;
3225
+ STORE_OPND(-1, rval);
3226
+ break;
3227
+
3228
+ case JSOP_ENUMELEM:
3229
+ /* Funky: the value to set is under the [obj, id] pair. */
3230
+ FETCH_ELEMENT_ID(-1, id);
3231
+ lval = FETCH_OPND(-2);
3232
+ VALUE_TO_OBJECT(cx, lval, obj);
3233
+ rval = FETCH_OPND(-3);
3234
+ SAVE_SP(fp);
3235
+ ok = OBJ_SET_PROPERTY(cx, obj, id, &rval);
3236
+ if (!ok)
3237
+ goto out;
3238
+ sp -= 3;
3239
+ break;
3240
+
3241
+ /*
3242
+ * LAZY_ARGS_THISP allows the JSOP_ARGSUB bytecode to defer creation of the
3243
+ * arguments object until it is truly needed. JSOP_ARGSUB optimizes away
3244
+ * arguments objects when the only uses of the 'arguments' parameter are to
3245
+ * fetch individual actual parameters. But if such a use were then invoked,
3246
+ * e.g., arguments[i](), the 'this' parameter would and must bind to the
3247
+ * caller's arguments object. So JSOP_ARGSUB sets obj to LAZY_ARGS_THISP.
3248
+ */
3249
+ #define LAZY_ARGS_THISP ((JSObject *) 1)
3250
+
3251
+ case JSOP_PUSHOBJ:
3252
+ if (obj == LAZY_ARGS_THISP && !(obj = js_GetArgsObject(cx, fp))) {
3253
+ ok = JS_FALSE;
3254
+ goto out;
3255
+ }
3256
+ PUSH_OPND(OBJECT_TO_JSVAL(obj));
3257
+ break;
3258
+
3259
+ case JSOP_CALL:
3260
+ case JSOP_EVAL:
3261
+ argc = GET_ARGC(pc);
3262
+ vp = sp - (argc + 2);
3263
+ lval = *vp;
3264
+ SAVE_SP(fp);
3265
+
3266
+ if (JSVAL_IS_FUNCTION(cx, lval) &&
3267
+ (obj = JSVAL_TO_OBJECT(lval),
3268
+ fun = (JSFunction *) JS_GetPrivate(cx, obj),
3269
+ fun->interpreted &&
3270
+ !(fun->flags & (JSFUN_HEAVYWEIGHT | JSFUN_BOUND_METHOD)) &&
3271
+ argc >= (uintN)(fun->nargs + fun->extra)))
3272
+ /* inline_call: */
3273
+ {
3274
+ uintN nframeslots, nvars;
3275
+ void *newmark;
3276
+ JSInlineFrame *newifp;
3277
+ JSInterpreterHook hook;
3278
+
3279
+ /* Restrict recursion of lightweight functions. */
3280
+ if (inlineCallCount == MAX_INLINE_CALL_COUNT) {
3281
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
3282
+ JSMSG_OVER_RECURSED);
3283
+ ok = JS_FALSE;
3284
+ goto out;
3285
+ }
3286
+
3287
+ #if JS_HAS_JIT
3288
+ /* ZZZbe should do this only if interpreted often enough. */
3289
+ ok = jsjit_Compile(cx, fun);
3290
+ if (!ok)
3291
+ goto out;
3292
+ #endif
3293
+
3294
+ /* Compute the number of stack slots needed for fun. */
3295
+ nframeslots = (sizeof(JSInlineFrame) + sizeof(jsval) - 1)
3296
+ / sizeof(jsval);
3297
+ nvars = fun->nvars;
3298
+ script = fun->u.script;
3299
+ depth = (jsint) script->depth;
3300
+
3301
+ /* Allocate the frame and space for vars and operands. */
3302
+ newsp = js_AllocRawStack(cx, nframeslots + nvars + 2 * depth,
3303
+ &newmark);
3304
+ if (!newsp) {
3305
+ ok = JS_FALSE;
3306
+ goto bad_inline_call;
3307
+ }
3308
+ newifp = (JSInlineFrame *) newsp;
3309
+ newsp += nframeslots;
3310
+
3311
+ /* Initialize the stack frame. */
3312
+ memset(newifp, 0, sizeof(JSInlineFrame));
3313
+ newifp->frame.script = script;
3314
+ newifp->frame.fun = fun;
3315
+ newifp->frame.argc = argc;
3316
+ newifp->frame.argv = vp + 2;
3317
+ newifp->frame.rval = JSVAL_VOID;
3318
+ newifp->frame.nvars = nvars;
3319
+ newifp->frame.vars = newsp;
3320
+ newifp->frame.down = fp;
3321
+ newifp->frame.scopeChain = OBJ_GET_PARENT(cx, obj);
3322
+ newifp->mark = newmark;
3323
+
3324
+ /* Compute the 'this' parameter now that argv is set. */
3325
+ ok = ComputeThis(cx, JSVAL_TO_OBJECT(vp[1]), &newifp->frame);
3326
+ if (!ok) {
3327
+ js_FreeRawStack(cx, newmark);
3328
+ goto bad_inline_call;
3329
+ }
3330
+ #ifdef DUMP_CALL_TABLE
3331
+ LogCall(cx, *vp, argc, vp + 2);
3332
+ #endif
3333
+
3334
+ /* Push void to initialize local variables. */
3335
+ sp = newsp;
3336
+ while (nvars--)
3337
+ PUSH(JSVAL_VOID);
3338
+ sp += depth;
3339
+ newifp->frame.spbase = sp;
3340
+ SAVE_SP(&newifp->frame);
3341
+
3342
+ /* Call the debugger hook if present. */
3343
+ hook = cx->runtime->callHook;
3344
+ if (hook) {
3345
+ newifp->hookData = hook(cx, &newifp->frame, JS_TRUE, 0,
3346
+ cx->runtime->callHookData);
3347
+ LOAD_INTERRUPT_HANDLER(rt);
3348
+ }
3349
+
3350
+ /* Switch to new version if currentVersion wasn't overridden. */
3351
+ newifp->callerVersion = cx->version;
3352
+ if (cx->version == currentVersion) {
3353
+ currentVersion = script->version;
3354
+ if (currentVersion != cx->version)
3355
+ JS_SetVersion(cx, currentVersion);
3356
+ }
3357
+
3358
+ /* Push the frame and set interpreter registers. */
3359
+ cx->fp = fp = &newifp->frame;
3360
+ pc = script->code;
3361
+ endpc = pc + script->length;
3362
+ inlineCallCount++;
3363
+ JS_RUNTIME_METER(rt, inlineCalls);
3364
+ continue;
3365
+
3366
+ bad_inline_call:
3367
+ script = fp->script;
3368
+ depth = (jsint) script->depth;
3369
+ goto out;
3370
+ }
3371
+
3372
+ ok = js_Invoke(cx, argc, 0);
3373
+ RESTORE_SP(fp);
3374
+ LOAD_BRANCH_CALLBACK(cx);
3375
+ LOAD_INTERRUPT_HANDLER(rt);
3376
+ if (!ok)
3377
+ goto out;
3378
+ JS_RUNTIME_METER(rt, nonInlineCalls);
3379
+ #if JS_HAS_LVALUE_RETURN
3380
+ if (cx->rval2set) {
3381
+ /*
3382
+ * Sneaky: use the stack depth we didn't claim in our budget,
3383
+ * but that we know is there on account of [fun, this] already
3384
+ * having been pushed, at a minimum (if no args). Those two
3385
+ * slots have been popped and [rval] has been pushed, which
3386
+ * leaves one more slot for rval2 before we might overflow.
3387
+ *
3388
+ * NB: rval2 must be the property identifier, and rval the
3389
+ * object from which to get the property. The pair form an
3390
+ * ECMA "reference type", which can be used on the right- or
3391
+ * left-hand side of assignment ops. Only native methods can
3392
+ * return reference types. See JSOP_SETCALL just below for
3393
+ * the left-hand-side case.
3394
+ */
3395
+ PUSH_OPND(cx->rval2);
3396
+ cx->rval2set = JS_FALSE;
3397
+ ELEMENT_OP(-1, ok = OBJ_GET_PROPERTY(cx, obj, id, &rval));
3398
+ sp--;
3399
+ STORE_OPND(-1, rval);
3400
+ }
3401
+ #endif
3402
+ obj = NULL;
3403
+ break;
3404
+
3405
+ #if JS_HAS_LVALUE_RETURN
3406
+ case JSOP_SETCALL:
3407
+ argc = GET_ARGC(pc);
3408
+ SAVE_SP(fp);
3409
+ ok = js_Invoke(cx, argc, 0);
3410
+ RESTORE_SP(fp);
3411
+ LOAD_BRANCH_CALLBACK(cx);
3412
+ LOAD_INTERRUPT_HANDLER(rt);
3413
+ if (!ok)
3414
+ goto out;
3415
+ if (!cx->rval2set) {
3416
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
3417
+ JSMSG_BAD_LEFTSIDE_OF_ASS);
3418
+ ok = JS_FALSE;
3419
+ goto out;
3420
+ }
3421
+ PUSH_OPND(cx->rval2);
3422
+ cx->rval2set = JS_FALSE;
3423
+ obj = NULL;
3424
+ break;
3425
+ #endif
3426
+
3427
+ case JSOP_NAME:
3428
+ atom = GET_ATOM(cx, script, pc);
3429
+ id = (jsid)atom;
3430
+
3431
+ SAVE_SP(fp);
3432
+ ok = js_FindProperty(cx, id, &obj, &obj2, &prop);
3433
+ if (!ok)
3434
+ goto out;
3435
+ if (!prop) {
3436
+ /* Kludge to allow (typeof foo == "undefined") tests. */
3437
+ for (pc2 = pc + len; pc2 < endpc; pc2++) {
3438
+ op2 = (JSOp)*pc2;
3439
+ if (op2 == JSOP_TYPEOF) {
3440
+ PUSH_OPND(JSVAL_VOID);
3441
+ goto advance_pc;
3442
+ }
3443
+ if (op2 != JSOP_GROUP)
3444
+ break;
3445
+ }
3446
+ goto atom_not_defined;
3447
+ }
3448
+
3449
+ /* Take the slow path if prop was not found in a native object. */
3450
+ if (!OBJ_IS_NATIVE(obj) || !OBJ_IS_NATIVE(obj2)) {
3451
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
3452
+ ok = OBJ_GET_PROPERTY(cx, obj, id, &rval);
3453
+ if (!ok)
3454
+ goto out;
3455
+ PUSH_OPND(rval);
3456
+ break;
3457
+ }
3458
+
3459
+ /* Get and push the obj[id] property's value. */
3460
+ sprop = (JSScopeProperty *)prop;
3461
+ slot = (uintN)sprop->slot;
3462
+ rval = (slot != SPROP_INVALID_SLOT)
3463
+ ? LOCKED_OBJ_GET_SLOT(obj2, slot)
3464
+ : JSVAL_VOID;
3465
+ JS_UNLOCK_OBJ(cx, obj2);
3466
+ ok = SPROP_GET(cx, sprop, obj, obj2, &rval);
3467
+ JS_LOCK_OBJ(cx, obj2);
3468
+ if (!ok) {
3469
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
3470
+ goto out;
3471
+ }
3472
+ if (SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj2)))
3473
+ LOCKED_OBJ_SET_SLOT(obj2, slot, rval);
3474
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
3475
+ PUSH_OPND(rval);
3476
+ break;
3477
+
3478
+ case JSOP_UINT16:
3479
+ i = (jsint) GET_ATOM_INDEX(pc);
3480
+ rval = INT_TO_JSVAL(i);
3481
+ PUSH_OPND(rval);
3482
+ obj = NULL;
3483
+ break;
3484
+
3485
+ case JSOP_NUMBER:
3486
+ case JSOP_STRING:
3487
+ case JSOP_OBJECT:
3488
+ atom = GET_ATOM(cx, script, pc);
3489
+ PUSH_OPND(ATOM_KEY(atom));
3490
+ obj = NULL;
3491
+ break;
3492
+
3493
+ case JSOP_REGEXP:
3494
+ {
3495
+ JSRegExp *re;
3496
+ JSObject *funobj;
3497
+
3498
+ /*
3499
+ * Push a regexp object for the atom mapped by the bytecode at pc,
3500
+ * cloning the literal's regexp object if necessary, to simulate in
3501
+ * the pre-compile/execute-later case what ECMA specifies for the
3502
+ * compile-and-go case: that scanning each regexp literal creates
3503
+ * a single corresponding RegExp object.
3504
+ *
3505
+ * To support pre-compilation transparently, we must handle the
3506
+ * case where a regexp object literal is used in a different global
3507
+ * at execution time from the global with which it was scanned at
3508
+ * compile time. We do this by re-wrapping the JSRegExp private
3509
+ * data struct with a cloned object having the right prototype and
3510
+ * parent, and having its own lastIndex property value storage.
3511
+ *
3512
+ * Unlike JSOP_DEFFUN and other prolog bytecodes that may clone
3513
+ * literal objects, we don't want to pay a script prolog execution
3514
+ * price for all regexp literals in a script (many may not be used
3515
+ * by a particular execution of that script, depending on control
3516
+ * flow), so we initialize lazily here.
3517
+ *
3518
+ * XXX This code is specific to regular expression objects. If we
3519
+ * need a similar op for other kinds of object literals, we should
3520
+ * push cloning down under JSObjectOps and reuse code here.
3521
+ */
3522
+ atom = GET_ATOM(cx, script, pc);
3523
+ JS_ASSERT(ATOM_IS_OBJECT(atom));
3524
+ obj = ATOM_TO_OBJECT(atom);
3525
+ JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_RegExpClass);
3526
+
3527
+ re = (JSRegExp *) JS_GetPrivate(cx, obj);
3528
+ slot = re->cloneIndex;
3529
+ if (fp->fun) {
3530
+ /*
3531
+ * We're in function code, not global or eval code (in eval
3532
+ * code, JSOP_REGEXP is never emitted). The code generator
3533
+ * recorded in fp->fun->nregexps the number of re->cloneIndex
3534
+ * slots that it reserved in the cloned funobj.
3535
+ */
3536
+ funobj = JSVAL_TO_OBJECT(fp->argv[-2]);
3537
+ slot += JSCLASS_RESERVED_SLOTS(&js_FunctionClass);
3538
+ if (!JS_GetReservedSlot(cx, funobj, slot, &rval))
3539
+ return JS_FALSE;
3540
+ if (JSVAL_IS_VOID(rval))
3541
+ rval = JSVAL_NULL;
3542
+ } else {
3543
+ /*
3544
+ * We're in global code. The code generator already arranged
3545
+ * via script->numGlobalVars to reserve a global variable slot
3546
+ * at cloneIndex. All global variable slots are initialized
3547
+ * to null, not void, for faster testing in JSOP_*GVAR cases.
3548
+ */
3549
+ rval = fp->vars[slot];
3550
+ #ifdef __GNUC__
3551
+ funobj = NULL; /* suppress bogus gcc warnings */
3552
+ #endif
3553
+ }
3554
+
3555
+ if (JSVAL_IS_NULL(rval)) {
3556
+ /* Compute the current global object in obj2. */
3557
+ obj2 = fp->scopeChain;
3558
+ while ((parent = OBJ_GET_PARENT(cx, obj2)) != NULL)
3559
+ obj2 = parent;
3560
+
3561
+ /*
3562
+ * If obj's parent is not obj2, we must clone obj so that it
3563
+ * has the right parent, and therefore, the right prototype.
3564
+ *
3565
+ * Yes, this means we assume that the correct RegExp.prototype
3566
+ * to which regexp instances (including literals) delegate can
3567
+ * be distinguished solely by the instance's parent, which was
3568
+ * set to the parent of the RegExp constructor function object
3569
+ * when the instance was created. In other words,
3570
+ *
3571
+ * (/x/.__parent__ == RegExp.__parent__) implies
3572
+ * (/x/.__proto__ == RegExp.prototype)
3573
+ *
3574
+ * (unless you assign a different object to RegExp.prototype
3575
+ * at runtime, in which case, ECMA doesn't specify operation,
3576
+ * and you get what you deserve).
3577
+ *
3578
+ * This same coupling between instance parent and constructor
3579
+ * parent turns up everywhere (see jsobj.c's FindConstructor,
3580
+ * js_ConstructObject, and js_NewObject). It's fundamental to
3581
+ * the design of the language when you consider multiple global
3582
+ * objects and separate compilation and execution, even though
3583
+ * it is not specified fully in ECMA.
3584
+ */
3585
+ if (OBJ_GET_PARENT(cx, obj) != obj2) {
3586
+ obj = js_CloneRegExpObject(cx, obj, obj2);
3587
+ if (!obj) {
3588
+ ok = JS_FALSE;
3589
+ goto out;
3590
+ }
3591
+ }
3592
+ rval = OBJECT_TO_JSVAL(obj);
3593
+
3594
+ /* Store the regexp object value in its cloneIndex slot. */
3595
+ if (fp->fun) {
3596
+ if (!JS_SetReservedSlot(cx, funobj, slot, rval))
3597
+ return JS_FALSE;
3598
+ } else {
3599
+ fp->vars[slot] = rval;
3600
+ }
3601
+ }
3602
+
3603
+ PUSH_OPND(rval);
3604
+ obj = NULL;
3605
+ break;
3606
+ }
3607
+
3608
+ case JSOP_ZERO:
3609
+ PUSH_OPND(JSVAL_ZERO);
3610
+ obj = NULL;
3611
+ break;
3612
+
3613
+ case JSOP_ONE:
3614
+ PUSH_OPND(JSVAL_ONE);
3615
+ obj = NULL;
3616
+ break;
3617
+
3618
+ case JSOP_NULL:
3619
+ PUSH_OPND(JSVAL_NULL);
3620
+ obj = NULL;
3621
+ break;
3622
+
3623
+ case JSOP_THIS:
3624
+ PUSH_OPND(OBJECT_TO_JSVAL(fp->thisp));
3625
+ obj = NULL;
3626
+ break;
3627
+
3628
+ case JSOP_FALSE:
3629
+ PUSH_OPND(JSVAL_FALSE);
3630
+ obj = NULL;
3631
+ break;
3632
+
3633
+ case JSOP_TRUE:
3634
+ PUSH_OPND(JSVAL_TRUE);
3635
+ obj = NULL;
3636
+ break;
3637
+
3638
+ #if JS_HAS_SWITCH_STATEMENT
3639
+ case JSOP_TABLESWITCH:
3640
+ pc2 = pc;
3641
+ len = GET_JUMP_OFFSET(pc2);
3642
+
3643
+ /*
3644
+ * ECMAv2 forbids conversion of discriminant, so we will skip to
3645
+ * the default case if the discriminant isn't already an int jsval.
3646
+ * (This opcode is emitted only for dense jsint-domain switches.)
3647
+ */
3648
+ if (cx->version == JSVERSION_DEFAULT ||
3649
+ cx->version >= JSVERSION_1_4) {
3650
+ rval = POP_OPND();
3651
+ if (!JSVAL_IS_INT(rval))
3652
+ break;
3653
+ i = JSVAL_TO_INT(rval);
3654
+ } else {
3655
+ FETCH_INT(cx, -1, i);
3656
+ sp--;
3657
+ }
3658
+
3659
+ pc2 += JUMP_OFFSET_LEN;
3660
+ low = GET_JUMP_OFFSET(pc2);
3661
+ pc2 += JUMP_OFFSET_LEN;
3662
+ high = GET_JUMP_OFFSET(pc2);
3663
+
3664
+ i -= low;
3665
+ if ((jsuint)i < (jsuint)(high - low + 1)) {
3666
+ pc2 += JUMP_OFFSET_LEN + JUMP_OFFSET_LEN * i;
3667
+ off = (jsint) GET_JUMP_OFFSET(pc2);
3668
+ if (off)
3669
+ len = off;
3670
+ }
3671
+ break;
3672
+
3673
+ case JSOP_LOOKUPSWITCH:
3674
+ lval = POP_OPND();
3675
+ pc2 = pc;
3676
+ len = GET_JUMP_OFFSET(pc2);
3677
+
3678
+ if (!JSVAL_IS_NUMBER(lval) &&
3679
+ !JSVAL_IS_STRING(lval) &&
3680
+ !JSVAL_IS_BOOLEAN(lval)) {
3681
+ goto advance_pc;
3682
+ }
3683
+
3684
+ pc2 += JUMP_OFFSET_LEN;
3685
+ npairs = (jsint) GET_ATOM_INDEX(pc2);
3686
+ pc2 += ATOM_INDEX_LEN;
3687
+
3688
+ #define SEARCH_PAIRS(MATCH_CODE) \
3689
+ while (npairs) { \
3690
+ atom = GET_ATOM(cx, script, pc2); \
3691
+ rval = ATOM_KEY(atom); \
3692
+ MATCH_CODE \
3693
+ if (match) { \
3694
+ pc2 += ATOM_INDEX_LEN; \
3695
+ len = GET_JUMP_OFFSET(pc2); \
3696
+ goto advance_pc; \
3697
+ } \
3698
+ pc2 += ATOM_INDEX_LEN + JUMP_OFFSET_LEN; \
3699
+ npairs--; \
3700
+ }
3701
+ if (JSVAL_IS_STRING(lval)) {
3702
+ str = JSVAL_TO_STRING(lval);
3703
+ SEARCH_PAIRS(
3704
+ match = (JSVAL_IS_STRING(rval) &&
3705
+ ((str2 = JSVAL_TO_STRING(rval)) == str ||
3706
+ !js_CompareStrings(str2, str)));
3707
+ )
3708
+ } else if (JSVAL_IS_DOUBLE(lval)) {
3709
+ d = *JSVAL_TO_DOUBLE(lval);
3710
+ SEARCH_PAIRS(
3711
+ match = (JSVAL_IS_DOUBLE(rval) &&
3712
+ *JSVAL_TO_DOUBLE(rval) == d);
3713
+ )
3714
+ } else {
3715
+ SEARCH_PAIRS(
3716
+ match = (lval == rval);
3717
+ )
3718
+ }
3719
+ #undef SEARCH_PAIRS
3720
+ break;
3721
+
3722
+ case JSOP_TABLESWITCHX:
3723
+ pc2 = pc;
3724
+ len = GET_JUMPX_OFFSET(pc2);
3725
+
3726
+ /*
3727
+ * ECMAv2 forbids conversion of discriminant, so we will skip to
3728
+ * the default case if the discriminant isn't already an int jsval.
3729
+ * (This opcode is emitted only for dense jsint-domain switches.)
3730
+ */
3731
+ if (cx->version == JSVERSION_DEFAULT ||
3732
+ cx->version >= JSVERSION_1_4) {
3733
+ rval = POP_OPND();
3734
+ if (!JSVAL_IS_INT(rval))
3735
+ break;
3736
+ i = JSVAL_TO_INT(rval);
3737
+ } else {
3738
+ FETCH_INT(cx, -1, i);
3739
+ sp--;
3740
+ }
3741
+
3742
+ pc2 += JUMPX_OFFSET_LEN;
3743
+ low = GET_JUMP_OFFSET(pc2);
3744
+ pc2 += JUMP_OFFSET_LEN;
3745
+ high = GET_JUMP_OFFSET(pc2);
3746
+
3747
+ i -= low;
3748
+ if ((jsuint)i < (jsuint)(high - low + 1)) {
3749
+ pc2 += JUMP_OFFSET_LEN + JUMPX_OFFSET_LEN * i;
3750
+ off = (jsint) GET_JUMPX_OFFSET(pc2);
3751
+ if (off)
3752
+ len = off;
3753
+ }
3754
+ break;
3755
+
3756
+ case JSOP_LOOKUPSWITCHX:
3757
+ lval = POP_OPND();
3758
+ pc2 = pc;
3759
+ len = GET_JUMPX_OFFSET(pc2);
3760
+
3761
+ if (!JSVAL_IS_NUMBER(lval) &&
3762
+ !JSVAL_IS_STRING(lval) &&
3763
+ !JSVAL_IS_BOOLEAN(lval)) {
3764
+ goto advance_pc;
3765
+ }
3766
+
3767
+ pc2 += JUMPX_OFFSET_LEN;
3768
+ npairs = (jsint) GET_ATOM_INDEX(pc2);
3769
+ pc2 += ATOM_INDEX_LEN;
3770
+
3771
+ #define SEARCH_EXTENDED_PAIRS(MATCH_CODE) \
3772
+ while (npairs) { \
3773
+ atom = GET_ATOM(cx, script, pc2); \
3774
+ rval = ATOM_KEY(atom); \
3775
+ MATCH_CODE \
3776
+ if (match) { \
3777
+ pc2 += ATOM_INDEX_LEN; \
3778
+ len = GET_JUMPX_OFFSET(pc2); \
3779
+ goto advance_pc; \
3780
+ } \
3781
+ pc2 += ATOM_INDEX_LEN + JUMPX_OFFSET_LEN; \
3782
+ npairs--; \
3783
+ }
3784
+ if (JSVAL_IS_STRING(lval)) {
3785
+ str = JSVAL_TO_STRING(lval);
3786
+ SEARCH_EXTENDED_PAIRS(
3787
+ match = (JSVAL_IS_STRING(rval) &&
3788
+ ((str2 = JSVAL_TO_STRING(rval)) == str ||
3789
+ !js_CompareStrings(str2, str)));
3790
+ )
3791
+ } else if (JSVAL_IS_DOUBLE(lval)) {
3792
+ d = *JSVAL_TO_DOUBLE(lval);
3793
+ SEARCH_EXTENDED_PAIRS(
3794
+ match = (JSVAL_IS_DOUBLE(rval) &&
3795
+ *JSVAL_TO_DOUBLE(rval) == d);
3796
+ )
3797
+ } else {
3798
+ SEARCH_EXTENDED_PAIRS(
3799
+ match = (lval == rval);
3800
+ )
3801
+ }
3802
+ #undef SEARCH_EXTENDED_PAIRS
3803
+ break;
3804
+
3805
+ case JSOP_CONDSWITCH:
3806
+ break;
3807
+
3808
+ #endif /* JS_HAS_SWITCH_STATEMENT */
3809
+
3810
+ #if JS_HAS_EXPORT_IMPORT
3811
+ case JSOP_EXPORTALL:
3812
+ obj = fp->varobj;
3813
+ ida = JS_Enumerate(cx, obj);
3814
+ if (!ida) {
3815
+ ok = JS_FALSE;
3816
+ } else {
3817
+ for (i = 0, j = ida->length; i < j; i++) {
3818
+ id = ida->vector[i];
3819
+ ok = OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop);
3820
+ if (!ok)
3821
+ break;
3822
+ if (!prop)
3823
+ continue;
3824
+ ok = OBJ_GET_ATTRIBUTES(cx, obj, id, prop, &attrs);
3825
+ if (ok) {
3826
+ attrs |= JSPROP_EXPORTED;
3827
+ ok = OBJ_SET_ATTRIBUTES(cx, obj, id, prop, &attrs);
3828
+ }
3829
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
3830
+ if (!ok)
3831
+ break;
3832
+ }
3833
+ JS_DestroyIdArray(cx, ida);
3834
+ }
3835
+ break;
3836
+
3837
+ case JSOP_EXPORTNAME:
3838
+ atom = GET_ATOM(cx, script, pc);
3839
+ id = (jsid)atom;
3840
+ obj = fp->varobj;
3841
+ ok = OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop);
3842
+ if (!ok)
3843
+ goto out;
3844
+ if (!prop) {
3845
+ ok = OBJ_DEFINE_PROPERTY(cx, obj, id, JSVAL_VOID, NULL, NULL,
3846
+ JSPROP_EXPORTED, NULL);
3847
+ } else {
3848
+ ok = OBJ_GET_ATTRIBUTES(cx, obj, id, prop, &attrs);
3849
+ if (ok) {
3850
+ attrs |= JSPROP_EXPORTED;
3851
+ ok = OBJ_SET_ATTRIBUTES(cx, obj, id, prop, &attrs);
3852
+ }
3853
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
3854
+ }
3855
+ if (!ok)
3856
+ goto out;
3857
+ break;
3858
+
3859
+ case JSOP_IMPORTALL:
3860
+ id = (jsid)JSVAL_VOID;
3861
+ PROPERTY_OP(-1, ok = ImportProperty(cx, obj, id));
3862
+ sp--;
3863
+ break;
3864
+
3865
+ case JSOP_IMPORTPROP:
3866
+ /* Get an immediate atom naming the property. */
3867
+ atom = GET_ATOM(cx, script, pc);
3868
+ id = (jsid)atom;
3869
+ PROPERTY_OP(-1, ok = ImportProperty(cx, obj, id));
3870
+ sp--;
3871
+ break;
3872
+
3873
+ case JSOP_IMPORTELEM:
3874
+ ELEMENT_OP(-1, ok = ImportProperty(cx, obj, id));
3875
+ sp -= 2;
3876
+ break;
3877
+ #endif /* JS_HAS_EXPORT_IMPORT */
3878
+
3879
+ case JSOP_TRAP:
3880
+ switch (JS_HandleTrap(cx, script, pc, &rval)) {
3881
+ case JSTRAP_ERROR:
3882
+ ok = JS_FALSE;
3883
+ goto out;
3884
+ case JSTRAP_CONTINUE:
3885
+ JS_ASSERT(JSVAL_IS_INT(rval));
3886
+ op = (JSOp) JSVAL_TO_INT(rval);
3887
+ JS_ASSERT((uintN)op < (uintN)JSOP_LIMIT);
3888
+ LOAD_INTERRUPT_HANDLER(rt);
3889
+ goto do_op;
3890
+ case JSTRAP_RETURN:
3891
+ fp->rval = rval;
3892
+ goto out;
3893
+ #if JS_HAS_EXCEPTIONS
3894
+ case JSTRAP_THROW:
3895
+ cx->throwing = JS_TRUE;
3896
+ cx->exception = rval;
3897
+ ok = JS_FALSE;
3898
+ goto out;
3899
+ #endif /* JS_HAS_EXCEPTIONS */
3900
+ default:;
3901
+ }
3902
+ LOAD_INTERRUPT_HANDLER(rt);
3903
+ break;
3904
+
3905
+ case JSOP_ARGUMENTS:
3906
+ SAVE_SP(fp);
3907
+ ok = js_GetArgsValue(cx, fp, &rval);
3908
+ if (!ok)
3909
+ goto out;
3910
+ PUSH_OPND(rval);
3911
+ break;
3912
+
3913
+ case JSOP_ARGSUB:
3914
+ id = (jsid) INT_TO_JSVAL(GET_ARGNO(pc));
3915
+ SAVE_SP(fp);
3916
+ ok = js_GetArgsProperty(cx, fp, id, &obj, &rval);
3917
+ if (!ok)
3918
+ goto out;
3919
+ if (!obj) {
3920
+ /*
3921
+ * If arguments was not overridden by eval('arguments = ...'),
3922
+ * set obj to the magic cookie respected by JSOP_PUSHOBJ, just
3923
+ * in case this bytecode is part of an 'arguments[i](j, k)' or
3924
+ * similar such invocation sequence, where the function that
3925
+ * is invoked expects its 'this' parameter to be the caller's
3926
+ * arguments object.
3927
+ */
3928
+ obj = LAZY_ARGS_THISP;
3929
+ }
3930
+ PUSH_OPND(rval);
3931
+ break;
3932
+
3933
+ #undef LAZY_ARGS_THISP
3934
+
3935
+ case JSOP_ARGCNT:
3936
+ id = (jsid) rt->atomState.lengthAtom;
3937
+ SAVE_SP(fp);
3938
+ ok = js_GetArgsProperty(cx, fp, id, &obj, &rval);
3939
+ if (!ok)
3940
+ goto out;
3941
+ PUSH_OPND(rval);
3942
+ break;
3943
+
3944
+ case JSOP_GETARG:
3945
+ slot = GET_ARGNO(pc);
3946
+ JS_ASSERT(slot < fp->fun->nargs);
3947
+ PUSH_OPND(fp->argv[slot]);
3948
+ obj = NULL;
3949
+ break;
3950
+
3951
+ case JSOP_SETARG:
3952
+ slot = GET_ARGNO(pc);
3953
+ JS_ASSERT(slot < fp->fun->nargs);
3954
+ vp = &fp->argv[slot];
3955
+ GC_POKE(cx, *vp);
3956
+ *vp = FETCH_OPND(-1);
3957
+ obj = NULL;
3958
+ break;
3959
+
3960
+ case JSOP_GETVAR:
3961
+ slot = GET_VARNO(pc);
3962
+ JS_ASSERT(slot < fp->fun->nvars);
3963
+ PUSH_OPND(fp->vars[slot]);
3964
+ obj = NULL;
3965
+ break;
3966
+
3967
+ case JSOP_SETVAR:
3968
+ slot = GET_VARNO(pc);
3969
+ JS_ASSERT(slot < fp->fun->nvars);
3970
+ vp = &fp->vars[slot];
3971
+ GC_POKE(cx, *vp);
3972
+ *vp = FETCH_OPND(-1);
3973
+ obj = NULL;
3974
+ break;
3975
+
3976
+ case JSOP_GETGVAR:
3977
+ slot = GET_VARNO(pc);
3978
+ JS_ASSERT(slot < fp->nvars);
3979
+ lval = fp->vars[slot];
3980
+ if (JSVAL_IS_NULL(lval)) {
3981
+ op = JSOP_NAME;
3982
+ goto do_op;
3983
+ }
3984
+ slot = JSVAL_TO_INT(lval);
3985
+ obj = fp->varobj;
3986
+ rval = OBJ_GET_SLOT(cx, obj, slot);
3987
+ PUSH_OPND(rval);
3988
+ break;
3989
+
3990
+ case JSOP_SETGVAR:
3991
+ slot = GET_VARNO(pc);
3992
+ JS_ASSERT(slot < fp->nvars);
3993
+ rval = FETCH_OPND(-1);
3994
+ lval = fp->vars[slot];
3995
+ obj = fp->varobj;
3996
+ if (JSVAL_IS_NULL(lval)) {
3997
+ /*
3998
+ * Inline-clone and specialize JSOP_SETNAME code here because
3999
+ * JSOP_SETGVAR has arity 1: [rval], not arity 2: [obj, rval]
4000
+ * as JSOP_SETNAME does, where [obj] is due to JSOP_BINDNAME.
4001
+ */
4002
+ atom = GET_ATOM(cx, script, pc);
4003
+ id = (jsid)atom;
4004
+ SAVE_SP(fp);
4005
+ CACHED_SET(OBJ_SET_PROPERTY(cx, obj, id, &rval));
4006
+ if (!ok)
4007
+ goto out;
4008
+ STORE_OPND(-1, rval);
4009
+ } else {
4010
+ slot = JSVAL_TO_INT(lval);
4011
+ GC_POKE(cx, obj->slots[slot]);
4012
+ OBJ_SET_SLOT(cx, obj, slot, rval);
4013
+ }
4014
+ break;
4015
+
4016
+ case JSOP_DEFCONST:
4017
+ case JSOP_DEFVAR:
4018
+ {
4019
+ jsatomid atomIndex;
4020
+
4021
+ atomIndex = GET_ATOM_INDEX(pc);
4022
+ atom = js_GetAtom(cx, &script->atomMap, atomIndex);
4023
+ obj = fp->varobj;
4024
+ attrs = JSPROP_ENUMERATE;
4025
+ if (!(fp->flags & JSFRAME_EVAL))
4026
+ attrs |= JSPROP_PERMANENT;
4027
+ if (op == JSOP_DEFCONST)
4028
+ attrs |= JSPROP_READONLY;
4029
+
4030
+ /* Lookup id in order to check for redeclaration problems. */
4031
+ id = (jsid)atom;
4032
+ ok = js_CheckRedeclaration(cx, obj, id, attrs, &obj2, &prop);
4033
+ if (!ok)
4034
+ goto out;
4035
+
4036
+ /* Bind a variable only if it's not yet defined. */
4037
+ if (!prop) {
4038
+ ok = OBJ_DEFINE_PROPERTY(cx, obj, id, JSVAL_VOID, NULL, NULL,
4039
+ attrs, &prop);
4040
+ if (!ok)
4041
+ goto out;
4042
+ JS_ASSERT(prop);
4043
+ obj2 = obj;
4044
+ }
4045
+
4046
+ /*
4047
+ * Try to optimize a property we either just created, or found
4048
+ * directly in the global object, that is permanent, has a slot,
4049
+ * and has stub getter and setter, into a "fast global" accessed
4050
+ * by the JSOP_*GVAR opcodes.
4051
+ */
4052
+ if (script->numGlobalVars &&
4053
+ (attrs & JSPROP_PERMANENT) &&
4054
+ obj2 == obj &&
4055
+ OBJ_IS_NATIVE(obj)) {
4056
+ sprop = (JSScopeProperty *) prop;
4057
+ if (SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj)) &&
4058
+ SPROP_HAS_STUB_GETTER(sprop) &&
4059
+ SPROP_HAS_STUB_SETTER(sprop)) {
4060
+ /*
4061
+ * Fast globals use fp->vars to map the global name's
4062
+ * atomIndex to the permanent fp->varobj slot number,
4063
+ * tagged as a jsval. The atomIndex for the global's
4064
+ * name literal is identical to its fp->vars index.
4065
+ */
4066
+ fp->vars[atomIndex] = INT_TO_JSVAL(sprop->slot);
4067
+ }
4068
+ }
4069
+
4070
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
4071
+ break;
4072
+ }
4073
+
4074
+ case JSOP_DEFFUN:
4075
+ {
4076
+ jsatomid atomIndex;
4077
+ uintN flags;
4078
+
4079
+ atomIndex = GET_ATOM_INDEX(pc);
4080
+ atom = js_GetAtom(cx, &script->atomMap, atomIndex);
4081
+ obj = ATOM_TO_OBJECT(atom);
4082
+ fun = (JSFunction *) JS_GetPrivate(cx, obj);
4083
+ id = (jsid) fun->atom;
4084
+
4085
+ /*
4086
+ * We must be at top-level (either outermost block that forms a
4087
+ * function's body, or a global) scope, not inside an expression
4088
+ * (JSOP_{ANON,NAMED}FUNOBJ) or compound statement (JSOP_CLOSURE)
4089
+ * in the same compilation unit (ECMA Program).
4090
+ *
4091
+ * However, we could be in a Program being eval'd from inside a
4092
+ * with statement, so we need to distinguish variables object from
4093
+ * scope chain head. Hence the two assignments to parent below.
4094
+ * First we make sure the function object we're defining has the
4095
+ * right scope chain. Then we define its name in fp->varobj.
4096
+ *
4097
+ * If static link is not current scope, clone fun's object to link
4098
+ * to the current scope via parent. This clause exists to enable
4099
+ * sharing of compiled functions among multiple equivalent scopes,
4100
+ * splitting the cost of compilation evenly among the scopes and
4101
+ * amortizing it over a number of executions. Examples include XUL
4102
+ * scripts and event handlers shared among Mozilla chrome windows,
4103
+ * and server-side JS user-defined functions shared among requests.
4104
+ *
4105
+ * NB: The Script object exposes compile and exec in the language,
4106
+ * such that this clause introduces an incompatible change from old
4107
+ * JS versions that supported Script. Such a JS version supported
4108
+ * executing a script that defined and called functions scoped by
4109
+ * the compile-time static link, not by the exec-time scope chain.
4110
+ *
4111
+ * We sacrifice compatibility, breaking such scripts, in order to
4112
+ * promote compile-cost sharing and amortizing, and because Script
4113
+ * is not and will not be standardized.
4114
+ */
4115
+ parent = fp->scopeChain;
4116
+ if (OBJ_GET_PARENT(cx, obj) != parent) {
4117
+ obj = js_CloneFunctionObject(cx, obj, parent);
4118
+ if (!obj) {
4119
+ ok = JS_FALSE;
4120
+ goto out;
4121
+ }
4122
+ }
4123
+
4124
+ /*
4125
+ * ECMA requires functions defined when entering Global code to be
4126
+ * permanent, and functions defined when entering Eval code to be
4127
+ * impermanent.
4128
+ */
4129
+ attrs = JSPROP_ENUMERATE;
4130
+ if (!(fp->flags & JSFRAME_EVAL))
4131
+ attrs |= JSPROP_PERMANENT;
4132
+
4133
+ /*
4134
+ * Load function flags that are also property attributes. Getters
4135
+ * and setters do not need a slot, their value is stored elsewhere
4136
+ * in the property itself, not in obj->slots.
4137
+ */
4138
+ flags = fun->flags & (JSFUN_GETTER | JSFUN_SETTER);
4139
+ if (flags)
4140
+ attrs |= flags | JSPROP_SHARED;
4141
+
4142
+ /*
4143
+ * Check for a const property of the same name -- or any kind
4144
+ * of property if executing with the strict option. We check
4145
+ * here at runtime as well as at compile-time, to handle eval
4146
+ * as well as multiple HTML script tags.
4147
+ */
4148
+ parent = fp->varobj;
4149
+ ok = js_CheckRedeclaration(cx, parent, id, attrs, NULL, NULL);
4150
+ if (!ok)
4151
+ goto out;
4152
+
4153
+ ok = OBJ_DEFINE_PROPERTY(cx, parent, id,
4154
+ flags ? JSVAL_VOID : OBJECT_TO_JSVAL(obj),
4155
+ (flags & JSFUN_GETTER)
4156
+ ? (JSPropertyOp) obj
4157
+ : NULL,
4158
+ (flags & JSFUN_SETTER)
4159
+ ? (JSPropertyOp) obj
4160
+ : NULL,
4161
+ attrs,
4162
+ &prop);
4163
+ if (!ok)
4164
+ goto out;
4165
+ if (attrs == (JSPROP_ENUMERATE | JSPROP_PERMANENT) &&
4166
+ script->numGlobalVars) {
4167
+ /*
4168
+ * As with JSOP_DEFVAR and JSOP_DEFCONST (above), fast globals
4169
+ * use fp->vars to map the global function name's atomIndex to
4170
+ * its permanent fp->varobj slot number, tagged as a jsval.
4171
+ */
4172
+ sprop = (JSScopeProperty *) prop;
4173
+ fp->vars[atomIndex] = INT_TO_JSVAL(sprop->slot);
4174
+ }
4175
+ OBJ_DROP_PROPERTY(cx, parent, prop);
4176
+ break;
4177
+ }
4178
+
4179
+ #if JS_HAS_LEXICAL_CLOSURE
4180
+ case JSOP_DEFLOCALFUN:
4181
+ /*
4182
+ * Define a local function (i.e., one nested at the top level of
4183
+ * another function), parented by the current scope chain, and
4184
+ * stored in a local variable slot that the compiler allocated.
4185
+ * This is an optimization over JSOP_DEFFUN that avoids requiring
4186
+ * a call object for the outer function's activation.
4187
+ */
4188
+ pc2 = pc;
4189
+ slot = GET_VARNO(pc2);
4190
+ pc2 += VARNO_LEN;
4191
+ atom = GET_ATOM(cx, script, pc2);
4192
+ obj = ATOM_TO_OBJECT(atom);
4193
+ fun = (JSFunction *) JS_GetPrivate(cx, obj);
4194
+
4195
+ parent = fp->scopeChain;
4196
+ if (OBJ_GET_PARENT(cx, obj) != parent) {
4197
+ obj = js_CloneFunctionObject(cx, obj, parent);
4198
+ if (!obj) {
4199
+ ok = JS_FALSE;
4200
+ goto out;
4201
+ }
4202
+ }
4203
+ fp->vars[slot] = OBJECT_TO_JSVAL(obj);
4204
+ break;
4205
+
4206
+ case JSOP_ANONFUNOBJ:
4207
+ /* Push the specified function object literal. */
4208
+ atom = GET_ATOM(cx, script, pc);
4209
+ obj = ATOM_TO_OBJECT(atom);
4210
+
4211
+ /* If re-parenting, push a clone of the function object. */
4212
+ parent = fp->scopeChain;
4213
+ if (OBJ_GET_PARENT(cx, obj) != parent) {
4214
+ obj = js_CloneFunctionObject(cx, obj, parent);
4215
+ if (!obj) {
4216
+ ok = JS_FALSE;
4217
+ goto out;
4218
+ }
4219
+ }
4220
+ PUSH_OPND(OBJECT_TO_JSVAL(obj));
4221
+ break;
4222
+
4223
+ case JSOP_NAMEDFUNOBJ:
4224
+ /* ECMA ed. 3 FunctionExpression: function Identifier [etc.]. */
4225
+ atom = GET_ATOM(cx, script, pc);
4226
+ rval = ATOM_KEY(atom);
4227
+ JS_ASSERT(JSVAL_IS_FUNCTION(cx, rval));
4228
+
4229
+ /*
4230
+ * 1. Create a new object as if by the expression new Object().
4231
+ * 2. Add Result(1) to the front of the scope chain.
4232
+ *
4233
+ * Step 2 is achieved by making the new object's parent be the
4234
+ * current scope chain, and then making the new object the parent
4235
+ * of the Function object clone.
4236
+ */
4237
+ SAVE_SP(fp);
4238
+ parent = js_ConstructObject(cx, &js_ObjectClass, NULL,
4239
+ fp->scopeChain, 0, NULL);
4240
+ if (!parent) {
4241
+ ok = JS_FALSE;
4242
+ goto out;
4243
+ }
4244
+
4245
+ /*
4246
+ * 3. Create a new Function object as specified in section 13.2
4247
+ * with [parameters and body specified by the function expression
4248
+ * that was parsed by the compiler into a Function object, and
4249
+ * saved in the script's atom map].
4250
+ */
4251
+ obj = js_CloneFunctionObject(cx, JSVAL_TO_OBJECT(rval), parent);
4252
+ if (!obj) {
4253
+ ok = JS_FALSE;
4254
+ goto out;
4255
+ }
4256
+
4257
+ /*
4258
+ * 4. Create a property in the object Result(1). The property's
4259
+ * name is [fun->atom, the identifier parsed by the compiler],
4260
+ * value is Result(3), and attributes are { DontDelete, ReadOnly }.
4261
+ */
4262
+ fun = (JSFunction *) JS_GetPrivate(cx, obj);
4263
+ attrs = fun->flags & (JSFUN_GETTER | JSFUN_SETTER);
4264
+ if (attrs)
4265
+ attrs |= JSPROP_SHARED;
4266
+ ok = OBJ_DEFINE_PROPERTY(cx, parent, (jsid)fun->atom,
4267
+ attrs ? JSVAL_VOID : OBJECT_TO_JSVAL(obj),
4268
+ (attrs & JSFUN_GETTER)
4269
+ ? (JSPropertyOp) obj
4270
+ : NULL,
4271
+ (attrs & JSFUN_SETTER)
4272
+ ? (JSPropertyOp) obj
4273
+ : NULL,
4274
+ attrs |
4275
+ JSPROP_ENUMERATE | JSPROP_PERMANENT |
4276
+ JSPROP_READONLY,
4277
+ NULL);
4278
+ if (!ok) {
4279
+ cx->newborn[GCX_OBJECT] = NULL;
4280
+ goto out;
4281
+ }
4282
+
4283
+ /*
4284
+ * 5. Remove Result(1) from the front of the scope chain [no-op].
4285
+ * 6. Return Result(3).
4286
+ */
4287
+ PUSH_OPND(OBJECT_TO_JSVAL(obj));
4288
+ break;
4289
+
4290
+ case JSOP_CLOSURE:
4291
+ {
4292
+ jsatomid atomIndex;
4293
+
4294
+ /*
4295
+ * ECMA ed. 3 extension: a named function expression in a compound
4296
+ * statement (not at the top statement level of global code, or at
4297
+ * the top level of a function body).
4298
+ *
4299
+ * Get immediate operand atom, which is a function object literal.
4300
+ * From it, get the function to close.
4301
+ */
4302
+ atomIndex = GET_ATOM_INDEX(pc);
4303
+ atom = js_GetAtom(cx, &script->atomMap, atomIndex);
4304
+ JS_ASSERT(JSVAL_IS_FUNCTION(cx, ATOM_KEY(atom)));
4305
+ obj = ATOM_TO_OBJECT(atom);
4306
+
4307
+ /*
4308
+ * Clone the function object with the current scope chain as the
4309
+ * clone's parent. The original function object is the prototype
4310
+ * of the clone. Do this only if re-parenting; the compiler may
4311
+ * have seen the right parent already and created a sufficiently
4312
+ * well-scoped function object.
4313
+ */
4314
+ parent = fp->scopeChain;
4315
+ if (OBJ_GET_PARENT(cx, obj) != parent) {
4316
+ obj = js_CloneFunctionObject(cx, obj, parent);
4317
+ if (!obj) {
4318
+ ok = JS_FALSE;
4319
+ goto out;
4320
+ }
4321
+ }
4322
+
4323
+ /*
4324
+ * Make a property in fp->varobj with id fun->atom and value obj,
4325
+ * unless fun is a getter or setter (in which case, obj is cast to
4326
+ * a JSPropertyOp and passed accordingly).
4327
+ */
4328
+ fun = (JSFunction *) JS_GetPrivate(cx, obj);
4329
+ attrs = fun->flags & (JSFUN_GETTER | JSFUN_SETTER);
4330
+ if (attrs)
4331
+ attrs |= JSPROP_SHARED;
4332
+ parent = fp->varobj;
4333
+ ok = OBJ_DEFINE_PROPERTY(cx, parent, (jsid)fun->atom,
4334
+ attrs ? JSVAL_VOID : OBJECT_TO_JSVAL(obj),
4335
+ (attrs & JSFUN_GETTER)
4336
+ ? (JSPropertyOp) obj
4337
+ : NULL,
4338
+ (attrs & JSFUN_SETTER)
4339
+ ? (JSPropertyOp) obj
4340
+ : NULL,
4341
+ attrs | JSPROP_ENUMERATE
4342
+ | JSPROP_PERMANENT,
4343
+ &prop);
4344
+ if (!ok) {
4345
+ cx->newborn[GCX_OBJECT] = NULL;
4346
+ goto out;
4347
+ }
4348
+ if (attrs == 0 && script->numGlobalVars) {
4349
+ /*
4350
+ * As with JSOP_DEFVAR and JSOP_DEFCONST (above), fast globals
4351
+ * use fp->vars to map the global function name's atomIndex to
4352
+ * its permanent fp->varobj slot number, tagged as a jsval.
4353
+ */
4354
+ sprop = (JSScopeProperty *) prop;
4355
+ fp->vars[atomIndex] = INT_TO_JSVAL(sprop->slot);
4356
+ }
4357
+ OBJ_DROP_PROPERTY(cx, parent, prop);
4358
+ break;
4359
+ }
4360
+ #endif /* JS_HAS_LEXICAL_CLOSURE */
4361
+
4362
+ #if JS_HAS_GETTER_SETTER
4363
+ case JSOP_GETTER:
4364
+ case JSOP_SETTER:
4365
+ JS_ASSERT(len == 1);
4366
+ op2 = (JSOp) *++pc;
4367
+ cs = &js_CodeSpec[op2];
4368
+ len = cs->length;
4369
+ switch (op2) {
4370
+ case JSOP_SETNAME:
4371
+ case JSOP_SETPROP:
4372
+ atom = GET_ATOM(cx, script, pc);
4373
+ id = (jsid)atom;
4374
+ i = -1;
4375
+ rval = FETCH_OPND(i);
4376
+ goto gs_pop_lval;
4377
+
4378
+ case JSOP_SETELEM:
4379
+ rval = FETCH_OPND(-1);
4380
+ i = -2;
4381
+ FETCH_ELEMENT_ID(i, id);
4382
+ gs_pop_lval:
4383
+ lval = FETCH_OPND(i-1);
4384
+ VALUE_TO_OBJECT(cx, lval, obj);
4385
+ break;
4386
+
4387
+ #if JS_HAS_INITIALIZERS
4388
+ case JSOP_INITPROP:
4389
+ JS_ASSERT(sp - fp->spbase >= 2);
4390
+ i = -1;
4391
+ rval = FETCH_OPND(i);
4392
+ atom = GET_ATOM(cx, script, pc);
4393
+ id = (jsid)atom;
4394
+ goto gs_get_lval;
4395
+
4396
+ case JSOP_INITELEM:
4397
+ JS_ASSERT(sp - fp->spbase >= 3);
4398
+ rval = FETCH_OPND(-1);
4399
+ i = -2;
4400
+ FETCH_ELEMENT_ID(i, id);
4401
+ gs_get_lval:
4402
+ lval = FETCH_OPND(i-1);
4403
+ JS_ASSERT(JSVAL_IS_OBJECT(lval));
4404
+ obj = JSVAL_TO_OBJECT(lval);
4405
+ break;
4406
+ #endif /* JS_HAS_INITIALIZERS */
4407
+
4408
+ default:
4409
+ JS_ASSERT(0);
4410
+ }
4411
+
4412
+ if (JS_TypeOfValue(cx, rval) != JSTYPE_FUNCTION) {
4413
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
4414
+ JSMSG_BAD_GETTER_OR_SETTER,
4415
+ (op == JSOP_GETTER)
4416
+ ? js_getter_str
4417
+ : js_setter_str);
4418
+ ok = JS_FALSE;
4419
+ goto out;
4420
+ }
4421
+
4422
+ /*
4423
+ * Getters and setters are just like watchpoints from an access
4424
+ * control point of view.
4425
+ */
4426
+ ok = OBJ_CHECK_ACCESS(cx, obj, id, JSACC_WATCH, &rtmp, &attrs);
4427
+ if (!ok)
4428
+ goto out;
4429
+
4430
+ if (op == JSOP_GETTER) {
4431
+ getter = (JSPropertyOp) JSVAL_TO_OBJECT(rval);
4432
+ setter = NULL;
4433
+ attrs = JSPROP_GETTER;
4434
+ } else {
4435
+ getter = NULL;
4436
+ setter = (JSPropertyOp) JSVAL_TO_OBJECT(rval);
4437
+ attrs = JSPROP_SETTER;
4438
+ }
4439
+ attrs |= JSPROP_ENUMERATE | JSPROP_SHARED;
4440
+
4441
+ /* Check for a readonly or permanent property of the same name. */
4442
+ ok = js_CheckRedeclaration(cx, obj, id, attrs, NULL, NULL);
4443
+ if (!ok)
4444
+ goto out;
4445
+
4446
+ ok = OBJ_DEFINE_PROPERTY(cx, obj, id, JSVAL_VOID, getter, setter,
4447
+ attrs, NULL);
4448
+ if (!ok)
4449
+ goto out;
4450
+
4451
+ sp += i;
4452
+ if (cs->ndefs)
4453
+ STORE_OPND(-1, rval);
4454
+ break;
4455
+ #endif /* JS_HAS_GETTER_SETTER */
4456
+
4457
+ #if JS_HAS_INITIALIZERS
4458
+ case JSOP_NEWINIT:
4459
+ argc = 0;
4460
+ fp->sharpDepth++;
4461
+ goto do_new;
4462
+
4463
+ case JSOP_ENDINIT:
4464
+ if (--fp->sharpDepth == 0)
4465
+ fp->sharpArray = NULL;
4466
+
4467
+ /* Re-set the newborn root to the top of this object tree. */
4468
+ JS_ASSERT(sp - fp->spbase >= 1);
4469
+ lval = FETCH_OPND(-1);
4470
+ JS_ASSERT(JSVAL_IS_OBJECT(lval));
4471
+ cx->newborn[GCX_OBJECT] = JSVAL_TO_GCTHING(lval);
4472
+ break;
4473
+
4474
+ case JSOP_INITPROP:
4475
+ /* Pop the property's value into rval. */
4476
+ JS_ASSERT(sp - fp->spbase >= 2);
4477
+ rval = FETCH_OPND(-1);
4478
+
4479
+ /* Get the immediate property name into id. */
4480
+ atom = GET_ATOM(cx, script, pc);
4481
+ id = (jsid)atom;
4482
+ i = -1;
4483
+ goto do_init;
4484
+
4485
+ case JSOP_INITELEM:
4486
+ /* Pop the element's value into rval. */
4487
+ JS_ASSERT(sp - fp->spbase >= 3);
4488
+ rval = FETCH_OPND(-1);
4489
+
4490
+ /* Pop and conditionally atomize the element id. */
4491
+ FETCH_ELEMENT_ID(-2, id);
4492
+ i = -2;
4493
+
4494
+ do_init:
4495
+ /* Find the object being initialized at top of stack. */
4496
+ lval = FETCH_OPND(i-1);
4497
+ JS_ASSERT(JSVAL_IS_OBJECT(lval));
4498
+ obj = JSVAL_TO_OBJECT(lval);
4499
+
4500
+ /* Set the property named by obj[id] to rval. */
4501
+ ok = OBJ_SET_PROPERTY(cx, obj, id, &rval);
4502
+ if (!ok)
4503
+ goto out;
4504
+ sp += i;
4505
+ break;
4506
+
4507
+ #if JS_HAS_SHARP_VARS
4508
+ case JSOP_DEFSHARP:
4509
+ obj = fp->sharpArray;
4510
+ if (!obj) {
4511
+ obj = js_NewArrayObject(cx, 0, NULL);
4512
+ if (!obj) {
4513
+ ok = JS_FALSE;
4514
+ goto out;
4515
+ }
4516
+ fp->sharpArray = obj;
4517
+ }
4518
+ i = (jsint) GET_ATOM_INDEX(pc);
4519
+ id = (jsid) INT_TO_JSVAL(i);
4520
+ rval = FETCH_OPND(-1);
4521
+ if (JSVAL_IS_PRIMITIVE(rval)) {
4522
+ char numBuf[12];
4523
+ JS_snprintf(numBuf, sizeof numBuf, "%u", (unsigned) i);
4524
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
4525
+ JSMSG_BAD_SHARP_DEF, numBuf);
4526
+ ok = JS_FALSE;
4527
+ goto out;
4528
+ }
4529
+ ok = OBJ_SET_PROPERTY(cx, obj, id, &rval);
4530
+ if (!ok)
4531
+ goto out;
4532
+ break;
4533
+
4534
+ case JSOP_USESHARP:
4535
+ i = (jsint) GET_ATOM_INDEX(pc);
4536
+ id = (jsid) INT_TO_JSVAL(i);
4537
+ obj = fp->sharpArray;
4538
+ if (!obj) {
4539
+ rval = JSVAL_VOID;
4540
+ } else {
4541
+ ok = OBJ_GET_PROPERTY(cx, obj, id, &rval);
4542
+ if (!ok)
4543
+ goto out;
4544
+ }
4545
+ if (!JSVAL_IS_OBJECT(rval)) {
4546
+ char numBuf[12];
4547
+ JS_snprintf(numBuf, sizeof numBuf, "%u", (unsigned) i);
4548
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
4549
+ JSMSG_BAD_SHARP_USE, numBuf);
4550
+ ok = JS_FALSE;
4551
+ goto out;
4552
+ }
4553
+ PUSH_OPND(rval);
4554
+ break;
4555
+ #endif /* JS_HAS_SHARP_VARS */
4556
+ #endif /* JS_HAS_INITIALIZERS */
4557
+
4558
+ #if JS_HAS_EXCEPTIONS
4559
+ /* No-ops for ease of decompilation and jit'ing. */
4560
+ case JSOP_TRY:
4561
+ case JSOP_FINALLY:
4562
+ break;
4563
+
4564
+ /* Reset the stack to the given depth. */
4565
+ case JSOP_SETSP:
4566
+ i = (jsint) GET_ATOM_INDEX(pc);
4567
+ JS_ASSERT(i >= 0);
4568
+ sp = fp->spbase + i;
4569
+ break;
4570
+
4571
+ case JSOP_GOSUB:
4572
+ i = PTRDIFF(pc, script->main, jsbytecode) + len;
4573
+ len = GET_JUMP_OFFSET(pc);
4574
+ PUSH(INT_TO_JSVAL(i));
4575
+ break;
4576
+
4577
+ case JSOP_GOSUBX:
4578
+ i = PTRDIFF(pc, script->main, jsbytecode) + len;
4579
+ len = GET_JUMPX_OFFSET(pc);
4580
+ PUSH(INT_TO_JSVAL(i));
4581
+ break;
4582
+
4583
+ case JSOP_RETSUB:
4584
+ rval = POP();
4585
+ JS_ASSERT(JSVAL_IS_INT(rval));
4586
+ i = JSVAL_TO_INT(rval);
4587
+ pc = script->main + i;
4588
+ len = 0;
4589
+ break;
4590
+
4591
+ case JSOP_EXCEPTION:
4592
+ PUSH(cx->exception);
4593
+ break;
4594
+
4595
+ case JSOP_THROW:
4596
+ cx->throwing = JS_TRUE;
4597
+ cx->exception = POP_OPND();
4598
+ ok = JS_FALSE;
4599
+ /* let the code at out try to catch the exception. */
4600
+ goto out;
4601
+
4602
+ case JSOP_INITCATCHVAR:
4603
+ /* Pop the property's value into rval. */
4604
+ JS_ASSERT(sp - fp->spbase >= 2);
4605
+ rval = POP_OPND();
4606
+
4607
+ /* Get the immediate catch variable name into id. */
4608
+ atom = GET_ATOM(cx, script, pc);
4609
+ id = (jsid)atom;
4610
+
4611
+ /* Find the object being initialized at top of stack. */
4612
+ lval = FETCH_OPND(-1);
4613
+ JS_ASSERT(JSVAL_IS_OBJECT(lval));
4614
+ obj = JSVAL_TO_OBJECT(lval);
4615
+
4616
+ /* Define obj[id] to contain rval and to be permanent. */
4617
+ ok = OBJ_DEFINE_PROPERTY(cx, obj, id, rval, NULL, NULL,
4618
+ JSPROP_PERMANENT, NULL);
4619
+ if (!ok)
4620
+ goto out;
4621
+ break;
4622
+ #endif /* JS_HAS_EXCEPTIONS */
4623
+
4624
+ #if JS_HAS_INSTANCEOF
4625
+ case JSOP_INSTANCEOF:
4626
+ rval = FETCH_OPND(-1);
4627
+ if (JSVAL_IS_PRIMITIVE(rval)) {
4628
+ SAVE_SP(fp);
4629
+ str = js_DecompileValueGenerator(cx, -1, rval, NULL);
4630
+ if (str) {
4631
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
4632
+ JSMSG_BAD_INSTANCEOF_RHS,
4633
+ JS_GetStringBytes(str));
4634
+ }
4635
+ ok = JS_FALSE;
4636
+ goto out;
4637
+ }
4638
+ obj = JSVAL_TO_OBJECT(rval);
4639
+ lval = FETCH_OPND(-2);
4640
+ cond = JS_FALSE;
4641
+ if (obj->map->ops->hasInstance) {
4642
+ SAVE_SP(fp);
4643
+ ok = obj->map->ops->hasInstance(cx, obj, lval, &cond);
4644
+ if (!ok)
4645
+ goto out;
4646
+ }
4647
+ sp--;
4648
+ STORE_OPND(-1, BOOLEAN_TO_JSVAL(cond));
4649
+ break;
4650
+ #endif /* JS_HAS_INSTANCEOF */
4651
+
4652
+ #if JS_HAS_DEBUGGER_KEYWORD
4653
+ case JSOP_DEBUGGER:
4654
+ {
4655
+ JSTrapHandler handler = rt->debuggerHandler;
4656
+ if (handler) {
4657
+ SAVE_SP(fp);
4658
+ switch (handler(cx, script, pc, &rval,
4659
+ rt->debuggerHandlerData)) {
4660
+ case JSTRAP_ERROR:
4661
+ ok = JS_FALSE;
4662
+ goto out;
4663
+ case JSTRAP_CONTINUE:
4664
+ break;
4665
+ case JSTRAP_RETURN:
4666
+ fp->rval = rval;
4667
+ goto out;
4668
+ #if JS_HAS_EXCEPTIONS
4669
+ case JSTRAP_THROW:
4670
+ cx->throwing = JS_TRUE;
4671
+ cx->exception = rval;
4672
+ ok = JS_FALSE;
4673
+ goto out;
4674
+ #endif /* JS_HAS_EXCEPTIONS */
4675
+ default:;
4676
+ }
4677
+ LOAD_INTERRUPT_HANDLER(rt);
4678
+ }
4679
+ break;
4680
+ }
4681
+ #endif /* JS_HAS_DEBUGGER_KEYWORD */
4682
+
4683
+ default: {
4684
+ char numBuf[12];
4685
+ JS_snprintf(numBuf, sizeof numBuf, "%d", op);
4686
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
4687
+ JSMSG_BAD_BYTECODE, numBuf);
4688
+ ok = JS_FALSE;
4689
+ goto out;
4690
+ }
4691
+ }
4692
+
4693
+ advance_pc:
4694
+ pc += len;
4695
+
4696
+ #ifdef DEBUG
4697
+ if (tracefp) {
4698
+ intN ndefs, n;
4699
+ jsval *siter;
4700
+
4701
+ ndefs = cs->ndefs;
4702
+ if (ndefs) {
4703
+ SAVE_SP(fp);
4704
+ for (n = -ndefs; n < 0; n++) {
4705
+ str = js_DecompileValueGenerator(cx, n, sp[n], NULL);
4706
+ if (str) {
4707
+ fprintf(tracefp, "%s %s",
4708
+ (n == -ndefs) ? " output:" : ",",
4709
+ JS_GetStringBytes(str));
4710
+ }
4711
+ }
4712
+ fprintf(tracefp, " @ %d\n", sp - fp->spbase);
4713
+ }
4714
+ fprintf(tracefp, " stack: ");
4715
+ for (siter = fp->spbase; siter < sp; siter++) {
4716
+ str = js_ValueToSource(cx, *siter);
4717
+ fprintf(tracefp, "%s ",
4718
+ str ? JS_GetStringBytes(str) : "<null>");
4719
+ }
4720
+ fputc('\n', tracefp);
4721
+ }
4722
+ #endif
4723
+ }
4724
+ out:
4725
+
4726
+ #if JS_HAS_EXCEPTIONS
4727
+ /*
4728
+ * Has an exception been raised?
4729
+ */
4730
+ if (!ok && cx->throwing) {
4731
+ /*
4732
+ * Call debugger throw hook if set (XXX thread safety?).
4733
+ */
4734
+ JSTrapHandler handler = rt->throwHook;
4735
+ if (handler) {
4736
+ SAVE_SP(fp);
4737
+ switch (handler(cx, script, pc, &rval, rt->throwHookData)) {
4738
+ case JSTRAP_ERROR:
4739
+ cx->throwing = JS_FALSE;
4740
+ goto no_catch;
4741
+ case JSTRAP_RETURN:
4742
+ ok = JS_TRUE;
4743
+ cx->throwing = JS_FALSE;
4744
+ fp->rval = rval;
4745
+ goto no_catch;
4746
+ case JSTRAP_THROW:
4747
+ cx->exception = rval;
4748
+ case JSTRAP_CONTINUE:
4749
+ default:;
4750
+ }
4751
+ LOAD_INTERRUPT_HANDLER(rt);
4752
+ }
4753
+
4754
+ /*
4755
+ * Look for a try block within this frame that can catch the exception.
4756
+ */
4757
+ SCRIPT_FIND_CATCH_START(script, pc, pc);
4758
+ if (pc) {
4759
+ len = 0;
4760
+ cx->throwing = JS_FALSE; /* caught */
4761
+ ok = JS_TRUE;
4762
+ goto advance_pc;
4763
+ }
4764
+ }
4765
+ no_catch:
4766
+ #endif
4767
+
4768
+ /*
4769
+ * Check whether control fell off the end of a lightweight function, or an
4770
+ * exception thrown under such a function was not caught by it. If so, go
4771
+ * to the inline code under JSOP_RETURN.
4772
+ */
4773
+ if (inlineCallCount)
4774
+ goto inline_return;
4775
+
4776
+ /*
4777
+ * Reset sp before freeing stack slots, because our caller may GC soon.
4778
+ * Clear spbase to indicate that we've popped the 2 * depth operand slots.
4779
+ * Restore the previous frame's execution state.
4780
+ */
4781
+ fp->sp = fp->spbase;
4782
+ fp->spbase = NULL;
4783
+ js_FreeRawStack(cx, mark);
4784
+ if (cx->version == currentVersion && currentVersion != originalVersion)
4785
+ JS_SetVersion(cx, originalVersion);
4786
+ cx->interpLevel--;
4787
+ return ok;
4788
+
4789
+ atom_not_defined:
4790
+ {
4791
+ const char *printable = js_AtomToPrintableString(cx, atom);
4792
+ if (printable)
4793
+ js_ReportIsNotDefined(cx, printable);
4794
+ ok = JS_FALSE;
4795
+ goto out;
4796
+ }
4797
+ }