maglev-webtools 0.2.1 → 1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (296) hide show
  1. data/README.rdoc +38 -29
  2. data/bin/webtools +22 -1
  3. data/lib/web_tools/code_browser.rb +156 -0
  4. data/lib/web_tools/debugger.rb +96 -199
  5. data/lib/web_tools/info.rb +1 -3
  6. data/lib/web_tools/method_list.rb +67 -0
  7. data/lib/web_tools/middleware/debugger.rb +10 -16
  8. data/lib/web_tools/object_log.rb +24 -0
  9. data/lib/web_tools/session_list.rb +119 -0
  10. data/lib/web_tools/shared_page_cache.rb +30 -0
  11. data/lib/web_tools/stat_process.rb +24 -0
  12. data/lib/web_tools/statistics.rb +14 -0
  13. data/lib/web_tools/support/app_model.rb +66 -101
  14. data/lib/web_tools/support/code_browser.rb +88 -86
  15. data/lib/web_tools/support/debugger.rb +303 -0
  16. data/lib/web_tools/support/error_log.rb +33 -0
  17. data/lib/web_tools/support/ruby.rb +60 -121
  18. data/lib/web_tools/support/service_helper.rb +38 -10
  19. data/lib/web_tools/support/smalltalk_extensions.rb +12 -0
  20. data/lib/web_tools/tool.rb +48 -0
  21. data/lib/web_tools/ui.rb +14 -53
  22. data/lib/web_tools/version_report.rb +29 -0
  23. data/lib/web_tools/workspace.rb +77 -0
  24. data/lib/web_tools.rb +14 -4
  25. data/public/CodeBrowser.html +51 -0
  26. data/public/CodeMirror/LICENSE +19 -0
  27. data/public/CodeMirror/css/codemirror.css +67 -0
  28. data/public/CodeMirror/css/default.css +18 -0
  29. data/public/CodeMirror/js/codemirror.js +2131 -0
  30. data/public/CodeMirror/js/ruby.js +195 -0
  31. data/public/CodeMirror/js/smalltalk.js +139 -0
  32. data/public/Debugger.html +28 -0
  33. data/public/MethodList.html +20 -0
  34. data/public/ObjectLog.html +20 -0
  35. data/public/SessionList.html +31 -0
  36. data/public/SharedPageCache.html +78 -0
  37. data/public/Statistics.html +64 -0
  38. data/public/VersionReport.html +50 -0
  39. data/public/Workspace.html +39 -0
  40. data/public/css/CodeBrowser.css +24 -0
  41. data/public/css/Debugger.css +32 -0
  42. data/public/css/MethodList.css +8 -0
  43. data/public/css/ObjectLog.css +5 -0
  44. data/public/css/SessionList.css +9 -0
  45. data/public/css/Statistics.css +24 -0
  46. data/public/{stylesheets → css}/base/images/ui-anim_basic_16x16.gif +0 -0
  47. data/public/{stylesheets → css}/base/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  48. data/public/{stylesheets → css}/base/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  49. data/public/{stylesheets → css}/base/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  50. data/public/{stylesheets → css}/base/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  51. data/public/{stylesheets → css}/base/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  52. data/public/{stylesheets → css}/base/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  53. data/public/{stylesheets → css}/base/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  54. data/public/{stylesheets → css}/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  55. data/public/{stylesheets → css}/base/images/ui-icons_222222_256x240.png +0 -0
  56. data/public/{stylesheets → css}/base/images/ui-icons_2e83ff_256x240.png +0 -0
  57. data/public/{stylesheets → css}/base/images/ui-icons_454545_256x240.png +0 -0
  58. data/public/{stylesheets → css}/base/images/ui-icons_888888_256x240.png +0 -0
  59. data/public/{stylesheets → css}/base/images/ui-icons_cd0a0a_256x240.png +0 -0
  60. data/public/{stylesheets → css}/base/jquery.ui.accordion.css +0 -0
  61. data/public/{stylesheets → css}/base/jquery.ui.all.css +0 -0
  62. data/public/{stylesheets → css}/base/jquery.ui.autocomplete.css +0 -0
  63. data/public/{stylesheets → css}/base/jquery.ui.base.css +0 -0
  64. data/public/{stylesheets → css}/base/jquery.ui.button.css +0 -0
  65. data/public/{stylesheets → css}/base/jquery.ui.core.css +0 -0
  66. data/public/{stylesheets → css}/base/jquery.ui.datepicker.css +0 -0
  67. data/public/{stylesheets → css}/base/jquery.ui.dialog.css +0 -0
  68. data/public/{stylesheets → css}/base/jquery.ui.progressbar.css +0 -0
  69. data/public/{stylesheets → css}/base/jquery.ui.resizable.css +0 -0
  70. data/public/{stylesheets → css}/base/jquery.ui.selectable.css +0 -0
  71. data/public/{stylesheets → css}/base/jquery.ui.slider.css +0 -0
  72. data/public/{stylesheets → css}/base/jquery.ui.tabs.css +0 -0
  73. data/public/{stylesheets → css}/base/jquery.ui.theme.css +0 -0
  74. data/public/css/editor.css +25 -0
  75. data/public/css/jjmenu.css +33 -0
  76. data/public/css/menuitem.gif +0 -0
  77. data/public/css/more.gif +0 -0
  78. data/public/{stylesheets → css}/reset.css +1 -1
  79. data/public/css/smoothness/images/ui-anim_basic_16x16.gif +0 -0
  80. data/public/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  81. data/public/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  82. data/public/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  83. data/public/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  84. data/public/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  85. data/public/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  86. data/public/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  87. data/public/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  88. data/public/css/smoothness/images/ui-icons_222222_256x240.png +0 -0
  89. data/public/css/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  90. data/public/css/smoothness/images/ui-icons_454545_256x240.png +0 -0
  91. data/public/css/smoothness/images/ui-icons_888888_256x240.png +0 -0
  92. data/public/css/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  93. data/public/css/smoothness/jquery-ui.css +489 -0
  94. data/public/css/ui-lightness/images/ui-anim_basic_16x16.gif +0 -0
  95. data/public/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
  96. data/public/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
  97. data/public/css/ui-lightness/images/ui-bg_flat_10_000000_40x100.png +0 -0
  98. data/public/css/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  99. data/public/css/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  100. data/public/css/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  101. data/public/css/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  102. data/public/css/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  103. data/public/css/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  104. data/public/css/ui-lightness/images/ui-icons_222222_256x240.png +0 -0
  105. data/public/css/ui-lightness/images/ui-icons_228ef1_256x240.png +0 -0
  106. data/public/css/ui-lightness/images/ui-icons_ef8c08_256x240.png +0 -0
  107. data/public/css/ui-lightness/images/ui-icons_ffd27a_256x240.png +0 -0
  108. data/public/css/ui-lightness/images/ui-icons_ffffff_256x240.png +0 -0
  109. data/public/css/ui-lightness/jquery-ui.css +489 -0
  110. data/public/css/webtools.css +65 -0
  111. data/public/favicon.ico +0 -0
  112. data/public/flot/API.txt +1201 -0
  113. data/public/flot/FAQ.txt +76 -0
  114. data/public/flot/LICENSE.txt +22 -0
  115. data/public/flot/Makefile +9 -0
  116. data/public/flot/NEWS.txt +508 -0
  117. data/public/flot/PLUGINS.txt +137 -0
  118. data/public/flot/README.txt +90 -0
  119. data/public/flot/examples/ajax.html +143 -0
  120. data/public/flot/examples/annotating.html +75 -0
  121. data/public/flot/examples/arrow-down.gif +0 -0
  122. data/public/flot/examples/arrow-left.gif +0 -0
  123. data/public/flot/examples/arrow-right.gif +0 -0
  124. data/public/flot/examples/arrow-up.gif +0 -0
  125. data/public/flot/examples/basic.html +38 -0
  126. data/public/flot/examples/data-eu-gdp-growth-1.json +4 -0
  127. data/public/flot/examples/data-eu-gdp-growth-2.json +4 -0
  128. data/public/flot/examples/data-eu-gdp-growth-3.json +4 -0
  129. data/public/flot/examples/data-eu-gdp-growth-4.json +4 -0
  130. data/public/flot/examples/data-eu-gdp-growth-5.json +4 -0
  131. data/public/flot/examples/data-eu-gdp-growth.json +4 -0
  132. data/public/flot/examples/data-japan-gdp-growth.json +4 -0
  133. data/public/flot/examples/data-usa-gdp-growth.json +4 -0
  134. data/public/flot/examples/graph-types.html +75 -0
  135. data/public/flot/examples/hs-2004-27-a-large_web.jpg +0 -0
  136. data/public/flot/examples/image.html +45 -0
  137. data/public/flot/examples/index.html +44 -0
  138. data/public/flot/examples/interacting-axes.html +97 -0
  139. data/public/flot/examples/interacting.html +93 -0
  140. data/public/flot/examples/layout.css +6 -0
  141. data/public/flot/examples/multiple-axes.html +60 -0
  142. data/public/flot/examples/navigate.html +118 -0
  143. data/public/flot/examples/percentiles.html +57 -0
  144. data/public/flot/examples/pie.html +756 -0
  145. data/public/flot/examples/realtime.html +83 -0
  146. data/public/flot/examples/resize.html +61 -0
  147. data/public/flot/examples/selection.html +114 -0
  148. data/public/flot/examples/setting-options.html +61 -0
  149. data/public/flot/examples/stacking.html +77 -0
  150. data/public/flot/examples/symbols.html +49 -0
  151. data/public/flot/examples/thresholding.html +54 -0
  152. data/public/flot/examples/time.html +71 -0
  153. data/public/flot/examples/tracking.html +95 -0
  154. data/public/flot/examples/turning-series.html +98 -0
  155. data/public/flot/examples/visitors.html +90 -0
  156. data/public/flot/examples/zooming.html +98 -0
  157. data/public/flot/excanvas.js +1427 -0
  158. data/public/flot/excanvas.min.js +1 -0
  159. data/public/flot/jquery.colorhelpers.js +179 -0
  160. data/public/flot/jquery.colorhelpers.min.js +1 -0
  161. data/public/flot/jquery.flot.crosshair.js +167 -0
  162. data/public/flot/jquery.flot.crosshair.min.js +1 -0
  163. data/public/flot/jquery.flot.fillbetween.js +183 -0
  164. data/public/flot/jquery.flot.fillbetween.min.js +1 -0
  165. data/public/flot/jquery.flot.image.js +238 -0
  166. data/public/flot/jquery.flot.image.min.js +1 -0
  167. data/public/flot/jquery.flot.js +2599 -0
  168. data/public/flot/jquery.flot.min.js +6 -0
  169. data/public/flot/jquery.flot.navigate.js +336 -0
  170. data/public/flot/jquery.flot.navigate.min.js +1 -0
  171. data/public/flot/jquery.flot.pie.js +750 -0
  172. data/public/flot/jquery.flot.pie.min.js +1 -0
  173. data/public/flot/jquery.flot.resize.js +60 -0
  174. data/public/flot/jquery.flot.resize.min.js +1 -0
  175. data/public/flot/jquery.flot.selection.js +344 -0
  176. data/public/flot/jquery.flot.selection.min.js +1 -0
  177. data/public/flot/jquery.flot.stack.js +184 -0
  178. data/public/flot/jquery.flot.stack.min.js +1 -0
  179. data/public/flot/jquery.flot.symbol.js +70 -0
  180. data/public/flot/jquery.flot.symbol.min.js +1 -0
  181. data/public/flot/jquery.flot.threshold.js +103 -0
  182. data/public/flot/jquery.flot.threshold.min.js +1 -0
  183. data/public/flot/jquery.js +8316 -0
  184. data/public/flot/jquery.min.js +23 -0
  185. data/public/genPacking.pl +30 -0
  186. data/public/index.html +28 -0
  187. data/public/install.tpz +66 -0
  188. data/public/installAndRun.tpz +5 -0
  189. data/public/jsTree/jquery.jstree.js +3510 -0
  190. data/public/jsTree/themes/default/d.gif +0 -0
  191. data/public/jsTree/themes/default/d.png +0 -0
  192. data/public/jsTree/themes/default/style.css +73 -0
  193. data/public/jsTree/themes/default/throbber.gif +0 -0
  194. data/public/readMe.txt +9 -0
  195. data/public/scripts/CodeBrowser.js +645 -0
  196. data/public/scripts/Debugger.js +134 -0
  197. data/public/scripts/MethodList.js +72 -0
  198. data/public/scripts/ObjectLog.js +59 -0
  199. data/public/scripts/SessionList.js +164 -0
  200. data/public/scripts/Statistics.js +266 -0
  201. data/public/scripts/editor.js +430 -0
  202. data/public/scripts/jjmenu.js +375 -0
  203. data/public/scripts/jquery-ui.js +1012 -0
  204. data/public/scripts/jquery.js +154 -0
  205. data/public/scripts/webtools.js +374 -0
  206. data/public/src/CodeBrowser.gs +416 -0
  207. data/public/src/Debugger.gs +132 -0
  208. data/public/src/MethodList.gs +130 -0
  209. data/public/src/ObjectLog.gs +73 -0
  210. data/public/src/Server.gs +544 -0
  211. data/public/src/SessionList.gs +172 -0
  212. data/public/src/SharedPageCache.gs +66 -0
  213. data/public/src/StatProcess.gs +280 -0
  214. data/public/src/StatProcessType.gs +242 -0
  215. data/public/src/StatStatistic.gs +381 -0
  216. data/public/src/Statistics.gs +222 -0
  217. data/public/src/Statmonitor.gs +490 -0
  218. data/public/src/Tool.gs +86 -0
  219. data/public/src/VersionReport.gs +52 -0
  220. data/public/src/Workspace.gs +163 -0
  221. data/views/debugger.rhtml +6 -9
  222. metadata +344 -243
  223. data/lib/web_tools/#debugger.rb# +0 -212
  224. data/lib/web_tools/browser.rb +0 -45
  225. data/public/images/favicon.ico +0 -0
  226. data/public/javascript/CodeMirror/LICENSE +0 -23
  227. data/public/javascript/CodeMirror/css/Smalltalk.css +0 -34
  228. data/public/javascript/CodeMirror/js/codemirror.js +0 -582
  229. data/public/javascript/CodeMirror/js/editor.js +0 -1671
  230. data/public/javascript/CodeMirror/js/highlight.js +0 -68
  231. data/public/javascript/CodeMirror/js/parseSmalltalk.js +0 -126
  232. data/public/javascript/CodeMirror/js/parsedummy.js +0 -32
  233. data/public/javascript/CodeMirror/js/select.js +0 -699
  234. data/public/javascript/CodeMirror/js/stringstream.js +0 -159
  235. data/public/javascript/CodeMirror/js/tokenize.js +0 -57
  236. data/public/javascript/CodeMirror/js/undo.js +0 -413
  237. data/public/javascript/CodeMirror/js/util.js +0 -133
  238. data/public/javascript/CodeMirror/testSmalltalkParser.html +0 -116
  239. data/public/javascript/ace/ace-uncompressed.js +0 -17299
  240. data/public/javascript/ace/ace.js +0 -1
  241. data/public/javascript/ace/keybinding-emacs.js +0 -1
  242. data/public/javascript/ace/keybinding-vim.js +0 -1
  243. data/public/javascript/ace/mode-c_cpp.js +0 -1
  244. data/public/javascript/ace/mode-clojure.js +0 -1
  245. data/public/javascript/ace/mode-coffee.js +0 -1
  246. data/public/javascript/ace/mode-csharp.js +0 -1
  247. data/public/javascript/ace/mode-css.js +0 -1
  248. data/public/javascript/ace/mode-groovy.js +0 -1
  249. data/public/javascript/ace/mode-html.js +0 -1
  250. data/public/javascript/ace/mode-java.js +0 -1
  251. data/public/javascript/ace/mode-javascript.js +0 -1
  252. data/public/javascript/ace/mode-json.js +0 -1
  253. data/public/javascript/ace/mode-lua.js +0 -1
  254. data/public/javascript/ace/mode-markdown.js +0 -1
  255. data/public/javascript/ace/mode-ocaml.js +0 -1
  256. data/public/javascript/ace/mode-perl.js +0 -1
  257. data/public/javascript/ace/mode-php.js +0 -1
  258. data/public/javascript/ace/mode-python.js +0 -1
  259. data/public/javascript/ace/mode-ruby.js +0 -1
  260. data/public/javascript/ace/mode-scad.js +0 -1
  261. data/public/javascript/ace/mode-scala.js +0 -1
  262. data/public/javascript/ace/mode-scss.js +0 -1
  263. data/public/javascript/ace/mode-svg.js +0 -1
  264. data/public/javascript/ace/mode-textile.js +0 -1
  265. data/public/javascript/ace/mode-xml.js +0 -1
  266. data/public/javascript/ace/theme-clouds.js +0 -1
  267. data/public/javascript/ace/theme-clouds_midnight.js +0 -1
  268. data/public/javascript/ace/theme-cobalt.js +0 -1
  269. data/public/javascript/ace/theme-crimson_editor.js +0 -1
  270. data/public/javascript/ace/theme-dawn.js +0 -1
  271. data/public/javascript/ace/theme-eclipse.js +0 -1
  272. data/public/javascript/ace/theme-idle_fingers.js +0 -1
  273. data/public/javascript/ace/theme-kr_theme.js +0 -1
  274. data/public/javascript/ace/theme-merbivore.js +0 -1
  275. data/public/javascript/ace/theme-merbivore_soft.js +0 -1
  276. data/public/javascript/ace/theme-mono_industrial.js +0 -1
  277. data/public/javascript/ace/theme-monokai.js +0 -1
  278. data/public/javascript/ace/theme-pastel_on_dark.js +0 -1
  279. data/public/javascript/ace/theme-solarized_dark.js +0 -1
  280. data/public/javascript/ace/theme-solarized_light.js +0 -1
  281. data/public/javascript/ace/theme-textmate.js +0 -1
  282. data/public/javascript/ace/theme-twilight.js +0 -1
  283. data/public/javascript/ace/theme-vibrant_ink.js +0 -1
  284. data/public/javascript/ace/worker-coffee.js +0 -1
  285. data/public/javascript/ace/worker-css.js +0 -1
  286. data/public/javascript/ace/worker-javascript.js +0 -1
  287. data/public/javascript/webtools/browser.js +0 -260
  288. data/public/javascript/webtools/debugger.coffee +0 -286
  289. data/public/javascript/webtools/debugger.js +0 -366
  290. data/public/javascript/webtools/sessions.coffee +0 -17
  291. data/public/javascript/webtools/sessions.js +0 -27
  292. data/public/javascript/webtools/version.coffee +0 -14
  293. data/public/javascript/webtools/version.js +0 -20
  294. data/public/stylesheets/jquery.contextMenu.css +0 -62
  295. data/public/stylesheets/webtools.css +0 -53
  296. data/public/test.html +0 -47
@@ -1,109 +1,111 @@
1
1
  require 'web_tools/support/ruby'
2
2
 
3
3
  module WebTools
4
- # The CodeBrowser is a ViewModel for MagLev code browsing. It keeps the
5
- # entire state of the UI and returns structured data for use by a UI.
6
- # For the first pass, we do not cache anything.
7
- class CodeBrowser
8
- def self.class_and_module_list
9
- { 'modules' => WebTools::Ruby.class_and_module_names }
10
- end
4
+ module Support
5
+ # The CodeBrowser is a ViewModel for MagLev code browsing. It keeps the
6
+ # entire state of the UI and returns structured data for use by a UI.
7
+ # For the first pass, we do not cache anything.
8
+ class CodeBrowser
9
+ def self.class_and_module_list
10
+ { 'modules' => Ruby.class_and_module_names }
11
+ end
11
12
 
12
- def select_module(module_name)
13
- mod = Ruby.find_in_namespace(module_name)
14
- methods = mod.instance_methods(false) +
15
- mod.protected_instance_methods(false) +
16
- mod.private_instance_methods(false)
17
- {
18
- :ancestors => mod.ancestors.reverse,
19
- :constants => mod.constants.sort,
20
- :instance_methods => methods.uniq.sort,
21
- :module_methods => Ruby.module_fns_for(mod),
22
- :selected_module => module_name,
23
- }
24
- end
13
+ def select_module(module_name)
14
+ mod = Ruby.find_in_namespace(module_name)
15
+ methods = mod.instance_methods(false) +
16
+ mod.protected_instance_methods(false) +
17
+ mod.private_instance_methods(false)
18
+ {
19
+ :ancestors => mod.ancestors.reverse,
20
+ :constants => mod.constants.sort,
21
+ :instance_methods => methods.uniq.sort,
22
+ :module_methods => Ruby.module_fns_for(mod),
23
+ :selected_module => module_name,
24
+ }
25
+ end
25
26
 
26
- def select_constant(module_name, const_name)
27
- parent = Ruby.find_in_namespace module_name
28
- {
29
- :const_value => ObjectInfo.for(parent.const_get(const_name)),
30
- :selected_constant => const_name,
31
- :selected_module => module_name,
32
- }
33
- end
27
+ def select_constant(module_name, const_name)
28
+ parent = Ruby.find_in_namespace module_name
29
+ {
30
+ :const_value => ObjectInfo.for(parent.const_get(const_name)),
31
+ :selected_constant => const_name,
32
+ :selected_module => module_name,
33
+ }
34
+ end
34
35
 
35
- def select_method(module_name, method_name, is_instance_method)
36
- mod = Ruby.find_in_namespace(module_name)
37
- src, file, line = mod.method_source(method_name, is_instance_method)
38
- {
39
- :is_instance_method => is_instance_method,
40
- :method_line_number => line,
41
- :method_source => src,
42
- :method_source_file => file,
43
- :module_name => module_name,
44
- :selected_method => method_name,
45
- }
46
- end
36
+ def select_method(module_name, method_name, is_instance_method)
37
+ mod = Ruby.find_in_namespace(module_name)
38
+ src, file, line = mod.method_source(method_name, is_instance_method)
39
+ {
40
+ :is_instance_method => is_instance_method,
41
+ :method_line_number => line,
42
+ :method_source => src,
43
+ :method_source_file => file,
44
+ :module_name => module_name,
45
+ :selected_method => method_name,
46
+ }
47
+ end
47
48
 
48
- def object_info(object_id)
49
- ObjectInfo.for(object_id)
49
+ def object_info(object_id)
50
+ ObjectInfo.for(object_id)
51
+ end
50
52
  end
51
- end
52
53
 
53
- class ObjectInfo
54
- # Return a new ObjectInfo instance for the object with the given object
55
- # id.
56
- def self.for_id(object_id)
57
- new(ObjectSpace._id2ref(object_id))
58
- end
54
+ class ObjectInfo
55
+ # Return a new ObjectInfo instance for the object with the given object
56
+ # id.
57
+ def self.for_id(object_id)
58
+ new(ObjectSpace._id2ref(object_id))
59
+ end
59
60
 
60
- # Return a new ObjectInfo instance for the given object.
61
- def self.for(object)
62
- new(object)
63
- end
61
+ # Return a new ObjectInfo instance for the given object.
62
+ def self.for(object)
63
+ new(object)
64
+ end
64
65
 
65
- attr_reader :info
66
+ attr_reader :info
66
67
 
67
- def initialize(obj)
68
- @info = { }
69
- @info[:object_id] = obj.object_id
70
- @info[:class] = obj.class.name
71
- @info[:inspect] = obj.inspect
72
- @info[:instance_variables] = []
73
- @info[:enumerated] = []
74
- @info[:enumerated_size] = obj.respond_to?(:size) ? obj.size : nil
68
+ def initialize(obj)
69
+ @info = { }
70
+ @info[:object_id] = obj.object_id
71
+ @info[:class] = obj.class.name
72
+ @info[:inspect] = obj.inspect
73
+ @info[:instance_variables] = []
74
+ @info[:enumerated] = []
75
+ @info[:enumerated_size] = obj.respond_to?(:size) ? obj.size : nil
75
76
 
76
- obj.instance_variables.each do |iv|
77
- val = obj.instance_variable_get(iv)
78
- @info[:instance_variables] << [iv, val.inspect, val.object_id]
79
- end
77
+ obj.instance_variables.each do |iv|
78
+ val = obj.instance_variable_get(iv)
79
+ @info[:instance_variables] << [iv, val.inspect, val.object_id]
80
+ end
80
81
 
81
- limit = 10
82
- case obj
83
- when Enumerable, Array
84
- obj.each_with_index do |o,i|
85
- if i > limit
86
- @info[:enumerated] << '...'
87
- break
88
- else
89
- @info[:enumerated] << o.inspect
82
+ limit = 10
83
+ case obj
84
+ when Enumerable, Array
85
+ obj.each_with_index do |o,i|
86
+ if i > limit
87
+ @info[:enumerated] << '...'
88
+ break
89
+ else
90
+ @info[:enumerated] << o.inspect
91
+ end
90
92
  end
91
- end
92
93
 
93
- when Hash
94
- obj.each_with_index do |pair, idx|
95
- if idx > limit
96
- @info[:enumerated] << ['', '...']
97
- break
94
+ when Hash
95
+ obj.each_with_index do |pair, idx|
96
+ if idx > limit
97
+ @info[:enumerated] << ['', '...']
98
+ break
99
+ end
100
+ @info[:enumerated] << [pair[0].to_s, pair[1].inspect]
98
101
  end
99
- @info[:enumerated] << [pair[0].to_s, pair[1].inspect]
100
102
  end
101
- end
102
103
 
103
- end
104
+ end
104
105
 
105
- def to_json(*args)
106
- @info.to_json
106
+ def to_json(*args)
107
+ @info.to_json
108
+ end
107
109
  end
108
110
  end
109
111
  end
@@ -0,0 +1,303 @@
1
+ # require 'maglev/objectlog'
2
+
3
+ module WebTools
4
+ module Support
5
+ module Debugger
6
+ ExceptionFrames = [:raise, :"signal:", :"signal", "_rubyReraise"]
7
+ RubyEnv = 1
8
+
9
+ extend self
10
+
11
+ ##
12
+ # Return the ObjectLog wrapper module
13
+ def object_log
14
+ ObjectLog
15
+ end
16
+
17
+ ##
18
+ # Saves an exception to the ObjectLog.
19
+ # This will abort the pending transaction.
20
+ def save_exception(exception)
21
+ if Maglev.needs_commit
22
+ warn("Saving exception to ObjectLog, discarding transaction")
23
+ end
24
+ Maglev.abort_transaction
25
+ DebuggerLogEntry.create_continuation_labeled(exception.message)
26
+ Maglev.commit_transaction
27
+ end
28
+
29
+ ##
30
+ # Calls the passed block in a new Thread.
31
+ #
32
+ # If the argument is true, any exception will be saved to the
33
+ # ObjectLog and re-raised. If the argument is false (default),
34
+ # any exception will wake the parent and suspend the failed thread
35
+ # for inspection.
36
+ # => the suspended thread and the exception that stopped it, if any
37
+ # => result of the passed block, if the thread finished
38
+ # => raises Exception, if any
39
+ def debug(reraise = false, &block)
40
+ raise ArgumentError, "must supply a block to debug" unless block
41
+
42
+ client = Thread.start(Thread.current, block) do |parent_thread, blk|
43
+ Thread.pass
44
+ begin
45
+ Thread.current[:result] = blk.call
46
+ rescue Exception => e
47
+ if reraise
48
+ save_exception(e.message)
49
+ raise e
50
+ else
51
+ result = Process.new(Thread.current)
52
+ result.exception = e
53
+ Thread.current[:result] = result
54
+ parent_thread.wakeup
55
+ Thread.stop
56
+ end
57
+ end
58
+ end
59
+ client.join # raises exception if client aborted
60
+ if (result = client[:result]).is_a? Process
61
+ result.pop_exception_handling_frames
62
+ end
63
+ result
64
+ end
65
+
66
+ class Wrapper; end
67
+
68
+ class Process < Wrapper
69
+ attr_accessor :thread, :exception, :timestamp, :label
70
+
71
+ def self.new(thread)
72
+ if thread.is_a? ObjectLogEntry
73
+ return ObjectLogError.new(thread) unless self == ObjectLogError
74
+ end
75
+ super(thread)
76
+ end
77
+
78
+ def initialize(thread)
79
+ @label = thread.inspect
80
+ @thread = thread
81
+ @timestamp = Time.now
82
+ end
83
+
84
+ # Kill process, remove entry from ObjectLog
85
+ def delete
86
+ @thread.exit
87
+ end
88
+
89
+ def ruby_frames
90
+ frames.select do |frame|
91
+ frame.gsmethod.__env_id == RubyEnv
92
+ end
93
+ end
94
+
95
+ def frames
96
+ methods = []
97
+ @thread.__stack_depth.times do |idx|
98
+ methods << [@thread.__method_at(idx + 1), idx + 1]
99
+ end
100
+ methods.collect do |method, idx|
101
+ Frame.new(:method => method, :index => idx, :thread => thread)
102
+ end
103
+ end
104
+
105
+ ##
106
+ # Searches method frames included in ExceptionFrames from the top
107
+ # of the stack, and resets the stack to the last ruby frame before
108
+ # that. If no useable frame is found, the stack is not modified.
109
+ def pop_exception_handling_frames
110
+ m = @thread.__method_at(i = 1)
111
+ until ExceptionFrames.include?(m.__name) or i >= @thread.__stack_depth
112
+ i += 1
113
+ m = @thread.__method_at(i)
114
+ end
115
+ if i < @thread.__stack_depth
116
+ until m.__env_id == RubyEnv or i >= @thread.__stack_depth
117
+ i += 1
118
+ m = @thread.__method_at(i)
119
+ end
120
+ end
121
+ @thread.__trim_stack_to_level(i) unless i >= @thread.__stack_depth
122
+ end
123
+
124
+ def [](key)
125
+ @thread[key]
126
+ end
127
+
128
+ def []=(key, value)
129
+ @thread[key] = value
130
+ end
131
+
132
+ def to_hash
133
+ { :label => label,
134
+ :process_id => thread.object_id,
135
+ :timestamp => timestamp }
136
+ end
137
+ end
138
+
139
+ class ObjectLogError < Process
140
+ def initialize(error)
141
+ super(error)
142
+ @log_entry = error
143
+ @label = error.label
144
+ @timestamp = error.timestamp
145
+ @thread = error.continuation
146
+ end
147
+
148
+ def delete
149
+ if Maglev::System.needs_commit
150
+ raise Exception, "Abort would loose data. Commit your data and try again"
151
+ end
152
+ Maglev.abort_transaction
153
+ ObjectLogEntry.object_log.delete(@log_entry)
154
+ Maglev.commit_transaction
155
+ end
156
+ end
157
+
158
+ class Frame < Wrapper
159
+ attr_reader :debug_info, :gsmethod, :index, :thread,
160
+ :method_name, :defining_class, :block_nesting
161
+
162
+ def initialize(params)
163
+ @gsmethod = params[:method]
164
+ @thread = params[:thread]
165
+ @index = params[:index]
166
+ initialize_frame_info
167
+ end
168
+
169
+ # Pop frame off the stack, effectively restarting it
170
+ def delete
171
+ @thread.__trim_stack_to_level(@index)
172
+ end
173
+
174
+ # Step. The manner of stepping defaults to :over, but :into or the
175
+ # number of steps can be passed as arguments
176
+ def step(symbol = :over)
177
+ raise RuntimeError, "can only step top frame" unless @index === 1
178
+ case symbol
179
+ when :into
180
+ @thread.__step_over_in_frame(0)
181
+ when :over
182
+ @thread.__step_over_in_frame(1)
183
+ when Fixnum
184
+ @thread.__step_over_in_frame(arg)
185
+ end
186
+ end
187
+
188
+ def context_eval(str)
189
+ context_object.instance_eval(str)
190
+ end
191
+
192
+ def context_object
193
+ @context ||= Context.create_for(self,
194
+ debug_info![:self],
195
+ debug_info![:context])
196
+ end
197
+
198
+ def initialize_frame_info
199
+ label = @gsmethod.__name
200
+ @block_nesting = 0
201
+ m = @gsmethod
202
+ while label.nil?
203
+ m = m.__home_method
204
+ label = m.__name
205
+ @block_nesting += 1
206
+ end
207
+ @defining_class = m.__in_class
208
+ @class = @gsmethod.__in_class
209
+ @method_name = label
210
+ if @gsmethod.__source_location
211
+ @source_location = @gsmethod.__source_location.join(":")
212
+ end
213
+ end
214
+
215
+ def debug_info!
216
+ @debug_info ||=
217
+ begin
218
+ ary = @thread.__gsi_debugger_detailed_report_at(@index)
219
+ context = {}
220
+ # First the named temps, matched to values
221
+ ary[6].each_with_index {|name,idx| context[name] = ary[7][idx] }
222
+ # Then the remaining scope values with temporary names
223
+ ary[7][ary[6].size..-1].each_with_index {|v,i| context[:'t#{i}'] = v}
224
+ context[:'(receiver)'] = ary[1]
225
+ context[:'(class)'] = ary[1].class
226
+ context[:'(self)'] = ary[2]
227
+ { :gsMethod => ary[0],
228
+ :receiver => ary[1],
229
+ :self => ary[2],
230
+ :method => ary[3],
231
+ :stepOffset => ary[4],
232
+ :stepPoints => ary[5],
233
+ :source => ary[8],
234
+ :context => context }
235
+ end
236
+ end
237
+
238
+ def to_hash
239
+ { :method_name => @method_name,
240
+ :class => @class,
241
+ :index => @index,
242
+ :defining_class => @defining_class,
243
+ :source_location => @source_location,
244
+ :block_nesting => @block_nesting,
245
+ :debug_info => @debug_info }
246
+ end
247
+
248
+ # Emulates the context of a frame execution
249
+ # Defines accessors to the frame locals and sets the instance variables to
250
+ # point to the original object's values
251
+ class Context
252
+ # Tries to create a duplicate of the receiver. If that is not possible,
253
+ # creates a new instance of self. In any case, a singleton class is added
254
+ # to define accessors to frame local values
255
+ def self.create_for(frame, receiver, context_hash)
256
+ rcv = nil
257
+ begin
258
+ rcv = receiver.dup
259
+ rescue Exception
260
+ end
261
+ if receiver === rcv || rcv.nil?
262
+ rcv = self.new(receiver)
263
+
264
+ receiver.instance_variables do |name|
265
+ rcv.instance_variable_set(name, receiver.instance_variable_get(name))
266
+ end
267
+
268
+ receiver_mod = (receiver.is_a?(Module) ? receiver : receiver.class)
269
+ receiver_mod.constants do |sym|
270
+ rcv.singleton_class.const_set(sym, receiver_mod.const_get(sym))
271
+ end
272
+ end
273
+
274
+ context_hash.each do |k,v|
275
+ next if [:"(self)", :"(class)", :"(receiver)"].include? k
276
+ rcv.singleton_class.define_method(:"#{k}") { v }
277
+ rcv.singleton_class.define_method(:"#{k}=") do |v|
278
+ frame.thread.__frame_at_temp_named_put(frame.index, k, v)
279
+ end
280
+ end
281
+ rcv
282
+ end
283
+
284
+ def initialize(rcv)
285
+ @receiver = rcv
286
+ end
287
+
288
+ def myself
289
+ @receiver
290
+ end
291
+
292
+ def respond_to?(method)
293
+ @receiver.respond_to? method
294
+ end
295
+
296
+ def method_missing(method, *args, &block)
297
+ @receiver.send(method, *args, &block)
298
+ end
299
+ end
300
+ end
301
+ end
302
+ end
303
+ end