maglev-webtools 0.2.1 → 1.0

Sign up to get free protection for your applications and to get access to all the features.
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
data/README.rdoc CHANGED
@@ -1,40 +1,51 @@
1
- = WebTools Example
1
+ = WebTools Example, a demo for what a unified Ruby mirror API can offer you
2
2
 
3
- The WebTools Sinatra application running in MagLev allows you to explore a
4
- MagLev Ruby application's Classes, Modules, Methods, Constants, and Ancestors
5
- in a web browser.
3
+ The WebTools Sinatra application allows you to explore a Ruby
4
+ application's Classes, Modules, Methods, Constants, and Ancestors in a
5
+ web browser, as well as run and debug code, or explore VM statistics
6
+ and other info.
6
7
 
7
- It will also allow you to explore GemStone/S Smalltalk code, and to examine
8
- detailed statistics about all processes connected to GemStone/S.
8
+ If running on MagLev, it will also allow you to explore GemStone/S
9
+ Smalltalk code, and to examine detailed statistics about all processes
10
+ connected to GemStone/S.
9
11
 
10
12
  === Setup
11
13
 
12
- 1. Download and install MagLev using instructions at
13
- https://github.com/MagLev/maglev/blob/master/README.rdoc
14
+ $ rvm use [maglev-head|rbx|jruby|ruby-head]
15
+ $ bundle install
14
16
 
15
- 2. Start the MagLev server
16
- $ cd $MAGLEV_HOME
17
- $ maglev start
18
-
19
- 3. Install necessary gems:
20
- $ cd <to this directory>
21
- $ $MAGLEV_HOME/bin/bundle install
22
-
23
- ### Temporary workaround for https://magtrac.gemstone.com/ticket/879 ###
17
+ ### Temporary workaround on MagLev for https://github.com/MagLev/maglev/issues/58 ###
24
18
  $ maglev-gem pristine rack
25
19
 
26
20
  == Viewing Ruby code
27
21
 
28
22
  Run the WebTools Sinatra application
29
23
 
30
- $ rake
24
+ $ bundle exec rake
31
25
 
32
26
  This will start WEBrick in your current window. Hit Ctl-C to stop.
33
27
 
34
- Browse to http://localhost:9292/, click on a class or module, then
35
- click on a constant or method. Results appear in the bottom pane, file
36
- locations with line numbers in the bottom status line, and time spent
37
- on the server/network/client in the top status line.
28
+ Browse to http://localhost:9292/webtools, open a browser, click on a
29
+ namespace, then click on a constant in that namespace. You will see
30
+ instance methods. Select boxes show ancestors and implementors of the
31
+ selected method in the hierarchy. To see class methods, switch to the
32
+ "Class" tab.
33
+
34
+ Method source appears in the bottom pane, and time spent on the
35
+ server/network/client in the status line. Depending on your Ruby,
36
+ saving methods will work or not.
37
+
38
+ If you choose to open a workspace, you can run Ruby code. If the code
39
+ has an error, a debugger will start. Depending on the capabilities of
40
+ your Ruby, you can also inspect stack frames, trim the stack, step
41
+ through methods and inspect arguments and locals. As a rule of thumb,
42
+ almost nothing of this will work with MRI, because the MRI reflection
43
+ is ad-hoc, infantile, and generally a prime example for an utter lack
44
+ of -- or disgregard for -- engineering prinicples. Have a look at the
45
+ Ruby mirrors project (https://github.com/timfel/rubymirrors) for more
46
+ information.
47
+
48
+ == MagLev specific demos
38
49
 
39
50
  === Add classes and modules from ActiveModel
40
51
 
@@ -46,8 +57,9 @@ to load an empty database.</b>
46
57
 
47
58
  $ rake meta
48
59
 
49
- Click on "Refresh View" in WebTools. Note that AValidPerson now appears in the
50
- class list, as do a number of classes/modules from ActiveModel and ActiveSupport.
60
+ Open a new browser in WebTools. Note that AValidPerson now appears in
61
+ the class list, as do a number of classes/modules from ActiveModel and
62
+ ActiveSupport.
51
63
 
52
64
  Click on the class AValidPerson and compare it with the source
53
65
  (meta_demo.rb). Some things to note:
@@ -92,7 +104,7 @@ $MAGLEV_HOME/gemstone/examples/www. The Smalltalk example code can be
92
104
  invoked from ruby (a demonstration of how to invoke Smalltalk from Ruby),
93
105
  via:
94
106
 
95
- $ rake smalltalk:run
107
+ $ rake smalltalk
96
108
 
97
109
  Then browse to http://localhost:8080/ and explore
98
110
 
@@ -100,10 +112,7 @@ Hit Ctl-C in the terminal window to stop.
100
112
 
101
113
  == Known problems
102
114
 
103
- Network timeouts are not caught. EAGAIN is not handled. If you're running WebTools on
104
- a slow network, this may cause data to not appear in the bottom pane.
105
-
106
- The line number displayed for evals is always 2. This will be fixed at a later date.
115
+ Oh, so many problems...
107
116
 
108
117
  == Contributing
109
118
 
data/bin/webtools CHANGED
@@ -1,14 +1,35 @@
1
- #!/usr/bin/env maglev-ruby
1
+ #!/usr/bin/env ruby
2
2
  $LOAD_PATH.unshift(File.expand_path("../../lib", __FILE__))
3
+ require 'rubygems'
3
4
  require 'rack'
4
5
  require 'web_tools'
5
6
 
7
+ # HACK
8
+ ARGV.each do |arg|
9
+ ARGV.shift
10
+ mirror_api = ARGV.first if arg == "-t"
11
+ end
12
+ mirror_api ||= RUBY_ENGINE
13
+ begin
14
+ require "#{mirror_api.downcase}/reflection"
15
+ MirrorAPI = Object.const_get(mirror_api.capitalize)
16
+ rescue LoadError
17
+ require "ruby/reflection"
18
+ MirrorAPI = Ruby
19
+ end
20
+ # HACK END ;)
21
+
6
22
  app = Rack::Builder.new do
7
23
  WebTools::UI.set :root, File.expand_path("../..", __FILE__)
8
24
  ui = WebTools::UI.new
25
+ WebTools.constants.each { |c| WebTools.const_get(c) }
26
+
9
27
  redirect = proc { |env| [301,
10
28
  {'Content-Type' => 'text/html', 'Location' => '/webtools/'},
11
29
  '<a href="/webtools">Moved permanently</a>'] }
30
+ WebTools::Tool.subclasses.each do |cls|
31
+ map('/webtools/' + cls.display_name) { run cls.new }
32
+ end
12
33
  map('/webtools/') { run ui }
13
34
  map('/') { run redirect }
14
35
  end
@@ -0,0 +1,156 @@
1
+ require 'sinatra/base'
2
+ require 'web_tools'
3
+ require 'web_tools/support/code_browser'
4
+ require 'web_tools/support/service_helper'
5
+
6
+ module WebTools
7
+ class CodeBrowser < Tool
8
+
9
+ def self.description
10
+ 'Browse Namespaces, Classes, and Methods'
11
+ end
12
+
13
+ get '/' do # Tool>>json in ST
14
+ json("response" => response_for_class,
15
+ "dictList" => dict_list,
16
+ "packageList" => [],
17
+ "classCatList" => class_cat_list,
18
+ "classList" => class_list,
19
+ "classDef" => "",
20
+ "superList" => super_list,
21
+ "methodFilterList" => [],
22
+ "methodList" => method_list,
23
+ "implList" => implementor_list,
24
+ "method" => method)
25
+ end
26
+
27
+ post '/removeClass' do
28
+ parent = reflect(Object).constant(params["dict"] || "Object").value
29
+ parent.constant(params["klass"]).delete
30
+ json({})
31
+ end
32
+
33
+ post '/removeMethod' do
34
+ parent = reflect(Object).constant(params["dict"] || "Object").value
35
+ klass = parent.constant(params["klass"]).value
36
+ klass = klass.singleton_class if params["isMeta"]
37
+ klass.method(params["name"]).delete
38
+ json({})
39
+ end
40
+
41
+ def response_for_class
42
+ # return nil if params["selector"]
43
+ # return nil unless params["request"]
44
+ # begin
45
+ # result = eval(params["request"])
46
+ # if result.is_a? Module
47
+ # return nil unless result.namespace
48
+ # response = { "dict" => result.namespace.my_class.inspect,
49
+ # "classCat" => nil,
50
+ # "klass" => result.inspect,
51
+ # "isMeta" => false,
52
+ # "superClass" => result.inspect,
53
+ # "methodCat" => nil,
54
+ # "selector" => nil,
55
+ # "implementor" => nil,
56
+ # "action" => "klass" }
57
+ # response.each {|k,v| params[k] = v }
58
+ # response
59
+ # else
60
+ # nil
61
+ # end
62
+ # rescue Exception => e
63
+ # { "action" => "klass",
64
+ # "error" => [e.class.inspect, e.message] }
65
+ # end
66
+ end
67
+
68
+ def dict_list
69
+ return [] unless params['isDictsTab']
70
+ pkgs = ["Object"]
71
+ reflect(Object).nested_classes.each do |k|
72
+ pkgs << k.name if k.nested_classes.any?
73
+ @dict = k if @dict.nil? && params['dict'] == k.name
74
+ end
75
+ pkgs.compact.uniq.sort
76
+ end
77
+
78
+ def class_cat_list
79
+ filter = (@dict || @package || reflect(Object))
80
+ names = []
81
+ class_cat_list_for(filter, names)
82
+ @class_category ||= filter
83
+ names.sort
84
+ end
85
+
86
+ def class_cat_list_for(klassmirror, ary)
87
+ klassmirror.nested_classes.each do |klass|
88
+ path = klass.name.gsub("::", "-")
89
+ unless ary.include? path
90
+ ary << path
91
+ if @class_category.nil? && params['classCat'] == path
92
+ @class_category = klass
93
+ end
94
+ class_cat_list_for(klass, ary)
95
+ end
96
+ end
97
+ end
98
+
99
+ # Returns a sorted list of class and module names in the Ruby Namespace
100
+ #
101
+ # @return [Array] sorted list of class and module names found in the Ruby
102
+ # namespace hierarchy.
103
+ def class_list
104
+ @klass = reflect(Object).constant(params["klass"]).value if params["klass"]
105
+ @klass = @klass.singleton_class if @klass && params["isMeta"]
106
+ (@class_category.nested_classes + [@class_category]).collect(&:name).uniq.sort
107
+ end
108
+
109
+ def super_list
110
+ return [] if @klass.nil?
111
+ if params["superClass"]
112
+ super_class = non_meta_name(params["superClass"])
113
+ @super_class = reflect(Object).constant(super_class).value
114
+ if super_class != params["superClass"]
115
+ @super_class = @super_class.singleton_class
116
+ end
117
+ else
118
+ @super_class = @klass
119
+ end
120
+ @super_list = @klass.ancestors.reverse
121
+ @super_list.collect(&:name)
122
+ end
123
+
124
+ def implementor_list
125
+ selected = params["implementor"]
126
+ return [] if @super_list.nil? || @super_list.empty?
127
+ list = @super_list.select do |c|
128
+ c.methods.include?(@selector)
129
+ end
130
+ @implementor = list.detect {|e| e.name == selected } || @klass
131
+ list.collect(&:name)
132
+ end
133
+
134
+ def method
135
+ return nil unless @implementor && @selector
136
+ nil.pause if Module === @implementor
137
+ @method = @implementor.method(@selector)
138
+ { "dictionaryName" => "",
139
+ "className" => @klass.name,
140
+ "isMeta" => params["isMeta"],
141
+ "category" => "",
142
+ "selector" => @selector,
143
+ "source" => @method.source,
144
+ "stepPoints" => @method.step_offsets,
145
+ "sends" => @method.send_offsets }
146
+ end
147
+
148
+ def method_list
149
+ selected = params["selector"]
150
+ return [] if @super_list.nil? || @super_list.empty?
151
+ list = @super_class.methods
152
+ @selector = selected if list.include? selected
153
+ list.sort
154
+ end
155
+ end
156
+ end
@@ -1,219 +1,116 @@
1
- require 'sinatra'
2
1
  require 'web_tools'
3
- require 'web_tools/support/service_helper'
4
- require 'rack/contrib/jsonp'
5
- require 'maglev/debugger'
6
- require 'maglev/method_source'
7
2
 
8
- module WebTools
9
- class Debugger < Sinatra::Base
10
- include WebTools::Support::ServiceHelper
11
- use Rack::JSONP
3
+ class WebTools::Debugger < WebTools::Tool
4
+ dont_show!
12
5
 
13
- def respond_json(obj)
14
- content_type :json
15
- result = case obj
16
- when Maglev::Debugger::Wrapper
17
- obj.to_hash
18
- else
19
- if obj.is_a? Array and
20
- obj.all? {|e| e.is_a? Maglev::Debugger::Wrapper}
21
- obj.collect(&:to_hash)
22
- else
23
- case obj
24
- when Array, Hash
25
- obj
26
- else
27
- details_for(obj)
28
- end
29
- end
30
- end
31
- body(result.to_json)
32
- end
33
-
34
- def process
35
- Maglev::Debugger::Process.new(ObjectSpace._id2ref(params[:oop].to_i))
36
- end
37
-
38
- def frames
39
- params.has_key?("all") ? process.frames : process.ruby_frames
40
- end
41
-
42
- def frame
43
- f = frames[params[:idx].to_i]
44
- f.debug_info!
45
- f
46
- end
47
-
48
- def objects
49
- instance_variables_for(object)
50
- end
51
-
52
- def object
53
- ctxt = frame.debug_info[:context]
54
- obj = nil
55
- variable_list = params[:splat].first.split("/objects/")
56
- variable_list.each do |name|
57
- name = name[0...(-"/objects".size)] if name.end_with? "/objects"
58
- obj = ctxt[name.to_sym]
59
- ctxt = instance_variables_for(obj)
60
- end
61
- obj
62
- end
63
-
64
- def instance_variables_for(object)
65
- object.instance_variables.inject({}) do |hash, var|
66
- hash[var.to_sym] = object.instance_variable_get(var)
67
- hash
68
- end
69
- end
6
+ before do
7
+ @entry = system.object_by_id(params["oop"].to_i).reflectee
8
+ @process = reflect(@entry.thread) if @entry
9
+ end
70
10
 
71
- def details_for(object)
72
- { "instance_variables" => instance_variables_for(object),
73
- "self" => object,
74
- "inspect" => object.inspect,
75
- "class" => object.class,
76
- "do-it" => nil,
77
- "do-it-result" => nil }
78
- end
11
+ get '/' do
12
+ return {} unless @entry
13
+ json("label" => @entry.exception.message,
14
+ "stack" => str_report_for(@process))
15
+ end
79
16
 
80
- before do
81
- Maglev.abort_transaction
82
- end
17
+ get '/frame' do
18
+ return {} unless @process
19
+ frame = @process.stack[params["frame"].to_i - 1]
20
+ return {} if frame.nil?
21
+ json("method" => method_data_from_frame(frame),
22
+ "variables" => variables_data_from_frame(frame))
23
+ end
83
24
 
84
- # => list of errors
85
- get "/process" do
86
- errors = ObjectLog.errors.collect {|e| Maglev::Debugger::Process.new(e) }
87
- processes = Thread.list.select(&:stop?).collect do |e|
88
- Maglev::Debugger::Process.new(e)
25
+ post '/step' do
26
+ return {} unless @process
27
+ steplevel = params["level"].to_i
28
+ stacksize = @process.stack.size
29
+
30
+ if params["level"]
31
+ @process.step(steplevel)
32
+ else
33
+ @process.run
34
+ sleep 0.2 until @process.reflectee.stop?
35
+ unless @process.alive? # No exception, return result
36
+ # TODO
37
+ nil.pause
89
38
  end
90
- respond_json (errors + processes)
91
39
  end
92
40
 
93
- get "/process/:oop" do
94
- respond_json process
95
- end
41
+ new_stack = @process.stack
42
+ frame = new_stack.first
96
43
 
97
- get "/process/:oop/frames" do
98
- respond_json frames
44
+ data = { "label" => @process.name,
45
+ "method" => method_data_from_frame(frame),
46
+ "variables" => variables_data_from_frame(frame) }
47
+ if new_stack.size != stacksize # Stack changed, reload
48
+ data["stack"] = str_report_for @process
99
49
  end
100
50
 
101
- get "/process/:oop/frames/:idx" do
102
- respond_json frame
103
- end
104
-
105
- get "/process/:oop/frames/:idx/objects" do
106
- respond_json frame.debug_info[:context]
107
- end
108
-
109
- get "/process/:oop/frames/:idx/objects/*" do
110
- if params[:splat].first.end_with? "objects"
111
- respond_json objects
112
- else
113
- respond_json details_for(object)
114
- end
115
- end
116
-
117
- delete "/process/:oop" do
118
- respond_json process.delete
119
- end
120
-
121
- delete "/process/:oop/frames/:idx" do
122
- respond_json frame.delete
123
- end
51
+ json(data)
52
+ end
124
53
 
125
- post "/process/:oop" do
126
- p = process
127
- return 404 if p.is_a? Maglev::Debugger::ObjectLogError
128
- if params["running"] == "true" and p.thread.alive? and p.thread.stop?
129
- p.thread.run
130
- Thread.pass
131
- Thread.pass
132
- p.thread.join
133
- if (result = p.thread[:result]).is_a? Maglev::Debugger::Process
134
- if params["debugging"] == "true"
135
- status 500
136
- body result.exception.inspect
137
- else
138
- p.thread.kill
139
- Thread.pass
140
- raise result.exception
141
- end
142
- else
143
- result
144
- end
145
- else
146
- 404
147
- end
148
- end
54
+ post '/restart' do
55
+ return {} unless @process
56
+ frame = @process.stack[params["frame"].to_i - 1]
57
+ return {} if frame.nil?
58
+ frame.restart
59
+ new_frame = @process.stack.first
60
+
61
+ json("label" => @process.name,
62
+ "stack" => str_report_for(@process),
63
+ "method" => method_data_from_frame(new_frame),
64
+ "variables" => variables_data_from_frame(new_frame))
65
+ end
149
66
 
150
- put "/process/:oop/frames/:idx" do
151
- # TODO: Really check the posted document
152
- if doIt = params["do-it"]
153
- begin
154
- result = frame.context_eval(doIt)
155
- rescue Exception => e
156
- result = e
157
- end
158
- current_frame = frame.to_hash
159
- current_frame[:"do-it"] = doIt
160
- current_frame[:"do-it-result"] = details_for(result)
161
- respond_json current_frame
162
- elsif params["index"] == "1" and params[:idx] == "0"
163
- current_frame = frame.to_hash
164
- until frame.method_name != current_frame[:method_name]
165
- frame.step(:into) # Step into until we find the next ruby frame
166
- end
167
- respond_json frame
168
- elsif di = params["debug_info"]
169
- current_frame = frame.to_hash
170
- if di["stepOffset"] && di["stepOffset"] != current_frame[:debug_info][:stepOffset]
171
- return 404 unless params[:idx] == "0"
172
- while di["stepOffset"].to_i > frame[:debug_info][:stepOffset].to_i
173
- frame.step(:over)
174
- end
175
- respond_json frame
176
- elsif di["source"] && di["source"] != current_frame[:debug_info][:source]
177
- current_frame = frame
178
- return 404 if frame.block_nesting > 0 # cannot change nested frames
179
- klass = current_frame.defining_class
180
- klass.set_method_source(current_frame.method_name, di["source"])
181
- current_frame.delete
182
- params[:idx] = "0"
183
- respond_json frame # Retreive the frame again, to show the updated source
184
- end
185
- else
186
- status 404
187
- respond_json frame
188
- end
189
- end
67
+ def method_data_from_frame(frame)
68
+ dict = frame.method.defining_class.nesting[1]
69
+ dict = dict ? dict.name : ""
70
+ { "source" => frame.method.source,
71
+ "stepPoints" => frame.method.step_offsets,
72
+ "sends" => frame.method.send_offsets,
73
+ "nowAt" => frame.step_offset,
74
+ "dictionaryName" => dict || "",
75
+ "className" => frame.method.defining_class.name,
76
+ "isMeta" => frame.method.defining_class.singleton_class? }
77
+ rescue Exception
78
+ return { "source" => "", "stepPoints" => "", "sends" => "", "nowAt" => 0,
79
+ "dictionaryName" => "", "className" => "", "isMeta" => "" }
80
+ end
190
81
 
191
- put "/process/:oop/frames/:idx/objects/*" do
192
- return 404 if params[:splat].first.end_with? "objects"
82
+ def variables_data_from_frame(frame)
83
+ list = [{ "name" => "self",
84
+ "string" => frame.self.name,
85
+ "oop" => frame.self.reflectee.object_id }]
86
+ if frame.self != frame.receiver
87
+ list << { "name" => "receiver",
88
+ "string" => frame.receiver.name,
89
+ "oop" => frame.receiver.reflectee.object_id }
90
+ end
91
+ frame.arguments.each do |k, v|
92
+ list << { "name" => k.to_s,
93
+ "string" => v.name,
94
+ "oop" => v.reflectee.object_id }
95
+ end
96
+ frame.locals.each do |k, v|
97
+ list << { "name" => k.to_s,
98
+ "string" => v.name,
99
+ "oop" => v.reflectee.object_id }
100
+ end
101
+ list
102
+ rescue Exception
103
+ return []
104
+ end
193
105
 
194
- if doIt = params["do-it"]
195
- begin
196
- result = object.instance_eval(doIt)
197
- rescue Exception => e
198
- result = e
199
- end
200
- return_value = details_for(object)
201
- return_value["do-it"] = doIt
202
- return_value["do-it-result"] = details_for(result)
203
- respond_json return_value
204
- else
205
- 404
106
+ def str_report_for(process_mirror)
107
+ process_mirror.stack.collect do |f|
108
+ str = ""
109
+ if f.method
110
+ separator = f.method.defining_class.singleton_class? ? '.' : '#'
111
+ str = "#{f.method.defining_class.name}#{separator}"
206
112
  end
207
- end
208
-
209
- # XXX: Remove me, please
210
- options '*' do
211
- [200,
212
- { 'Access-Control-Allow-Origin' => '*',
213
- 'Access-Control-Allow-Methods' => 'PUT, POST, GET, DELETE, OPTIONS',
214
- 'Access-Control-Max-Age' => '1000',
215
- 'Access-Control-Allow-Headers' => '*' },
216
- [""]]
113
+ str += (f.name || "block in #{f.selector}")
217
114
  end
218
115
  end
219
116
  end