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
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