distil 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (552) hide show
  1. data/Rakefile +28 -0
  2. data/VERSION +1 -0
  3. data/bin/distil +45 -0
  4. data/distil.gemspec +586 -0
  5. data/lib/bootstrap-template.js +56 -0
  6. data/lib/configurable.rb +125 -0
  7. data/lib/file-set.rb +42 -0
  8. data/lib/file-types/css-file.rb +75 -0
  9. data/lib/file-types/html-file.rb +11 -0
  10. data/lib/file-types/javascript-file.rb +98 -0
  11. data/lib/file-types/json-file.rb +14 -0
  12. data/lib/file-types/nib-file.rb +9 -0
  13. data/lib/jsdoc.conf +18 -0
  14. data/lib/jsl.conf +121 -0
  15. data/lib/project.rb +96 -0
  16. data/lib/source-file.rb +181 -0
  17. data/lib/target.rb +96 -0
  18. data/lib/task.rb +239 -0
  19. data/lib/tasks/copy-task.rb +21 -0
  20. data/lib/tasks/css-task.rb +18 -0
  21. data/lib/tasks/javascript-task.rb +125 -0
  22. data/lib/tasks/multiple-output-task.rb +134 -0
  23. data/lib/tasks/nib-task.rb +83 -0
  24. data/lib/tasks/output-task.rb +73 -0
  25. data/lib/tasks/single-output-task.rb +83 -0
  26. data/lib/tasks/test-task.rb +280 -0
  27. data/lib/test/HtmlTestReporter.js +127 -0
  28. data/lib/test/Test.js +248 -0
  29. data/lib/test/TestReporter.js +79 -0
  30. data/lib/test/TestRunner.js +132 -0
  31. data/lib/test/browser.rb +97 -0
  32. data/lib/test/scriptwrapper.html +10 -0
  33. data/lib/test/unittest.html +127 -0
  34. data/vendor/Makefile +35 -0
  35. data/vendor/extconf.rb +3 -0
  36. data/vendor/jsdoc-extras/plugins/distil-plugin.js +142 -0
  37. data/vendor/jsdoc-extras/plugins/interface-plugin.js +36 -0
  38. data/vendor/jsdoc-extras/templates/coherent/allclasses.tmpl +17 -0
  39. data/vendor/jsdoc-extras/templates/coherent/allfiles.tmpl +53 -0
  40. data/vendor/jsdoc-extras/templates/coherent/class.tmpl +803 -0
  41. data/vendor/jsdoc-extras/templates/coherent/index.tmpl +37 -0
  42. data/vendor/jsdoc-extras/templates/coherent/publish.js +242 -0
  43. data/vendor/jsdoc-extras/templates/coherent/showdown.js +421 -0
  44. data/vendor/jsdoc-extras/templates/coherent/static/code-footer.html +3 -0
  45. data/vendor/jsdoc-extras/templates/coherent/static/code-header.html +7 -0
  46. data/vendor/jsdoc-extras/templates/coherent/static/default.css +297 -0
  47. data/vendor/jsdoc-extras/templates/coherent/static/header.html +2 -0
  48. data/vendor/jsdoc-extras/templates/coherent/static/index.html +19 -0
  49. data/vendor/jsdoc-extras/templates/coherent/symbol.tmpl +35 -0
  50. data/vendor/jsdoc-toolkit/README.txt +183 -0
  51. data/vendor/jsdoc-toolkit/app/frame/Chain.js +102 -0
  52. data/vendor/jsdoc-toolkit/app/frame/Dumper.js +144 -0
  53. data/vendor/jsdoc-toolkit/app/frame/Hash.js +84 -0
  54. data/vendor/jsdoc-toolkit/app/frame/Link.js +171 -0
  55. data/vendor/jsdoc-toolkit/app/frame/Namespace.js +10 -0
  56. data/vendor/jsdoc-toolkit/app/frame/Opt.js +134 -0
  57. data/vendor/jsdoc-toolkit/app/frame/Reflection.js +26 -0
  58. data/vendor/jsdoc-toolkit/app/frame/String.js +93 -0
  59. data/vendor/jsdoc-toolkit/app/frame/Testrun.js +129 -0
  60. data/vendor/jsdoc-toolkit/app/frame.js +33 -0
  61. data/vendor/jsdoc-toolkit/app/handlers/FOODOC.js +26 -0
  62. data/vendor/jsdoc-toolkit/app/handlers/XMLDOC/DomReader.js +159 -0
  63. data/vendor/jsdoc-toolkit/app/handlers/XMLDOC/XMLDoc.js +16 -0
  64. data/vendor/jsdoc-toolkit/app/handlers/XMLDOC/XMLParse.js +292 -0
  65. data/vendor/jsdoc-toolkit/app/handlers/XMLDOC.js +26 -0
  66. data/vendor/jsdoc-toolkit/app/lib/JSDOC/DocComment.js +204 -0
  67. data/vendor/jsdoc-toolkit/app/lib/JSDOC/DocTag.js +300 -0
  68. data/vendor/jsdoc-toolkit/app/lib/JSDOC/JsDoc.js +126 -0
  69. data/vendor/jsdoc-toolkit/app/lib/JSDOC/JsPlate.js +109 -0
  70. data/vendor/jsdoc-toolkit/app/lib/JSDOC/Lang.js +144 -0
  71. data/vendor/jsdoc-toolkit/app/lib/JSDOC/Parser.js +144 -0
  72. data/vendor/jsdoc-toolkit/app/lib/JSDOC/PluginManager.js +33 -0
  73. data/vendor/jsdoc-toolkit/app/lib/JSDOC/Symbol.js +644 -0
  74. data/vendor/jsdoc-toolkit/app/lib/JSDOC/SymbolSet.js +241 -0
  75. data/vendor/jsdoc-toolkit/app/lib/JSDOC/TextStream.js +41 -0
  76. data/vendor/jsdoc-toolkit/app/lib/JSDOC/Token.js +18 -0
  77. data/vendor/jsdoc-toolkit/app/lib/JSDOC/TokenReader.js +332 -0
  78. data/vendor/jsdoc-toolkit/app/lib/JSDOC/TokenStream.js +133 -0
  79. data/vendor/jsdoc-toolkit/app/lib/JSDOC/Util.js +32 -0
  80. data/vendor/jsdoc-toolkit/app/lib/JSDOC/Walker.js +499 -0
  81. data/vendor/jsdoc-toolkit/app/lib/JSDOC.js +106 -0
  82. data/vendor/jsdoc-toolkit/app/main.js +129 -0
  83. data/vendor/jsdoc-toolkit/app/plugins/commentSrcJson.js +20 -0
  84. data/vendor/jsdoc-toolkit/app/plugins/frameworkPrototype.js +16 -0
  85. data/vendor/jsdoc-toolkit/app/plugins/functionCall.js +10 -0
  86. data/vendor/jsdoc-toolkit/app/plugins/publishSrcHilite.js +54 -0
  87. data/vendor/jsdoc-toolkit/app/plugins/symbolLink.js +10 -0
  88. data/vendor/jsdoc-toolkit/app/plugins/tagParamConfig.js +31 -0
  89. data/vendor/jsdoc-toolkit/app/plugins/tagSynonyms.js +43 -0
  90. data/vendor/jsdoc-toolkit/app/run.js +348 -0
  91. data/vendor/jsdoc-toolkit/app/t/TestDoc.js +144 -0
  92. data/vendor/jsdoc-toolkit/app/t/runner.js +13 -0
  93. data/vendor/jsdoc-toolkit/app/test/addon.js +24 -0
  94. data/vendor/jsdoc-toolkit/app/test/anon_inner.js +14 -0
  95. data/vendor/jsdoc-toolkit/app/test/augments.js +31 -0
  96. data/vendor/jsdoc-toolkit/app/test/augments2.js +26 -0
  97. data/vendor/jsdoc-toolkit/app/test/borrows.js +46 -0
  98. data/vendor/jsdoc-toolkit/app/test/borrows2.js +23 -0
  99. data/vendor/jsdoc-toolkit/app/test/config.js +22 -0
  100. data/vendor/jsdoc-toolkit/app/test/constructs.js +18 -0
  101. data/vendor/jsdoc-toolkit/app/test/encoding.js +10 -0
  102. data/vendor/jsdoc-toolkit/app/test/encoding_other.js +12 -0
  103. data/vendor/jsdoc-toolkit/app/test/event.js +54 -0
  104. data/vendor/jsdoc-toolkit/app/test/exports.js +14 -0
  105. data/vendor/jsdoc-toolkit/app/test/functions_anon.js +39 -0
  106. data/vendor/jsdoc-toolkit/app/test/functions_nested.js +33 -0
  107. data/vendor/jsdoc-toolkit/app/test/global.js +13 -0
  108. data/vendor/jsdoc-toolkit/app/test/globals.js +25 -0
  109. data/vendor/jsdoc-toolkit/app/test/ignore.js +10 -0
  110. data/vendor/jsdoc-toolkit/app/test/inner.js +16 -0
  111. data/vendor/jsdoc-toolkit/app/test/jsdoc_test.js +477 -0
  112. data/vendor/jsdoc-toolkit/app/test/lend.js +33 -0
  113. data/vendor/jsdoc-toolkit/app/test/memberof.js +19 -0
  114. data/vendor/jsdoc-toolkit/app/test/memberof2.js +38 -0
  115. data/vendor/jsdoc-toolkit/app/test/memberof3.js +33 -0
  116. data/vendor/jsdoc-toolkit/app/test/memberof_constructor.js +17 -0
  117. data/vendor/jsdoc-toolkit/app/test/module.js +17 -0
  118. data/vendor/jsdoc-toolkit/app/test/name.js +19 -0
  119. data/vendor/jsdoc-toolkit/app/test/namespace_nested.js +23 -0
  120. data/vendor/jsdoc-toolkit/app/test/nocode.js +13 -0
  121. data/vendor/jsdoc-toolkit/app/test/oblit_anon.js +20 -0
  122. data/vendor/jsdoc-toolkit/app/test/overview.js +20 -0
  123. data/vendor/jsdoc-toolkit/app/test/param_inline.js +37 -0
  124. data/vendor/jsdoc-toolkit/app/test/params_optional.js +8 -0
  125. data/vendor/jsdoc-toolkit/app/test/prototype.js +17 -0
  126. data/vendor/jsdoc-toolkit/app/test/prototype_nested.js +9 -0
  127. data/vendor/jsdoc-toolkit/app/test/prototype_oblit.js +13 -0
  128. data/vendor/jsdoc-toolkit/app/test/prototype_oblit_constructor.js +24 -0
  129. data/vendor/jsdoc-toolkit/app/test/public.js +10 -0
  130. data/vendor/jsdoc-toolkit/app/test/scripts/code.js +5 -0
  131. data/vendor/jsdoc-toolkit/app/test/scripts/notcode.txt +5 -0
  132. data/vendor/jsdoc-toolkit/app/test/shared.js +42 -0
  133. data/vendor/jsdoc-toolkit/app/test/shared2.js +2 -0
  134. data/vendor/jsdoc-toolkit/app/test/shortcuts.js +22 -0
  135. data/vendor/jsdoc-toolkit/app/test/static_this.js +13 -0
  136. data/vendor/jsdoc-toolkit/app/test/synonyms.js +31 -0
  137. data/vendor/jsdoc-toolkit/app/test/tosource.js +23 -0
  138. data/vendor/jsdoc-toolkit/app/test/variable_redefine.js +14 -0
  139. data/vendor/jsdoc-toolkit/app/test.js +342 -0
  140. data/vendor/jsdoc-toolkit/changes.txt +116 -0
  141. data/vendor/jsdoc-toolkit/conf/sample.conf +31 -0
  142. data/vendor/jsdoc-toolkit/java/build.xml +36 -0
  143. data/vendor/jsdoc-toolkit/java/build_1.4.xml +36 -0
  144. data/vendor/jsdoc-toolkit/java/classes/js.jar +0 -0
  145. data/vendor/jsdoc-toolkit/java/src/JsDebugRun.java +21 -0
  146. data/vendor/jsdoc-toolkit/java/src/JsRun.java +21 -0
  147. data/vendor/jsdoc-toolkit/jsdebug.jar +0 -0
  148. data/vendor/jsdoc-toolkit/jsrun.jar +0 -0
  149. data/vendor/jsdoc-toolkit/jsrun.sh +53 -0
  150. data/vendor/jsdoc-toolkit/templates/jsdoc/allclasses.tmpl +17 -0
  151. data/vendor/jsdoc-toolkit/templates/jsdoc/allfiles.tmpl +56 -0
  152. data/vendor/jsdoc-toolkit/templates/jsdoc/class.tmpl +649 -0
  153. data/vendor/jsdoc-toolkit/templates/jsdoc/index.tmpl +39 -0
  154. data/vendor/jsdoc-toolkit/templates/jsdoc/publish.js +201 -0
  155. data/vendor/jsdoc-toolkit/templates/jsdoc/static/code-footer.html +3 -0
  156. data/vendor/jsdoc-toolkit/templates/jsdoc/static/code-header.html +14 -0
  157. data/vendor/jsdoc-toolkit/templates/jsdoc/static/default.css +162 -0
  158. data/vendor/jsdoc-toolkit/templates/jsdoc/static/header.html +2 -0
  159. data/vendor/jsdoc-toolkit/templates/jsdoc/static/index.html +19 -0
  160. data/vendor/jsdoc-toolkit/templates/jsdoc/symbol.tmpl +35 -0
  161. data/vendor/jsl-0.3.0/src/JavaScriptLintAPI.cpp +333 -0
  162. data/vendor/jsl-0.3.0/src/JavaScriptLintAPI.h +86 -0
  163. data/vendor/jsl-0.3.0/src/Makefile.in +375 -0
  164. data/vendor/jsl-0.3.0/src/Makefile.ref +372 -0
  165. data/vendor/jsl-0.3.0/src/README.html +826 -0
  166. data/vendor/jsl-0.3.0/src/SpiderMonkey.rsp +12 -0
  167. data/vendor/jsl-0.3.0/src/_jsl_online.php +223 -0
  168. data/vendor/jsl-0.3.0/src/config/AIX4.1.mk +65 -0
  169. data/vendor/jsl-0.3.0/src/config/AIX4.2.mk +64 -0
  170. data/vendor/jsl-0.3.0/src/config/AIX4.3.mk +65 -0
  171. data/vendor/jsl-0.3.0/src/config/Darwin.mk +81 -0
  172. data/vendor/jsl-0.3.0/src/config/Darwin1.3.mk +81 -0
  173. data/vendor/jsl-0.3.0/src/config/Darwin1.4.mk +41 -0
  174. data/vendor/jsl-0.3.0/src/config/Darwin5.2.mk +81 -0
  175. data/vendor/jsl-0.3.0/src/config/Darwin5.3.mk +81 -0
  176. data/vendor/jsl-0.3.0/src/config/HP-UXB.10.10.mk +77 -0
  177. data/vendor/jsl-0.3.0/src/config/HP-UXB.10.20.mk +77 -0
  178. data/vendor/jsl-0.3.0/src/config/HP-UXB.11.00.mk +80 -0
  179. data/vendor/jsl-0.3.0/src/config/IRIX.mk +87 -0
  180. data/vendor/jsl-0.3.0/src/config/IRIX5.3.mk +44 -0
  181. data/vendor/jsl-0.3.0/src/config/IRIX6.1.mk +44 -0
  182. data/vendor/jsl-0.3.0/src/config/IRIX6.2.mk +44 -0
  183. data/vendor/jsl-0.3.0/src/config/IRIX6.3.mk +44 -0
  184. data/vendor/jsl-0.3.0/src/config/IRIX6.5.mk +44 -0
  185. data/vendor/jsl-0.3.0/src/config/Linux_All.mk +103 -0
  186. data/vendor/jsl-0.3.0/src/config/Mac_OS10.0.mk +82 -0
  187. data/vendor/jsl-0.3.0/src/config/OSF1V4.0.mk +72 -0
  188. data/vendor/jsl-0.3.0/src/config/OSF1V5.0.mk +69 -0
  189. data/vendor/jsl-0.3.0/src/config/SunOS4.1.4.mk +101 -0
  190. data/vendor/jsl-0.3.0/src/config/SunOS5.3.mk +91 -0
  191. data/vendor/jsl-0.3.0/src/config/SunOS5.4.mk +92 -0
  192. data/vendor/jsl-0.3.0/src/config/SunOS5.5.1.mk +44 -0
  193. data/vendor/jsl-0.3.0/src/config/SunOS5.5.mk +87 -0
  194. data/vendor/jsl-0.3.0/src/config/SunOS5.6.mk +89 -0
  195. data/vendor/jsl-0.3.0/src/config/SunOS5.7.mk +44 -0
  196. data/vendor/jsl-0.3.0/src/config/SunOS5.8.mk +44 -0
  197. data/vendor/jsl-0.3.0/src/config/SunOS5.9.mk +44 -0
  198. data/vendor/jsl-0.3.0/src/config/WINNT4.0.mk +112 -0
  199. data/vendor/jsl-0.3.0/src/config/WINNT5.0.mk +112 -0
  200. data/vendor/jsl-0.3.0/src/config/WINNT5.1.mk +112 -0
  201. data/vendor/jsl-0.3.0/src/config/WINNT5.2.mk +112 -0
  202. data/vendor/jsl-0.3.0/src/config/dgux.mk +64 -0
  203. data/vendor/jsl-0.3.0/src/config.mk +166 -0
  204. data/vendor/jsl-0.3.0/src/editline/Makefile.ref +144 -0
  205. data/vendor/jsl-0.3.0/src/editline/README +83 -0
  206. data/vendor/jsl-0.3.0/src/editline/editline.3 +175 -0
  207. data/vendor/jsl-0.3.0/src/editline/editline.c +1369 -0
  208. data/vendor/jsl-0.3.0/src/editline/editline.h +135 -0
  209. data/vendor/jsl-0.3.0/src/editline/sysunix.c +182 -0
  210. data/vendor/jsl-0.3.0/src/editline/unix.h +82 -0
  211. data/vendor/jsl-0.3.0/src/fdlibm/Makefile.in +127 -0
  212. data/vendor/jsl-0.3.0/src/fdlibm/Makefile.ref +192 -0
  213. data/vendor/jsl-0.3.0/src/fdlibm/e_acos.c +147 -0
  214. data/vendor/jsl-0.3.0/src/fdlibm/e_acosh.c +105 -0
  215. data/vendor/jsl-0.3.0/src/fdlibm/e_asin.c +156 -0
  216. data/vendor/jsl-0.3.0/src/fdlibm/e_atan2.c +165 -0
  217. data/vendor/jsl-0.3.0/src/fdlibm/e_atanh.c +110 -0
  218. data/vendor/jsl-0.3.0/src/fdlibm/e_cosh.c +133 -0
  219. data/vendor/jsl-0.3.0/src/fdlibm/e_exp.c +202 -0
  220. data/vendor/jsl-0.3.0/src/fdlibm/e_fmod.c +184 -0
  221. data/vendor/jsl-0.3.0/src/fdlibm/e_gamma.c +71 -0
  222. data/vendor/jsl-0.3.0/src/fdlibm/e_gamma_r.c +70 -0
  223. data/vendor/jsl-0.3.0/src/fdlibm/e_hypot.c +173 -0
  224. data/vendor/jsl-0.3.0/src/fdlibm/e_j0.c +524 -0
  225. data/vendor/jsl-0.3.0/src/fdlibm/e_j1.c +523 -0
  226. data/vendor/jsl-0.3.0/src/fdlibm/e_jn.c +315 -0
  227. data/vendor/jsl-0.3.0/src/fdlibm/e_lgamma.c +71 -0
  228. data/vendor/jsl-0.3.0/src/fdlibm/e_lgamma_r.c +347 -0
  229. data/vendor/jsl-0.3.0/src/fdlibm/e_log.c +184 -0
  230. data/vendor/jsl-0.3.0/src/fdlibm/e_log10.c +134 -0
  231. data/vendor/jsl-0.3.0/src/fdlibm/e_pow.c +386 -0
  232. data/vendor/jsl-0.3.0/src/fdlibm/e_rem_pio2.c +221 -0
  233. data/vendor/jsl-0.3.0/src/fdlibm/e_remainder.c +120 -0
  234. data/vendor/jsl-0.3.0/src/fdlibm/e_scalb.c +89 -0
  235. data/vendor/jsl-0.3.0/src/fdlibm/e_sinh.c +122 -0
  236. data/vendor/jsl-0.3.0/src/fdlibm/e_sqrt.c +497 -0
  237. data/vendor/jsl-0.3.0/src/fdlibm/fdlibm.dsp +160 -0
  238. data/vendor/jsl-0.3.0/src/fdlibm/fdlibm.h +273 -0
  239. data/vendor/jsl-0.3.0/src/fdlibm/fdlibm.mak +1453 -0
  240. data/vendor/jsl-0.3.0/src/fdlibm/fdlibm.mdp +0 -0
  241. data/vendor/jsl-0.3.0/src/fdlibm/k_cos.c +134 -0
  242. data/vendor/jsl-0.3.0/src/fdlibm/k_rem_pio2.c +354 -0
  243. data/vendor/jsl-0.3.0/src/fdlibm/k_sin.c +114 -0
  244. data/vendor/jsl-0.3.0/src/fdlibm/k_standard.c +785 -0
  245. data/vendor/jsl-0.3.0/src/fdlibm/k_tan.c +170 -0
  246. data/vendor/jsl-0.3.0/src/fdlibm/s_asinh.c +101 -0
  247. data/vendor/jsl-0.3.0/src/fdlibm/s_atan.c +175 -0
  248. data/vendor/jsl-0.3.0/src/fdlibm/s_cbrt.c +133 -0
  249. data/vendor/jsl-0.3.0/src/fdlibm/s_ceil.c +120 -0
  250. data/vendor/jsl-0.3.0/src/fdlibm/s_copysign.c +72 -0
  251. data/vendor/jsl-0.3.0/src/fdlibm/s_cos.c +118 -0
  252. data/vendor/jsl-0.3.0/src/fdlibm/s_erf.c +356 -0
  253. data/vendor/jsl-0.3.0/src/fdlibm/s_expm1.c +267 -0
  254. data/vendor/jsl-0.3.0/src/fdlibm/s_fabs.c +70 -0
  255. data/vendor/jsl-0.3.0/src/fdlibm/s_finite.c +71 -0
  256. data/vendor/jsl-0.3.0/src/fdlibm/s_floor.c +121 -0
  257. data/vendor/jsl-0.3.0/src/fdlibm/s_frexp.c +99 -0
  258. data/vendor/jsl-0.3.0/src/fdlibm/s_ilogb.c +85 -0
  259. data/vendor/jsl-0.3.0/src/fdlibm/s_isnan.c +74 -0
  260. data/vendor/jsl-0.3.0/src/fdlibm/s_ldexp.c +66 -0
  261. data/vendor/jsl-0.3.0/src/fdlibm/s_lib_version.c +73 -0
  262. data/vendor/jsl-0.3.0/src/fdlibm/s_log1p.c +211 -0
  263. data/vendor/jsl-0.3.0/src/fdlibm/s_logb.c +79 -0
  264. data/vendor/jsl-0.3.0/src/fdlibm/s_matherr.c +64 -0
  265. data/vendor/jsl-0.3.0/src/fdlibm/s_modf.c +132 -0
  266. data/vendor/jsl-0.3.0/src/fdlibm/s_nextafter.c +124 -0
  267. data/vendor/jsl-0.3.0/src/fdlibm/s_rint.c +131 -0
  268. data/vendor/jsl-0.3.0/src/fdlibm/s_scalbn.c +107 -0
  269. data/vendor/jsl-0.3.0/src/fdlibm/s_signgam.c +40 -0
  270. data/vendor/jsl-0.3.0/src/fdlibm/s_significand.c +68 -0
  271. data/vendor/jsl-0.3.0/src/fdlibm/s_sin.c +118 -0
  272. data/vendor/jsl-0.3.0/src/fdlibm/s_tan.c +112 -0
  273. data/vendor/jsl-0.3.0/src/fdlibm/s_tanh.c +122 -0
  274. data/vendor/jsl-0.3.0/src/fdlibm/w_acos.c +78 -0
  275. data/vendor/jsl-0.3.0/src/fdlibm/w_acosh.c +78 -0
  276. data/vendor/jsl-0.3.0/src/fdlibm/w_asin.c +80 -0
  277. data/vendor/jsl-0.3.0/src/fdlibm/w_atan2.c +79 -0
  278. data/vendor/jsl-0.3.0/src/fdlibm/w_atanh.c +81 -0
  279. data/vendor/jsl-0.3.0/src/fdlibm/w_cosh.c +77 -0
  280. data/vendor/jsl-0.3.0/src/fdlibm/w_exp.c +88 -0
  281. data/vendor/jsl-0.3.0/src/fdlibm/w_fmod.c +78 -0
  282. data/vendor/jsl-0.3.0/src/fdlibm/w_gamma.c +85 -0
  283. data/vendor/jsl-0.3.0/src/fdlibm/w_gamma_r.c +81 -0
  284. data/vendor/jsl-0.3.0/src/fdlibm/w_hypot.c +78 -0
  285. data/vendor/jsl-0.3.0/src/fdlibm/w_j0.c +105 -0
  286. data/vendor/jsl-0.3.0/src/fdlibm/w_j1.c +106 -0
  287. data/vendor/jsl-0.3.0/src/fdlibm/w_jn.c +128 -0
  288. data/vendor/jsl-0.3.0/src/fdlibm/w_lgamma.c +85 -0
  289. data/vendor/jsl-0.3.0/src/fdlibm/w_lgamma_r.c +81 -0
  290. data/vendor/jsl-0.3.0/src/fdlibm/w_log.c +78 -0
  291. data/vendor/jsl-0.3.0/src/fdlibm/w_log10.c +81 -0
  292. data/vendor/jsl-0.3.0/src/fdlibm/w_pow.c +99 -0
  293. data/vendor/jsl-0.3.0/src/fdlibm/w_remainder.c +77 -0
  294. data/vendor/jsl-0.3.0/src/fdlibm/w_scalb.c +95 -0
  295. data/vendor/jsl-0.3.0/src/fdlibm/w_sinh.c +77 -0
  296. data/vendor/jsl-0.3.0/src/fdlibm/w_sqrt.c +77 -0
  297. data/vendor/jsl-0.3.0/src/js.c +2447 -0
  298. data/vendor/jsl-0.3.0/src/js.dsp +420 -0
  299. data/vendor/jsl-0.3.0/src/js.mak +4025 -0
  300. data/vendor/jsl-0.3.0/src/js.mdp +0 -0
  301. data/vendor/jsl-0.3.0/src/js.msg +291 -0
  302. data/vendor/jsl-0.3.0/src/js.pkg +2 -0
  303. data/vendor/jsl-0.3.0/src/js3240.rc +79 -0
  304. data/vendor/jsl-0.3.0/src/jsOS240.def +654 -0
  305. data/vendor/jsl-0.3.0/src/jsapi.c +4405 -0
  306. data/vendor/jsl-0.3.0/src/jsapi.h +1856 -0
  307. data/vendor/jsl-0.3.0/src/jsarena.c +567 -0
  308. data/vendor/jsl-0.3.0/src/jsarena.h +302 -0
  309. data/vendor/jsl-0.3.0/src/jsarray.c +1428 -0
  310. data/vendor/jsl-0.3.0/src/jsarray.h +77 -0
  311. data/vendor/jsl-0.3.0/src/jsatom.c +927 -0
  312. data/vendor/jsl-0.3.0/src/jsatom.h +426 -0
  313. data/vendor/jsl-0.3.0/src/jsbit.h +113 -0
  314. data/vendor/jsl-0.3.0/src/jsbool.c +220 -0
  315. data/vendor/jsl-0.3.0/src/jsbool.h +62 -0
  316. data/vendor/jsl-0.3.0/src/jsclist.h +139 -0
  317. data/vendor/jsl-0.3.0/src/jscntxt.c +1036 -0
  318. data/vendor/jsl-0.3.0/src/jscntxt.h +608 -0
  319. data/vendor/jsl-0.3.0/src/jscompat.h +57 -0
  320. data/vendor/jsl-0.3.0/src/jsconfig.h +489 -0
  321. data/vendor/jsl-0.3.0/src/jsconfig.mk +181 -0
  322. data/vendor/jsl-0.3.0/src/jscpucfg.c +377 -0
  323. data/vendor/jsl-0.3.0/src/jscpucfg.h +204 -0
  324. data/vendor/jsl-0.3.0/src/jsdate.c +2238 -0
  325. data/vendor/jsl-0.3.0/src/jsdate.h +118 -0
  326. data/vendor/jsl-0.3.0/src/jsdbgapi.c +1260 -0
  327. data/vendor/jsl-0.3.0/src/jsdbgapi.h +345 -0
  328. data/vendor/jsl-0.3.0/src/jsdhash.c +763 -0
  329. data/vendor/jsl-0.3.0/src/jsdhash.h +579 -0
  330. data/vendor/jsl-0.3.0/src/jsdtoa.c +3135 -0
  331. data/vendor/jsl-0.3.0/src/jsdtoa.h +130 -0
  332. data/vendor/jsl-0.3.0/src/jsemit.c +4851 -0
  333. data/vendor/jsl-0.3.0/src/jsemit.h +576 -0
  334. data/vendor/jsl-0.3.0/src/jsexn.c +1084 -0
  335. data/vendor/jsl-0.3.0/src/jsexn.h +102 -0
  336. data/vendor/jsl-0.3.0/src/jsfile.c +2610 -0
  337. data/vendor/jsl-0.3.0/src/jsfile.h +50 -0
  338. data/vendor/jsl-0.3.0/src/jsfile.msg +89 -0
  339. data/vendor/jsl-0.3.0/src/jsfun.c +2015 -0
  340. data/vendor/jsl-0.3.0/src/jsfun.h +158 -0
  341. data/vendor/jsl-0.3.0/src/jsgc.c +1441 -0
  342. data/vendor/jsl-0.3.0/src/jsgc.h +230 -0
  343. data/vendor/jsl-0.3.0/src/jshash.c +471 -0
  344. data/vendor/jsl-0.3.0/src/jshash.h +152 -0
  345. data/vendor/jsl-0.3.0/src/jsify.pl +485 -0
  346. data/vendor/jsl-0.3.0/src/jsinterp.c +4797 -0
  347. data/vendor/jsl-0.3.0/src/jsinterp.h +302 -0
  348. data/vendor/jsl-0.3.0/src/jsl-test.js +28 -0
  349. data/vendor/jsl-0.3.0/src/jsl.c +2371 -0
  350. data/vendor/jsl-0.3.0/src/jsl.conf +127 -0
  351. data/vendor/jsl-0.3.0/src/jsl.conf.old +124 -0
  352. data/vendor/jsl-0.3.0/src/jsl.dsp +242 -0
  353. data/vendor/jsl-0.3.0/src/jsl.dsw +59 -0
  354. data/vendor/jsl-0.3.0/src/jslibmath.h +290 -0
  355. data/vendor/jsl-0.3.0/src/jslock.c +1261 -0
  356. data/vendor/jsl-0.3.0/src/jslock.h +289 -0
  357. data/vendor/jsl-0.3.0/src/jslocko.asm +59 -0
  358. data/vendor/jsl-0.3.0/src/jslog2.c +83 -0
  359. data/vendor/jsl-0.3.0/src/jslong.c +281 -0
  360. data/vendor/jsl-0.3.0/src/jslong.h +437 -0
  361. data/vendor/jsl-0.3.0/src/jsmath.c +477 -0
  362. data/vendor/jsl-0.3.0/src/jsmath.h +55 -0
  363. data/vendor/jsl-0.3.0/src/jsnum.c +1148 -0
  364. data/vendor/jsl-0.3.0/src/jsnum.h +257 -0
  365. data/vendor/jsl-0.3.0/src/jsobj.c +4066 -0
  366. data/vendor/jsl-0.3.0/src/jsobj.h +475 -0
  367. data/vendor/jsl-0.3.0/src/jsopcode.c +2730 -0
  368. data/vendor/jsl-0.3.0/src/jsopcode.h +275 -0
  369. data/vendor/jsl-0.3.0/src/jsopcode.tbl +344 -0
  370. data/vendor/jsl-0.3.0/src/jsosdep.h +127 -0
  371. data/vendor/jsl-0.3.0/src/jsotypes.h +211 -0
  372. data/vendor/jsl-0.3.0/src/jsparse.c +4438 -0
  373. data/vendor/jsl-0.3.0/src/jsparse.h +345 -0
  374. data/vendor/jsl-0.3.0/src/jsprf.c +1212 -0
  375. data/vendor/jsl-0.3.0/src/jsprf.h +148 -0
  376. data/vendor/jsl-0.3.0/src/jsprvtd.h +174 -0
  377. data/vendor/jsl-0.3.0/src/jspubtd.h +586 -0
  378. data/vendor/jsl-0.3.0/src/jsregexp.c +3831 -0
  379. data/vendor/jsl-0.3.0/src/jsregexp.h +180 -0
  380. data/vendor/jsl-0.3.0/src/jsscan.c +1814 -0
  381. data/vendor/jsl-0.3.0/src/jsscan.h +267 -0
  382. data/vendor/jsl-0.3.0/src/jsscope.c +1639 -0
  383. data/vendor/jsl-0.3.0/src/jsscope.h +389 -0
  384. data/vendor/jsl-0.3.0/src/jsscript.c +1284 -0
  385. data/vendor/jsl-0.3.0/src/jsscript.h +179 -0
  386. data/vendor/jsl-0.3.0/src/jsshell.msg +50 -0
  387. data/vendor/jsl-0.3.0/src/jsstddef.h +83 -0
  388. data/vendor/jsl-0.3.0/src/jsstr.c +4502 -0
  389. data/vendor/jsl-0.3.0/src/jsstr.h +448 -0
  390. data/vendor/jsl-0.3.0/src/jstypes.h +391 -0
  391. data/vendor/jsl-0.3.0/src/jsutil.c +157 -0
  392. data/vendor/jsl-0.3.0/src/jsutil.h +75 -0
  393. data/vendor/jsl-0.3.0/src/jsxdrapi.c +686 -0
  394. data/vendor/jsl-0.3.0/src/jsxdrapi.h +193 -0
  395. data/vendor/jsl-0.3.0/src/liveconnect/LiveConnect.dsp +157 -0
  396. data/vendor/jsl-0.3.0/src/liveconnect/LiveConnectShell.dsp +120 -0
  397. data/vendor/jsl-0.3.0/src/liveconnect/LiveConnectShell.dsw +44 -0
  398. data/vendor/jsl-0.3.0/src/liveconnect/Makefile.in +106 -0
  399. data/vendor/jsl-0.3.0/src/liveconnect/Makefile.ref +169 -0
  400. data/vendor/jsl-0.3.0/src/liveconnect/README.html +719 -0
  401. data/vendor/jsl-0.3.0/src/liveconnect/_jni/netscape_javascript_JSException.h +14 -0
  402. data/vendor/jsl-0.3.0/src/liveconnect/_jni/netscape_javascript_JSObject.h +155 -0
  403. data/vendor/jsl-0.3.0/src/liveconnect/classes/Makefile.in +89 -0
  404. data/vendor/jsl-0.3.0/src/liveconnect/classes/Makefile.ref +57 -0
  405. data/vendor/jsl-0.3.0/src/liveconnect/classes/netscape/Makefile.ref +47 -0
  406. data/vendor/jsl-0.3.0/src/liveconnect/classes/netscape/javascript/JSException.java +140 -0
  407. data/vendor/jsl-0.3.0/src/liveconnect/classes/netscape/javascript/JSObject.java +183 -0
  408. data/vendor/jsl-0.3.0/src/liveconnect/classes/netscape/javascript/JSProxy.java +58 -0
  409. data/vendor/jsl-0.3.0/src/liveconnect/classes/netscape/javascript/JSRunnable.java +70 -0
  410. data/vendor/jsl-0.3.0/src/liveconnect/classes/netscape/javascript/JSUtil.java +59 -0
  411. data/vendor/jsl-0.3.0/src/liveconnect/classes/netscape/javascript/Makefile.ref +53 -0
  412. data/vendor/jsl-0.3.0/src/liveconnect/config/AIX4.1.mk +45 -0
  413. data/vendor/jsl-0.3.0/src/liveconnect/config/AIX4.2.mk +45 -0
  414. data/vendor/jsl-0.3.0/src/liveconnect/config/AIX4.3.mk +50 -0
  415. data/vendor/jsl-0.3.0/src/liveconnect/config/HP-UXB.10.10.mk +43 -0
  416. data/vendor/jsl-0.3.0/src/liveconnect/config/HP-UXB.10.20.mk +43 -0
  417. data/vendor/jsl-0.3.0/src/liveconnect/config/HP-UXB.11.00.mk +43 -0
  418. data/vendor/jsl-0.3.0/src/liveconnect/config/IRIX6.2.mk +43 -0
  419. data/vendor/jsl-0.3.0/src/liveconnect/config/IRIX6.3.mk +43 -0
  420. data/vendor/jsl-0.3.0/src/liveconnect/config/IRIX6.5.mk +43 -0
  421. data/vendor/jsl-0.3.0/src/liveconnect/config/Linux_All.mk +73 -0
  422. data/vendor/jsl-0.3.0/src/liveconnect/config/OSF1V4.0.mk +65 -0
  423. data/vendor/jsl-0.3.0/src/liveconnect/config/OSF1V5.0.mk +62 -0
  424. data/vendor/jsl-0.3.0/src/liveconnect/config/SunOS5.5.1.mk +55 -0
  425. data/vendor/jsl-0.3.0/src/liveconnect/config/SunOS5.6.mk +39 -0
  426. data/vendor/jsl-0.3.0/src/liveconnect/config/SunOS5.7.mk +39 -0
  427. data/vendor/jsl-0.3.0/src/liveconnect/config/SunOS5.8.mk +39 -0
  428. data/vendor/jsl-0.3.0/src/liveconnect/config/WINNT4.0.mk +53 -0
  429. data/vendor/jsl-0.3.0/src/liveconnect/jsj.c +884 -0
  430. data/vendor/jsl-0.3.0/src/liveconnect/jsj.msg +98 -0
  431. data/vendor/jsl-0.3.0/src/liveconnect/jsj_JSObject.c +1379 -0
  432. data/vendor/jsl-0.3.0/src/liveconnect/jsj_JavaArray.c +481 -0
  433. data/vendor/jsl-0.3.0/src/liveconnect/jsj_JavaClass.c +749 -0
  434. data/vendor/jsl-0.3.0/src/liveconnect/jsj_JavaMember.c +186 -0
  435. data/vendor/jsl-0.3.0/src/liveconnect/jsj_JavaObject.c +1099 -0
  436. data/vendor/jsl-0.3.0/src/liveconnect/jsj_JavaPackage.c +548 -0
  437. data/vendor/jsl-0.3.0/src/liveconnect/jsj_array.c +207 -0
  438. data/vendor/jsl-0.3.0/src/liveconnect/jsj_class.c +765 -0
  439. data/vendor/jsl-0.3.0/src/liveconnect/jsj_convert.c +954 -0
  440. data/vendor/jsl-0.3.0/src/liveconnect/jsj_field.c +421 -0
  441. data/vendor/jsl-0.3.0/src/liveconnect/jsj_hash.c +504 -0
  442. data/vendor/jsl-0.3.0/src/liveconnect/jsj_hash.h +161 -0
  443. data/vendor/jsl-0.3.0/src/liveconnect/jsj_method.c +1823 -0
  444. data/vendor/jsl-0.3.0/src/liveconnect/jsj_nodl.c +1 -0
  445. data/vendor/jsl-0.3.0/src/liveconnect/jsj_private.h +689 -0
  446. data/vendor/jsl-0.3.0/src/liveconnect/jsj_simpleapi.c +219 -0
  447. data/vendor/jsl-0.3.0/src/liveconnect/jsj_utils.c +513 -0
  448. data/vendor/jsl-0.3.0/src/liveconnect/jsjava.h +313 -0
  449. data/vendor/jsl-0.3.0/src/liveconnect/liveconnect.pkg +3 -0
  450. data/vendor/jsl-0.3.0/src/liveconnect/netscape_javascript_JSObject.h +155 -0
  451. data/vendor/jsl-0.3.0/src/liveconnect/nsCLiveconnect.cpp +785 -0
  452. data/vendor/jsl-0.3.0/src/liveconnect/nsCLiveconnect.h +197 -0
  453. data/vendor/jsl-0.3.0/src/liveconnect/nsCLiveconnectFactory.cpp +163 -0
  454. data/vendor/jsl-0.3.0/src/liveconnect/nsCLiveconnectFactory.h +76 -0
  455. data/vendor/jsl-0.3.0/src/liveconnect/nsILiveconnect.h +195 -0
  456. data/vendor/jsl-0.3.0/src/liveconnect/nsISecureLiveconnect.h +84 -0
  457. data/vendor/jsl-0.3.0/src/liveconnect/nsISecurityContext.h +135 -0
  458. data/vendor/jsl-0.3.0/src/liveconnect/win32.order +6 -0
  459. data/vendor/jsl-0.3.0/src/lock_SunOS.s +114 -0
  460. data/vendor/jsl-0.3.0/src/perfect.js +39 -0
  461. data/vendor/jsl-0.3.0/src/perlconnect/JS.def +6 -0
  462. data/vendor/jsl-0.3.0/src/perlconnect/JS.dsp +107 -0
  463. data/vendor/jsl-0.3.0/src/perlconnect/JS.pm +318 -0
  464. data/vendor/jsl-0.3.0/src/perlconnect/JS.xs +1050 -0
  465. data/vendor/jsl-0.3.0/src/perlconnect/Makefile.PL +67 -0
  466. data/vendor/jsl-0.3.0/src/perlconnect/Makefile.ref +152 -0
  467. data/vendor/jsl-0.3.0/src/perlconnect/PerlConnect.dsp +103 -0
  468. data/vendor/jsl-0.3.0/src/perlconnect/PerlConnect.dsw +59 -0
  469. data/vendor/jsl-0.3.0/src/perlconnect/PerlConnect.pm +126 -0
  470. data/vendor/jsl-0.3.0/src/perlconnect/PerlConnectShell.dsp +89 -0
  471. data/vendor/jsl-0.3.0/src/perlconnect/README.html +345 -0
  472. data/vendor/jsl-0.3.0/src/perlconnect/bg.jpg +0 -0
  473. data/vendor/jsl-0.3.0/src/perlconnect/jsperl.c +1100 -0
  474. data/vendor/jsl-0.3.0/src/perlconnect/jsperl.h +52 -0
  475. data/vendor/jsl-0.3.0/src/perlconnect/jsperlbuild.pl +81 -0
  476. data/vendor/jsl-0.3.0/src/perlconnect/jsperlpvt.h +57 -0
  477. data/vendor/jsl-0.3.0/src/perlconnect/test.js +73 -0
  478. data/vendor/jsl-0.3.0/src/perlconnect/test.pl +244 -0
  479. data/vendor/jsl-0.3.0/src/perlconnect/typemap +121 -0
  480. data/vendor/jsl-0.3.0/src/plify_jsdhash.sed +31 -0
  481. data/vendor/jsl-0.3.0/src/prmjtime.c +646 -0
  482. data/vendor/jsl-0.3.0/src/prmjtime.h +95 -0
  483. data/vendor/jsl-0.3.0/src/resource.h +15 -0
  484. data/vendor/jsl-0.3.0/src/rules.mk +193 -0
  485. data/vendor/jsl-0.3.0/src/win32.order +391 -0
  486. data/vendor/jsl-0.3.0/tests/conf/always_use_option_explicit.js +4 -0
  487. data/vendor/jsl-0.3.0/tests/conf/define.js +8 -0
  488. data/vendor/jsl-0.3.0/tests/conf/jscript_function_extensions-1.js +7 -0
  489. data/vendor/jsl-0.3.0/tests/conf/jscript_function_extensions-2.js +8 -0
  490. data/vendor/jsl-0.3.0/tests/conf/jscript_function_extensions-3.js +27 -0
  491. data/vendor/jsl-0.3.0/tests/conf/jscript_function_extensions-4.js +4 -0
  492. data/vendor/jsl-0.3.0/tests/conf/lambda_assign_requires_semicolon.js +24 -0
  493. data/vendor/jsl-0.3.0/tests/conf/legacy_control_comments.js +8 -0
  494. data/vendor/jsl-0.3.0/tests/control_comments/control_comments.js +33 -0
  495. data/vendor/jsl-0.3.0/tests/control_comments/declare.js +26 -0
  496. data/vendor/jsl-0.3.0/tests/control_comments/import-overflow.js +9 -0
  497. data/vendor/jsl-0.3.0/tests/control_comments/import.js +5 -0
  498. data/vendor/jsl-0.3.0/tests/control_comments/import2.js +2 -0
  499. data/vendor/jsl-0.3.0/tests/control_comments/invalid_fallthru.js +13 -0
  500. data/vendor/jsl-0.3.0/tests/control_comments/option_explicit-with.js +12 -0
  501. data/vendor/jsl-0.3.0/tests/control_comments/option_explicit.js +64 -0
  502. data/vendor/jsl-0.3.0/tests/errors/unterminated_comment.js +8 -0
  503. data/vendor/jsl-0.3.0/tests/html/script_tag_in_js_literal.html +14 -0
  504. data/vendor/jsl-0.3.0/tests/run_tests.pl +71 -0
  505. data/vendor/jsl-0.3.0/tests/warnings/ambiguous_else_stmt.js +21 -0
  506. data/vendor/jsl-0.3.0/tests/warnings/ambiguous_nested_stmt.js +66 -0
  507. data/vendor/jsl-0.3.0/tests/warnings/ambiguous_newline.js +261 -0
  508. data/vendor/jsl-0.3.0/tests/warnings/anon_no_return_value.js +26 -0
  509. data/vendor/jsl-0.3.0/tests/warnings/assign_to_function_call.js +16 -0
  510. data/vendor/jsl-0.3.0/tests/warnings/block_without_braces.js +13 -0
  511. data/vendor/jsl-0.3.0/tests/warnings/comma_separated_stmts.js +17 -0
  512. data/vendor/jsl-0.3.0/tests/warnings/comparison_type_conv.js +44 -0
  513. data/vendor/jsl-0.3.0/tests/warnings/default_not_at_end.js +15 -0
  514. data/vendor/jsl-0.3.0/tests/warnings/dup_option_explicit.js +5 -0
  515. data/vendor/jsl-0.3.0/tests/warnings/duplicate_case_in_switch.js +62 -0
  516. data/vendor/jsl-0.3.0/tests/warnings/duplicate_formal.js +5 -0
  517. data/vendor/jsl-0.3.0/tests/warnings/empty_statement.js +29 -0
  518. data/vendor/jsl-0.3.0/tests/warnings/equal_as_assign.js +7 -0
  519. data/vendor/jsl-0.3.0/tests/warnings/inc_dec_within_stmt-ignore.js +21 -0
  520. data/vendor/jsl-0.3.0/tests/warnings/inc_dec_within_stmt.js +63 -0
  521. data/vendor/jsl-0.3.0/tests/warnings/jsl_cc_not_understood.js +5 -0
  522. data/vendor/jsl-0.3.0/tests/warnings/leading_decimal_point.js +7 -0
  523. data/vendor/jsl-0.3.0/tests/warnings/legacy_cc_not_understood.js +9 -0
  524. data/vendor/jsl-0.3.0/tests/warnings/meaningless_block.js +12 -0
  525. data/vendor/jsl-0.3.0/tests/warnings/misplaced_regex.js +20 -0
  526. data/vendor/jsl-0.3.0/tests/warnings/missing_break.js +87 -0
  527. data/vendor/jsl-0.3.0/tests/warnings/missing_break_for_last_case.js +19 -0
  528. data/vendor/jsl-0.3.0/tests/warnings/missing_default_case.js +51 -0
  529. data/vendor/jsl-0.3.0/tests/warnings/missing_option_explicit.js +5 -0
  530. data/vendor/jsl-0.3.0/tests/warnings/missing_semicolon.js +19 -0
  531. data/vendor/jsl-0.3.0/tests/warnings/multiple_plus_minus.js +10 -0
  532. data/vendor/jsl-0.3.0/tests/warnings/nested_comment.js +6 -0
  533. data/vendor/jsl-0.3.0/tests/warnings/no_return_value.js +25 -0
  534. data/vendor/jsl-0.3.0/tests/warnings/octal_number.js +5 -0
  535. data/vendor/jsl-0.3.0/tests/warnings/parseint_missing_radix.js +15 -0
  536. data/vendor/jsl-0.3.0/tests/warnings/partial_option_explicit.js +5 -0
  537. data/vendor/jsl-0.3.0/tests/warnings/redeclared_var.js +10 -0
  538. data/vendor/jsl-0.3.0/tests/warnings/spidermonkey/bad_backref.js +5 -0
  539. data/vendor/jsl-0.3.0/tests/warnings/spidermonkey/deprecated_usage.js +11 -0
  540. data/vendor/jsl-0.3.0/tests/warnings/spidermonkey/invalid_backref.js +5 -0
  541. data/vendor/jsl-0.3.0/tests/warnings/spidermonkey/trailing_comma.js +5 -0
  542. data/vendor/jsl-0.3.0/tests/warnings/trailing_comma_in_array.js +8 -0
  543. data/vendor/jsl-0.3.0/tests/warnings/trailing_decimal_point.js +7 -0
  544. data/vendor/jsl-0.3.0/tests/warnings/unreachable_code.js +29 -0
  545. data/vendor/jsl-0.3.0/tests/warnings/use_of_label.js +19 -0
  546. data/vendor/jsl-0.3.0/tests/warnings/useless_assign.js +20 -0
  547. data/vendor/jsl-0.3.0/tests/warnings/useless_comparison.js +55 -0
  548. data/vendor/jsl-0.3.0/tests/warnings/useless_void.js +6 -0
  549. data/vendor/jsl-0.3.0/tests/warnings/var_hides_arg.js +4 -0
  550. data/vendor/jsl-0.3.0/tests/warnings/with_statement.js +7 -0
  551. data/vendor/yuicompressor-2.4.2.jar +0 -0
  552. metadata +605 -0
@@ -0,0 +1,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