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
|
@@ -1,109 +1,111 @@
|
|
|
1
1
|
require 'web_tools/support/ruby'
|
|
2
2
|
|
|
3
3
|
module WebTools
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
4
|
+
module Support
|
|
5
|
+
# The CodeBrowser is a ViewModel for MagLev code browsing. It keeps the
|
|
6
|
+
# entire state of the UI and returns structured data for use by a UI.
|
|
7
|
+
# For the first pass, we do not cache anything.
|
|
8
|
+
class CodeBrowser
|
|
9
|
+
def self.class_and_module_list
|
|
10
|
+
{ 'modules' => Ruby.class_and_module_names }
|
|
11
|
+
end
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
13
|
+
def select_module(module_name)
|
|
14
|
+
mod = Ruby.find_in_namespace(module_name)
|
|
15
|
+
methods = mod.instance_methods(false) +
|
|
16
|
+
mod.protected_instance_methods(false) +
|
|
17
|
+
mod.private_instance_methods(false)
|
|
18
|
+
{
|
|
19
|
+
:ancestors => mod.ancestors.reverse,
|
|
20
|
+
:constants => mod.constants.sort,
|
|
21
|
+
:instance_methods => methods.uniq.sort,
|
|
22
|
+
:module_methods => Ruby.module_fns_for(mod),
|
|
23
|
+
:selected_module => module_name,
|
|
24
|
+
}
|
|
25
|
+
end
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
27
|
+
def select_constant(module_name, const_name)
|
|
28
|
+
parent = Ruby.find_in_namespace module_name
|
|
29
|
+
{
|
|
30
|
+
:const_value => ObjectInfo.for(parent.const_get(const_name)),
|
|
31
|
+
:selected_constant => const_name,
|
|
32
|
+
:selected_module => module_name,
|
|
33
|
+
}
|
|
34
|
+
end
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
36
|
+
def select_method(module_name, method_name, is_instance_method)
|
|
37
|
+
mod = Ruby.find_in_namespace(module_name)
|
|
38
|
+
src, file, line = mod.method_source(method_name, is_instance_method)
|
|
39
|
+
{
|
|
40
|
+
:is_instance_method => is_instance_method,
|
|
41
|
+
:method_line_number => line,
|
|
42
|
+
:method_source => src,
|
|
43
|
+
:method_source_file => file,
|
|
44
|
+
:module_name => module_name,
|
|
45
|
+
:selected_method => method_name,
|
|
46
|
+
}
|
|
47
|
+
end
|
|
47
48
|
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
def object_info(object_id)
|
|
50
|
+
ObjectInfo.for(object_id)
|
|
51
|
+
end
|
|
50
52
|
end
|
|
51
|
-
end
|
|
52
53
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
54
|
+
class ObjectInfo
|
|
55
|
+
# Return a new ObjectInfo instance for the object with the given object
|
|
56
|
+
# id.
|
|
57
|
+
def self.for_id(object_id)
|
|
58
|
+
new(ObjectSpace._id2ref(object_id))
|
|
59
|
+
end
|
|
59
60
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
# Return a new ObjectInfo instance for the given object.
|
|
62
|
+
def self.for(object)
|
|
63
|
+
new(object)
|
|
64
|
+
end
|
|
64
65
|
|
|
65
|
-
|
|
66
|
+
attr_reader :info
|
|
66
67
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
68
|
+
def initialize(obj)
|
|
69
|
+
@info = { }
|
|
70
|
+
@info[:object_id] = obj.object_id
|
|
71
|
+
@info[:class] = obj.class.name
|
|
72
|
+
@info[:inspect] = obj.inspect
|
|
73
|
+
@info[:instance_variables] = []
|
|
74
|
+
@info[:enumerated] = []
|
|
75
|
+
@info[:enumerated_size] = obj.respond_to?(:size) ? obj.size : nil
|
|
75
76
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
77
|
+
obj.instance_variables.each do |iv|
|
|
78
|
+
val = obj.instance_variable_get(iv)
|
|
79
|
+
@info[:instance_variables] << [iv, val.inspect, val.object_id]
|
|
80
|
+
end
|
|
80
81
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
82
|
+
limit = 10
|
|
83
|
+
case obj
|
|
84
|
+
when Enumerable, Array
|
|
85
|
+
obj.each_with_index do |o,i|
|
|
86
|
+
if i > limit
|
|
87
|
+
@info[:enumerated] << '...'
|
|
88
|
+
break
|
|
89
|
+
else
|
|
90
|
+
@info[:enumerated] << o.inspect
|
|
91
|
+
end
|
|
90
92
|
end
|
|
91
|
-
end
|
|
92
93
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
94
|
+
when Hash
|
|
95
|
+
obj.each_with_index do |pair, idx|
|
|
96
|
+
if idx > limit
|
|
97
|
+
@info[:enumerated] << ['', '...']
|
|
98
|
+
break
|
|
99
|
+
end
|
|
100
|
+
@info[:enumerated] << [pair[0].to_s, pair[1].inspect]
|
|
98
101
|
end
|
|
99
|
-
@info[:enumerated] << [pair[0].to_s, pair[1].inspect]
|
|
100
102
|
end
|
|
101
|
-
end
|
|
102
103
|
|
|
103
|
-
|
|
104
|
+
end
|
|
104
105
|
|
|
105
|
-
|
|
106
|
-
|
|
106
|
+
def to_json(*args)
|
|
107
|
+
@info.to_json
|
|
108
|
+
end
|
|
107
109
|
end
|
|
108
110
|
end
|
|
109
111
|
end
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
# require 'maglev/objectlog'
|
|
2
|
+
|
|
3
|
+
module WebTools
|
|
4
|
+
module Support
|
|
5
|
+
module Debugger
|
|
6
|
+
ExceptionFrames = [:raise, :"signal:", :"signal", "_rubyReraise"]
|
|
7
|
+
RubyEnv = 1
|
|
8
|
+
|
|
9
|
+
extend self
|
|
10
|
+
|
|
11
|
+
##
|
|
12
|
+
# Return the ObjectLog wrapper module
|
|
13
|
+
def object_log
|
|
14
|
+
ObjectLog
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
##
|
|
18
|
+
# Saves an exception to the ObjectLog.
|
|
19
|
+
# This will abort the pending transaction.
|
|
20
|
+
def save_exception(exception)
|
|
21
|
+
if Maglev.needs_commit
|
|
22
|
+
warn("Saving exception to ObjectLog, discarding transaction")
|
|
23
|
+
end
|
|
24
|
+
Maglev.abort_transaction
|
|
25
|
+
DebuggerLogEntry.create_continuation_labeled(exception.message)
|
|
26
|
+
Maglev.commit_transaction
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
##
|
|
30
|
+
# Calls the passed block in a new Thread.
|
|
31
|
+
#
|
|
32
|
+
# If the argument is true, any exception will be saved to the
|
|
33
|
+
# ObjectLog and re-raised. If the argument is false (default),
|
|
34
|
+
# any exception will wake the parent and suspend the failed thread
|
|
35
|
+
# for inspection.
|
|
36
|
+
# => the suspended thread and the exception that stopped it, if any
|
|
37
|
+
# => result of the passed block, if the thread finished
|
|
38
|
+
# => raises Exception, if any
|
|
39
|
+
def debug(reraise = false, &block)
|
|
40
|
+
raise ArgumentError, "must supply a block to debug" unless block
|
|
41
|
+
|
|
42
|
+
client = Thread.start(Thread.current, block) do |parent_thread, blk|
|
|
43
|
+
Thread.pass
|
|
44
|
+
begin
|
|
45
|
+
Thread.current[:result] = blk.call
|
|
46
|
+
rescue Exception => e
|
|
47
|
+
if reraise
|
|
48
|
+
save_exception(e.message)
|
|
49
|
+
raise e
|
|
50
|
+
else
|
|
51
|
+
result = Process.new(Thread.current)
|
|
52
|
+
result.exception = e
|
|
53
|
+
Thread.current[:result] = result
|
|
54
|
+
parent_thread.wakeup
|
|
55
|
+
Thread.stop
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
client.join # raises exception if client aborted
|
|
60
|
+
if (result = client[:result]).is_a? Process
|
|
61
|
+
result.pop_exception_handling_frames
|
|
62
|
+
end
|
|
63
|
+
result
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
class Wrapper; end
|
|
67
|
+
|
|
68
|
+
class Process < Wrapper
|
|
69
|
+
attr_accessor :thread, :exception, :timestamp, :label
|
|
70
|
+
|
|
71
|
+
def self.new(thread)
|
|
72
|
+
if thread.is_a? ObjectLogEntry
|
|
73
|
+
return ObjectLogError.new(thread) unless self == ObjectLogError
|
|
74
|
+
end
|
|
75
|
+
super(thread)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def initialize(thread)
|
|
79
|
+
@label = thread.inspect
|
|
80
|
+
@thread = thread
|
|
81
|
+
@timestamp = Time.now
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Kill process, remove entry from ObjectLog
|
|
85
|
+
def delete
|
|
86
|
+
@thread.exit
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def ruby_frames
|
|
90
|
+
frames.select do |frame|
|
|
91
|
+
frame.gsmethod.__env_id == RubyEnv
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def frames
|
|
96
|
+
methods = []
|
|
97
|
+
@thread.__stack_depth.times do |idx|
|
|
98
|
+
methods << [@thread.__method_at(idx + 1), idx + 1]
|
|
99
|
+
end
|
|
100
|
+
methods.collect do |method, idx|
|
|
101
|
+
Frame.new(:method => method, :index => idx, :thread => thread)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
##
|
|
106
|
+
# Searches method frames included in ExceptionFrames from the top
|
|
107
|
+
# of the stack, and resets the stack to the last ruby frame before
|
|
108
|
+
# that. If no useable frame is found, the stack is not modified.
|
|
109
|
+
def pop_exception_handling_frames
|
|
110
|
+
m = @thread.__method_at(i = 1)
|
|
111
|
+
until ExceptionFrames.include?(m.__name) or i >= @thread.__stack_depth
|
|
112
|
+
i += 1
|
|
113
|
+
m = @thread.__method_at(i)
|
|
114
|
+
end
|
|
115
|
+
if i < @thread.__stack_depth
|
|
116
|
+
until m.__env_id == RubyEnv or i >= @thread.__stack_depth
|
|
117
|
+
i += 1
|
|
118
|
+
m = @thread.__method_at(i)
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
@thread.__trim_stack_to_level(i) unless i >= @thread.__stack_depth
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def [](key)
|
|
125
|
+
@thread[key]
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def []=(key, value)
|
|
129
|
+
@thread[key] = value
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def to_hash
|
|
133
|
+
{ :label => label,
|
|
134
|
+
:process_id => thread.object_id,
|
|
135
|
+
:timestamp => timestamp }
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
class ObjectLogError < Process
|
|
140
|
+
def initialize(error)
|
|
141
|
+
super(error)
|
|
142
|
+
@log_entry = error
|
|
143
|
+
@label = error.label
|
|
144
|
+
@timestamp = error.timestamp
|
|
145
|
+
@thread = error.continuation
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def delete
|
|
149
|
+
if Maglev::System.needs_commit
|
|
150
|
+
raise Exception, "Abort would loose data. Commit your data and try again"
|
|
151
|
+
end
|
|
152
|
+
Maglev.abort_transaction
|
|
153
|
+
ObjectLogEntry.object_log.delete(@log_entry)
|
|
154
|
+
Maglev.commit_transaction
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
class Frame < Wrapper
|
|
159
|
+
attr_reader :debug_info, :gsmethod, :index, :thread,
|
|
160
|
+
:method_name, :defining_class, :block_nesting
|
|
161
|
+
|
|
162
|
+
def initialize(params)
|
|
163
|
+
@gsmethod = params[:method]
|
|
164
|
+
@thread = params[:thread]
|
|
165
|
+
@index = params[:index]
|
|
166
|
+
initialize_frame_info
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Pop frame off the stack, effectively restarting it
|
|
170
|
+
def delete
|
|
171
|
+
@thread.__trim_stack_to_level(@index)
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Step. The manner of stepping defaults to :over, but :into or the
|
|
175
|
+
# number of steps can be passed as arguments
|
|
176
|
+
def step(symbol = :over)
|
|
177
|
+
raise RuntimeError, "can only step top frame" unless @index === 1
|
|
178
|
+
case symbol
|
|
179
|
+
when :into
|
|
180
|
+
@thread.__step_over_in_frame(0)
|
|
181
|
+
when :over
|
|
182
|
+
@thread.__step_over_in_frame(1)
|
|
183
|
+
when Fixnum
|
|
184
|
+
@thread.__step_over_in_frame(arg)
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def context_eval(str)
|
|
189
|
+
context_object.instance_eval(str)
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def context_object
|
|
193
|
+
@context ||= Context.create_for(self,
|
|
194
|
+
debug_info![:self],
|
|
195
|
+
debug_info![:context])
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def initialize_frame_info
|
|
199
|
+
label = @gsmethod.__name
|
|
200
|
+
@block_nesting = 0
|
|
201
|
+
m = @gsmethod
|
|
202
|
+
while label.nil?
|
|
203
|
+
m = m.__home_method
|
|
204
|
+
label = m.__name
|
|
205
|
+
@block_nesting += 1
|
|
206
|
+
end
|
|
207
|
+
@defining_class = m.__in_class
|
|
208
|
+
@class = @gsmethod.__in_class
|
|
209
|
+
@method_name = label
|
|
210
|
+
if @gsmethod.__source_location
|
|
211
|
+
@source_location = @gsmethod.__source_location.join(":")
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def debug_info!
|
|
216
|
+
@debug_info ||=
|
|
217
|
+
begin
|
|
218
|
+
ary = @thread.__gsi_debugger_detailed_report_at(@index)
|
|
219
|
+
context = {}
|
|
220
|
+
# First the named temps, matched to values
|
|
221
|
+
ary[6].each_with_index {|name,idx| context[name] = ary[7][idx] }
|
|
222
|
+
# Then the remaining scope values with temporary names
|
|
223
|
+
ary[7][ary[6].size..-1].each_with_index {|v,i| context[:'t#{i}'] = v}
|
|
224
|
+
context[:'(receiver)'] = ary[1]
|
|
225
|
+
context[:'(class)'] = ary[1].class
|
|
226
|
+
context[:'(self)'] = ary[2]
|
|
227
|
+
{ :gsMethod => ary[0],
|
|
228
|
+
:receiver => ary[1],
|
|
229
|
+
:self => ary[2],
|
|
230
|
+
:method => ary[3],
|
|
231
|
+
:stepOffset => ary[4],
|
|
232
|
+
:stepPoints => ary[5],
|
|
233
|
+
:source => ary[8],
|
|
234
|
+
:context => context }
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
def to_hash
|
|
239
|
+
{ :method_name => @method_name,
|
|
240
|
+
:class => @class,
|
|
241
|
+
:index => @index,
|
|
242
|
+
:defining_class => @defining_class,
|
|
243
|
+
:source_location => @source_location,
|
|
244
|
+
:block_nesting => @block_nesting,
|
|
245
|
+
:debug_info => @debug_info }
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
# Emulates the context of a frame execution
|
|
249
|
+
# Defines accessors to the frame locals and sets the instance variables to
|
|
250
|
+
# point to the original object's values
|
|
251
|
+
class Context
|
|
252
|
+
# Tries to create a duplicate of the receiver. If that is not possible,
|
|
253
|
+
# creates a new instance of self. In any case, a singleton class is added
|
|
254
|
+
# to define accessors to frame local values
|
|
255
|
+
def self.create_for(frame, receiver, context_hash)
|
|
256
|
+
rcv = nil
|
|
257
|
+
begin
|
|
258
|
+
rcv = receiver.dup
|
|
259
|
+
rescue Exception
|
|
260
|
+
end
|
|
261
|
+
if receiver === rcv || rcv.nil?
|
|
262
|
+
rcv = self.new(receiver)
|
|
263
|
+
|
|
264
|
+
receiver.instance_variables do |name|
|
|
265
|
+
rcv.instance_variable_set(name, receiver.instance_variable_get(name))
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
receiver_mod = (receiver.is_a?(Module) ? receiver : receiver.class)
|
|
269
|
+
receiver_mod.constants do |sym|
|
|
270
|
+
rcv.singleton_class.const_set(sym, receiver_mod.const_get(sym))
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
context_hash.each do |k,v|
|
|
275
|
+
next if [:"(self)", :"(class)", :"(receiver)"].include? k
|
|
276
|
+
rcv.singleton_class.define_method(:"#{k}") { v }
|
|
277
|
+
rcv.singleton_class.define_method(:"#{k}=") do |v|
|
|
278
|
+
frame.thread.__frame_at_temp_named_put(frame.index, k, v)
|
|
279
|
+
end
|
|
280
|
+
end
|
|
281
|
+
rcv
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
def initialize(rcv)
|
|
285
|
+
@receiver = rcv
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
def myself
|
|
289
|
+
@receiver
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
def respond_to?(method)
|
|
293
|
+
@receiver.respond_to? method
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
def method_missing(method, *args, &block)
|
|
297
|
+
@receiver.send(method, *args, &block)
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
end
|
|
301
|
+
end
|
|
302
|
+
end
|
|
303
|
+
end
|