binding_of_caller 0.6.8 → 0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.travis.yml +1 -2
- data/Rakefile +26 -17
- data/binding_of_caller.gemspec +8 -5
- data/ext/binding_of_caller/binding_of_caller.c +3 -2
- data/ext/binding_of_caller/extconf.rb +12 -3
- data/lib/binding_of_caller.rb +9 -80
- data/lib/binding_of_caller/mri2.rb +68 -0
- data/lib/binding_of_caller/rubinius.rb +77 -0
- data/lib/binding_of_caller/version.rb +1 -1
- data/test/test_binding_of_caller.rb +33 -0
- metadata +37 -17
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f04635fb28639852333bfbee1550220af00a4028
|
4
|
+
data.tar.gz: 5badb7913920490c656b9474ce86f7cc4a942b16
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e2fac2a7efe9388ba217124dd615d66b4b4732faad53f8211543047315acb0ebea803f9d31d842c990ef34f80fba6792a1f2ae6ab04c78d7cf496f5923c2ed34
|
7
|
+
data.tar.gz: 500c220951bb64eb5597b4e5beae0dc1ba5a01e3cd9818012845f313740a5d80f631b0b3b36832ab437c5a856af5cd8b21ae4945c100389778bed2cacc7e24ec
|
data/.travis.yml
CHANGED
data/Rakefile
CHANGED
@@ -3,20 +3,23 @@ direc = File.dirname(__FILE__)
|
|
3
3
|
|
4
4
|
$:.unshift 'lib'
|
5
5
|
|
6
|
-
PROJECT_NAME = "binding_of_caller"
|
7
|
-
|
8
6
|
require 'rake/clean'
|
9
7
|
require 'rubygems/package_task'
|
10
8
|
|
11
|
-
require "
|
9
|
+
require "binding_of_caller/version"
|
12
10
|
|
13
11
|
CLOBBER.include("**/*.#{dlext}", "**/*~", "**/*#*", "**/*.log", "**/*.o")
|
14
12
|
CLEAN.include("ext/**/*.#{dlext}", "ext/**/*.log", "ext/**/*.o",
|
15
13
|
"ext/**/*~", "ext/**/*#*", "ext/**/*.obj", "**/*#*", "**/*#*.*",
|
16
14
|
"ext/**/*.def", "ext/**/*.pdb", "**/*_flymake*.*", "**/*_flymake", "**/*.rbc")
|
17
15
|
|
16
|
+
def mri_2?
|
17
|
+
defined?(RUBY_ENGINE) && RUBY_ENGINE == "ruby" &&
|
18
|
+
RUBY_VERSION =~ /^2/
|
19
|
+
end
|
20
|
+
|
18
21
|
def apply_spec_defaults(s)
|
19
|
-
s.name =
|
22
|
+
s.name = "binding_of_caller"
|
20
23
|
s.summary = "Retrieve the binding of a method's caller. Can also retrieve bindings even further up the stack."
|
21
24
|
s.version = BindingOfCaller::VERSION
|
22
25
|
s.date = Time.now.strftime '%Y-%m-%d'
|
@@ -24,8 +27,9 @@ def apply_spec_defaults(s)
|
|
24
27
|
s.email = 'jrmair@gmail.com'
|
25
28
|
s.description = s.summary
|
26
29
|
s.require_path = 'lib'
|
27
|
-
s.
|
28
|
-
s.add_development_dependency
|
30
|
+
s.add_dependency 'debug_inspector', '>= 0.0.1'
|
31
|
+
s.add_development_dependency 'bacon'
|
32
|
+
s.add_development_dependency 'rake'
|
29
33
|
s.homepage = "http://github.com/banister/binding_of_caller"
|
30
34
|
s.has_rdoc = 'yard'
|
31
35
|
s.files = `git ls-files`.split("\n")
|
@@ -67,7 +71,7 @@ namespace :ruby do
|
|
67
71
|
spec = Gem::Specification.new do |s|
|
68
72
|
apply_spec_defaults(s)
|
69
73
|
s.platform = Gem::Platform::RUBY
|
70
|
-
s.extensions = ["ext
|
74
|
+
s.extensions = ["ext/binding_of_caller/extconf.rb"]
|
71
75
|
end
|
72
76
|
|
73
77
|
Gem::PackageTask.new(spec) do |pkg|
|
@@ -84,29 +88,34 @@ namespace :ruby do
|
|
84
88
|
end
|
85
89
|
|
86
90
|
desc "build the binaries"
|
87
|
-
task :compile do
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
91
|
+
task :compile => :cleanup do
|
92
|
+
if !mri_2?
|
93
|
+
chdir "./ext/binding_of_caller/" do
|
94
|
+
sh "ruby extconf.rb"
|
95
|
+
sh "make"
|
96
|
+
sh "cp *.#{dlext} ../../lib/"
|
97
|
+
end
|
93
98
|
end
|
94
99
|
end
|
95
100
|
|
96
101
|
desc 'cleanup the extensions'
|
97
102
|
task :cleanup do
|
98
|
-
|
99
|
-
|
100
|
-
|
103
|
+
if !mri_2?
|
104
|
+
sh 'rm -rf lib/binding_of_caller.so'
|
105
|
+
chdir "./ext/binding_of_caller/" do
|
106
|
+
sh 'make clean'
|
107
|
+
end
|
101
108
|
end
|
102
109
|
end
|
103
110
|
|
104
111
|
desc "reinstall gem"
|
105
112
|
task :reinstall => :gems do
|
106
113
|
sh "gem uninstall binding_of_caller" rescue nil
|
107
|
-
sh "gem install #{direc}/pkg
|
114
|
+
sh "gem install #{direc}/pkg/binding_of_caller-#{BindingOfCaller::VERSION}.gem"
|
108
115
|
end
|
109
116
|
|
117
|
+
task :install => :reinstall
|
118
|
+
|
110
119
|
desc "build all platform gems at once"
|
111
120
|
task :gems => [:clean, :rmgems, "ruby:gem"]
|
112
121
|
|
data/binding_of_caller.gemspec
CHANGED
@@ -2,32 +2,35 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = "binding_of_caller"
|
5
|
-
s.version = "0.6.
|
5
|
+
s.version = "0.6.9"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["John Mair (banisterfiend)"]
|
9
|
-
s.date = "
|
9
|
+
s.date = "2013-02-14"
|
10
10
|
s.description = "Retrieve the binding of a method's caller. Can also retrieve bindings even further up the stack."
|
11
11
|
s.email = "jrmair@gmail.com"
|
12
12
|
s.extensions = ["ext/binding_of_caller/extconf.rb"]
|
13
|
-
s.files = [".gemtest", ".gitignore", ".travis.yml", ".yardopts", "Gemfile", "HISTORY", "LICENSE", "README.md", "Rakefile", "binding_of_caller.gemspec", "examples/example.rb", "ext/binding_of_caller/binding_of_caller.c", "ext/binding_of_caller/extconf.rb", "ext/binding_of_caller/ruby_headers/192/debug.h", "ext/binding_of_caller/ruby_headers/192/dln.h", "ext/binding_of_caller/ruby_headers/192/eval_intern.h", "ext/binding_of_caller/ruby_headers/192/gc.h", "ext/binding_of_caller/ruby_headers/192/id.h", "ext/binding_of_caller/ruby_headers/192/iseq.h", "ext/binding_of_caller/ruby_headers/192/method.h", "ext/binding_of_caller/ruby_headers/192/node.h", "ext/binding_of_caller/ruby_headers/192/regenc.h", "ext/binding_of_caller/ruby_headers/192/regint.h", "ext/binding_of_caller/ruby_headers/192/regparse.h", "ext/binding_of_caller/ruby_headers/192/thread_pthread.h", "ext/binding_of_caller/ruby_headers/192/thread_win32.h", "ext/binding_of_caller/ruby_headers/192/timev.h", "ext/binding_of_caller/ruby_headers/192/transcode_data.h", "ext/binding_of_caller/ruby_headers/192/version.h", "ext/binding_of_caller/ruby_headers/192/vm_core.h", "ext/binding_of_caller/ruby_headers/192/vm_exec.h", "ext/binding_of_caller/ruby_headers/192/vm_insnhelper.h", "ext/binding_of_caller/ruby_headers/192/vm_opts.h", "ext/binding_of_caller/ruby_headers/193/addr2line.h", "ext/binding_of_caller/ruby_headers/193/atomic.h", "ext/binding_of_caller/ruby_headers/193/constant.h", "ext/binding_of_caller/ruby_headers/193/debug.h", "ext/binding_of_caller/ruby_headers/193/dln.h", "ext/binding_of_caller/ruby_headers/193/encdb.h", "ext/binding_of_caller/ruby_headers/193/eval_intern.h", "ext/binding_of_caller/ruby_headers/193/gc.h", "ext/binding_of_caller/ruby_headers/193/id.h", "ext/binding_of_caller/ruby_headers/193/internal.h", "ext/binding_of_caller/ruby_headers/193/iseq.h", "ext/binding_of_caller/ruby_headers/193/method.h", "ext/binding_of_caller/ruby_headers/193/node.h", "ext/binding_of_caller/ruby_headers/193/parse.h", "ext/binding_of_caller/ruby_headers/193/regenc.h", "ext/binding_of_caller/ruby_headers/193/regint.h", "ext/binding_of_caller/ruby_headers/193/regparse.h", "ext/binding_of_caller/ruby_headers/193/revision.h", "ext/binding_of_caller/ruby_headers/193/thread_pthread.h", "ext/binding_of_caller/ruby_headers/193/thread_win32.h", "ext/binding_of_caller/ruby_headers/193/timev.h", "ext/binding_of_caller/ruby_headers/193/transcode_data.h", "ext/binding_of_caller/ruby_headers/193/transdb.h", "ext/binding_of_caller/ruby_headers/193/version.h", "ext/binding_of_caller/ruby_headers/193/vm_core.h", "ext/binding_of_caller/ruby_headers/193/vm_exec.h", "ext/binding_of_caller/ruby_headers/193/vm_insnhelper.h", "ext/binding_of_caller/ruby_headers/193/vm_opts.h", "lib/binding_of_caller.rb", "lib/binding_of_caller/version.rb", "test/test_binding_of_caller.rb"]
|
13
|
+
s.files = [".gemtest", ".gitignore", ".travis.yml", ".yardopts", "Gemfile", "HISTORY", "LICENSE", "README.md", "Rakefile", "binding_of_caller.gemspec", "examples/example.rb", "ext/binding_of_caller/binding_of_caller.c", "ext/binding_of_caller/extconf.rb", "ext/binding_of_caller/ruby_headers/192/debug.h", "ext/binding_of_caller/ruby_headers/192/dln.h", "ext/binding_of_caller/ruby_headers/192/eval_intern.h", "ext/binding_of_caller/ruby_headers/192/gc.h", "ext/binding_of_caller/ruby_headers/192/id.h", "ext/binding_of_caller/ruby_headers/192/iseq.h", "ext/binding_of_caller/ruby_headers/192/method.h", "ext/binding_of_caller/ruby_headers/192/node.h", "ext/binding_of_caller/ruby_headers/192/regenc.h", "ext/binding_of_caller/ruby_headers/192/regint.h", "ext/binding_of_caller/ruby_headers/192/regparse.h", "ext/binding_of_caller/ruby_headers/192/thread_pthread.h", "ext/binding_of_caller/ruby_headers/192/thread_win32.h", "ext/binding_of_caller/ruby_headers/192/timev.h", "ext/binding_of_caller/ruby_headers/192/transcode_data.h", "ext/binding_of_caller/ruby_headers/192/version.h", "ext/binding_of_caller/ruby_headers/192/vm_core.h", "ext/binding_of_caller/ruby_headers/192/vm_exec.h", "ext/binding_of_caller/ruby_headers/192/vm_insnhelper.h", "ext/binding_of_caller/ruby_headers/192/vm_opts.h", "ext/binding_of_caller/ruby_headers/193/addr2line.h", "ext/binding_of_caller/ruby_headers/193/atomic.h", "ext/binding_of_caller/ruby_headers/193/constant.h", "ext/binding_of_caller/ruby_headers/193/debug.h", "ext/binding_of_caller/ruby_headers/193/dln.h", "ext/binding_of_caller/ruby_headers/193/encdb.h", "ext/binding_of_caller/ruby_headers/193/eval_intern.h", "ext/binding_of_caller/ruby_headers/193/gc.h", "ext/binding_of_caller/ruby_headers/193/id.h", "ext/binding_of_caller/ruby_headers/193/internal.h", "ext/binding_of_caller/ruby_headers/193/iseq.h", "ext/binding_of_caller/ruby_headers/193/method.h", "ext/binding_of_caller/ruby_headers/193/node.h", "ext/binding_of_caller/ruby_headers/193/parse.h", "ext/binding_of_caller/ruby_headers/193/regenc.h", "ext/binding_of_caller/ruby_headers/193/regint.h", "ext/binding_of_caller/ruby_headers/193/regparse.h", "ext/binding_of_caller/ruby_headers/193/revision.h", "ext/binding_of_caller/ruby_headers/193/thread_pthread.h", "ext/binding_of_caller/ruby_headers/193/thread_win32.h", "ext/binding_of_caller/ruby_headers/193/timev.h", "ext/binding_of_caller/ruby_headers/193/transcode_data.h", "ext/binding_of_caller/ruby_headers/193/transdb.h", "ext/binding_of_caller/ruby_headers/193/version.h", "ext/binding_of_caller/ruby_headers/193/vm_core.h", "ext/binding_of_caller/ruby_headers/193/vm_exec.h", "ext/binding_of_caller/ruby_headers/193/vm_insnhelper.h", "ext/binding_of_caller/ruby_headers/193/vm_opts.h", "lib/binding_of_caller.rb", "lib/binding_of_caller/mri2.rb", "lib/binding_of_caller/rubinius.rb", "lib/binding_of_caller/version.rb", "test/test_binding_of_caller.rb"]
|
14
14
|
s.homepage = "http://github.com/banister/binding_of_caller"
|
15
15
|
s.require_paths = ["lib"]
|
16
|
-
s.rubygems_version = "
|
16
|
+
s.rubygems_version = "2.0.0.rc.2"
|
17
17
|
s.summary = "Retrieve the binding of a method's caller. Can also retrieve bindings even further up the stack."
|
18
18
|
s.test_files = ["test/test_binding_of_caller.rb"]
|
19
19
|
|
20
20
|
if s.respond_to? :specification_version then
|
21
|
-
s.specification_version =
|
21
|
+
s.specification_version = 4
|
22
22
|
|
23
23
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
24
|
+
s.add_runtime_dependency(%q<debug_inspector>, [">= 0.0.1"])
|
24
25
|
s.add_development_dependency(%q<bacon>, [">= 0"])
|
25
26
|
s.add_development_dependency(%q<rake>, [">= 0"])
|
26
27
|
else
|
28
|
+
s.add_dependency(%q<debug_inspector>, [">= 0.0.1"])
|
27
29
|
s.add_dependency(%q<bacon>, [">= 0"])
|
28
30
|
s.add_dependency(%q<rake>, [">= 0"])
|
29
31
|
end
|
30
32
|
else
|
33
|
+
s.add_dependency(%q<debug_inspector>, [">= 0.0.1"])
|
31
34
|
s.add_dependency(%q<bacon>, [">= 0"])
|
32
35
|
s.add_dependency(%q<rake>, [">= 0"])
|
33
36
|
end
|
@@ -24,6 +24,7 @@ threadptr_data_type(void)
|
|
24
24
|
}
|
25
25
|
|
26
26
|
#define ruby_thread_data_type *threadptr_data_type()
|
27
|
+
#define ruby_threadptr_data_type *threadptr_data_type()
|
27
28
|
|
28
29
|
#define ruby_current_thread ((rb_thread_t *)RTYPEDDATA_DATA(rb_thread_current()))
|
29
30
|
|
@@ -109,7 +110,6 @@ frametype_name(VALUE flag)
|
|
109
110
|
case VM_FRAME_MAGIC_BLOCK: return string2sym("block");
|
110
111
|
case VM_FRAME_MAGIC_CLASS: return string2sym("class");
|
111
112
|
case VM_FRAME_MAGIC_TOP: return string2sym("top");
|
112
|
-
case VM_FRAME_MAGIC_FINISH: return string2sym("finish");
|
113
113
|
case VM_FRAME_MAGIC_CFUNC: return string2sym("cfunc");
|
114
114
|
case VM_FRAME_MAGIC_PROC: return string2sym("proc");
|
115
115
|
case VM_FRAME_MAGIC_IFUNC: return string2sym("ifunc");
|
@@ -148,10 +148,11 @@ static VALUE binding_of_caller(VALUE self, VALUE rb_level)
|
|
148
148
|
rb_raise(rb_eRuntimeError, "Can't create Binding Object on top of Fiber.");
|
149
149
|
|
150
150
|
GetBindingPtr(bindval, bind);
|
151
|
+
|
151
152
|
bind->env = rb_vm_make_env_object(th, cfp);
|
152
153
|
bind->filename = cfp->iseq->filename;
|
153
154
|
bind->line_no = rb_vm_get_sourceline(cfp);
|
154
|
-
|
155
|
+
|
155
156
|
rb_iv_set(bindval, "@frame_type", frametype_name(cfp->flag));
|
156
157
|
rb_iv_set(bindval, "@frame_description", cfp->iseq->name);
|
157
158
|
|
@@ -1,10 +1,19 @@
|
|
1
1
|
def fake_makefile
|
2
|
-
File.open(File.join(File.dirname(__FILE__), "Makefile"), "w")
|
2
|
+
File.open(File.join(File.dirname(__FILE__), "Makefile"), "w") do |f|
|
3
3
|
f.puts %[install:\n\techo "Nada."]
|
4
|
-
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
def mri_2?
|
8
|
+
defined?(RUBY_ENGINE) && RUBY_ENGINE == "ruby" &&
|
9
|
+
RUBY_VERSION =~ /^2/
|
10
|
+
end
|
11
|
+
|
12
|
+
def rbx?
|
13
|
+
defined?(RUBY_ENGINE) && RUBY_ENGINE =~ /rbx/
|
5
14
|
end
|
6
15
|
|
7
|
-
if
|
16
|
+
if mri_2? || rbx?
|
8
17
|
fake_makefile
|
9
18
|
else
|
10
19
|
require 'mkmf'
|
data/lib/binding_of_caller.rb
CHANGED
@@ -1,85 +1,14 @@
|
|
1
1
|
dlext = RbConfig::CONFIG['DLEXT']
|
2
|
-
direc = File.dirname(__FILE__)
|
3
2
|
|
4
|
-
|
5
|
-
|
3
|
+
def mri_2?
|
4
|
+
defined?(RUBY_ENGINE) && RUBY_ENGINE == "ruby" &&
|
5
|
+
RUBY_VERSION =~ /^2/
|
6
|
+
end
|
6
7
|
|
8
|
+
if mri_2?
|
9
|
+
require 'binding_of_caller/mri2'
|
10
|
+
elsif defined?(RUBY_ENGINE) && RUBY_ENGINE == "ruby"
|
11
|
+
require "binding_of_caller.#{dlext}"
|
7
12
|
elsif defined?(Rubinius)
|
8
|
-
|
9
|
-
module BindingExtensions
|
10
|
-
|
11
|
-
# Retrieve the binding of the nth caller of the current frame.
|
12
|
-
# @return [Binding]
|
13
|
-
def of_caller(n)
|
14
|
-
bt = Rubinius::VM.backtrace(1 + n, true).first
|
15
|
-
|
16
|
-
b = Binding.setup(
|
17
|
-
bt.variables,
|
18
|
-
bt.variables.method,
|
19
|
-
bt.static_scope,
|
20
|
-
bt.variables.self,
|
21
|
-
bt
|
22
|
-
)
|
23
|
-
|
24
|
-
b.instance_variable_set(:@frame_description, bt.describe)
|
25
|
-
|
26
|
-
b
|
27
|
-
rescue
|
28
|
-
raise RuntimeError, "Invalid frame, gone beyond end of stack!"
|
29
|
-
end
|
30
|
-
|
31
|
-
# The description of the frame.
|
32
|
-
# @return [String]
|
33
|
-
def frame_description
|
34
|
-
@frame_description
|
35
|
-
end
|
36
|
-
|
37
|
-
# Return bindings for all caller frames.
|
38
|
-
# @return [Array<Binding>]
|
39
|
-
def callers
|
40
|
-
ary = []
|
41
|
-
n = 0
|
42
|
-
loop do
|
43
|
-
begin
|
44
|
-
ary << Binding.of_caller(n)
|
45
|
-
rescue
|
46
|
-
break
|
47
|
-
end
|
48
|
-
n += 1
|
49
|
-
end
|
50
|
-
ary.drop_while do |v|
|
51
|
-
!(v.frame_type == :method && v.eval("__method__") == :callers)
|
52
|
-
end.drop(1)
|
53
|
-
end
|
54
|
-
|
55
|
-
# Number of parent frames available at the point of call.
|
56
|
-
# @return [Fixnum]
|
57
|
-
def frame_count
|
58
|
-
callers.size - 1
|
59
|
-
end
|
60
|
-
|
61
|
-
# The type of the frame.
|
62
|
-
# @return [Symbol]
|
63
|
-
def frame_type
|
64
|
-
case self.variables.method.metadata.to_a.first.to_s
|
65
|
-
when /block/
|
66
|
-
:block
|
67
|
-
when /eval/
|
68
|
-
:eval
|
69
|
-
else
|
70
|
-
if frame_description =~ /__(?:class|module)_init__/
|
71
|
-
:class
|
72
|
-
else
|
73
|
-
:method
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
class ::Binding
|
82
|
-
include BindingOfCaller::BindingExtensions
|
83
|
-
extend BindingOfCaller::BindingExtensions
|
84
|
-
end
|
13
|
+
require 'binding_of_caller/rubinius'
|
85
14
|
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'debug_inspector'
|
2
|
+
|
3
|
+
module BindingOfCaller
|
4
|
+
module BindingExtensions
|
5
|
+
# Retrieve the binding of the nth caller of the current frame.
|
6
|
+
# @return [Binding]
|
7
|
+
def of_caller(n)
|
8
|
+
c = callers.drop(1)
|
9
|
+
if n > (c.size - 1)
|
10
|
+
raise "No such frame, gone beyond end of stack!"
|
11
|
+
else
|
12
|
+
c[n]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# The description of the frame.
|
17
|
+
# @return [String]
|
18
|
+
def frame_description
|
19
|
+
@frame_description ||= @iseq.label
|
20
|
+
end
|
21
|
+
|
22
|
+
# Return bindings for all caller frames.
|
23
|
+
# @return [Array<Binding>]
|
24
|
+
def callers
|
25
|
+
ary = []
|
26
|
+
|
27
|
+
RubyVM::DebugInspector.open do |i|
|
28
|
+
n = 0
|
29
|
+
loop do
|
30
|
+
begin
|
31
|
+
b = i.frame_binding(n)
|
32
|
+
|
33
|
+
if b
|
34
|
+
iseq = i.frame_iseq(n)
|
35
|
+
b.instance_variable_set(:@iseq, iseq)
|
36
|
+
ary << b
|
37
|
+
end
|
38
|
+
rescue ArgumentError
|
39
|
+
break
|
40
|
+
end
|
41
|
+
n += 1
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
ary.drop(1)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Number of parent frames available at the point of call.
|
49
|
+
# @return [Fixnum]
|
50
|
+
def frame_count
|
51
|
+
callers.size - 1
|
52
|
+
end
|
53
|
+
|
54
|
+
# The type of the frame.
|
55
|
+
# @return [Symbol]
|
56
|
+
def frame_type
|
57
|
+
# apparently the 9th element of the iseq array holds the frame type
|
58
|
+
# ...not sure how reliable this is.
|
59
|
+
@frame_type ||= @iseq.to_a[9]
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
class ::Binding
|
67
|
+
include BindingOfCaller::BindingExtensions
|
68
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module BindingOfCaller
|
2
|
+
module BindingExtensions
|
3
|
+
|
4
|
+
# Retrieve the binding of the nth caller of the current frame.
|
5
|
+
# @return [Binding]
|
6
|
+
def of_caller(n)
|
7
|
+
bt = Rubinius::VM.backtrace(1 + n, true).first
|
8
|
+
|
9
|
+
b = Binding.setup(
|
10
|
+
bt.variables,
|
11
|
+
bt.variables.method,
|
12
|
+
bt.static_scope,
|
13
|
+
bt.variables.self,
|
14
|
+
bt
|
15
|
+
)
|
16
|
+
|
17
|
+
b.instance_variable_set(:@frame_description, bt.describe)
|
18
|
+
|
19
|
+
b
|
20
|
+
rescue
|
21
|
+
raise RuntimeError, "Invalid frame, gone beyond end of stack!"
|
22
|
+
end
|
23
|
+
|
24
|
+
# The description of the frame.
|
25
|
+
# @return [String]
|
26
|
+
def frame_description
|
27
|
+
@frame_description
|
28
|
+
end
|
29
|
+
|
30
|
+
# Return bindings for all caller frames.
|
31
|
+
# @return [Array<Binding>]
|
32
|
+
def callers
|
33
|
+
ary = []
|
34
|
+
n = 0
|
35
|
+
loop do
|
36
|
+
begin
|
37
|
+
ary << Binding.of_caller(n)
|
38
|
+
rescue
|
39
|
+
break
|
40
|
+
end
|
41
|
+
n += 1
|
42
|
+
end
|
43
|
+
ary.drop_while do |v|
|
44
|
+
!(v.frame_type == :method && v.eval("__method__") == :callers)
|
45
|
+
end.drop(1)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Number of parent frames available at the point of call.
|
49
|
+
# @return [Fixnum]
|
50
|
+
def frame_count
|
51
|
+
callers.size - 1
|
52
|
+
end
|
53
|
+
|
54
|
+
# The type of the frame.
|
55
|
+
# @return [Symbol]
|
56
|
+
def frame_type
|
57
|
+
case self.variables.method.metadata.to_a.first.to_s
|
58
|
+
when /block/
|
59
|
+
:block
|
60
|
+
when /eval/
|
61
|
+
:eval
|
62
|
+
else
|
63
|
+
if frame_description =~ /__(?:class|module)_init__/
|
64
|
+
:class
|
65
|
+
else
|
66
|
+
:method
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
class ::Binding
|
75
|
+
include BindingOfCaller::BindingExtensions
|
76
|
+
extend BindingOfCaller::BindingExtensions
|
77
|
+
end
|
@@ -4,6 +4,10 @@ unless Object.const_defined? :BindingOfCaller
|
|
4
4
|
require 'binding_of_caller/version'
|
5
5
|
end
|
6
6
|
|
7
|
+
class Module
|
8
|
+
public :remove_const
|
9
|
+
end
|
10
|
+
|
7
11
|
puts "Testing binding_of_caller version #{BindingOfCaller::VERSION}..."
|
8
12
|
puts "Ruby version: #{RUBY_VERSION}"
|
9
13
|
|
@@ -81,6 +85,27 @@ describe BindingOfCaller do
|
|
81
85
|
end
|
82
86
|
end
|
83
87
|
|
88
|
+
describe "frame_descripton" do
|
89
|
+
it 'describes a block frame' do
|
90
|
+
binding.of_caller(0).frame_description.should =~ /block/
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'describes a method frame' do
|
94
|
+
o = Object.new
|
95
|
+
def o.horsey_malone
|
96
|
+
binding.of_caller(0).frame_description.should =~ /horsey_malone/
|
97
|
+
end
|
98
|
+
o.horsey_malone
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'describes a class frame' do
|
102
|
+
class HorseyMalone
|
103
|
+
binding.of_caller(0).frame_description.should =~ /class/
|
104
|
+
end
|
105
|
+
Object.remove_const(:HorseyMalone)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
84
109
|
describe "frame_type" do
|
85
110
|
it 'should return the correct frame types' do
|
86
111
|
o = Object.new
|
@@ -103,6 +128,14 @@ describe BindingOfCaller do
|
|
103
128
|
caller_bindings[2].frame_type.should == :method
|
104
129
|
end
|
105
130
|
|
131
|
+
it 'identifies a class frame' do
|
132
|
+
class HorseyMalone
|
133
|
+
binding.of_caller(0).frame_type.should == :class
|
134
|
+
end
|
135
|
+
|
136
|
+
Object.remove_const(:HorseyMalone)
|
137
|
+
end
|
138
|
+
|
106
139
|
end
|
107
140
|
end
|
108
141
|
|
metadata
CHANGED
@@ -1,38 +1,57 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: binding_of_caller
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: '0.7'
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- John Mair (banisterfiend)
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2013-02-16 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: debug_inspector
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.0.1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.0.1
|
14
27
|
- !ruby/object:Gem::Dependency
|
15
28
|
name: bacon
|
16
|
-
requirement:
|
17
|
-
none: false
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
18
30
|
requirements:
|
19
|
-
- -
|
31
|
+
- - '>='
|
20
32
|
- !ruby/object:Gem::Version
|
21
33
|
version: '0'
|
22
34
|
type: :development
|
23
35
|
prerelease: false
|
24
|
-
version_requirements:
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
25
41
|
- !ruby/object:Gem::Dependency
|
26
42
|
name: rake
|
27
|
-
requirement:
|
28
|
-
none: false
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
29
44
|
requirements:
|
30
|
-
- -
|
45
|
+
- - '>='
|
31
46
|
- !ruby/object:Gem::Version
|
32
47
|
version: '0'
|
33
48
|
type: :development
|
34
49
|
prerelease: false
|
35
|
-
version_requirements:
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
36
55
|
description: Retrieve the binding of a method's caller. Can also retrieve bindings
|
37
56
|
even further up the stack.
|
38
57
|
email: jrmair@gmail.com
|
@@ -103,31 +122,32 @@ files:
|
|
103
122
|
- ext/binding_of_caller/ruby_headers/193/vm_insnhelper.h
|
104
123
|
- ext/binding_of_caller/ruby_headers/193/vm_opts.h
|
105
124
|
- lib/binding_of_caller.rb
|
125
|
+
- lib/binding_of_caller/mri2.rb
|
126
|
+
- lib/binding_of_caller/rubinius.rb
|
106
127
|
- lib/binding_of_caller/version.rb
|
107
128
|
- test/test_binding_of_caller.rb
|
108
129
|
homepage: http://github.com/banister/binding_of_caller
|
109
130
|
licenses: []
|
131
|
+
metadata: {}
|
110
132
|
post_install_message:
|
111
133
|
rdoc_options: []
|
112
134
|
require_paths:
|
113
135
|
- lib
|
114
136
|
required_ruby_version: !ruby/object:Gem::Requirement
|
115
|
-
none: false
|
116
137
|
requirements:
|
117
|
-
- -
|
138
|
+
- - '>='
|
118
139
|
- !ruby/object:Gem::Version
|
119
140
|
version: '0'
|
120
141
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
121
|
-
none: false
|
122
142
|
requirements:
|
123
|
-
- -
|
143
|
+
- - '>='
|
124
144
|
- !ruby/object:Gem::Version
|
125
145
|
version: '0'
|
126
146
|
requirements: []
|
127
147
|
rubyforge_project:
|
128
|
-
rubygems_version:
|
148
|
+
rubygems_version: 2.0.0.rc.2
|
129
149
|
signing_key:
|
130
|
-
specification_version:
|
150
|
+
specification_version: 4
|
131
151
|
summary: Retrieve the binding of a method's caller. Can also retrieve bindings even
|
132
152
|
further up the stack.
|
133
153
|
test_files:
|