lib/v8/access.rb in therubyracer-0.7.4 vs lib/v8/access.rb in therubyracer-0.7.5

- old
+ new

@@ -23,17 +23,11 @@ @classes.delete(cls.object_id) self[cls] end else template(cls).tap do |t| - t.InstanceTemplate().SetNamedPropertyHandler( - NamedPropertyGetter, - NamedPropertySetter, - nil, - nil, - NamedPropertyEnumerator - ) + Access.setuptemplate(t.InstanceTemplate()) if cls.name && cls.name =~ /(::)?(\w+?)$/ t.SetClassName(C::String::NewSymbol("rb::" + $2)) else t.SetClassName("Ruby") end @@ -54,19 +48,30 @@ end end def self.rubyobject @rubyobject ||= C::ObjectTemplate::New().tap do |t| - t.SetNamedPropertyHandler( - NamedPropertyGetter, - NamedPropertySetter, - nil, - nil, - NamedPropertyEnumerator - ) + setuptemplate(t) end end + + def self.setuptemplate(t) + t.SetNamedPropertyHandler( + NamedPropertyGetter, + NamedPropertySetter, + nil, + nil, + NamedPropertyEnumerator + ) + t.SetIndexedPropertyHandler( + IndexedPropertyGetter, + IndexedPropertySetter, + nil, + nil, + IndexedPropertyEnumerator + ) + end end class Constructors < Access def self.[](cls) Access[cls].tap do |template| @@ -77,73 +82,121 @@ else rbargs = [] for i in 0..arguments.Length() - 1 rbargs << To.rb(arguments[i]) end - instance = V8::Function.rubycall(cls.method(:new), *rbargs) + instance = V8::Function.rubysend(cls, :new, *rbargs) wrap = C::External::New(instance) end arguments.This().tap do |this| this.SetHiddenValue(C::String::NewSymbol("TheRubyRacer::RubyObject"), wrap) end end end end end + module AccessibleMethods + def accessible_methods(obj) + obj.public_methods(false).map {|m| m.to_s}.to_set.tap do |methods| + ancestors = obj.class.ancestors.dup + while ancestor = ancestors.shift + break if ancestor == ::Object + methods.merge(ancestor.public_instance_methods(false).map {|m| m.to_s}) + end + methods.reject! {|m| m == "[]" || m == "[]="} + end + end + end + class NamedPropertyGetter + extend AccessibleMethods def self.call(property, info) name = To.rb(property) obj = To.rb(info.This()) - perl_name = To.perl_case(name) - methods = obj.public_methods(false).map {|m| m.to_s} - method_name = if methods.include?(name) - name - elsif methods.include?(perl_name) - perl_name - end - if method_name - method = obj.method(method_name) + methods = accessible_methods(obj) + if methods.include?(name) + method = obj.method(name) if method.arity == 0 Function.rubycall(method) else To.v8(method) end + elsif obj.respond_to?(:[]) + Function.rubysend(obj, :[], name) else C::Empty end end end class NamedPropertySetter + extend AccessibleMethods def self.call(property, value, info) obj = To.rb(info.This()) - setter = To.rb(property) + "=" - camel_name = To.camel_case(setter) - perl_name = To.perl_case(setter) - methods = obj.public_methods(false).map {|m| m.to_s} - if methods.include?(perl_name) - obj.send(perl_name, To.rb(value)) - elsif methods.include?(camel_name) - obj.send(camel_name, To.rb(value)) + name = To.rb(property) + setter = name + "=" + methods = accessible_methods(obj) + if methods.include?(setter) + Function.rubysend(obj, setter, To.rb(value)) + value + elsif obj.respond_to?(:[]=) + Function.rubysend(obj, :[]=, name, To.rb(value)) + value else - C::Empty + C::Empty end end end class NamedPropertyEnumerator + extend AccessibleMethods def self.call(info) obj = To.rb(info.This()) - camel_methods = obj.public_methods(false).inject(Set.new) do |set, name| - set.tap do - set << To.camel_case(name) - end - end - names = V8::C::Array::New(camel_methods.length) - camel_methods.each_with_index do |name, i| + methods = accessible_methods(obj).reject! {|m| m.to_s =~ /=$/} + names = V8::C::Array::New(methods.length) + methods.each_with_index do |name, i| names.Set(i, C::String::New(name)) end return names + end + end + + class IndexedPropertyGetter + def self.call(index, info) + obj = To.rb(info.This()) + if obj.respond_to?(:[]) + Function.rubysend(obj, :[], index) + else + C::Empty + end + end + end + + class IndexedPropertySetter + def self.call(index, value, info) + obj = To.rb(info.This()) + if obj.respond_to?(:[]=) + Function.rubysend(obj, :[]=, index, To.rb(value)) + value + else + C::Empty + end + end + end + + class IndexedPropertyEnumerator + def self.call(info) + obj = To.rb(info.This()) + if obj.respond_to?(:length) + C::Array::New(obj.length).tap do |indices| + for index in 0..obj.length - 1 + rputs "index: #{index}" + indices.Set(index,index) + end + end + else + C::Array::New() + end end end end \ No newline at end of file