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.
- data/README.rdoc +38 -29
- data/bin/webtools +22 -1
- data/lib/web_tools/code_browser.rb +156 -0
- data/lib/web_tools/debugger.rb +96 -199
- data/lib/web_tools/info.rb +1 -3
- data/lib/web_tools/method_list.rb +67 -0
- data/lib/web_tools/middleware/debugger.rb +10 -16
- data/lib/web_tools/object_log.rb +24 -0
- data/lib/web_tools/session_list.rb +119 -0
- data/lib/web_tools/shared_page_cache.rb +30 -0
- data/lib/web_tools/stat_process.rb +24 -0
- data/lib/web_tools/statistics.rb +14 -0
- data/lib/web_tools/support/app_model.rb +66 -101
- data/lib/web_tools/support/code_browser.rb +88 -86
- data/lib/web_tools/support/debugger.rb +303 -0
- data/lib/web_tools/support/error_log.rb +33 -0
- data/lib/web_tools/support/ruby.rb +60 -121
- data/lib/web_tools/support/service_helper.rb +38 -10
- data/lib/web_tools/support/smalltalk_extensions.rb +12 -0
- data/lib/web_tools/tool.rb +48 -0
- data/lib/web_tools/ui.rb +14 -53
- data/lib/web_tools/version_report.rb +29 -0
- data/lib/web_tools/workspace.rb +77 -0
- data/lib/web_tools.rb +14 -4
- data/public/CodeBrowser.html +51 -0
- data/public/CodeMirror/LICENSE +19 -0
- data/public/CodeMirror/css/codemirror.css +67 -0
- data/public/CodeMirror/css/default.css +18 -0
- data/public/CodeMirror/js/codemirror.js +2131 -0
- data/public/CodeMirror/js/ruby.js +195 -0
- data/public/CodeMirror/js/smalltalk.js +139 -0
- data/public/Debugger.html +28 -0
- data/public/MethodList.html +20 -0
- data/public/ObjectLog.html +20 -0
- data/public/SessionList.html +31 -0
- data/public/SharedPageCache.html +78 -0
- data/public/Statistics.html +64 -0
- data/public/VersionReport.html +50 -0
- data/public/Workspace.html +39 -0
- data/public/css/CodeBrowser.css +24 -0
- data/public/css/Debugger.css +32 -0
- data/public/css/MethodList.css +8 -0
- data/public/css/ObjectLog.css +5 -0
- data/public/css/SessionList.css +9 -0
- data/public/css/Statistics.css +24 -0
- data/public/{stylesheets → css}/base/images/ui-anim_basic_16x16.gif +0 -0
- data/public/{stylesheets → css}/base/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- data/public/{stylesheets → css}/base/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
- data/public/{stylesheets → css}/base/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
- data/public/{stylesheets → css}/base/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/public/{stylesheets → css}/base/images/ui-bg_glass_75_dadada_1x400.png +0 -0
- data/public/{stylesheets → css}/base/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- data/public/{stylesheets → css}/base/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- data/public/{stylesheets → css}/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- data/public/{stylesheets → css}/base/images/ui-icons_222222_256x240.png +0 -0
- data/public/{stylesheets → css}/base/images/ui-icons_2e83ff_256x240.png +0 -0
- data/public/{stylesheets → css}/base/images/ui-icons_454545_256x240.png +0 -0
- data/public/{stylesheets → css}/base/images/ui-icons_888888_256x240.png +0 -0
- data/public/{stylesheets → css}/base/images/ui-icons_cd0a0a_256x240.png +0 -0
- data/public/{stylesheets → css}/base/jquery.ui.accordion.css +0 -0
- data/public/{stylesheets → css}/base/jquery.ui.all.css +0 -0
- data/public/{stylesheets → css}/base/jquery.ui.autocomplete.css +0 -0
- data/public/{stylesheets → css}/base/jquery.ui.base.css +0 -0
- data/public/{stylesheets → css}/base/jquery.ui.button.css +0 -0
- data/public/{stylesheets → css}/base/jquery.ui.core.css +0 -0
- data/public/{stylesheets → css}/base/jquery.ui.datepicker.css +0 -0
- data/public/{stylesheets → css}/base/jquery.ui.dialog.css +0 -0
- data/public/{stylesheets → css}/base/jquery.ui.progressbar.css +0 -0
- data/public/{stylesheets → css}/base/jquery.ui.resizable.css +0 -0
- data/public/{stylesheets → css}/base/jquery.ui.selectable.css +0 -0
- data/public/{stylesheets → css}/base/jquery.ui.slider.css +0 -0
- data/public/{stylesheets → css}/base/jquery.ui.tabs.css +0 -0
- data/public/{stylesheets → css}/base/jquery.ui.theme.css +0 -0
- data/public/css/editor.css +25 -0
- data/public/css/jjmenu.css +33 -0
- data/public/css/menuitem.gif +0 -0
- data/public/css/more.gif +0 -0
- data/public/{stylesheets → css}/reset.css +1 -1
- data/public/css/smoothness/images/ui-anim_basic_16x16.gif +0 -0
- data/public/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- data/public/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
- data/public/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
- data/public/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/public/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
- data/public/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- data/public/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- data/public/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- data/public/css/smoothness/images/ui-icons_222222_256x240.png +0 -0
- data/public/css/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
- data/public/css/smoothness/images/ui-icons_454545_256x240.png +0 -0
- data/public/css/smoothness/images/ui-icons_888888_256x240.png +0 -0
- data/public/css/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
- data/public/css/smoothness/jquery-ui.css +489 -0
- data/public/css/ui-lightness/images/ui-anim_basic_16x16.gif +0 -0
- data/public/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
- data/public/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
- data/public/css/ui-lightness/images/ui-bg_flat_10_000000_40x100.png +0 -0
- data/public/css/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
- data/public/css/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
- data/public/css/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/public/css/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
- data/public/css/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
- data/public/css/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
- data/public/css/ui-lightness/images/ui-icons_222222_256x240.png +0 -0
- data/public/css/ui-lightness/images/ui-icons_228ef1_256x240.png +0 -0
- data/public/css/ui-lightness/images/ui-icons_ef8c08_256x240.png +0 -0
- data/public/css/ui-lightness/images/ui-icons_ffd27a_256x240.png +0 -0
- data/public/css/ui-lightness/images/ui-icons_ffffff_256x240.png +0 -0
- data/public/css/ui-lightness/jquery-ui.css +489 -0
- data/public/css/webtools.css +65 -0
- data/public/favicon.ico +0 -0
- data/public/flot/API.txt +1201 -0
- data/public/flot/FAQ.txt +76 -0
- data/public/flot/LICENSE.txt +22 -0
- data/public/flot/Makefile +9 -0
- data/public/flot/NEWS.txt +508 -0
- data/public/flot/PLUGINS.txt +137 -0
- data/public/flot/README.txt +90 -0
- data/public/flot/examples/ajax.html +143 -0
- data/public/flot/examples/annotating.html +75 -0
- data/public/flot/examples/arrow-down.gif +0 -0
- data/public/flot/examples/arrow-left.gif +0 -0
- data/public/flot/examples/arrow-right.gif +0 -0
- data/public/flot/examples/arrow-up.gif +0 -0
- data/public/flot/examples/basic.html +38 -0
- data/public/flot/examples/data-eu-gdp-growth-1.json +4 -0
- data/public/flot/examples/data-eu-gdp-growth-2.json +4 -0
- data/public/flot/examples/data-eu-gdp-growth-3.json +4 -0
- data/public/flot/examples/data-eu-gdp-growth-4.json +4 -0
- data/public/flot/examples/data-eu-gdp-growth-5.json +4 -0
- data/public/flot/examples/data-eu-gdp-growth.json +4 -0
- data/public/flot/examples/data-japan-gdp-growth.json +4 -0
- data/public/flot/examples/data-usa-gdp-growth.json +4 -0
- data/public/flot/examples/graph-types.html +75 -0
- data/public/flot/examples/hs-2004-27-a-large_web.jpg +0 -0
- data/public/flot/examples/image.html +45 -0
- data/public/flot/examples/index.html +44 -0
- data/public/flot/examples/interacting-axes.html +97 -0
- data/public/flot/examples/interacting.html +93 -0
- data/public/flot/examples/layout.css +6 -0
- data/public/flot/examples/multiple-axes.html +60 -0
- data/public/flot/examples/navigate.html +118 -0
- data/public/flot/examples/percentiles.html +57 -0
- data/public/flot/examples/pie.html +756 -0
- data/public/flot/examples/realtime.html +83 -0
- data/public/flot/examples/resize.html +61 -0
- data/public/flot/examples/selection.html +114 -0
- data/public/flot/examples/setting-options.html +61 -0
- data/public/flot/examples/stacking.html +77 -0
- data/public/flot/examples/symbols.html +49 -0
- data/public/flot/examples/thresholding.html +54 -0
- data/public/flot/examples/time.html +71 -0
- data/public/flot/examples/tracking.html +95 -0
- data/public/flot/examples/turning-series.html +98 -0
- data/public/flot/examples/visitors.html +90 -0
- data/public/flot/examples/zooming.html +98 -0
- data/public/flot/excanvas.js +1427 -0
- data/public/flot/excanvas.min.js +1 -0
- data/public/flot/jquery.colorhelpers.js +179 -0
- data/public/flot/jquery.colorhelpers.min.js +1 -0
- data/public/flot/jquery.flot.crosshair.js +167 -0
- data/public/flot/jquery.flot.crosshair.min.js +1 -0
- data/public/flot/jquery.flot.fillbetween.js +183 -0
- data/public/flot/jquery.flot.fillbetween.min.js +1 -0
- data/public/flot/jquery.flot.image.js +238 -0
- data/public/flot/jquery.flot.image.min.js +1 -0
- data/public/flot/jquery.flot.js +2599 -0
- data/public/flot/jquery.flot.min.js +6 -0
- data/public/flot/jquery.flot.navigate.js +336 -0
- data/public/flot/jquery.flot.navigate.min.js +1 -0
- data/public/flot/jquery.flot.pie.js +750 -0
- data/public/flot/jquery.flot.pie.min.js +1 -0
- data/public/flot/jquery.flot.resize.js +60 -0
- data/public/flot/jquery.flot.resize.min.js +1 -0
- data/public/flot/jquery.flot.selection.js +344 -0
- data/public/flot/jquery.flot.selection.min.js +1 -0
- data/public/flot/jquery.flot.stack.js +184 -0
- data/public/flot/jquery.flot.stack.min.js +1 -0
- data/public/flot/jquery.flot.symbol.js +70 -0
- data/public/flot/jquery.flot.symbol.min.js +1 -0
- data/public/flot/jquery.flot.threshold.js +103 -0
- data/public/flot/jquery.flot.threshold.min.js +1 -0
- data/public/flot/jquery.js +8316 -0
- data/public/flot/jquery.min.js +23 -0
- data/public/genPacking.pl +30 -0
- data/public/index.html +28 -0
- data/public/install.tpz +66 -0
- data/public/installAndRun.tpz +5 -0
- data/public/jsTree/jquery.jstree.js +3510 -0
- data/public/jsTree/themes/default/d.gif +0 -0
- data/public/jsTree/themes/default/d.png +0 -0
- data/public/jsTree/themes/default/style.css +73 -0
- data/public/jsTree/themes/default/throbber.gif +0 -0
- data/public/readMe.txt +9 -0
- data/public/scripts/CodeBrowser.js +645 -0
- data/public/scripts/Debugger.js +134 -0
- data/public/scripts/MethodList.js +72 -0
- data/public/scripts/ObjectLog.js +59 -0
- data/public/scripts/SessionList.js +164 -0
- data/public/scripts/Statistics.js +266 -0
- data/public/scripts/editor.js +430 -0
- data/public/scripts/jjmenu.js +375 -0
- data/public/scripts/jquery-ui.js +1012 -0
- data/public/scripts/jquery.js +154 -0
- data/public/scripts/webtools.js +374 -0
- data/public/src/CodeBrowser.gs +416 -0
- data/public/src/Debugger.gs +132 -0
- data/public/src/MethodList.gs +130 -0
- data/public/src/ObjectLog.gs +73 -0
- data/public/src/Server.gs +544 -0
- data/public/src/SessionList.gs +172 -0
- data/public/src/SharedPageCache.gs +66 -0
- data/public/src/StatProcess.gs +280 -0
- data/public/src/StatProcessType.gs +242 -0
- data/public/src/StatStatistic.gs +381 -0
- data/public/src/Statistics.gs +222 -0
- data/public/src/Statmonitor.gs +490 -0
- data/public/src/Tool.gs +86 -0
- data/public/src/VersionReport.gs +52 -0
- data/public/src/Workspace.gs +163 -0
- data/views/debugger.rhtml +6 -9
- metadata +344 -243
- data/lib/web_tools/#debugger.rb# +0 -212
- data/lib/web_tools/browser.rb +0 -45
- data/public/images/favicon.ico +0 -0
- data/public/javascript/CodeMirror/LICENSE +0 -23
- data/public/javascript/CodeMirror/css/Smalltalk.css +0 -34
- data/public/javascript/CodeMirror/js/codemirror.js +0 -582
- data/public/javascript/CodeMirror/js/editor.js +0 -1671
- data/public/javascript/CodeMirror/js/highlight.js +0 -68
- data/public/javascript/CodeMirror/js/parseSmalltalk.js +0 -126
- data/public/javascript/CodeMirror/js/parsedummy.js +0 -32
- data/public/javascript/CodeMirror/js/select.js +0 -699
- data/public/javascript/CodeMirror/js/stringstream.js +0 -159
- data/public/javascript/CodeMirror/js/tokenize.js +0 -57
- data/public/javascript/CodeMirror/js/undo.js +0 -413
- data/public/javascript/CodeMirror/js/util.js +0 -133
- data/public/javascript/CodeMirror/testSmalltalkParser.html +0 -116
- data/public/javascript/ace/ace-uncompressed.js +0 -17299
- data/public/javascript/ace/ace.js +0 -1
- data/public/javascript/ace/keybinding-emacs.js +0 -1
- data/public/javascript/ace/keybinding-vim.js +0 -1
- data/public/javascript/ace/mode-c_cpp.js +0 -1
- data/public/javascript/ace/mode-clojure.js +0 -1
- data/public/javascript/ace/mode-coffee.js +0 -1
- data/public/javascript/ace/mode-csharp.js +0 -1
- data/public/javascript/ace/mode-css.js +0 -1
- data/public/javascript/ace/mode-groovy.js +0 -1
- data/public/javascript/ace/mode-html.js +0 -1
- data/public/javascript/ace/mode-java.js +0 -1
- data/public/javascript/ace/mode-javascript.js +0 -1
- data/public/javascript/ace/mode-json.js +0 -1
- data/public/javascript/ace/mode-lua.js +0 -1
- data/public/javascript/ace/mode-markdown.js +0 -1
- data/public/javascript/ace/mode-ocaml.js +0 -1
- data/public/javascript/ace/mode-perl.js +0 -1
- data/public/javascript/ace/mode-php.js +0 -1
- data/public/javascript/ace/mode-python.js +0 -1
- data/public/javascript/ace/mode-ruby.js +0 -1
- data/public/javascript/ace/mode-scad.js +0 -1
- data/public/javascript/ace/mode-scala.js +0 -1
- data/public/javascript/ace/mode-scss.js +0 -1
- data/public/javascript/ace/mode-svg.js +0 -1
- data/public/javascript/ace/mode-textile.js +0 -1
- data/public/javascript/ace/mode-xml.js +0 -1
- data/public/javascript/ace/theme-clouds.js +0 -1
- data/public/javascript/ace/theme-clouds_midnight.js +0 -1
- data/public/javascript/ace/theme-cobalt.js +0 -1
- data/public/javascript/ace/theme-crimson_editor.js +0 -1
- data/public/javascript/ace/theme-dawn.js +0 -1
- data/public/javascript/ace/theme-eclipse.js +0 -1
- data/public/javascript/ace/theme-idle_fingers.js +0 -1
- data/public/javascript/ace/theme-kr_theme.js +0 -1
- data/public/javascript/ace/theme-merbivore.js +0 -1
- data/public/javascript/ace/theme-merbivore_soft.js +0 -1
- data/public/javascript/ace/theme-mono_industrial.js +0 -1
- data/public/javascript/ace/theme-monokai.js +0 -1
- data/public/javascript/ace/theme-pastel_on_dark.js +0 -1
- data/public/javascript/ace/theme-solarized_dark.js +0 -1
- data/public/javascript/ace/theme-solarized_light.js +0 -1
- data/public/javascript/ace/theme-textmate.js +0 -1
- data/public/javascript/ace/theme-twilight.js +0 -1
- data/public/javascript/ace/theme-vibrant_ink.js +0 -1
- data/public/javascript/ace/worker-coffee.js +0 -1
- data/public/javascript/ace/worker-css.js +0 -1
- data/public/javascript/ace/worker-javascript.js +0 -1
- data/public/javascript/webtools/browser.js +0 -260
- data/public/javascript/webtools/debugger.coffee +0 -286
- data/public/javascript/webtools/debugger.js +0 -366
- data/public/javascript/webtools/sessions.coffee +0 -17
- data/public/javascript/webtools/sessions.js +0 -27
- data/public/javascript/webtools/version.coffee +0 -14
- data/public/javascript/webtools/version.js +0 -20
- data/public/stylesheets/jquery.contextMenu.css +0 -62
- data/public/stylesheets/webtools.css +0 -53
- 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
|
|
4
|
-
|
|
5
|
-
|
|
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
|
-
|
|
8
|
-
detailed statistics about all processes
|
|
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
|
-
|
|
13
|
-
|
|
14
|
+
$ rvm use [maglev-head|rbx|jruby|ruby-head]
|
|
15
|
+
$ bundle install
|
|
14
16
|
|
|
15
|
-
|
|
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
|
|
35
|
-
click on a constant
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
|
|
50
|
-
class list, as do a number of classes/modules from ActiveModel and
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
data/lib/web_tools/debugger.rb
CHANGED
|
@@ -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
|
-
|
|
9
|
-
|
|
10
|
-
include WebTools::Support::ServiceHelper
|
|
11
|
-
use Rack::JSONP
|
|
3
|
+
class WebTools::Debugger < WebTools::Tool
|
|
4
|
+
dont_show!
|
|
12
5
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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
|
-
|
|
94
|
-
|
|
95
|
-
end
|
|
41
|
+
new_stack = @process.stack
|
|
42
|
+
frame = new_stack.first
|
|
96
43
|
|
|
97
|
-
|
|
98
|
-
|
|
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
|
-
|
|
102
|
-
|
|
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
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
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
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
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
|
-
|
|
192
|
-
|
|
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
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
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
|
-
|
|
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
|