binding_of_caller 0.6.8 → 0.7
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.
- 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:
|