distil 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (552) hide show
  1. data/Rakefile +28 -0
  2. data/VERSION +1 -0
  3. data/bin/distil +45 -0
  4. data/distil.gemspec +586 -0
  5. data/lib/bootstrap-template.js +56 -0
  6. data/lib/configurable.rb +125 -0
  7. data/lib/file-set.rb +42 -0
  8. data/lib/file-types/css-file.rb +75 -0
  9. data/lib/file-types/html-file.rb +11 -0
  10. data/lib/file-types/javascript-file.rb +98 -0
  11. data/lib/file-types/json-file.rb +14 -0
  12. data/lib/file-types/nib-file.rb +9 -0
  13. data/lib/jsdoc.conf +18 -0
  14. data/lib/jsl.conf +121 -0
  15. data/lib/project.rb +96 -0
  16. data/lib/source-file.rb +181 -0
  17. data/lib/target.rb +96 -0
  18. data/lib/task.rb +239 -0
  19. data/lib/tasks/copy-task.rb +21 -0
  20. data/lib/tasks/css-task.rb +18 -0
  21. data/lib/tasks/javascript-task.rb +125 -0
  22. data/lib/tasks/multiple-output-task.rb +134 -0
  23. data/lib/tasks/nib-task.rb +83 -0
  24. data/lib/tasks/output-task.rb +73 -0
  25. data/lib/tasks/single-output-task.rb +83 -0
  26. data/lib/tasks/test-task.rb +280 -0
  27. data/lib/test/HtmlTestReporter.js +127 -0
  28. data/lib/test/Test.js +248 -0
  29. data/lib/test/TestReporter.js +79 -0
  30. data/lib/test/TestRunner.js +132 -0
  31. data/lib/test/browser.rb +97 -0
  32. data/lib/test/scriptwrapper.html +10 -0
  33. data/lib/test/unittest.html +127 -0
  34. data/vendor/Makefile +35 -0
  35. data/vendor/extconf.rb +3 -0
  36. data/vendor/jsdoc-extras/plugins/distil-plugin.js +142 -0
  37. data/vendor/jsdoc-extras/plugins/interface-plugin.js +36 -0
  38. data/vendor/jsdoc-extras/templates/coherent/allclasses.tmpl +17 -0
  39. data/vendor/jsdoc-extras/templates/coherent/allfiles.tmpl +53 -0
  40. data/vendor/jsdoc-extras/templates/coherent/class.tmpl +803 -0
  41. data/vendor/jsdoc-extras/templates/coherent/index.tmpl +37 -0
  42. data/vendor/jsdoc-extras/templates/coherent/publish.js +242 -0
  43. data/vendor/jsdoc-extras/templates/coherent/showdown.js +421 -0
  44. data/vendor/jsdoc-extras/templates/coherent/static/code-footer.html +3 -0
  45. data/vendor/jsdoc-extras/templates/coherent/static/code-header.html +7 -0
  46. data/vendor/jsdoc-extras/templates/coherent/static/default.css +297 -0
  47. data/vendor/jsdoc-extras/templates/coherent/static/header.html +2 -0
  48. data/vendor/jsdoc-extras/templates/coherent/static/index.html +19 -0
  49. data/vendor/jsdoc-extras/templates/coherent/symbol.tmpl +35 -0
  50. data/vendor/jsdoc-toolkit/README.txt +183 -0
  51. data/vendor/jsdoc-toolkit/app/frame/Chain.js +102 -0
  52. data/vendor/jsdoc-toolkit/app/frame/Dumper.js +144 -0
  53. data/vendor/jsdoc-toolkit/app/frame/Hash.js +84 -0
  54. data/vendor/jsdoc-toolkit/app/frame/Link.js +171 -0
  55. data/vendor/jsdoc-toolkit/app/frame/Namespace.js +10 -0
  56. data/vendor/jsdoc-toolkit/app/frame/Opt.js +134 -0
  57. data/vendor/jsdoc-toolkit/app/frame/Reflection.js +26 -0
  58. data/vendor/jsdoc-toolkit/app/frame/String.js +93 -0
  59. data/vendor/jsdoc-toolkit/app/frame/Testrun.js +129 -0
  60. data/vendor/jsdoc-toolkit/app/frame.js +33 -0
  61. data/vendor/jsdoc-toolkit/app/handlers/FOODOC.js +26 -0
  62. data/vendor/jsdoc-toolkit/app/handlers/XMLDOC/DomReader.js +159 -0
  63. data/vendor/jsdoc-toolkit/app/handlers/XMLDOC/XMLDoc.js +16 -0
  64. data/vendor/jsdoc-toolkit/app/handlers/XMLDOC/XMLParse.js +292 -0
  65. data/vendor/jsdoc-toolkit/app/handlers/XMLDOC.js +26 -0
  66. data/vendor/jsdoc-toolkit/app/lib/JSDOC/DocComment.js +204 -0
  67. data/vendor/jsdoc-toolkit/app/lib/JSDOC/DocTag.js +300 -0
  68. data/vendor/jsdoc-toolkit/app/lib/JSDOC/JsDoc.js +126 -0
  69. data/vendor/jsdoc-toolkit/app/lib/JSDOC/JsPlate.js +109 -0
  70. data/vendor/jsdoc-toolkit/app/lib/JSDOC/Lang.js +144 -0
  71. data/vendor/jsdoc-toolkit/app/lib/JSDOC/Parser.js +144 -0
  72. data/vendor/jsdoc-toolkit/app/lib/JSDOC/PluginManager.js +33 -0
  73. data/vendor/jsdoc-toolkit/app/lib/JSDOC/Symbol.js +644 -0
  74. data/vendor/jsdoc-toolkit/app/lib/JSDOC/SymbolSet.js +241 -0
  75. data/vendor/jsdoc-toolkit/app/lib/JSDOC/TextStream.js +41 -0
  76. data/vendor/jsdoc-toolkit/app/lib/JSDOC/Token.js +18 -0
  77. data/vendor/jsdoc-toolkit/app/lib/JSDOC/TokenReader.js +332 -0
  78. data/vendor/jsdoc-toolkit/app/lib/JSDOC/TokenStream.js +133 -0
  79. data/vendor/jsdoc-toolkit/app/lib/JSDOC/Util.js +32 -0
  80. data/vendor/jsdoc-toolkit/app/lib/JSDOC/Walker.js +499 -0
  81. data/vendor/jsdoc-toolkit/app/lib/JSDOC.js +106 -0
  82. data/vendor/jsdoc-toolkit/app/main.js +129 -0
  83. data/vendor/jsdoc-toolkit/app/plugins/commentSrcJson.js +20 -0
  84. data/vendor/jsdoc-toolkit/app/plugins/frameworkPrototype.js +16 -0
  85. data/vendor/jsdoc-toolkit/app/plugins/functionCall.js +10 -0
  86. data/vendor/jsdoc-toolkit/app/plugins/publishSrcHilite.js +54 -0
  87. data/vendor/jsdoc-toolkit/app/plugins/symbolLink.js +10 -0
  88. data/vendor/jsdoc-toolkit/app/plugins/tagParamConfig.js +31 -0
  89. data/vendor/jsdoc-toolkit/app/plugins/tagSynonyms.js +43 -0
  90. data/vendor/jsdoc-toolkit/app/run.js +348 -0
  91. data/vendor/jsdoc-toolkit/app/t/TestDoc.js +144 -0
  92. data/vendor/jsdoc-toolkit/app/t/runner.js +13 -0
  93. data/vendor/jsdoc-toolkit/app/test/addon.js +24 -0
  94. data/vendor/jsdoc-toolkit/app/test/anon_inner.js +14 -0
  95. data/vendor/jsdoc-toolkit/app/test/augments.js +31 -0
  96. data/vendor/jsdoc-toolkit/app/test/augments2.js +26 -0
  97. data/vendor/jsdoc-toolkit/app/test/borrows.js +46 -0
  98. data/vendor/jsdoc-toolkit/app/test/borrows2.js +23 -0
  99. data/vendor/jsdoc-toolkit/app/test/config.js +22 -0
  100. data/vendor/jsdoc-toolkit/app/test/constructs.js +18 -0
  101. data/vendor/jsdoc-toolkit/app/test/encoding.js +10 -0
  102. data/vendor/jsdoc-toolkit/app/test/encoding_other.js +12 -0
  103. data/vendor/jsdoc-toolkit/app/test/event.js +54 -0
  104. data/vendor/jsdoc-toolkit/app/test/exports.js +14 -0
  105. data/vendor/jsdoc-toolkit/app/test/functions_anon.js +39 -0
  106. data/vendor/jsdoc-toolkit/app/test/functions_nested.js +33 -0
  107. data/vendor/jsdoc-toolkit/app/test/global.js +13 -0
  108. data/vendor/jsdoc-toolkit/app/test/globals.js +25 -0
  109. data/vendor/jsdoc-toolkit/app/test/ignore.js +10 -0
  110. data/vendor/jsdoc-toolkit/app/test/inner.js +16 -0
  111. data/vendor/jsdoc-toolkit/app/test/jsdoc_test.js +477 -0
  112. data/vendor/jsdoc-toolkit/app/test/lend.js +33 -0
  113. data/vendor/jsdoc-toolkit/app/test/memberof.js +19 -0
  114. data/vendor/jsdoc-toolkit/app/test/memberof2.js +38 -0
  115. data/vendor/jsdoc-toolkit/app/test/memberof3.js +33 -0
  116. data/vendor/jsdoc-toolkit/app/test/memberof_constructor.js +17 -0
  117. data/vendor/jsdoc-toolkit/app/test/module.js +17 -0
  118. data/vendor/jsdoc-toolkit/app/test/name.js +19 -0
  119. data/vendor/jsdoc-toolkit/app/test/namespace_nested.js +23 -0
  120. data/vendor/jsdoc-toolkit/app/test/nocode.js +13 -0
  121. data/vendor/jsdoc-toolkit/app/test/oblit_anon.js +20 -0
  122. data/vendor/jsdoc-toolkit/app/test/overview.js +20 -0
  123. data/vendor/jsdoc-toolkit/app/test/param_inline.js +37 -0
  124. data/vendor/jsdoc-toolkit/app/test/params_optional.js +8 -0
  125. data/vendor/jsdoc-toolkit/app/test/prototype.js +17 -0
  126. data/vendor/jsdoc-toolkit/app/test/prototype_nested.js +9 -0
  127. data/vendor/jsdoc-toolkit/app/test/prototype_oblit.js +13 -0
  128. data/vendor/jsdoc-toolkit/app/test/prototype_oblit_constructor.js +24 -0
  129. data/vendor/jsdoc-toolkit/app/test/public.js +10 -0
  130. data/vendor/jsdoc-toolkit/app/test/scripts/code.js +5 -0
  131. data/vendor/jsdoc-toolkit/app/test/scripts/notcode.txt +5 -0
  132. data/vendor/jsdoc-toolkit/app/test/shared.js +42 -0
  133. data/vendor/jsdoc-toolkit/app/test/shared2.js +2 -0
  134. data/vendor/jsdoc-toolkit/app/test/shortcuts.js +22 -0
  135. data/vendor/jsdoc-toolkit/app/test/static_this.js +13 -0
  136. data/vendor/jsdoc-toolkit/app/test/synonyms.js +31 -0
  137. data/vendor/jsdoc-toolkit/app/test/tosource.js +23 -0
  138. data/vendor/jsdoc-toolkit/app/test/variable_redefine.js +14 -0
  139. data/vendor/jsdoc-toolkit/app/test.js +342 -0
  140. data/vendor/jsdoc-toolkit/changes.txt +116 -0
  141. data/vendor/jsdoc-toolkit/conf/sample.conf +31 -0
  142. data/vendor/jsdoc-toolkit/java/build.xml +36 -0
  143. data/vendor/jsdoc-toolkit/java/build_1.4.xml +36 -0
  144. data/vendor/jsdoc-toolkit/java/classes/js.jar +0 -0
  145. data/vendor/jsdoc-toolkit/java/src/JsDebugRun.java +21 -0
  146. data/vendor/jsdoc-toolkit/java/src/JsRun.java +21 -0
  147. data/vendor/jsdoc-toolkit/jsdebug.jar +0 -0
  148. data/vendor/jsdoc-toolkit/jsrun.jar +0 -0
  149. data/vendor/jsdoc-toolkit/jsrun.sh +53 -0
  150. data/vendor/jsdoc-toolkit/templates/jsdoc/allclasses.tmpl +17 -0
  151. data/vendor/jsdoc-toolkit/templates/jsdoc/allfiles.tmpl +56 -0
  152. data/vendor/jsdoc-toolkit/templates/jsdoc/class.tmpl +649 -0
  153. data/vendor/jsdoc-toolkit/templates/jsdoc/index.tmpl +39 -0
  154. data/vendor/jsdoc-toolkit/templates/jsdoc/publish.js +201 -0
  155. data/vendor/jsdoc-toolkit/templates/jsdoc/static/code-footer.html +3 -0
  156. data/vendor/jsdoc-toolkit/templates/jsdoc/static/code-header.html +14 -0
  157. data/vendor/jsdoc-toolkit/templates/jsdoc/static/default.css +162 -0
  158. data/vendor/jsdoc-toolkit/templates/jsdoc/static/header.html +2 -0
  159. data/vendor/jsdoc-toolkit/templates/jsdoc/static/index.html +19 -0
  160. data/vendor/jsdoc-toolkit/templates/jsdoc/symbol.tmpl +35 -0
  161. data/vendor/jsl-0.3.0/src/JavaScriptLintAPI.cpp +333 -0
  162. data/vendor/jsl-0.3.0/src/JavaScriptLintAPI.h +86 -0
  163. data/vendor/jsl-0.3.0/src/Makefile.in +375 -0
  164. data/vendor/jsl-0.3.0/src/Makefile.ref +372 -0
  165. data/vendor/jsl-0.3.0/src/README.html +826 -0
  166. data/vendor/jsl-0.3.0/src/SpiderMonkey.rsp +12 -0
  167. data/vendor/jsl-0.3.0/src/_jsl_online.php +223 -0
  168. data/vendor/jsl-0.3.0/src/config/AIX4.1.mk +65 -0
  169. data/vendor/jsl-0.3.0/src/config/AIX4.2.mk +64 -0
  170. data/vendor/jsl-0.3.0/src/config/AIX4.3.mk +65 -0
  171. data/vendor/jsl-0.3.0/src/config/Darwin.mk +81 -0
  172. data/vendor/jsl-0.3.0/src/config/Darwin1.3.mk +81 -0
  173. data/vendor/jsl-0.3.0/src/config/Darwin1.4.mk +41 -0
  174. data/vendor/jsl-0.3.0/src/config/Darwin5.2.mk +81 -0
  175. data/vendor/jsl-0.3.0/src/config/Darwin5.3.mk +81 -0
  176. data/vendor/jsl-0.3.0/src/config/HP-UXB.10.10.mk +77 -0
  177. data/vendor/jsl-0.3.0/src/config/HP-UXB.10.20.mk +77 -0
  178. data/vendor/jsl-0.3.0/src/config/HP-UXB.11.00.mk +80 -0
  179. data/vendor/jsl-0.3.0/src/config/IRIX.mk +87 -0
  180. data/vendor/jsl-0.3.0/src/config/IRIX5.3.mk +44 -0
  181. data/vendor/jsl-0.3.0/src/config/IRIX6.1.mk +44 -0
  182. data/vendor/jsl-0.3.0/src/config/IRIX6.2.mk +44 -0
  183. data/vendor/jsl-0.3.0/src/config/IRIX6.3.mk +44 -0
  184. data/vendor/jsl-0.3.0/src/config/IRIX6.5.mk +44 -0
  185. data/vendor/jsl-0.3.0/src/config/Linux_All.mk +103 -0
  186. data/vendor/jsl-0.3.0/src/config/Mac_OS10.0.mk +82 -0
  187. data/vendor/jsl-0.3.0/src/config/OSF1V4.0.mk +72 -0
  188. data/vendor/jsl-0.3.0/src/config/OSF1V5.0.mk +69 -0
  189. data/vendor/jsl-0.3.0/src/config/SunOS4.1.4.mk +101 -0
  190. data/vendor/jsl-0.3.0/src/config/SunOS5.3.mk +91 -0
  191. data/vendor/jsl-0.3.0/src/config/SunOS5.4.mk +92 -0
  192. data/vendor/jsl-0.3.0/src/config/SunOS5.5.1.mk +44 -0
  193. data/vendor/jsl-0.3.0/src/config/SunOS5.5.mk +87 -0
  194. data/vendor/jsl-0.3.0/src/config/SunOS5.6.mk +89 -0
  195. data/vendor/jsl-0.3.0/src/config/SunOS5.7.mk +44 -0
  196. data/vendor/jsl-0.3.0/src/config/SunOS5.8.mk +44 -0
  197. data/vendor/jsl-0.3.0/src/config/SunOS5.9.mk +44 -0
  198. data/vendor/jsl-0.3.0/src/config/WINNT4.0.mk +112 -0
  199. data/vendor/jsl-0.3.0/src/config/WINNT5.0.mk +112 -0
  200. data/vendor/jsl-0.3.0/src/config/WINNT5.1.mk +112 -0
  201. data/vendor/jsl-0.3.0/src/config/WINNT5.2.mk +112 -0
  202. data/vendor/jsl-0.3.0/src/config/dgux.mk +64 -0
  203. data/vendor/jsl-0.3.0/src/config.mk +166 -0
  204. data/vendor/jsl-0.3.0/src/editline/Makefile.ref +144 -0
  205. data/vendor/jsl-0.3.0/src/editline/README +83 -0
  206. data/vendor/jsl-0.3.0/src/editline/editline.3 +175 -0
  207. data/vendor/jsl-0.3.0/src/editline/editline.c +1369 -0
  208. data/vendor/jsl-0.3.0/src/editline/editline.h +135 -0
  209. data/vendor/jsl-0.3.0/src/editline/sysunix.c +182 -0
  210. data/vendor/jsl-0.3.0/src/editline/unix.h +82 -0
  211. data/vendor/jsl-0.3.0/src/fdlibm/Makefile.in +127 -0
  212. data/vendor/jsl-0.3.0/src/fdlibm/Makefile.ref +192 -0
  213. data/vendor/jsl-0.3.0/src/fdlibm/e_acos.c +147 -0
  214. data/vendor/jsl-0.3.0/src/fdlibm/e_acosh.c +105 -0
  215. data/vendor/jsl-0.3.0/src/fdlibm/e_asin.c +156 -0
  216. data/vendor/jsl-0.3.0/src/fdlibm/e_atan2.c +165 -0
  217. data/vendor/jsl-0.3.0/src/fdlibm/e_atanh.c +110 -0
  218. data/vendor/jsl-0.3.0/src/fdlibm/e_cosh.c +133 -0
  219. data/vendor/jsl-0.3.0/src/fdlibm/e_exp.c +202 -0
  220. data/vendor/jsl-0.3.0/src/fdlibm/e_fmod.c +184 -0
  221. data/vendor/jsl-0.3.0/src/fdlibm/e_gamma.c +71 -0
  222. data/vendor/jsl-0.3.0/src/fdlibm/e_gamma_r.c +70 -0
  223. data/vendor/jsl-0.3.0/src/fdlibm/e_hypot.c +173 -0
  224. data/vendor/jsl-0.3.0/src/fdlibm/e_j0.c +524 -0
  225. data/vendor/jsl-0.3.0/src/fdlibm/e_j1.c +523 -0
  226. data/vendor/jsl-0.3.0/src/fdlibm/e_jn.c +315 -0
  227. data/vendor/jsl-0.3.0/src/fdlibm/e_lgamma.c +71 -0
  228. data/vendor/jsl-0.3.0/src/fdlibm/e_lgamma_r.c +347 -0
  229. data/vendor/jsl-0.3.0/src/fdlibm/e_log.c +184 -0
  230. data/vendor/jsl-0.3.0/src/fdlibm/e_log10.c +134 -0
  231. data/vendor/jsl-0.3.0/src/fdlibm/e_pow.c +386 -0
  232. data/vendor/jsl-0.3.0/src/fdlibm/e_rem_pio2.c +221 -0
  233. data/vendor/jsl-0.3.0/src/fdlibm/e_remainder.c +120 -0
  234. data/vendor/jsl-0.3.0/src/fdlibm/e_scalb.c +89 -0
  235. data/vendor/jsl-0.3.0/src/fdlibm/e_sinh.c +122 -0
  236. data/vendor/jsl-0.3.0/src/fdlibm/e_sqrt.c +497 -0
  237. data/vendor/jsl-0.3.0/src/fdlibm/fdlibm.dsp +160 -0
  238. data/vendor/jsl-0.3.0/src/fdlibm/fdlibm.h +273 -0
  239. data/vendor/jsl-0.3.0/src/fdlibm/fdlibm.mak +1453 -0
  240. data/vendor/jsl-0.3.0/src/fdlibm/fdlibm.mdp +0 -0
  241. data/vendor/jsl-0.3.0/src/fdlibm/k_cos.c +134 -0
  242. data/vendor/jsl-0.3.0/src/fdlibm/k_rem_pio2.c +354 -0
  243. data/vendor/jsl-0.3.0/src/fdlibm/k_sin.c +114 -0
  244. data/vendor/jsl-0.3.0/src/fdlibm/k_standard.c +785 -0
  245. data/vendor/jsl-0.3.0/src/fdlibm/k_tan.c +170 -0
  246. data/vendor/jsl-0.3.0/src/fdlibm/s_asinh.c +101 -0
  247. data/vendor/jsl-0.3.0/src/fdlibm/s_atan.c +175 -0
  248. data/vendor/jsl-0.3.0/src/fdlibm/s_cbrt.c +133 -0
  249. data/vendor/jsl-0.3.0/src/fdlibm/s_ceil.c +120 -0
  250. data/vendor/jsl-0.3.0/src/fdlibm/s_copysign.c +72 -0
  251. data/vendor/jsl-0.3.0/src/fdlibm/s_cos.c +118 -0
  252. data/vendor/jsl-0.3.0/src/fdlibm/s_erf.c +356 -0
  253. data/vendor/jsl-0.3.0/src/fdlibm/s_expm1.c +267 -0
  254. data/vendor/jsl-0.3.0/src/fdlibm/s_fabs.c +70 -0
  255. data/vendor/jsl-0.3.0/src/fdlibm/s_finite.c +71 -0
  256. data/vendor/jsl-0.3.0/src/fdlibm/s_floor.c +121 -0
  257. data/vendor/jsl-0.3.0/src/fdlibm/s_frexp.c +99 -0
  258. data/vendor/jsl-0.3.0/src/fdlibm/s_ilogb.c +85 -0
  259. data/vendor/jsl-0.3.0/src/fdlibm/s_isnan.c +74 -0
  260. data/vendor/jsl-0.3.0/src/fdlibm/s_ldexp.c +66 -0
  261. data/vendor/jsl-0.3.0/src/fdlibm/s_lib_version.c +73 -0
  262. data/vendor/jsl-0.3.0/src/fdlibm/s_log1p.c +211 -0
  263. data/vendor/jsl-0.3.0/src/fdlibm/s_logb.c +79 -0
  264. data/vendor/jsl-0.3.0/src/fdlibm/s_matherr.c +64 -0
  265. data/vendor/jsl-0.3.0/src/fdlibm/s_modf.c +132 -0
  266. data/vendor/jsl-0.3.0/src/fdlibm/s_nextafter.c +124 -0
  267. data/vendor/jsl-0.3.0/src/fdlibm/s_rint.c +131 -0
  268. data/vendor/jsl-0.3.0/src/fdlibm/s_scalbn.c +107 -0
  269. data/vendor/jsl-0.3.0/src/fdlibm/s_signgam.c +40 -0
  270. data/vendor/jsl-0.3.0/src/fdlibm/s_significand.c +68 -0
  271. data/vendor/jsl-0.3.0/src/fdlibm/s_sin.c +118 -0
  272. data/vendor/jsl-0.3.0/src/fdlibm/s_tan.c +112 -0
  273. data/vendor/jsl-0.3.0/src/fdlibm/s_tanh.c +122 -0
  274. data/vendor/jsl-0.3.0/src/fdlibm/w_acos.c +78 -0
  275. data/vendor/jsl-0.3.0/src/fdlibm/w_acosh.c +78 -0
  276. data/vendor/jsl-0.3.0/src/fdlibm/w_asin.c +80 -0
  277. data/vendor/jsl-0.3.0/src/fdlibm/w_atan2.c +79 -0
  278. data/vendor/jsl-0.3.0/src/fdlibm/w_atanh.c +81 -0
  279. data/vendor/jsl-0.3.0/src/fdlibm/w_cosh.c +77 -0
  280. data/vendor/jsl-0.3.0/src/fdlibm/w_exp.c +88 -0
  281. data/vendor/jsl-0.3.0/src/fdlibm/w_fmod.c +78 -0
  282. data/vendor/jsl-0.3.0/src/fdlibm/w_gamma.c +85 -0
  283. data/vendor/jsl-0.3.0/src/fdlibm/w_gamma_r.c +81 -0
  284. data/vendor/jsl-0.3.0/src/fdlibm/w_hypot.c +78 -0
  285. data/vendor/jsl-0.3.0/src/fdlibm/w_j0.c +105 -0
  286. data/vendor/jsl-0.3.0/src/fdlibm/w_j1.c +106 -0
  287. data/vendor/jsl-0.3.0/src/fdlibm/w_jn.c +128 -0
  288. data/vendor/jsl-0.3.0/src/fdlibm/w_lgamma.c +85 -0
  289. data/vendor/jsl-0.3.0/src/fdlibm/w_lgamma_r.c +81 -0
  290. data/vendor/jsl-0.3.0/src/fdlibm/w_log.c +78 -0
  291. data/vendor/jsl-0.3.0/src/fdlibm/w_log10.c +81 -0
  292. data/vendor/jsl-0.3.0/src/fdlibm/w_pow.c +99 -0
  293. data/vendor/jsl-0.3.0/src/fdlibm/w_remainder.c +77 -0
  294. data/vendor/jsl-0.3.0/src/fdlibm/w_scalb.c +95 -0
  295. data/vendor/jsl-0.3.0/src/fdlibm/w_sinh.c +77 -0
  296. data/vendor/jsl-0.3.0/src/fdlibm/w_sqrt.c +77 -0
  297. data/vendor/jsl-0.3.0/src/js.c +2447 -0
  298. data/vendor/jsl-0.3.0/src/js.dsp +420 -0
  299. data/vendor/jsl-0.3.0/src/js.mak +4025 -0
  300. data/vendor/jsl-0.3.0/src/js.mdp +0 -0
  301. data/vendor/jsl-0.3.0/src/js.msg +291 -0
  302. data/vendor/jsl-0.3.0/src/js.pkg +2 -0
  303. data/vendor/jsl-0.3.0/src/js3240.rc +79 -0
  304. data/vendor/jsl-0.3.0/src/jsOS240.def +654 -0
  305. data/vendor/jsl-0.3.0/src/jsapi.c +4405 -0
  306. data/vendor/jsl-0.3.0/src/jsapi.h +1856 -0
  307. data/vendor/jsl-0.3.0/src/jsarena.c +567 -0
  308. data/vendor/jsl-0.3.0/src/jsarena.h +302 -0
  309. data/vendor/jsl-0.3.0/src/jsarray.c +1428 -0
  310. data/vendor/jsl-0.3.0/src/jsarray.h +77 -0
  311. data/vendor/jsl-0.3.0/src/jsatom.c +927 -0
  312. data/vendor/jsl-0.3.0/src/jsatom.h +426 -0
  313. data/vendor/jsl-0.3.0/src/jsbit.h +113 -0
  314. data/vendor/jsl-0.3.0/src/jsbool.c +220 -0
  315. data/vendor/jsl-0.3.0/src/jsbool.h +62 -0
  316. data/vendor/jsl-0.3.0/src/jsclist.h +139 -0
  317. data/vendor/jsl-0.3.0/src/jscntxt.c +1036 -0
  318. data/vendor/jsl-0.3.0/src/jscntxt.h +608 -0
  319. data/vendor/jsl-0.3.0/src/jscompat.h +57 -0
  320. data/vendor/jsl-0.3.0/src/jsconfig.h +489 -0
  321. data/vendor/jsl-0.3.0/src/jsconfig.mk +181 -0
  322. data/vendor/jsl-0.3.0/src/jscpucfg.c +377 -0
  323. data/vendor/jsl-0.3.0/src/jscpucfg.h +204 -0
  324. data/vendor/jsl-0.3.0/src/jsdate.c +2238 -0
  325. data/vendor/jsl-0.3.0/src/jsdate.h +118 -0
  326. data/vendor/jsl-0.3.0/src/jsdbgapi.c +1260 -0
  327. data/vendor/jsl-0.3.0/src/jsdbgapi.h +345 -0
  328. data/vendor/jsl-0.3.0/src/jsdhash.c +763 -0
  329. data/vendor/jsl-0.3.0/src/jsdhash.h +579 -0
  330. data/vendor/jsl-0.3.0/src/jsdtoa.c +3135 -0
  331. data/vendor/jsl-0.3.0/src/jsdtoa.h +130 -0
  332. data/vendor/jsl-0.3.0/src/jsemit.c +4851 -0
  333. data/vendor/jsl-0.3.0/src/jsemit.h +576 -0
  334. data/vendor/jsl-0.3.0/src/jsexn.c +1084 -0
  335. data/vendor/jsl-0.3.0/src/jsexn.h +102 -0
  336. data/vendor/jsl-0.3.0/src/jsfile.c +2610 -0
  337. data/vendor/jsl-0.3.0/src/jsfile.h +50 -0
  338. data/vendor/jsl-0.3.0/src/jsfile.msg +89 -0
  339. data/vendor/jsl-0.3.0/src/jsfun.c +2015 -0
  340. data/vendor/jsl-0.3.0/src/jsfun.h +158 -0
  341. data/vendor/jsl-0.3.0/src/jsgc.c +1441 -0
  342. data/vendor/jsl-0.3.0/src/jsgc.h +230 -0
  343. data/vendor/jsl-0.3.0/src/jshash.c +471 -0
  344. data/vendor/jsl-0.3.0/src/jshash.h +152 -0
  345. data/vendor/jsl-0.3.0/src/jsify.pl +485 -0
  346. data/vendor/jsl-0.3.0/src/jsinterp.c +4797 -0
  347. data/vendor/jsl-0.3.0/src/jsinterp.h +302 -0
  348. data/vendor/jsl-0.3.0/src/jsl-test.js +28 -0
  349. data/vendor/jsl-0.3.0/src/jsl.c +2371 -0
  350. data/vendor/jsl-0.3.0/src/jsl.conf +127 -0
  351. data/vendor/jsl-0.3.0/src/jsl.conf.old +124 -0
  352. data/vendor/jsl-0.3.0/src/jsl.dsp +242 -0
  353. data/vendor/jsl-0.3.0/src/jsl.dsw +59 -0
  354. data/vendor/jsl-0.3.0/src/jslibmath.h +290 -0
  355. data/vendor/jsl-0.3.0/src/jslock.c +1261 -0
  356. data/vendor/jsl-0.3.0/src/jslock.h +289 -0
  357. data/vendor/jsl-0.3.0/src/jslocko.asm +59 -0
  358. data/vendor/jsl-0.3.0/src/jslog2.c +83 -0
  359. data/vendor/jsl-0.3.0/src/jslong.c +281 -0
  360. data/vendor/jsl-0.3.0/src/jslong.h +437 -0
  361. data/vendor/jsl-0.3.0/src/jsmath.c +477 -0
  362. data/vendor/jsl-0.3.0/src/jsmath.h +55 -0
  363. data/vendor/jsl-0.3.0/src/jsnum.c +1148 -0
  364. data/vendor/jsl-0.3.0/src/jsnum.h +257 -0
  365. data/vendor/jsl-0.3.0/src/jsobj.c +4066 -0
  366. data/vendor/jsl-0.3.0/src/jsobj.h +475 -0
  367. data/vendor/jsl-0.3.0/src/jsopcode.c +2730 -0
  368. data/vendor/jsl-0.3.0/src/jsopcode.h +275 -0
  369. data/vendor/jsl-0.3.0/src/jsopcode.tbl +344 -0
  370. data/vendor/jsl-0.3.0/src/jsosdep.h +127 -0
  371. data/vendor/jsl-0.3.0/src/jsotypes.h +211 -0
  372. data/vendor/jsl-0.3.0/src/jsparse.c +4438 -0
  373. data/vendor/jsl-0.3.0/src/jsparse.h +345 -0
  374. data/vendor/jsl-0.3.0/src/jsprf.c +1212 -0
  375. data/vendor/jsl-0.3.0/src/jsprf.h +148 -0
  376. data/vendor/jsl-0.3.0/src/jsprvtd.h +174 -0
  377. data/vendor/jsl-0.3.0/src/jspubtd.h +586 -0
  378. data/vendor/jsl-0.3.0/src/jsregexp.c +3831 -0
  379. data/vendor/jsl-0.3.0/src/jsregexp.h +180 -0
  380. data/vendor/jsl-0.3.0/src/jsscan.c +1814 -0
  381. data/vendor/jsl-0.3.0/src/jsscan.h +267 -0
  382. data/vendor/jsl-0.3.0/src/jsscope.c +1639 -0
  383. data/vendor/jsl-0.3.0/src/jsscope.h +389 -0
  384. data/vendor/jsl-0.3.0/src/jsscript.c +1284 -0
  385. data/vendor/jsl-0.3.0/src/jsscript.h +179 -0
  386. data/vendor/jsl-0.3.0/src/jsshell.msg +50 -0
  387. data/vendor/jsl-0.3.0/src/jsstddef.h +83 -0
  388. data/vendor/jsl-0.3.0/src/jsstr.c +4502 -0
  389. data/vendor/jsl-0.3.0/src/jsstr.h +448 -0
  390. data/vendor/jsl-0.3.0/src/jstypes.h +391 -0
  391. data/vendor/jsl-0.3.0/src/jsutil.c +157 -0
  392. data/vendor/jsl-0.3.0/src/jsutil.h +75 -0
  393. data/vendor/jsl-0.3.0/src/jsxdrapi.c +686 -0
  394. data/vendor/jsl-0.3.0/src/jsxdrapi.h +193 -0
  395. data/vendor/jsl-0.3.0/src/liveconnect/LiveConnect.dsp +157 -0
  396. data/vendor/jsl-0.3.0/src/liveconnect/LiveConnectShell.dsp +120 -0
  397. data/vendor/jsl-0.3.0/src/liveconnect/LiveConnectShell.dsw +44 -0
  398. data/vendor/jsl-0.3.0/src/liveconnect/Makefile.in +106 -0
  399. data/vendor/jsl-0.3.0/src/liveconnect/Makefile.ref +169 -0
  400. data/vendor/jsl-0.3.0/src/liveconnect/README.html +719 -0
  401. data/vendor/jsl-0.3.0/src/liveconnect/_jni/netscape_javascript_JSException.h +14 -0
  402. data/vendor/jsl-0.3.0/src/liveconnect/_jni/netscape_javascript_JSObject.h +155 -0
  403. data/vendor/jsl-0.3.0/src/liveconnect/classes/Makefile.in +89 -0
  404. data/vendor/jsl-0.3.0/src/liveconnect/classes/Makefile.ref +57 -0
  405. data/vendor/jsl-0.3.0/src/liveconnect/classes/netscape/Makefile.ref +47 -0
  406. data/vendor/jsl-0.3.0/src/liveconnect/classes/netscape/javascript/JSException.java +140 -0
  407. data/vendor/jsl-0.3.0/src/liveconnect/classes/netscape/javascript/JSObject.java +183 -0
  408. data/vendor/jsl-0.3.0/src/liveconnect/classes/netscape/javascript/JSProxy.java +58 -0
  409. data/vendor/jsl-0.3.0/src/liveconnect/classes/netscape/javascript/JSRunnable.java +70 -0
  410. data/vendor/jsl-0.3.0/src/liveconnect/classes/netscape/javascript/JSUtil.java +59 -0
  411. data/vendor/jsl-0.3.0/src/liveconnect/classes/netscape/javascript/Makefile.ref +53 -0
  412. data/vendor/jsl-0.3.0/src/liveconnect/config/AIX4.1.mk +45 -0
  413. data/vendor/jsl-0.3.0/src/liveconnect/config/AIX4.2.mk +45 -0
  414. data/vendor/jsl-0.3.0/src/liveconnect/config/AIX4.3.mk +50 -0
  415. data/vendor/jsl-0.3.0/src/liveconnect/config/HP-UXB.10.10.mk +43 -0
  416. data/vendor/jsl-0.3.0/src/liveconnect/config/HP-UXB.10.20.mk +43 -0
  417. data/vendor/jsl-0.3.0/src/liveconnect/config/HP-UXB.11.00.mk +43 -0
  418. data/vendor/jsl-0.3.0/src/liveconnect/config/IRIX6.2.mk +43 -0
  419. data/vendor/jsl-0.3.0/src/liveconnect/config/IRIX6.3.mk +43 -0
  420. data/vendor/jsl-0.3.0/src/liveconnect/config/IRIX6.5.mk +43 -0
  421. data/vendor/jsl-0.3.0/src/liveconnect/config/Linux_All.mk +73 -0
  422. data/vendor/jsl-0.3.0/src/liveconnect/config/OSF1V4.0.mk +65 -0
  423. data/vendor/jsl-0.3.0/src/liveconnect/config/OSF1V5.0.mk +62 -0
  424. data/vendor/jsl-0.3.0/src/liveconnect/config/SunOS5.5.1.mk +55 -0
  425. data/vendor/jsl-0.3.0/src/liveconnect/config/SunOS5.6.mk +39 -0
  426. data/vendor/jsl-0.3.0/src/liveconnect/config/SunOS5.7.mk +39 -0
  427. data/vendor/jsl-0.3.0/src/liveconnect/config/SunOS5.8.mk +39 -0
  428. data/vendor/jsl-0.3.0/src/liveconnect/config/WINNT4.0.mk +53 -0
  429. data/vendor/jsl-0.3.0/src/liveconnect/jsj.c +884 -0
  430. data/vendor/jsl-0.3.0/src/liveconnect/jsj.msg +98 -0
  431. data/vendor/jsl-0.3.0/src/liveconnect/jsj_JSObject.c +1379 -0
  432. data/vendor/jsl-0.3.0/src/liveconnect/jsj_JavaArray.c +481 -0
  433. data/vendor/jsl-0.3.0/src/liveconnect/jsj_JavaClass.c +749 -0
  434. data/vendor/jsl-0.3.0/src/liveconnect/jsj_JavaMember.c +186 -0
  435. data/vendor/jsl-0.3.0/src/liveconnect/jsj_JavaObject.c +1099 -0
  436. data/vendor/jsl-0.3.0/src/liveconnect/jsj_JavaPackage.c +548 -0
  437. data/vendor/jsl-0.3.0/src/liveconnect/jsj_array.c +207 -0
  438. data/vendor/jsl-0.3.0/src/liveconnect/jsj_class.c +765 -0
  439. data/vendor/jsl-0.3.0/src/liveconnect/jsj_convert.c +954 -0
  440. data/vendor/jsl-0.3.0/src/liveconnect/jsj_field.c +421 -0
  441. data/vendor/jsl-0.3.0/src/liveconnect/jsj_hash.c +504 -0
  442. data/vendor/jsl-0.3.0/src/liveconnect/jsj_hash.h +161 -0
  443. data/vendor/jsl-0.3.0/src/liveconnect/jsj_method.c +1823 -0
  444. data/vendor/jsl-0.3.0/src/liveconnect/jsj_nodl.c +1 -0
  445. data/vendor/jsl-0.3.0/src/liveconnect/jsj_private.h +689 -0
  446. data/vendor/jsl-0.3.0/src/liveconnect/jsj_simpleapi.c +219 -0
  447. data/vendor/jsl-0.3.0/src/liveconnect/jsj_utils.c +513 -0
  448. data/vendor/jsl-0.3.0/src/liveconnect/jsjava.h +313 -0
  449. data/vendor/jsl-0.3.0/src/liveconnect/liveconnect.pkg +3 -0
  450. data/vendor/jsl-0.3.0/src/liveconnect/netscape_javascript_JSObject.h +155 -0
  451. data/vendor/jsl-0.3.0/src/liveconnect/nsCLiveconnect.cpp +785 -0
  452. data/vendor/jsl-0.3.0/src/liveconnect/nsCLiveconnect.h +197 -0
  453. data/vendor/jsl-0.3.0/src/liveconnect/nsCLiveconnectFactory.cpp +163 -0
  454. data/vendor/jsl-0.3.0/src/liveconnect/nsCLiveconnectFactory.h +76 -0
  455. data/vendor/jsl-0.3.0/src/liveconnect/nsILiveconnect.h +195 -0
  456. data/vendor/jsl-0.3.0/src/liveconnect/nsISecureLiveconnect.h +84 -0
  457. data/vendor/jsl-0.3.0/src/liveconnect/nsISecurityContext.h +135 -0
  458. data/vendor/jsl-0.3.0/src/liveconnect/win32.order +6 -0
  459. data/vendor/jsl-0.3.0/src/lock_SunOS.s +114 -0
  460. data/vendor/jsl-0.3.0/src/perfect.js +39 -0
  461. data/vendor/jsl-0.3.0/src/perlconnect/JS.def +6 -0
  462. data/vendor/jsl-0.3.0/src/perlconnect/JS.dsp +107 -0
  463. data/vendor/jsl-0.3.0/src/perlconnect/JS.pm +318 -0
  464. data/vendor/jsl-0.3.0/src/perlconnect/JS.xs +1050 -0
  465. data/vendor/jsl-0.3.0/src/perlconnect/Makefile.PL +67 -0
  466. data/vendor/jsl-0.3.0/src/perlconnect/Makefile.ref +152 -0
  467. data/vendor/jsl-0.3.0/src/perlconnect/PerlConnect.dsp +103 -0
  468. data/vendor/jsl-0.3.0/src/perlconnect/PerlConnect.dsw +59 -0
  469. data/vendor/jsl-0.3.0/src/perlconnect/PerlConnect.pm +126 -0
  470. data/vendor/jsl-0.3.0/src/perlconnect/PerlConnectShell.dsp +89 -0
  471. data/vendor/jsl-0.3.0/src/perlconnect/README.html +345 -0
  472. data/vendor/jsl-0.3.0/src/perlconnect/bg.jpg +0 -0
  473. data/vendor/jsl-0.3.0/src/perlconnect/jsperl.c +1100 -0
  474. data/vendor/jsl-0.3.0/src/perlconnect/jsperl.h +52 -0
  475. data/vendor/jsl-0.3.0/src/perlconnect/jsperlbuild.pl +81 -0
  476. data/vendor/jsl-0.3.0/src/perlconnect/jsperlpvt.h +57 -0
  477. data/vendor/jsl-0.3.0/src/perlconnect/test.js +73 -0
  478. data/vendor/jsl-0.3.0/src/perlconnect/test.pl +244 -0
  479. data/vendor/jsl-0.3.0/src/perlconnect/typemap +121 -0
  480. data/vendor/jsl-0.3.0/src/plify_jsdhash.sed +31 -0
  481. data/vendor/jsl-0.3.0/src/prmjtime.c +646 -0
  482. data/vendor/jsl-0.3.0/src/prmjtime.h +95 -0
  483. data/vendor/jsl-0.3.0/src/resource.h +15 -0
  484. data/vendor/jsl-0.3.0/src/rules.mk +193 -0
  485. data/vendor/jsl-0.3.0/src/win32.order +391 -0
  486. data/vendor/jsl-0.3.0/tests/conf/always_use_option_explicit.js +4 -0
  487. data/vendor/jsl-0.3.0/tests/conf/define.js +8 -0
  488. data/vendor/jsl-0.3.0/tests/conf/jscript_function_extensions-1.js +7 -0
  489. data/vendor/jsl-0.3.0/tests/conf/jscript_function_extensions-2.js +8 -0
  490. data/vendor/jsl-0.3.0/tests/conf/jscript_function_extensions-3.js +27 -0
  491. data/vendor/jsl-0.3.0/tests/conf/jscript_function_extensions-4.js +4 -0
  492. data/vendor/jsl-0.3.0/tests/conf/lambda_assign_requires_semicolon.js +24 -0
  493. data/vendor/jsl-0.3.0/tests/conf/legacy_control_comments.js +8 -0
  494. data/vendor/jsl-0.3.0/tests/control_comments/control_comments.js +33 -0
  495. data/vendor/jsl-0.3.0/tests/control_comments/declare.js +26 -0
  496. data/vendor/jsl-0.3.0/tests/control_comments/import-overflow.js +9 -0
  497. data/vendor/jsl-0.3.0/tests/control_comments/import.js +5 -0
  498. data/vendor/jsl-0.3.0/tests/control_comments/import2.js +2 -0
  499. data/vendor/jsl-0.3.0/tests/control_comments/invalid_fallthru.js +13 -0
  500. data/vendor/jsl-0.3.0/tests/control_comments/option_explicit-with.js +12 -0
  501. data/vendor/jsl-0.3.0/tests/control_comments/option_explicit.js +64 -0
  502. data/vendor/jsl-0.3.0/tests/errors/unterminated_comment.js +8 -0
  503. data/vendor/jsl-0.3.0/tests/html/script_tag_in_js_literal.html +14 -0
  504. data/vendor/jsl-0.3.0/tests/run_tests.pl +71 -0
  505. data/vendor/jsl-0.3.0/tests/warnings/ambiguous_else_stmt.js +21 -0
  506. data/vendor/jsl-0.3.0/tests/warnings/ambiguous_nested_stmt.js +66 -0
  507. data/vendor/jsl-0.3.0/tests/warnings/ambiguous_newline.js +261 -0
  508. data/vendor/jsl-0.3.0/tests/warnings/anon_no_return_value.js +26 -0
  509. data/vendor/jsl-0.3.0/tests/warnings/assign_to_function_call.js +16 -0
  510. data/vendor/jsl-0.3.0/tests/warnings/block_without_braces.js +13 -0
  511. data/vendor/jsl-0.3.0/tests/warnings/comma_separated_stmts.js +17 -0
  512. data/vendor/jsl-0.3.0/tests/warnings/comparison_type_conv.js +44 -0
  513. data/vendor/jsl-0.3.0/tests/warnings/default_not_at_end.js +15 -0
  514. data/vendor/jsl-0.3.0/tests/warnings/dup_option_explicit.js +5 -0
  515. data/vendor/jsl-0.3.0/tests/warnings/duplicate_case_in_switch.js +62 -0
  516. data/vendor/jsl-0.3.0/tests/warnings/duplicate_formal.js +5 -0
  517. data/vendor/jsl-0.3.0/tests/warnings/empty_statement.js +29 -0
  518. data/vendor/jsl-0.3.0/tests/warnings/equal_as_assign.js +7 -0
  519. data/vendor/jsl-0.3.0/tests/warnings/inc_dec_within_stmt-ignore.js +21 -0
  520. data/vendor/jsl-0.3.0/tests/warnings/inc_dec_within_stmt.js +63 -0
  521. data/vendor/jsl-0.3.0/tests/warnings/jsl_cc_not_understood.js +5 -0
  522. data/vendor/jsl-0.3.0/tests/warnings/leading_decimal_point.js +7 -0
  523. data/vendor/jsl-0.3.0/tests/warnings/legacy_cc_not_understood.js +9 -0
  524. data/vendor/jsl-0.3.0/tests/warnings/meaningless_block.js +12 -0
  525. data/vendor/jsl-0.3.0/tests/warnings/misplaced_regex.js +20 -0
  526. data/vendor/jsl-0.3.0/tests/warnings/missing_break.js +87 -0
  527. data/vendor/jsl-0.3.0/tests/warnings/missing_break_for_last_case.js +19 -0
  528. data/vendor/jsl-0.3.0/tests/warnings/missing_default_case.js +51 -0
  529. data/vendor/jsl-0.3.0/tests/warnings/missing_option_explicit.js +5 -0
  530. data/vendor/jsl-0.3.0/tests/warnings/missing_semicolon.js +19 -0
  531. data/vendor/jsl-0.3.0/tests/warnings/multiple_plus_minus.js +10 -0
  532. data/vendor/jsl-0.3.0/tests/warnings/nested_comment.js +6 -0
  533. data/vendor/jsl-0.3.0/tests/warnings/no_return_value.js +25 -0
  534. data/vendor/jsl-0.3.0/tests/warnings/octal_number.js +5 -0
  535. data/vendor/jsl-0.3.0/tests/warnings/parseint_missing_radix.js +15 -0
  536. data/vendor/jsl-0.3.0/tests/warnings/partial_option_explicit.js +5 -0
  537. data/vendor/jsl-0.3.0/tests/warnings/redeclared_var.js +10 -0
  538. data/vendor/jsl-0.3.0/tests/warnings/spidermonkey/bad_backref.js +5 -0
  539. data/vendor/jsl-0.3.0/tests/warnings/spidermonkey/deprecated_usage.js +11 -0
  540. data/vendor/jsl-0.3.0/tests/warnings/spidermonkey/invalid_backref.js +5 -0
  541. data/vendor/jsl-0.3.0/tests/warnings/spidermonkey/trailing_comma.js +5 -0
  542. data/vendor/jsl-0.3.0/tests/warnings/trailing_comma_in_array.js +8 -0
  543. data/vendor/jsl-0.3.0/tests/warnings/trailing_decimal_point.js +7 -0
  544. data/vendor/jsl-0.3.0/tests/warnings/unreachable_code.js +29 -0
  545. data/vendor/jsl-0.3.0/tests/warnings/use_of_label.js +19 -0
  546. data/vendor/jsl-0.3.0/tests/warnings/useless_assign.js +20 -0
  547. data/vendor/jsl-0.3.0/tests/warnings/useless_comparison.js +55 -0
  548. data/vendor/jsl-0.3.0/tests/warnings/useless_void.js +6 -0
  549. data/vendor/jsl-0.3.0/tests/warnings/var_hides_arg.js +4 -0
  550. data/vendor/jsl-0.3.0/tests/warnings/with_statement.js +7 -0
  551. data/vendor/yuicompressor-2.4.2.jar +0 -0
  552. metadata +605 -0
@@ -0,0 +1,4066 @@
1
+ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2
+ *
3
+ * ***** BEGIN LICENSE BLOCK *****
4
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5
+ *
6
+ * The contents of this file are subject to the Mozilla Public License Version
7
+ * 1.1 (the "License"); you may not use this file except in compliance with
8
+ * the License. You may obtain a copy of the License at
9
+ * http://www.mozilla.org/MPL/
10
+ *
11
+ * Software distributed under the License is distributed on an "AS IS" basis,
12
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13
+ * for the specific language governing rights and limitations under the
14
+ * License.
15
+ *
16
+ * The Original Code is Mozilla Communicator client code, released
17
+ * March 31, 1998.
18
+ *
19
+ * The Initial Developer of the Original Code is
20
+ * Netscape Communications Corporation.
21
+ * Portions created by the Initial Developer are Copyright (C) 1998
22
+ * the Initial Developer. All Rights Reserved.
23
+ *
24
+ * Contributor(s):
25
+ *
26
+ * Alternatively, the contents of this file may be used under the terms of
27
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
28
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29
+ * in which case the provisions of the GPL or the LGPL are applicable instead
30
+ * of those above. If you wish to allow use of your version of this file only
31
+ * under the terms of either the GPL or the LGPL, and not to allow others to
32
+ * use your version of this file under the terms of the MPL, indicate your
33
+ * decision by deleting the provisions above and replace them with the notice
34
+ * and other provisions required by the GPL or the LGPL. If you do not delete
35
+ * the provisions above, a recipient may use your version of this file under
36
+ * the terms of any one of the MPL, the GPL or the LGPL.
37
+ *
38
+ * ***** END LICENSE BLOCK ***** */
39
+
40
+ /*
41
+ * JS object implementation.
42
+ */
43
+ #include "jsstddef.h"
44
+ #include <stdlib.h>
45
+ #include <string.h>
46
+ #include "jstypes.h"
47
+ #include "jsarena.h" /* Added by JSIFY */
48
+ #include "jsutil.h" /* Added by JSIFY */
49
+ #include "jshash.h" /* Added by JSIFY */
50
+ #include "jsdhash.h"
51
+ #include "jsprf.h"
52
+ #include "jsapi.h"
53
+ #include "jsarray.h"
54
+ #include "jsatom.h"
55
+ #include "jsbool.h"
56
+ #include "jscntxt.h"
57
+ #include "jsconfig.h"
58
+ #include "jsfun.h"
59
+ #include "jsgc.h"
60
+ #include "jsinterp.h"
61
+ #include "jslock.h"
62
+ #include "jsnum.h"
63
+ #include "jsobj.h"
64
+ #include "jsscope.h"
65
+ #include "jsscript.h"
66
+ #include "jsstr.h"
67
+ #include "jsopcode.h"
68
+
69
+ #include "jsdbgapi.h" /* whether or not JS_HAS_OBJ_WATCHPOINT */
70
+
71
+ #ifdef JS_THREADSAFE
72
+ #define NATIVE_DROP_PROPERTY js_DropProperty
73
+
74
+ extern void
75
+ js_DropProperty(JSContext *cx, JSObject *obj, JSProperty *prop);
76
+ #else
77
+ #define NATIVE_DROP_PROPERTY NULL
78
+ #endif
79
+
80
+ #ifdef XP_MAC
81
+ #pragma export on
82
+ #endif
83
+
84
+ JS_FRIEND_DATA(JSObjectOps) js_ObjectOps = {
85
+ js_NewObjectMap, js_DestroyObjectMap,
86
+ #if defined JS_THREADSAFE && defined DEBUG
87
+ _js_LookupProperty, js_DefineProperty,
88
+ #else
89
+ js_LookupProperty, js_DefineProperty,
90
+ #endif
91
+ js_GetProperty, js_SetProperty,
92
+ js_GetAttributes, js_SetAttributes,
93
+ js_DeleteProperty, js_DefaultValue,
94
+ js_Enumerate, js_CheckAccess,
95
+ NULL, NATIVE_DROP_PROPERTY,
96
+ js_Call, js_Construct,
97
+ NULL, js_HasInstance,
98
+ js_SetProtoOrParent, js_SetProtoOrParent,
99
+ js_Mark, js_Clear,
100
+ js_GetRequiredSlot, js_SetRequiredSlot
101
+ };
102
+
103
+ #ifdef XP_MAC
104
+ #pragma export off
105
+ #endif
106
+
107
+ JSClass js_ObjectClass = {
108
+ js_Object_str,
109
+ 0,
110
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
111
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
112
+ JSCLASS_NO_OPTIONAL_MEMBERS
113
+ };
114
+
115
+ #if JS_HAS_OBJ_PROTO_PROP
116
+
117
+ static JSBool
118
+ obj_getSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
119
+
120
+ static JSBool
121
+ obj_setSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
122
+
123
+ static JSBool
124
+ obj_getCount(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
125
+
126
+ static JSPropertySpec object_props[] = {
127
+ /* These two must come first; see object_props[slot].name usage below. */
128
+ {js_proto_str, JSSLOT_PROTO, JSPROP_PERMANENT|JSPROP_SHARED,
129
+ obj_getSlot, obj_setSlot},
130
+ {js_parent_str,JSSLOT_PARENT,JSPROP_READONLY|JSPROP_PERMANENT|JSPROP_SHARED,
131
+ obj_getSlot, obj_setSlot},
132
+ {js_count_str, 0, JSPROP_PERMANENT,obj_getCount, obj_getCount},
133
+ {0,0,0,0,0}
134
+ };
135
+
136
+ /* NB: JSSLOT_PROTO and JSSLOT_PARENT are already indexes into object_props. */
137
+ #define JSSLOT_COUNT 2
138
+
139
+ static JSBool
140
+ ReportStrictSlot(JSContext *cx, uint32 slot)
141
+ {
142
+ if (slot == JSSLOT_PROTO)
143
+ return JS_TRUE;
144
+ return JS_ReportErrorFlagsAndNumber(cx,
145
+ JSREPORT_WARNING | JSREPORT_STRICT,
146
+ js_GetErrorMessage, NULL,
147
+ JSMSG_DEPRECATED_USAGE,
148
+ object_props[slot].name);
149
+ }
150
+
151
+ static JSBool
152
+ obj_getSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
153
+ {
154
+ uint32 slot;
155
+ JSAccessMode mode;
156
+ uintN attrs;
157
+
158
+ slot = (uint32) JSVAL_TO_INT(id);
159
+ if (id == INT_TO_JSVAL(JSSLOT_PROTO)) {
160
+ id = (jsid)cx->runtime->atomState.protoAtom;
161
+ mode = JSACC_PROTO;
162
+ } else {
163
+ id = (jsid)cx->runtime->atomState.parentAtom;
164
+ mode = JSACC_PARENT;
165
+ }
166
+ if (!OBJ_CHECK_ACCESS(cx, obj, id, mode, vp, &attrs))
167
+ return JS_FALSE;
168
+ *vp = OBJ_GET_SLOT(cx, obj, slot);
169
+ return JS_TRUE;
170
+ }
171
+
172
+ static JSBool
173
+ obj_setSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
174
+ {
175
+ JSObject *pobj;
176
+ uint32 slot;
177
+ uintN attrs;
178
+
179
+ if (!JSVAL_IS_OBJECT(*vp))
180
+ return JS_TRUE;
181
+ pobj = JSVAL_TO_OBJECT(*vp);
182
+ slot = (uint32) JSVAL_TO_INT(id);
183
+ if (JS_HAS_STRICT_OPTION(cx) && !ReportStrictSlot(cx, slot))
184
+ return JS_FALSE;
185
+
186
+ /* __parent__ is readonly and permanent, only __proto__ may be set. */
187
+ if (!OBJ_CHECK_ACCESS(cx, obj, id, JSACC_PROTO | JSACC_WRITE, vp, &attrs))
188
+ return JS_FALSE;
189
+
190
+ return js_SetProtoOrParent(cx, obj, slot, pobj);
191
+ }
192
+
193
+ static JSBool
194
+ obj_getCount(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
195
+ {
196
+ jsval iter_state;
197
+ jsid num_properties;
198
+ JSBool ok;
199
+
200
+ if (JS_HAS_STRICT_OPTION(cx) && !ReportStrictSlot(cx, JSSLOT_COUNT))
201
+ return JS_FALSE;
202
+
203
+ /* Get the number of properties to enumerate. */
204
+ iter_state = JSVAL_NULL;
205
+ ok = OBJ_ENUMERATE(cx, obj, JSENUMERATE_INIT, &iter_state, &num_properties);
206
+ if (!ok)
207
+ goto out;
208
+
209
+ if (!JSVAL_IS_INT(num_properties)) {
210
+ JS_ASSERT(0);
211
+ *vp = JSVAL_ZERO;
212
+ goto out;
213
+ }
214
+ *vp = num_properties;
215
+
216
+ out:
217
+ if (iter_state != JSVAL_NULL)
218
+ ok = OBJ_ENUMERATE(cx, obj, JSENUMERATE_DESTROY, &iter_state, 0);
219
+ return ok;
220
+ }
221
+
222
+ #else /* !JS_HAS_OBJ_PROTO_PROP */
223
+
224
+ #define object_props NULL
225
+
226
+ #endif /* !JS_HAS_OBJ_PROTO_PROP */
227
+
228
+ JSBool
229
+ js_SetProtoOrParent(JSContext *cx, JSObject *obj, uint32 slot, JSObject *pobj)
230
+ {
231
+ JSRuntime *rt;
232
+ JSObject *obj2, *oldproto;
233
+ JSScope *scope, *newscope;
234
+
235
+ /*
236
+ * Serialize all proto and parent setting in order to detect cycles.
237
+ * We nest locks in this function, and only here, in the following orders:
238
+ *
239
+ * (1) rt->setSlotLock < pobj's scope lock;
240
+ * rt->setSlotLock < pobj's proto-or-parent's scope lock;
241
+ * rt->setSlotLock < pobj's grand-proto-or-parent's scope lock;
242
+ * etc...
243
+ * (2) rt->setSlotLock < obj's scope lock < pobj's scope lock.
244
+ *
245
+ * We avoid AB-BA deadlock by restricting obj from being on pobj's parent
246
+ * or proto chain (pobj may already be on obj's parent or proto chain; it
247
+ * could be moving up or down). We finally order obj with respect to pobj
248
+ * at the bottom of this routine (just before releasing rt->setSlotLock),
249
+ * by making pobj be obj's prototype or parent.
250
+ *
251
+ * After we have set the slot and released rt->setSlotLock, another call
252
+ * to js_SetProtoOrParent could nest locks according to the first order
253
+ * list above, but it cannot deadlock with any other thread. For there
254
+ * to be a deadlock, other parts of the engine would have to nest scope
255
+ * locks in the opposite order. XXXbe ensure they don't!
256
+ */
257
+ rt = cx->runtime;
258
+ #ifdef JS_THREADSAFE
259
+
260
+ JS_ACQUIRE_LOCK(rt->setSlotLock);
261
+ while (rt->setSlotBusy) {
262
+ jsrefcount saveDepth;
263
+
264
+ /* Take pains to avoid nesting rt->gcLock inside rt->setSlotLock! */
265
+ JS_RELEASE_LOCK(rt->setSlotLock);
266
+ saveDepth = JS_SuspendRequest(cx);
267
+ JS_ACQUIRE_LOCK(rt->setSlotLock);
268
+ if (rt->setSlotBusy)
269
+ JS_WAIT_CONDVAR(rt->setSlotDone, JS_NO_TIMEOUT);
270
+ JS_RELEASE_LOCK(rt->setSlotLock);
271
+ JS_ResumeRequest(cx, saveDepth);
272
+ JS_ACQUIRE_LOCK(rt->setSlotLock);
273
+ }
274
+ rt->setSlotBusy = JS_TRUE;
275
+ JS_RELEASE_LOCK(rt->setSlotLock);
276
+
277
+ #define SET_SLOT_DONE(rt) \
278
+ JS_BEGIN_MACRO \
279
+ JS_ACQUIRE_LOCK((rt)->setSlotLock); \
280
+ (rt)->setSlotBusy = JS_FALSE; \
281
+ JS_NOTIFY_ALL_CONDVAR((rt)->setSlotDone); \
282
+ JS_RELEASE_LOCK((rt)->setSlotLock); \
283
+ JS_END_MACRO
284
+
285
+ #else
286
+
287
+ #define SET_SLOT_DONE(rt) /* nothing */
288
+
289
+ #endif
290
+
291
+ obj2 = pobj;
292
+ while (obj2) {
293
+ if (obj2 == obj) {
294
+ SET_SLOT_DONE(rt);
295
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
296
+ JSMSG_CYCLIC_VALUE,
297
+ #if JS_HAS_OBJ_PROTO_PROP
298
+ object_props[slot].name
299
+ #else
300
+ (slot == JSSLOT_PROTO) ? js_proto_str
301
+ : js_parent_str
302
+ #endif
303
+ );
304
+ return JS_FALSE;
305
+ }
306
+ obj2 = JSVAL_TO_OBJECT(OBJ_GET_SLOT(cx, obj2, slot));
307
+ }
308
+
309
+ if (slot == JSSLOT_PROTO && OBJ_IS_NATIVE(obj)) {
310
+ /* Check to see whether obj shares its prototype's scope. */
311
+ JS_LOCK_OBJ(cx, obj);
312
+ scope = OBJ_SCOPE(obj);
313
+ oldproto = JSVAL_TO_OBJECT(LOCKED_OBJ_GET_SLOT(obj, JSSLOT_PROTO));
314
+ if (oldproto && OBJ_SCOPE(oldproto) == scope) {
315
+ /* Either obj needs a new empty scope, or it should share pobj's. */
316
+ if (!pobj ||
317
+ !OBJ_IS_NATIVE(pobj) ||
318
+ OBJ_GET_CLASS(cx, pobj) != LOCKED_OBJ_GET_CLASS(oldproto)) {
319
+ /*
320
+ * With no proto and no scope of its own, obj is truly empty.
321
+ *
322
+ * If pobj is not native, obj needs its own empty scope -- it
323
+ * should not continue to share oldproto's scope once oldproto
324
+ * is not on obj's prototype chain. That would put properties
325
+ * from oldproto's scope ahead of properties defined by pobj,
326
+ * in lookup order.
327
+ *
328
+ * If pobj's class differs from oldproto's, we may need a new
329
+ * scope to handle differences in private and reserved slots,
330
+ * so we suboptimally but safely make one.
331
+ */
332
+ scope = js_GetMutableScope(cx, obj);
333
+ if (!scope) {
334
+ JS_UNLOCK_OBJ(cx, obj);
335
+ SET_SLOT_DONE(rt);
336
+ return JS_FALSE;
337
+ }
338
+ } else if (OBJ_SCOPE(pobj) != scope) {
339
+ #ifdef JS_THREADSAFE
340
+ /*
341
+ * We are about to nest scope locks. Help jslock.c:ShareScope
342
+ * keep scope->u.count balanced for the JS_UNLOCK_SCOPE, while
343
+ * avoiding deadlock, by recording scope in rt->setSlotScope.
344
+ */
345
+ if (scope->ownercx) {
346
+ JS_ASSERT(scope->ownercx == cx);
347
+ rt->setSlotScope = scope;
348
+ }
349
+ #endif
350
+
351
+ /* We can't deadlock because we checked for cycles above (2). */
352
+ JS_LOCK_OBJ(cx, pobj);
353
+ newscope = (JSScope *) js_HoldObjectMap(cx, pobj->map);
354
+ obj->map = &newscope->map;
355
+ js_DropObjectMap(cx, &scope->map, obj);
356
+ JS_TRANSFER_SCOPE_LOCK(cx, scope, newscope);
357
+ scope = newscope;
358
+ #ifdef JS_THREADSAFE
359
+ rt->setSlotScope = NULL;
360
+ #endif
361
+ }
362
+ }
363
+ LOCKED_OBJ_SET_SLOT(obj, JSSLOT_PROTO, OBJECT_TO_JSVAL(pobj));
364
+ JS_UNLOCK_SCOPE(cx, scope);
365
+ } else {
366
+ OBJ_SET_SLOT(cx, obj, slot, OBJECT_TO_JSVAL(pobj));
367
+ }
368
+
369
+ SET_SLOT_DONE(rt);
370
+ return JS_TRUE;
371
+
372
+ #undef SET_SLOT_DONE
373
+ }
374
+
375
+ JS_STATIC_DLL_CALLBACK(JSHashNumber)
376
+ js_hash_object(const void *key)
377
+ {
378
+ return (JSHashNumber)key >> JSVAL_TAGBITS;
379
+ }
380
+
381
+ static JSHashEntry *
382
+ MarkSharpObjects(JSContext *cx, JSObject *obj, JSIdArray **idap)
383
+ {
384
+ JSSharpObjectMap *map;
385
+ JSHashTable *table;
386
+ JSHashNumber hash;
387
+ JSHashEntry **hep, *he;
388
+ jsatomid sharpid;
389
+ JSIdArray *ida;
390
+ JSBool ok;
391
+ jsint i, length;
392
+ jsid id;
393
+ #if JS_HAS_GETTER_SETTER
394
+ JSObject *obj2;
395
+ JSProperty *prop;
396
+ uintN attrs;
397
+ #endif
398
+ jsval val;
399
+
400
+ map = &cx->sharpObjectMap;
401
+ table = map->table;
402
+ hash = js_hash_object(obj);
403
+ hep = JS_HashTableRawLookup(table, hash, obj);
404
+ he = *hep;
405
+ if (!he) {
406
+ sharpid = 0;
407
+ he = JS_HashTableRawAdd(table, hep, hash, obj, (void *)sharpid);
408
+ if (!he) {
409
+ JS_ReportOutOfMemory(cx);
410
+ return NULL;
411
+ }
412
+ ida = JS_Enumerate(cx, obj);
413
+ if (!ida)
414
+ return NULL;
415
+ ok = JS_TRUE;
416
+ for (i = 0, length = ida->length; i < length; i++) {
417
+ id = ida->vector[i];
418
+ #if JS_HAS_GETTER_SETTER
419
+ ok = OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop);
420
+ if (!ok)
421
+ break;
422
+ if (prop) {
423
+ ok = OBJ_GET_ATTRIBUTES(cx, obj2, id, prop, &attrs);
424
+ if (ok) {
425
+ if (OBJ_IS_NATIVE(obj2) &&
426
+ (attrs & (JSPROP_GETTER | JSPROP_SETTER))) {
427
+ val = JSVAL_NULL;
428
+ if (attrs & JSPROP_GETTER)
429
+ val = (jsval) ((JSScopeProperty*)prop)->getter;
430
+ if (attrs & JSPROP_SETTER) {
431
+ if (val != JSVAL_NULL) {
432
+ /* Mark the getter, then set val to setter. */
433
+ ok = (MarkSharpObjects(cx, JSVAL_TO_OBJECT(val),
434
+ NULL)
435
+ != NULL);
436
+ }
437
+ val = (jsval) ((JSScopeProperty*)prop)->setter;
438
+ }
439
+ } else {
440
+ ok = OBJ_GET_PROPERTY(cx, obj, id, &val);
441
+ }
442
+ }
443
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
444
+ }
445
+ #else
446
+ ok = OBJ_GET_PROPERTY(cx, obj, id, &val);
447
+ #endif
448
+ if (!ok)
449
+ break;
450
+ if (!JSVAL_IS_PRIMITIVE(val) &&
451
+ !MarkSharpObjects(cx, JSVAL_TO_OBJECT(val), NULL)) {
452
+ ok = JS_FALSE;
453
+ break;
454
+ }
455
+ }
456
+ if (!ok || !idap)
457
+ JS_DestroyIdArray(cx, ida);
458
+ if (!ok)
459
+ return NULL;
460
+ } else {
461
+ sharpid = (jsatomid) he->value;
462
+ if (sharpid == 0) {
463
+ sharpid = ++map->sharpgen << SHARP_ID_SHIFT;
464
+ he->value = (void *) sharpid;
465
+ }
466
+ ida = NULL;
467
+ }
468
+ if (idap)
469
+ *idap = ida;
470
+ return he;
471
+ }
472
+
473
+ JSHashEntry *
474
+ js_EnterSharpObject(JSContext *cx, JSObject *obj, JSIdArray **idap,
475
+ jschar **sp)
476
+ {
477
+ JSSharpObjectMap *map;
478
+ JSHashTable *table;
479
+ JSIdArray *ida;
480
+ JSHashNumber hash;
481
+ JSHashEntry *he, **hep;
482
+ jsatomid sharpid;
483
+ char buf[20];
484
+ size_t len;
485
+
486
+ /* Set to null in case we return an early error. */
487
+ *sp = NULL;
488
+ map = &cx->sharpObjectMap;
489
+ table = map->table;
490
+ if (!table) {
491
+ table = JS_NewHashTable(8, js_hash_object, JS_CompareValues,
492
+ JS_CompareValues, NULL, NULL);
493
+ if (!table) {
494
+ JS_ReportOutOfMemory(cx);
495
+ return NULL;
496
+ }
497
+ map->table = table;
498
+ }
499
+
500
+ ida = NULL;
501
+ if (map->depth == 0) {
502
+ he = MarkSharpObjects(cx, obj, &ida);
503
+ if (!he)
504
+ goto bad;
505
+ JS_ASSERT((((jsatomid) he->value) & SHARP_BIT) == 0);
506
+ if (!idap) {
507
+ JS_DestroyIdArray(cx, ida);
508
+ ida = NULL;
509
+ }
510
+ } else {
511
+ hash = js_hash_object(obj);
512
+ hep = JS_HashTableRawLookup(table, hash, obj);
513
+ he = *hep;
514
+
515
+ /*
516
+ * It's possible that the value of a property has changed from the
517
+ * first time the object's properties are traversed (when the property
518
+ * ids are entered into the hash table) to the second (when they are
519
+ * converted to strings), i.e., the OBJ_GET_PROPERTY() call is not
520
+ * idempotent.
521
+ */
522
+ if (!he) {
523
+ he = JS_HashTableRawAdd(table, hep, hash, obj, NULL);
524
+ if (!he) {
525
+ JS_ReportOutOfMemory(cx);
526
+ goto bad;
527
+ }
528
+ *sp = NULL;
529
+ sharpid = 0;
530
+ goto out;
531
+ }
532
+ }
533
+
534
+ sharpid = (jsatomid) he->value;
535
+ if (sharpid == 0) {
536
+ *sp = NULL;
537
+ } else {
538
+ len = JS_snprintf(buf, sizeof buf, "#%u%c",
539
+ sharpid >> SHARP_ID_SHIFT,
540
+ (sharpid & SHARP_BIT) ? '#' : '=');
541
+ *sp = js_InflateString(cx, buf, len);
542
+ if (!*sp) {
543
+ if (ida)
544
+ JS_DestroyIdArray(cx, ida);
545
+ goto bad;
546
+ }
547
+ }
548
+
549
+ out:
550
+ JS_ASSERT(he);
551
+ if ((sharpid & SHARP_BIT) == 0) {
552
+ if (idap && !ida) {
553
+ ida = JS_Enumerate(cx, obj);
554
+ if (!ida) {
555
+ if (*sp) {
556
+ JS_free(cx, *sp);
557
+ *sp = NULL;
558
+ }
559
+ goto bad;
560
+ }
561
+ }
562
+ map->depth++;
563
+ }
564
+
565
+ if (idap)
566
+ *idap = ida;
567
+ return he;
568
+
569
+ bad:
570
+ /* Clean up the sharpObjectMap table on outermost error. */
571
+ if (map->depth == 0) {
572
+ map->sharpgen = 0;
573
+ JS_HashTableDestroy(map->table);
574
+ map->table = NULL;
575
+ }
576
+ return NULL;
577
+ }
578
+
579
+ void
580
+ js_LeaveSharpObject(JSContext *cx, JSIdArray **idap)
581
+ {
582
+ JSSharpObjectMap *map;
583
+ JSIdArray *ida;
584
+
585
+ map = &cx->sharpObjectMap;
586
+ JS_ASSERT(map->depth > 0);
587
+ if (--map->depth == 0) {
588
+ map->sharpgen = 0;
589
+ JS_HashTableDestroy(map->table);
590
+ map->table = NULL;
591
+ }
592
+ if (idap) {
593
+ ida = *idap;
594
+ if (ida) {
595
+ JS_DestroyIdArray(cx, ida);
596
+ *idap = NULL;
597
+ }
598
+ }
599
+ }
600
+
601
+ #define OBJ_TOSTRING_EXTRA 3 /* for 3 local GC roots */
602
+
603
+ #if JS_HAS_INITIALIZERS || JS_HAS_TOSOURCE
604
+ JSBool
605
+ js_obj_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
606
+ jsval *rval)
607
+ {
608
+ JSBool ok, outermost;
609
+ JSHashEntry *he;
610
+ JSIdArray *ida;
611
+ jschar *chars, *ochars, *vsharp;
612
+ const jschar *idstrchars, *vchars;
613
+ size_t nchars, idstrlength, gsoplength, vlength, vsharplength;
614
+ char *comma;
615
+ jsint i, j, length, valcnt;
616
+ jsid id;
617
+ #if JS_HAS_GETTER_SETTER
618
+ JSObject *obj2;
619
+ JSProperty *prop;
620
+ uintN attrs;
621
+ #endif
622
+ jsval val[2];
623
+ JSString *gsop[2];
624
+ JSAtom *atom;
625
+ JSString *idstr, *valstr, *str;
626
+ int stackDummy;
627
+
628
+ if (!JS_CHECK_STACK_SIZE(cx, stackDummy)) {
629
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_OVER_RECURSED);
630
+ return JS_FALSE;
631
+ }
632
+
633
+ /*
634
+ * obj_toString for 1.2 calls toSource, and doesn't want the extra parens
635
+ * on the outside.
636
+ */
637
+ outermost = (cx->version != JSVERSION_1_2 && cx->sharpObjectMap.depth == 0);
638
+ he = js_EnterSharpObject(cx, obj, &ida, &chars);
639
+ if (!he)
640
+ return JS_FALSE;
641
+ if (IS_SHARP(he)) {
642
+ /*
643
+ * We didn't enter -- obj is already "sharp", meaning we've visited it
644
+ * already in our depth first search, and therefore chars contains a
645
+ * string of the form "#n#".
646
+ */
647
+ JS_ASSERT(!ida);
648
+ #if JS_HAS_SHARP_VARS
649
+ nchars = js_strlen(chars);
650
+ #else
651
+ chars[0] = '{';
652
+ chars[1] = '}';
653
+ chars[2] = 0;
654
+ nchars = 2;
655
+ #endif
656
+ goto make_string;
657
+ }
658
+ JS_ASSERT(ida);
659
+ ok = JS_TRUE;
660
+
661
+ if (!chars) {
662
+ /* If outermost, allocate 4 + 1 for "({})" and the terminator. */
663
+ chars = (jschar *) malloc(((outermost ? 4 : 2) + 1) * sizeof(jschar));
664
+ nchars = 0;
665
+ if (!chars)
666
+ goto error;
667
+ if (outermost)
668
+ chars[nchars++] = '(';
669
+ } else {
670
+ /* js_EnterSharpObject returned a string of the form "#n=" in chars. */
671
+ MAKE_SHARP(he);
672
+ nchars = js_strlen(chars);
673
+ chars = (jschar *)
674
+ realloc((ochars = chars), (nchars + 2 + 1) * sizeof(jschar));
675
+ if (!chars) {
676
+ free(ochars);
677
+ goto error;
678
+ }
679
+ if (outermost) {
680
+ /*
681
+ * No need for parentheses around the whole shebang, because #n=
682
+ * unambiguously begins an object initializer, and never a block
683
+ * statement.
684
+ */
685
+ outermost = JS_FALSE;
686
+ }
687
+ }
688
+
689
+ #ifdef DUMP_CALL_TABLE
690
+ if (cx->options & JSOPTION_LOGCALL_TOSOURCE) {
691
+ const char *classname = OBJ_GET_CLASS(cx, obj)->name;
692
+ size_t classnchars = strlen(classname);
693
+ static const char classpropid[] = "C";
694
+ const char *cp;
695
+ size_t onchars = nchars;
696
+
697
+ /* 2 for ': ', 2 quotes around classname, 2 for ', ' after. */
698
+ classnchars += sizeof classpropid - 1 + 2 + 2;
699
+ if (ida->length)
700
+ classnchars += 2;
701
+
702
+ /* 2 for the braces, 1 for the terminator */
703
+ chars = (jschar *)
704
+ realloc((ochars = chars),
705
+ (nchars + classnchars + 2 + 1) * sizeof(jschar));
706
+ if (!chars) {
707
+ free(ochars);
708
+ goto error;
709
+ }
710
+
711
+ chars[nchars++] = '{'; /* 1 from the 2 braces */
712
+ for (cp = classpropid; *cp; cp++)
713
+ chars[nchars++] = (jschar) *cp;
714
+ chars[nchars++] = ':';
715
+ chars[nchars++] = ' '; /* 2 for ': ' */
716
+ chars[nchars++] = '"';
717
+ for (cp = classname; *cp; cp++)
718
+ chars[nchars++] = (jschar) *cp;
719
+ chars[nchars++] = '"'; /* 2 quotes */
720
+ if (ida->length) {
721
+ chars[nchars++] = ',';
722
+ chars[nchars++] = ' '; /* 2 for ', ' */
723
+ }
724
+
725
+ JS_ASSERT(nchars - onchars == 1 + classnchars);
726
+ } else
727
+ #endif
728
+ chars[nchars++] = '{';
729
+
730
+ comma = NULL;
731
+
732
+ for (i = 0, length = ida->length; i < length; i++) {
733
+ /* Get strings for id and value and GC-root them via argv. */
734
+ id = ida->vector[i];
735
+
736
+ #if JS_HAS_GETTER_SETTER
737
+
738
+ ok = OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop);
739
+ if (!ok)
740
+ goto error;
741
+ valcnt = 0;
742
+ if (prop) {
743
+ ok = OBJ_GET_ATTRIBUTES(cx, obj2, id, prop, &attrs);
744
+ if (!ok) {
745
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
746
+ goto error;
747
+ }
748
+ if (OBJ_IS_NATIVE(obj2) &&
749
+ (attrs & (JSPROP_GETTER | JSPROP_SETTER))) {
750
+ if (attrs & JSPROP_GETTER) {
751
+ val[valcnt] = (jsval) ((JSScopeProperty *)prop)->getter;
752
+ #ifdef OLD_GETTER_SETTER
753
+ gsop[valcnt] =
754
+ ATOM_TO_STRING(cx->runtime->atomState.getterAtom);
755
+ #else
756
+ gsop[valcnt] =
757
+ ATOM_TO_STRING(cx->runtime->atomState.getAtom);
758
+ #endif
759
+ valcnt++;
760
+ }
761
+ if (attrs & JSPROP_SETTER) {
762
+ val[valcnt] = (jsval) ((JSScopeProperty *)prop)->setter;
763
+ #ifdef OLD_GETTER_SETTER
764
+ gsop[valcnt] =
765
+ ATOM_TO_STRING(cx->runtime->atomState.setterAtom);
766
+ #else
767
+ gsop[valcnt] =
768
+ ATOM_TO_STRING(cx->runtime->atomState.setAtom);
769
+ #endif
770
+ valcnt++;
771
+ }
772
+ } else {
773
+ valcnt = 1;
774
+ gsop[0] = NULL;
775
+ ok = OBJ_GET_PROPERTY(cx, obj, id, &val[0]);
776
+ }
777
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
778
+ }
779
+
780
+ #else /* !JS_HAS_GETTER_SETTER */
781
+
782
+ valcnt = 1;
783
+ gsop[0] = NULL;
784
+ ok = OBJ_GET_PROPERTY(cx, obj, id, &val[0]);
785
+
786
+ #endif /* !JS_HAS_GETTER_SETTER */
787
+
788
+ if (!ok)
789
+ goto error;
790
+
791
+ /* Convert id to a jsval and then to a string. */
792
+ atom = JSVAL_IS_INT(id) ? NULL : (JSAtom *)id;
793
+ id = ID_TO_VALUE(id);
794
+ idstr = js_ValueToString(cx, id);
795
+ if (!idstr) {
796
+ ok = JS_FALSE;
797
+ goto error;
798
+ }
799
+ argv[0] = STRING_TO_JSVAL(idstr);
800
+
801
+ /*
802
+ * If id is a string that's a reserved identifier, or else id is not
803
+ * an identifier at all, then it needs to be quoted. Also, negative
804
+ * integer ids must be quoted.
805
+ */
806
+ if (atom
807
+ ? (ATOM_KEYWORD(atom) || !js_IsIdentifier(idstr))
808
+ : JSVAL_TO_INT(id) < 0) {
809
+ idstr = js_QuoteString(cx, idstr, (jschar)'\'');
810
+ if (!idstr) {
811
+ ok = JS_FALSE;
812
+ goto error;
813
+ }
814
+ argv[0] = STRING_TO_JSVAL(idstr);
815
+ }
816
+ idstrchars = JSSTRING_CHARS(idstr);
817
+ idstrlength = JSSTRING_LENGTH(idstr);
818
+
819
+ for (j = 0; j < valcnt; j++) {
820
+ /* Convert val[j] to its canonical source form. */
821
+ valstr = js_ValueToSource(cx, val[j]);
822
+ if (!valstr) {
823
+ ok = JS_FALSE;
824
+ goto error;
825
+ }
826
+ argv[1+j] = STRING_TO_JSVAL(valstr);
827
+ vchars = JSSTRING_CHARS(valstr);
828
+ vlength = JSSTRING_LENGTH(valstr);
829
+
830
+ #ifndef OLD_GETTER_SETTER
831
+ /* Remove 'function ' from beginning of valstr. */
832
+ if (gsop[j]) {
833
+ int n = strlen(js_function_str) + 1;
834
+ vchars += n;
835
+ vlength -= n;
836
+ }
837
+ #endif
838
+
839
+ /* If val[j] is a non-sharp object, consider sharpening it. */
840
+ vsharp = NULL;
841
+ vsharplength = 0;
842
+ #if JS_HAS_SHARP_VARS
843
+ if (!JSVAL_IS_PRIMITIVE(val[j]) && vchars[0] != '#') {
844
+ he = js_EnterSharpObject(cx, JSVAL_TO_OBJECT(val[j]), NULL,
845
+ &vsharp);
846
+ if (!he) {
847
+ ok = JS_FALSE;
848
+ goto error;
849
+ }
850
+ if (IS_SHARP(he)) {
851
+ vchars = vsharp;
852
+ vlength = js_strlen(vchars);
853
+ } else {
854
+ if (vsharp) {
855
+ vsharplength = js_strlen(vsharp);
856
+ MAKE_SHARP(he);
857
+ }
858
+ js_LeaveSharpObject(cx, NULL);
859
+ }
860
+ }
861
+ #endif
862
+
863
+ /* Allocate 1 + 1 at end for closing brace and terminating 0. */
864
+ chars = (jschar *)
865
+ realloc((ochars = chars),
866
+ (nchars + (comma ? 2 : 0) +
867
+ idstrlength + 1 +
868
+ (gsop[j] ? 1 + JSSTRING_LENGTH(gsop[j]) : 0) +
869
+ vsharplength + vlength +
870
+ (outermost ? 2 : 1) + 1) * sizeof(jschar));
871
+ if (!chars) {
872
+ /* Save code space on error: let JS_free ignore null vsharp. */
873
+ JS_free(cx, vsharp);
874
+ free(ochars);
875
+ goto error;
876
+ }
877
+
878
+ if (comma) {
879
+ chars[nchars++] = comma[0];
880
+ chars[nchars++] = comma[1];
881
+ }
882
+ comma = ", ";
883
+
884
+ #ifdef OLD_GETTER_SETTER
885
+ js_strncpy(&chars[nchars], idstrchars, idstrlength);
886
+ nchars += idstrlength;
887
+ if (gsop[j]) {
888
+ chars[nchars++] = ' ';
889
+ gsoplength = JSSTRING_LENGTH(gsop[j]);
890
+ js_strncpy(&chars[nchars], JSSTRING_CHARS(gsop[j]), gsoplength);
891
+ nchars += gsoplength;
892
+ }
893
+ chars[nchars++] = ':';
894
+ #else
895
+ if (gsop[j]) {
896
+ gsoplength = JSSTRING_LENGTH(gsop[j]);
897
+ js_strncpy(&chars[nchars], JSSTRING_CHARS(gsop[j]), gsoplength);
898
+ nchars += gsoplength;
899
+ chars[nchars++] = ' ';
900
+ }
901
+ js_strncpy(&chars[nchars], idstrchars, idstrlength);
902
+ nchars += idstrlength;
903
+ if (!gsop[j])
904
+ chars[nchars++] = ':';
905
+ #endif
906
+ if (vsharplength) {
907
+ js_strncpy(&chars[nchars], vsharp, vsharplength);
908
+ nchars += vsharplength;
909
+ }
910
+ js_strncpy(&chars[nchars], vchars, vlength);
911
+ nchars += vlength;
912
+
913
+ if (vsharp)
914
+ JS_free(cx, vsharp);
915
+ #ifdef DUMP_CALL_TABLE
916
+ if (outermost && nchars >= js_LogCallToSourceLimit)
917
+ break;
918
+ #endif
919
+ }
920
+ }
921
+
922
+ chars[nchars++] = '}';
923
+ if (outermost)
924
+ chars[nchars++] = ')';
925
+ chars[nchars] = 0;
926
+
927
+ error:
928
+ js_LeaveSharpObject(cx, &ida);
929
+
930
+ if (!ok) {
931
+ if (chars)
932
+ free(chars);
933
+ return ok;
934
+ }
935
+
936
+ if (!chars) {
937
+ JS_ReportOutOfMemory(cx);
938
+ return JS_FALSE;
939
+ }
940
+ make_string:
941
+ str = js_NewString(cx, chars, nchars, 0);
942
+ if (!str) {
943
+ free(chars);
944
+ return JS_FALSE;
945
+ }
946
+ *rval = STRING_TO_JSVAL(str);
947
+ return JS_TRUE;
948
+ }
949
+ #endif /* JS_HAS_INITIALIZERS || JS_HAS_TOSOURCE */
950
+
951
+ JSBool
952
+ js_obj_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
953
+ jsval *rval)
954
+ {
955
+ jschar *chars;
956
+ size_t nchars;
957
+ const char *clazz, *prefix;
958
+ JSString *str;
959
+
960
+ #if JS_HAS_INITIALIZERS
961
+ if (cx->version == JSVERSION_1_2)
962
+ return js_obj_toSource(cx, obj, argc, argv, rval);
963
+ #endif
964
+
965
+ clazz = OBJ_GET_CLASS(cx, obj)->name;
966
+ nchars = 9 + strlen(clazz); /* 9 for "[object ]" */
967
+ chars = (jschar *) JS_malloc(cx, (nchars + 1) * sizeof(jschar));
968
+ if (!chars)
969
+ return JS_FALSE;
970
+
971
+ prefix = "[object ";
972
+ nchars = 0;
973
+ while ((chars[nchars] = (jschar)*prefix) != 0)
974
+ nchars++, prefix++;
975
+ while ((chars[nchars] = (jschar)*clazz) != 0)
976
+ nchars++, clazz++;
977
+ chars[nchars++] = ']';
978
+ chars[nchars] = 0;
979
+
980
+ str = js_NewString(cx, chars, nchars, 0);
981
+ if (!str) {
982
+ JS_free(cx, chars);
983
+ return JS_FALSE;
984
+ }
985
+ *rval = STRING_TO_JSVAL(str);
986
+ return JS_TRUE;
987
+ }
988
+
989
+ static JSBool
990
+ obj_valueOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
991
+ {
992
+ *rval = OBJECT_TO_JSVAL(obj);
993
+ return JS_TRUE;
994
+ }
995
+
996
+ static JSBool
997
+ obj_eval(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
998
+ {
999
+ JSStackFrame *fp, *caller;
1000
+ JSBool indirectCall;
1001
+ JSObject *scopeobj;
1002
+ JSString *str;
1003
+ const char *file;
1004
+ uintN line;
1005
+ JSPrincipals *principals;
1006
+ JSScript *script;
1007
+ JSBool ok;
1008
+ #if JS_HAS_EVAL_THIS_SCOPE
1009
+ JSObject *callerScopeChain = NULL, *callerVarObj = NULL;
1010
+ JSBool setCallerScopeChain = JS_FALSE, setCallerVarObj = JS_FALSE;
1011
+ #endif
1012
+
1013
+ fp = cx->fp;
1014
+ caller = JS_GetScriptedCaller(cx, fp);
1015
+ indirectCall = (caller && caller->pc && *caller->pc != JSOP_EVAL);
1016
+
1017
+ if (JSVERSION_IS_ECMA(cx->version) &&
1018
+ indirectCall &&
1019
+ !JS_ReportErrorFlagsAndNumber(cx,
1020
+ JSREPORT_WARNING | JSREPORT_STRICT,
1021
+ js_GetErrorMessage, NULL,
1022
+ JSMSG_BAD_INDIRECT_CALL,
1023
+ js_eval_str)) {
1024
+ return JS_FALSE;
1025
+ }
1026
+
1027
+ if (!JSVAL_IS_STRING(argv[0])) {
1028
+ *rval = argv[0];
1029
+ return JS_TRUE;
1030
+ }
1031
+
1032
+ #if JS_HAS_SCRIPT_OBJECT
1033
+ /*
1034
+ * Script.prototype.compile/exec and Object.prototype.eval all take an
1035
+ * optional trailing argument that overrides the scope object.
1036
+ */
1037
+ scopeobj = NULL;
1038
+ if (argc >= 2) {
1039
+ if (!js_ValueToObject(cx, argv[1], &scopeobj))
1040
+ return JS_FALSE;
1041
+ argv[1] = OBJECT_TO_JSVAL(scopeobj);
1042
+ }
1043
+ if (!scopeobj)
1044
+ #endif
1045
+ {
1046
+ #if JS_HAS_EVAL_THIS_SCOPE
1047
+ /* If obj.eval(str), emulate 'with (obj) eval(str)' in the caller. */
1048
+ if (indirectCall) {
1049
+ callerScopeChain = caller->scopeChain;
1050
+ if (obj != callerScopeChain) {
1051
+ scopeobj = js_NewObject(cx, &js_WithClass, obj,
1052
+ callerScopeChain);
1053
+ if (!scopeobj)
1054
+ return JS_FALSE;
1055
+
1056
+ /* Set fp->scopeChain too, for the compiler. */
1057
+ caller->scopeChain = fp->scopeChain = scopeobj;
1058
+ setCallerScopeChain = JS_TRUE;
1059
+ }
1060
+
1061
+ callerVarObj = caller->varobj;
1062
+ if (obj != callerVarObj) {
1063
+ /* Set fp->varobj too, for the compiler. */
1064
+ caller->varobj = fp->varobj = obj;
1065
+ setCallerVarObj = JS_TRUE;
1066
+ }
1067
+ }
1068
+ /* From here on, control must exit through label out with ok set. */
1069
+ #endif
1070
+
1071
+ #if JS_BUG_EVAL_THIS_SCOPE
1072
+ /* An old version used the object in which eval was found for scope. */
1073
+ scopeobj = obj;
1074
+ #else
1075
+ /* Compile using caller's current scope object. */
1076
+ if (caller)
1077
+ scopeobj = caller->scopeChain;
1078
+ #endif
1079
+ }
1080
+
1081
+ str = JSVAL_TO_STRING(argv[0]);
1082
+ if (caller) {
1083
+ file = caller->script->filename;
1084
+ line = js_PCToLineNumber(cx, caller->script, caller->pc);
1085
+ principals = JS_EvalFramePrincipals(cx, fp, caller);
1086
+ } else {
1087
+ file = NULL;
1088
+ line = 0;
1089
+ principals = NULL;
1090
+ }
1091
+
1092
+ fp->flags |= JSFRAME_EVAL;
1093
+ script = JS_CompileUCScriptForPrincipals(cx, scopeobj, principals,
1094
+ JSSTRING_CHARS(str),
1095
+ JSSTRING_LENGTH(str),
1096
+ file, line);
1097
+ if (!script) {
1098
+ ok = JS_FALSE;
1099
+ goto out;
1100
+ }
1101
+
1102
+ #if !JS_BUG_EVAL_THIS_SCOPE
1103
+ #if JS_HAS_SCRIPT_OBJECT
1104
+ if (argc < 2)
1105
+ #endif
1106
+ {
1107
+ /* Execute using caller's new scope object (might be a Call object). */
1108
+ if (caller)
1109
+ scopeobj = caller->scopeChain;
1110
+ }
1111
+ #endif
1112
+ ok = js_Execute(cx, scopeobj, script, caller, JSFRAME_EVAL, rval);
1113
+ JS_DestroyScript(cx, script);
1114
+
1115
+ out:
1116
+ #if JS_HAS_EVAL_THIS_SCOPE
1117
+ /* Restore OBJ_GET_PARENT(scopeobj) not callerScopeChain in case of Call. */
1118
+ if (setCallerScopeChain)
1119
+ caller->scopeChain = callerScopeChain;
1120
+ if (setCallerVarObj)
1121
+ caller->varobj = callerVarObj;
1122
+ #endif
1123
+ return ok;
1124
+ }
1125
+
1126
+ #if JS_HAS_OBJ_WATCHPOINT
1127
+
1128
+ static JSBool
1129
+ obj_watch_handler(JSContext *cx, JSObject *obj, jsval id, jsval old, jsval *nvp,
1130
+ void *closure)
1131
+ {
1132
+ JSResolvingKey key;
1133
+ JSResolvingEntry *entry;
1134
+ uint32 generation;
1135
+ JSObject *funobj;
1136
+ jsval argv[3];
1137
+ JSBool ok;
1138
+
1139
+ /* Avoid recursion on (obj, id) already being watched on cx. */
1140
+ key.obj = obj;
1141
+ key.id = id;
1142
+ if (!js_StartResolving(cx, &key, JSRESFLAG_WATCH, &entry))
1143
+ return JS_FALSE;
1144
+ if (!entry)
1145
+ return JS_TRUE;
1146
+ generation = cx->resolvingTable->generation;
1147
+
1148
+ funobj = (JSObject *) closure;
1149
+ argv[0] = id;
1150
+ argv[1] = old;
1151
+ argv[2] = *nvp;
1152
+ ok = js_InternalCall(cx, obj, OBJECT_TO_JSVAL(funobj), 3, argv, nvp);
1153
+ js_StopResolving(cx, &key, JSRESFLAG_WATCH, entry, generation);
1154
+ return ok;
1155
+ }
1156
+
1157
+ static JSBool
1158
+ obj_watch(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1159
+ {
1160
+ JSObject *funobj;
1161
+ JSFunction *fun;
1162
+ jsval userid, value;
1163
+ jsid propid;
1164
+ uintN attrs;
1165
+
1166
+ if (JSVAL_IS_FUNCTION(cx, argv[1])) {
1167
+ funobj = JSVAL_TO_OBJECT(argv[1]);
1168
+ } else {
1169
+ fun = js_ValueToFunction(cx, &argv[1], 0);
1170
+ if (!fun)
1171
+ return JS_FALSE;
1172
+ funobj = fun->object;
1173
+ }
1174
+ argv[1] = OBJECT_TO_JSVAL(funobj);
1175
+
1176
+ /* Compute the unique int/atom symbol id needed by js_LookupProperty. */
1177
+ userid = argv[0];
1178
+ if (!JS_ValueToId(cx, userid, &propid))
1179
+ return JS_FALSE;
1180
+
1181
+ if (!OBJ_CHECK_ACCESS(cx, obj, propid, JSACC_WATCH, &value, &attrs))
1182
+ return JS_FALSE;
1183
+ if (attrs & JSPROP_READONLY)
1184
+ return JS_TRUE;
1185
+ return JS_SetWatchPoint(cx, obj, userid, obj_watch_handler, funobj);
1186
+ }
1187
+
1188
+ static JSBool
1189
+ obj_unwatch(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1190
+ {
1191
+ return JS_ClearWatchPoint(cx, obj, argv[0], NULL, NULL);
1192
+ }
1193
+
1194
+ #endif /* JS_HAS_OBJ_WATCHPOINT */
1195
+
1196
+ #if JS_HAS_NEW_OBJ_METHODS
1197
+ /*
1198
+ * Prototype and property query methods, to complement the 'in' and
1199
+ * 'instanceof' operators.
1200
+ */
1201
+
1202
+ /* Proposed ECMA 15.2.4.5. */
1203
+ static JSBool
1204
+ obj_hasOwnProperty(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
1205
+ jsval *rval)
1206
+ {
1207
+ jsid id;
1208
+ JSObject *obj2;
1209
+ JSProperty *prop;
1210
+ JSScopeProperty *sprop;
1211
+
1212
+ if (!JS_ValueToId(cx, argv[0], &id))
1213
+ return JS_FALSE;
1214
+ if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))
1215
+ return JS_FALSE;
1216
+ if (!prop) {
1217
+ *rval = JSVAL_FALSE;
1218
+ } else if (obj2 == obj) {
1219
+ *rval = JSVAL_TRUE;
1220
+ } else if (OBJ_IS_NATIVE(obj2)) {
1221
+ sprop = (JSScopeProperty *)prop;
1222
+ *rval = BOOLEAN_TO_JSVAL(SPROP_IS_SHARED_PERMANENT(sprop));
1223
+ } else {
1224
+ *rval = JSVAL_FALSE;
1225
+ }
1226
+ if (prop)
1227
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
1228
+ return JS_TRUE;
1229
+ }
1230
+
1231
+ /* Proposed ECMA 15.2.4.6. */
1232
+ static JSBool
1233
+ obj_isPrototypeOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
1234
+ jsval *rval)
1235
+ {
1236
+ JSBool b;
1237
+
1238
+ if (!js_IsDelegate(cx, obj, *argv, &b))
1239
+ return JS_FALSE;
1240
+ *rval = BOOLEAN_TO_JSVAL(b);
1241
+ return JS_TRUE;
1242
+ }
1243
+
1244
+ /* Proposed ECMA 15.2.4.7. */
1245
+ static JSBool
1246
+ obj_propertyIsEnumerable(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
1247
+ jsval *rval)
1248
+ {
1249
+ jsid id;
1250
+ uintN attrs;
1251
+ JSObject *obj2;
1252
+ JSProperty *prop;
1253
+ JSBool ok;
1254
+
1255
+ if (!JS_ValueToId(cx, argv[0], &id))
1256
+ return JS_FALSE;
1257
+
1258
+ if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))
1259
+ return JS_FALSE;
1260
+
1261
+ if (!prop) {
1262
+ *rval = JSVAL_FALSE;
1263
+ return JS_TRUE;
1264
+ }
1265
+
1266
+ /*
1267
+ * XXX ECMA spec error compatible: return false unless hasOwnProperty.
1268
+ * The ECMA spec really should be fixed so propertyIsEnumerable and the
1269
+ * for..in loop agree on whether prototype properties are enumerable,
1270
+ * obviously by fixing this method (not by breaking the for..in loop!).
1271
+ *
1272
+ * We check here for shared permanent prototype properties, which should
1273
+ * be treated as if they are local to obj. They are an implementation
1274
+ * technique used to satisfy ECMA requirements; users should not be able
1275
+ * to distinguish a shared permanent proto-property from a local one.
1276
+ */
1277
+ if (obj2 != obj &&
1278
+ !(OBJ_IS_NATIVE(obj2) &&
1279
+ SPROP_IS_SHARED_PERMANENT((JSScopeProperty *)prop))) {
1280
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
1281
+ *rval = JSVAL_FALSE;
1282
+ return JS_TRUE;
1283
+ }
1284
+
1285
+ ok = OBJ_GET_ATTRIBUTES(cx, obj2, id, prop, &attrs);
1286
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
1287
+ if (ok)
1288
+ *rval = BOOLEAN_TO_JSVAL((attrs & JSPROP_ENUMERATE) != 0);
1289
+ return ok;
1290
+ }
1291
+ #endif /* JS_HAS_NEW_OBJ_METHODS */
1292
+
1293
+ #if JS_HAS_GETTER_SETTER
1294
+ static JSBool
1295
+ obj_defineGetter(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
1296
+ jsval *rval)
1297
+ {
1298
+ jsval fval, junk;
1299
+ jsid id;
1300
+ uintN attrs;
1301
+
1302
+ fval = argv[1];
1303
+ if (JS_TypeOfValue(cx, fval) != JSTYPE_FUNCTION) {
1304
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
1305
+ JSMSG_BAD_GETTER_OR_SETTER,
1306
+ js_getter_str);
1307
+ return JS_FALSE;
1308
+ }
1309
+
1310
+ if (!JS_ValueToId(cx, argv[0], &id))
1311
+ return JS_FALSE;
1312
+ if (!js_CheckRedeclaration(cx, obj, id, JSPROP_GETTER, NULL, NULL))
1313
+ return JS_FALSE;
1314
+ /*
1315
+ * Getters and setters are just like watchpoints from an access
1316
+ * control point of view.
1317
+ */
1318
+ if (!OBJ_CHECK_ACCESS(cx, obj, id, JSACC_WATCH, &junk, &attrs))
1319
+ return JS_FALSE;
1320
+ return OBJ_DEFINE_PROPERTY(cx, obj, id, JSVAL_VOID,
1321
+ (JSPropertyOp) JSVAL_TO_OBJECT(fval), NULL,
1322
+ JSPROP_ENUMERATE | JSPROP_GETTER | JSPROP_SHARED,
1323
+ NULL);
1324
+ }
1325
+
1326
+ static JSBool
1327
+ obj_defineSetter(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
1328
+ jsval *rval)
1329
+ {
1330
+ jsval fval, junk;
1331
+ jsid id;
1332
+ uintN attrs;
1333
+
1334
+ fval = argv[1];
1335
+ if (JS_TypeOfValue(cx, fval) != JSTYPE_FUNCTION) {
1336
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
1337
+ JSMSG_BAD_GETTER_OR_SETTER,
1338
+ js_setter_str);
1339
+ return JS_FALSE;
1340
+ }
1341
+
1342
+ if (!JS_ValueToId(cx, argv[0], &id))
1343
+ return JS_FALSE;
1344
+ if (!js_CheckRedeclaration(cx, obj, id, JSPROP_SETTER, NULL, NULL))
1345
+ return JS_FALSE;
1346
+ /*
1347
+ * Getters and setters are just like watchpoints from an access
1348
+ * control point of view.
1349
+ */
1350
+ if (!OBJ_CHECK_ACCESS(cx, obj, id, JSACC_WATCH, &junk, &attrs))
1351
+ return JS_FALSE;
1352
+ return OBJ_DEFINE_PROPERTY(cx, obj, id, JSVAL_VOID,
1353
+ NULL, (JSPropertyOp) JSVAL_TO_OBJECT(fval),
1354
+ JSPROP_ENUMERATE | JSPROP_SETTER | JSPROP_SHARED,
1355
+ NULL);
1356
+ }
1357
+
1358
+ static JSBool
1359
+ obj_lookupGetter(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
1360
+ jsval *rval)
1361
+ {
1362
+ jsid id;
1363
+ JSObject *pobj;
1364
+ JSProperty *prop;
1365
+ JSScopeProperty *sprop;
1366
+
1367
+ if (!JS_ValueToId(cx, argv[0], &id))
1368
+ return JS_FALSE;
1369
+ if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &pobj, &prop))
1370
+ return JS_FALSE;
1371
+ if (prop) {
1372
+ if (OBJ_IS_NATIVE(pobj)) {
1373
+ sprop = (JSScopeProperty *) prop;
1374
+ if (sprop->attrs & JSPROP_GETTER)
1375
+ *rval = OBJECT_TO_JSVAL(sprop->getter);
1376
+ }
1377
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
1378
+ }
1379
+ return JS_TRUE;
1380
+ }
1381
+
1382
+ static JSBool
1383
+ obj_lookupSetter(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
1384
+ jsval *rval)
1385
+ {
1386
+ jsid id;
1387
+ JSObject *pobj;
1388
+ JSProperty *prop;
1389
+ JSScopeProperty *sprop;
1390
+
1391
+ if (!JS_ValueToId(cx, argv[0], &id))
1392
+ return JS_FALSE;
1393
+ if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &pobj, &prop))
1394
+ return JS_FALSE;
1395
+ if (prop) {
1396
+ if (OBJ_IS_NATIVE(pobj)) {
1397
+ sprop = (JSScopeProperty *) prop;
1398
+ if (sprop->attrs & JSPROP_SETTER)
1399
+ *rval = OBJECT_TO_JSVAL(sprop->setter);
1400
+ }
1401
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
1402
+ }
1403
+ return JS_TRUE;
1404
+ }
1405
+ #endif /* JS_HAS_GETTER_SETTER */
1406
+
1407
+ #if JS_HAS_OBJ_WATCHPOINT
1408
+ const char js_watch_str[] = "watch";
1409
+ const char js_unwatch_str[] = "unwatch";
1410
+ #endif
1411
+ #if JS_HAS_NEW_OBJ_METHODS
1412
+ const char js_hasOwnProperty_str[] = "hasOwnProperty";
1413
+ const char js_isPrototypeOf_str[] = "isPrototypeOf";
1414
+ const char js_propertyIsEnumerable_str[] = "propertyIsEnumerable";
1415
+ #endif
1416
+ #if JS_HAS_GETTER_SETTER
1417
+ const char js_defineGetter_str[] = "__defineGetter__";
1418
+ const char js_defineSetter_str[] = "__defineSetter__";
1419
+ const char js_lookupGetter_str[] = "__lookupGetter__";
1420
+ const char js_lookupSetter_str[] = "__lookupSetter__";
1421
+ #endif
1422
+
1423
+ static JSFunctionSpec object_methods[] = {
1424
+ #if JS_HAS_TOSOURCE
1425
+ {js_toSource_str, js_obj_toSource, 0, 0, OBJ_TOSTRING_EXTRA},
1426
+ #endif
1427
+ {js_toString_str, js_obj_toString, 0, 0, OBJ_TOSTRING_EXTRA},
1428
+ {js_toLocaleString_str, js_obj_toString, 0, 0, OBJ_TOSTRING_EXTRA},
1429
+ {js_valueOf_str, obj_valueOf, 0,0,0},
1430
+ {js_eval_str, obj_eval, 1,0,0},
1431
+ #if JS_HAS_OBJ_WATCHPOINT
1432
+ {js_watch_str, obj_watch, 2,0,0},
1433
+ {js_unwatch_str, obj_unwatch, 1,0,0},
1434
+ #endif
1435
+ #if JS_HAS_NEW_OBJ_METHODS
1436
+ {js_hasOwnProperty_str, obj_hasOwnProperty, 1,0,0},
1437
+ {js_isPrototypeOf_str, obj_isPrototypeOf, 1,0,0},
1438
+ {js_propertyIsEnumerable_str, obj_propertyIsEnumerable, 1,0,0},
1439
+ #endif
1440
+ #if JS_HAS_GETTER_SETTER
1441
+ {js_defineGetter_str, obj_defineGetter, 2,0,0},
1442
+ {js_defineSetter_str, obj_defineSetter, 2,0,0},
1443
+ {js_lookupGetter_str, obj_lookupGetter, 1,0,0},
1444
+ {js_lookupSetter_str, obj_lookupSetter, 1,0,0},
1445
+ #endif
1446
+ {0,0,0,0,0}
1447
+ };
1448
+
1449
+ static JSBool
1450
+ Object(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1451
+ {
1452
+ if (argc == 0) {
1453
+ /* Trigger logic below to construct a blank object. */
1454
+ obj = NULL;
1455
+ } else {
1456
+ /* If argv[0] is null or undefined, obj comes back null. */
1457
+ if (!js_ValueToObject(cx, argv[0], &obj))
1458
+ return JS_FALSE;
1459
+ }
1460
+ if (!obj) {
1461
+ JS_ASSERT(!argc || JSVAL_IS_NULL(argv[0]) || JSVAL_IS_VOID(argv[0]));
1462
+ if (cx->fp->flags & JSFRAME_CONSTRUCTING)
1463
+ return JS_TRUE;
1464
+ obj = js_NewObject(cx, &js_ObjectClass, NULL, NULL);
1465
+ if (!obj)
1466
+ return JS_FALSE;
1467
+ }
1468
+ *rval = OBJECT_TO_JSVAL(obj);
1469
+ return JS_TRUE;
1470
+ }
1471
+
1472
+ /*
1473
+ * ObjectOps and Class for with-statement stack objects.
1474
+ */
1475
+ static JSBool
1476
+ with_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
1477
+ JSProperty **propp
1478
+ #if defined JS_THREADSAFE && defined DEBUG
1479
+ , const char *file, uintN line
1480
+ #endif
1481
+ )
1482
+ {
1483
+ JSObject *proto;
1484
+ JSScopeProperty *sprop;
1485
+ JSStackFrame *fp;
1486
+
1487
+ proto = OBJ_GET_PROTO(cx, obj);
1488
+ if (!proto)
1489
+ return js_LookupProperty(cx, obj, id, objp, propp);
1490
+ if (!OBJ_LOOKUP_PROPERTY(cx, proto, id, objp, propp))
1491
+ return JS_FALSE;
1492
+
1493
+ /*
1494
+ * Check whether id names an argument or local variable in an active
1495
+ * function. If so, pretend we didn't find it, so that the real arg or
1496
+ * var property can be found in the function's call object, later on in
1497
+ * the scope chain. But skip unshared arg and var properties -- those
1498
+ * result when a script explicitly sets a function "static" property of
1499
+ * the same name. See jsinterp.c:SetFunctionSlot.
1500
+ *
1501
+ * XXX blame pre-ECMA reflection of function args and vars as properties
1502
+ */
1503
+ if ((sprop = (JSScopeProperty *) *propp) &&
1504
+ (proto = *objp, OBJ_IS_NATIVE(proto)) &&
1505
+ (sprop->getter == js_GetArgument ||
1506
+ sprop->getter == js_GetLocalVariable) &&
1507
+ (sprop->attrs & JSPROP_SHARED)) {
1508
+ JS_ASSERT(OBJ_GET_CLASS(cx, proto) == &js_FunctionClass);
1509
+ for (fp = cx->fp; fp && (!fp->fun || !fp->fun->interpreted);
1510
+ fp = fp->down) {
1511
+ continue;
1512
+ }
1513
+ if (fp && fp->fun == (JSFunction *) JS_GetPrivate(cx, proto)) {
1514
+ OBJ_DROP_PROPERTY(cx, proto, *propp);
1515
+ *objp = NULL;
1516
+ *propp = NULL;
1517
+ }
1518
+ }
1519
+ return JS_TRUE;
1520
+ }
1521
+
1522
+ static JSBool
1523
+ with_GetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
1524
+ {
1525
+ JSObject *proto = OBJ_GET_PROTO(cx, obj);
1526
+ if (!proto)
1527
+ return js_GetProperty(cx, obj, id, vp);
1528
+ return OBJ_GET_PROPERTY(cx, proto, id, vp);
1529
+ }
1530
+
1531
+ static JSBool
1532
+ with_SetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
1533
+ {
1534
+ JSObject *proto = OBJ_GET_PROTO(cx, obj);
1535
+ if (!proto)
1536
+ return js_SetProperty(cx, obj, id, vp);
1537
+ return OBJ_SET_PROPERTY(cx, proto, id, vp);
1538
+ }
1539
+
1540
+ static JSBool
1541
+ with_GetAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop,
1542
+ uintN *attrsp)
1543
+ {
1544
+ JSObject *proto = OBJ_GET_PROTO(cx, obj);
1545
+ if (!proto)
1546
+ return js_GetAttributes(cx, obj, id, prop, attrsp);
1547
+ return OBJ_GET_ATTRIBUTES(cx, proto, id, prop, attrsp);
1548
+ }
1549
+
1550
+ static JSBool
1551
+ with_SetAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop,
1552
+ uintN *attrsp)
1553
+ {
1554
+ JSObject *proto = OBJ_GET_PROTO(cx, obj);
1555
+ if (!proto)
1556
+ return js_SetAttributes(cx, obj, id, prop, attrsp);
1557
+ return OBJ_SET_ATTRIBUTES(cx, proto, id, prop, attrsp);
1558
+ }
1559
+
1560
+ static JSBool
1561
+ with_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *rval)
1562
+ {
1563
+ JSObject *proto = OBJ_GET_PROTO(cx, obj);
1564
+ if (!proto)
1565
+ return js_DeleteProperty(cx, obj, id, rval);
1566
+ return OBJ_DELETE_PROPERTY(cx, proto, id, rval);
1567
+ }
1568
+
1569
+ static JSBool
1570
+ with_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp)
1571
+ {
1572
+ JSObject *proto = OBJ_GET_PROTO(cx, obj);
1573
+ if (!proto)
1574
+ return js_DefaultValue(cx, obj, hint, vp);
1575
+ return OBJ_DEFAULT_VALUE(cx, proto, hint, vp);
1576
+ }
1577
+
1578
+ static JSBool
1579
+ with_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
1580
+ jsval *statep, jsid *idp)
1581
+ {
1582
+ JSObject *proto = OBJ_GET_PROTO(cx, obj);
1583
+ if (!proto)
1584
+ return js_Enumerate(cx, obj, enum_op, statep, idp);
1585
+ return OBJ_ENUMERATE(cx, proto, enum_op, statep, idp);
1586
+ }
1587
+
1588
+ static JSBool
1589
+ with_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
1590
+ jsval *vp, uintN *attrsp)
1591
+ {
1592
+ JSObject *proto = OBJ_GET_PROTO(cx, obj);
1593
+ if (!proto)
1594
+ return js_CheckAccess(cx, obj, id, mode, vp, attrsp);
1595
+ return OBJ_CHECK_ACCESS(cx, proto, id, mode, vp, attrsp);
1596
+ }
1597
+
1598
+ static JSObject *
1599
+ with_ThisObject(JSContext *cx, JSObject *obj)
1600
+ {
1601
+ JSObject *proto = OBJ_GET_PROTO(cx, obj);
1602
+ if (!proto)
1603
+ return obj;
1604
+ return OBJ_THIS_OBJECT(cx, proto);
1605
+ }
1606
+
1607
+ JS_FRIEND_DATA(JSObjectOps) js_WithObjectOps = {
1608
+ js_NewObjectMap, js_DestroyObjectMap,
1609
+ with_LookupProperty, js_DefineProperty,
1610
+ with_GetProperty, with_SetProperty,
1611
+ with_GetAttributes, with_SetAttributes,
1612
+ with_DeleteProperty, with_DefaultValue,
1613
+ with_Enumerate, with_CheckAccess,
1614
+ with_ThisObject, NATIVE_DROP_PROPERTY,
1615
+ NULL, NULL,
1616
+ NULL, NULL,
1617
+ js_SetProtoOrParent, js_SetProtoOrParent,
1618
+ js_Mark, js_Clear,
1619
+ NULL, NULL
1620
+ };
1621
+
1622
+ static JSObjectOps *
1623
+ with_getObjectOps(JSContext *cx, JSClass *clasp)
1624
+ {
1625
+ return &js_WithObjectOps;
1626
+ }
1627
+
1628
+ JSClass js_WithClass = {
1629
+ "With",
1630
+ 0,
1631
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
1632
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
1633
+ with_getObjectOps,
1634
+ 0,0,0,0,0,0,0
1635
+ };
1636
+
1637
+ #if JS_HAS_OBJ_PROTO_PROP
1638
+ static JSBool
1639
+ With(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1640
+ {
1641
+ JSObject *parent, *proto;
1642
+ jsval v;
1643
+
1644
+ if (!JS_ReportErrorFlagsAndNumber(cx,
1645
+ JSREPORT_WARNING | JSREPORT_STRICT,
1646
+ js_GetErrorMessage, NULL,
1647
+ JSMSG_DEPRECATED_USAGE,
1648
+ js_WithClass.name)) {
1649
+ return JS_FALSE;
1650
+ }
1651
+
1652
+ if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {
1653
+ obj = js_NewObject(cx, &js_WithClass, NULL, NULL);
1654
+ if (!obj)
1655
+ return JS_FALSE;
1656
+ *rval = OBJECT_TO_JSVAL(obj);
1657
+ }
1658
+
1659
+ parent = cx->fp->scopeChain;
1660
+ if (argc > 0) {
1661
+ if (!js_ValueToObject(cx, argv[0], &proto))
1662
+ return JS_FALSE;
1663
+ v = OBJECT_TO_JSVAL(proto);
1664
+ if (!obj_setSlot(cx, obj, INT_TO_JSVAL(JSSLOT_PROTO), &v))
1665
+ return JS_FALSE;
1666
+ if (argc > 1) {
1667
+ if (!js_ValueToObject(cx, argv[1], &parent))
1668
+ return JS_FALSE;
1669
+ }
1670
+ }
1671
+ v = OBJECT_TO_JSVAL(parent);
1672
+ return obj_setSlot(cx, obj, INT_TO_JSVAL(JSSLOT_PARENT), &v);
1673
+ }
1674
+ #endif
1675
+
1676
+ JSObject *
1677
+ js_InitObjectClass(JSContext *cx, JSObject *obj)
1678
+ {
1679
+ JSObject *proto;
1680
+ jsval eval;
1681
+
1682
+ #if JS_HAS_SHARP_VARS
1683
+ JS_ASSERT(sizeof(jsatomid) * JS_BITS_PER_BYTE >= ATOM_INDEX_LIMIT_LOG2 + 1);
1684
+ #endif
1685
+
1686
+ proto = JS_InitClass(cx, obj, NULL, &js_ObjectClass, Object, 1,
1687
+ object_props, object_methods, NULL, NULL);
1688
+ if (!proto)
1689
+ return NULL;
1690
+
1691
+ #if JS_HAS_OBJ_PROTO_PROP
1692
+ if (!JS_InitClass(cx, obj, NULL, &js_WithClass, With, 0,
1693
+ NULL, NULL, NULL, NULL)) {
1694
+ return NULL;
1695
+ }
1696
+ #endif
1697
+
1698
+ /* ECMA (15.1.2.1) says 'eval' is also a property of the global object. */
1699
+ if (!OBJ_GET_PROPERTY(cx, proto, (jsid)cx->runtime->atomState.evalAtom,
1700
+ &eval)) {
1701
+ return NULL;
1702
+ }
1703
+ if (!OBJ_DEFINE_PROPERTY(cx, obj, (jsid)cx->runtime->atomState.evalAtom,
1704
+ eval, NULL, NULL, 0, NULL)) {
1705
+ return NULL;
1706
+ }
1707
+
1708
+ return proto;
1709
+ }
1710
+
1711
+ void
1712
+ js_InitObjectMap(JSObjectMap *map, jsrefcount nrefs, JSObjectOps *ops,
1713
+ JSClass *clasp)
1714
+ {
1715
+ map->nrefs = nrefs;
1716
+ map->ops = ops;
1717
+ map->nslots = JS_INITIAL_NSLOTS;
1718
+ map->freeslot = JSSLOT_FREE(clasp);
1719
+ }
1720
+
1721
+ JSObjectMap *
1722
+ js_NewObjectMap(JSContext *cx, jsrefcount nrefs, JSObjectOps *ops,
1723
+ JSClass *clasp, JSObject *obj)
1724
+ {
1725
+ return (JSObjectMap *) js_NewScope(cx, nrefs, ops, clasp, obj);
1726
+ }
1727
+
1728
+ void
1729
+ js_DestroyObjectMap(JSContext *cx, JSObjectMap *map)
1730
+ {
1731
+ js_DestroyScope(cx, (JSScope *)map);
1732
+ }
1733
+
1734
+ JSObjectMap *
1735
+ js_HoldObjectMap(JSContext *cx, JSObjectMap *map)
1736
+ {
1737
+ JS_ASSERT(map->nrefs >= 0);
1738
+ JS_ATOMIC_INCREMENT(&map->nrefs);
1739
+ return map;
1740
+ }
1741
+
1742
+ JSObjectMap *
1743
+ js_DropObjectMap(JSContext *cx, JSObjectMap *map, JSObject *obj)
1744
+ {
1745
+ JS_ASSERT(map->nrefs > 0);
1746
+ JS_ATOMIC_DECREMENT(&map->nrefs);
1747
+ if (map->nrefs == 0) {
1748
+ map->ops->destroyObjectMap(cx, map);
1749
+ return NULL;
1750
+ }
1751
+ if (MAP_IS_NATIVE(map) && ((JSScope *)map)->object == obj)
1752
+ ((JSScope *)map)->object = NULL;
1753
+ return map;
1754
+ }
1755
+
1756
+ static JSBool
1757
+ GetClassPrototype(JSContext *cx, JSObject *scope, const char *name,
1758
+ JSObject **protop);
1759
+
1760
+ JSObject *
1761
+ js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent)
1762
+ {
1763
+ JSObject *obj, *ctor;
1764
+ JSObjectOps *ops;
1765
+ JSObjectMap *map;
1766
+ JSClass *protoclasp;
1767
+ jsval cval;
1768
+ uint32 nslots, i;
1769
+ jsval *newslots;
1770
+
1771
+ /* Allocate an object from the GC heap and zero it. */
1772
+ obj = (JSObject *) js_AllocGCThing(cx, GCX_OBJECT);
1773
+ if (!obj)
1774
+ return NULL;
1775
+
1776
+ /* Bootstrap the ur-object, and make it the default prototype object. */
1777
+ if (!proto) {
1778
+ if (!GetClassPrototype(cx, parent, clasp->name, &proto))
1779
+ goto bad;
1780
+ if (!proto && !GetClassPrototype(cx, parent, js_Object_str, &proto))
1781
+ goto bad;
1782
+ }
1783
+
1784
+ /* Always call the class's getObjectOps hook if it has one. */
1785
+ ops = clasp->getObjectOps
1786
+ ? clasp->getObjectOps(cx, clasp)
1787
+ : &js_ObjectOps;
1788
+
1789
+ /*
1790
+ * Share proto's map only if it has the same JSObjectOps, and only if
1791
+ * proto's class has the same private and reserved slots as obj's map
1792
+ * and class have. We assume that if prototype and object are of the
1793
+ * same class, they always have the same number of computed reserved
1794
+ * slots (returned via clasp->reserveSlots); otherwise, prototype and
1795
+ * object classes must have the same (null or not) reserveSlots hook.
1796
+ */
1797
+ if (proto &&
1798
+ (map = proto->map)->ops == ops &&
1799
+ ((protoclasp = OBJ_GET_CLASS(cx, proto)) == clasp ||
1800
+ (!((protoclasp->flags ^ clasp->flags) &
1801
+ (JSCLASS_HAS_PRIVATE |
1802
+ (JSCLASS_RESERVED_SLOTS_MASK << JSCLASS_RESERVED_SLOTS_SHIFT))) &&
1803
+ protoclasp->reserveSlots == clasp->reserveSlots)))
1804
+ {
1805
+ /* Default parent to the parent of the prototype's constructor. */
1806
+ if (!parent) {
1807
+ if (!OBJ_GET_PROPERTY(cx, proto,
1808
+ (jsid)cx->runtime->atomState.constructorAtom,
1809
+ &cval)) {
1810
+ goto bad;
1811
+ }
1812
+ if (JSVAL_IS_OBJECT(cval) && (ctor = JSVAL_TO_OBJECT(cval)) != NULL)
1813
+ parent = OBJ_GET_PARENT(cx, ctor);
1814
+ }
1815
+
1816
+ /* Share the given prototype's map. */
1817
+ obj->map = js_HoldObjectMap(cx, map);
1818
+
1819
+ /* Ensure that obj starts with the minimum slots for clasp. */
1820
+ nslots = JS_INITIAL_NSLOTS;
1821
+ } else {
1822
+ /* Leave parent alone. Allocate a new map for obj. */
1823
+ map = ops->newObjectMap(cx, 1, ops, clasp, obj);
1824
+ if (!map)
1825
+ goto bad;
1826
+ obj->map = map;
1827
+
1828
+ /* Let ops->newObjectMap set nslots so as to reserve slots. */
1829
+ nslots = map->nslots;
1830
+ }
1831
+
1832
+ /* Allocate a slots vector, with a -1'st element telling its length. */
1833
+ newslots = (jsval *) JS_malloc(cx, (nslots + 1) * sizeof(jsval));
1834
+ if (!newslots) {
1835
+ js_DropObjectMap(cx, obj->map, obj);
1836
+ obj->map = NULL;
1837
+ goto bad;
1838
+ }
1839
+ newslots[0] = nslots;
1840
+ newslots++;
1841
+
1842
+ /* Set the proto, parent, and class properties. */
1843
+ newslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto);
1844
+ newslots[JSSLOT_PARENT] = OBJECT_TO_JSVAL(parent);
1845
+ newslots[JSSLOT_CLASS] = PRIVATE_TO_JSVAL(clasp);
1846
+
1847
+ /* Clear above JSSLOT_CLASS so the GC doesn't load uninitialized memory. */
1848
+ for (i = JSSLOT_CLASS + 1; i < nslots; i++)
1849
+ newslots[i] = JSVAL_VOID;
1850
+
1851
+ /* Store newslots after initializing all of 'em, just in case. */
1852
+ obj->slots = newslots;
1853
+
1854
+ if (cx->runtime->objectHook) {
1855
+ JS_KEEP_ATOMS(cx->runtime);
1856
+ cx->runtime->objectHook(cx, obj, JS_TRUE, cx->runtime->objectHookData);
1857
+ JS_UNKEEP_ATOMS(cx->runtime);
1858
+ }
1859
+
1860
+ return obj;
1861
+
1862
+ bad:
1863
+ cx->newborn[GCX_OBJECT] = NULL;
1864
+ return NULL;
1865
+ }
1866
+
1867
+ static JSBool
1868
+ FindConstructor(JSContext *cx, JSObject *start, const char *name, jsval *vp)
1869
+ {
1870
+ JSAtom *atom;
1871
+ JSObject *obj, *pobj;
1872
+ JSProperty *prop;
1873
+ JSScopeProperty *sprop;
1874
+
1875
+ atom = js_Atomize(cx, name, strlen(name), 0);
1876
+ if (!atom)
1877
+ return JS_FALSE;
1878
+
1879
+ if (start || (cx->fp && (start = cx->fp->scopeChain) != NULL)) {
1880
+ /* Find the topmost object in the scope chain. */
1881
+ do {
1882
+ obj = start;
1883
+ start = OBJ_GET_PARENT(cx, obj);
1884
+ } while (start);
1885
+ } else {
1886
+ obj = cx->globalObject;
1887
+ if (!obj) {
1888
+ *vp = JSVAL_VOID;
1889
+ return JS_TRUE;
1890
+ }
1891
+ }
1892
+
1893
+ JS_ASSERT(OBJ_IS_NATIVE(obj));
1894
+ if (!js_LookupPropertyWithFlags(cx, obj, (jsid)atom, JSRESOLVE_CLASSNAME,
1895
+ &pobj, &prop
1896
+ #if defined JS_THREADSAFE && defined DEBUG
1897
+ , __FILE__, __LINE__
1898
+ #endif
1899
+ )) {
1900
+ return JS_FALSE;
1901
+ }
1902
+ if (!prop) {
1903
+ *vp = JSVAL_VOID;
1904
+ return JS_TRUE;
1905
+ }
1906
+
1907
+ JS_ASSERT(OBJ_IS_NATIVE(pobj));
1908
+ sprop = (JSScopeProperty *) prop;
1909
+ JS_ASSERT(SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(pobj)));
1910
+ *vp = OBJ_GET_SLOT(cx, pobj, sprop->slot);
1911
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
1912
+ return JS_TRUE;
1913
+ }
1914
+
1915
+ JSObject *
1916
+ js_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto,
1917
+ JSObject *parent, uintN argc, jsval *argv)
1918
+ {
1919
+ jsval cval, rval;
1920
+ JSObject *obj, *ctor;
1921
+
1922
+ if (!FindConstructor(cx, parent, clasp->name, &cval))
1923
+ return NULL;
1924
+ if (JSVAL_IS_PRIMITIVE(cval)) {
1925
+ js_ReportIsNotFunction(cx, &cval, JSV2F_CONSTRUCT | JSV2F_SEARCH_STACK);
1926
+ return NULL;
1927
+ }
1928
+
1929
+ /*
1930
+ * If proto or parent are NULL, set them to Constructor.prototype and/or
1931
+ * Constructor.__parent__, just like JSOP_NEW does.
1932
+ */
1933
+ ctor = JSVAL_TO_OBJECT(cval);
1934
+ if (!parent)
1935
+ parent = OBJ_GET_PARENT(cx, ctor);
1936
+ if (!proto) {
1937
+ if (!OBJ_GET_PROPERTY(cx, ctor,
1938
+ (jsid)cx->runtime->atomState.classPrototypeAtom,
1939
+ &rval)) {
1940
+ return NULL;
1941
+ }
1942
+ if (JSVAL_IS_OBJECT(rval))
1943
+ proto = JSVAL_TO_OBJECT(rval);
1944
+ }
1945
+
1946
+ obj = js_NewObject(cx, clasp, proto, parent);
1947
+ if (!obj)
1948
+ return NULL;
1949
+
1950
+ if (!js_InternalConstruct(cx, obj, cval, argc, argv, &rval))
1951
+ goto bad;
1952
+ return JSVAL_IS_OBJECT(rval) ? JSVAL_TO_OBJECT(rval) : obj;
1953
+ bad:
1954
+ cx->newborn[GCX_OBJECT] = NULL;
1955
+ return NULL;
1956
+ }
1957
+
1958
+ void
1959
+ js_FinalizeObject(JSContext *cx, JSObject *obj)
1960
+ {
1961
+ JSObjectMap *map;
1962
+
1963
+ /* Cope with stillborn objects that have no map. */
1964
+ map = obj->map;
1965
+ if (!map)
1966
+ return;
1967
+ JS_ASSERT(obj->slots);
1968
+
1969
+ if (cx->runtime->objectHook)
1970
+ cx->runtime->objectHook(cx, obj, JS_FALSE, cx->runtime->objectHookData);
1971
+
1972
+ /* Remove all watchpoints with weak links to obj. */
1973
+ JS_ClearWatchPointsForObject(cx, obj);
1974
+
1975
+ /*
1976
+ * Finalize obj first, in case it needs map and slots. Optimized to use
1977
+ * LOCKED_OBJ_GET_CLASS instead of OBJ_GET_CLASS, so we avoid "promoting"
1978
+ * obj's scope from lock-free to lock-full (see jslock.c:ClaimScope) when
1979
+ * we're called from the GC. Only the GC should call js_FinalizeObject,
1980
+ * and no other threads run JS (and possibly racing to update obj->slots)
1981
+ * while the GC is running.
1982
+ */
1983
+ LOCKED_OBJ_GET_CLASS(obj)->finalize(cx, obj);
1984
+
1985
+ /* Drop map and free slots. */
1986
+ js_DropObjectMap(cx, map, obj);
1987
+ obj->map = NULL;
1988
+ JS_free(cx, obj->slots - 1);
1989
+ obj->slots = NULL;
1990
+ }
1991
+
1992
+ /* XXXbe if one adds props, deletes earlier props, adds more, the last added
1993
+ won't recycle the deleted props' slots. */
1994
+ JSBool
1995
+ js_AllocSlot(JSContext *cx, JSObject *obj, uint32 *slotp)
1996
+ {
1997
+ JSObjectMap *map;
1998
+ JSClass *clasp;
1999
+ uint32 nslots, i;
2000
+ jsval *newslots;
2001
+
2002
+ map = obj->map;
2003
+ JS_ASSERT(!MAP_IS_NATIVE(map) || ((JSScope *)map)->object == obj);
2004
+ clasp = LOCKED_OBJ_GET_CLASS(obj);
2005
+ if (map->freeslot == JSSLOT_FREE(clasp)) {
2006
+ /* Adjust map->freeslot to include computed reserved slots, if any. */
2007
+ if (clasp->reserveSlots)
2008
+ map->freeslot += clasp->reserveSlots(cx, obj);
2009
+ }
2010
+ nslots = map->nslots;
2011
+ if (map->freeslot >= nslots) {
2012
+ nslots = map->freeslot;
2013
+ JS_ASSERT(nslots >= JS_INITIAL_NSLOTS);
2014
+ nslots += (nslots + 1) / 2;
2015
+
2016
+ newslots = (jsval *)
2017
+ JS_realloc(cx, obj->slots - 1, (nslots + 1) * sizeof(jsval));
2018
+ if (!newslots)
2019
+ return JS_FALSE;
2020
+ for (i = 1 + newslots[0]; i <= nslots; i++)
2021
+ newslots[i] = JSVAL_VOID;
2022
+ newslots[0] = map->nslots = nslots;
2023
+ obj->slots = newslots + 1;
2024
+ }
2025
+
2026
+ #ifdef TOO_MUCH_GC
2027
+ obj->slots[map->freeslot] = JSVAL_VOID;
2028
+ #endif
2029
+ *slotp = map->freeslot++;
2030
+ return JS_TRUE;
2031
+ }
2032
+
2033
+ void
2034
+ js_FreeSlot(JSContext *cx, JSObject *obj, uint32 slot)
2035
+ {
2036
+ JSObjectMap *map;
2037
+ uint32 nslots;
2038
+ jsval *newslots;
2039
+
2040
+ OBJ_CHECK_SLOT(obj, slot);
2041
+ obj->slots[slot] = JSVAL_VOID;
2042
+ map = obj->map;
2043
+ JS_ASSERT(!MAP_IS_NATIVE(map) || ((JSScope *)map)->object == obj);
2044
+ if (map->freeslot == slot + 1)
2045
+ map->freeslot = slot;
2046
+ nslots = map->nslots;
2047
+ if (nslots > JS_INITIAL_NSLOTS && map->freeslot < nslots / 2) {
2048
+ nslots = map->freeslot;
2049
+ nslots += nslots / 2;
2050
+ if (nslots < JS_INITIAL_NSLOTS)
2051
+ nslots = JS_INITIAL_NSLOTS;
2052
+
2053
+ newslots = (jsval *)
2054
+ JS_realloc(cx, obj->slots - 1, (nslots + 1) * sizeof(jsval));
2055
+ if (!newslots)
2056
+ return;
2057
+ newslots[0] = map->nslots = nslots;
2058
+ obj->slots = newslots + 1;
2059
+ }
2060
+ }
2061
+
2062
+ #if JS_BUG_EMPTY_INDEX_ZERO
2063
+ #define CHECK_FOR_EMPTY_INDEX(id) \
2064
+ JS_BEGIN_MACRO \
2065
+ if (JSSTRING_LENGTH(_str) == 0) \
2066
+ id = JSVAL_ZERO; \
2067
+ JS_END_MACRO
2068
+ #else
2069
+ #define CHECK_FOR_EMPTY_INDEX(id) /* nothing */
2070
+ #endif
2071
+
2072
+ /* JSVAL_INT_MAX as a string */
2073
+ #define JSVAL_INT_MAX_STRING "1073741823"
2074
+
2075
+ #define CHECK_FOR_FUNNY_INDEX(id) \
2076
+ JS_BEGIN_MACRO \
2077
+ if (!JSVAL_IS_INT(id)) { \
2078
+ JSAtom *atom_ = (JSAtom *)id; \
2079
+ JSString *str_ = ATOM_TO_STRING(atom_); \
2080
+ const jschar *cp_ = str_->chars; \
2081
+ JSBool negative_ = (*cp_ == '-'); \
2082
+ if (negative_) cp_++; \
2083
+ if (JS7_ISDEC(*cp_) && \
2084
+ str_->length - negative_ <= sizeof(JSVAL_INT_MAX_STRING)-1) { \
2085
+ id = CheckForFunnyIndex(id, cp_, negative_); \
2086
+ } else { \
2087
+ CHECK_FOR_EMPTY_INDEX(id); \
2088
+ } \
2089
+ } \
2090
+ JS_END_MACRO
2091
+
2092
+ static jsid
2093
+ CheckForFunnyIndex(jsid id, const jschar *cp, JSBool negative)
2094
+ {
2095
+ jsuint index = JS7_UNDEC(*cp++);
2096
+ jsuint oldIndex = 0;
2097
+ jsuint c = 0;
2098
+
2099
+ if (index != 0) {
2100
+ while (JS7_ISDEC(*cp)) {
2101
+ oldIndex = index;
2102
+ c = JS7_UNDEC(*cp);
2103
+ index = 10 * index + c;
2104
+ cp++;
2105
+ }
2106
+ }
2107
+ if (*cp == 0 &&
2108
+ (oldIndex < (JSVAL_INT_MAX / 10) ||
2109
+ (oldIndex == (JSVAL_INT_MAX / 10) &&
2110
+ c <= (JSVAL_INT_MAX % 10)))) {
2111
+ if (negative)
2112
+ index = 0 - index;
2113
+ id = INT_TO_JSVAL((jsint)index);
2114
+ }
2115
+ return id;
2116
+ }
2117
+
2118
+ JSScopeProperty *
2119
+ js_AddNativeProperty(JSContext *cx, JSObject *obj, jsid id,
2120
+ JSPropertyOp getter, JSPropertyOp setter, uint32 slot,
2121
+ uintN attrs, uintN flags, intN shortid)
2122
+ {
2123
+ JSScope *scope;
2124
+ JSScopeProperty *sprop;
2125
+
2126
+ JS_LOCK_OBJ(cx, obj);
2127
+ scope = js_GetMutableScope(cx, obj);
2128
+ if (!scope) {
2129
+ sprop = NULL;
2130
+ } else {
2131
+ /*
2132
+ * Handle old bug that took empty string as zero index. Also convert
2133
+ * string indices to integers if appropriate.
2134
+ */
2135
+ CHECK_FOR_FUNNY_INDEX(id);
2136
+ sprop = js_AddScopeProperty(cx, scope, id, getter, setter, slot, attrs,
2137
+ flags, shortid);
2138
+ }
2139
+ JS_UNLOCK_OBJ(cx, obj);
2140
+ return sprop;
2141
+ }
2142
+
2143
+ JSScopeProperty *
2144
+ js_ChangeNativePropertyAttrs(JSContext *cx, JSObject *obj,
2145
+ JSScopeProperty *sprop, uintN attrs, uintN mask,
2146
+ JSPropertyOp getter, JSPropertyOp setter)
2147
+ {
2148
+ JSScope *scope;
2149
+
2150
+ JS_LOCK_OBJ(cx, obj);
2151
+ scope = js_GetMutableScope(cx, obj);
2152
+ if (!scope) {
2153
+ sprop = NULL;
2154
+ } else {
2155
+ sprop = js_ChangeScopePropertyAttrs(cx, scope, sprop, attrs, mask,
2156
+ getter, setter);
2157
+ if (sprop) {
2158
+ PROPERTY_CACHE_FILL(&cx->runtime->propertyCache, obj, sprop->id,
2159
+ sprop);
2160
+ }
2161
+ }
2162
+ JS_UNLOCK_OBJ(cx, obj);
2163
+ return sprop;
2164
+ }
2165
+
2166
+ JSBool
2167
+ js_DefineProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
2168
+ JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
2169
+ JSProperty **propp)
2170
+ {
2171
+ return js_DefineNativeProperty(cx, obj, id, value, getter, setter, attrs,
2172
+ 0, 0, propp);
2173
+ }
2174
+
2175
+ JSBool
2176
+ js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
2177
+ JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
2178
+ uintN flags, intN shortid, JSProperty **propp)
2179
+ {
2180
+ JSClass *clasp;
2181
+ JSScope *scope;
2182
+ JSProperty *prop;
2183
+ JSScopeProperty *sprop;
2184
+
2185
+ /*
2186
+ * Handle old bug that took empty string as zero index. Also convert
2187
+ * string indices to integers if appropriate.
2188
+ */
2189
+ CHECK_FOR_FUNNY_INDEX(id);
2190
+
2191
+ #if JS_HAS_GETTER_SETTER
2192
+ /*
2193
+ * If defining a getter or setter, we must check for its counterpart and
2194
+ * update the attributes and property ops. A getter or setter is really
2195
+ * only half of a property.
2196
+ */
2197
+ if (attrs & (JSPROP_GETTER | JSPROP_SETTER)) {
2198
+ JSObject *pobj;
2199
+
2200
+ /*
2201
+ * If JS_THREADSAFE and id is found, js_LookupProperty returns with
2202
+ * sprop non-null and pobj locked. If pobj == obj, the property is
2203
+ * already in obj and obj has its own (mutable) scope. So if we are
2204
+ * defining a getter whose setter was already defined, or vice versa,
2205
+ * finish the job via js_ChangeScopePropertyAttributes, and refresh
2206
+ * the property cache line for (obj, id) to map sprop.
2207
+ */
2208
+ if (!js_LookupProperty(cx, obj, id, &pobj, &prop))
2209
+ return JS_FALSE;
2210
+ sprop = (JSScopeProperty *) prop;
2211
+ if (sprop &&
2212
+ pobj == obj &&
2213
+ (sprop->attrs & (JSPROP_GETTER | JSPROP_SETTER))) {
2214
+ sprop = js_ChangeScopePropertyAttrs(cx, OBJ_SCOPE(obj), sprop,
2215
+ attrs, sprop->attrs,
2216
+ (attrs & JSPROP_GETTER)
2217
+ ? getter
2218
+ : sprop->getter,
2219
+ (attrs & JSPROP_SETTER)
2220
+ ? setter
2221
+ : sprop->setter);
2222
+
2223
+ /* NB: obj == pobj, so we can share unlock code at the bottom. */
2224
+ if (!sprop)
2225
+ goto bad;
2226
+ goto out;
2227
+ }
2228
+
2229
+ if (prop) {
2230
+ /* NB: call OBJ_DROP_PROPERTY, as pobj might not be native. */
2231
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
2232
+ prop = NULL;
2233
+ }
2234
+ }
2235
+ #endif /* JS_HAS_GETTER_SETTER */
2236
+
2237
+ /* Lock if object locking is required by this implementation. */
2238
+ JS_LOCK_OBJ(cx, obj);
2239
+
2240
+ /* Use the object's class getter and setter by default. */
2241
+ clasp = LOCKED_OBJ_GET_CLASS(obj);
2242
+ if (!getter)
2243
+ getter = clasp->getProperty;
2244
+ if (!setter)
2245
+ setter = clasp->setProperty;
2246
+
2247
+ /* Get obj's own scope if it has one, or create a new one for obj. */
2248
+ scope = js_GetMutableScope(cx, obj);
2249
+ if (!scope)
2250
+ goto bad;
2251
+
2252
+ /* Add the property to scope, or replace an existing one of the same id. */
2253
+ if (clasp->flags & JSCLASS_SHARE_ALL_PROPERTIES)
2254
+ attrs |= JSPROP_SHARED;
2255
+ sprop = js_AddScopeProperty(cx, scope, id, getter, setter,
2256
+ SPROP_INVALID_SLOT, attrs, flags, shortid);
2257
+ if (!sprop)
2258
+ goto bad;
2259
+
2260
+ /* XXXbe called with lock held */
2261
+ if (!clasp->addProperty(cx, obj, SPROP_USERID(sprop), &value)) {
2262
+ (void) js_RemoveScopeProperty(cx, scope, id);
2263
+ goto bad;
2264
+ }
2265
+
2266
+ if (SPROP_HAS_VALID_SLOT(sprop, scope))
2267
+ LOCKED_OBJ_SET_SLOT(obj, sprop->slot, value);
2268
+
2269
+ #if JS_HAS_GETTER_SETTER
2270
+ out:
2271
+ #endif
2272
+ PROPERTY_CACHE_FILL(&cx->runtime->propertyCache, obj, id, sprop);
2273
+ if (propp)
2274
+ *propp = (JSProperty *) sprop;
2275
+ else
2276
+ JS_UNLOCK_OBJ(cx, obj);
2277
+ return JS_TRUE;
2278
+
2279
+ bad:
2280
+ JS_UNLOCK_OBJ(cx, obj);
2281
+ return JS_FALSE;
2282
+ }
2283
+
2284
+ /*
2285
+ * Given pc pointing after a property accessing bytecode, return true if the
2286
+ * access is a "object-detecting" in the sense used by web pages, e.g., when
2287
+ * checking whether document.all is defined.
2288
+ */
2289
+ static JSBool
2290
+ Detecting(JSContext *cx, jsbytecode *pc)
2291
+ {
2292
+ JSScript *script;
2293
+ jsbytecode *endpc;
2294
+ JSOp op;
2295
+ JSAtom *atom;
2296
+
2297
+ script = cx->fp->script;
2298
+ for (endpc = script->code + script->length; pc < endpc; pc++) {
2299
+ /* General case: a branch or equality op follows the access. */
2300
+ op = (JSOp) *pc;
2301
+ if (js_CodeSpec[op].format & JOF_DETECTING)
2302
+ return JS_TRUE;
2303
+
2304
+ /*
2305
+ * Special case #1: handle (document.all == null). Don't sweat about
2306
+ * JS1.2's revision of the equality operators here.
2307
+ */
2308
+ if (op == JSOP_NULL) {
2309
+ if (++pc < endpc)
2310
+ return *pc == JSOP_EQ || *pc == JSOP_NE;
2311
+ break;
2312
+ }
2313
+
2314
+ /*
2315
+ * Special case #2: handle (document.all == undefined). Don't worry
2316
+ * about someone redefining undefined, which was added by Edition 3,
2317
+ * so was read/write for backward compatibility.
2318
+ */
2319
+ if (op == JSOP_NAME) {
2320
+ atom = GET_ATOM(cx, script, pc);
2321
+ if (atom == cx->runtime->atomState.typeAtoms[JSTYPE_VOID] &&
2322
+ (pc += js_CodeSpec[op].length) < endpc) {
2323
+ op = (JSOp) *pc;
2324
+ return op == JSOP_EQ || op == JSOP_NE ||
2325
+ op == JSOP_NEW_EQ || op == JSOP_NEW_NE;
2326
+ }
2327
+ break;
2328
+ }
2329
+
2330
+ /* At this point, anything but grouping means we're not detecting. */
2331
+ if (op != JSOP_GROUP)
2332
+ break;
2333
+ }
2334
+ return JS_FALSE;
2335
+ }
2336
+
2337
+ JSBool
2338
+ js_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, uintN flags,
2339
+ JSObject **objp, JSProperty **propp
2340
+ #if defined JS_THREADSAFE && defined DEBUG
2341
+ , const char *file, uintN line
2342
+ #endif
2343
+ )
2344
+ {
2345
+ JSObject *start, *obj2, *proto;
2346
+ JSScope *scope;
2347
+ JSScopeProperty *sprop;
2348
+ JSClass *clasp;
2349
+ JSResolveOp resolve;
2350
+ JSResolvingKey key;
2351
+ JSResolvingEntry *entry;
2352
+ uint32 generation;
2353
+ JSNewResolveOp newresolve;
2354
+ jsbytecode *pc;
2355
+ const JSCodeSpec *cs;
2356
+ uint32 format;
2357
+ JSBool ok;
2358
+
2359
+ /*
2360
+ * Handle old bug that took empty string as zero index. Also convert
2361
+ * string indices to integers if appropriate.
2362
+ */
2363
+ CHECK_FOR_FUNNY_INDEX(id);
2364
+
2365
+ /* Search scopes starting with obj and following the prototype link. */
2366
+ start = obj;
2367
+ for (;;) {
2368
+ JS_LOCK_OBJ(cx, obj);
2369
+ SET_OBJ_INFO(obj, file, line);
2370
+ scope = OBJ_SCOPE(obj);
2371
+ if (scope->object == obj) {
2372
+ sprop = SCOPE_GET_PROPERTY(scope, id);
2373
+ } else {
2374
+ /* Shared prototype scope: try resolve before lookup. */
2375
+ sprop = NULL;
2376
+ }
2377
+
2378
+ /* Try obj's class resolve hook if id was not found in obj's scope. */
2379
+ if (!sprop) {
2380
+ clasp = LOCKED_OBJ_GET_CLASS(obj);
2381
+ resolve = clasp->resolve;
2382
+ if (resolve != JS_ResolveStub) {
2383
+ /* Avoid recursion on (obj, id) already being resolved on cx. */
2384
+ key.obj = obj;
2385
+ key.id = id;
2386
+
2387
+ /*
2388
+ * Once we have successfully added an entry for (obj, key) to
2389
+ * cx->resolvingTable, control must go through cleanup: before
2390
+ * returning. But note that JS_DHASH_ADD may find an existing
2391
+ * entry, in which case we bail to suppress runaway recursion.
2392
+ */
2393
+ if (!js_StartResolving(cx, &key, JSRESFLAG_LOOKUP, &entry)) {
2394
+ JS_UNLOCK_OBJ(cx, obj);
2395
+ return JS_FALSE;
2396
+ }
2397
+ if (!entry) {
2398
+ /* Already resolving id in obj -- dampen recursion. */
2399
+ JS_UNLOCK_OBJ(cx, obj);
2400
+ goto out;
2401
+ }
2402
+ generation = cx->resolvingTable->generation;
2403
+
2404
+ /* Null *propp here so we can test it at cleanup: safely. */
2405
+ *propp = NULL;
2406
+
2407
+ if (clasp->flags & JSCLASS_NEW_RESOLVE) {
2408
+ newresolve = (JSNewResolveOp)resolve;
2409
+ if (cx->fp && (pc = cx->fp->pc)) {
2410
+ cs = &js_CodeSpec[*pc];
2411
+ format = cs->format;
2412
+ if ((format & JOF_MODEMASK) != JOF_NAME)
2413
+ flags |= JSRESOLVE_QUALIFIED;
2414
+ if ((format & JOF_ASSIGNING) ||
2415
+ (cx->fp->flags & JSFRAME_ASSIGNING)) {
2416
+ flags |= JSRESOLVE_ASSIGNING;
2417
+ } else {
2418
+ pc += cs->length;
2419
+ if (Detecting(cx, pc))
2420
+ flags |= JSRESOLVE_DETECTING;
2421
+ }
2422
+ if (format & JOF_DECLARING)
2423
+ flags |= JSRESOLVE_DECLARING;
2424
+ }
2425
+ obj2 = (clasp->flags & JSCLASS_NEW_RESOLVE_GETS_START)
2426
+ ? start
2427
+ : NULL;
2428
+ JS_UNLOCK_OBJ(cx, obj);
2429
+
2430
+ /* Protect id and all atoms from a GC nested in resolve. */
2431
+ JS_KEEP_ATOMS(cx->runtime);
2432
+ ok = newresolve(cx, obj, ID_TO_VALUE(id), flags, &obj2);
2433
+ JS_UNKEEP_ATOMS(cx->runtime);
2434
+ if (!ok)
2435
+ goto cleanup;
2436
+
2437
+ JS_LOCK_OBJ(cx, obj);
2438
+ SET_OBJ_INFO(obj, file, line);
2439
+ if (obj2) {
2440
+ /* Resolved: juggle locks and lookup id again. */
2441
+ if (obj2 != obj) {
2442
+ JS_UNLOCK_OBJ(cx, obj);
2443
+ JS_LOCK_OBJ(cx, obj2);
2444
+ }
2445
+ scope = OBJ_SCOPE(obj2);
2446
+ if (!MAP_IS_NATIVE(&scope->map)) {
2447
+ /* Whoops, newresolve handed back a foreign obj2. */
2448
+ JS_ASSERT(obj2 != obj);
2449
+ JS_UNLOCK_OBJ(cx, obj2);
2450
+ ok = OBJ_LOOKUP_PROPERTY(cx, obj2, id, objp, propp);
2451
+ if (!ok || *propp)
2452
+ goto cleanup;
2453
+ JS_LOCK_OBJ(cx, obj2);
2454
+ } else {
2455
+ /*
2456
+ * Require that obj2 have its own scope now, as we
2457
+ * do for old-style resolve. If it doesn't, then
2458
+ * id was not truly resolved, and we'll find it in
2459
+ * the proto chain, or miss it if obj2's proto is
2460
+ * not on obj's proto chain. That last case is a
2461
+ * "too bad!" case.
2462
+ */
2463
+ if (scope->object == obj2)
2464
+ sprop = SCOPE_GET_PROPERTY(scope, id);
2465
+ }
2466
+ if (obj2 != obj && !sprop) {
2467
+ JS_UNLOCK_OBJ(cx, obj2);
2468
+ JS_LOCK_OBJ(cx, obj);
2469
+ }
2470
+ }
2471
+ } else {
2472
+ /*
2473
+ * Old resolve always requires id re-lookup if obj owns
2474
+ * its scope after resolve returns.
2475
+ */
2476
+ JS_UNLOCK_OBJ(cx, obj);
2477
+ ok = resolve(cx, obj, ID_TO_VALUE(id));
2478
+ if (!ok)
2479
+ goto cleanup;
2480
+ JS_LOCK_OBJ(cx, obj);
2481
+ SET_OBJ_INFO(obj, file, line);
2482
+ scope = OBJ_SCOPE(obj);
2483
+ JS_ASSERT(MAP_IS_NATIVE(&scope->map));
2484
+ if (scope->object == obj)
2485
+ sprop = SCOPE_GET_PROPERTY(scope, id);
2486
+ }
2487
+
2488
+ cleanup:
2489
+ js_StopResolving(cx, &key, JSRESFLAG_LOOKUP, entry, generation);
2490
+ if (!ok || *propp)
2491
+ return ok;
2492
+ }
2493
+ }
2494
+
2495
+ if (sprop) {
2496
+ JS_ASSERT(OBJ_SCOPE(obj) == scope);
2497
+ *objp = scope->object; /* XXXbe hide in jsscope.[ch] */
2498
+
2499
+ *propp = (JSProperty *) sprop;
2500
+ return JS_TRUE;
2501
+ }
2502
+
2503
+ proto = LOCKED_OBJ_GET_PROTO(obj);
2504
+ JS_UNLOCK_OBJ(cx, obj);
2505
+ if (!proto)
2506
+ break;
2507
+ if (!OBJ_IS_NATIVE(proto))
2508
+ return OBJ_LOOKUP_PROPERTY(cx, proto, id, objp, propp);
2509
+ obj = proto;
2510
+ }
2511
+
2512
+ out:
2513
+ *objp = NULL;
2514
+ *propp = NULL;
2515
+ return JS_TRUE;
2516
+ }
2517
+
2518
+ #if defined JS_THREADSAFE && defined DEBUG
2519
+ JS_FRIEND_API(JSBool)
2520
+ _js_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
2521
+ JSProperty **propp, const char *file, uintN line)
2522
+ {
2523
+ return js_LookupPropertyWithFlags(cx, obj, id, 0, objp, propp, file, line);
2524
+ }
2525
+ #else
2526
+ JS_FRIEND_API(JSBool)
2527
+ js_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
2528
+ JSProperty **propp)
2529
+ {
2530
+ return js_LookupPropertyWithFlags(cx, obj, id, 0, objp, propp);
2531
+ }
2532
+ #endif
2533
+
2534
+ JS_FRIEND_API(JSBool)
2535
+ js_FindProperty(JSContext *cx, jsid id, JSObject **objp, JSObject **pobjp,
2536
+ JSProperty **propp)
2537
+ {
2538
+ JSRuntime *rt;
2539
+ JSObject *obj, *pobj, *lastobj;
2540
+ JSScopeProperty *sprop;
2541
+ JSProperty *prop;
2542
+
2543
+ rt = cx->runtime;
2544
+ obj = cx->fp->scopeChain;
2545
+ do {
2546
+ /* Try the property cache and return immediately on cache hit. */
2547
+ if (OBJ_IS_NATIVE(obj)) {
2548
+ JS_LOCK_OBJ(cx, obj);
2549
+ PROPERTY_CACHE_TEST(&rt->propertyCache, obj, id, sprop);
2550
+ if (sprop) {
2551
+ JS_ASSERT(OBJ_IS_NATIVE(obj));
2552
+ *objp = obj;
2553
+ *pobjp = obj;
2554
+ *propp = (JSProperty *) sprop;
2555
+ return JS_TRUE;
2556
+ }
2557
+ JS_UNLOCK_OBJ(cx, obj);
2558
+ }
2559
+
2560
+ /* If cache miss, take the slow path. */
2561
+ if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &pobj, &prop))
2562
+ return JS_FALSE;
2563
+ if (prop) {
2564
+ if (OBJ_IS_NATIVE(pobj)) {
2565
+ sprop = (JSScopeProperty *) prop;
2566
+ PROPERTY_CACHE_FILL(&rt->propertyCache, pobj, id, sprop);
2567
+ }
2568
+ *objp = obj;
2569
+ *pobjp = pobj;
2570
+ *propp = prop;
2571
+ return JS_TRUE;
2572
+ }
2573
+ lastobj = obj;
2574
+ } while ((obj = OBJ_GET_PARENT(cx, obj)) != NULL);
2575
+
2576
+ *objp = lastobj;
2577
+ *pobjp = NULL;
2578
+ *propp = NULL;
2579
+ return JS_TRUE;
2580
+ }
2581
+
2582
+ JSObject *
2583
+ js_FindIdentifierBase(JSContext *cx, jsid id)
2584
+ {
2585
+ JSObject *obj, *pobj;
2586
+ JSProperty *prop;
2587
+
2588
+ /*
2589
+ * Look for id's property along the "with" statement chain and the
2590
+ * statically-linked scope chain.
2591
+ */
2592
+ if (!js_FindProperty(cx, id, &obj, &pobj, &prop))
2593
+ return NULL;
2594
+ if (prop) {
2595
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
2596
+ return obj;
2597
+ }
2598
+
2599
+ /*
2600
+ * Use the top-level scope from the scope chain, which won't end in the
2601
+ * same scope as cx->globalObject for cross-context function calls.
2602
+ */
2603
+ JS_ASSERT(obj);
2604
+
2605
+ /*
2606
+ * Property not found. Give a strict warning if binding an undeclared
2607
+ * top-level variable.
2608
+ */
2609
+ if (JS_HAS_STRICT_OPTION(cx)) {
2610
+ JSString *str = JSVAL_TO_STRING(ID_TO_VALUE(id));
2611
+ if (!JS_ReportErrorFlagsAndNumber(cx,
2612
+ JSREPORT_WARNING | JSREPORT_STRICT,
2613
+ js_GetErrorMessage, NULL,
2614
+ JSMSG_UNDECLARED_VAR,
2615
+ JS_GetStringBytes(str))) {
2616
+ return NULL;
2617
+ }
2618
+ }
2619
+ return obj;
2620
+ }
2621
+
2622
+ JSBool
2623
+ js_GetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
2624
+ {
2625
+ JSObject *obj2;
2626
+ JSProperty *prop;
2627
+ JSScope *scope;
2628
+ JSScopeProperty *sprop;
2629
+ uint32 slot;
2630
+
2631
+ /*
2632
+ * Handle old bug that took empty string as zero index. Also convert
2633
+ * string indices to integers if appropriate.
2634
+ */
2635
+ CHECK_FOR_FUNNY_INDEX(id);
2636
+
2637
+ if (!js_LookupProperty(cx, obj, id, &obj2, &prop))
2638
+ return JS_FALSE;
2639
+ if (!prop) {
2640
+ jsval default_val;
2641
+
2642
+ #if JS_BUG_NULL_INDEX_PROPS
2643
+ /* Indexed properties defaulted to null in old versions. */
2644
+ default_val = (JSVAL_IS_INT(id) && JSVAL_TO_INT(id) >= 0)
2645
+ ? JSVAL_NULL
2646
+ : JSVAL_VOID;
2647
+ #else
2648
+ default_val = JSVAL_VOID;
2649
+ #endif
2650
+ *vp = default_val;
2651
+
2652
+ if (!OBJ_GET_CLASS(cx, obj)->getProperty(cx, obj, ID_TO_VALUE(id), vp))
2653
+ return JS_FALSE;
2654
+
2655
+ /*
2656
+ * Give a strict warning if foo.bar is evaluated by a script for an
2657
+ * object foo with no property named 'bar'.
2658
+ */
2659
+ if (JS_HAS_STRICT_OPTION(cx) &&
2660
+ *vp == default_val &&
2661
+ cx->fp && cx->fp->pc &&
2662
+ (*cx->fp->pc == JSOP_GETPROP || *cx->fp->pc == JSOP_GETELEM))
2663
+ {
2664
+ jsbytecode *pc;
2665
+ JSString *str;
2666
+
2667
+ /* Kludge to allow (typeof foo == "undefined") tests. */
2668
+ JS_ASSERT(cx->fp->script);
2669
+ pc = cx->fp->pc;
2670
+ pc += js_CodeSpec[*pc].length;
2671
+ if (Detecting(cx, pc))
2672
+ return JS_TRUE;
2673
+
2674
+ /* Ok, bad undefined property reference: whine about it. */
2675
+ str = js_DecompileValueGenerator(cx, JSDVG_IGNORE_STACK,
2676
+ ID_TO_VALUE(id), NULL);
2677
+ if (!str ||
2678
+ !JS_ReportErrorFlagsAndNumber(cx,
2679
+ JSREPORT_WARNING|JSREPORT_STRICT,
2680
+ js_GetErrorMessage, NULL,
2681
+ JSMSG_UNDEFINED_PROP,
2682
+ JS_GetStringBytes(str))) {
2683
+ return JS_FALSE;
2684
+ }
2685
+ }
2686
+ return JS_TRUE;
2687
+ }
2688
+
2689
+ if (!OBJ_IS_NATIVE(obj2)) {
2690
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
2691
+ return OBJ_GET_PROPERTY(cx, obj2, id, vp);
2692
+ }
2693
+
2694
+ /* Unlock obj2 before calling getter, relock after to avoid deadlock. */
2695
+ scope = OBJ_SCOPE(obj2);
2696
+ sprop = (JSScopeProperty *) prop;
2697
+ slot = sprop->slot;
2698
+ if (slot != SPROP_INVALID_SLOT) {
2699
+ JS_ASSERT(slot < obj2->map->freeslot);
2700
+ *vp = LOCKED_OBJ_GET_SLOT(obj2, slot);
2701
+
2702
+ /* If sprop has a stub getter, we're done. */
2703
+ if (!sprop->getter)
2704
+ goto out;
2705
+ } else {
2706
+ *vp = JSVAL_VOID;
2707
+ }
2708
+
2709
+ JS_UNLOCK_SCOPE(cx, scope);
2710
+ if (!SPROP_GET(cx, sprop, obj, obj2, vp))
2711
+ return JS_FALSE;
2712
+ JS_LOCK_SCOPE(cx, scope);
2713
+
2714
+ if (SPROP_HAS_VALID_SLOT(sprop, scope)) {
2715
+ LOCKED_OBJ_SET_SLOT(obj2, slot, *vp);
2716
+ PROPERTY_CACHE_FILL(&cx->runtime->propertyCache, obj2, id, sprop);
2717
+ }
2718
+
2719
+ out:
2720
+ JS_UNLOCK_SCOPE(cx, scope);
2721
+ return JS_TRUE;
2722
+ }
2723
+
2724
+ JSBool
2725
+ js_SetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
2726
+ {
2727
+ JSObject *pobj;
2728
+ JSProperty *prop;
2729
+ JSScopeProperty *sprop;
2730
+ JSScope *scope;
2731
+ uintN attrs, flags;
2732
+ intN shortid;
2733
+ JSClass *clasp;
2734
+ JSPropertyOp getter, setter;
2735
+ jsval pval;
2736
+ uint32 slot;
2737
+
2738
+ /*
2739
+ * Handle old bug that took empty string as zero index. Also convert
2740
+ * string indices to integers if appropriate.
2741
+ */
2742
+ CHECK_FOR_FUNNY_INDEX(id);
2743
+
2744
+ if (!js_LookupProperty(cx, obj, id, &pobj, &prop))
2745
+ return JS_FALSE;
2746
+
2747
+ if (prop && !OBJ_IS_NATIVE(pobj)) {
2748
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
2749
+ prop = NULL;
2750
+ }
2751
+ sprop = (JSScopeProperty *) prop;
2752
+
2753
+ /*
2754
+ * Now either sprop is null, meaning id was not found in obj or one of its
2755
+ * prototypes; or sprop is non-null, meaning id was found in pobj's scope.
2756
+ * If JS_THREADSAFE and sprop is non-null, then scope is locked, and sprop
2757
+ * is held: we must OBJ_DROP_PROPERTY or JS_UNLOCK_SCOPE before we return
2758
+ * (the two are equivalent for native objects, but we use JS_UNLOCK_SCOPE
2759
+ * because it is cheaper).
2760
+ */
2761
+ attrs = JSPROP_ENUMERATE;
2762
+ flags = 0;
2763
+ shortid = 0;
2764
+ clasp = OBJ_GET_CLASS(cx, obj);
2765
+ getter = clasp->getProperty;
2766
+ setter = clasp->setProperty;
2767
+
2768
+ if (sprop) {
2769
+ /*
2770
+ * Set scope for use below. It was locked by js_LookupProperty, and
2771
+ * we know pobj owns it (i.e., scope->object == pobj). Therefore we
2772
+ * optimize JS_UNLOCK_OBJ(cx, pobj) into JS_UNLOCK_SCOPE(cx, scope).
2773
+ */
2774
+ scope = OBJ_SCOPE(pobj);
2775
+
2776
+ attrs = sprop->attrs;
2777
+ if ((attrs & JSPROP_READONLY) ||
2778
+ (SCOPE_IS_SEALED(scope) && pobj == obj)) {
2779
+ JS_UNLOCK_SCOPE(cx, scope);
2780
+ if ((attrs & JSPROP_READONLY) && JSVERSION_IS_ECMA(cx->version))
2781
+ return JS_TRUE;
2782
+ goto read_only_error;
2783
+ }
2784
+
2785
+ if (pobj != obj) {
2786
+ /*
2787
+ * We found id in a prototype object: prepare to share or shadow.
2788
+ * NB: Thanks to the immutable, garbage-collected property tree
2789
+ * maintained by jsscope.c in cx->runtime, we needn't worry about
2790
+ * sprop going away behind our back after we've unlocked scope.
2791
+ */
2792
+ JS_UNLOCK_SCOPE(cx, scope);
2793
+
2794
+ /* Don't clone a shared prototype property. */
2795
+ if (attrs & JSPROP_SHARED)
2796
+ return SPROP_SET(cx, sprop, obj, pobj, vp);
2797
+
2798
+ /* Restore attrs to the ECMA default for new properties. */
2799
+ attrs = JSPROP_ENUMERATE;
2800
+
2801
+ /*
2802
+ * Preserve the shortid, getter, and setter when shadowing any
2803
+ * property that has a shortid. An old API convention requires
2804
+ * that the property's getter and setter functions receive the
2805
+ * shortid, not id, when they are called on the shadow we are
2806
+ * about to create in obj's scope.
2807
+ */
2808
+ if (sprop->flags & SPROP_HAS_SHORTID) {
2809
+ flags = SPROP_HAS_SHORTID;
2810
+ shortid = sprop->shortid;
2811
+ getter = sprop->getter;
2812
+ setter = sprop->setter;
2813
+ }
2814
+
2815
+ /*
2816
+ * Forget we found the proto-property now that we've copied any
2817
+ * needed member values.
2818
+ */
2819
+ sprop = NULL;
2820
+ }
2821
+ #ifdef __GNUC__ /* suppress bogus gcc warnings */
2822
+ } else {
2823
+ scope = NULL;
2824
+ #endif
2825
+ }
2826
+
2827
+ if (!sprop) {
2828
+ if (SCOPE_IS_SEALED(OBJ_SCOPE(obj)) && OBJ_SCOPE(obj)->object == obj)
2829
+ goto read_only_error;
2830
+
2831
+ /* Find or make a property descriptor with the right heritage. */
2832
+ JS_LOCK_OBJ(cx, obj);
2833
+ scope = js_GetMutableScope(cx, obj);
2834
+ if (!scope) {
2835
+ JS_UNLOCK_OBJ(cx, obj);
2836
+ return JS_FALSE;
2837
+ }
2838
+ if (clasp->flags & JSCLASS_SHARE_ALL_PROPERTIES)
2839
+ attrs |= JSPROP_SHARED;
2840
+ sprop = js_AddScopeProperty(cx, scope, id, getter, setter,
2841
+ SPROP_INVALID_SLOT, attrs, flags, shortid);
2842
+ if (!sprop) {
2843
+ JS_UNLOCK_SCOPE(cx, scope);
2844
+ return JS_FALSE;
2845
+ }
2846
+
2847
+ /* XXXbe called with obj locked */
2848
+ if (!clasp->addProperty(cx, obj, SPROP_USERID(sprop), vp)) {
2849
+ (void) js_RemoveScopeProperty(cx, scope, id);
2850
+ JS_UNLOCK_SCOPE(cx, scope);
2851
+ return JS_FALSE;
2852
+ }
2853
+
2854
+ /* Initialize new property value (passed to setter) to undefined. */
2855
+ if (SPROP_HAS_VALID_SLOT(sprop, scope))
2856
+ LOCKED_OBJ_SET_SLOT(obj, sprop->slot, JSVAL_VOID);
2857
+
2858
+ PROPERTY_CACHE_FILL(&cx->runtime->propertyCache, obj, id, sprop);
2859
+ }
2860
+
2861
+ /* Get the current property value from its slot. */
2862
+ slot = sprop->slot;
2863
+ if (slot != SPROP_INVALID_SLOT) {
2864
+ JS_ASSERT(slot < obj->map->freeslot);
2865
+ pval = LOCKED_OBJ_GET_SLOT(obj, slot);
2866
+
2867
+ /* If sprop has a stub setter, keep scope locked and just store *vp. */
2868
+ if (!sprop->setter)
2869
+ goto set_slot;
2870
+ }
2871
+
2872
+ /* Avoid deadlock by unlocking obj's scope while calling sprop's setter. */
2873
+ JS_UNLOCK_SCOPE(cx, scope);
2874
+
2875
+ /* Let the setter modify vp before copying from it to obj->slots[slot]. */
2876
+ if (!SPROP_SET(cx, sprop, obj, obj, vp))
2877
+ return JS_FALSE;
2878
+
2879
+ /* Relock obj's scope until we are done with sprop. */
2880
+ JS_LOCK_SCOPE(cx, scope);
2881
+
2882
+ /*
2883
+ * Check whether sprop is still around (was not deleted), and whether it
2884
+ * has a slot (it may never have had one, or we may have lost a race with
2885
+ * someone who cleared scope).
2886
+ */
2887
+ if (SPROP_HAS_VALID_SLOT(sprop, scope)) {
2888
+ set_slot:
2889
+ GC_POKE(cx, pval);
2890
+ LOCKED_OBJ_SET_SLOT(obj, slot, *vp);
2891
+ }
2892
+ JS_UNLOCK_SCOPE(cx, scope);
2893
+ return JS_TRUE;
2894
+
2895
+ read_only_error: {
2896
+ JSString *str = js_DecompileValueGenerator(cx,
2897
+ JSDVG_IGNORE_STACK,
2898
+ ID_TO_VALUE(id),
2899
+ NULL);
2900
+ if (str) {
2901
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
2902
+ JSMSG_READ_ONLY,
2903
+ JS_GetStringBytes(str));
2904
+ }
2905
+ return JS_FALSE;
2906
+ }
2907
+ }
2908
+
2909
+ JSBool
2910
+ js_GetAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop,
2911
+ uintN *attrsp)
2912
+ {
2913
+ JSBool noprop, ok;
2914
+ JSScopeProperty *sprop;
2915
+
2916
+ noprop = !prop;
2917
+ if (noprop) {
2918
+ if (!js_LookupProperty(cx, obj, id, &obj, &prop))
2919
+ return JS_FALSE;
2920
+ if (!prop) {
2921
+ *attrsp = 0;
2922
+ return JS_TRUE;
2923
+ }
2924
+ if (!OBJ_IS_NATIVE(obj)) {
2925
+ ok = OBJ_GET_ATTRIBUTES(cx, obj, id, prop, attrsp);
2926
+ OBJ_DROP_PROPERTY(cx, obj, prop);
2927
+ return ok;
2928
+ }
2929
+ }
2930
+ sprop = (JSScopeProperty *)prop;
2931
+ *attrsp = sprop->attrs;
2932
+ if (noprop)
2933
+ OBJ_DROP_PROPERTY(cx, obj, prop);
2934
+ return JS_TRUE;
2935
+ }
2936
+
2937
+ JSBool
2938
+ js_SetAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop,
2939
+ uintN *attrsp)
2940
+ {
2941
+ JSBool noprop, ok;
2942
+ JSScopeProperty *sprop;
2943
+
2944
+ noprop = !prop;
2945
+ if (noprop) {
2946
+ if (!js_LookupProperty(cx, obj, id, &obj, &prop))
2947
+ return JS_FALSE;
2948
+ if (!prop)
2949
+ return JS_TRUE;
2950
+ if (!OBJ_IS_NATIVE(obj)) {
2951
+ ok = OBJ_SET_ATTRIBUTES(cx, obj, id, prop, attrsp);
2952
+ OBJ_DROP_PROPERTY(cx, obj, prop);
2953
+ return ok;
2954
+ }
2955
+ }
2956
+ sprop = (JSScopeProperty *)prop;
2957
+ sprop = js_ChangeNativePropertyAttrs(cx, obj, sprop,
2958
+ *attrsp &
2959
+ ~(JSPROP_GETTER | JSPROP_SETTER), 0,
2960
+ sprop->getter, sprop->setter);
2961
+ if (noprop)
2962
+ OBJ_DROP_PROPERTY(cx, obj, prop);
2963
+ return (sprop != NULL);
2964
+ }
2965
+
2966
+ JSBool
2967
+ js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *rval)
2968
+ {
2969
+ #if JS_HAS_PROP_DELETE
2970
+
2971
+ JSObject *proto;
2972
+ JSProperty *prop;
2973
+ JSScopeProperty *sprop;
2974
+ JSString *str;
2975
+ JSScope *scope;
2976
+ JSBool ok;
2977
+
2978
+ *rval = JSVERSION_IS_ECMA(cx->version) ? JSVAL_TRUE : JSVAL_VOID;
2979
+
2980
+ /*
2981
+ * Handle old bug that took empty string as zero index. Also convert
2982
+ * string indices to integers if appropriate.
2983
+ */
2984
+ CHECK_FOR_FUNNY_INDEX(id);
2985
+
2986
+ if (!js_LookupProperty(cx, obj, id, &proto, &prop))
2987
+ return JS_FALSE;
2988
+ if (!prop || proto != obj) {
2989
+ /*
2990
+ * If the property was found in a native prototype, check whether it's
2991
+ * shared and permanent. Such a property stands for direct properties
2992
+ * in all delegating objects, matching ECMA semantics without bloating
2993
+ * each delegating object.
2994
+ */
2995
+ if (prop) {
2996
+ if (OBJ_IS_NATIVE(proto)) {
2997
+ sprop = (JSScopeProperty *)prop;
2998
+ if (SPROP_IS_SHARED_PERMANENT(sprop))
2999
+ *rval = JSVAL_FALSE;
3000
+ }
3001
+ OBJ_DROP_PROPERTY(cx, proto, prop);
3002
+ if (*rval == JSVAL_FALSE)
3003
+ return JS_TRUE;
3004
+ }
3005
+
3006
+ /*
3007
+ * If no property, or the property comes unshared or impermanent from
3008
+ * a prototype, call the class's delProperty hook, passing rval as the
3009
+ * result parameter.
3010
+ */
3011
+ return OBJ_GET_CLASS(cx, obj)->delProperty(cx, obj, ID_TO_VALUE(id),
3012
+ rval);
3013
+ }
3014
+
3015
+ sprop = (JSScopeProperty *)prop;
3016
+ if (sprop->attrs & JSPROP_PERMANENT) {
3017
+ OBJ_DROP_PROPERTY(cx, obj, prop);
3018
+ if (JSVERSION_IS_ECMA(cx->version)) {
3019
+ *rval = JSVAL_FALSE;
3020
+ return JS_TRUE;
3021
+ }
3022
+ str = js_DecompileValueGenerator(cx, JSDVG_IGNORE_STACK,
3023
+ ID_TO_VALUE(id), NULL);
3024
+ if (str) {
3025
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
3026
+ JSMSG_PERMANENT, JS_GetStringBytes(str));
3027
+ }
3028
+ return JS_FALSE;
3029
+ }
3030
+
3031
+ /* XXXbe called with obj locked */
3032
+ if (!LOCKED_OBJ_GET_CLASS(obj)->delProperty(cx, obj, SPROP_USERID(sprop),
3033
+ rval)) {
3034
+ OBJ_DROP_PROPERTY(cx, obj, prop);
3035
+ return JS_FALSE;
3036
+ }
3037
+
3038
+ scope = OBJ_SCOPE(obj);
3039
+ if (SPROP_HAS_VALID_SLOT(sprop, scope))
3040
+ GC_POKE(cx, LOCKED_OBJ_GET_SLOT(obj, sprop->slot));
3041
+
3042
+ PROPERTY_CACHE_FILL(&cx->runtime->propertyCache, obj, id, NULL);
3043
+ ok = js_RemoveScopeProperty(cx, scope, id);
3044
+ OBJ_DROP_PROPERTY(cx, obj, prop);
3045
+ return ok;
3046
+
3047
+ #else /* !JS_HAS_PROP_DELETE */
3048
+
3049
+ jsval null = JSVAL_NULL;
3050
+
3051
+ *rval = JSVAL_VOID;
3052
+ return js_SetProperty(cx, obj, id, &null);
3053
+
3054
+ #endif /* !JS_HAS_PROP_DELETE */
3055
+ }
3056
+
3057
+ JSBool
3058
+ js_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp)
3059
+ {
3060
+ jsval v;
3061
+ JSString *str;
3062
+
3063
+ v = OBJECT_TO_JSVAL(obj);
3064
+ switch (hint) {
3065
+ case JSTYPE_STRING:
3066
+ /*
3067
+ * Propagate the exception if js_TryMethod finds an appropriate
3068
+ * method, and calling that method returned failure.
3069
+ */
3070
+ if (!js_TryMethod(cx, obj, cx->runtime->atomState.toStringAtom, 0, NULL,
3071
+ &v))
3072
+ return JS_FALSE;
3073
+
3074
+ if (!JSVAL_IS_PRIMITIVE(v)) {
3075
+ if (!OBJ_GET_CLASS(cx, obj)->convert(cx, obj, hint, &v))
3076
+ return JS_FALSE;
3077
+
3078
+ /*
3079
+ * JS1.2 never failed (except for malloc failure) to convert an
3080
+ * object to a string. ECMA requires an error if both toString
3081
+ * and valueOf fail to produce a primitive value.
3082
+ */
3083
+ if (!JSVAL_IS_PRIMITIVE(v) && cx->version == JSVERSION_1_2) {
3084
+ char *bytes = JS_smprintf("[object %s]",
3085
+ OBJ_GET_CLASS(cx, obj)->name);
3086
+ if (!bytes)
3087
+ return JS_FALSE;
3088
+ str = JS_NewString(cx, bytes, strlen(bytes));
3089
+ if (!str) {
3090
+ free(bytes);
3091
+ return JS_FALSE;
3092
+ }
3093
+ v = STRING_TO_JSVAL(str);
3094
+ goto out;
3095
+ }
3096
+ }
3097
+ break;
3098
+
3099
+ default:
3100
+ if (!OBJ_GET_CLASS(cx, obj)->convert(cx, obj, hint, &v))
3101
+ return JS_FALSE;
3102
+ if (!JSVAL_IS_PRIMITIVE(v)) {
3103
+ JSType type = JS_TypeOfValue(cx, v);
3104
+ if (type == hint ||
3105
+ (type == JSTYPE_FUNCTION && hint == JSTYPE_OBJECT)) {
3106
+ goto out;
3107
+ }
3108
+ /* Don't convert to string (source object literal) for JS1.2. */
3109
+ if (cx->version == JSVERSION_1_2 && hint == JSTYPE_BOOLEAN)
3110
+ goto out;
3111
+ if (!js_TryMethod(cx, obj, cx->runtime->atomState.toStringAtom, 0,
3112
+ NULL, &v))
3113
+ return JS_FALSE;
3114
+ }
3115
+ break;
3116
+ }
3117
+ if (!JSVAL_IS_PRIMITIVE(v)) {
3118
+ /* Avoid recursive death through js_DecompileValueGenerator. */
3119
+ if (hint == JSTYPE_STRING) {
3120
+ str = JS_InternString(cx, OBJ_GET_CLASS(cx, obj)->name);
3121
+ if (!str)
3122
+ return JS_FALSE;
3123
+ } else {
3124
+ str = NULL;
3125
+ }
3126
+ *vp = OBJECT_TO_JSVAL(obj);
3127
+ str = js_DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, v, str);
3128
+ if (str) {
3129
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
3130
+ JSMSG_CANT_CONVERT_TO,
3131
+ JS_GetStringBytes(str),
3132
+ (hint == JSTYPE_VOID)
3133
+ ? "primitive type"
3134
+ : js_type_str[hint]);
3135
+ }
3136
+ return JS_FALSE;
3137
+ }
3138
+ out:
3139
+ *vp = v;
3140
+ return JS_TRUE;
3141
+ }
3142
+
3143
+ JSIdArray *
3144
+ js_NewIdArray(JSContext *cx, jsint length)
3145
+ {
3146
+ JSIdArray *ida;
3147
+
3148
+ ida = (JSIdArray *)
3149
+ JS_malloc(cx, sizeof(JSIdArray) + (length - 1) * sizeof(jsval));
3150
+ if (ida)
3151
+ ida->length = length;
3152
+ return ida;
3153
+ }
3154
+
3155
+ JSIdArray *
3156
+ js_GrowIdArray(JSContext *cx, JSIdArray *ida, jsint length)
3157
+ {
3158
+ ida = (JSIdArray *)
3159
+ JS_realloc(cx, ida, sizeof(JSIdArray) + (length - 1) * sizeof(jsval));
3160
+ if (ida)
3161
+ ida->length = length;
3162
+ return ida;
3163
+ }
3164
+
3165
+ /* Private type used to iterate over all properties of a native JS object */
3166
+ typedef struct JSNativeIteratorState {
3167
+ jsint next_index; /* index into jsid array */
3168
+ JSIdArray *ida; /* All property ids in enumeration */
3169
+ } JSNativeIteratorState;
3170
+
3171
+ /*
3172
+ * This function is used to enumerate the properties of native JSObjects
3173
+ * and those host objects that do not define a JSNewEnumerateOp-style iterator
3174
+ * function.
3175
+ */
3176
+ JSBool
3177
+ js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
3178
+ jsval *statep, jsid *idp)
3179
+ {
3180
+ JSObject *proto_obj;
3181
+ JSClass *clasp;
3182
+ JSEnumerateOp enumerate;
3183
+ JSScopeProperty *sprop, *lastProp;
3184
+ jsint i, length;
3185
+ JSScope *scope;
3186
+ JSIdArray *ida;
3187
+ JSNativeIteratorState *state;
3188
+
3189
+ clasp = OBJ_GET_CLASS(cx, obj);
3190
+ enumerate = clasp->enumerate;
3191
+ if (clasp->flags & JSCLASS_NEW_ENUMERATE)
3192
+ return ((JSNewEnumerateOp) enumerate)(cx, obj, enum_op, statep, idp);
3193
+
3194
+ switch (enum_op) {
3195
+
3196
+ case JSENUMERATE_INIT:
3197
+ if (!enumerate(cx, obj))
3198
+ goto init_error;
3199
+ length = 0;
3200
+
3201
+ /*
3202
+ * The set of all property ids is pre-computed when the iterator
3203
+ * is initialized so as to avoid problems with properties being
3204
+ * deleted during the iteration.
3205
+ */
3206
+ JS_LOCK_OBJ(cx, obj);
3207
+ scope = OBJ_SCOPE(obj);
3208
+
3209
+ /*
3210
+ * If this object shares a scope with its prototype, don't enumerate
3211
+ * its properties. Otherwise they will be enumerated a second time
3212
+ * when the prototype object is enumerated.
3213
+ */
3214
+ proto_obj = OBJ_GET_PROTO(cx, obj);
3215
+ if (proto_obj && scope == OBJ_SCOPE(proto_obj)) {
3216
+ ida = js_NewIdArray(cx, 0);
3217
+ if (!ida) {
3218
+ JS_UNLOCK_OBJ(cx, obj);
3219
+ goto init_error;
3220
+ }
3221
+ } else {
3222
+ /* Object has a private scope; Enumerate all props in scope. */
3223
+ for (sprop = lastProp = SCOPE_LAST_PROP(scope); sprop;
3224
+ sprop = sprop->parent) {
3225
+ if ((
3226
+ #ifdef DUMP_CALL_TABLE
3227
+ (cx->options & JSOPTION_LOGCALL_TOSOURCE) ||
3228
+ #endif
3229
+ (sprop->attrs & JSPROP_ENUMERATE)) &&
3230
+ !(sprop->flags & SPROP_IS_ALIAS) &&
3231
+ (!SCOPE_HAD_MIDDLE_DELETE(scope) ||
3232
+ SCOPE_HAS_PROPERTY(scope, sprop))) {
3233
+ length++;
3234
+ }
3235
+ }
3236
+ ida = js_NewIdArray(cx, length);
3237
+ if (!ida) {
3238
+ JS_UNLOCK_OBJ(cx, obj);
3239
+ goto init_error;
3240
+ }
3241
+ i = length;
3242
+ for (sprop = lastProp; sprop; sprop = sprop->parent) {
3243
+ if ((
3244
+ #ifdef DUMP_CALL_TABLE
3245
+ (cx->options & JSOPTION_LOGCALL_TOSOURCE) ||
3246
+ #endif
3247
+ (sprop->attrs & JSPROP_ENUMERATE)) &&
3248
+ !(sprop->flags & SPROP_IS_ALIAS) &&
3249
+ (!SCOPE_HAD_MIDDLE_DELETE(scope) ||
3250
+ SCOPE_HAS_PROPERTY(scope, sprop))) {
3251
+ JS_ASSERT(i > 0);
3252
+ ida->vector[--i] = sprop->id;
3253
+ }
3254
+ }
3255
+ }
3256
+ JS_UNLOCK_OBJ(cx, obj);
3257
+
3258
+ state = (JSNativeIteratorState *)
3259
+ JS_malloc(cx, sizeof(JSNativeIteratorState));
3260
+ if (!state) {
3261
+ JS_DestroyIdArray(cx, ida);
3262
+ goto init_error;
3263
+ }
3264
+ state->ida = ida;
3265
+ state->next_index = 0;
3266
+ *statep = PRIVATE_TO_JSVAL(state);
3267
+ if (idp)
3268
+ *idp = INT_TO_JSVAL(length);
3269
+ return JS_TRUE;
3270
+
3271
+ case JSENUMERATE_NEXT:
3272
+ state = (JSNativeIteratorState *) JSVAL_TO_PRIVATE(*statep);
3273
+ ida = state->ida;
3274
+ length = ida->length;
3275
+ if (state->next_index != length) {
3276
+ *idp = ida->vector[state->next_index++];
3277
+ return JS_TRUE;
3278
+ }
3279
+
3280
+ /* Fall through ... */
3281
+
3282
+ case JSENUMERATE_DESTROY:
3283
+ state = (JSNativeIteratorState *) JSVAL_TO_PRIVATE(*statep);
3284
+ JS_DestroyIdArray(cx, state->ida);
3285
+ JS_free(cx, state);
3286
+ *statep = JSVAL_NULL;
3287
+ return JS_TRUE;
3288
+
3289
+ default:
3290
+ JS_ASSERT(0);
3291
+ return JS_FALSE;
3292
+ }
3293
+
3294
+ init_error:
3295
+ *statep = JSVAL_NULL;
3296
+ return JS_FALSE;
3297
+ }
3298
+
3299
+ JSBool
3300
+ js_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
3301
+ jsval *vp, uintN *attrsp)
3302
+ {
3303
+ JSObject *pobj;
3304
+ JSProperty *prop;
3305
+ JSScopeProperty *sprop;
3306
+ JSClass *clasp;
3307
+ JSBool ok;
3308
+
3309
+ if (!js_LookupProperty(cx, obj, id, &pobj, &prop))
3310
+ return JS_FALSE;
3311
+ if (!prop) {
3312
+ *vp = JSVAL_VOID;
3313
+ *attrsp = 0;
3314
+ clasp = OBJ_GET_CLASS(cx, obj);
3315
+ return !clasp->checkAccess ||
3316
+ clasp->checkAccess(cx, obj, ID_TO_VALUE(id), mode, vp);
3317
+ }
3318
+ if (!OBJ_IS_NATIVE(pobj)) {
3319
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
3320
+ return OBJ_CHECK_ACCESS(cx, pobj, id, mode, vp, attrsp);
3321
+ }
3322
+ sprop = (JSScopeProperty *)prop;
3323
+ *vp = (SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(pobj)))
3324
+ ? LOCKED_OBJ_GET_SLOT(pobj, sprop->slot)
3325
+ : JSVAL_VOID;
3326
+ *attrsp = sprop->attrs;
3327
+ clasp = LOCKED_OBJ_GET_CLASS(obj);
3328
+ if (clasp->checkAccess) {
3329
+ JS_UNLOCK_OBJ(cx, pobj);
3330
+ ok = clasp->checkAccess(cx, obj, ID_TO_VALUE(id), mode, vp);
3331
+ JS_LOCK_OBJ(cx, pobj);
3332
+ } else {
3333
+ ok = JS_TRUE;
3334
+ }
3335
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
3336
+ return ok;
3337
+ }
3338
+
3339
+ #ifdef JS_THREADSAFE
3340
+ void
3341
+ js_DropProperty(JSContext *cx, JSObject *obj, JSProperty *prop)
3342
+ {
3343
+ JS_UNLOCK_OBJ(cx, obj);
3344
+ }
3345
+ #endif
3346
+
3347
+ static void
3348
+ ReportIsNotFunction(JSContext *cx, jsval *vp, uintN flags)
3349
+ {
3350
+ /*
3351
+ * The decompiler may need to access the args of the function in
3352
+ * progress rather than the one we had hoped to call.
3353
+ * So we switch the cx->fp to the frame below us. We stick the
3354
+ * current frame in the dormantFrameChain to protect it from gc.
3355
+ */
3356
+
3357
+ JSStackFrame *fp = cx->fp;
3358
+ if (fp->down) {
3359
+ JS_ASSERT(!fp->dormantNext);
3360
+ fp->dormantNext = cx->dormantFrameChain;
3361
+ cx->dormantFrameChain = fp;
3362
+ cx->fp = fp->down;
3363
+ }
3364
+
3365
+ js_ReportIsNotFunction(cx, vp, flags);
3366
+
3367
+ if (fp->down) {
3368
+ JS_ASSERT(cx->dormantFrameChain == fp);
3369
+ cx->dormantFrameChain = fp->dormantNext;
3370
+ fp->dormantNext = NULL;
3371
+ cx->fp = fp;
3372
+ }
3373
+ }
3374
+
3375
+ #ifdef NARCISSUS
3376
+ static JSBool
3377
+ GetCurrentExecutionContext(JSContext *cx, JSObject *obj, jsval *rval)
3378
+ {
3379
+ JSObject *tmp;
3380
+ jsval xcval;
3381
+
3382
+ while ((tmp = OBJ_GET_PARENT(cx, obj)) != NULL)
3383
+ obj = tmp;
3384
+ if (!OBJ_GET_PROPERTY(cx, obj,
3385
+ (jsid)cx->runtime->atomState.ExecutionContextAtom,
3386
+ &xcval)) {
3387
+ return JS_FALSE;
3388
+ }
3389
+ if (JSVAL_IS_PRIMITIVE(xcval)) {
3390
+ JS_ReportError(cx, "invalid ExecutionContext in global object");
3391
+ return JS_FALSE;
3392
+ }
3393
+ if (!OBJ_GET_PROPERTY(cx, JSVAL_TO_OBJECT(xcval),
3394
+ (jsid)cx->runtime->atomState.currentAtom,
3395
+ rval)) {
3396
+ return JS_FALSE;
3397
+ }
3398
+ return JS_TRUE;
3399
+ }
3400
+ #endif
3401
+
3402
+ JSBool
3403
+ js_Call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
3404
+ {
3405
+ JSClass *clasp;
3406
+
3407
+ clasp = OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(argv[-2]));
3408
+ if (!clasp->call) {
3409
+ #ifdef NARCISSUS
3410
+ JSObject *callee, *args;
3411
+ jsval fval, nargv[3];
3412
+ JSBool ok;
3413
+
3414
+ callee = JSVAL_TO_OBJECT(argv[-2]);
3415
+ if (!OBJ_GET_PROPERTY(cx, callee,
3416
+ (jsid)cx->runtime->atomState.callAtom,
3417
+ &fval)) {
3418
+ return JS_FALSE;
3419
+ }
3420
+ if (JSVAL_IS_FUNCTION(cx, fval)) {
3421
+ if (!GetCurrentExecutionContext(cx, obj, &nargv[2]))
3422
+ return JS_FALSE;
3423
+ args = js_GetArgsObject(cx, cx->fp);
3424
+ if (!args)
3425
+ return JS_FALSE;
3426
+ nargv[0] = OBJECT_TO_JSVAL(obj);
3427
+ nargv[1] = OBJECT_TO_JSVAL(args);
3428
+ return js_InternalCall(cx, callee, fval, 3, nargv, rval);
3429
+ }
3430
+ if (JSVAL_IS_OBJECT(fval) && JSVAL_TO_OBJECT(fval) != callee) {
3431
+ argv[-2] = fval;
3432
+ ok = js_Call(cx, obj, argc, argv, rval);
3433
+ argv[-2] = OBJECT_TO_JSVAL(callee);
3434
+ return ok;
3435
+ }
3436
+ #endif
3437
+ ReportIsNotFunction(cx, &argv[-2], 0);
3438
+ return JS_FALSE;
3439
+ }
3440
+ return clasp->call(cx, obj, argc, argv, rval);
3441
+ }
3442
+
3443
+ JSBool
3444
+ js_Construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
3445
+ jsval *rval)
3446
+ {
3447
+ JSClass *clasp;
3448
+
3449
+ clasp = OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(argv[-2]));
3450
+ if (!clasp->construct) {
3451
+ #ifdef NARCISSUS
3452
+ JSObject *callee, *args;
3453
+ jsval cval, nargv[2];
3454
+ JSBool ok;
3455
+
3456
+ callee = JSVAL_TO_OBJECT(argv[-2]);
3457
+ if (!OBJ_GET_PROPERTY(cx, callee,
3458
+ (jsid)cx->runtime->atomState.constructAtom,
3459
+ &cval)) {
3460
+ return JS_FALSE;
3461
+ }
3462
+ if (JSVAL_IS_FUNCTION(cx, cval)) {
3463
+ if (!GetCurrentExecutionContext(cx, obj, &nargv[1]))
3464
+ return JS_FALSE;
3465
+ args = js_GetArgsObject(cx, cx->fp);
3466
+ if (!args)
3467
+ return JS_FALSE;
3468
+ nargv[0] = OBJECT_TO_JSVAL(args);
3469
+ return js_InternalCall(cx, callee, cval, 2, nargv, rval);
3470
+ }
3471
+ if (JSVAL_IS_OBJECT(cval) && JSVAL_TO_OBJECT(cval) != callee) {
3472
+ argv[-2] = cval;
3473
+ ok = js_Call(cx, obj, argc, argv, rval);
3474
+ argv[-2] = OBJECT_TO_JSVAL(callee);
3475
+ return ok;
3476
+ }
3477
+ #endif
3478
+ ReportIsNotFunction(cx, &argv[-2], JSV2F_CONSTRUCT);
3479
+ return JS_FALSE;
3480
+ }
3481
+ return clasp->construct(cx, obj, argc, argv, rval);
3482
+ }
3483
+
3484
+ JSBool
3485
+ js_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
3486
+ {
3487
+ JSClass *clasp;
3488
+
3489
+ clasp = OBJ_GET_CLASS(cx, obj);
3490
+ if (clasp->hasInstance)
3491
+ return clasp->hasInstance(cx, obj, v, bp);
3492
+ #ifdef NARCISSUS
3493
+ {
3494
+ jsval fval, rval;
3495
+
3496
+ if (!OBJ_GET_PROPERTY(cx, obj,
3497
+ (jsid)cx->runtime->atomState.hasInstanceAtom,
3498
+ &fval)) {
3499
+ return JS_FALSE;
3500
+ }
3501
+ if (JSVAL_IS_FUNCTION(cx, fval)) {
3502
+ return js_InternalCall(cx, obj, fval, 1, &v, &rval) &&
3503
+ js_ValueToBoolean(cx, rval, bp);
3504
+ }
3505
+ }
3506
+ #endif
3507
+ *bp = JS_FALSE;
3508
+ return JS_TRUE;
3509
+ }
3510
+
3511
+ JSBool
3512
+ js_IsDelegate(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
3513
+ {
3514
+ JSObject *obj2;
3515
+
3516
+ *bp = JS_FALSE;
3517
+ if (JSVAL_IS_PRIMITIVE(v))
3518
+ return JS_TRUE;
3519
+ obj2 = JSVAL_TO_OBJECT(v);
3520
+ while ((obj2 = OBJ_GET_PROTO(cx, obj2)) != NULL) {
3521
+ if (obj2 == obj) {
3522
+ *bp = JS_TRUE;
3523
+ break;
3524
+ }
3525
+ }
3526
+ return JS_TRUE;
3527
+ }
3528
+
3529
+ JSBool
3530
+ js_GetClassPrototype(JSContext *cx, const char *name, JSObject **protop)
3531
+ {
3532
+ return GetClassPrototype(cx, NULL, name, protop);
3533
+ }
3534
+
3535
+ static JSBool
3536
+ GetClassPrototype(JSContext *cx, JSObject *scope, const char *name,
3537
+ JSObject **protop)
3538
+ {
3539
+ jsval v;
3540
+ JSObject *ctor;
3541
+
3542
+ if (!FindConstructor(cx, scope, name, &v))
3543
+ return JS_FALSE;
3544
+ if (JSVAL_IS_FUNCTION(cx, v)) {
3545
+ ctor = JSVAL_TO_OBJECT(v);
3546
+ if (!OBJ_GET_PROPERTY(cx, ctor,
3547
+ (jsid)cx->runtime->atomState.classPrototypeAtom,
3548
+ &v)) {
3549
+ return JS_FALSE;
3550
+ }
3551
+ }
3552
+ *protop = JSVAL_IS_OBJECT(v) ? JSVAL_TO_OBJECT(v) : NULL;
3553
+ return JS_TRUE;
3554
+ }
3555
+
3556
+ JSBool
3557
+ js_SetClassPrototype(JSContext *cx, JSObject *ctor, JSObject *proto,
3558
+ uintN attrs)
3559
+ {
3560
+ /*
3561
+ * Use the given attributes for the prototype property of the constructor,
3562
+ * as user-defined constructors have a DontDelete prototype (which may be
3563
+ * reset), while native or "system" constructors have DontEnum | ReadOnly |
3564
+ * DontDelete.
3565
+ */
3566
+ if (!OBJ_DEFINE_PROPERTY(cx, ctor,
3567
+ (jsid)cx->runtime->atomState.classPrototypeAtom,
3568
+ OBJECT_TO_JSVAL(proto), NULL, NULL,
3569
+ attrs, NULL)) {
3570
+ return JS_FALSE;
3571
+ }
3572
+
3573
+ /*
3574
+ * ECMA says that Object.prototype.constructor, or f.prototype.constructor
3575
+ * for a user-defined function f, is DontEnum.
3576
+ */
3577
+ return OBJ_DEFINE_PROPERTY(cx, proto,
3578
+ (jsid)cx->runtime->atomState.constructorAtom,
3579
+ OBJECT_TO_JSVAL(ctor), NULL, NULL,
3580
+ 0, NULL);
3581
+ }
3582
+
3583
+ JSBool
3584
+ js_ValueToObject(JSContext *cx, jsval v, JSObject **objp)
3585
+ {
3586
+ JSObject *obj;
3587
+
3588
+ if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v)) {
3589
+ obj = NULL;
3590
+ } else if (JSVAL_IS_OBJECT(v)) {
3591
+ obj = JSVAL_TO_OBJECT(v);
3592
+ if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_OBJECT, &v))
3593
+ return JS_FALSE;
3594
+ if (JSVAL_IS_OBJECT(v))
3595
+ obj = JSVAL_TO_OBJECT(v);
3596
+ } else {
3597
+ if (JSVAL_IS_STRING(v)) {
3598
+ obj = js_StringToObject(cx, JSVAL_TO_STRING(v));
3599
+ } else if (JSVAL_IS_INT(v)) {
3600
+ obj = js_NumberToObject(cx, (jsdouble)JSVAL_TO_INT(v));
3601
+ } else if (JSVAL_IS_DOUBLE(v)) {
3602
+ obj = js_NumberToObject(cx, *JSVAL_TO_DOUBLE(v));
3603
+ } else {
3604
+ JS_ASSERT(JSVAL_IS_BOOLEAN(v));
3605
+ obj = js_BooleanToObject(cx, JSVAL_TO_BOOLEAN(v));
3606
+ }
3607
+ if (!obj)
3608
+ return JS_FALSE;
3609
+ }
3610
+ *objp = obj;
3611
+ return JS_TRUE;
3612
+ }
3613
+
3614
+ JSObject *
3615
+ js_ValueToNonNullObject(JSContext *cx, jsval v)
3616
+ {
3617
+ JSObject *obj;
3618
+ JSString *str;
3619
+
3620
+ if (!js_ValueToObject(cx, v, &obj))
3621
+ return NULL;
3622
+ if (!obj) {
3623
+ str = js_DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, v, NULL);
3624
+ if (str) {
3625
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
3626
+ JSMSG_NO_PROPERTIES, JS_GetStringBytes(str));
3627
+ }
3628
+ }
3629
+ return obj;
3630
+ }
3631
+
3632
+ JSBool
3633
+ js_TryValueOf(JSContext *cx, JSObject *obj, JSType type, jsval *rval)
3634
+ {
3635
+ #if JS_HAS_VALUEOF_HINT
3636
+ jsval argv[1];
3637
+
3638
+ argv[0] = ATOM_KEY(cx->runtime->atomState.typeAtoms[type]);
3639
+ return js_TryMethod(cx, obj, cx->runtime->atomState.valueOfAtom, 1, argv,
3640
+ rval);
3641
+ #else
3642
+ return js_TryMethod(cx, obj, cx->runtime->atomState.valueOfAtom, 0, NULL,
3643
+ rval);
3644
+ #endif
3645
+ }
3646
+
3647
+ JSBool
3648
+ js_TryMethod(JSContext *cx, JSObject *obj, JSAtom *atom,
3649
+ uintN argc, jsval *argv, jsval *rval)
3650
+ {
3651
+ JSErrorReporter older;
3652
+ jsval fval;
3653
+ JSBool ok;
3654
+
3655
+ /*
3656
+ * Report failure only if an appropriate method was found, and calling it
3657
+ * returned failure. We propagate failure in this case to make exceptions
3658
+ * behave properly.
3659
+ */
3660
+ older = JS_SetErrorReporter(cx, NULL);
3661
+ if (!OBJ_GET_PROPERTY(cx, obj, (jsid)atom, &fval)) {
3662
+ JS_ClearPendingException(cx);
3663
+ ok = JS_TRUE;
3664
+ } else if (!JSVAL_IS_PRIMITIVE(fval)) {
3665
+ ok = js_InternalCall(cx, obj, fval, argc, argv, rval);
3666
+ if (!ok)
3667
+ JS_ClearPendingException(cx);
3668
+ } else {
3669
+ ok = JS_TRUE;
3670
+ }
3671
+ JS_SetErrorReporter(cx, older);
3672
+ return ok;
3673
+ }
3674
+
3675
+ #if JS_HAS_XDR
3676
+
3677
+ #include "jsxdrapi.h"
3678
+
3679
+ JSBool
3680
+ js_XDRObject(JSXDRState *xdr, JSObject **objp)
3681
+ {
3682
+ JSContext *cx;
3683
+ JSClass *clasp;
3684
+ const char *className;
3685
+ uint32 classId, classDef;
3686
+ JSBool ok;
3687
+ JSObject *proto;
3688
+
3689
+ cx = xdr->cx;
3690
+ if (xdr->mode == JSXDR_ENCODE) {
3691
+ clasp = OBJ_GET_CLASS(cx, *objp);
3692
+ className = clasp->name;
3693
+ classId = JS_XDRFindClassIdByName(xdr, className);
3694
+ classDef = !classId;
3695
+ if (classDef && !JS_XDRRegisterClass(xdr, clasp, &classId))
3696
+ return JS_FALSE;
3697
+ } else {
3698
+ classDef = 0;
3699
+ className = NULL;
3700
+ clasp = NULL; /* quell GCC overwarning */
3701
+ }
3702
+
3703
+ /* XDR a flag word followed (if true) by the class name. */
3704
+ if (!JS_XDRUint32(xdr, &classDef))
3705
+ return JS_FALSE;
3706
+ if (classDef && !JS_XDRCString(xdr, (char **) &className))
3707
+ return JS_FALSE;
3708
+
3709
+ /* From here on, return through out: to free className if it was set. */
3710
+ ok = JS_XDRUint32(xdr, &classId);
3711
+ if (!ok)
3712
+ goto out;
3713
+
3714
+ if (xdr->mode != JSXDR_ENCODE) {
3715
+ if (classDef) {
3716
+ ok = js_GetClassPrototype(cx, className, &proto);
3717
+ if (!ok)
3718
+ goto out;
3719
+ clasp = OBJ_GET_CLASS(cx, proto);
3720
+ ok = JS_XDRRegisterClass(xdr, clasp, &classId);
3721
+ if (!ok)
3722
+ goto out;
3723
+ } else {
3724
+ clasp = JS_XDRFindClassById(xdr, classId);
3725
+ if (!clasp) {
3726
+ char numBuf[12];
3727
+ JS_snprintf(numBuf, sizeof numBuf, "%ld", (long)classId);
3728
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
3729
+ JSMSG_CANT_FIND_CLASS, numBuf);
3730
+ ok = JS_FALSE;
3731
+ goto out;
3732
+ }
3733
+ }
3734
+ }
3735
+
3736
+ if (!clasp->xdrObject) {
3737
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
3738
+ JSMSG_CANT_XDR_CLASS, clasp->name);
3739
+ ok = JS_FALSE;
3740
+ } else {
3741
+ ok = clasp->xdrObject(xdr, objp);
3742
+ }
3743
+ out:
3744
+ if (xdr->mode != JSXDR_ENCODE && className)
3745
+ JS_free(cx, (void *)className);
3746
+ return ok;
3747
+ }
3748
+
3749
+ #endif /* JS_HAS_XDR */
3750
+
3751
+ #ifdef DEBUG_brendan
3752
+
3753
+ #include <stdio.h>
3754
+ #include <math.h>
3755
+
3756
+ uint32 js_entry_count_max;
3757
+ uint32 js_entry_count_sum;
3758
+ double js_entry_count_sqsum;
3759
+ uint32 js_entry_count_hist[11];
3760
+
3761
+ static void
3762
+ MeterEntryCount(uintN count)
3763
+ {
3764
+ if (count) {
3765
+ js_entry_count_sum += count;
3766
+ js_entry_count_sqsum += (double)count * count;
3767
+ if (count > js_entry_count_max)
3768
+ js_entry_count_max = count;
3769
+ }
3770
+ js_entry_count_hist[JS_MIN(count, 10)]++;
3771
+ }
3772
+
3773
+ void
3774
+ js_DumpScopeMeters(JSRuntime *rt)
3775
+ {
3776
+ static FILE *logfp;
3777
+ if (!logfp)
3778
+ logfp = fopen("/tmp/scope.stats", "a");
3779
+
3780
+ {
3781
+ double mean = 0., var = 0., sigma = 0.;
3782
+ double nscopes = rt->liveScopes;
3783
+ double nentrys = js_entry_count_sum;
3784
+ if (nscopes > 0 && nentrys >= 0) {
3785
+ mean = nentrys / nscopes;
3786
+ var = nscopes * js_entry_count_sqsum - nentrys * nentrys;
3787
+ if (var < 0.0 || nscopes <= 1)
3788
+ var = 0.0;
3789
+ else
3790
+ var /= nscopes * (nscopes - 1);
3791
+
3792
+ /* Windows says sqrt(0.0) is "-1.#J" (?!) so we must test. */
3793
+ sigma = (var != 0.) ? sqrt(var) : 0.;
3794
+ }
3795
+
3796
+ fprintf(logfp,
3797
+ "scopes %g entries %g mean %g sigma %g max %u",
3798
+ nscopes, nentrys, mean, sigma, js_entry_count_max);
3799
+ }
3800
+
3801
+ fprintf(logfp, " histogram %u %u %u %u %u %u %u %u %u %u %u\n",
3802
+ js_entry_count_hist[0], js_entry_count_hist[1],
3803
+ js_entry_count_hist[2], js_entry_count_hist[3],
3804
+ js_entry_count_hist[4], js_entry_count_hist[5],
3805
+ js_entry_count_hist[6], js_entry_count_hist[7],
3806
+ js_entry_count_hist[8], js_entry_count_hist[9],
3807
+ js_entry_count_hist[10]);
3808
+ js_entry_count_sum = js_entry_count_max = 0;
3809
+ js_entry_count_sqsum = 0;
3810
+ memset(js_entry_count_hist, 0, sizeof js_entry_count_hist);
3811
+ fflush(logfp);
3812
+ }
3813
+
3814
+ #endif /* DEBUG_brendan */
3815
+
3816
+ uint32
3817
+ js_Mark(JSContext *cx, JSObject *obj, void *arg)
3818
+ {
3819
+ JSScope *scope;
3820
+ JSScopeProperty *sprop;
3821
+ JSClass *clasp;
3822
+
3823
+ JS_ASSERT(OBJ_IS_NATIVE(obj));
3824
+ scope = OBJ_SCOPE(obj);
3825
+ #ifdef DEBUG_brendan
3826
+ if (scope->object == obj)
3827
+ MeterEntryCount(scope->entryCount);
3828
+ #endif
3829
+
3830
+ JS_ASSERT(!SCOPE_LAST_PROP(scope) ||
3831
+ SCOPE_HAS_PROPERTY(scope, SCOPE_LAST_PROP(scope)));
3832
+
3833
+ for (sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent) {
3834
+ if (SCOPE_HAD_MIDDLE_DELETE(scope) && !SCOPE_HAS_PROPERTY(scope, sprop))
3835
+ continue;
3836
+ MARK_SCOPE_PROPERTY(sprop);
3837
+ if (!JSVAL_IS_INT(sprop->id))
3838
+ GC_MARK_ATOM(cx, (JSAtom *)sprop->id, arg);
3839
+
3840
+ #if JS_HAS_GETTER_SETTER
3841
+ if (sprop->attrs & (JSPROP_GETTER | JSPROP_SETTER)) {
3842
+ #ifdef GC_MARK_DEBUG
3843
+ char buf[64];
3844
+ JSAtom *atom = (JSAtom *)sprop->id;
3845
+ const char *id = (atom && ATOM_IS_STRING(atom))
3846
+ ? JS_GetStringBytes(ATOM_TO_STRING(atom))
3847
+ : "unknown";
3848
+ #endif
3849
+
3850
+ if (sprop->attrs & JSPROP_GETTER) {
3851
+ #ifdef GC_MARK_DEBUG
3852
+ JS_snprintf(buf, sizeof buf, "%s %s",
3853
+ id, js_getter_str);
3854
+ #endif
3855
+ GC_MARK(cx,
3856
+ JSVAL_TO_GCTHING((jsval) sprop->getter),
3857
+ buf,
3858
+ arg);
3859
+ }
3860
+ if (sprop->attrs & JSPROP_SETTER) {
3861
+ #ifdef GC_MARK_DEBUG
3862
+ JS_snprintf(buf, sizeof buf, "%s %s",
3863
+ id, js_setter_str);
3864
+ #endif
3865
+ GC_MARK(cx,
3866
+ JSVAL_TO_GCTHING((jsval) sprop->setter),
3867
+ buf,
3868
+ arg);
3869
+ }
3870
+ }
3871
+ #endif /* JS_HAS_GETTER_SETTER */
3872
+ }
3873
+
3874
+ /* No one runs while the GC is running, so we can use LOCKED_... here. */
3875
+ clasp = LOCKED_OBJ_GET_CLASS(obj);
3876
+ if (clasp->mark)
3877
+ (void) clasp->mark(cx, obj, arg);
3878
+
3879
+ if (scope->object != obj) {
3880
+ /*
3881
+ * An unmutated object that shares a prototype's scope. We can't tell
3882
+ * how many slots are allocated and in use at obj->slots by looking at
3883
+ * scope, so we get obj->slots' length from its -1'st element.
3884
+ */
3885
+ return (uint32) obj->slots[-1];
3886
+ }
3887
+ return JS_MIN(scope->map.freeslot, scope->map.nslots);
3888
+ }
3889
+
3890
+ void
3891
+ js_Clear(JSContext *cx, JSObject *obj)
3892
+ {
3893
+ JSScope *scope;
3894
+ JSRuntime *rt;
3895
+ JSScopeProperty *sprop;
3896
+ uint32 i, n;
3897
+
3898
+ /*
3899
+ * Clear our scope and the property cache of all obj's properties only if
3900
+ * obj owns the scope (i.e., not if obj is unmutated and therefore sharing
3901
+ * its prototype's scope). NB: we do not clear any reserved slots lying
3902
+ * below JSSLOT_FREE(clasp).
3903
+ */
3904
+ JS_LOCK_OBJ(cx, obj);
3905
+ scope = OBJ_SCOPE(obj);
3906
+ if (scope->object == obj) {
3907
+ /* Clear the property cache before we clear the scope. */
3908
+ rt = cx->runtime;
3909
+ for (sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent) {
3910
+ if (!SCOPE_HAD_MIDDLE_DELETE(scope) ||
3911
+ SCOPE_HAS_PROPERTY(scope, sprop)) {
3912
+ PROPERTY_CACHE_FILL(&rt->propertyCache, obj, sprop->id, NULL);
3913
+ }
3914
+ }
3915
+
3916
+ /* Now that we're done using scope->lastProp/table, clear scope. */
3917
+ js_ClearScope(cx, scope);
3918
+
3919
+ /* Clear slot values and reset freeslot so we're consistent. */
3920
+ i = scope->map.nslots;
3921
+ n = JSSLOT_FREE(LOCKED_OBJ_GET_CLASS(obj));
3922
+ while (--i >= n)
3923
+ obj->slots[i] = JSVAL_VOID;
3924
+ scope->map.freeslot = n;
3925
+ }
3926
+ JS_UNLOCK_OBJ(cx, obj);
3927
+ }
3928
+
3929
+ jsval
3930
+ js_GetRequiredSlot(JSContext *cx, JSObject *obj, uint32 slot)
3931
+ {
3932
+ jsval v;
3933
+
3934
+ JS_LOCK_OBJ(cx, obj);
3935
+ v = (slot < (uint32) obj->slots[-1]) ? obj->slots[slot] : JSVAL_VOID;
3936
+ JS_UNLOCK_OBJ(cx, obj);
3937
+ return v;
3938
+ }
3939
+
3940
+ JSBool
3941
+ js_SetRequiredSlot(JSContext *cx, JSObject *obj, uint32 slot, jsval v)
3942
+ {
3943
+ JSScope *scope;
3944
+ uint32 nslots, i;
3945
+ JSClass *clasp;
3946
+ jsval *newslots;
3947
+
3948
+ JS_LOCK_OBJ(cx, obj);
3949
+ scope = OBJ_SCOPE(obj);
3950
+ nslots = (uint32) obj->slots[-1];
3951
+ if (slot >= nslots) {
3952
+ /*
3953
+ * At this point, obj may or may not own scope. If some path calls
3954
+ * js_GetMutableScope but does not add a slot-owning property, then
3955
+ * scope->object == obj but nslots will be nominal. If obj shares a
3956
+ * prototype's scope, then we cannot update scope->map here, but we
3957
+ * must update obj->slots[-1] when we grow obj->slots.
3958
+ *
3959
+ * See js_Mark, before the last return, where we make a special case
3960
+ * for unmutated (scope->object != obj) objects.
3961
+ */
3962
+ JS_ASSERT(nslots == JS_INITIAL_NSLOTS);
3963
+ clasp = LOCKED_OBJ_GET_CLASS(obj);
3964
+ nslots = JSSLOT_FREE(clasp);
3965
+ if (clasp->reserveSlots)
3966
+ nslots += clasp->reserveSlots(cx, obj);
3967
+ JS_ASSERT(slot < nslots);
3968
+
3969
+ newslots = (jsval *)
3970
+ JS_realloc(cx, obj->slots - 1, (nslots + 1) * sizeof(jsval));
3971
+ if (!newslots) {
3972
+ JS_UNLOCK_SCOPE(cx, scope);
3973
+ return JS_FALSE;
3974
+ }
3975
+ for (i = 1 + newslots[0]; i <= nslots; i++)
3976
+ newslots[i] = JSVAL_VOID;
3977
+ if (scope->object == obj)
3978
+ scope->map.nslots = nslots;
3979
+ newslots[0] = nslots;
3980
+ obj->slots = newslots + 1;
3981
+ }
3982
+
3983
+ /* Whether or not we grew nslots, we may need to advance freeslot. */
3984
+ if (scope->object == obj && slot >= scope->map.freeslot)
3985
+ scope->map.freeslot = slot + 1;
3986
+
3987
+ obj->slots[slot] = v;
3988
+ JS_UNLOCK_SCOPE(cx, scope);
3989
+ return JS_TRUE;
3990
+ }
3991
+
3992
+ #ifdef DEBUG
3993
+
3994
+ /* Routines to print out values during debugging. */
3995
+
3996
+ void printChar(jschar *cp) {
3997
+ fprintf(stderr, "jschar* (0x%p) \"", (void *)cp);
3998
+ while (*cp)
3999
+ fputc(*cp++, stderr);
4000
+ fputc('"', stderr);
4001
+ fputc('\n', stderr);
4002
+ }
4003
+
4004
+ void printString(JSString *str) {
4005
+ size_t i, n;
4006
+ jschar *s;
4007
+ fprintf(stderr, "string (0x%p) \"", (void *)str);
4008
+ s = JSSTRING_CHARS(str);
4009
+ for (i=0, n=JSSTRING_LENGTH(str); i < n; i++)
4010
+ fputc(s[i], stderr);
4011
+ fputc('"', stderr);
4012
+ fputc('\n', stderr);
4013
+ }
4014
+
4015
+ void printVal(JSContext *cx, jsval val);
4016
+
4017
+ void printObj(JSContext *cx, JSObject *jsobj) {
4018
+ jsuint i;
4019
+ jsval val;
4020
+ JSClass *clasp;
4021
+
4022
+ fprintf(stderr, "object 0x%p\n", (void *)jsobj);
4023
+ clasp = OBJ_GET_CLASS(cx, jsobj);
4024
+ fprintf(stderr, "class 0x%p %s\n", (void *)clasp, clasp->name);
4025
+ for (i=0; i < jsobj->map->nslots; i++) {
4026
+ fprintf(stderr, "slot %3d ", i);
4027
+ val = jsobj->slots[i];
4028
+ if (JSVAL_IS_OBJECT(val))
4029
+ fprintf(stderr, "object 0x%p\n", (void *)JSVAL_TO_OBJECT(val));
4030
+ else
4031
+ printVal(cx, val);
4032
+ }
4033
+ }
4034
+
4035
+ void printVal(JSContext *cx, jsval val) {
4036
+ fprintf(stderr, "val %d (0x%p) = ", (int)val, (void *)val);
4037
+ if (JSVAL_IS_NULL(val)) {
4038
+ fprintf(stderr, "null\n");
4039
+ } else if (JSVAL_IS_VOID(val)) {
4040
+ fprintf(stderr, "undefined\n");
4041
+ } else if (JSVAL_IS_OBJECT(val)) {
4042
+ printObj(cx, JSVAL_TO_OBJECT(val));
4043
+ } else if (JSVAL_IS_INT(val)) {
4044
+ fprintf(stderr, "(int) %d\n", JSVAL_TO_INT(val));
4045
+ } else if (JSVAL_IS_STRING(val)) {
4046
+ printString(JSVAL_TO_STRING(val));
4047
+ } else if (JSVAL_IS_DOUBLE(val)) {
4048
+ fprintf(stderr, "(double) %g\n", *JSVAL_TO_DOUBLE(val));
4049
+ } else {
4050
+ JS_ASSERT(JSVAL_IS_BOOLEAN(val));
4051
+ fprintf(stderr, "(boolean) %s\n",
4052
+ JSVAL_TO_BOOLEAN(val) ? "true" : "false");
4053
+ }
4054
+ fflush(stderr);
4055
+ }
4056
+
4057
+ void printId(JSContext *cx, jsid id) {
4058
+ fprintf(stderr, "id %d (0x%p) is ", (int)id, (void *)id);
4059
+ printVal(cx, ID_TO_VALUE(id));
4060
+ }
4061
+
4062
+ void printAtom(JSAtom *atom) {
4063
+ printString(ATOM_TO_STRING(atom));
4064
+ }
4065
+
4066
+ #endif