evalhook 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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