binding_of_caller 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -21,31 +21,37 @@ call stack, not limited to just the immediate caller.
21
21
  Example: Modifying a local inside the caller of a caller
22
22
  --------
23
23
 
24
- def a
25
- var = 10
26
- b
27
- puts var
28
- end
24
+ ```ruby
25
+ def a
26
+ var = 10
27
+ b
28
+ puts var
29
+ end
29
30
 
30
- def b
31
- c
32
- end
31
+ def b
32
+ c
33
+ end
33
34
 
34
- def c
35
- binding.of_caller(2).eval('var = :hello')
36
- end
35
+ def c
36
+ binding.of_caller(2).eval('var = :hello')
37
+ end
37
38
 
38
- a()
39
+ a()
39
40
 
40
- # OUTPUT
41
- # => hello
41
+ # OUTPUT
42
+ # => hello
43
+ ```
44
+
45
+ Spinoff project
46
+ -------
47
+
48
+ This project is a spinoff from the [Pry REPL project.](http://pry.github.com)
42
49
 
43
50
  Features and limitations
44
51
  -------------------------
45
52
 
46
53
  * Only works with MRI 1.9.2
47
- * Broken in 1.9.3, support will hopefully be provided in the near
48
- * future.
54
+ * Broken in 1.9.3, support will hopefully be provided in the near future.
49
55
  * Does not work in 1.8.7, but there is a well known (continuation-based) hack to get a `Binding#of_caller` there.
50
56
 
51
57
  Contact
@@ -58,24 +58,25 @@ binding_alloc(VALUE klass)
58
58
  return obj;
59
59
  }
60
60
 
61
- static bool valid_frame_p(rb_control_frame_t * cfp) {
61
+ static bool valid_frame_p(rb_control_frame_t * cfp, rb_control_frame_t * limit_cfp) {
62
+ if (cfp > limit_cfp)
63
+ rb_raise(rb_eRuntimeError, "Invalid frame, gone beyond end of stack!");
64
+
62
65
  return cfp->iseq && !NIL_P(cfp->self);
63
66
  }
64
67
 
65
- static rb_control_frame_t * find_valid_frame(rb_control_frame_t * cfp) {
68
+ static rb_control_frame_t * find_valid_frame(rb_control_frame_t * cfp, rb_control_frame_t * limit_cfp) {
66
69
  int error_count = 0;
67
70
 
68
71
  while (error_count <= max_frame_errors) {
69
72
  cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
70
73
 
71
- if (valid_frame_p(cfp))
74
+ if (valid_frame_p(cfp, limit_cfp))
72
75
  return cfp;
73
76
  else
74
77
  error_count += 1;
75
78
  }
76
79
 
77
- rb_raise(rb_eRuntimeError, "No valid stack frame found.");
78
-
79
80
  // never reached
80
81
  return 0;
81
82
  }
@@ -84,15 +85,17 @@ static VALUE binding_of_caller(VALUE self, VALUE rb_level)
84
85
  {
85
86
  rb_thread_t *th = GET_THREAD();
86
87
  rb_control_frame_t *cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
88
+ rb_control_frame_t *limit_cfp = (void *)(th->stack + th->stack_size);
87
89
  int level = FIX2INT(rb_level);
88
90
 
89
91
  // attempt to locate the nth parent control frame
90
- for (int i = 0; i < level; i++)
92
+ for (int i = 0; i < level; i++) {
91
93
  cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
92
94
 
93
- // if did not find a valid one, then search for a valid one
94
- if (!valid_frame_p(cfp))
95
- cfp = find_valid_frame(cfp);
95
+ // skip invalid frames
96
+ if (!valid_frame_p(cfp, limit_cfp))
97
+ cfp = find_valid_frame(cfp, limit_cfp);
98
+ }
96
99
 
97
100
  VALUE bindval = binding_alloc(rb_cBinding);
98
101
  rb_binding_t *bind;
@@ -1,3 +1,3 @@
1
1
  module BindingOfCaller
2
- VERSION = "0.3.1"
2
+ VERSION = "0.4.0"
3
3
  end
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.3.1
5
+ version: 0.4.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-18 00:00:00 Z
13
+ date: 2011-10-20 00:00:00 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bacon