binding_of_caller 0.3.1 → 0.4.0

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.
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