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
-
#__rubybreaker_obj ⇒ Object
This method returns the original object.
-
#__rubybreaker_type ⇒ Object
This method returns the type gathered so far for this object.
-
#__rubybreaker_wrap_level ⇒ Object
This method computes the wrap level of any given wrapped object.
-
#initialize(obj) ⇒ ObjectWrapper
constructor
A new instance of ObjectWrapper.
-
#method_missing(mname, *args, &blk) ⇒ Object
This method missing method redirects all other method calls.
-
#respond_to?(mname) ⇒ Boolean
Only behave differently if it’s looking for
WRAPPED_INDICATOR
method.
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_obj ⇒ Object
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_type ⇒ Object
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_level ⇒ Object
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
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 |