maglev-webtools 0.2.1 → 1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|