binding_of_caller 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gemtest +0 -0
- data/.gitignore +7 -0
- data/.yardopts +1 -0
- data/LICENSE +25 -0
- data/Rakefile +25 -44
- data/ext/binding_of_caller/binding_of_caller.c +9 -14
- data/ext/binding_of_caller/example.rb +39 -0
- data/lib/binding_of_caller/version.rb +2 -2
- data/test/test.rb +53 -6
- metadata +18 -14
- data/lib/binding_of_caller.rb +0 -22
data/.gemtest
ADDED
File without changes
|
data/.gitignore
ADDED
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--markup markdown
|
data/LICENSE
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
License
|
2
|
+
-------
|
3
|
+
|
4
|
+
(The MIT License)
|
5
|
+
|
6
|
+
Copyright (c) 2011 John Mair (banisterfiend)
|
7
|
+
|
8
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
9
|
+
a copy of this software and associated documentation files (the
|
10
|
+
'Software'), to deal in the Software without restriction, including
|
11
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
12
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
13
|
+
permit persons to whom the Software is furnished to do so, subject to
|
14
|
+
the following conditions:
|
15
|
+
|
16
|
+
The above copyright notice and this permission notice shall be
|
17
|
+
included in all copies or substantial portions of the Software.
|
18
|
+
|
19
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
20
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
21
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
22
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
23
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
24
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
25
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
dlext = Config::CONFIG['DLEXT']
|
2
|
-
|
2
|
+
|
3
|
+
$:.unshift 'lib'
|
3
4
|
|
4
5
|
PROJECT_NAME = "binding_of_caller"
|
5
6
|
|
6
7
|
require 'rake/clean'
|
7
8
|
require 'rake/gempackagetask'
|
8
|
-
require "#{
|
9
|
+
require "#{PROJECT_NAME}/version"
|
9
10
|
|
10
11
|
CLOBBER.include("**/*.#{dlext}", "**/*~", "**/*#*", "**/*.log", "**/*.o")
|
11
12
|
CLEAN.include("ext/**/*.#{dlext}", "ext/**/*.log", "ext/**/*.o",
|
@@ -14,77 +15,57 @@ CLEAN.include("ext/**/*.#{dlext}", "ext/**/*.log", "ext/**/*.o",
|
|
14
15
|
|
15
16
|
def apply_spec_defaults(s)
|
16
17
|
s.name = PROJECT_NAME
|
17
|
-
s.summary = "
|
18
|
+
s.summary = "Retrieve the binding of a method's caller. Can also retrieve bindings even further up the stack. Currently only works for MRI 1.9.2."
|
18
19
|
s.version = BindingOfCaller::VERSION
|
19
20
|
s.date = Time.now.strftime '%Y-%m-%d'
|
20
21
|
s.author = "John Mair (banisterfiend)"
|
21
22
|
s.email = 'jrmair@gmail.com'
|
22
23
|
s.description = s.summary
|
23
24
|
s.require_path = 'lib'
|
24
|
-
s.add_development_dependency("bacon","
|
25
|
-
s.homepage = "http://
|
25
|
+
s.add_development_dependency("bacon","~>1.1.0")
|
26
|
+
s.homepage = "http://github.com/banister/binding_of_caller"
|
26
27
|
s.has_rdoc = 'yard'
|
27
|
-
s.files =
|
28
|
-
|
28
|
+
s.files = `git ls-files`.split("\n")
|
29
|
+
s.test_files = `git ls-files -- test/*`.split("\n")
|
29
30
|
end
|
30
31
|
|
31
|
-
desc "
|
32
|
+
desc "Run tests"
|
32
33
|
task :test do
|
33
|
-
sh "bacon -
|
34
|
+
sh "bacon -Itest -rubygems test.rb -q"
|
34
35
|
end
|
35
36
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
apply_spec_defaults(s)
|
40
|
-
s.platform = "i386-#{v}"
|
41
|
-
s.files += FileList["lib/**/*.#{dlext}"].to_a
|
42
|
-
end
|
43
|
-
|
44
|
-
Rake::GemPackageTask.new(spec) do |pkg|
|
45
|
-
pkg.need_zip = false
|
46
|
-
pkg.need_tar = false
|
47
|
-
end
|
48
|
-
end
|
37
|
+
task :pry do
|
38
|
+
puts "loading binding_of_caller into pry"
|
39
|
+
sh "pry -r ./lib/binding_of_caller"
|
49
40
|
end
|
50
41
|
|
51
42
|
namespace :ruby do
|
52
43
|
spec = Gem::Specification.new do |s|
|
53
|
-
apply_spec_defaults(s)
|
44
|
+
apply_spec_defaults(s)
|
54
45
|
s.platform = Gem::Platform::RUBY
|
55
46
|
s.extensions = ["ext/#{PROJECT_NAME}/extconf.rb"]
|
56
47
|
end
|
57
|
-
|
48
|
+
|
58
49
|
Rake::GemPackageTask.new(spec) do |pkg|
|
59
50
|
pkg.need_zip = false
|
60
51
|
pkg.need_tar = false
|
61
52
|
end
|
62
53
|
end
|
63
54
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
sh
|
71
|
-
c:\\devkit\\devkitvars.bat && \
|
72
|
-
pik #{pik_ver} && \
|
73
|
-
ruby extconf.rb && \
|
74
|
-
make clean && \
|
75
|
-
make && \
|
76
|
-
cp *.so #{direc}/lib/#{ver} \
|
77
|
-
}
|
78
|
-
end
|
79
|
-
|
80
|
-
chdir("#{direc}/ext/#{PROJECT_NAME}") do
|
81
|
-
build_for.call("187", "1.8")
|
82
|
-
build_for.call("192", "1.9")
|
55
|
+
desc "build the biinaries"
|
56
|
+
task :compile do
|
57
|
+
chdir "./ext/#{PROJECT_NAME}/" do
|
58
|
+
sh "ruby extconf.rb"
|
59
|
+
sh "make clean"
|
60
|
+
sh "make"
|
61
|
+
sh "cp *.#{dlext} ../../lib/"
|
83
62
|
end
|
84
63
|
end
|
85
64
|
|
86
65
|
desc "build all platform gems at once"
|
87
|
-
task :gems => [:clean, :rmgems, "
|
66
|
+
task :gems => [:clean, :rmgems, "ruby:gem"]
|
67
|
+
|
68
|
+
task :gem => [:gems]
|
88
69
|
|
89
70
|
desc "remove all platform gems"
|
90
71
|
task :rmgems => ["ruby:clobber_package"]
|
@@ -1,22 +1,15 @@
|
|
1
1
|
/* (c) 2011 John Mair (banisterfiend), MIT license */
|
2
2
|
|
3
3
|
#include <ruby.h>
|
4
|
-
//#include "compat.h"
|
5
4
|
|
6
|
-
//#ifdef RUBY_19
|
7
5
|
# include <ruby/io.h>
|
8
6
|
# include <ruby/re.h>
|
9
7
|
# include "vm_core.h"
|
10
8
|
# include "gc.h"
|
11
|
-
/* #else */
|
12
|
-
/* # include "re.h" */
|
13
|
-
/* # include "env.h" */
|
14
|
-
/* # include "node.h" */
|
15
|
-
/* # include "rubysig.h" */
|
16
|
-
/* # include "rubyio.h" */
|
17
|
-
/* #endif */
|
18
9
|
|
19
|
-
|
10
|
+
typedef enum { false, true } bool;
|
11
|
+
|
12
|
+
const int max_frame_errors = 4;
|
20
13
|
|
21
14
|
static size_t
|
22
15
|
binding_memsize(const void *ptr)
|
@@ -65,8 +58,6 @@ binding_alloc(VALUE klass)
|
|
65
58
|
return obj;
|
66
59
|
}
|
67
60
|
|
68
|
-
typedef enum { false, true } bool;
|
69
|
-
|
70
61
|
static bool valid_frame_p(rb_control_frame_t * cfp) {
|
71
62
|
return cfp->iseq && !NIL_P(cfp->self);
|
72
63
|
}
|
@@ -74,7 +65,7 @@ static bool valid_frame_p(rb_control_frame_t * cfp) {
|
|
74
65
|
static rb_control_frame_t * find_valid_frame(rb_control_frame_t * cfp) {
|
75
66
|
int error_count = 0;
|
76
67
|
|
77
|
-
while (error_count <=
|
68
|
+
while (error_count <= max_frame_errors) {
|
78
69
|
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
|
79
70
|
|
80
71
|
if (valid_frame_p(cfp))
|
@@ -95,9 +86,11 @@ static VALUE binding_of_caller(VALUE self, VALUE rb_level)
|
|
95
86
|
rb_control_frame_t *cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
|
96
87
|
int level = FIX2INT(rb_level);
|
97
88
|
|
89
|
+
// attempt to locate the nth parent control frame
|
98
90
|
for (int i = 0; i < level; i++)
|
99
91
|
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
|
100
92
|
|
93
|
+
// if did not find a valid one, then search for a valid one
|
101
94
|
if (!valid_frame_p(cfp))
|
102
95
|
cfp = find_valid_frame(cfp);
|
103
96
|
|
@@ -118,7 +111,9 @@ static VALUE binding_of_caller(VALUE self, VALUE rb_level)
|
|
118
111
|
void
|
119
112
|
Init_binding_of_caller()
|
120
113
|
{
|
121
|
-
|
114
|
+
VALUE mBindingOfCaller = rb_define_module("BindingOfCaller");
|
122
115
|
|
116
|
+
rb_define_method(mBindingOfCaller, "of_caller", binding_of_caller, 1);
|
117
|
+
rb_include_module(rb_cBinding, mBindingOfCaller);
|
123
118
|
}
|
124
119
|
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require './binding_of_caller'
|
2
|
+
|
3
|
+
outer = 10
|
4
|
+
|
5
|
+
class Z
|
6
|
+
def z
|
7
|
+
u = 10
|
8
|
+
A.new.a
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class A
|
13
|
+
def a
|
14
|
+
y = 10
|
15
|
+
B.new.b
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class B
|
20
|
+
def b
|
21
|
+
x = 10
|
22
|
+
puts binding_of_caller(0).eval('local_variables')
|
23
|
+
puts binding_of_caller(1).eval('local_variables')
|
24
|
+
puts binding_of_caller(2).eval('local_variables')
|
25
|
+
puts binding_of_caller(3).eval('local_variables')
|
26
|
+
puts binding_of_caller(400).eval('local_variables')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def a; b; end; def b; binding_of_caller(10); end; a;
|
31
|
+
|
32
|
+
# Z.new.z
|
33
|
+
|
34
|
+
# output:
|
35
|
+
# => x
|
36
|
+
# => y
|
37
|
+
# => u
|
38
|
+
# => outer
|
39
|
+
# Exception
|
@@ -1,3 +1,3 @@
|
|
1
1
|
module BindingOfCaller
|
2
|
-
VERSION = "0.
|
3
|
-
end
|
2
|
+
VERSION = "0.3.0"
|
3
|
+
end
|
data/test/test.rb
CHANGED
@@ -1,12 +1,59 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require '
|
4
|
-
require
|
5
|
-
|
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
6
|
|
7
|
-
puts "Testing binding_of_caller version #{BindingOfCaller::VERSION}..."
|
7
|
+
puts "Testing binding_of_caller version #{BindingOfCaller::VERSION}..."
|
8
8
|
puts "Ruby version: #{RUBY_VERSION}"
|
9
9
|
|
10
10
|
describe BindingOfCaller do
|
11
|
+
it "should fetch immediate caller's binding when 0 is passed" do
|
12
|
+
o = Object.new
|
13
|
+
def o.a
|
14
|
+
var = 1
|
15
|
+
binding.of_caller(0).eval('var')
|
16
|
+
end
|
17
|
+
|
18
|
+
o. a.should == 1
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should fetch parent of caller's binding when 1 is passed" do
|
22
|
+
o = Object.new
|
23
|
+
def o.a
|
24
|
+
var = 1
|
25
|
+
b
|
26
|
+
end
|
27
|
+
|
28
|
+
def o.b
|
29
|
+
binding.of_caller(1).eval('var')
|
30
|
+
end
|
31
|
+
|
32
|
+
o.a.should == 1
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should modify locals in parent of caller's binding" do
|
36
|
+
o = Object.new
|
37
|
+
def o.a
|
38
|
+
var = 1
|
39
|
+
b
|
40
|
+
var
|
41
|
+
end
|
42
|
+
|
43
|
+
def o.b
|
44
|
+
binding.of_caller(1).eval('var = 20')
|
45
|
+
end
|
46
|
+
|
47
|
+
o.a.should == 20
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should raise an exception when retrieving an out of band binding" do
|
51
|
+
o = Object.new
|
52
|
+
def o.a
|
53
|
+
binding.of_caller(100)
|
54
|
+
end
|
55
|
+
|
56
|
+
lambda { o.a }.should.raise RuntimeError
|
57
|
+
end
|
11
58
|
end
|
12
59
|
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: binding_of_caller
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.
|
5
|
+
version: 0.3.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- John Mair (banisterfiend)
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-10-
|
13
|
+
date: 2011-10-18 00:00:00 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: bacon
|
@@ -18,12 +18,12 @@ dependencies:
|
|
18
18
|
requirement: &id001 !ruby/object:Gem::Requirement
|
19
19
|
none: false
|
20
20
|
requirements:
|
21
|
-
- -
|
21
|
+
- - ~>
|
22
22
|
- !ruby/object:Gem::Version
|
23
23
|
version: 1.1.0
|
24
24
|
type: :development
|
25
25
|
version_requirements: *id001
|
26
|
-
description:
|
26
|
+
description: Retrieve the binding of a method's caller. Can also retrieve bindings even further up the stack. Currently only works for MRI 1.9.2.
|
27
27
|
email: jrmair@gmail.com
|
28
28
|
executables: []
|
29
29
|
|
@@ -32,8 +32,17 @@ extensions:
|
|
32
32
|
extra_rdoc_files: []
|
33
33
|
|
34
34
|
files:
|
35
|
-
-
|
35
|
+
- .gemtest
|
36
|
+
- .gitignore
|
37
|
+
- .yardopts
|
38
|
+
- HISTORY
|
39
|
+
- LICENSE
|
40
|
+
- README.md
|
41
|
+
- Rakefile
|
42
|
+
- ext/binding_of_caller/binding_of_caller.c
|
36
43
|
- ext/binding_of_caller/compat.h
|
44
|
+
- ext/binding_of_caller/example.rb
|
45
|
+
- ext/binding_of_caller/extconf.rb
|
37
46
|
- ext/binding_of_caller/ruby_headers/192/debug.h
|
38
47
|
- ext/binding_of_caller/ruby_headers/192/dln.h
|
39
48
|
- ext/binding_of_caller/ruby_headers/192/eval_intern.h
|
@@ -82,14 +91,9 @@ files:
|
|
82
91
|
- ext/binding_of_caller/ruby_headers/193/vm_exec.h
|
83
92
|
- ext/binding_of_caller/ruby_headers/193/vm_insnhelper.h
|
84
93
|
- ext/binding_of_caller/ruby_headers/193/vm_opts.h
|
85
|
-
- ext/binding_of_caller/binding_of_caller.c
|
86
94
|
- lib/binding_of_caller/version.rb
|
87
|
-
- lib/binding_of_caller.rb
|
88
95
|
- test/test.rb
|
89
|
-
|
90
|
-
- README.md
|
91
|
-
- Rakefile
|
92
|
-
homepage: http://banisterfiend.wordpress.com
|
96
|
+
homepage: http://github.com/banister/binding_of_caller
|
93
97
|
licenses: []
|
94
98
|
|
95
99
|
post_install_message:
|
@@ -115,6 +119,6 @@ rubyforge_project:
|
|
115
119
|
rubygems_version: 1.8.11
|
116
120
|
signing_key:
|
117
121
|
specification_version: 3
|
118
|
-
summary:
|
119
|
-
test_files:
|
120
|
-
|
122
|
+
summary: Retrieve the binding of a method's caller. Can also retrieve bindings even further up the stack. Currently only works for MRI 1.9.2.
|
123
|
+
test_files:
|
124
|
+
- test/test.rb
|
data/lib/binding_of_caller.rb
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
# binding_of_caller.rb
|
2
|
-
# (C) John Mair (banisterfiend); MIT license
|
3
|
-
|
4
|
-
direc = File.dirname(__FILE__)
|
5
|
-
|
6
|
-
require "#{direc}/binding_of_caller/version"
|
7
|
-
|
8
|
-
begin
|
9
|
-
if RUBY_VERSION =~ /1.9/
|
10
|
-
require "#{direc}/1.9/binding_of_caller"
|
11
|
-
else
|
12
|
-
require "#{direc}/1.8/binding_of_caller"
|
13
|
-
end
|
14
|
-
rescue LoadError => e
|
15
|
-
require "rbconfig"
|
16
|
-
dlext = Config::CONFIG['DLEXT']
|
17
|
-
require "#{direc}/binding_of_caller.#{dlext}"
|
18
|
-
end
|
19
|
-
|
20
|
-
module BindingOfCaller
|
21
|
-
end
|
22
|
-
|