module LightIO::Monkey

Constants

IO_PATCH_CONSTANTS
THREAD_PATCH_CONSTANTS

Public Class Methods

patch_all!() click to toggle source
# File lib/lightio/monkey.rb, line 12
def patch_all!
  # Fix https://github.com/socketry/lightio/issues/7
  begin
    require 'ffi'
  rescue LoadError
    nil
  end

  patch_thread!
  patch_io!
  patch_kernel!
  nil
end
patch_io!() click to toggle source
# File lib/lightio/monkey.rb, line 51
def patch_io!
  require 'socket'
  IO_PATCH_CONSTANTS.each {|klass_name| patch!(klass_name)}
  patch_method!(Process, :spawn, LightIO.method(:spawn).to_proc)
  nil
end
patch_kernel!() click to toggle source
# File lib/lightio/monkey.rb, line 65
def patch_kernel!
  patch_kernel_method!(:sleep, LightIO.method(:sleep))
  patch_kernel_method!(:select, LightIO::Library::IO.method(:select))
  patch_kernel_method!(:open, LightIO::Library::File.method(:open).to_proc)
  patch_kernel_method!(:spawn, LightIO.method(:spawn).to_proc)
  patch_kernel_method!(:`, LightIO.method(:`).to_proc)
  patch_kernel_method!(:system, LightIO.method(:system).to_proc)
  %w{gets readline readlines}.each do |method|
    patch_kernel_method!(method.to_sym, LightIO.method(method.to_sym).to_proc)
  end
  nil
end
patch_thread!() click to toggle source
# File lib/lightio/monkey.rb, line 37
def patch_thread!
  require 'thread'
  THREAD_PATCH_CONSTANTS.each {|klass_name| patch!(klass_name)}
  patch_method!(Timeout, :timeout, LightIO::Timeout.method(:timeout))
  nil
end
patched?(obj) click to toggle source
# File lib/lightio/monkey.rb, line 33
def patched?(obj)
  patched.key?(obj) && !patched[obj]&.empty?
end
unpatch_all!() click to toggle source
# File lib/lightio/monkey.rb, line 26
def unpatch_all!
  unpatch_thread!
  unpatch_io!
  unpatch_kernel!
  nil
end
unpatch_io!() click to toggle source
# File lib/lightio/monkey.rb, line 58
def unpatch_io!
  require 'socket'
  IO_PATCH_CONSTANTS.each {|klass_name| unpatch!(klass_name)}
  unpatch_method!(Process, :spawn)
  nil
end
unpatch_kernel!() click to toggle source
# File lib/lightio/monkey.rb, line 78
def unpatch_kernel!
  unpatch_kernel_method!(:sleep)
  unpatch_kernel_method!(:select)
  unpatch_kernel_method!(:open)
  unpatch_kernel_method!(:spawn)
  unpatch_kernel_method!(:`)
  unpatch_kernel_method!(:system)
  %w{gets readline readlines}.each do |method|
    unpatch_kernel_method!(method.to_sym, LightIO.method(method.to_sym).to_proc)
  end
  nil
end
unpatch_thread!() click to toggle source
# File lib/lightio/monkey.rb, line 44
def unpatch_thread!
  require 'thread'
  THREAD_PATCH_CONSTANTS.each {|klass_name| unpatch!(klass_name)}
  unpatch_method!(Timeout, :timeout)
  nil
end

Private Class Methods

find_class_methods_module(klass_name) click to toggle source
# File lib/lightio/monkey.rb, line 128
def find_class_methods_module(klass_name)
  LightIO::Module.const_get("#{klass_name}::ClassMethods", false)
rescue NameError
  nil
end
find_monkey_patch_class_methods(klass_name) click to toggle source
# File lib/lightio/monkey.rb, line 134
def find_monkey_patch_class_methods(klass_name)
  find_class_methods_module(klass_name).instance_methods
end
patch!(klass_name) click to toggle source
# File lib/lightio/monkey.rb, line 92
def patch!(klass_name)
  klass = Object.const_get(klass_name)
  raise PatchError, "already patched constant #{klass}" if patched?(klass)
  patched[klass] = {}
  class_methods_module = find_class_methods_module(klass_name)
  methods = class_methods_module && find_monkey_patch_class_methods(klass_name)
  return unless class_methods_module && methods
  methods.each do |method_name|
    method = class_methods_module.instance_method(method_name)
    patch_method!(klass, method_name, method)
  end
rescue
  patched.delete(klass)
  raise
end
patch_instance_method!(const, method, patched_method) click to toggle source
# File lib/lightio/monkey.rb, line 168
def patch_instance_method!(const, method, patched_method)
  raise PatchError, "already patched method #{const}.#{method}" if patched_instance_method?(const, method)
  patched_instance_methods(const)[method] = patched_method
  const.send(:define_method, method, patched_method)
  nil
end
patch_kernel_method!(method_name, method) click to toggle source
# File lib/lightio/monkey.rb, line 118
def patch_kernel_method!(method_name, method)
  patch_method!(Kernel, method_name, method)
  patch_instance_method!(Kernel, method_name, method)
end
patch_method!(const, method, patched_method) click to toggle source
# File lib/lightio/monkey.rb, line 146
def patch_method!(const, method, patched_method)
  raise PatchError, "already patched method #{const}.#{method}" if patched_method?(const, method)
  patched_methods(const)[method] = patched_method
  const.send(:define_singleton_method, method, patched_method)
  nil
end
patched() click to toggle source
# File lib/lightio/monkey.rb, line 182
def patched
  @patched ||= {}
end
patched_instance_method?(obj, method) click to toggle source
# File lib/lightio/monkey.rb, line 160
def patched_instance_method?(obj, method)
  patched_instance_methods(obj).key?(method)
end
patched_instance_methods(const) click to toggle source
# File lib/lightio/monkey.rb, line 164
def patched_instance_methods(const)
  (patched[:instance_methods] ||= {})[const] ||= {}
end
patched_method?(obj, method) click to toggle source
# File lib/lightio/monkey.rb, line 138
def patched_method?(obj, method)
  patched?(obj) && patched[obj].key?(method)
end
patched_methods(const) click to toggle source
# File lib/lightio/monkey.rb, line 142
def patched_methods(const)
  patched[const] ||= {}
end
unpatch!(klass_name) click to toggle source
# File lib/lightio/monkey.rb, line 108
def unpatch!(klass_name)
  klass = Object.const_get(klass_name)
  raise PatchError, "can't find patched constant #{klass}" unless patched?(klass)
  unpatch_method!(klass, :new)
  find_monkey_patch_class_methods(klass_name).each do |method_name|
    unpatch_method!(klass, method_name)
  end
  patched.delete(klass)
end
unpatch_instance_method!(const, method) click to toggle source
# File lib/lightio/monkey.rb, line 175
def unpatch_instance_method!(const, method)
  raise PatchError, "can't find patched method #{const}.#{method}" unless patched_instance_method?(const, method)
  origin_method = patched_instance_methods(const).delete(method)
  const.send(:define_method, method, origin_method)
  nil
end
unpatch_kernel_method!(method_name) click to toggle source
# File lib/lightio/monkey.rb, line 123
def unpatch_kernel_method!(method_name)
  unpatch_method!(Kernel, method_name)
  unpatch_instance_method!(Kernel, method_name)
end
unpatch_method!(const, method) click to toggle source
# File lib/lightio/monkey.rb, line 153
def unpatch_method!(const, method)
  raise PatchError, "can't find patched method #{const}.#{method}" unless patched_method?(const, method)
  origin_method = patched_methods(const).delete(method)
  const.send(:define_singleton_method, method, origin_method)
  nil
end