lib/appmap/hook/method.rb in appmap-0.54.0 vs lib/appmap/hook/method.rb in appmap-0.54.1

- old
+ new

@@ -16,10 +16,12 @@ # Grab the definition of Time.now here, to avoid interfering # with the method we're hooking. TIME_NOW = Time.method(:now) private_constant :TIME_NOW + ARRAY_OF_EMPTY_HASH = [{}.freeze].freeze + def initialize(hook_package, hook_class, hook_method) @hook_package = hook_package @hook_class = hook_class @hook_method = hook_method @@ -43,45 +45,51 @@ 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 = nil - hook_class.instance_eval do - hook_method_def = Proc.new do |*args, &block| - instance_method = hook_method.bind(self).to_proc - call_instance_method = -> { instance_method.call(*args, &block) } + hook_method_def = Proc.new do |*args, &block| + instance_method = hook_method.bind(self).to_proc + call_instance_method = -> { + # https://github.com/applandinc/appmap-ruby/issues/153 + if Util.ruby_minor_version >= 2.7 && args == ARRAY_OF_EMPTY_HASH && hook_method.arity == 1 + instance_method.call({}, &block) + else + instance_method.call(*args, &block) + end + } - # 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 + # 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 - reentrant = Thread.current[HOOK_DISABLE_KEY] - disabled_by_shallow_flag = \ - -> { hook_package&.shallow? && AppMap.tracing.last_package_for_current_thread == hook_package } + reentrant = Thread.current[HOOK_DISABLE_KEY] + 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 + enabled = true if AppMap.tracing.enabled? && !reentrant && !disabled_by_shallow_flag.call - return call_instance_method.call unless enabled + return call_instance_method.call unless enabled - call_event, start_time = with_disabled_hook.call do - before_hook.call(self, defined_class, args) + 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 + rescue + exception = $ERROR_INFO + raise + ensure + with_disabled_hook.call do + after_hook.call(self, call_event, start_time, return_value, exception) if call_event end - return_value = nil - exception = nil - begin - return_value = call_instance_method.call - rescue - exception = $ERROR_INFO - raise - ensure - with_disabled_hook.call do - after_hook.call(self, call_event, start_time, return_value, exception) if call_event - end - end end end + hook_method_def = hook_method_def.ruby2_keywords if hook_method_def.respond_to?(:ruby2_keywords) + hook_class.define_method_with_arity(hook_method.name, hook_method.arity, hook_method_def) end protected