binding_of_caller 0.6.3 → 0.7.3.pre1

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.
@@ -0,0 +1,64 @@
1
+ class org::jruby::runtime::ThreadContext
2
+ java_import org.jruby.runtime.Binding
3
+ java_import org.jruby.RubyBinding
4
+ java_import org.jruby.RubyInstanceConfig::CompileMode
5
+
6
+ field_accessor :frameStack, :frameIndex,
7
+ :scopeStack, :scopeIndex,
8
+ :backtrace, :backtraceIndex
9
+
10
+ def binding_of_caller(index)
11
+ unless JRuby.runtime.instance_config.compile_mode == CompileMode::OFF
12
+ raise RuntimeError, "caller binding only supported in interpreter"
13
+ end
14
+
15
+ index += 1 # always omit this frame
16
+
17
+ raise RuntimeError, "Invalid frame, gone beyond end of stack!" if index > frameIndex
18
+
19
+ frame = frameStack[frameIndex - index]
20
+
21
+ return binding_of_caller(index - 1) if index > scopeIndex
22
+
23
+ scope = scopeStack[scopeIndex - index]
24
+ element = backtrace[backtraceIndex - index]
25
+
26
+ binding = Binding.new(frame, scope.static_scope.module, scope, element.clone)
27
+
28
+ JRuby.dereference(RubyBinding.new(JRuby.runtime, Binding, binding))
29
+ end
30
+ end
31
+
32
+ module BindingOfCaller
33
+ module BindingExtensions
34
+ def of_caller(index = 1)
35
+ index += 1 # always omit this frame
36
+ JRuby.runtime.current_context.binding_of_caller(index)
37
+ end
38
+
39
+ def callers
40
+ ary = []
41
+ n = 2
42
+ loop do
43
+ ary << of_caller(n) rescue break
44
+ n += 1
45
+ end
46
+ ary
47
+ end
48
+
49
+ def frame_count
50
+ callers.count - 1
51
+ end
52
+ end
53
+ end
54
+
55
+ class ::Binding
56
+ include BindingOfCaller::BindingExtensions
57
+ extend BindingOfCaller::BindingExtensions
58
+ end
59
+
60
+ class Java::OrgJrubyRuntime::Binding
61
+ def eval(code)
62
+ Kernel.eval code, self
63
+ end
64
+ end
@@ -0,0 +1,69 @@
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
+ # Return bindings for all caller frames.
17
+ # @return [Array<Binding>]
18
+ def callers
19
+ ary = []
20
+
21
+ RubyVM::DebugInspector.open do |i|
22
+ n = 0
23
+ loop do
24
+ begin
25
+ b = i.frame_binding(n)
26
+ rescue ArgumentError
27
+ break
28
+ end
29
+
30
+ if b
31
+ b.instance_variable_set(:@iseq, i.frame_iseq(n))
32
+ ary << b
33
+ end
34
+
35
+ n += 1
36
+ end
37
+ end
38
+
39
+ ary.drop(1)
40
+ end
41
+
42
+ # Number of parent frames available at the point of call.
43
+ # @return [Fixnum]
44
+ def frame_count
45
+ callers.size - 1
46
+ end
47
+
48
+ # The type of the frame.
49
+ # @return [Symbol]
50
+ def frame_type
51
+ return nil if !@iseq
52
+
53
+ # apparently the 9th element of the iseq array holds the frame type
54
+ # ...not sure how reliable this is.
55
+ @frame_type ||= @iseq.to_a[9]
56
+ end
57
+
58
+ # The description of the frame.
59
+ # @return [String]
60
+ def frame_description
61
+ return nil if !@iseq
62
+ @frame_description ||= @iseq.label
63
+ end
64
+ end
65
+ end
66
+
67
+ class ::Binding
68
+ include BindingOfCaller::BindingExtensions
69
+ end
@@ -0,0 +1,67 @@
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
+ location = Rubinius::VM.backtrace(1 + n, true).first
8
+
9
+ raise RuntimeError, "Invalid frame, gone beyond end of stack!" if location.nil?
10
+
11
+ setup_binding_from_location(location)
12
+ end
13
+
14
+ # The description of the frame.
15
+ # @return [String]
16
+ def frame_description
17
+ @frame_description
18
+ end
19
+
20
+ # Return bindings for all caller frames.
21
+ # @return [Array<Binding>]
22
+ def callers
23
+ Rubinius::VM.backtrace(1, true).map &(method(:setup_binding_from_location).
24
+ to_proc)
25
+ end
26
+
27
+ # Number of parent frames available at the point of call.
28
+ # @return [Fixnum]
29
+ def frame_count
30
+ Rubinius::VM.backtrace(1).count
31
+ end
32
+
33
+ # The type of the frame.
34
+ # @return [Symbol]
35
+ def frame_type
36
+ if compiled_code.for_module_body?
37
+ :class
38
+ elsif compiled_code.for_eval?
39
+ :eval
40
+ elsif compiled_code.is_block?
41
+ :block
42
+ else
43
+ :method
44
+ end
45
+ end
46
+
47
+ protected
48
+
49
+ def setup_binding_from_location(location)
50
+ binding = Binding.setup location.variables,
51
+ location.variables.method,
52
+ location.constant_scope,
53
+ location.variables.self,
54
+ location
55
+
56
+ binding.instance_variable_set :@frame_description,
57
+ location.describe.gsub("{ } in", "block in")
58
+
59
+ binding
60
+ end
61
+ end
62
+ end
63
+
64
+ class ::Binding
65
+ include BindingOfCaller::BindingExtensions
66
+ extend BindingOfCaller::BindingExtensions
67
+ end
@@ -1,3 +1,3 @@
1
- module BindingOfCaller
2
- VERSION = "0.6.3"
3
- end
1
+ module BindingOfCaller
2
+ VERSION = "0.7.3.pre1"
3
+ end
@@ -1,82 +1,16 @@
1
- dlext = Config::CONFIG['DLEXT']
1
+ dlext = RbConfig::CONFIG['DLEXT']
2
2
 
3
- if RUBY_ENGINE && RUBY_ENGINE == "ruby"
4
- require "binding_of_caller.#{dlext}"
3
+ def mri_2?
4
+ defined?(RUBY_ENGINE) && RUBY_ENGINE == "ruby" &&
5
+ RUBY_VERSION =~ /^2/
6
+ end
5
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}"
6
12
  elsif defined?(Rubinius)
7
- module BindingOfCaller
8
- module BindingExtensions
9
-
10
- def of_caller(n)
11
- bt = Rubinius::VM.backtrace(1 + n, true).first
12
-
13
- b = Binding.setup(
14
- bt.variables,
15
- bt.variables.method,
16
- bt.static_scope,
17
- bt.variables.self,
18
- bt
19
- )
20
-
21
- b.instance_variable_set(:@frame_description, bt.describe)
22
-
23
- b
24
- rescue
25
- raise RuntimeError, "Invalid frame, gone beyond end of stack!"
26
- end
27
-
28
- def frame_description
29
- @frame_description
30
- end
31
-
32
- def callers
33
- ary = []
34
- n = 0
35
- loop {
36
- begin
37
- ary << Binding.of_caller(n)
38
- rescue
39
- break
40
- end
41
-
42
- n += 1
43
- }
44
-
45
- ary
46
- end
47
-
48
- def frame_count
49
- ary = []
50
- n = 1
51
- loop {
52
- begin
53
- Binding.of_caller(n)
54
- rescue
55
- break
56
- end
57
-
58
- n += 1
59
- }
60
-
61
- n
62
- end
63
-
64
- def frame_type
65
- case self.variables.method.metadata.to_a.first.to_s
66
- when /block/
67
- :block
68
- when /eval/
69
- :eval
70
- else
71
- :method
72
- end
73
- end
74
-
75
- end
76
- end
77
-
78
- class ::Binding
79
- include BindingOfCaller::BindingExtensions
80
- extend BindingOfCaller::BindingExtensions
81
- end
13
+ require 'binding_of_caller/rubinius'
14
+ elsif defined?(JRuby)
15
+ require 'binding_of_caller/jruby_interpreted'
82
16
  end
@@ -0,0 +1,161 @@
1
+ unless Object.const_defined? :BindingOfCaller
2
+ $:.unshift File.expand_path '../../lib', __FILE__
3
+ require 'binding_of_caller'
4
+ require 'binding_of_caller/version'
5
+ end
6
+
7
+ class Module
8
+ public :remove_const
9
+ end
10
+
11
+ puts "Testing binding_of_caller version #{BindingOfCaller::VERSION}..."
12
+ puts "Ruby version: #{RUBY_VERSION}"
13
+
14
+ describe BindingOfCaller do
15
+ describe "of_caller" do
16
+ it "should fetch immediate caller's binding when 0 is passed" do
17
+ o = Object.new
18
+ def o.a
19
+ var = 1
20
+ binding.of_caller(0).eval('var')
21
+ end
22
+
23
+ o. a.should == 1
24
+ end
25
+
26
+ it "should fetch parent of caller's binding when 1 is passed" do
27
+ o = Object.new
28
+ def o.a
29
+ var = 1
30
+ b
31
+ end
32
+
33
+ def o.b
34
+ binding.of_caller(1).eval('var')
35
+ end
36
+
37
+ o.a.should == 1
38
+ end
39
+
40
+ it "should modify locals in parent of caller's binding" do
41
+ o = Object.new
42
+ def o.a
43
+ var = 1
44
+ b
45
+ var
46
+ end
47
+
48
+ def o.b
49
+ binding.of_caller(1).eval('var = 20')
50
+ end
51
+
52
+ o.a.should == 20
53
+ end
54
+
55
+ it "should raise an exception when retrieving an out of band binding" do
56
+ o = Object.new
57
+ def o.a
58
+ binding.of_caller(100)
59
+ end
60
+
61
+ lambda { o.a }.should.raise RuntimeError
62
+ end
63
+ end
64
+
65
+ describe "callers" do
66
+ before do
67
+ @o = Object.new
68
+ end
69
+
70
+ it 'should return the first non-internal binding when using callers.first' do
71
+ def @o.meth
72
+ x = :a_local
73
+ [binding.callers.first, binding.of_caller(0)]
74
+ end
75
+
76
+ b1, b2 = @o.meth
77
+ b1.eval("x").should == :a_local
78
+ b2.eval("x").should == :a_local
79
+ end
80
+ end
81
+
82
+ describe "frame_count" do
83
+ it 'frame_count should equal callers.count' do
84
+ binding.frame_count.should == binding.callers.count
85
+ end
86
+ end
87
+
88
+ describe "frame_descripton" do
89
+ it 'can be called on ordinary binding without raising' do
90
+ lambda { binding.frame_description }.should.not.raise
91
+ end
92
+
93
+ it 'describes a block frame' do
94
+ binding.of_caller(0).frame_description.should =~ /block/
95
+ end
96
+
97
+ it 'describes a method frame' do
98
+ o = Object.new
99
+ def o.horsey_malone
100
+ binding.of_caller(0).frame_description.should =~ /horsey_malone/
101
+ end
102
+ o.horsey_malone
103
+ end
104
+
105
+ it 'describes a class frame' do
106
+ class HorseyMalone
107
+ binding.of_caller(0).frame_description.should =~ /class/i
108
+ end
109
+ Object.remove_const(:HorseyMalone)
110
+ end
111
+ end
112
+
113
+ describe "frame_type" do
114
+ it 'can be called on ordinary binding without raising' do
115
+ lambda { binding.frame_type }.should.not.raise
116
+ end
117
+
118
+ describe "when inside a class definition" do
119
+ before do
120
+ class HorseyMalone
121
+ @binding = binding.of_caller(0)
122
+ def self.binding; @binding; end
123
+ end
124
+ @binding = HorseyMalone.binding
125
+ end
126
+
127
+ it 'returns :class' do
128
+ @binding.frame_type.should == :class
129
+ end
130
+ end
131
+
132
+ describe "when evaluated" do
133
+ before { @binding = eval("binding.of_caller(0)") }
134
+
135
+ it 'returns :eval' do
136
+ @binding.frame_type.should == :eval
137
+ end
138
+ end
139
+
140
+ describe "when inside a block" do
141
+ before { @binding = proc { binding.of_caller(0) }.call }
142
+
143
+ it 'returns :block' do
144
+ @binding.frame_type.should == :block
145
+ end
146
+ end
147
+
148
+ describe "when inside an instance method" do
149
+ before do
150
+ o = Object.new
151
+ def o.a; binding.of_caller(0); end
152
+ @binding = o.a;
153
+ end
154
+
155
+ it 'returns :method' do
156
+ @binding.frame_type.should == :method
157
+ end
158
+ end
159
+ end
160
+ end
161
+
metadata CHANGED
@@ -1,49 +1,82 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: binding_of_caller
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.3
5
- prerelease:
4
+ version: 0.7.3.pre1
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: 2012-02-29 00:00:00.000000000 Z
11
+ date: 2014-08-20 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: &70210333909540 !ruby/object:Gem::Requirement
17
- none: false
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
18
44
  requirements:
19
- - - ~>
45
+ - - ">="
20
46
  - !ruby/object:Gem::Version
21
- version: '1.1'
47
+ version: '0'
22
48
  type: :development
23
49
  prerelease: false
24
- version_requirements: *70210333909540
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
25
55
  description: Retrieve the binding of a method's caller. Can also retrieve bindings
26
- even further up the stack. Currently only works for MRI 1.9.2+
56
+ even further up the stack.
27
57
  email: jrmair@gmail.com
28
58
  executables: []
29
59
  extensions:
30
60
  - ext/binding_of_caller/extconf.rb
31
61
  extra_rdoc_files: []
32
62
  files:
33
- - .gemtest
34
- - .gitignore
35
- - .yardopts
63
+ - ".gemtest"
64
+ - ".gitignore"
65
+ - ".travis.yml"
66
+ - ".yardopts"
67
+ - Gemfile
36
68
  - HISTORY
37
69
  - LICENSE
38
70
  - README.md
39
71
  - Rakefile
72
+ - binding_of_caller.gemspec
73
+ - examples/benchmark.rb
40
74
  - examples/example.rb
41
75
  - ext/binding_of_caller/binding_of_caller.c
42
76
  - ext/binding_of_caller/extconf.rb
43
77
  - ext/binding_of_caller/ruby_headers/192/debug.h
44
78
  - ext/binding_of_caller/ruby_headers/192/dln.h
45
79
  - ext/binding_of_caller/ruby_headers/192/eval_intern.h
46
- - ext/binding_of_caller/ruby_headers/192/gc.h
47
80
  - ext/binding_of_caller/ruby_headers/192/id.h
48
81
  - ext/binding_of_caller/ruby_headers/192/iseq.h
49
82
  - ext/binding_of_caller/ruby_headers/192/method.h
@@ -51,6 +84,7 @@ files:
51
84
  - ext/binding_of_caller/ruby_headers/192/regenc.h
52
85
  - ext/binding_of_caller/ruby_headers/192/regint.h
53
86
  - ext/binding_of_caller/ruby_headers/192/regparse.h
87
+ - ext/binding_of_caller/ruby_headers/192/rubys_gc.h
54
88
  - ext/binding_of_caller/ruby_headers/192/thread_pthread.h
55
89
  - ext/binding_of_caller/ruby_headers/192/thread_win32.h
56
90
  - ext/binding_of_caller/ruby_headers/192/timev.h
@@ -67,7 +101,6 @@ files:
67
101
  - ext/binding_of_caller/ruby_headers/193/dln.h
68
102
  - ext/binding_of_caller/ruby_headers/193/encdb.h
69
103
  - ext/binding_of_caller/ruby_headers/193/eval_intern.h
70
- - ext/binding_of_caller/ruby_headers/193/gc.h
71
104
  - ext/binding_of_caller/ruby_headers/193/id.h
72
105
  - ext/binding_of_caller/ruby_headers/193/internal.h
73
106
  - ext/binding_of_caller/ruby_headers/193/iseq.h
@@ -78,6 +111,7 @@ files:
78
111
  - ext/binding_of_caller/ruby_headers/193/regint.h
79
112
  - ext/binding_of_caller/ruby_headers/193/regparse.h
80
113
  - ext/binding_of_caller/ruby_headers/193/revision.h
114
+ - ext/binding_of_caller/ruby_headers/193/rubys_gc.h
81
115
  - ext/binding_of_caller/ruby_headers/193/thread_pthread.h
82
116
  - ext/binding_of_caller/ruby_headers/193/thread_win32.h
83
117
  - ext/binding_of_caller/ruby_headers/193/timev.h
@@ -88,35 +122,35 @@ files:
88
122
  - ext/binding_of_caller/ruby_headers/193/vm_exec.h
89
123
  - ext/binding_of_caller/ruby_headers/193/vm_insnhelper.h
90
124
  - ext/binding_of_caller/ruby_headers/193/vm_opts.h
91
- - lib/binding_of_caller.bundle
92
125
  - lib/binding_of_caller.rb
126
+ - lib/binding_of_caller/jruby_interpreted.rb
127
+ - lib/binding_of_caller/mri2.rb
128
+ - lib/binding_of_caller/rubinius.rb
93
129
  - lib/binding_of_caller/version.rb
94
- - lib/tester.rb
95
- - test/test.rb
130
+ - test/test_binding_of_caller.rb
96
131
  homepage: http://github.com/banister/binding_of_caller
97
132
  licenses: []
133
+ metadata: {}
98
134
  post_install_message:
99
135
  rdoc_options: []
100
136
  require_paths:
101
137
  - lib
102
138
  required_ruby_version: !ruby/object:Gem::Requirement
103
- none: false
104
139
  requirements:
105
- - - ! '>='
140
+ - - ">="
106
141
  - !ruby/object:Gem::Version
107
142
  version: '0'
108
143
  required_rubygems_version: !ruby/object:Gem::Requirement
109
- none: false
110
144
  requirements:
111
- - - ! '>='
145
+ - - ">"
112
146
  - !ruby/object:Gem::Version
113
- version: '0'
147
+ version: 1.3.1
114
148
  requirements: []
115
149
  rubyforge_project:
116
- rubygems_version: 1.8.16
150
+ rubygems_version: 2.2.2
117
151
  signing_key:
118
- specification_version: 3
152
+ specification_version: 4
119
153
  summary: Retrieve the binding of a method's caller. Can also retrieve bindings even
120
- further up the stack. Currently only works for MRI 1.9.2+
154
+ further up the stack.
121
155
  test_files:
122
- - test/test.rb
156
+ - test/test_binding_of_caller.rb
Binary file
data/lib/tester.rb DELETED
@@ -1,15 +0,0 @@
1
- require './binding_of_caller'
2
-
3
- def a
4
- x = 1
5
- y = 2
6
- b()
7
- end
8
-
9
- def b
10
- proc do
11
- puts binding.of_caller(2).eval('__method__')
12
- end.call
13
- end
14
-
15
- a