lib/appmap/hook/method.rb in appmap-0.73.0 vs lib/appmap/hook/method.rb in appmap-0.74.0

- old
+ new

@@ -67,32 +67,28 @@ hook_method = self.hook_method before_hook = self.method(:before_hook) after_hook = self.method(:after_hook) with_disabled_hook = self.method(:with_disabled_hook) - hook_method_def = Proc.new do |*args, &block| - is_array_containing_empty_hash = ->(obj) { - obj.is_a?(Array) && obj.length == 1 && obj[0].is_a?(Hash) && obj[0].size == 0 - } + is_array_containing_empty_hash = ->(obj) { + obj.is_a?(Array) && obj.length == 1 && obj[0].is_a?(Hash) && obj[0].size == 0 + } - call_instance_method = -> { - # https://github.com/applandinc/appmap-ruby/issues/153 - if NEW_RUBY && is_array_containing_empty_hash.(args) && hook_method.arity == 1 - if NEW_RUBY - hook_method.bind_call(self, {}, &block) - else - hook_method.bind(self).call({}, &block) - end + call_instance_method = lambda do |receiver, args, &block| + # https://github.com/applandinc/appmap-ruby/issues/153 + if NEW_RUBY && is_array_containing_empty_hash.(args) && hook_method.arity == 1 + hook_method.bind_call(receiver, {}, &block) + else + if NEW_RUBY + hook_method.bind_call(receiver, *args, &block) else - if NEW_RUBY - hook_method.bind_call(self, *args, &block) - else - hook_method.bind(self).call(*args, &block) - end + hook_method.bind(receiver).call(*args, &block) end - } + end + end + hook_method_def = Proc.new do |*args, &block| # We may not have gotten the class for the method during # initialization (e.g. for a singleton method on an embedded # struct), so make sure we have it now. defined_class, = Hook.qualify_method_name(hook_method) unless defined_class @@ -100,19 +96,21 @@ disabled_by_shallow_flag = \ -> { hook_package&.shallow? && AppMap.tracing.last_package_for_current_thread == hook_package } enabled = true if AppMap.tracing.enabled? && !reentrant && !disabled_by_shallow_flag.call - return call_instance_method.call unless enabled + enabled = false if %i[instance_eval instance_exec].member?(hook_method.name) && args.empty? + return call_instance_method.call(self, args, &block) unless enabled + call_event, start_time = with_disabled_hook.call do before_hook.call(self, defined_class, args) end return_value = nil exception = nil begin - return_value = call_instance_method.call + return_value = call_instance_method.call(self, args, &block) rescue exception = $ERROR_INFO raise ensure with_disabled_hook.call do @@ -123,11 +121,21 @@ hook_method_def = hook_method_def.ruby2_keywords if hook_method_def.respond_to?(:ruby2_keywords) hook_method_parameters = hook_method.parameters.dup.freeze SIGNATURES[[ hook_class, hook_method.name ]] = hook_method_parameters - hook_class.ancestors.first.tap do |cls| - cls.define_method_with_arity(hook_method.name, hook_method.arity, hook_method_def) + # irb(main):001:0> Kernel.public_instance_method(:system) + # (irb):1:in `public_instance_method': method `system' for module `Kernel' is private (NameError) + if hook_class == Kernel + hook_class.define_method_with_arity(hook_method.name, hook_method.arity, hook_method_def) + else + hook_class.ancestors.find { |cls| cls.method_defined?(hook_method.name, false) }.tap do |cls| + if cls + cls.define_method_with_arity(hook_method.name, hook_method.arity, hook_method_def) + else + warn "#{hook_method.name} not found on #{hook_class}" + end + end end end protected