johnson 2.0.0.pre1 → 2.0.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (311) hide show
  1. data/CHANGELOG.rdoc +12 -0
  2. data/Manifest.txt +4 -285
  3. data/Rakefile +13 -20
  4. data/ext/tracemonkey/global.cc +4 -1
  5. data/ext/tracemonkey/js.cc +30 -33
  6. data/ext/tracemonkey/runtime.cc +96 -6
  7. data/ext/tracemonkey/split_global.cc +0 -5
  8. data/ext/tracemonkey/tracemonkey.h +2 -2
  9. data/lib/johnson.rb +2 -2
  10. data/lib/johnson/runtime.rb +25 -15
  11. data/lib/johnson/tracemonkey/runtime.rb +6 -3
  12. data/vendor/tracemonkey/config/system-headers +1 -3
  13. data/vendor/tracemonkey/jscntxt.h +5 -2
  14. data/vendor/tracemonkey/jsdbgapi.cpp +9 -1
  15. data/vendor/tracemonkey/jsdbgapi.h +4 -0
  16. data/vendor/tracemonkey/tests/ecma/NativeObjects/browser.js +0 -0
  17. data/vendor/tracemonkey/tests/ecma/NativeObjects/jstests.list +0 -0
  18. data/vendor/tracemonkey/tests/ecma_3_1/Object/jstests.list +1 -1
  19. data/vendor/tracemonkey/tests/js1_3/misc/browser.js +0 -0
  20. data/vendor/tracemonkey/tests/js1_3/misc/jstests.list +0 -0
  21. data/vendor/tracemonkey/tests/js1_5/Regress/jstests.list +4 -4
  22. data/vendor/tracemonkey/tests/js1_5/Scope/jstests.list +1 -1
  23. data/vendor/tracemonkey/tests/js1_5/decompilation/jstests.list +2 -2
  24. data/vendor/tracemonkey/tests/js1_7/decompilation/jstests.list +1 -1
  25. data/vendor/tracemonkey/tests/shell.js +2 -1
  26. metadata +51 -309
  27. data/ext/spidermonkey/context.c +0 -116
  28. data/ext/spidermonkey/context.h +0 -19
  29. data/ext/spidermonkey/conversions.c +0 -361
  30. data/ext/spidermonkey/conversions.h +0 -31
  31. data/ext/spidermonkey/debugger.c +0 -234
  32. data/ext/spidermonkey/debugger.h +0 -10
  33. data/ext/spidermonkey/extconf.rb +0 -32
  34. data/ext/spidermonkey/extensions.c +0 -37
  35. data/ext/spidermonkey/extensions.h +0 -12
  36. data/ext/spidermonkey/global.c +0 -40
  37. data/ext/spidermonkey/global.h +0 -11
  38. data/ext/spidermonkey/idhash.c +0 -16
  39. data/ext/spidermonkey/idhash.h +0 -8
  40. data/ext/spidermonkey/immutable_node.c +0 -1153
  41. data/ext/spidermonkey/immutable_node.c.erb +0 -523
  42. data/ext/spidermonkey/immutable_node.h +0 -22
  43. data/ext/spidermonkey/jroot.h +0 -197
  44. data/ext/spidermonkey/js_land_proxy.c +0 -620
  45. data/ext/spidermonkey/js_land_proxy.h +0 -20
  46. data/ext/spidermonkey/ruby_land_proxy.c +0 -618
  47. data/ext/spidermonkey/ruby_land_proxy.h +0 -38
  48. data/ext/spidermonkey/runtime.c +0 -396
  49. data/ext/spidermonkey/runtime.h +0 -27
  50. data/ext/spidermonkey/spidermonkey.c +0 -22
  51. data/ext/spidermonkey/spidermonkey.h +0 -29
  52. data/lib/johnson/spidermonkey.rb +0 -12
  53. data/lib/johnson/spidermonkey/context.rb +0 -10
  54. data/lib/johnson/spidermonkey/debugger.rb +0 -67
  55. data/lib/johnson/spidermonkey/immutable_node.rb +0 -282
  56. data/lib/johnson/spidermonkey/js_land_proxy.rb +0 -64
  57. data/lib/johnson/spidermonkey/mutable_tree_visitor.rb +0 -242
  58. data/lib/johnson/spidermonkey/ruby_land_proxy.rb +0 -17
  59. data/lib/johnson/spidermonkey/runtime.rb +0 -74
  60. data/test/johnson/spidermonkey/context_test.rb +0 -21
  61. data/test/johnson/spidermonkey/immutable_node_test.rb +0 -34
  62. data/test/johnson/spidermonkey/js_land_proxy_test.rb +0 -273
  63. data/test/johnson/spidermonkey/ruby_land_proxy_test.rb +0 -274
  64. data/test/johnson/spidermonkey/runtime_test.rb +0 -41
  65. data/vendor/spidermonkey/.cvsignore +0 -9
  66. data/vendor/spidermonkey/Makefile.in +0 -449
  67. data/vendor/spidermonkey/Makefile.ref +0 -365
  68. data/vendor/spidermonkey/README.html +0 -820
  69. data/vendor/spidermonkey/SpiderMonkey.rsp +0 -12
  70. data/vendor/spidermonkey/Y.js +0 -19
  71. data/vendor/spidermonkey/build.mk +0 -43
  72. data/vendor/spidermonkey/config.mk +0 -192
  73. data/vendor/spidermonkey/config/AIX4.1.mk +0 -65
  74. data/vendor/spidermonkey/config/AIX4.2.mk +0 -64
  75. data/vendor/spidermonkey/config/AIX4.3.mk +0 -65
  76. data/vendor/spidermonkey/config/Darwin.mk +0 -83
  77. data/vendor/spidermonkey/config/Darwin1.3.mk +0 -81
  78. data/vendor/spidermonkey/config/Darwin1.4.mk +0 -41
  79. data/vendor/spidermonkey/config/Darwin5.2.mk +0 -81
  80. data/vendor/spidermonkey/config/Darwin5.3.mk +0 -81
  81. data/vendor/spidermonkey/config/HP-UXB.10.10.mk +0 -77
  82. data/vendor/spidermonkey/config/HP-UXB.10.20.mk +0 -77
  83. data/vendor/spidermonkey/config/HP-UXB.11.00.mk +0 -80
  84. data/vendor/spidermonkey/config/IRIX.mk +0 -87
  85. data/vendor/spidermonkey/config/IRIX5.3.mk +0 -44
  86. data/vendor/spidermonkey/config/IRIX6.1.mk +0 -44
  87. data/vendor/spidermonkey/config/IRIX6.2.mk +0 -44
  88. data/vendor/spidermonkey/config/IRIX6.3.mk +0 -44
  89. data/vendor/spidermonkey/config/IRIX6.5.mk +0 -44
  90. data/vendor/spidermonkey/config/Linux_All.mk +0 -103
  91. data/vendor/spidermonkey/config/Mac_OS10.0.mk +0 -82
  92. data/vendor/spidermonkey/config/OSF1V4.0.mk +0 -72
  93. data/vendor/spidermonkey/config/OSF1V5.0.mk +0 -69
  94. data/vendor/spidermonkey/config/SunOS4.1.4.mk +0 -101
  95. data/vendor/spidermonkey/config/SunOS5.10.mk +0 -50
  96. data/vendor/spidermonkey/config/SunOS5.3.mk +0 -91
  97. data/vendor/spidermonkey/config/SunOS5.4.mk +0 -92
  98. data/vendor/spidermonkey/config/SunOS5.5.1.mk +0 -44
  99. data/vendor/spidermonkey/config/SunOS5.5.mk +0 -87
  100. data/vendor/spidermonkey/config/SunOS5.6.mk +0 -89
  101. data/vendor/spidermonkey/config/SunOS5.7.mk +0 -44
  102. data/vendor/spidermonkey/config/SunOS5.8.mk +0 -44
  103. data/vendor/spidermonkey/config/SunOS5.9.mk +0 -44
  104. data/vendor/spidermonkey/config/WINNT4.0.mk +0 -117
  105. data/vendor/spidermonkey/config/WINNT5.0.mk +0 -117
  106. data/vendor/spidermonkey/config/WINNT5.1.mk +0 -117
  107. data/vendor/spidermonkey/config/WINNT5.2.mk +0 -117
  108. data/vendor/spidermonkey/config/WINNT6.0.mk +0 -117
  109. data/vendor/spidermonkey/config/dgux.mk +0 -64
  110. data/vendor/spidermonkey/editline/Makefile.ref +0 -144
  111. data/vendor/spidermonkey/editline/README +0 -83
  112. data/vendor/spidermonkey/editline/editline.3 +0 -175
  113. data/vendor/spidermonkey/editline/editline.c +0 -1369
  114. data/vendor/spidermonkey/editline/editline.h +0 -135
  115. data/vendor/spidermonkey/editline/sysunix.c +0 -182
  116. data/vendor/spidermonkey/editline/unix.h +0 -82
  117. data/vendor/spidermonkey/fdlibm/.cvsignore +0 -7
  118. data/vendor/spidermonkey/fdlibm/Makefile.in +0 -127
  119. data/vendor/spidermonkey/fdlibm/Makefile.ref +0 -192
  120. data/vendor/spidermonkey/fdlibm/e_acos.c +0 -147
  121. data/vendor/spidermonkey/fdlibm/e_acosh.c +0 -105
  122. data/vendor/spidermonkey/fdlibm/e_asin.c +0 -156
  123. data/vendor/spidermonkey/fdlibm/e_atan2.c +0 -165
  124. data/vendor/spidermonkey/fdlibm/e_atanh.c +0 -110
  125. data/vendor/spidermonkey/fdlibm/e_cosh.c +0 -133
  126. data/vendor/spidermonkey/fdlibm/e_exp.c +0 -202
  127. data/vendor/spidermonkey/fdlibm/e_fmod.c +0 -184
  128. data/vendor/spidermonkey/fdlibm/e_gamma.c +0 -71
  129. data/vendor/spidermonkey/fdlibm/e_gamma_r.c +0 -70
  130. data/vendor/spidermonkey/fdlibm/e_hypot.c +0 -173
  131. data/vendor/spidermonkey/fdlibm/e_j0.c +0 -524
  132. data/vendor/spidermonkey/fdlibm/e_j1.c +0 -523
  133. data/vendor/spidermonkey/fdlibm/e_jn.c +0 -315
  134. data/vendor/spidermonkey/fdlibm/e_lgamma.c +0 -71
  135. data/vendor/spidermonkey/fdlibm/e_lgamma_r.c +0 -347
  136. data/vendor/spidermonkey/fdlibm/e_log.c +0 -184
  137. data/vendor/spidermonkey/fdlibm/e_log10.c +0 -134
  138. data/vendor/spidermonkey/fdlibm/e_pow.c +0 -386
  139. data/vendor/spidermonkey/fdlibm/e_rem_pio2.c +0 -222
  140. data/vendor/spidermonkey/fdlibm/e_remainder.c +0 -120
  141. data/vendor/spidermonkey/fdlibm/e_scalb.c +0 -89
  142. data/vendor/spidermonkey/fdlibm/e_sinh.c +0 -122
  143. data/vendor/spidermonkey/fdlibm/e_sqrt.c +0 -497
  144. data/vendor/spidermonkey/fdlibm/fdlibm.h +0 -273
  145. data/vendor/spidermonkey/fdlibm/fdlibm.mak +0 -1453
  146. data/vendor/spidermonkey/fdlibm/fdlibm.mdp +0 -0
  147. data/vendor/spidermonkey/fdlibm/k_cos.c +0 -135
  148. data/vendor/spidermonkey/fdlibm/k_rem_pio2.c +0 -354
  149. data/vendor/spidermonkey/fdlibm/k_sin.c +0 -114
  150. data/vendor/spidermonkey/fdlibm/k_standard.c +0 -785
  151. data/vendor/spidermonkey/fdlibm/k_tan.c +0 -170
  152. data/vendor/spidermonkey/fdlibm/s_asinh.c +0 -101
  153. data/vendor/spidermonkey/fdlibm/s_atan.c +0 -175
  154. data/vendor/spidermonkey/fdlibm/s_cbrt.c +0 -133
  155. data/vendor/spidermonkey/fdlibm/s_ceil.c +0 -120
  156. data/vendor/spidermonkey/fdlibm/s_copysign.c +0 -72
  157. data/vendor/spidermonkey/fdlibm/s_cos.c +0 -118
  158. data/vendor/spidermonkey/fdlibm/s_erf.c +0 -356
  159. data/vendor/spidermonkey/fdlibm/s_expm1.c +0 -267
  160. data/vendor/spidermonkey/fdlibm/s_fabs.c +0 -70
  161. data/vendor/spidermonkey/fdlibm/s_finite.c +0 -71
  162. data/vendor/spidermonkey/fdlibm/s_floor.c +0 -121
  163. data/vendor/spidermonkey/fdlibm/s_frexp.c +0 -99
  164. data/vendor/spidermonkey/fdlibm/s_ilogb.c +0 -85
  165. data/vendor/spidermonkey/fdlibm/s_isnan.c +0 -74
  166. data/vendor/spidermonkey/fdlibm/s_ldexp.c +0 -66
  167. data/vendor/spidermonkey/fdlibm/s_lib_version.c +0 -73
  168. data/vendor/spidermonkey/fdlibm/s_log1p.c +0 -211
  169. data/vendor/spidermonkey/fdlibm/s_logb.c +0 -79
  170. data/vendor/spidermonkey/fdlibm/s_matherr.c +0 -64
  171. data/vendor/spidermonkey/fdlibm/s_modf.c +0 -132
  172. data/vendor/spidermonkey/fdlibm/s_nextafter.c +0 -124
  173. data/vendor/spidermonkey/fdlibm/s_rint.c +0 -131
  174. data/vendor/spidermonkey/fdlibm/s_scalbn.c +0 -107
  175. data/vendor/spidermonkey/fdlibm/s_signgam.c +0 -40
  176. data/vendor/spidermonkey/fdlibm/s_significand.c +0 -68
  177. data/vendor/spidermonkey/fdlibm/s_sin.c +0 -118
  178. data/vendor/spidermonkey/fdlibm/s_tan.c +0 -112
  179. data/vendor/spidermonkey/fdlibm/s_tanh.c +0 -122
  180. data/vendor/spidermonkey/fdlibm/w_acos.c +0 -78
  181. data/vendor/spidermonkey/fdlibm/w_acosh.c +0 -78
  182. data/vendor/spidermonkey/fdlibm/w_asin.c +0 -80
  183. data/vendor/spidermonkey/fdlibm/w_atan2.c +0 -79
  184. data/vendor/spidermonkey/fdlibm/w_atanh.c +0 -81
  185. data/vendor/spidermonkey/fdlibm/w_cosh.c +0 -77
  186. data/vendor/spidermonkey/fdlibm/w_exp.c +0 -88
  187. data/vendor/spidermonkey/fdlibm/w_fmod.c +0 -78
  188. data/vendor/spidermonkey/fdlibm/w_gamma.c +0 -85
  189. data/vendor/spidermonkey/fdlibm/w_gamma_r.c +0 -81
  190. data/vendor/spidermonkey/fdlibm/w_hypot.c +0 -78
  191. data/vendor/spidermonkey/fdlibm/w_j0.c +0 -105
  192. data/vendor/spidermonkey/fdlibm/w_j1.c +0 -106
  193. data/vendor/spidermonkey/fdlibm/w_jn.c +0 -128
  194. data/vendor/spidermonkey/fdlibm/w_lgamma.c +0 -85
  195. data/vendor/spidermonkey/fdlibm/w_lgamma_r.c +0 -81
  196. data/vendor/spidermonkey/fdlibm/w_log.c +0 -78
  197. data/vendor/spidermonkey/fdlibm/w_log10.c +0 -81
  198. data/vendor/spidermonkey/fdlibm/w_pow.c +0 -99
  199. data/vendor/spidermonkey/fdlibm/w_remainder.c +0 -77
  200. data/vendor/spidermonkey/fdlibm/w_scalb.c +0 -95
  201. data/vendor/spidermonkey/fdlibm/w_sinh.c +0 -77
  202. data/vendor/spidermonkey/fdlibm/w_sqrt.c +0 -77
  203. data/vendor/spidermonkey/javascript-trace.d +0 -73
  204. data/vendor/spidermonkey/js.c +0 -3951
  205. data/vendor/spidermonkey/js.mdp +0 -0
  206. data/vendor/spidermonkey/js.msg +0 -308
  207. data/vendor/spidermonkey/js.pkg +0 -2
  208. data/vendor/spidermonkey/js3240.rc +0 -79
  209. data/vendor/spidermonkey/jsOS240.def +0 -654
  210. data/vendor/spidermonkey/jsapi.c +0 -5836
  211. data/vendor/spidermonkey/jsapi.h +0 -2624
  212. data/vendor/spidermonkey/jsarena.c +0 -450
  213. data/vendor/spidermonkey/jsarena.h +0 -318
  214. data/vendor/spidermonkey/jsarray.c +0 -2996
  215. data/vendor/spidermonkey/jsarray.h +0 -127
  216. data/vendor/spidermonkey/jsatom.c +0 -1045
  217. data/vendor/spidermonkey/jsatom.h +0 -442
  218. data/vendor/spidermonkey/jsbit.h +0 -253
  219. data/vendor/spidermonkey/jsbool.c +0 -176
  220. data/vendor/spidermonkey/jsbool.h +0 -73
  221. data/vendor/spidermonkey/jsclist.h +0 -139
  222. data/vendor/spidermonkey/jscntxt.c +0 -1348
  223. data/vendor/spidermonkey/jscntxt.h +0 -1120
  224. data/vendor/spidermonkey/jscompat.h +0 -57
  225. data/vendor/spidermonkey/jsconfig.h +0 -248
  226. data/vendor/spidermonkey/jsconfig.mk +0 -181
  227. data/vendor/spidermonkey/jscpucfg.c +0 -396
  228. data/vendor/spidermonkey/jscpucfg.h +0 -212
  229. data/vendor/spidermonkey/jsdate.c +0 -2390
  230. data/vendor/spidermonkey/jsdate.h +0 -124
  231. data/vendor/spidermonkey/jsdbgapi.c +0 -1802
  232. data/vendor/spidermonkey/jsdbgapi.h +0 -464
  233. data/vendor/spidermonkey/jsdhash.c +0 -868
  234. data/vendor/spidermonkey/jsdhash.h +0 -592
  235. data/vendor/spidermonkey/jsdtoa.c +0 -3167
  236. data/vendor/spidermonkey/jsdtoa.h +0 -130
  237. data/vendor/spidermonkey/jsdtracef.c +0 -317
  238. data/vendor/spidermonkey/jsdtracef.h +0 -77
  239. data/vendor/spidermonkey/jsemit.c +0 -6909
  240. data/vendor/spidermonkey/jsemit.h +0 -741
  241. data/vendor/spidermonkey/jsexn.c +0 -1371
  242. data/vendor/spidermonkey/jsexn.h +0 -96
  243. data/vendor/spidermonkey/jsfile.c +0 -2736
  244. data/vendor/spidermonkey/jsfile.h +0 -56
  245. data/vendor/spidermonkey/jsfile.msg +0 -90
  246. data/vendor/spidermonkey/jsfun.c +0 -2634
  247. data/vendor/spidermonkey/jsfun.h +0 -254
  248. data/vendor/spidermonkey/jsgc.c +0 -3562
  249. data/vendor/spidermonkey/jsgc.h +0 -403
  250. data/vendor/spidermonkey/jshash.c +0 -476
  251. data/vendor/spidermonkey/jshash.h +0 -151
  252. data/vendor/spidermonkey/jsify.pl +0 -485
  253. data/vendor/spidermonkey/jsinterp.c +0 -7007
  254. data/vendor/spidermonkey/jsinterp.h +0 -525
  255. data/vendor/spidermonkey/jsinvoke.c +0 -43
  256. data/vendor/spidermonkey/jsiter.c +0 -1067
  257. data/vendor/spidermonkey/jsiter.h +0 -122
  258. data/vendor/spidermonkey/jskeyword.tbl +0 -124
  259. data/vendor/spidermonkey/jskwgen.c +0 -460
  260. data/vendor/spidermonkey/jslibmath.h +0 -266
  261. data/vendor/spidermonkey/jslock.c +0 -1309
  262. data/vendor/spidermonkey/jslock.h +0 -313
  263. data/vendor/spidermonkey/jslocko.asm +0 -60
  264. data/vendor/spidermonkey/jslog2.c +0 -94
  265. data/vendor/spidermonkey/jslong.c +0 -264
  266. data/vendor/spidermonkey/jslong.h +0 -412
  267. data/vendor/spidermonkey/jsmath.c +0 -567
  268. data/vendor/spidermonkey/jsmath.h +0 -57
  269. data/vendor/spidermonkey/jsnum.c +0 -1239
  270. data/vendor/spidermonkey/jsnum.h +0 -283
  271. data/vendor/spidermonkey/jsobj.c +0 -5282
  272. data/vendor/spidermonkey/jsobj.h +0 -709
  273. data/vendor/spidermonkey/jsopcode.c +0 -5245
  274. data/vendor/spidermonkey/jsopcode.h +0 -394
  275. data/vendor/spidermonkey/jsopcode.tbl +0 -523
  276. data/vendor/spidermonkey/jsotypes.h +0 -202
  277. data/vendor/spidermonkey/jsparse.c +0 -6704
  278. data/vendor/spidermonkey/jsparse.h +0 -511
  279. data/vendor/spidermonkey/jsprf.c +0 -1264
  280. data/vendor/spidermonkey/jsprf.h +0 -150
  281. data/vendor/spidermonkey/jsproto.tbl +0 -128
  282. data/vendor/spidermonkey/jsprvtd.h +0 -267
  283. data/vendor/spidermonkey/jspubtd.h +0 -744
  284. data/vendor/spidermonkey/jsregexp.c +0 -4364
  285. data/vendor/spidermonkey/jsregexp.h +0 -183
  286. data/vendor/spidermonkey/jsreops.tbl +0 -145
  287. data/vendor/spidermonkey/jsscan.c +0 -2012
  288. data/vendor/spidermonkey/jsscan.h +0 -387
  289. data/vendor/spidermonkey/jsscope.c +0 -1957
  290. data/vendor/spidermonkey/jsscope.h +0 -418
  291. data/vendor/spidermonkey/jsscript.c +0 -1832
  292. data/vendor/spidermonkey/jsscript.h +0 -287
  293. data/vendor/spidermonkey/jsshell.msg +0 -50
  294. data/vendor/spidermonkey/jsstddef.h +0 -83
  295. data/vendor/spidermonkey/jsstr.c +0 -5005
  296. data/vendor/spidermonkey/jsstr.h +0 -641
  297. data/vendor/spidermonkey/jstypes.h +0 -475
  298. data/vendor/spidermonkey/jsutil.c +0 -345
  299. data/vendor/spidermonkey/jsutil.h +0 -157
  300. data/vendor/spidermonkey/jsxdrapi.c +0 -800
  301. data/vendor/spidermonkey/jsxdrapi.h +0 -218
  302. data/vendor/spidermonkey/jsxml.c +0 -8476
  303. data/vendor/spidermonkey/jsxml.h +0 -349
  304. data/vendor/spidermonkey/lock_SunOS.s +0 -119
  305. data/vendor/spidermonkey/perfect.js +0 -39
  306. data/vendor/spidermonkey/plify_jsdhash.sed +0 -36
  307. data/vendor/spidermonkey/prmjtime.c +0 -846
  308. data/vendor/spidermonkey/prmjtime.h +0 -103
  309. data/vendor/spidermonkey/resource.h +0 -15
  310. data/vendor/spidermonkey/rules.mk +0 -197
  311. data/vendor/spidermonkey/win32.order +0 -384
@@ -1,418 +0,0 @@
1
- /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2
- * vim: set ts=8 sw=4 et tw=78:
3
- *
4
- * ***** BEGIN LICENSE BLOCK *****
5
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6
- *
7
- * The contents of this file are subject to the Mozilla Public License Version
8
- * 1.1 (the "License"); you may not use this file except in compliance with
9
- * the License. You may obtain a copy of the License at
10
- * http://www.mozilla.org/MPL/
11
- *
12
- * Software distributed under the License is distributed on an "AS IS" basis,
13
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14
- * for the specific language governing rights and limitations under the
15
- * License.
16
- *
17
- * The Original Code is Mozilla Communicator client code, released
18
- * March 31, 1998.
19
- *
20
- * The Initial Developer of the Original Code is
21
- * Netscape Communications Corporation.
22
- * Portions created by the Initial Developer are Copyright (C) 1998
23
- * the Initial Developer. All Rights Reserved.
24
- *
25
- * Contributor(s):
26
- *
27
- * Alternatively, the contents of this file may be used under the terms of
28
- * either of the GNU General Public License Version 2 or later (the "GPL"),
29
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30
- * in which case the provisions of the GPL or the LGPL are applicable instead
31
- * of those above. If you wish to allow use of your version of this file only
32
- * under the terms of either the GPL or the LGPL, and not to allow others to
33
- * use your version of this file under the terms of the MPL, indicate your
34
- * decision by deleting the provisions above and replace them with the notice
35
- * and other provisions required by the GPL or the LGPL. If you do not delete
36
- * the provisions above, a recipient may use your version of this file under
37
- * the terms of any one of the MPL, the GPL or the LGPL.
38
- *
39
- * ***** END LICENSE BLOCK ***** */
40
-
41
- #ifndef jsscope_h___
42
- #define jsscope_h___
43
- /*
44
- * JS symbol tables.
45
- */
46
- #include "jstypes.h"
47
- #include "jslock.h"
48
- #include "jsobj.h"
49
- #include "jsprvtd.h"
50
- #include "jspubtd.h"
51
-
52
- JS_BEGIN_EXTERN_C
53
-
54
- /*
55
- * Given P independent, non-unique properties each of size S words mapped by
56
- * all scopes in a runtime, construct a property tree of N nodes each of size
57
- * S+L words (L for tree linkage). A nominal L value is 2 for leftmost-child
58
- * and right-sibling links. We hope that the N < P by enough that the space
59
- * overhead of L, and the overhead of scope entries pointing at property tree
60
- * nodes, is worth it.
61
- *
62
- * The tree construction goes as follows. If any empty scope in the runtime
63
- * has a property X added to it, find or create a node under the tree root
64
- * labeled X, and set scope->lastProp to point at that node. If any non-empty
65
- * scope whose most recently added property is labeled Y has another property
66
- * labeled Z added, find or create a node for Z under the node that was added
67
- * for Y, and set scope->lastProp to point at that node.
68
- *
69
- * A property is labeled by its members' values: id, getter, setter, slot,
70
- * attributes, tiny or short id, and a field telling for..in order. Note that
71
- * labels are not unique in the tree, but they are unique among a node's kids
72
- * (barring rare and benign multi-threaded race condition outcomes, see below)
73
- * and along any ancestor line from the tree root to a given leaf node (except
74
- * for the hard case of duplicate formal parameters to a function).
75
- *
76
- * Thus the root of the tree represents all empty scopes, and the first ply
77
- * of the tree represents all scopes containing one property, etc. Each node
78
- * in the tree can stand for any number of scopes having the same ordered set
79
- * of properties, where that node was the last added to the scope. (We need
80
- * not store the root of the tree as a node, and do not -- all we need are
81
- * links to its kids.)
82
- *
83
- * Sidebar on for..in loop order: ECMA requires no particular order, but this
84
- * implementation has promised and delivered property definition order, and
85
- * compatibility is king. We could use an order number per property, which
86
- * would require a sort in js_Enumerate, and an entry order generation number
87
- * per scope. An order number beats a list, which should be doubly-linked for
88
- * O(1) delete. An even better scheme is to use a parent link in the property
89
- * tree, so that the ancestor line can be iterated from scope->lastProp when
90
- * filling in a JSIdArray from back to front. This parent link also helps the
91
- * GC to sweep properties iteratively.
92
- *
93
- * What if a property Y is deleted from a scope? If Y is the last property in
94
- * the scope, we simply adjust the scope's lastProp member after we remove the
95
- * scope's hash-table entry pointing at that property node. The parent link
96
- * mentioned in the for..in sidebar above makes this adjustment O(1). But if
97
- * Y comes between X and Z in the scope, then we might have to "fork" the tree
98
- * at X, leaving X->Y->Z in case other scopes have those properties added in
99
- * that order; and to finish the fork, we'd add a node labeled Z with the path
100
- * X->Z, if it doesn't exist. This could lead to lots of extra nodes, and to
101
- * O(n^2) growth when deleting lots of properties.
102
- *
103
- * Rather, for O(1) growth all around, we should share the path X->Y->Z among
104
- * scopes having those three properties added in that order, and among scopes
105
- * having only X->Z where Y was deleted. All such scopes have a lastProp that
106
- * points to the Z child of Y. But a scope in which Y was deleted does not
107
- * have a table entry for Y, and when iterating that scope by traversing the
108
- * ancestor line from Z, we will have to test for a table entry for each node,
109
- * skipping nodes that lack entries.
110
- *
111
- * What if we add Y again? X->Y->Z->Y is wrong and we'll enumerate Y twice.
112
- * Therefore we must fork in such a case, if not earlier. Because delete is
113
- * "bursty", we should not fork eagerly. Delaying a fork till we are at risk
114
- * of adding Y after it was deleted already requires a flag in the JSScope, to
115
- * wit, SCOPE_MIDDLE_DELETE.
116
- *
117
- * What about thread safety? If the property tree operations done by requests
118
- * are find-node and insert-node, then the only hazard is duplicate insertion.
119
- * This is harmless except for minor bloat. When all requests have ended or
120
- * been suspended, the GC is free to sweep the tree after marking all nodes
121
- * reachable from scopes, performing remove-node operations as needed.
122
- *
123
- * Is the property tree worth it compared to property storage in each table's
124
- * entries? To decide, we must find the relation <> between the words used
125
- * with a property tree and the words required without a tree.
126
- *
127
- * Model all scopes as one super-scope of capacity T entries (T a power of 2).
128
- * Let alpha be the load factor of this double hash-table. With the property
129
- * tree, each entry in the table is a word-sized pointer to a node that can be
130
- * shared by many scopes. But all such pointers are overhead compared to the
131
- * situation without the property tree, where the table stores property nodes
132
- * directly, as entries each of size S words. With the property tree, we need
133
- * L=2 extra words per node for siblings and kids pointers. Without the tree,
134
- * (1-alpha)*S*T words are wasted on free or removed sentinel-entries required
135
- * by double hashing.
136
- *
137
- * Therefore,
138
- *
139
- * (property tree) <> (no property tree)
140
- * N*(S+L) + T <> S*T
141
- * N*(S+L) + T <> P*S + (1-alpha)*S*T
142
- * N*(S+L) + alpha*T + (1-alpha)*T <> P*S + (1-alpha)*S*T
143
- *
144
- * Note that P is alpha*T by definition, so
145
- *
146
- * N*(S+L) + P + (1-alpha)*T <> P*S + (1-alpha)*S*T
147
- * N*(S+L) <> P*S - P + (1-alpha)*S*T - (1-alpha)*T
148
- * N*(S+L) <> (P + (1-alpha)*T) * (S-1)
149
- * N*(S+L) <> (P + (1-alpha)*P/alpha) * (S-1)
150
- * N*(S+L) <> P * (1/alpha) * (S-1)
151
- *
152
- * Let N = P*beta for a compression ratio beta, beta <= 1:
153
- *
154
- * P*beta*(S+L) <> P * (1/alpha) * (S-1)
155
- * beta*(S+L) <> (S-1)/alpha
156
- * beta <> (S-1)/((S+L)*alpha)
157
- *
158
- * For S = 6 (32-bit architectures) and L = 2, the property tree wins iff
159
- *
160
- * beta < 5/(8*alpha)
161
- *
162
- * We ensure that alpha <= .75, so the property tree wins if beta < .83_. An
163
- * average beta from recent Mozilla browser startups was around .6.
164
- *
165
- * Can we reduce L? Observe that the property tree degenerates into a list of
166
- * lists if at most one property Y follows X in all scopes. In or near such a
167
- * case, we waste a word on the right-sibling link outside of the root ply of
168
- * the tree. Note also that the root ply tends to be large, so O(n^2) growth
169
- * searching it is likely, indicating the need for hashing (but with increased
170
- * thread safety costs).
171
- *
172
- * If only K out of N nodes in the property tree have more than one child, we
173
- * could eliminate the sibling link and overlay a children list or hash-table
174
- * pointer on the leftmost-child link (which would then be either null or an
175
- * only-child link; the overlay could be tagged in the low bit of the pointer,
176
- * or flagged elsewhere in the property tree node, although such a flag must
177
- * not be considered when comparing node labels during tree search).
178
- *
179
- * For such a system, L = 1 + (K * averageChildrenTableSize) / N instead of 2.
180
- * If K << N, L approaches 1 and the property tree wins if beta < .95.
181
- *
182
- * We observe that fan-out below the root ply of the property tree appears to
183
- * have extremely low degree (see the MeterPropertyTree code that histograms
184
- * child-counts in jsscope.c), so instead of a hash-table we use a linked list
185
- * of child node pointer arrays ("kid chunks"). The details are isolated in
186
- * jsscope.c; others must treat JSScopeProperty.kids as opaque. We leave it
187
- * strongly typed for debug-ability of the common (null or one-kid) cases.
188
- *
189
- * One final twist (can you stand it?): the mean number of entries per scope
190
- * in Mozilla is < 5, with a large standard deviation (~8). Instead of always
191
- * allocating scope->table, we leave it null while initializing all the other
192
- * scope members as if it were non-null and minimal-length. Until a property
193
- * is added that crosses the threshold of 6 or more entries for hashing, or
194
- * until a "middle delete" occurs, we use linear search from scope->lastProp
195
- * to find a given id, and save on the space overhead of a hash table.
196
- */
197
-
198
- struct JSScope {
199
- JSObjectMap map; /* base class state */
200
- #ifdef JS_THREADSAFE
201
- JSTitle title; /* lock state */
202
- #endif
203
- JSObject *object; /* object that owns this scope */
204
- uint32 shape; /* property cache shape identifier */
205
- uint8 flags; /* flags, see below */
206
- int8 hashShift; /* multiplicative hash shift */
207
- uint16 spare; /* reserved */
208
- uint32 entryCount; /* number of entries in table */
209
- uint32 removedCount; /* removed entry sentinels in table */
210
- JSScopeProperty **table; /* table of ptrs to shared tree nodes */
211
- JSScopeProperty *lastProp; /* pointer to last property added */
212
- };
213
-
214
- #ifdef JS_THREADSAFE
215
- JS_STATIC_ASSERT(offsetof(JSScope, title) == sizeof(JSObjectMap));
216
- #endif
217
-
218
- #define JS_IS_SCOPE_LOCKED(cx, scope) JS_IS_TITLE_LOCKED(cx, &(scope)->title)
219
-
220
- #define OBJ_SCOPE(obj) ((JSScope *)(obj)->map)
221
-
222
- #define SCOPE_MAKE_UNIQUE_SHAPE(cx,scope) \
223
- ((scope)->shape = js_GenerateShape((cx), JS_FALSE, NULL))
224
-
225
- #define SCOPE_EXTEND_SHAPE(cx,scope,sprop) \
226
- JS_BEGIN_MACRO \
227
- if (!(scope)->lastProp || \
228
- (scope)->shape == (scope)->lastProp->shape) { \
229
- (scope)->shape = (sprop)->shape; \
230
- } else { \
231
- (scope)->shape = js_GenerateShape((cx), JS_FALSE, sprop); \
232
- } \
233
- JS_END_MACRO
234
-
235
- /* By definition, hashShift = JS_DHASH_BITS - log2(capacity). */
236
- #define SCOPE_CAPACITY(scope) JS_BIT(JS_DHASH_BITS-(scope)->hashShift)
237
-
238
- /* Scope flags and some macros to hide them from other files than jsscope.c. */
239
- #define SCOPE_MIDDLE_DELETE 0x0001
240
- #define SCOPE_SEALED 0x0002
241
- #define SCOPE_BRANDED 0x0004
242
-
243
- #define SCOPE_HAD_MIDDLE_DELETE(scope) ((scope)->flags & SCOPE_MIDDLE_DELETE)
244
- #define SCOPE_SET_MIDDLE_DELETE(scope) ((scope)->flags |= SCOPE_MIDDLE_DELETE)
245
- #define SCOPE_CLR_MIDDLE_DELETE(scope) ((scope)->flags &= ~SCOPE_MIDDLE_DELETE)
246
-
247
- #define SCOPE_IS_SEALED(scope) ((scope)->flags & SCOPE_SEALED)
248
- #define SCOPE_SET_SEALED(scope) ((scope)->flags |= SCOPE_SEALED)
249
- #if 0
250
- /*
251
- * Don't define this, it can't be done safely because JS_LOCK_OBJ will avoid
252
- * taking the lock if the object owns its scope and the scope is sealed.
253
- */
254
- #undef SCOPE_CLR_SEALED(scope) ((scope)->flags &= ~SCOPE_SEALED)
255
- #endif
256
-
257
- /*
258
- * A branded scope's object contains plain old methods (function-valued
259
- * properties without magic getters and setters), and its scope->shape
260
- * evolves whenever a function value changes.
261
- */
262
- #define SCOPE_IS_BRANDED(scope) ((scope)->flags & SCOPE_BRANDED)
263
- #define SCOPE_SET_BRANDED(scope) ((scope)->flags |= SCOPE_BRANDED)
264
- #define SCOPE_CLR_BRANDED(scope) ((scope)->flags &= ~SCOPE_BRANDED)
265
-
266
- /*
267
- * A little information hiding for scope->lastProp, in case it ever becomes
268
- * a tagged pointer again.
269
- */
270
- #define SCOPE_LAST_PROP(scope) ((scope)->lastProp)
271
- #define SCOPE_REMOVE_LAST_PROP(scope) ((scope)->lastProp = \
272
- (scope)->lastProp->parent)
273
-
274
- struct JSScopeProperty {
275
- jsid id; /* int-tagged jsval/untagged JSAtom* */
276
- JSPropertyOp getter; /* getter and setter hooks or objects */
277
- JSPropertyOp setter;
278
- uint32 slot; /* abstract index in object slots */
279
- uint8 attrs; /* attributes, see jsapi.h JSPROP_* */
280
- uint8 flags; /* flags, see below for defines */
281
- int16 shortid; /* tinyid, or local arg/var index */
282
- JSScopeProperty *parent; /* parent node, reverse for..in order */
283
- JSScopeProperty *kids; /* null, single child, or a tagged ptr
284
- to many-kids data structure */
285
- uint32 shape; /* property cache shape identifier */
286
- };
287
-
288
- /* JSScopeProperty pointer tag bit indicating a collision. */
289
- #define SPROP_COLLISION ((jsuword)1)
290
- #define SPROP_REMOVED ((JSScopeProperty *) SPROP_COLLISION)
291
-
292
- /* Macros to get and set sprop pointer values and collision flags. */
293
- #define SPROP_IS_FREE(sprop) ((sprop) == NULL)
294
- #define SPROP_IS_REMOVED(sprop) ((sprop) == SPROP_REMOVED)
295
- #define SPROP_IS_LIVE(sprop) ((sprop) > SPROP_REMOVED)
296
- #define SPROP_FLAG_COLLISION(spp,sprop) (*(spp) = (JSScopeProperty *) \
297
- ((jsuword)(sprop) | SPROP_COLLISION))
298
- #define SPROP_HAD_COLLISION(sprop) ((jsuword)(sprop) & SPROP_COLLISION)
299
- #define SPROP_FETCH(spp) SPROP_CLEAR_COLLISION(*(spp))
300
-
301
- #define SPROP_CLEAR_COLLISION(sprop) \
302
- ((JSScopeProperty *) ((jsuword)(sprop) & ~SPROP_COLLISION))
303
-
304
- #define SPROP_STORE_PRESERVING_COLLISION(spp, sprop) \
305
- (*(spp) = (JSScopeProperty *) ((jsuword)(sprop) \
306
- | SPROP_HAD_COLLISION(*(spp))))
307
-
308
- /* Bits stored in sprop->flags. */
309
- #define SPROP_MARK 0x01
310
- #define SPROP_IS_ALIAS 0x02
311
- #define SPROP_HAS_SHORTID 0x04
312
- #define SPROP_FLAG_SHAPE_REGEN 0x08
313
-
314
- /*
315
- * If SPROP_HAS_SHORTID is set in sprop->flags, we use sprop->shortid rather
316
- * than id when calling sprop's getter or setter.
317
- */
318
- #define SPROP_USERID(sprop) \
319
- (((sprop)->flags & SPROP_HAS_SHORTID) ? INT_TO_JSVAL((sprop)->shortid) \
320
- : ID_TO_VALUE((sprop)->id))
321
-
322
- #define SPROP_INVALID_SLOT 0xffffffff
323
-
324
- #define SLOT_IN_SCOPE(slot,scope) ((slot) < (scope)->map.freeslot)
325
- #define SPROP_HAS_VALID_SLOT(sprop,scope) SLOT_IN_SCOPE((sprop)->slot, scope)
326
-
327
- #define SPROP_HAS_STUB_GETTER(sprop) (!(sprop)->getter)
328
- #define SPROP_HAS_STUB_SETTER(sprop) (!(sprop)->setter)
329
-
330
- /*
331
- * NB: SPROP_GET must not be called if SPROP_HAS_STUB_GETTER(sprop).
332
- */
333
- #define SPROP_GET(cx,sprop,obj,obj2,vp) \
334
- (((sprop)->attrs & JSPROP_GETTER) \
335
- ? js_InternalGetOrSet(cx, obj, (sprop)->id, \
336
- OBJECT_TO_JSVAL((sprop)->getter), JSACC_READ, \
337
- 0, 0, vp) \
338
- : (sprop)->getter(cx, OBJ_THIS_OBJECT(cx,obj), SPROP_USERID(sprop), vp))
339
-
340
- /*
341
- * NB: SPROP_SET must not be called if (SPROP_HAS_STUB_SETTER(sprop) &&
342
- * !(sprop->attrs & JSPROP_GETTER)).
343
- */
344
- #define SPROP_SET(cx,sprop,obj,obj2,vp) \
345
- (((sprop)->attrs & JSPROP_SETTER) \
346
- ? js_InternalGetOrSet(cx, obj, (sprop)->id, \
347
- OBJECT_TO_JSVAL((sprop)->setter), JSACC_WRITE, \
348
- 1, vp, vp) \
349
- : ((sprop)->attrs & JSPROP_GETTER) \
350
- ? (JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, \
351
- JSMSG_GETTER_ONLY, NULL), JS_FALSE) \
352
- : (sprop)->setter(cx, OBJ_THIS_OBJECT(cx,obj), SPROP_USERID(sprop), vp))
353
-
354
- /* Macro for common expression to test for shared permanent attributes. */
355
- #define SPROP_IS_SHARED_PERMANENT(sprop) \
356
- ((~(sprop)->attrs & (JSPROP_SHARED | JSPROP_PERMANENT)) == 0)
357
-
358
- extern JSScope *
359
- js_GetMutableScope(JSContext *cx, JSObject *obj);
360
-
361
- extern JSScope *
362
- js_NewScope(JSContext *cx, jsrefcount nrefs, JSObjectOps *ops, JSClass *clasp,
363
- JSObject *obj);
364
-
365
- extern void
366
- js_DestroyScope(JSContext *cx, JSScope *scope);
367
-
368
- extern JS_FRIEND_API(JSScopeProperty **)
369
- js_SearchScope(JSScope *scope, jsid id, JSBool adding);
370
-
371
- #define SCOPE_GET_PROPERTY(scope, id) \
372
- SPROP_FETCH(js_SearchScope(scope, id, JS_FALSE))
373
-
374
- #define SCOPE_HAS_PROPERTY(scope, sprop) \
375
- (SCOPE_GET_PROPERTY(scope, (sprop)->id) == (sprop))
376
-
377
- extern JSScopeProperty *
378
- js_AddScopeProperty(JSContext *cx, JSScope *scope, jsid id,
379
- JSPropertyOp getter, JSPropertyOp setter, uint32 slot,
380
- uintN attrs, uintN flags, intN shortid);
381
-
382
- extern JSScopeProperty *
383
- js_ChangeScopePropertyAttrs(JSContext *cx, JSScope *scope,
384
- JSScopeProperty *sprop, uintN attrs, uintN mask,
385
- JSPropertyOp getter, JSPropertyOp setter);
386
-
387
- extern JSBool
388
- js_RemoveScopeProperty(JSContext *cx, JSScope *scope, jsid id);
389
-
390
- extern void
391
- js_ClearScope(JSContext *cx, JSScope *scope);
392
-
393
- /*
394
- * These macros used to inline short code sequences, but they grew over time.
395
- * We retain them for internal backward compatibility, and in case one or both
396
- * ever shrink to inline-able size.
397
- */
398
- #define TRACE_ID(trc, id) js_TraceId(trc, id)
399
- #define TRACE_SCOPE_PROPERTY(trc, sprop) js_TraceScopeProperty(trc, sprop)
400
-
401
- extern void
402
- js_TraceId(JSTracer *trc, jsid id);
403
-
404
- extern void
405
- js_TraceScopeProperty(JSTracer *trc, JSScopeProperty *sprop);
406
-
407
- extern void
408
- js_SweepScopeProperties(JSContext *cx);
409
-
410
- extern JSBool
411
- js_InitPropertyTree(JSRuntime *rt);
412
-
413
- extern void
414
- js_FinishPropertyTree(JSRuntime *rt);
415
-
416
- JS_END_EXTERN_C
417
-
418
- #endif /* jsscope_h___ */
@@ -1,1832 +0,0 @@
1
- /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2
- * vim: set ts=8 sw=4 et tw=78:
3
- *
4
- * ***** BEGIN LICENSE BLOCK *****
5
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6
- *
7
- * The contents of this file are subject to the Mozilla Public License Version
8
- * 1.1 (the "License"); you may not use this file except in compliance with
9
- * the License. You may obtain a copy of the License at
10
- * http://www.mozilla.org/MPL/
11
- *
12
- * Software distributed under the License is distributed on an "AS IS" basis,
13
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14
- * for the specific language governing rights and limitations under the
15
- * License.
16
- *
17
- * The Original Code is Mozilla Communicator client code, released
18
- * March 31, 1998.
19
- *
20
- * The Initial Developer of the Original Code is
21
- * Netscape Communications Corporation.
22
- * Portions created by the Initial Developer are Copyright (C) 1998
23
- * the Initial Developer. All Rights Reserved.
24
- *
25
- * Contributor(s):
26
- *
27
- * Alternatively, the contents of this file may be used under the terms of
28
- * either of the GNU General Public License Version 2 or later (the "GPL"),
29
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30
- * in which case the provisions of the GPL or the LGPL are applicable instead
31
- * of those above. If you wish to allow use of your version of this file only
32
- * under the terms of either the GPL or the LGPL, and not to allow others to
33
- * use your version of this file under the terms of the MPL, indicate your
34
- * decision by deleting the provisions above and replace them with the notice
35
- * and other provisions required by the GPL or the LGPL. If you do not delete
36
- * the provisions above, a recipient may use your version of this file under
37
- * the terms of any one of the MPL, the GPL or the LGPL.
38
- *
39
- * ***** END LICENSE BLOCK ***** */
40
-
41
- /*
42
- * JS script operations.
43
- */
44
- #include "jsstddef.h"
45
- #include <string.h>
46
- #include "jstypes.h"
47
- #include "jsutil.h" /* Added by JSIFY */
48
- #include "jsprf.h"
49
- #include "jsapi.h"
50
- #include "jsatom.h"
51
- #include "jscntxt.h"
52
- #include "jsconfig.h"
53
- #include "jsdbgapi.h"
54
- #include "jsemit.h"
55
- #include "jsfun.h"
56
- #include "jsinterp.h"
57
- #include "jslock.h"
58
- #include "jsnum.h"
59
- #include "jsopcode.h"
60
- #include "jsparse.h"
61
- #include "jsscript.h"
62
- #if JS_HAS_XDR
63
- #include "jsxdrapi.h"
64
- #endif
65
-
66
- #if JS_HAS_SCRIPT_OBJECT
67
-
68
- static const char js_script_exec_str[] = "Script.prototype.exec";
69
- static const char js_script_compile_str[] = "Script.prototype.compile";
70
-
71
- /*
72
- * This routine requires that obj has been locked previously.
73
- */
74
- static jsint
75
- GetScriptExecDepth(JSContext *cx, JSObject *obj)
76
- {
77
- jsval v;
78
-
79
- JS_ASSERT(JS_IS_OBJ_LOCKED(cx, obj));
80
- v = LOCKED_OBJ_GET_SLOT(obj, JSSLOT_START(&js_ScriptClass));
81
- return JSVAL_TO_INT(v);
82
- }
83
-
84
- static void
85
- AdjustScriptExecDepth(JSContext *cx, JSObject *obj, jsint delta)
86
- {
87
- jsint execDepth;
88
-
89
- JS_LOCK_OBJ(cx, obj);
90
- execDepth = GetScriptExecDepth(cx, obj);
91
- LOCKED_OBJ_SET_SLOT(obj, JSSLOT_START(&js_ScriptClass),
92
- INT_TO_JSVAL(execDepth + delta));
93
- JS_UNLOCK_OBJ(cx, obj);
94
- }
95
-
96
- #if JS_HAS_TOSOURCE
97
- static JSBool
98
- script_toSource(JSContext *cx, uintN argc, jsval *vp)
99
- {
100
- JSObject *obj;
101
- uint32 indent;
102
- JSScript *script;
103
- size_t i, j, k, n;
104
- char buf[16];
105
- jschar *s, *t;
106
- JSString *str;
107
-
108
- obj = JS_THIS_OBJECT(cx, vp);
109
- if (!JS_InstanceOf(cx, obj, &js_ScriptClass, vp + 2))
110
- return JS_FALSE;
111
-
112
- indent = 0;
113
- if (argc != 0) {
114
- indent = js_ValueToECMAUint32(cx, &vp[2]);
115
- if (JSVAL_IS_NULL(vp[2]))
116
- return JS_FALSE;
117
- }
118
-
119
- script = (JSScript *) JS_GetPrivate(cx, obj);
120
-
121
- /* Let n count the source string length, j the "front porch" length. */
122
- j = JS_snprintf(buf, sizeof buf, "(new %s(", js_ScriptClass.name);
123
- n = j + 2;
124
- if (!script) {
125
- /* Let k count the constructor argument string length. */
126
- k = 0;
127
- s = NULL; /* quell GCC overwarning */
128
- } else {
129
- str = JS_DecompileScript(cx, script, "Script.prototype.toSource",
130
- (uintN)indent);
131
- if (!str)
132
- return JS_FALSE;
133
- str = js_QuoteString(cx, str, '\'');
134
- if (!str)
135
- return JS_FALSE;
136
- JSSTRING_CHARS_AND_LENGTH(str, s, k);
137
- n += k;
138
- }
139
-
140
- /* Allocate the source string and copy into it. */
141
- t = (jschar *) JS_malloc(cx, (n + 1) * sizeof(jschar));
142
- if (!t)
143
- return JS_FALSE;
144
- for (i = 0; i < j; i++)
145
- t[i] = buf[i];
146
- for (j = 0; j < k; i++, j++)
147
- t[i] = s[j];
148
- t[i++] = ')';
149
- t[i++] = ')';
150
- t[i] = 0;
151
-
152
- /* Create and return a JS string for t. */
153
- str = JS_NewUCString(cx, t, n);
154
- if (!str) {
155
- JS_free(cx, t);
156
- return JS_FALSE;
157
- }
158
- *vp = STRING_TO_JSVAL(str);
159
- return JS_TRUE;
160
- }
161
- #endif /* JS_HAS_TOSOURCE */
162
-
163
- static JSBool
164
- script_toString(JSContext *cx, uintN argc, jsval *vp)
165
- {
166
- uint32 indent;
167
- JSObject *obj;
168
- JSScript *script;
169
- JSString *str;
170
-
171
- indent = 0;
172
- if (argc != 0) {
173
- indent = js_ValueToECMAUint32(cx, &vp[2]);
174
- if (JSVAL_IS_NULL(vp[2]))
175
- return JS_FALSE;
176
- }
177
-
178
- obj = JS_THIS_OBJECT(cx, vp);
179
- if (!JS_InstanceOf(cx, obj, &js_ScriptClass, vp + 2))
180
- return JS_FALSE;
181
- script = (JSScript *) JS_GetPrivate(cx, obj);
182
- if (!script) {
183
- *vp = STRING_TO_JSVAL(cx->runtime->emptyString);
184
- return JS_TRUE;
185
- }
186
-
187
- str = JS_DecompileScript(cx, script, "Script.prototype.toString",
188
- (uintN)indent);
189
- if (!str)
190
- return JS_FALSE;
191
- *vp = STRING_TO_JSVAL(str);
192
- return JS_TRUE;
193
- }
194
-
195
- static JSBool
196
- script_compile_sub(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
197
- jsval *rval)
198
- {
199
- JSString *str;
200
- JSObject *scopeobj;
201
- jsval v;
202
- JSScript *script, *oldscript;
203
- JSStackFrame *fp, *caller;
204
- const char *file;
205
- uintN line;
206
- JSPrincipals *principals;
207
- uint32 tcflags;
208
- jsint execDepth;
209
-
210
- /* Make sure obj is a Script object. */
211
- if (!JS_InstanceOf(cx, obj, &js_ScriptClass, argv))
212
- return JS_FALSE;
213
-
214
- /* If no args, leave private undefined and return early. */
215
- if (argc == 0)
216
- goto out;
217
-
218
- /* Otherwise, the first arg is the script source to compile. */
219
- str = js_ValueToString(cx, argv[0]);
220
- if (!str)
221
- return JS_FALSE;
222
- argv[0] = STRING_TO_JSVAL(str);
223
-
224
- scopeobj = NULL;
225
- if (argc >= 2) {
226
- if (!js_ValueToObject(cx, argv[1], &scopeobj))
227
- return JS_FALSE;
228
- argv[1] = OBJECT_TO_JSVAL(scopeobj);
229
- }
230
-
231
- /* Compile using the caller's scope chain, which js_Invoke passes to fp. */
232
- fp = cx->fp;
233
- caller = JS_GetScriptedCaller(cx, fp);
234
- JS_ASSERT(!caller || fp->scopeChain == caller->scopeChain);
235
-
236
- if (caller) {
237
- if (!scopeobj) {
238
- scopeobj = js_GetScopeChain(cx, caller);
239
- if (!scopeobj)
240
- return JS_FALSE;
241
- fp->scopeChain = scopeobj; /* for the compiler's benefit */
242
- }
243
-
244
- principals = JS_EvalFramePrincipals(cx, fp, caller);
245
- file = js_ComputeFilename(cx, caller, principals, &line);
246
- } else {
247
- file = NULL;
248
- line = 0;
249
- principals = NULL;
250
- }
251
-
252
- /* Ensure we compile this script with the right (inner) principals. */
253
- scopeobj = js_CheckScopeChainValidity(cx, scopeobj, js_script_compile_str);
254
- if (!scopeobj)
255
- return JS_FALSE;
256
-
257
- /*
258
- * Compile the new script using the caller's scope chain, a la eval().
259
- * Unlike jsobj.c:obj_eval, however, we do not pass TCF_COMPILE_N_GO in
260
- * tcflags, because compilation is here separated from execution, and the
261
- * run-time scope chain may not match the compile-time. JSFRAME_EVAL is
262
- * tested in jsemit.c and jsscan.c to optimize based on identity of run-
263
- * and compile-time scope.
264
- */
265
- fp->flags |= JSFRAME_SCRIPT_OBJECT;
266
- tcflags = 0;
267
- script = js_CompileScript(cx, scopeobj, principals, tcflags,
268
- JSSTRING_CHARS(str), JSSTRING_LENGTH(str),
269
- NULL, file, line);
270
- if (!script)
271
- return JS_FALSE;
272
-
273
- JS_LOCK_OBJ(cx, obj);
274
- execDepth = GetScriptExecDepth(cx, obj);
275
-
276
- /*
277
- * execDepth must be 0 to allow compilation here, otherwise the JSScript
278
- * struct can be released while running.
279
- */
280
- if (execDepth > 0) {
281
- JS_UNLOCK_OBJ(cx, obj);
282
- JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
283
- JSMSG_COMPILE_EXECED_SCRIPT);
284
- return JS_FALSE;
285
- }
286
-
287
- /* Swap script for obj's old script, if any. */
288
- v = LOCKED_OBJ_GET_SLOT(obj, JSSLOT_PRIVATE);
289
- oldscript = !JSVAL_IS_VOID(v) ? JSVAL_TO_PRIVATE(v) : NULL;
290
- LOCKED_OBJ_SET_SLOT(obj, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(script));
291
- JS_UNLOCK_OBJ(cx, obj);
292
-
293
- if (oldscript)
294
- js_DestroyScript(cx, oldscript);
295
-
296
- script->object = obj;
297
- js_CallNewScriptHook(cx, script, NULL);
298
-
299
- out:
300
- /* Return the object. */
301
- *rval = OBJECT_TO_JSVAL(obj);
302
- return JS_TRUE;
303
- }
304
-
305
- static JSBool
306
- script_compile(JSContext *cx, uintN argc, jsval *vp)
307
- {
308
- return script_compile_sub(cx, JS_THIS_OBJECT(cx, vp), argc, vp + 2, vp);
309
- }
310
-
311
- static JSBool
312
- script_exec_sub(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
313
- jsval *rval)
314
- {
315
- JSObject *scopeobj, *parent;
316
- JSStackFrame *fp, *caller;
317
- JSPrincipals *principals;
318
- JSScript *script;
319
- JSBool ok;
320
-
321
- if (!JS_InstanceOf(cx, obj, &js_ScriptClass, argv))
322
- return JS_FALSE;
323
-
324
- scopeobj = NULL;
325
- if (argc != 0) {
326
- if (!js_ValueToObject(cx, argv[0], &scopeobj))
327
- return JS_FALSE;
328
- argv[0] = OBJECT_TO_JSVAL(scopeobj);
329
- }
330
-
331
- /*
332
- * Emulate eval() by using caller's this, var object, sharp array, etc.,
333
- * all propagated by js_Execute via a non-null fourth (down) argument to
334
- * js_Execute. If there is no scripted caller, js_Execute uses its second
335
- * (chain) argument to set the exec frame's varobj, thisp, and scopeChain.
336
- *
337
- * Unlike eval, which the compiler detects, Script.prototype.exec may be
338
- * called from a lightweight function, or even from native code (in which
339
- * case fp->varobj and fp->scopeChain are null). If exec is called from
340
- * a lightweight function, we will need to get a Call object representing
341
- * its frame, to act as the var object and scope chain head.
342
- */
343
- fp = cx->fp;
344
- caller = JS_GetScriptedCaller(cx, fp);
345
- if (caller && !caller->varobj) {
346
- /* Called from a lightweight function. */
347
- JS_ASSERT(caller->fun && !JSFUN_HEAVYWEIGHT_TEST(caller->fun->flags));
348
-
349
- /* Scope chain links from Call object to callee's parent. */
350
- parent = OBJ_GET_PARENT(cx, caller->callee);
351
- if (!js_GetCallObject(cx, caller, parent))
352
- return JS_FALSE;
353
- }
354
-
355
- if (!scopeobj) {
356
- /* No scope object passed in: try to use the caller's scope chain. */
357
- if (caller) {
358
- /*
359
- * Load caller->scopeChain after the conditional js_GetCallObject
360
- * call above, which resets scopeChain as well as varobj.
361
- */
362
- scopeobj = js_GetScopeChain(cx, caller);
363
- if (!scopeobj)
364
- return JS_FALSE;
365
- } else {
366
- /*
367
- * Called from native code, so we don't know what scope object to
368
- * use. We could use parent (see above), but Script.prototype.exec
369
- * might be a shared/sealed "superglobal" method. A more general
370
- * approach would use cx->globalObject, which will be the same as
371
- * exec.__parent__ in the non-superglobal case. In the superglobal
372
- * case it's the right object: the global, not the superglobal.
373
- */
374
- scopeobj = cx->globalObject;
375
- }
376
- }
377
-
378
- scopeobj = js_CheckScopeChainValidity(cx, scopeobj, js_script_exec_str);
379
- if (!scopeobj)
380
- return JS_FALSE;
381
-
382
- /* Keep track of nesting depth for the script. */
383
- AdjustScriptExecDepth(cx, obj, 1);
384
-
385
- /* Must get to out label after this */
386
- script = (JSScript *) JS_GetPrivate(cx, obj);
387
- if (!script) {
388
- ok = JS_FALSE;
389
- goto out;
390
- }
391
-
392
- /* Belt-and-braces: check that this script object has access to scopeobj. */
393
- principals = script->principals;
394
- ok = js_CheckPrincipalsAccess(cx, scopeobj, principals,
395
- CLASS_ATOM(cx, Script));
396
- if (!ok)
397
- goto out;
398
-
399
- ok = js_Execute(cx, scopeobj, script, caller, JSFRAME_EVAL, rval);
400
-
401
- out:
402
- AdjustScriptExecDepth(cx, obj, -1);
403
- return ok;
404
- }
405
-
406
- static JSBool
407
- script_exec(JSContext *cx, uintN argc, jsval *vp)
408
- {
409
- return script_exec_sub(cx, JS_THIS_OBJECT(cx, vp), argc, vp + 2, vp);
410
- }
411
-
412
- #endif /* JS_HAS_SCRIPT_OBJECT */
413
-
414
- #if JS_HAS_XDR
415
-
416
- JSBool
417
- js_XDRScript(JSXDRState *xdr, JSScript **scriptp, JSBool *hasMagic)
418
- {
419
- JSContext *cx;
420
- JSScript *script, *oldscript;
421
- JSBool ok;
422
- jsbytecode *code;
423
- uint32 length, lineno, depth, magic;
424
- uint32 natoms, nsrcnotes, ntrynotes, nobjects, nregexps, i;
425
- uint32 prologLength, version;
426
- JSTempValueRooter tvr;
427
- JSPrincipals *principals;
428
- uint32 encodeable;
429
- JSBool filenameWasSaved;
430
- jssrcnote *notes, *sn;
431
-
432
- cx = xdr->cx;
433
- script = *scriptp;
434
- nsrcnotes = ntrynotes = natoms = nobjects = nregexps = 0;
435
- filenameWasSaved = JS_FALSE;
436
- notes = NULL;
437
-
438
- if (xdr->mode == JSXDR_ENCODE)
439
- magic = JSXDR_MAGIC_SCRIPT_CURRENT;
440
- if (!JS_XDRUint32(xdr, &magic))
441
- return JS_FALSE;
442
- if (magic != JSXDR_MAGIC_SCRIPT_CURRENT) {
443
- /* We do not provide binary compatibility with older scripts. */
444
- if (!hasMagic) {
445
- JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
446
- JSMSG_BAD_SCRIPT_MAGIC);
447
- return JS_FALSE;
448
- }
449
- *hasMagic = JS_FALSE;
450
- return JS_TRUE;
451
- }
452
- if (hasMagic)
453
- *hasMagic = JS_TRUE;
454
-
455
- if (xdr->mode == JSXDR_ENCODE) {
456
- length = script->length;
457
- prologLength = PTRDIFF(script->main, script->code, jsbytecode);
458
- JS_ASSERT((int16)script->version != JSVERSION_UNKNOWN);
459
- version = (uint32)script->version | (script->ngvars << 16);
460
- lineno = (uint32)script->lineno;
461
- depth = (uint32)script->depth;
462
- natoms = (uint32)script->atomMap.length;
463
-
464
- /* Count the srcnotes, keeping notes pointing at the first one. */
465
- notes = SCRIPT_NOTES(script);
466
- for (sn = notes; !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn))
467
- continue;
468
- nsrcnotes = PTRDIFF(sn, notes, jssrcnote);
469
- nsrcnotes++; /* room for the terminator */
470
-
471
- if (script->objectsOffset != 0)
472
- nobjects = JS_SCRIPT_OBJECTS(script)->length;
473
- if (script->regexpsOffset != 0)
474
- nregexps = JS_SCRIPT_REGEXPS(script)->length;
475
- if (script->trynotesOffset != 0)
476
- ntrynotes = JS_SCRIPT_TRYNOTES(script)->length;
477
- }
478
-
479
- if (!JS_XDRUint32(xdr, &length))
480
- return JS_FALSE;
481
- if (!JS_XDRUint32(xdr, &prologLength))
482
- return JS_FALSE;
483
- if (!JS_XDRUint32(xdr, &version))
484
- return JS_FALSE;
485
-
486
- /*
487
- * To fuse allocations, we need srcnote, atom, objects, regexp and trynote
488
- * counts early.
489
- */
490
- if (!JS_XDRUint32(xdr, &natoms))
491
- return JS_FALSE;
492
- if (!JS_XDRUint32(xdr, &nsrcnotes))
493
- return JS_FALSE;
494
- if (!JS_XDRUint32(xdr, &ntrynotes))
495
- return JS_FALSE;
496
- if (!JS_XDRUint32(xdr, &nobjects))
497
- return JS_FALSE;
498
- if (!JS_XDRUint32(xdr, &nregexps))
499
- return JS_FALSE;
500
-
501
- if (xdr->mode == JSXDR_DECODE) {
502
- script = js_NewScript(cx, length, nsrcnotes, natoms, nobjects, nregexps,
503
- ntrynotes);
504
- if (!script)
505
- return JS_FALSE;
506
-
507
- script->main += prologLength;
508
- script->version = (JSVersion) (version & 0xffff);
509
- script->ngvars = (uint16) (version >> 16);
510
-
511
- /* If we know nsrcnotes, we allocated space for notes in script. */
512
- notes = SCRIPT_NOTES(script);
513
- *scriptp = script;
514
- JS_PUSH_TEMP_ROOT_SCRIPT(cx, script, &tvr);
515
- }
516
-
517
- /*
518
- * Control hereafter must goto error on failure, in order for the
519
- * DECODE case to destroy script.
520
- */
521
- oldscript = xdr->script;
522
- code = script->code;
523
- if (xdr->mode == JSXDR_ENCODE) {
524
- code = js_UntrapScriptCode(cx, script);
525
- if (!code)
526
- goto error;
527
- }
528
-
529
- xdr->script = script;
530
- ok = JS_XDRBytes(xdr, (char *) code, length * sizeof(jsbytecode));
531
-
532
- if (code != script->code)
533
- JS_free(cx, code);
534
-
535
- if (!ok)
536
- goto error;
537
-
538
- if (!JS_XDRBytes(xdr, (char *)notes, nsrcnotes * sizeof(jssrcnote)) ||
539
- !JS_XDRCStringOrNull(xdr, (char **)&script->filename) ||
540
- !JS_XDRUint32(xdr, &lineno) ||
541
- !JS_XDRUint32(xdr, &depth)) {
542
- goto error;
543
- }
544
-
545
- if (xdr->mode == JSXDR_ENCODE) {
546
- principals = script->principals;
547
- encodeable = (cx->runtime->principalsTranscoder != NULL);
548
- if (!JS_XDRUint32(xdr, &encodeable))
549
- goto error;
550
- if (encodeable &&
551
- !cx->runtime->principalsTranscoder(xdr, &principals)) {
552
- goto error;
553
- }
554
- } else {
555
- if (!JS_XDRUint32(xdr, &encodeable))
556
- goto error;
557
- if (encodeable) {
558
- if (!cx->runtime->principalsTranscoder) {
559
- JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
560
- JSMSG_CANT_DECODE_PRINCIPALS);
561
- goto error;
562
- }
563
- if (!cx->runtime->principalsTranscoder(xdr, &principals))
564
- goto error;
565
- script->principals = principals;
566
- }
567
- }
568
-
569
- if (xdr->mode == JSXDR_DECODE) {
570
- const char *filename = script->filename;
571
- if (filename) {
572
- filename = js_SaveScriptFilename(cx, filename);
573
- if (!filename)
574
- goto error;
575
- JS_free(cx, (void *) script->filename);
576
- script->filename = filename;
577
- filenameWasSaved = JS_TRUE;
578
- }
579
- script->lineno = (uintN)lineno;
580
- script->depth = (uintN)depth;
581
- }
582
-
583
- for (i = 0; i != natoms; ++i) {
584
- if (!js_XDRAtom(xdr, &script->atomMap.vector[i]))
585
- goto error;
586
- }
587
-
588
- /*
589
- * Here looping from 0-to-length to xdr objects is essential. It ensures
590
- * that block objects from the script->objects will be written and
591
- * restored in the outer-to-inner order. block_xdrObject uses this to
592
- * restore the parent chain.
593
- */
594
- for (i = 0; i != nobjects; ++i) {
595
- if (!js_XDRObject(xdr, &JS_SCRIPT_OBJECTS(script)->vector[i]))
596
- goto error;
597
- }
598
- for (i = 0; i != nregexps; ++i) {
599
- if (!js_XDRObject(xdr, &JS_SCRIPT_REGEXPS(script)->vector[i]))
600
- goto error;
601
- }
602
-
603
- if (ntrynotes != 0) {
604
- /*
605
- * We combine tn->kind and tn->stackDepth when serializing as XDR is not
606
- * efficient when serializing small integer types.
607
- */
608
- JSTryNote *tn, *tnfirst;
609
- uint32 kindAndDepth;
610
- JS_STATIC_ASSERT(sizeof(tn->kind) == sizeof(uint8));
611
- JS_STATIC_ASSERT(sizeof(tn->stackDepth) == sizeof(uint16));
612
-
613
- tnfirst = JS_SCRIPT_TRYNOTES(script)->vector;
614
- JS_ASSERT(JS_SCRIPT_TRYNOTES(script)->length == ntrynotes);
615
- tn = tnfirst + ntrynotes;
616
- do {
617
- --tn;
618
- if (xdr->mode == JSXDR_ENCODE) {
619
- kindAndDepth = ((uint32)tn->kind << 16)
620
- | (uint32)tn->stackDepth;
621
- }
622
- if (!JS_XDRUint32(xdr, &kindAndDepth) ||
623
- !JS_XDRUint32(xdr, &tn->start) ||
624
- !JS_XDRUint32(xdr, &tn->length)) {
625
- goto error;
626
- }
627
- if (xdr->mode == JSXDR_DECODE) {
628
- tn->kind = (uint8)(kindAndDepth >> 16);
629
- tn->stackDepth = (uint16)kindAndDepth;
630
- }
631
- } while (tn != tnfirst);
632
- }
633
-
634
- xdr->script = oldscript;
635
- if (xdr->mode == JSXDR_DECODE)
636
- JS_POP_TEMP_ROOT(cx, &tvr);
637
- return JS_TRUE;
638
-
639
- error:
640
- if (xdr->mode == JSXDR_DECODE) {
641
- JS_POP_TEMP_ROOT(cx, &tvr);
642
- if (script->filename && !filenameWasSaved) {
643
- JS_free(cx, (void *) script->filename);
644
- script->filename = NULL;
645
- }
646
- js_DestroyScript(cx, script);
647
- *scriptp = NULL;
648
- }
649
- xdr->script = oldscript;
650
- return JS_FALSE;
651
- }
652
-
653
- #if JS_HAS_SCRIPT_OBJECT && JS_HAS_XDR_FREEZE_THAW
654
- /*
655
- * These cannot be exposed to web content, and chrome does not need them, so
656
- * we take them out of the Mozilla client altogether. Fortunately, there is
657
- * no way to serialize a native function (see fun_xdrObject in jsfun.c).
658
- */
659
-
660
- static JSBool
661
- script_freeze(JSContext *cx, uintN argc, jsval *vp)
662
- {
663
- JSObject *obj;
664
- JSXDRState *xdr;
665
- JSScript *script;
666
- JSBool ok, hasMagic;
667
- uint32 len;
668
- void *buf;
669
- JSString *str;
670
-
671
- obj = JS_THIS_OBJECT(cx, vp);
672
- if (!JS_InstanceOf(cx, obj, &js_ScriptClass, vp + 2))
673
- return JS_FALSE;
674
- script = (JSScript *) JS_GetPrivate(cx, obj);
675
- if (!script)
676
- return JS_TRUE;
677
-
678
- /* create new XDR */
679
- xdr = JS_XDRNewMem(cx, JSXDR_ENCODE);
680
- if (!xdr)
681
- return JS_FALSE;
682
-
683
- /* write */
684
- ok = js_XDRScript(xdr, &script, &hasMagic);
685
- if (!ok)
686
- goto out;
687
- if (!hasMagic) {
688
- *vp = JSVAL_VOID;
689
- goto out;
690
- }
691
-
692
- buf = JS_XDRMemGetData(xdr, &len);
693
- if (!buf) {
694
- ok = JS_FALSE;
695
- goto out;
696
- }
697
-
698
- JS_ASSERT((jsword)buf % sizeof(jschar) == 0);
699
- len /= sizeof(jschar);
700
- #if IS_BIG_ENDIAN
701
- {
702
- jschar *chars;
703
- uint32 i;
704
-
705
- /* Swap bytes in Unichars to keep frozen strings machine-independent. */
706
- chars = (jschar *)buf;
707
- for (i = 0; i < len; i++)
708
- chars[i] = JSXDR_SWAB16(chars[i]);
709
- }
710
- #endif
711
- str = JS_NewUCStringCopyN(cx, (jschar *)buf, len);
712
- if (!str) {
713
- ok = JS_FALSE;
714
- goto out;
715
- }
716
-
717
- *vp = STRING_TO_JSVAL(str);
718
-
719
- out:
720
- JS_XDRDestroy(xdr);
721
- return ok;
722
- }
723
-
724
- static JSBool
725
- script_thaw(JSContext *cx, uintN argc, jsval *vp)
726
- {
727
- JSObject *obj;
728
- JSXDRState *xdr;
729
- JSString *str;
730
- void *buf;
731
- uint32 len;
732
- jsval v;
733
- JSScript *script, *oldscript;
734
- JSBool ok, hasMagic;
735
- jsint execDepth;
736
-
737
- obj = JS_THIS_OBJECT(cx, vp);
738
- if (!JS_InstanceOf(cx, obj, &js_ScriptClass, vp + 2))
739
- return JS_FALSE;
740
-
741
- if (argc == 0)
742
- return JS_TRUE;
743
- str = js_ValueToString(cx, vp[2]);
744
- if (!str)
745
- return JS_FALSE;
746
- vp[2] = STRING_TO_JSVAL(str);
747
-
748
- /* create new XDR */
749
- xdr = JS_XDRNewMem(cx, JSXDR_DECODE);
750
- if (!xdr)
751
- return JS_FALSE;
752
-
753
- JSSTRING_CHARS_AND_LENGTH(str, buf, len);
754
- #if IS_BIG_ENDIAN
755
- {
756
- jschar *from, *to;
757
- uint32 i;
758
-
759
- /* Swap bytes in Unichars to keep frozen strings machine-independent. */
760
- from = (jschar *)buf;
761
- to = (jschar *) JS_malloc(cx, len * sizeof(jschar));
762
- if (!to) {
763
- JS_XDRDestroy(xdr);
764
- return JS_FALSE;
765
- }
766
- for (i = 0; i < len; i++)
767
- to[i] = JSXDR_SWAB16(from[i]);
768
- buf = (char *)to;
769
- }
770
- #endif
771
- len *= sizeof(jschar);
772
- JS_XDRMemSetData(xdr, buf, len);
773
-
774
- /* XXXbe should magic mismatch be error, or false return value? */
775
- ok = js_XDRScript(xdr, &script, &hasMagic);
776
- if (!ok)
777
- goto out;
778
- if (!hasMagic) {
779
- *vp = JSVAL_FALSE;
780
- goto out;
781
- }
782
-
783
- JS_LOCK_OBJ(cx, obj);
784
- execDepth = GetScriptExecDepth(cx, obj);
785
-
786
- /*
787
- * execDepth must be 0 to allow compilation here, otherwise the JSScript
788
- * struct can be released while running.
789
- */
790
- if (execDepth > 0) {
791
- JS_UNLOCK_OBJ(cx, obj);
792
- JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
793
- JSMSG_COMPILE_EXECED_SCRIPT);
794
- goto out;
795
- }
796
-
797
- /* Swap script for obj's old script, if any. */
798
- v = LOCKED_OBJ_GET_SLOT(obj, JSSLOT_PRIVATE);
799
- oldscript = !JSVAL_IS_VOID(v) ? JSVAL_TO_PRIVATE(v) : NULL;
800
- LOCKED_OBJ_SET_SLOT(obj, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(script));
801
- JS_UNLOCK_OBJ(cx, obj);
802
-
803
- if (oldscript)
804
- js_DestroyScript(cx, oldscript);
805
-
806
- script->object = obj;
807
- js_CallNewScriptHook(cx, script, NULL);
808
-
809
- out:
810
- /*
811
- * We reset the buffer to be NULL so that it doesn't free the chars
812
- * memory owned by str (vp[2]).
813
- */
814
- JS_XDRMemSetData(xdr, NULL, 0);
815
- JS_XDRDestroy(xdr);
816
- #if IS_BIG_ENDIAN
817
- JS_free(cx, buf);
818
- #endif
819
- *vp = JSVAL_TRUE;
820
- return ok;
821
- }
822
-
823
- static const char js_thaw_str[] = "thaw";
824
-
825
- #endif /* JS_HAS_SCRIPT_OBJECT && JS_HAS_XDR_FREEZE_THAW */
826
- #endif /* JS_HAS_XDR */
827
-
828
- #if JS_HAS_SCRIPT_OBJECT
829
-
830
- static JSFunctionSpec script_methods[] = {
831
- #if JS_HAS_TOSOURCE
832
- JS_FN(js_toSource_str, script_toSource, 0,0,0),
833
- #endif
834
- JS_FN(js_toString_str, script_toString, 0,0,0),
835
- JS_FN("compile", script_compile, 0,2,0),
836
- JS_FN("exec", script_exec, 0,1,0),
837
- #if JS_HAS_XDR_FREEZE_THAW
838
- JS_FN("freeze", script_freeze, 0,0,0),
839
- JS_FN(js_thaw_str, script_thaw, 0,1,0),
840
- #endif /* JS_HAS_XDR_FREEZE_THAW */
841
- JS_FS_END
842
- };
843
-
844
- #endif /* JS_HAS_SCRIPT_OBJECT */
845
-
846
- static void
847
- script_finalize(JSContext *cx, JSObject *obj)
848
- {
849
- JSScript *script;
850
-
851
- script = (JSScript *) JS_GetPrivate(cx, obj);
852
- if (script)
853
- js_DestroyScript(cx, script);
854
- }
855
-
856
- static JSBool
857
- script_call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
858
- {
859
- #if JS_HAS_SCRIPT_OBJECT
860
- return script_exec_sub(cx, JSVAL_TO_OBJECT(argv[-2]), argc, argv, rval);
861
- #else
862
- return JS_FALSE;
863
- #endif
864
- }
865
-
866
- static void
867
- script_trace(JSTracer *trc, JSObject *obj)
868
- {
869
- JSScript *script;
870
-
871
- script = (JSScript *) JS_GetPrivate(trc->context, obj);
872
- if (script)
873
- js_TraceScript(trc, script);
874
- }
875
-
876
- #if !JS_HAS_SCRIPT_OBJECT
877
- #define JSProto_Script JSProto_Object
878
- #endif
879
-
880
- JS_FRIEND_DATA(JSClass) js_ScriptClass = {
881
- js_Script_str,
882
- JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1) |
883
- JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Script),
884
- JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
885
- JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, script_finalize,
886
- NULL, NULL, script_call, NULL,/*XXXbe xdr*/
887
- NULL, NULL, JS_CLASS_TRACE(script_trace), NULL
888
- };
889
-
890
- #if JS_HAS_SCRIPT_OBJECT
891
-
892
- static JSBool
893
- Script(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
894
- {
895
- /* If not constructing, replace obj with a new Script object. */
896
- if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {
897
- obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL);
898
- if (!obj)
899
- return JS_FALSE;
900
-
901
- /*
902
- * script_compile_sub does not use rval to root its temporaries so we
903
- * can use it to root obj.
904
- */
905
- *rval = OBJECT_TO_JSVAL(obj);
906
- }
907
-
908
- if (!JS_SetReservedSlot(cx, obj, 0, INT_TO_JSVAL(0)))
909
- return JS_FALSE;
910
-
911
- return script_compile_sub(cx, obj, argc, argv, rval);
912
- }
913
-
914
- #if JS_HAS_SCRIPT_OBJECT && JS_HAS_XDR_FREEZE_THAW
915
-
916
- static JSBool
917
- script_static_thaw(JSContext *cx, uintN argc, jsval *vp)
918
- {
919
- JSObject *obj;
920
-
921
- obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL);
922
- if (!obj)
923
- return JS_FALSE;
924
- vp[1] = OBJECT_TO_JSVAL(obj);
925
- if (!script_thaw(cx, vp))
926
- return JS_FALSE;
927
- *vp = OBJECT_TO_JSVAL(obj);
928
- return JS_TRUE;
929
- }
930
-
931
- static JSFunctionSpec script_static_methods[] = {
932
- JS_FN(js_thaw_str, script_static_thaw, 1,1,0),
933
- JS_FS_END
934
- };
935
-
936
- #else /* !JS_HAS_SCRIPT_OBJECT || !JS_HAS_XDR_FREEZE_THAW */
937
-
938
- #define script_static_methods NULL
939
-
940
- #endif /* !JS_HAS_SCRIPT_OBJECT || !JS_HAS_XDR_FREEZE_THAW */
941
-
942
- JSObject *
943
- js_InitScriptClass(JSContext *cx, JSObject *obj)
944
- {
945
- return JS_InitClass(cx, obj, NULL, &js_ScriptClass, Script, 1,
946
- NULL, script_methods, NULL, script_static_methods);
947
- }
948
-
949
- #endif /* JS_HAS_SCRIPT_OBJECT */
950
-
951
- /*
952
- * Shared script filename management.
953
- */
954
- JS_STATIC_DLL_CALLBACK(int)
955
- js_compare_strings(const void *k1, const void *k2)
956
- {
957
- return strcmp((const char *) k1, (const char *) k2) == 0;
958
- }
959
-
960
- /* NB: This struct overlays JSHashEntry -- see jshash.h, do not reorganize. */
961
- typedef struct ScriptFilenameEntry {
962
- JSHashEntry *next; /* hash chain linkage */
963
- JSHashNumber keyHash; /* key hash function result */
964
- const void *key; /* ptr to filename, below */
965
- uint32 flags; /* user-defined filename prefix flags */
966
- JSPackedBool mark; /* GC mark flag */
967
- char filename[3]; /* two or more bytes, NUL-terminated */
968
- } ScriptFilenameEntry;
969
-
970
- JS_STATIC_DLL_CALLBACK(void *)
971
- js_alloc_table_space(void *priv, size_t size)
972
- {
973
- return malloc(size);
974
- }
975
-
976
- JS_STATIC_DLL_CALLBACK(void)
977
- js_free_table_space(void *priv, void *item)
978
- {
979
- free(item);
980
- }
981
-
982
- JS_STATIC_DLL_CALLBACK(JSHashEntry *)
983
- js_alloc_sftbl_entry(void *priv, const void *key)
984
- {
985
- size_t nbytes = offsetof(ScriptFilenameEntry, filename) +
986
- strlen((const char *) key) + 1;
987
-
988
- return (JSHashEntry *) malloc(JS_MAX(nbytes, sizeof(JSHashEntry)));
989
- }
990
-
991
- JS_STATIC_DLL_CALLBACK(void)
992
- js_free_sftbl_entry(void *priv, JSHashEntry *he, uintN flag)
993
- {
994
- if (flag != HT_FREE_ENTRY)
995
- return;
996
- free(he);
997
- }
998
-
999
- static JSHashAllocOps sftbl_alloc_ops = {
1000
- js_alloc_table_space, js_free_table_space,
1001
- js_alloc_sftbl_entry, js_free_sftbl_entry
1002
- };
1003
-
1004
- JSBool
1005
- js_InitRuntimeScriptState(JSRuntime *rt)
1006
- {
1007
- #ifdef JS_THREADSAFE
1008
- JS_ASSERT(!rt->scriptFilenameTableLock);
1009
- rt->scriptFilenameTableLock = JS_NEW_LOCK();
1010
- if (!rt->scriptFilenameTableLock)
1011
- return JS_FALSE;
1012
- #endif
1013
- JS_ASSERT(!rt->scriptFilenameTable);
1014
- rt->scriptFilenameTable =
1015
- JS_NewHashTable(16, JS_HashString, js_compare_strings, NULL,
1016
- &sftbl_alloc_ops, NULL);
1017
- if (!rt->scriptFilenameTable) {
1018
- js_FinishRuntimeScriptState(rt); /* free lock if threadsafe */
1019
- return JS_FALSE;
1020
- }
1021
- JS_INIT_CLIST(&rt->scriptFilenamePrefixes);
1022
- return JS_TRUE;
1023
- }
1024
-
1025
- typedef struct ScriptFilenamePrefix {
1026
- JSCList links; /* circular list linkage for easy deletion */
1027
- const char *name; /* pointer to pinned ScriptFilenameEntry string */
1028
- size_t length; /* prefix string length, precomputed */
1029
- uint32 flags; /* user-defined flags to inherit from this prefix */
1030
- } ScriptFilenamePrefix;
1031
-
1032
- void
1033
- js_FinishRuntimeScriptState(JSRuntime *rt)
1034
- {
1035
- if (rt->scriptFilenameTable) {
1036
- JS_HashTableDestroy(rt->scriptFilenameTable);
1037
- rt->scriptFilenameTable = NULL;
1038
- }
1039
- #ifdef JS_THREADSAFE
1040
- if (rt->scriptFilenameTableLock) {
1041
- JS_DESTROY_LOCK(rt->scriptFilenameTableLock);
1042
- rt->scriptFilenameTableLock = NULL;
1043
- }
1044
- #endif
1045
- }
1046
-
1047
- void
1048
- js_FreeRuntimeScriptState(JSRuntime *rt)
1049
- {
1050
- ScriptFilenamePrefix *sfp;
1051
-
1052
- if (!rt->scriptFilenameTable)
1053
- return;
1054
-
1055
- while (!JS_CLIST_IS_EMPTY(&rt->scriptFilenamePrefixes)) {
1056
- sfp = (ScriptFilenamePrefix *) rt->scriptFilenamePrefixes.next;
1057
- JS_REMOVE_LINK(&sfp->links);
1058
- free(sfp);
1059
- }
1060
- js_FinishRuntimeScriptState(rt);
1061
- }
1062
-
1063
- #ifdef DEBUG_brendan
1064
- #define DEBUG_SFTBL
1065
- #endif
1066
- #ifdef DEBUG_SFTBL
1067
- size_t sftbl_savings = 0;
1068
- #endif
1069
-
1070
- static ScriptFilenameEntry *
1071
- SaveScriptFilename(JSRuntime *rt, const char *filename, uint32 flags)
1072
- {
1073
- JSHashTable *table;
1074
- JSHashNumber hash;
1075
- JSHashEntry **hep;
1076
- ScriptFilenameEntry *sfe;
1077
- size_t length;
1078
- JSCList *head, *link;
1079
- ScriptFilenamePrefix *sfp;
1080
-
1081
- table = rt->scriptFilenameTable;
1082
- hash = JS_HashString(filename);
1083
- hep = JS_HashTableRawLookup(table, hash, filename);
1084
- sfe = (ScriptFilenameEntry *) *hep;
1085
- #ifdef DEBUG_SFTBL
1086
- if (sfe)
1087
- sftbl_savings += strlen(sfe->filename);
1088
- #endif
1089
-
1090
- if (!sfe) {
1091
- sfe = (ScriptFilenameEntry *)
1092
- JS_HashTableRawAdd(table, hep, hash, filename, NULL);
1093
- if (!sfe)
1094
- return NULL;
1095
- sfe->key = strcpy(sfe->filename, filename);
1096
- sfe->flags = 0;
1097
- sfe->mark = JS_FALSE;
1098
- }
1099
-
1100
- /* If saving a prefix, add it to the set in rt->scriptFilenamePrefixes. */
1101
- if (flags != 0) {
1102
- /* Search in case filename was saved already; we must be idempotent. */
1103
- sfp = NULL;
1104
- length = strlen(filename);
1105
- for (head = link = &rt->scriptFilenamePrefixes;
1106
- link->next != head;
1107
- link = link->next) {
1108
- /* Lag link behind sfp to insert in non-increasing length order. */
1109
- sfp = (ScriptFilenamePrefix *) link->next;
1110
- if (!strcmp(sfp->name, filename))
1111
- break;
1112
- if (sfp->length <= length) {
1113
- sfp = NULL;
1114
- break;
1115
- }
1116
- sfp = NULL;
1117
- }
1118
-
1119
- if (!sfp) {
1120
- /* No such prefix: add one now. */
1121
- sfp = (ScriptFilenamePrefix *) malloc(sizeof(ScriptFilenamePrefix));
1122
- if (!sfp)
1123
- return NULL;
1124
- JS_INSERT_AFTER(&sfp->links, link);
1125
- sfp->name = sfe->filename;
1126
- sfp->length = length;
1127
- sfp->flags = 0;
1128
- }
1129
-
1130
- /*
1131
- * Accumulate flags in both sfe and sfp: sfe for later access from the
1132
- * JS_GetScriptedCallerFilenameFlags debug-API, and sfp so that longer
1133
- * filename entries can inherit by prefix.
1134
- */
1135
- sfe->flags |= flags;
1136
- sfp->flags |= flags;
1137
- }
1138
-
1139
- return sfe;
1140
- }
1141
-
1142
- const char *
1143
- js_SaveScriptFilename(JSContext *cx, const char *filename)
1144
- {
1145
- JSRuntime *rt;
1146
- ScriptFilenameEntry *sfe;
1147
- JSCList *head, *link;
1148
- ScriptFilenamePrefix *sfp;
1149
-
1150
- rt = cx->runtime;
1151
- JS_ACQUIRE_LOCK(rt->scriptFilenameTableLock);
1152
- sfe = SaveScriptFilename(rt, filename, 0);
1153
- if (!sfe) {
1154
- JS_RELEASE_LOCK(rt->scriptFilenameTableLock);
1155
- JS_ReportOutOfMemory(cx);
1156
- return NULL;
1157
- }
1158
-
1159
- /*
1160
- * Try to inherit flags by prefix. We assume there won't be more than a
1161
- * few (dozen! ;-) prefixes, so linear search is tolerable.
1162
- * XXXbe every time I've assumed that in the JS engine, I've been wrong!
1163
- */
1164
- for (head = &rt->scriptFilenamePrefixes, link = head->next;
1165
- link != head;
1166
- link = link->next) {
1167
- sfp = (ScriptFilenamePrefix *) link;
1168
- if (!strncmp(sfp->name, filename, sfp->length)) {
1169
- sfe->flags |= sfp->flags;
1170
- break;
1171
- }
1172
- }
1173
- JS_RELEASE_LOCK(rt->scriptFilenameTableLock);
1174
- return sfe->filename;
1175
- }
1176
-
1177
- const char *
1178
- js_SaveScriptFilenameRT(JSRuntime *rt, const char *filename, uint32 flags)
1179
- {
1180
- ScriptFilenameEntry *sfe;
1181
-
1182
- /* This may be called very early, via the jsdbgapi.h entry point. */
1183
- if (!rt->scriptFilenameTable && !js_InitRuntimeScriptState(rt))
1184
- return NULL;
1185
-
1186
- JS_ACQUIRE_LOCK(rt->scriptFilenameTableLock);
1187
- sfe = SaveScriptFilename(rt, filename, flags);
1188
- JS_RELEASE_LOCK(rt->scriptFilenameTableLock);
1189
- if (!sfe)
1190
- return NULL;
1191
-
1192
- return sfe->filename;
1193
- }
1194
-
1195
- /*
1196
- * Back up from a saved filename by its offset within its hash table entry.
1197
- */
1198
- #define FILENAME_TO_SFE(fn) \
1199
- ((ScriptFilenameEntry *) ((fn) - offsetof(ScriptFilenameEntry, filename)))
1200
-
1201
- /*
1202
- * The sfe->key member, redundant given sfe->filename but required by the old
1203
- * jshash.c code, here gives us a useful sanity check. This assertion will
1204
- * very likely botch if someone tries to mark a string that wasn't allocated
1205
- * as an sfe->filename.
1206
- */
1207
- #define ASSERT_VALID_SFE(sfe) JS_ASSERT((sfe)->key == (sfe)->filename)
1208
-
1209
- uint32
1210
- js_GetScriptFilenameFlags(const char *filename)
1211
- {
1212
- ScriptFilenameEntry *sfe;
1213
-
1214
- sfe = FILENAME_TO_SFE(filename);
1215
- ASSERT_VALID_SFE(sfe);
1216
- return sfe->flags;
1217
- }
1218
-
1219
- void
1220
- js_MarkScriptFilename(const char *filename)
1221
- {
1222
- ScriptFilenameEntry *sfe;
1223
-
1224
- sfe = FILENAME_TO_SFE(filename);
1225
- ASSERT_VALID_SFE(sfe);
1226
- sfe->mark = JS_TRUE;
1227
- }
1228
-
1229
- JS_STATIC_DLL_CALLBACK(intN)
1230
- js_script_filename_marker(JSHashEntry *he, intN i, void *arg)
1231
- {
1232
- ScriptFilenameEntry *sfe = (ScriptFilenameEntry *) he;
1233
-
1234
- sfe->mark = JS_TRUE;
1235
- return HT_ENUMERATE_NEXT;
1236
- }
1237
-
1238
- void
1239
- js_MarkScriptFilenames(JSRuntime *rt, JSBool keepAtoms)
1240
- {
1241
- JSCList *head, *link;
1242
- ScriptFilenamePrefix *sfp;
1243
-
1244
- if (!rt->scriptFilenameTable)
1245
- return;
1246
-
1247
- if (keepAtoms) {
1248
- JS_HashTableEnumerateEntries(rt->scriptFilenameTable,
1249
- js_script_filename_marker,
1250
- rt);
1251
- }
1252
- for (head = &rt->scriptFilenamePrefixes, link = head->next;
1253
- link != head;
1254
- link = link->next) {
1255
- sfp = (ScriptFilenamePrefix *) link;
1256
- js_MarkScriptFilename(sfp->name);
1257
- }
1258
- }
1259
-
1260
- JS_STATIC_DLL_CALLBACK(intN)
1261
- js_script_filename_sweeper(JSHashEntry *he, intN i, void *arg)
1262
- {
1263
- ScriptFilenameEntry *sfe = (ScriptFilenameEntry *) he;
1264
-
1265
- if (!sfe->mark)
1266
- return HT_ENUMERATE_REMOVE;
1267
- sfe->mark = JS_FALSE;
1268
- return HT_ENUMERATE_NEXT;
1269
- }
1270
-
1271
- void
1272
- js_SweepScriptFilenames(JSRuntime *rt)
1273
- {
1274
- if (!rt->scriptFilenameTable)
1275
- return;
1276
-
1277
- JS_HashTableEnumerateEntries(rt->scriptFilenameTable,
1278
- js_script_filename_sweeper,
1279
- rt);
1280
- #ifdef DEBUG_notme
1281
- #ifdef DEBUG_SFTBL
1282
- printf("script filename table savings so far: %u\n", sftbl_savings);
1283
- #endif
1284
- #endif
1285
- }
1286
-
1287
- /*
1288
- * JSScript data structures memory alignment:
1289
- *
1290
- * JSScript
1291
- * JSObjectArray script objects' descriptor if JSScript.objectsOffset != 0,
1292
- * use JS_SCRIPT_OBJECTS(script) macro to access it.
1293
- * JSObjectArray script regexps' descriptor if JSScript.regexpsOffset != 0,
1294
- * use JS_SCRIPT_REGEXPS(script) macro to access it.
1295
- * JSTryNoteArray script try notes' descriptor if JSScript.tryNotesOffset
1296
- * != 0, use JS_SCRIPT_TRYNOTES(script) macro to access it.
1297
- * JSAtom *a[] array of JSScript.atomMap.length atoms pointed by
1298
- * JSScript.atomMap.vector if any.
1299
- * JSObject *o[] array of JS_SCRIPT_OBJECTS(script)->length objects if any
1300
- * pointed by JS_SCRIPT_OBJECTS(script)->vector.
1301
- * JSObject *r[] array of JS_SCRIPT_REGEXPS(script)->length regexps if any
1302
- * pointed by JS_SCRIPT_REGEXPS(script)->vector.
1303
- * JSTryNote t[] array of JS_SCRIPT_TRYNOTES(script)->length try notes if any
1304
- * pointed by JS_SCRIPT_TRYNOTES(script)->vector.
1305
- * jsbytecode b[] script bytecode pointed by JSScript.code.
1306
- * jssrcnote s[] script source notes, use SCRIPT_NOTES(script) to access it
1307
- *
1308
- * The alignment avoids gaps between entries as alignment requirement for each
1309
- * subsequent structure or array is the same or divides the alignment
1310
- * requirement for the previous one.
1311
- *
1312
- * The followings asserts checks that assuming that the alignment requirement
1313
- * for JSObjectArray and JSTryNoteArray are sizeof(void *) and for JSTryNote
1314
- * it is sizeof(uint32) as the structure consists of 3 uint32 fields.
1315
- */
1316
- JS_STATIC_ASSERT(sizeof(JSScript) % sizeof(void *) == 0);
1317
- JS_STATIC_ASSERT(sizeof(JSObjectArray) % sizeof(void *) == 0);
1318
- JS_STATIC_ASSERT(sizeof(JSTryNoteArray) == sizeof(JSObjectArray));
1319
- JS_STATIC_ASSERT(sizeof(JSAtom *) == sizeof(JSObject *));
1320
- JS_STATIC_ASSERT(sizeof(JSObject *) % sizeof(uint32) == 0);
1321
- JS_STATIC_ASSERT(sizeof(JSTryNote) == 3 * sizeof(uint32));
1322
- JS_STATIC_ASSERT(sizeof(uint32) % sizeof(jsbytecode) == 0);
1323
- JS_STATIC_ASSERT(sizeof(jsbytecode) % sizeof(jssrcnote) == 0);
1324
-
1325
- /*
1326
- * Check that uint8 offset for object, regexp and try note arrays is sufficient.
1327
- */
1328
- JS_STATIC_ASSERT(sizeof(JSScript) + 2 * sizeof(JSObjectArray) < JS_BIT(8));
1329
-
1330
- JSScript *
1331
- js_NewScript(JSContext *cx, uint32 length, uint32 nsrcnotes, uint32 natoms,
1332
- uint32 nobjects, uint32 nregexps, uint32 ntrynotes)
1333
- {
1334
- size_t size, vectorSize;
1335
- JSScript *script;
1336
- uint8 *cursor;
1337
-
1338
- size = sizeof(JSScript) +
1339
- sizeof(JSAtom *) * natoms +
1340
- length * sizeof(jsbytecode) +
1341
- nsrcnotes * sizeof(jssrcnote);
1342
- if (nobjects != 0)
1343
- size += sizeof(JSObjectArray) + nobjects * sizeof(JSObject *);
1344
- if (nregexps != 0)
1345
- size += sizeof(JSObjectArray) + nregexps * sizeof(JSObject *);
1346
- if (ntrynotes != 0)
1347
- size += sizeof(JSTryNoteArray) + ntrynotes * sizeof(JSTryNote);
1348
-
1349
- script = (JSScript *) JS_malloc(cx, size);
1350
- if (!script)
1351
- return NULL;
1352
- memset(script, 0, sizeof(JSScript));
1353
- script->length = length;
1354
- script->version = cx->version;
1355
-
1356
- cursor = (uint8 *)script + sizeof(JSScript);
1357
- if (nobjects != 0) {
1358
- script->objectsOffset = (uint8)(cursor - (uint8 *)script);
1359
- cursor += sizeof(JSObjectArray);
1360
- }
1361
- if (nregexps != 0) {
1362
- script->regexpsOffset = (uint8)(cursor - (uint8 *)script);
1363
- cursor += sizeof(JSObjectArray);
1364
- }
1365
- if (ntrynotes != 0) {
1366
- script->trynotesOffset = (uint8)(cursor - (uint8 *)script);
1367
- cursor += sizeof(JSTryNoteArray);
1368
- }
1369
-
1370
- if (natoms != 0) {
1371
- script->atomMap.length = natoms;
1372
- script->atomMap.vector = (JSAtom **)cursor;
1373
- vectorSize = natoms * sizeof(script->atomMap.vector[0]);
1374
-
1375
- /*
1376
- * Clear object map's vector so the GC tracing can run when not yet
1377
- * all atoms are copied to the array.
1378
- */
1379
- memset(cursor, 0, vectorSize);
1380
- cursor += vectorSize;
1381
- }
1382
- if (nobjects != 0) {
1383
- JS_SCRIPT_OBJECTS(script)->length = nobjects;
1384
- JS_SCRIPT_OBJECTS(script)->vector = (JSObject **)cursor;
1385
- vectorSize = nobjects * sizeof(JS_SCRIPT_OBJECTS(script)->vector[0]);
1386
- memset(cursor, 0, vectorSize);
1387
- cursor += vectorSize;
1388
- }
1389
- if (nregexps != 0) {
1390
- JS_SCRIPT_REGEXPS(script)->length = nregexps;
1391
- JS_SCRIPT_REGEXPS(script)->vector = (JSObject **)cursor;
1392
- vectorSize = nregexps * sizeof(JS_SCRIPT_REGEXPS(script)->vector[0]);
1393
- memset(cursor, 0, vectorSize);
1394
- cursor += vectorSize;
1395
- }
1396
- if (ntrynotes != 0) {
1397
- JS_SCRIPT_TRYNOTES(script)->length = ntrynotes;
1398
- JS_SCRIPT_TRYNOTES(script)->vector = (JSTryNote *)cursor;
1399
- vectorSize = ntrynotes * sizeof(JS_SCRIPT_TRYNOTES(script)->vector[0]);
1400
- #ifdef DEBUG
1401
- memset(cursor, 0, vectorSize);
1402
- #endif
1403
- cursor += vectorSize;
1404
- }
1405
-
1406
- script->code = script->main = (jsbytecode *)cursor;
1407
- JS_ASSERT(cursor +
1408
- length * sizeof(jsbytecode) +
1409
- nsrcnotes * sizeof(jssrcnote) ==
1410
- (uint8 *)script + size);
1411
-
1412
- #ifdef CHECK_SCRIPT_OWNER
1413
- script->owner = cx->thread;
1414
- #endif
1415
- return script;
1416
- }
1417
-
1418
- JSScript *
1419
- js_NewScriptFromCG(JSContext *cx, JSCodeGenerator *cg)
1420
- {
1421
- uint32 mainLength, prologLength, nsrcnotes;
1422
- JSScript *script;
1423
- const char *filename;
1424
- JSFunction *fun;
1425
-
1426
- /* The counts of indexed things must be checked during code generation. */
1427
- JS_ASSERT(cg->atomList.count <= INDEX_LIMIT);
1428
- JS_ASSERT(cg->objectList.length <= INDEX_LIMIT);
1429
- JS_ASSERT(cg->regexpList.length <= INDEX_LIMIT);
1430
-
1431
- mainLength = CG_OFFSET(cg);
1432
- prologLength = CG_PROLOG_OFFSET(cg);
1433
- CG_COUNT_FINAL_SRCNOTES(cg, nsrcnotes);
1434
- script = js_NewScript(cx, prologLength + mainLength, nsrcnotes,
1435
- cg->atomList.count, cg->objectList.length,
1436
- cg->regexpList.length, cg->ntrynotes);
1437
- if (!script)
1438
- return NULL;
1439
-
1440
- /* Now that we have script, error control flow must go to label bad. */
1441
- script->main += prologLength;
1442
- memcpy(script->code, CG_PROLOG_BASE(cg), prologLength * sizeof(jsbytecode));
1443
- memcpy(script->main, CG_BASE(cg), mainLength * sizeof(jsbytecode));
1444
- script->ngvars = cg->treeContext.ngvars;
1445
-
1446
- js_InitAtomMap(cx, &script->atomMap, &cg->atomList);
1447
-
1448
- filename = cg->treeContext.parseContext->tokenStream.filename;
1449
- if (filename) {
1450
- script->filename = js_SaveScriptFilename(cx, filename);
1451
- if (!script->filename)
1452
- goto bad;
1453
- }
1454
- script->lineno = cg->firstLine;
1455
- script->depth = cg->maxStackDepth;
1456
- script->principals = cg->treeContext.parseContext->principals;
1457
- if (script->principals)
1458
- JSPRINCIPALS_HOLD(cx, script->principals);
1459
-
1460
- if (!js_FinishTakingSrcNotes(cx, cg, SCRIPT_NOTES(script)))
1461
- goto bad;
1462
- if (cg->ntrynotes != 0)
1463
- js_FinishTakingTryNotes(cg, JS_SCRIPT_TRYNOTES(script));
1464
- if (cg->objectList.length != 0)
1465
- FinishParsedObjects(&cg->objectList, JS_SCRIPT_OBJECTS(script));
1466
- if (cg->regexpList.length != 0)
1467
- FinishParsedObjects(&cg->regexpList, JS_SCRIPT_REGEXPS(script));
1468
-
1469
- /*
1470
- * We initialize fun->u.script to be the script constructed above
1471
- * so that the debugger has a valid FUN_SCRIPT(fun).
1472
- */
1473
- fun = NULL;
1474
- if (cg->treeContext.flags & TCF_IN_FUNCTION) {
1475
- fun = cg->treeContext.fun;
1476
- JS_ASSERT(FUN_INTERPRETED(fun) && !FUN_SCRIPT(fun));
1477
- js_FreezeLocalNames(cx, fun);
1478
- fun->u.i.script = script;
1479
- #ifdef CHECK_SCRIPT_OWNER
1480
- script->owner = NULL;
1481
- #endif
1482
- if (cg->treeContext.flags & TCF_FUN_HEAVYWEIGHT)
1483
- fun->flags |= JSFUN_HEAVYWEIGHT;
1484
- if (fun->flags & JSFUN_HEAVYWEIGHT)
1485
- ++cg->treeContext.maxScopeDepth;
1486
- }
1487
-
1488
- #ifdef JS_SCOPE_DEPTH_METER
1489
- JS_BASIC_STATS_ACCUM(&cx->runtime->lexicalScopeDepthStats,
1490
- cg->treeContext.maxScopeDepth);
1491
- #endif
1492
-
1493
- /* Tell the debugger about this compiled script. */
1494
- js_CallNewScriptHook(cx, script, fun);
1495
- return script;
1496
-
1497
- bad:
1498
- js_DestroyScript(cx, script);
1499
- return NULL;
1500
- }
1501
-
1502
- JS_FRIEND_API(void)
1503
- js_CallNewScriptHook(JSContext *cx, JSScript *script, JSFunction *fun)
1504
- {
1505
- JSNewScriptHook hook;
1506
-
1507
- hook = cx->debugHooks->newScriptHook;
1508
- if (hook) {
1509
- JS_KEEP_ATOMS(cx->runtime);
1510
- hook(cx, script->filename, script->lineno, script, fun,
1511
- cx->debugHooks->newScriptHookData);
1512
- JS_UNKEEP_ATOMS(cx->runtime);
1513
- }
1514
- }
1515
-
1516
- JS_FRIEND_API(void)
1517
- js_CallDestroyScriptHook(JSContext *cx, JSScript *script)
1518
- {
1519
- JSDestroyScriptHook hook;
1520
-
1521
- hook = cx->debugHooks->destroyScriptHook;
1522
- if (hook)
1523
- hook(cx, script, cx->debugHooks->destroyScriptHookData);
1524
- }
1525
-
1526
- void
1527
- js_DestroyScript(JSContext *cx, JSScript *script)
1528
- {
1529
- js_CallDestroyScriptHook(cx, script);
1530
- JS_ClearScriptTraps(cx, script);
1531
-
1532
- if (script->principals)
1533
- JSPRINCIPALS_DROP(cx, script->principals);
1534
-
1535
- if (JS_GSN_CACHE(cx).code == script->code)
1536
- JS_CLEAR_GSN_CACHE(cx);
1537
-
1538
- /*
1539
- * The GC flushes all property caches, so no need to purge just the
1540
- * entries for this script.
1541
- *
1542
- * JS_THREADSAFE note: js_FlushPropertyCacheForScript flushes only the
1543
- * current thread's property cache, so a script not owned by a function
1544
- * or object, which hands off lifetime management for that script to the
1545
- * GC, must be used by only one thread over its lifetime.
1546
- *
1547
- * This should be an API-compatible change, since a script is never safe
1548
- * against premature GC if shared among threads without a rooted object
1549
- * wrapping it to protect the script's mapped atoms against GC. We use
1550
- * script->owner to enforce this requirement via assertions.
1551
- */
1552
- #ifdef CHECK_SCRIPT_OWNER
1553
- JS_ASSERT_IF(cx->runtime->gcRunning, !script->owner);
1554
- #endif
1555
-
1556
- if (!cx->runtime->gcRunning &&
1557
- !(cx->fp && (cx->fp->flags & JSFRAME_EVAL))) {
1558
- #ifdef CHECK_SCRIPT_OWNER
1559
- JS_ASSERT(script->owner == cx->thread);
1560
- #endif
1561
- js_FlushPropertyCacheForScript(cx, script);
1562
- }
1563
-
1564
- JS_free(cx, script);
1565
- }
1566
-
1567
- void
1568
- js_TraceScript(JSTracer *trc, JSScript *script)
1569
- {
1570
- JSAtomMap *map;
1571
- uintN i, length;
1572
- JSAtom **vector;
1573
- jsval v;
1574
- JSObjectArray *objarray;
1575
-
1576
- map = &script->atomMap;
1577
- length = map->length;
1578
- vector = map->vector;
1579
- for (i = 0; i < length; i++) {
1580
- v = ATOM_KEY(vector[i]);
1581
- if (JSVAL_IS_TRACEABLE(v)) {
1582
- JS_SET_TRACING_INDEX(trc, "atomMap", i);
1583
- JS_CallTracer(trc, JSVAL_TO_TRACEABLE(v), JSVAL_TRACE_KIND(v));
1584
- }
1585
- }
1586
-
1587
- if (script->objectsOffset != 0) {
1588
- objarray = JS_SCRIPT_OBJECTS(script);
1589
- i = objarray->length;
1590
- do {
1591
- --i;
1592
- if (objarray->vector[i]) {
1593
- JS_SET_TRACING_INDEX(trc, "objects", i);
1594
- JS_CallTracer(trc, objarray->vector[i], JSTRACE_OBJECT);
1595
- }
1596
- } while (i != 0);
1597
- }
1598
-
1599
- if (script->regexpsOffset != 0) {
1600
- objarray = JS_SCRIPT_REGEXPS(script);
1601
- i = objarray->length;
1602
- do {
1603
- --i;
1604
- if (objarray->vector[i]) {
1605
- JS_SET_TRACING_INDEX(trc, "regexps", i);
1606
- JS_CallTracer(trc, objarray->vector[i], JSTRACE_OBJECT);
1607
- }
1608
- } while (i != 0);
1609
- }
1610
-
1611
- if (IS_GC_MARKING_TRACER(trc) && script->filename)
1612
- js_MarkScriptFilename(script->filename);
1613
- }
1614
-
1615
- typedef struct GSNCacheEntry {
1616
- JSDHashEntryHdr hdr;
1617
- jsbytecode *pc;
1618
- jssrcnote *sn;
1619
- } GSNCacheEntry;
1620
-
1621
- #define GSN_CACHE_THRESHOLD 100
1622
-
1623
- jssrcnote *
1624
- js_GetSrcNoteCached(JSContext *cx, JSScript *script, jsbytecode *pc)
1625
- {
1626
- ptrdiff_t target, offset;
1627
- GSNCacheEntry *entry;
1628
- jssrcnote *sn, *result;
1629
- uintN nsrcnotes;
1630
-
1631
-
1632
- target = PTRDIFF(pc, script->code, jsbytecode);
1633
- if ((uint32)target >= script->length)
1634
- return NULL;
1635
-
1636
- if (JS_GSN_CACHE(cx).code == script->code) {
1637
- JS_METER_GSN_CACHE(cx, hits);
1638
- entry = (GSNCacheEntry *)
1639
- JS_DHashTableOperate(&JS_GSN_CACHE(cx).table, pc,
1640
- JS_DHASH_LOOKUP);
1641
- return entry->sn;
1642
- }
1643
-
1644
- JS_METER_GSN_CACHE(cx, misses);
1645
- offset = 0;
1646
- for (sn = SCRIPT_NOTES(script); ; sn = SN_NEXT(sn)) {
1647
- if (SN_IS_TERMINATOR(sn)) {
1648
- result = NULL;
1649
- break;
1650
- }
1651
- offset += SN_DELTA(sn);
1652
- if (offset == target && SN_IS_GETTABLE(sn)) {
1653
- result = sn;
1654
- break;
1655
- }
1656
- }
1657
-
1658
- if (JS_GSN_CACHE(cx).code != script->code &&
1659
- script->length >= GSN_CACHE_THRESHOLD) {
1660
- JS_CLEAR_GSN_CACHE(cx);
1661
- nsrcnotes = 0;
1662
- for (sn = SCRIPT_NOTES(script); !SN_IS_TERMINATOR(sn);
1663
- sn = SN_NEXT(sn)) {
1664
- if (SN_IS_GETTABLE(sn))
1665
- ++nsrcnotes;
1666
- }
1667
- if (!JS_DHashTableInit(&JS_GSN_CACHE(cx).table, JS_DHashGetStubOps(),
1668
- NULL, sizeof(GSNCacheEntry),
1669
- JS_DHASH_DEFAULT_CAPACITY(nsrcnotes))) {
1670
- JS_GSN_CACHE(cx).table.ops = NULL;
1671
- } else {
1672
- pc = script->code;
1673
- for (sn = SCRIPT_NOTES(script); !SN_IS_TERMINATOR(sn);
1674
- sn = SN_NEXT(sn)) {
1675
- pc += SN_DELTA(sn);
1676
- if (SN_IS_GETTABLE(sn)) {
1677
- entry = (GSNCacheEntry *)
1678
- JS_DHashTableOperate(&JS_GSN_CACHE(cx).table, pc,
1679
- JS_DHASH_ADD);
1680
- entry->pc = pc;
1681
- entry->sn = sn;
1682
- }
1683
- }
1684
- JS_GSN_CACHE(cx).code = script->code;
1685
- JS_METER_GSN_CACHE(cx, fills);
1686
- }
1687
- }
1688
-
1689
- return result;
1690
- }
1691
-
1692
- uintN
1693
- js_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc)
1694
- {
1695
- JSFunction *fun;
1696
- uintN lineno;
1697
- ptrdiff_t offset, target;
1698
- jssrcnote *sn;
1699
- JSSrcNoteType type;
1700
-
1701
- /* Cope with JSStackFrame.pc value prior to entering js_Interpret. */
1702
- if (!pc)
1703
- return 0;
1704
-
1705
- /*
1706
- * Special case: function definition needs no line number note because
1707
- * the function's script contains its starting line number.
1708
- */
1709
- if (js_CodeSpec[*pc].format & JOF_INDEXBASE)
1710
- pc += js_CodeSpec[*pc].length;
1711
- if (*pc == JSOP_DEFFUN) {
1712
- GET_FUNCTION_FROM_BYTECODE(script, pc, 0, fun);
1713
- return fun->u.i.script->lineno;
1714
- }
1715
-
1716
- /*
1717
- * General case: walk through source notes accumulating their deltas,
1718
- * keeping track of line-number notes, until we pass the note for pc's
1719
- * offset within script->code.
1720
- */
1721
- lineno = script->lineno;
1722
- offset = 0;
1723
- target = PTRDIFF(pc, script->code, jsbytecode);
1724
- for (sn = SCRIPT_NOTES(script); !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) {
1725
- offset += SN_DELTA(sn);
1726
- type = (JSSrcNoteType) SN_TYPE(sn);
1727
- if (type == SRC_SETLINE) {
1728
- if (offset <= target)
1729
- lineno = (uintN) js_GetSrcNoteOffset(sn, 0);
1730
- } else if (type == SRC_NEWLINE) {
1731
- if (offset <= target)
1732
- lineno++;
1733
- }
1734
- if (offset > target)
1735
- break;
1736
- }
1737
- return lineno;
1738
- }
1739
-
1740
- /* The line number limit is the same as the jssrcnote offset limit. */
1741
- #define SN_LINE_LIMIT (SN_3BYTE_OFFSET_FLAG << 16)
1742
-
1743
- jsbytecode *
1744
- js_LineNumberToPC(JSScript *script, uintN target)
1745
- {
1746
- ptrdiff_t offset, best;
1747
- uintN lineno, bestdiff, diff;
1748
- jssrcnote *sn;
1749
- JSSrcNoteType type;
1750
-
1751
- offset = 0;
1752
- best = -1;
1753
- lineno = script->lineno;
1754
- bestdiff = SN_LINE_LIMIT;
1755
- for (sn = SCRIPT_NOTES(script); !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) {
1756
- /*
1757
- * Exact-match only if offset is not in the prolog; otherwise use
1758
- * nearest greater-or-equal line number match.
1759
- */
1760
- if (lineno == target && script->code + offset >= script->main)
1761
- goto out;
1762
- if (lineno >= target) {
1763
- diff = lineno - target;
1764
- if (diff < bestdiff) {
1765
- bestdiff = diff;
1766
- best = offset;
1767
- }
1768
- }
1769
- offset += SN_DELTA(sn);
1770
- type = (JSSrcNoteType) SN_TYPE(sn);
1771
- if (type == SRC_SETLINE) {
1772
- lineno = (uintN) js_GetSrcNoteOffset(sn, 0);
1773
- } else if (type == SRC_NEWLINE) {
1774
- lineno++;
1775
- }
1776
- }
1777
- if (best >= 0)
1778
- offset = best;
1779
- out:
1780
- return script->code + offset;
1781
- }
1782
-
1783
- JS_FRIEND_API(uintN)
1784
- js_GetScriptLineExtent(JSScript *script)
1785
- {
1786
- uintN lineno;
1787
- jssrcnote *sn;
1788
- JSSrcNoteType type;
1789
-
1790
- lineno = script->lineno;
1791
- for (sn = SCRIPT_NOTES(script); !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) {
1792
- type = (JSSrcNoteType) SN_TYPE(sn);
1793
- if (type == SRC_SETLINE) {
1794
- lineno = (uintN) js_GetSrcNoteOffset(sn, 0);
1795
- } else if (type == SRC_NEWLINE) {
1796
- lineno++;
1797
- }
1798
- }
1799
- return 1 + lineno - script->lineno;
1800
- }
1801
-
1802
- #if JS_HAS_GENERATORS
1803
-
1804
- JSBool
1805
- js_IsInsideTryWithFinally(JSScript *script, jsbytecode *pc)
1806
- {
1807
- JSTryNoteArray *tarray;
1808
- JSTryNote *tn, *tnlimit;
1809
- uint32 off;
1810
-
1811
- JS_ASSERT(script->code <= pc);
1812
- JS_ASSERT(pc < script->code + script->length);
1813
-
1814
- if (!script->trynotesOffset != 0)
1815
- return JS_FALSE;
1816
- tarray = JS_SCRIPT_TRYNOTES(script);
1817
- JS_ASSERT(tarray->length != 0);
1818
-
1819
- tn = tarray->vector;
1820
- tnlimit = tn + tarray->length;
1821
- off = (uint32)(pc - script->main);
1822
- do {
1823
- if (off - tn->start < tn->length) {
1824
- if (tn->kind == JSTN_FINALLY)
1825
- return JS_TRUE;
1826
- JS_ASSERT(tn->kind == JSTN_CATCH);
1827
- }
1828
- } while (++tn != tnlimit);
1829
- return JS_FALSE;
1830
- }
1831
-
1832
- #endif