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