Class: RubyBreaker::Runtime::ObjectWrapper

Inherits:
BasicObject
Defined in:
lib/rubybreaker/runtime/object_wrapper.rb

Overview

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

Instance Method Summary collapse

Constructor Details

#initialize(obj) ⇒ ObjectWrapper

Returns a new instance of ObjectWrapper.



22
23
24
25
26
# 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

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(mname, *args, &blk) ⇒ Object

This method missing method redirects all other method calls.



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# 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

Instance Method Details

#__rubybreaker_objObject

This method returns the original object.



29
30
31
# File 'lib/rubybreaker/runtime/object_wrapper.rb', line 29

def __rubybreaker_obj()
  return @__rubybreaker_obj
end

#__rubybreaker_typeObject

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



34
35
36
# File 'lib/rubybreaker/runtime/object_wrapper.rb', line 34

def __rubybreaker_type()
  return @__rubybreaker_type
end

#__rubybreaker_wrap_levelObject

This method computes the wrap level of any given wrapped object. In theory, this should always be 1.

Used for internal debugging purpose only



42
43
44
45
46
47
48
# File 'lib/rubybreaker/runtime/object_wrapper.rb', line 42

def __rubybreaker_wrap_level() #:nodoc:
  val = 1
  if @__rubybreaker_obj.respond_to?(WRAPPED_INDICATOR)
    val += @__rubybreaker_obj.__rubybreaker_wrap_level
  end
  return val
end

#respond_to?(mname) ⇒ Boolean

Only behave differently if it’s looking for WRAPPED_INDICATOR method

Returns:

  • (Boolean)


76
77
78
79
# 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