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