distil 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ }