evalhook 0.4.1 → 0.5.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/CHANGELOG CHANGED
@@ -1,3 +1,9 @@
1
+ 0.5.0 Implemented code packets (see documentation)
2
+
3
+ Refactor of hooking of call, super and zsuper nodes to improve performance
4
+
5
+ Refactor of spec to be compatible with ruby 1.9
6
+
1
7
  0.4.1 Fixed bug on hooking of node type super (lack of hooking for arguments)
2
8
 
3
9
  0.4.0 Removed evalmimic dependency
data/Rakefile CHANGED
@@ -6,7 +6,7 @@ require 'rake/gempackagetask'
6
6
 
7
7
  spec = Gem::Specification.new do |s|
8
8
  s.name = 'evalhook'
9
- s.version = '0.4.1'
9
+ s.version = '0.5.0'
10
10
  s.author = 'Dario Seminara'
11
11
  s.email = 'robertodarioseminara@gmail.com'
12
12
  s.platform = Gem::Platform::RUBY
@@ -18,10 +18,12 @@ you should have received a copy of the gnu general public license
18
18
  along with evalhook. if not, see <http://www.gnu.org/licenses/>.
19
19
 
20
20
  =end
21
- require "evalhook/hook_handler"
22
-
23
21
  module EvalHook
24
22
 
23
+ class HookHandler
24
+
25
+ end
26
+
25
27
  class MultiHookHandler < HookHandler
26
28
  def initialize
27
29
  @nested_hook_handlers = Array.new
@@ -59,37 +59,34 @@ module EvalHook
59
59
 
60
60
  def process_gasgn(tree)
61
61
 
62
- args1 = s(:arglist, s(:lit, tree[1]))
63
- args2 = s(:arglist, process(tree[2]))
64
-
65
- firstcall = s(:call, hook_handler_reference, :hooked_gasgn, args1)
66
-
67
- s(:call, firstcall, :set_value, args2)
62
+ args1 = s(:arglist, s(:lit, tree[1]), process(tree[2]))
68
63
 
64
+ s(:call, hook_handler_reference, :hooked_gasgn, args1)
69
65
  end
70
66
 
71
67
 
72
68
  def process_call(tree)
69
+ original_receiver = tree[1]
73
70
 
74
- original_receiver = tree[1]
75
-
76
- receiver = process(original_receiver|| s(:self))
77
-
78
- args1 = s(:arglist, s(:lit, tree[2]), s(:call, nil, :binding, s(:arglist)))
79
- args2 = s(:arglist, hook_handler_reference)
71
+ receiver = process(original_receiver|| s(:self))
80
72
 
81
- firstcall = nil
82
- secondcall = nil
73
+ firstcall = nil
83
74
 
84
- if original_receiver
85
- firstcall = s(:call, receiver, :local_hooked_method, args1)
86
- secondcall = s(:call, firstcall, :set_hook_handler, args2)
87
- else
88
- firstcall = s(:call, receiver, :hooked_method, args1)
89
- secondcall = s(:call, firstcall, :set_hook_handler, args2)
90
- end
75
+ if tree[3] == s(:arglist)
76
+ firstcall = s(:call,
77
+ hook_handler_reference,
78
+ :hooked_variable_method,
79
+ s(:arglist, receiver, s(:lit, tree[2]), s(:call, nil, :binding, s(:arglist)))
80
+ )
81
+ else
82
+ firstcall = s(:call,
83
+ hook_handler_reference,
84
+ :hooked_method,
85
+ s(:arglist, receiver, s(:lit, tree[2]))
86
+ )
87
+ end
91
88
 
92
- s(:call, secondcall, :call, process(tree[3]))
89
+ s(:call, firstcall, :call, process(tree[3]))
93
90
  end
94
91
 
95
92
  def process_cdecl(tree)
@@ -113,14 +110,9 @@ module EvalHook
113
110
  const_id = const_tree
114
111
  end
115
112
 
116
- args1 = s(:arglist, base_class_tree)
117
- args2 = s(:arglist, s(:lit, const_id))
118
- args3 = s(:arglist, process(value_tree))
119
-
120
- firstcall = s(:call, hook_handler_reference, :hooked_cdecl, args1 )
121
- secondcall = s(:call, firstcall, :set_id, args2)
113
+ args1 = s(:arglist, base_class_tree, s(:lit, const_id), process(value_tree))
122
114
 
123
- s(:call, secondcall, :set_value, args3)
115
+ s(:call, hook_handler_reference, :hooked_cdecl, args1 )
124
116
  end
125
117
 
126
118
  def process_dxstr(tree)
@@ -231,16 +223,12 @@ module EvalHook
231
223
 
232
224
  receiver = s(:self)
233
225
 
234
- args1 = s(:arglist, s(:lit, @last_method_name), s(:call, nil, :binding, s(:arglist)))
235
- args2 = s(:arglist, hook_handler_reference)
236
-
237
- firstcall = s(:call, receiver, :local_hooked_method, args1)
238
- secondcall = s(:call, firstcall, :set_hook_handler, args2)
239
- thirdcall = s(:call,secondcall,:set_class,s(:arglist, superclass_call_tree))
226
+ firstcall = s(:call, hook_handler_reference,
227
+ :hooked_method,
228
+ s(:arglist, receiver, s(:lit,@last_method_name), superclass_call_tree))
240
229
 
241
230
  # pass the args passed to super
242
- s(:call, thirdcall, :call, process(s(:arglist, *tree[1..-1])))
243
-
231
+ s(:call, firstcall, :call, process(s(:arglist, *tree[1..-1])))
244
232
  end
245
233
 
246
234
  def process_defs(tree)
@@ -254,15 +242,11 @@ module EvalHook
254
242
 
255
243
  receiver = s(:self)
256
244
 
257
- args1 = s(:arglist, s(:lit, @last_method_name), s(:call, nil, :binding, s(:arglist)))
258
- args2 = s(:arglist, hook_handler_reference)
259
-
260
- firstcall = s(:call, receiver, :local_hooked_method, args1)
261
- secondcall = s(:call, firstcall, :set_hook_handler, args2)
262
- thirdcall = s(:call,secondcall,:set_class,s(:arglist, superclass_call_tree))
245
+ firstcall = s(:call, hook_handler_reference,
246
+ :hooked_method,
247
+ s(:arglist, receiver, s(:lit,@last_method_name), superclass_call_tree))
263
248
 
264
249
  # pass the args of the current defn
265
-
266
250
  args = s(:arglist)
267
251
  @last_args[1..-1].each do |arg_sym|
268
252
  if arg_sym.to_s[0] == "*"
@@ -272,7 +256,7 @@ module EvalHook
272
256
  end
273
257
  end
274
258
 
275
- s(:call, thirdcall, :call, args)
259
+ s(:call, firstcall, :call, args)
276
260
  end
277
261
 
278
262
  end
data/lib/evalhook.rb CHANGED
@@ -21,7 +21,6 @@ along with evalhook. if not, see <http://www.gnu.org/licenses/>.
21
21
  require "partialruby"
22
22
  require "evalhook/redirect_helper"
23
23
  require "evalhook/multi_hook_handler"
24
- require "evalhook/hook_handler"
25
24
  require "evalhook/tree_processor"
26
25
 
27
26
  begin
@@ -31,87 +30,33 @@ rescue LoadError
31
30
  $evalmimic_defined = false
32
31
  end
33
32
 
34
-
35
- class Object
36
- def local_hooked_method(mname,_binding)
37
- EvalHook::HookedMethod.new(self,mname,true,_binding)
38
- end
39
- def hooked_method(mname,_binding)
40
- EvalHook::HookedMethod.new(self,mname,false,_binding)
41
- end
42
- end
43
-
44
33
  module EvalHook
45
34
 
46
35
  # used internally
47
- class HookedMethod
48
-
49
- def initialize(recv, m,localcall,_binding)
50
- @recv = recv
51
- @m = m
52
- @localcall = localcall
53
- @_binding = _binding
54
- end
55
-
56
- # used internally
57
- def set_hook_handler(method_handler)
58
- @method_handler = method_handler
59
- self
60
- end
61
-
62
- # used internally
63
- def set_class(klass)
64
- @klass = klass
65
- self
36
+ class FakeEvalHook
37
+ def self.hook_block(*args)
66
38
  end
39
+ end
67
40
 
68
- # used internally
69
- def call(*args)
70
- method_handler = @method_handler
71
- ret = nil
72
-
73
- method_name = @m
74
- if args.length == 0
75
- local_vars = @_binding.eval("local_variables").map(&:to_s)
76
- if local_vars.include? method_name.to_s
77
- return @_binding.eval(method_name.to_s)
78
- end
79
- end
80
-
81
- klass = @klass || @recv.method(@m).owner
82
- recv = @recv
83
-
84
- if method_handler
85
- ret = method_handler.handle_method(klass, recv, method_name )
86
- end
87
-
88
- if ret.kind_of? RedirectHelper::MethodRedirect
89
- klass = ret.klass
90
- method_name = ret.method_name
91
- recv = ret.recv
92
- end
93
-
94
- method_object = nil
95
-
96
- begin
97
- method_object = klass.instance_method(method_name).bind(recv)
98
- rescue
99
- method_object = recv.method(method_name)
100
- end
101
-
102
- if block_given?
103
- method_object.call(*args) do |*x|
104
- yield(*x)
105
- end
106
- else
107
- method_object.call(*args)
108
- end
41
+ class Packet
42
+ def initialize(emulationcode) #:nodoc:
43
+ @emulationcode = emulationcode
109
44
  end
110
- end
111
45
 
112
- # used internally
113
- class FakeEvalHook
114
- def self.hook_block(*args)
46
+ # Executes the code with a given binding, source name (optional) and line (optional)
47
+ #
48
+ # See EvalHook::HookHandler#packet for more info
49
+ #
50
+ # Example:
51
+ #
52
+ # hook_handler = HookHandler.new
53
+ #
54
+ # pack = hook_handler.packet('print "hello world\n"')
55
+ # 10.times do
56
+ # pack.run
57
+ # end
58
+ def run(binding_, name = "(eval)", line = 1)
59
+ eval(@emulationcode, binding_, name, line)
115
60
  end
116
61
  end
117
62
 
@@ -134,57 +79,7 @@ module EvalHook
134
79
  end
135
80
  end
136
81
 
137
- # used internally
138
- class HookCdecl
139
- def initialize(klass, hook_handler)
140
- @klass = klass
141
- @hook_handler = hook_handler
142
- end
143
-
144
- def set_id(const_id)
145
- @const_id = const_id
146
- self
147
- end
148
-
149
- def set_value(value)
150
- klass = @klass
151
- const_id = @const_id
152
-
153
- ret = @hook_handler.handle_cdecl( @klass, @const_id, value )
154
-
155
- if ret then
156
- klass = ret.klass
157
- const_id = ret.const_id
158
- value = ret.value
159
- end
160
-
161
- klass.const_set(const_id, value)
162
- end
163
- end
164
-
165
- # used internally
166
- class HookGasgn
167
- def initialize(global_id, hook_handler)
168
- @global_id = global_id
169
- @hook_handler = hook_handler
170
- end
171
-
172
- def set_value(value)
173
- global_id = @global_id
174
-
175
- ret = @hook_handler.handle_gasgn(@global_id, value)
176
-
177
- if ret then
178
- global_id = ret.global_id
179
- value = ret.value
180
- end
181
-
182
- eval("#{global_id} = value")
183
- end
184
- end
185
-
186
- # used internally
187
- def hooked_gvar(global_id)
82
+ def hooked_gvar(global_id) #:nodoc:
188
83
  ret = handle_gvar(global_id)
189
84
  if ret
190
85
  ret.value
@@ -193,8 +88,7 @@ module EvalHook
193
88
  end
194
89
  end
195
90
 
196
- # used internally
197
- def hooked_const(name)
91
+ def hooked_const(name) #:nodoc:
198
92
  ret = handle_const(name)
199
93
  if ret
200
94
  ret.value
@@ -203,8 +97,7 @@ module EvalHook
203
97
  end
204
98
  end
205
99
 
206
- # used internally
207
- def hooked_colon2(context,name)
100
+ def hooked_colon2(context,name) #:nodoc:
208
101
  ret = handle_colon2(context, name)
209
102
  if ret
210
103
  ret.value
@@ -213,14 +106,86 @@ module EvalHook
213
106
  end
214
107
  end
215
108
 
216
- # used internally
217
- def hooked_cdecl(context)
218
- HookCdecl.new(context,self)
109
+ def hooked_cdecl(klass, const_id, value) #:nodoc:
110
+ ret = handle_cdecl( klass, const_id, value )
111
+
112
+ if ret then
113
+ klass = ret.klass
114
+ const_id = ret.const_id
115
+ value = ret.value
116
+ end
117
+
118
+ klass.const_set(const_id, value)
219
119
  end
220
120
 
221
- # used internally
222
- def hooked_gasgn(global_id)
223
- HookGasgn.new(global_id,self)
121
+ def hooked_gasgn(global_id, value) #:nodoc:
122
+ ret = handle_gasgn(global_id, value)
123
+
124
+ if ret then
125
+ global_id = ret.global_id
126
+ value = ret.value
127
+ end
128
+ eval("#{global_id} = value")
129
+ end
130
+
131
+ class HookedCallValue
132
+ def initialize(value)
133
+ @value = value
134
+ end
135
+ def call(*args)
136
+ @value
137
+ end
138
+ end
139
+
140
+ def hooked_method(receiver, mname, klass = nil) #:nodoc:
141
+ m = nil
142
+ unless klass
143
+ m = receiver.method(mname)
144
+ klass = m.owner
145
+ else
146
+ m = klass.instance_method(mname).bind(receiver)
147
+ end
148
+
149
+ ret = handle_method(klass, receiver, mname )
150
+
151
+ if ret.kind_of? RedirectHelper::MethodRedirect
152
+ klass = ret.klass
153
+ mname = ret.method_name
154
+ receiver = ret.recv
155
+
156
+ begin
157
+ m = ret.klass.instance_method(ret.method_name).bind(ret.recv)
158
+ rescue
159
+ m = ret.recv.method(ret.method_name)
160
+ end
161
+ end
162
+
163
+ m
164
+ end
165
+
166
+ def hooked_variable_method(receiver, mname, _binding) #:nodoc:
167
+ local_vars = _binding.eval("local_variables").map(&:to_s)
168
+ if local_vars.include? mname.to_s
169
+ HookedCallValue.new( _binding.eval(mname.to_s) )
170
+ else
171
+ m = receiver.method(mname)
172
+ klass = m.owner
173
+ ret = handle_method(klass, receiver, mname )
174
+
175
+ if ret.kind_of? RedirectHelper::MethodRedirect
176
+ klass = ret.klass
177
+ mname = ret.method_name
178
+ receiver = ret.recv
179
+
180
+ begin
181
+ m = ret.klass.instance_method(ret.method_name).bind(ret.recv)
182
+ rescue
183
+ m = ret.recv.method(ret.method_name)
184
+ end
185
+ end
186
+
187
+ m
188
+ end
224
189
  end
225
190
 
226
191
  # Overwrite to handle the assignment/creation of global variables. By default do nothing but assign the variable. See examples
@@ -262,31 +227,37 @@ module EvalHook
262
227
  nil
263
228
  end
264
229
 
265
- # used internally
266
- def hooked_super(*args)
267
- hm = caller_obj(2).hooked_method(caller_method(2))
268
- hm.set_class(caller_class(2).superclass)
269
- hm.set_hook_handler(self)
270
-
271
- if block_given?
272
- hm.call(*args) do |*x|
273
- yield(*x)
274
- end
275
- else
276
- hm.call(*args)
277
- end
278
- end
279
-
280
- # used internally
281
- def hooked_xstr(str)
230
+ def hooked_xstr(str) #:nodoc:
282
231
  runstr = handle_xstr(str) || str
283
232
  end
284
233
 
285
234
  def evalhook_i(code, b_ = nil, name = "(eval)", line = 1)
235
+ packet(code).run(b_,name,line)
236
+ end
286
237
 
287
- EvalHook.validate_syntax code
238
+ # Creates a packet of preprocessed ruby code to run it later
239
+ # , useful to execute the same code repeatedly and avoid heavy
240
+ # preprocessing of ruby code all the times.
241
+ #
242
+ # See EvalHook::Packet for more information
243
+ #
244
+ # Example:
245
+ #
246
+ # hook_handler = HookHandler.new
247
+ #
248
+ # pack = hook_handler.packet('print "hello world\n"')
249
+ # 10.times do
250
+ # pack.run
251
+ # end
252
+ def packet(code)
253
+
254
+ tree = nil
288
255
 
289
- tree = RubyParser.new.parse code
256
+ begin
257
+ tree = RubyParser.new.parse code
258
+ rescue
259
+ raise SyntaxError
260
+ end
290
261
 
291
262
  context = PartialRuby::PureRubyContext.new
292
263
 
@@ -294,8 +265,7 @@ module EvalHook
294
265
 
295
266
  emulationcode = context.emul tree
296
267
 
297
- eval emulationcode, b_, name, line
298
-
268
+ EvalHook::Packet.new(emulationcode)
299
269
  end
300
270
 
301
271
  if ($evalmimic_defined)
@@ -9,7 +9,7 @@ describe EvalHook::HookHandler, "hook handler" do
9
9
  begin
10
10
  hh.evalhook("raise '0'",binding, "sourcename", 1)
11
11
  rescue Exception => e
12
- e.backtrace.join.include? ("sourcename").should be == true
12
+ e.backtrace.join.include?("sourcename").should be == true
13
13
  end
14
14
  end
15
15
  end
@@ -7,6 +7,8 @@ class NilClass
7
7
  end
8
8
  end
9
9
 
10
+ $top_level_binding = binding
11
+
10
12
  describe EvalHook::HookHandler, "hook handler defaults" do
11
13
  it "should throw exception when call evalhook with no parameters" do
12
14
  hook_handler = EvalHook::HookHandler.new
@@ -38,7 +40,7 @@ describe EvalHook::HookHandler, "hook handler defaults" do
38
40
  it "should allow reference to constants" do
39
41
  hook_handler = EvalHook::HookHandler.new
40
42
 
41
- CONSTANTTEST = 5
43
+ ::CONSTANTTEST = 5
42
44
  hook_handler.evalhook("CONSTANTTEST", binding).should be == CONSTANTTEST
43
45
  end
44
46
 
@@ -63,7 +65,7 @@ describe EvalHook::HookHandler, "hook handler defaults" do
63
65
  N.new.foo(hook_handler).should be == 5
64
66
  end
65
67
 
66
- class X
68
+ class ::X
67
69
  def foo
68
70
  3
69
71
  end
@@ -71,7 +73,7 @@ describe EvalHook::HookHandler, "hook handler defaults" do
71
73
 
72
74
  it "should allow method calls" do
73
75
  hook_handler = EvalHook::HookHandler.new
74
- hook_handler.evalhook("X.new.foo", binding).should be X.new.foo
76
+ hook_handler.evalhook("X.new.foo", binding).should be(X.new.foo)
75
77
  end
76
78
 
77
79
  it "should capture method calls" do
@@ -123,10 +125,10 @@ describe EvalHook::HookHandler, "hook handler defaults" do
123
125
  end
124
126
 
125
127
 
126
- module B
128
+ module ::B
127
129
 
128
130
  end
129
- module A
131
+ module ::A
130
132
  module B
131
133
  class C
132
134
 
@@ -138,23 +140,23 @@ describe EvalHook::HookHandler, "hook handler defaults" do
138
140
  it "should allow define base_namespace" do
139
141
  hook_handler = EvalHook::HookHandler.new
140
142
 
141
- hook_handler.base_namespace = :A
142
- hook_handler.evalhook("::B", binding).should be == A::B
143
+ hook_handler.base_namespace = ::A
144
+ hook_handler.evalhook("::B", binding).should be == ::A::B
143
145
  end
144
146
 
145
147
  it "should allow define base_namespace (const)" do
146
148
  hook_handler = EvalHook::HookHandler.new
147
149
 
148
- hook_handler.base_namespace = A
149
- hook_handler.evalhook("::B", binding).should be == A::B
150
+ hook_handler.base_namespace = ::A
151
+ hook_handler.evalhook("::B", binding).should be == ::A::B
150
152
  end
151
153
 
152
- class C1
154
+ class ::C1
153
155
  def foo
154
156
  "C1#foo"
155
157
  end
156
158
  end
157
- module A1
159
+ module ::A1
158
160
  class C1
159
161
  def foo
160
162
  "A1::C1#foo"
@@ -165,7 +167,7 @@ describe EvalHook::HookHandler, "hook handler defaults" do
165
167
  it "should allow define base_namespace (class)" do
166
168
  hook_handler = EvalHook::HookHandler.new
167
169
 
168
- hook_handler.base_namespace = A1
170
+ hook_handler.base_namespace = ::A1
169
171
  hook_handler.evalhook("class ::C1
170
172
  def foo
171
173
  'A1::C1#foo at evalhook'
@@ -177,7 +179,7 @@ describe EvalHook::HookHandler, "hook handler defaults" do
177
179
  end
178
180
 
179
181
 
180
- class C2
182
+ class ::C2
181
183
  def foo
182
184
  "C2#foo"
183
185
  end
@@ -201,7 +203,7 @@ describe EvalHook::HookHandler, "hook handler defaults" do
201
203
  C2.new.foo.should be == "::C2#foo at evalhook"
202
204
  end
203
205
 
204
- module A1
206
+ module ::A1
205
207
  module A2
206
208
 
207
209
  end
@@ -211,7 +213,7 @@ describe EvalHook::HookHandler, "hook handler defaults" do
211
213
  it "should allow define base_namespace (3 levels)" do
212
214
  hook_handler = EvalHook::HookHandler.new
213
215
 
214
- hook_handler.base_namespace = A1::A2
216
+ hook_handler.base_namespace = ::A1::A2
215
217
  hook_handler.evalhook("class ::C1
216
218
  def foo
217
219
  'A1::A2::C1#foo at evalhook'
@@ -226,7 +228,7 @@ describe EvalHook::HookHandler, "hook handler defaults" do
226
228
  EvalHook::HookHandler.new.evalhook("class Fixnum::TestClass12345; end", binding)
227
229
  end
228
230
 
229
- module TestInheritedClassMethodError
231
+ module ::TestInheritedClassMethodError
230
232
  class A
231
233
  def self.foo
232
234
  'Foo'
@@ -246,54 +248,54 @@ describe EvalHook::HookHandler, "hook handler defaults" do
246
248
  EvalHook::HookHandler.new.evalhook("module Fixnum::TestModule12345; end", binding)
247
249
  end
248
250
 
249
- module TestModule12347
251
+ module ::TestModule12347
250
252
  end
251
253
 
252
254
  it "should allow assignment of constants nested on modules" do
253
255
  EvalHook::HookHandler.new.evalhook("TestModule12347::A = 9", binding)
254
256
  end
255
257
 
256
- class XTEST44
258
+ class ::XTEST44
257
259
  def foo(a)
258
260
  a+1
259
261
  end
260
262
  end
261
263
  it "should pass arguments on super" do
262
264
  EvalHook::HookHandler.new.evalhook('
263
- class YTEST44 < XTEST44
265
+ class ::YTEST44 < XTEST44
264
266
  def foo(a)
265
267
  super
266
268
  end
267
269
  end
268
- YTEST44.new.foo(9)
270
+ ::YTEST44.new.foo(9)
269
271
  ', binding).should be == 10
270
272
  end
271
273
 
272
274
  it "should pass arguments on super (explicitly)" do
273
275
  EvalHook::HookHandler.new.evalhook('
274
- class YTEST45 < XTEST44
276
+ class ::YTEST45 < XTEST44
275
277
  def foo(a)
276
278
  super(a)
277
279
  end
278
280
  end
279
- YTEST45.new.foo(9)
281
+ ::YTEST45.new.foo(9)
280
282
  ', binding).should be == 10
281
283
  end
282
284
 
283
285
  it "should pass arguments on super with three levels" do
284
286
  EvalHook::HookHandler.new.evalhook('
285
- class YTEST46 < XTEST44
287
+ class ::YTEST46 < XTEST44
286
288
  def foo(a)
287
289
  super(a)
288
290
  end
289
291
  end
290
292
 
291
- class ZTEST46 < YTEST46
293
+ class ::ZTEST46 < ::YTEST46
292
294
  def foo(a)
293
295
  super(a)
294
296
  end
295
297
  end
296
- ZTEST46.new.foo(9)
298
+ ::ZTEST46.new.foo(9)
297
299
  ', binding).should be == 10
298
300
 
299
301
  end
@@ -303,16 +305,16 @@ describe EvalHook::HookHandler, "hook handler defaults" do
303
305
  lambda {
304
306
 
305
307
  EvalHook::HookHandler.new.evalhook('
306
- module MODULETEST48
308
+ module ::MODULETEST48
307
309
  def foo(a)
308
310
  super(a)
309
311
  end
310
312
  end
311
313
 
312
- class XTEST48 < XTEST44
313
- include MODULETEST48
314
+ class ::XTEST48 < XTEST44
315
+ include ::MODULETEST48
314
316
  end
315
- XTEST48.new.foo(9)
317
+ ::XTEST48.new.foo(9)
316
318
  ', binding)
317
319
 
318
320
  }.should raise_error(SecurityError)
@@ -325,7 +327,7 @@ describe EvalHook::HookHandler, "hook handler defaults" do
325
327
 
326
328
  EvalHook::HookHandler.new.evalhook('
327
329
 
328
- class CLASSTEST49
330
+ class ::CLASSTEST49
329
331
  module MODULETEST49
330
332
  def foo(a)
331
333
  super(a)
@@ -333,10 +335,10 @@ describe EvalHook::HookHandler, "hook handler defaults" do
333
335
  end
334
336
  end
335
337
 
336
- class YTEST49 < XTEST44
338
+ class ::YTEST49 < XTEST44
337
339
  include CLASSTEST49::MODULETEST49
338
340
  end
339
- YTEST49.new.foo(9)
341
+ ::YTEST49.new.foo(9)
340
342
  ', binding)
341
343
 
342
344
  }.should raise_error(SecurityError)
@@ -345,18 +347,18 @@ describe EvalHook::HookHandler, "hook handler defaults" do
345
347
 
346
348
  it "should pass arguments on super with no arguments throught three levels" do
347
349
  EvalHook::HookHandler.new.evalhook('
348
- class YTEST50 < XTEST44
350
+ class ::YTEST50 < XTEST44
349
351
  def foo(a)
350
352
  super
351
353
  end
352
354
  end
353
355
 
354
- class ZTEST50 < YTEST50
356
+ class ::ZTEST50 < ::YTEST50
355
357
  def foo(a)
356
358
  super
357
359
  end
358
360
  end
359
- ZTEST50.new.foo(9)
361
+ ::ZTEST50.new.foo(9)
360
362
  ', binding).should be == 10
361
363
 
362
364
  end
@@ -366,16 +368,16 @@ describe EvalHook::HookHandler, "hook handler defaults" do
366
368
  lambda {
367
369
 
368
370
  EvalHook::HookHandler.new.evalhook('
369
- module MODULETEST51
371
+ module ::MODULETEST51
370
372
  def foo(a)
371
373
  super
372
374
  end
373
375
  end
374
376
 
375
- class XTEST51 < XTEST44
376
- include MODULETEST51
377
+ class ::XTEST51 < ::XTEST44
378
+ include ::MODULETEST51
377
379
  end
378
- XTEST51.new.foo(9)
380
+ ::XTEST51.new.foo(9)
379
381
  ', binding)
380
382
 
381
383
  }.should raise_error(SecurityError)
@@ -388,7 +390,7 @@ describe EvalHook::HookHandler, "hook handler defaults" do
388
390
 
389
391
  EvalHook::HookHandler.new.evalhook('
390
392
 
391
- class CLASSTEST52
393
+ class ::CLASSTEST52
392
394
  module MODULETEST52
393
395
  def foo(a)
394
396
  super
@@ -396,10 +398,10 @@ describe EvalHook::HookHandler, "hook handler defaults" do
396
398
  end
397
399
  end
398
400
 
399
- class YTEST52 < XTEST44
400
- include CLASSTEST52::MODULETEST52
401
+ class ::YTEST52 < ::XTEST44
402
+ include ::CLASSTEST52::MODULETEST52
401
403
  end
402
- YTEST52.new.foo(9)
404
+ ::YTEST52.new.foo(9)
403
405
  ', binding)
404
406
 
405
407
  }.should raise_error(SecurityError)
@@ -409,13 +411,13 @@ describe EvalHook::HookHandler, "hook handler defaults" do
409
411
  it "should execute super call from singleton methods" do
410
412
  EvalHook::HookHandler.new.evalhook('
411
413
 
412
- class CLASSTEST53
414
+ class ::CLASSTEST53
413
415
  def bar(a)
414
416
  a+1
415
417
  end
416
418
  end
417
419
 
418
- obj = CLASSTEST53.new
420
+ obj = ::CLASSTEST53.new
419
421
 
420
422
  def obj.bar(a)
421
423
  super(a+1)
@@ -424,5 +426,17 @@ describe EvalHook::HookHandler, "hook handler defaults" do
424
426
  ', binding).should be == 12
425
427
  end
426
428
 
429
+ it "should reference constants in same context" do
430
+ EvalHook::HookHandler.new.evalhook("XCONSTANT=9; XCONSTANT", binding).should be == 9
431
+ end
432
+
433
+ it "should reference classes in same context" do
434
+ EvalHook::HookHandler.new.evalhook("class XCLASS; end; XCLASS", $top_level_binding)
435
+ end
436
+
437
+ it "should reference modules in same context" do
438
+ EvalHook::HookHandler.new.evalhook("module XMODULE; end; XMODULE", $top_level_binding)
439
+ end
440
+
427
441
  end
428
442
 
@@ -76,7 +76,9 @@ describe EvalHook::HookHandler, "hook handler hooks" do
76
76
  it "should intercept constant access" do
77
77
  hh = EvalHook::HookHandler.new
78
78
 
79
- hh.should_receive(:handle_const).with("A")
79
+ hh.should_receive(:handle_const).with("A") {
80
+ RedirectHelper::Value.new(0)
81
+ }
80
82
 
81
83
  hh.evalhook("A")
82
84
  end
@@ -87,8 +89,13 @@ describe EvalHook::HookHandler, "hook handler hooks" do
87
89
  it "should intercept nested constant access" do
88
90
  hh = EvalHook::HookHandler.new
89
91
 
90
- hh.should_receive(:handle_const).once.with("TestModule321")
91
- hh.should_receive(:handle_colon2).once.with(TestModule321,"B")
92
+ hh.should_receive(:handle_const).once.with("TestModule321") {
93
+ RedirectHelper::Value.new(TestModule321)
94
+ }
95
+
96
+ hh.should_receive(:handle_colon2).once.with(TestModule321,"B") {
97
+ RedirectHelper::Value.new(0)
98
+ }
92
99
 
93
100
  hh.evalhook("TestModule321::B")
94
101
  end
@@ -114,19 +121,53 @@ describe EvalHook::HookHandler, "hook handler hooks" do
114
121
  h = EvalHook::HookHandler.new
115
122
 
116
123
  # reference to X for inheritance
117
- h.should_receive(:handle_const).with("X")
124
+ h.should_receive(:handle_const).with("X") {
125
+ RedirectHelper::Value.new(X)
126
+ }
118
127
 
119
128
  # reference to Y
120
- h.should_receive(:handle_const).with("Y")
129
+ h.should_receive(:handle_const).with("Y") {
130
+ RedirectHelper::Value.new(Y)
131
+ }
132
+
133
+
134
+ h.instance_eval {
135
+ @called1 = 0
136
+ @called2 = 0
137
+ @called3 = 0
138
+ }
139
+
140
+ def h.handle_method(klass,recv,method_name)
141
+
142
+ if klass == Y.class
143
+ unless method_name == :new
144
+ raise Rspec::Mocks::MockExpectationError, "#{recv} received :handle_method with unexpected arguments"
145
+ end
146
+ @called1 = @called1 + 1
147
+ elsif klass == Y
148
+ unless method_name == :foo
149
+ raise Rspec::Mocks::MockExpectationError, "#{recv} received :handle_method with unexpected arguments"
150
+ end
151
+ @called2 = @called2 + 1
152
+ elsif klass == X
153
+ unless method_name == :foo
154
+ raise Rspec::Mocks::MockExpectationError, "#{recv} received :handle_method with unexpected arguments"
155
+ end
156
+ @called3 = @called3 + 1
157
+ else
158
+ raise Rspec::Mocks::MockExpectationError, "#{recv} received unexpected :handle_method"
159
+ end
160
+ end
121
161
 
162
+ # rspec doesn't work for ruby1.9 in that way
122
163
  # call to new
123
- h.should_receive(:handle_method).with(Y.class,Y,:new)
164
+ #h.should_receive(:handle_method).with(Y.class,anything(),:new)
124
165
 
125
166
  # first Y#foo call
126
- h.should_receive(:handle_method).with(Y,anything(),:foo)
167
+ #h.should_receive(:handle_method).with(Y,anything(),:foo)
127
168
 
128
169
  # super call
129
- h.should_receive(:handle_method).with(X,anything(),:foo)
170
+ #h.should_receive(:handle_method).with(X,anything(),:foo)
130
171
 
131
172
  h.evalhook('
132
173
 
@@ -138,6 +179,10 @@ describe EvalHook::HookHandler, "hook handler hooks" do
138
179
  Y.new.foo
139
180
 
140
181
  ', binding)
182
+
183
+ h.instance_eval{@called1}.should be == 1
184
+ h.instance_eval{@called2}.should be == 1
185
+ h.instance_eval{@called3}.should be == 1
141
186
  end
142
187
 
143
188
  class X2
@@ -153,19 +198,54 @@ describe EvalHook::HookHandler, "hook handler hooks" do
153
198
  h = EvalHook::HookHandler.new
154
199
 
155
200
  # reference to X for inheritance
156
- h.should_receive(:handle_const).with("X2")
201
+ h.should_receive(:handle_const).with("X2") {
202
+ RedirectHelper::Value.new(X2)
203
+ }
157
204
 
158
205
  # reference to Y
159
- h.should_receive(:handle_const).with("Y2")
206
+ h.should_receive(:handle_const).with("Y2") {
207
+ RedirectHelper::Value.new(Y2)
208
+ }
209
+
210
+ h.instance_eval {
211
+ @called1 = 0
212
+ @called2 = 0
213
+ @called3 = 0
214
+ }
215
+
216
+ def h.handle_method(klass,recv,method_name)
217
+
218
+ if klass == Y2.class
219
+ unless method_name == :new
220
+ raise Rspec::Mocks::MockExpectationError, "#{recv} received :handle_method with unexpected arguments"
221
+ end
222
+ @called1 = @called1 + 1
223
+ super(klass,recv,method_name)
224
+ elsif klass == Y2
225
+ unless method_name == :foo
226
+ raise Rspec::Mocks::MockExpectationError, "#{recv} received :handle_method with unexpected arguments"
227
+ end
228
+ @called2 = @called2 + 1
229
+ super(klass,recv,method_name)
230
+ elsif klass == X2
231
+ unless method_name == :foo
232
+ raise Rspec::Mocks::MockExpectationError, "#{recv} received :handle_method with unexpected arguments"
233
+ end
234
+ @called3 = @called3 + 1
235
+ super(klass,recv,method_name)
236
+ else
237
+ raise Rspec::Mocks::MockExpectationError, "#{recv} received unexpected :handle_method"
238
+ end
239
+ end
160
240
 
161
241
  # call to new
162
- h.should_receive(:handle_method).with(Y2.class,Y2,:new)
242
+ #h.should_receive(:handle_method).with(Y2.class,Y2,:new)
163
243
 
164
244
  # first Y#foo call
165
- h.should_receive(:handle_method).with(Y2,anything(),:foo)
245
+ #h.should_receive(:handle_method).with(Y2,anything(),:foo)
166
246
 
167
247
  # super call
168
- h.should_receive(:handle_method).with(X2,anything(),:foo)
248
+ #h.should_receive(:handle_method).with(X2,anything(),:foo)
169
249
 
170
250
  h.evalhook('
171
251
 
@@ -177,6 +257,11 @@ describe EvalHook::HookHandler, "hook handler hooks" do
177
257
  Y2.new.foo(9)
178
258
 
179
259
  ', binding).should be == 10
260
+
261
+ h.instance_eval{@called1}.should be == 1
262
+ h.instance_eval{@called2}.should be == 1
263
+ h.instance_eval{@called3}.should be == 1
264
+
180
265
  end
181
266
 
182
267
  class Y9 < X2
@@ -186,22 +271,32 @@ describe EvalHook::HookHandler, "hook handler hooks" do
186
271
  h = EvalHook::HookHandler.new
187
272
 
188
273
  # reference to X for inheritance
189
- h.should_receive(:handle_const).with("X2")
274
+ h.should_receive(:handle_const).with("X2"){
275
+ RedirectHelper::Value.new(X2)
276
+ }
190
277
 
191
278
  # reference to Y
192
- h.should_receive(:handle_const).with("Y2")
193
-
194
- # call to new
195
- h.should_receive(:handle_method).with(Y2.class,Y2,:new)
196
-
197
- # first Y#foo call
198
- h.should_receive(:handle_method).with(Y2,anything(),:foo)
199
-
200
- # call Y#bar
201
- h.should_receive(:handle_method).with(Y2,anything(),:bar)
202
-
203
- # super call
204
- h.should_receive(:handle_method).with(X2,anything(),:foo)
279
+ h.should_receive(:handle_const).with("Y2") {
280
+ RedirectHelper::Value.new(Y2)
281
+ }
282
+
283
+ h.instance_eval {
284
+ @called1 = 0
285
+ @called2 = 0
286
+ @called3 = 0
287
+ }
288
+
289
+ def h.handle_method(klass,recv,mname)
290
+ if recv == Y2 and mname == :new
291
+ @called1 = 1
292
+ end
293
+ if mname == :foo
294
+ @called2 = @called2 + 1
295
+ end
296
+ if klass == Y2 and mname == :bar
297
+ @called3 = 1
298
+ end
299
+ end
205
300
 
206
301
  h.evalhook('
207
302
 
@@ -217,5 +312,9 @@ describe EvalHook::HookHandler, "hook handler hooks" do
217
312
 
218
313
  ', binding).should be == 10
219
314
 
315
+ h.instance_eval{@called1}.should be == 1
316
+ h.instance_eval{@called2}.should be == 2
317
+ h.instance_eval{@called3}.should be == 1
318
+
220
319
  end
221
320
  end
@@ -3,7 +3,7 @@ require "evalhook"
3
3
 
4
4
  describe EvalHook::MultiHookHandler, "multiple hook handler redirect" do
5
5
 
6
- class X
6
+ class ::X
7
7
  def self.foo
8
8
 
9
9
  end
@@ -19,7 +19,7 @@ describe EvalHook::MultiHookHandler, "multiple hook handler" do
19
19
  end
20
20
  end
21
21
 
22
- class X
22
+ class ::X
23
23
  def foo
24
24
 
25
25
  end
@@ -27,7 +27,7 @@ describe EvalHook::MultiHookHandler, "multiple hook handler" do
27
27
 
28
28
  it "should allow method calls" do
29
29
  hook_handler = EvalHook::HookHandler.new
30
- hook_handler.evalhook("X.new.foo").should be X.new.foo
30
+ hook_handler.evalhook("X.new.foo").should be(X.new.foo)
31
31
  end
32
32
 
33
33
  it "should capture method calls" do
@@ -0,0 +1,23 @@
1
+ require "rubygems"
2
+ require "evalhook"
3
+
4
+ describe EvalHook::HookHandler, "hook handler" do
5
+
6
+ it "should return package of code" do
7
+ hh = EvalHook::HookHandler.new
8
+
9
+ lambda {
10
+ hh.packet("0")
11
+ }.should_not raise_error
12
+
13
+ end
14
+
15
+ it "should execute package of code" do
16
+ hh = EvalHook::HookHandler.new
17
+
18
+ lambda {
19
+ hh.packet("0").run(binding).should be == 0
20
+ }.should_not raise_error
21
+
22
+ end
23
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: evalhook
3
3
  version: !ruby/object:Gem::Version
4
- hash: 13
4
+ hash: 11
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 4
9
- - 1
10
- version: 0.4.1
8
+ - 5
9
+ - 0
10
+ version: 0.5.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Dario Seminara
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-06-09 00:00:00 -03:00
18
+ date: 2011-06-20 00:00:00 -03:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -66,7 +66,6 @@ files:
66
66
  - examples/example2.rb
67
67
  - lib/evalhook/multi_hook_handler.rb
68
68
  - lib/evalhook/tree_processor.rb
69
- - lib/evalhook/hook_handler.rb
70
69
  - lib/evalhook/redirect_helper.rb
71
70
  - lib/evalhook.rb
72
71
  - spec/hook_handler/hook_handler_arguments_spec.rb
@@ -75,6 +74,7 @@ files:
75
74
  - spec/hook_handler/hook_handler_multiple_spec.rb
76
75
  - spec/hook_handler/hook_handler_visitor_spec.rb
77
76
  - spec/hook_handler/hook_handler_ruby_spec.rb
77
+ - spec/hook_handler/hook_handler_package_spec.rb
78
78
  - spec/hook_handler/hook_handler_defaults_spec.rb
79
79
  - spec/validation/hook_handler_spec.rb
80
80
  - LICENSE
@@ -1,35 +0,0 @@
1
- =begin
2
-
3
- This file is part of the evalhook project, http://github.com/tario/evalhook
4
-
5
- Copyright (c) 2010 Roberto Dario Seminara <robertodarioseminara@gmail.com>
6
-
7
- evalhook is free software: you can redistribute it and/or modify
8
- it under the terms of the gnu general public license as published by
9
- the free software foundation, either version 3 of the license, or
10
- (at your option) any later version.
11
-
12
- evalhook is distributed in the hope that it will be useful,
13
- but without any warranty; without even the implied warranty of
14
- merchantability or fitness for a particular purpose. see the
15
- gnu general public license for more details.
16
-
17
- you should have received a copy of the gnu general public license
18
- along with evalhook. if not, see <http://www.gnu.org/licenses/>.
19
-
20
- =end
21
- require "ruby_parser"
22
-
23
- module EvalHook
24
- def self.validate_syntax(code)
25
- begin
26
- RubyParser.new.parse(code)
27
- rescue
28
- raise SyntaxError
29
- end
30
- true
31
- end
32
-
33
- class HookHandler
34
- end
35
- end