class RubyBreaker::Runtime::ObjectWrapper

This class represents the shell object that wraps around another object. Note that it is a subclass of BasicObject to keep it really concise. It also redirects the following methods (from BasicObject):

!, !=, ==, equal?, eql?, __id__, object_id, send, __send__, instance_eval, instance_exec

Public Class Methods

new(obj) click to toggle source
# File lib/rubybreaker/runtime/object_wrapper.rb, line 22
def initialize(obj)
  @__rubybreaker_obj = obj
  nom_type = TypeDefs::NominalType.new(obj.class)
  @__rubybreaker_type = TypeDefs::FusionType.new(nom_type,[])
end

Public Instance Methods

__rubybreaker_obj() click to toggle source

This method returns the original object.

# File lib/rubybreaker/runtime/object_wrapper.rb, line 29
def __rubybreaker_obj()
  return @__rubybreaker_obj
end
__rubybreaker_type() click to toggle source

This method returns the type gathered so far for this object.

# File lib/rubybreaker/runtime/object_wrapper.rb, line 34
def __rubybreaker_type()
  return @__rubybreaker_type
end
method_missing(mname,*args,&blk) click to toggle source

This method missing method redirects all other method calls.

# File lib/rubybreaker/runtime/object_wrapper.rb, line 88
def method_missing(mname,*args,&blk)
  if GLOBAL_MONITOR_SWITCH.switch

    # Be safe and turn the switch off
    GLOBAL_MONITOR_SWITCH.turn_off
    ::RubyBreaker.log("Object wrapper method_missing for #{mname} started")

    # Must handle send method specially (do not track them)
    if [:"__send__", :send].include?(mname)
      mname = args[0]
      args = args[1..-1]
    end
    @__rubybreaker_type.add_meth(mname)

    # If self is not subject to breaking, then no need to send the
    # wrapped arguments. This part is super IMPORTANT. Otherwise many
    # native code stuff won't work including Numeric#+.
    obj = self.__rubybreaker_obj
    is_obj_mod = (obj.class == ::Class or obj.class == ::Module)
    mod = is_obj_mod ? Runtime.eigen_class(obj) : obj.class

    # # There are certain methods that should not take wrapped
    # # argument(s) whatsoever. Use WRAP_BLACKLIST for these.
    # if !MONITOR_MAP[mod] && WRAP_BLACKLIST[mod] &&
    #    WRAP_BLACKLIST[mod].include?(mname)
    #   args.map! do |arg|
    #     if arg.respond_to?(WRAPPED_INDICATOR)
    #       arg.__rubybreaker_obj
    #     else
    #       arg
    #     end
    #   end
    # end

    # Turn on the global switch again
    GLOBAL_MONITOR_SWITCH.turn_on

    # And call the original method 
    retval =  @__rubybreaker_obj.send(mname, *args, &blk)

    # # No need to wrap the object again...if it's wrapped already
    # unless retval.respond_to?(WRAPPED_INDICATOR)
    #   retval = ObjectWrapper.new(retval)
    # end
  else
    ::RubyBreaker.log("Object wrapper method_missing for #{mname} started")
    retval = @__rubybreaker_obj.send(mname, *args, &blk)
  end
  ::RubyBreaker.log("Object wrapper method_missing for #{mname} ended")
  return retval
end
respond_to?(mname) click to toggle source

Only behave differently if it’s looking for WRAPPED_INDICATOR method

# File lib/rubybreaker/runtime/object_wrapper.rb, line 76
def respond_to?(mname)
  return true if mname.to_sym == WRAPPED_INDICATOR
  return @__rubybreaker_obj.respond_to?(mname)
end