From 21434b05dfa5f27d5cee31770065051e240baefb Mon Sep 17 00:00:00 2001 From: kares Date: Tue, 13 Dec 2011 13:43:07 +0100 Subject: [PATCH] extract and reuse Scriptable get/has/put implementation across all ruby wrappers ... --- lib/rhino/ruby.rb | 149 ++++++++++++++++++++++++---------------------- 1 file changed, 78 insertions(+), 71 deletions(-) diff --git a/lib/rhino/ruby.rb b/lib/rhino/ruby.rb index 9c5415f..da71b45 100644 --- a/lib/rhino/ruby.rb +++ b/lib/rhino/ruby.rb @@ -2,9 +2,71 @@ module Rhino module Ruby + # shared JS::Scriptable implementation + module Scriptable + + # override Object Scriptable#get(String name, Scriptable start); + # override Object Scriptable#get(int index, Scriptable start); + def get(name, start) + if name.is_a?(String) + if unwrap.respond_to?(name) + method = unwrap.method(name) + if method.arity == 0 && # check if it is an attr_reader + ( unwrap.respond_to?("#{name}=") || unwrap.instance_variables.include?("@#{name}") ) + begin + return Rhino.to_javascript(method.call, self) + rescue => e + raise Function.wrap_error(e) + end + else + return Function.wrap(unwrap.method(name)) + end + end + end + super + end + + # override boolean Scriptable#has(String name, Scriptable start); + # override boolean Scriptable#has(int index, Scriptable start); + def has(name, start) + if name.is_a?(String) + if unwrap.respond_to?(name) || + unwrap.respond_to?("#{name}=") # might have a writer but no reader + return true + end + end + super + end + + # override void Scriptable#put(String name, Scriptable start, Object value); + # override void Scriptable#put(int index, Scriptable start, Object value); + def put(name, start, value) + if name.is_a?(String) + if unwrap.respond_to?(set_name = "#{name}=") + return unwrap.send(set_name, Rhino.to_ruby(value)) + end + end + super + end + + # override Object[] Scriptable#getIds(); + def getIds + ids = [] + unwrap.public_methods(false).each do |name| + name = name[0...-1] if name[-1, 1] == '=' # 'foo=' ... 'foo' + name = name.to_java # java.lang.String + ids << name unless ids.include?(name) + end + super.each { |id| ids.unshift(id) } + ids.to_java + end + + end + class Object < JS::ScriptableObject include JS::Wrapper - + include Scriptable + # wrap an arbitrary (ruby) object def self.wrap(object, scope = nil) Rhino::Ruby.cache(object) { new(object, scope) } @@ -13,10 +75,7 @@ module Rhino def initialize(object, scope) super() @ruby = object - if scope - JS::ScriptRuntime.setObjectProtoAndParent(self, scope) - setPrototype(JS::ScriptableObject.getObjectPrototype(scope)) unless getPrototype - end + @scope = scope end # abstract Object Wrapper#unwrap(); @@ -33,71 +92,28 @@ module Rhino "[ruby #{getClassName}]" # [object User] end - # override Object Scriptable#get(String name, Scriptable start); - # override Object Scriptable#get(int index, Scriptable start); - def get(name, start) - if name.is_a?(String) - if @ruby.respond_to?(name) - method = @ruby.method(name) - if method.arity == 0 && # check if it is an attr_reader - ( @ruby.respond_to?("#{name}=") || @ruby.instance_variables.include?("@#{name}") ) - begin - return Rhino.to_javascript(method.call, self) - rescue => e - raise Function.wrap_error(e) - end - else - return Function.wrap(@ruby.method(name)) - end - end - end - super - end - - # override boolean Scriptable#has(String name, Scriptable start); - # override boolean Scriptable#has(int index, Scriptable start); - def has(name, start) - if name.is_a?(String) - if @ruby.respond_to?(name) || - @ruby.respond_to?("#{name}=") # might have a writer but no reader - return true - end - end - super - end - - # override void Scriptable#put(String name, Scriptable start, Object value); - # override void Scriptable#put(int index, Scriptable start, Object value); - def put(name, start, value) - if name.is_a?(String) - if @ruby.respond_to?(set_name = "#{name}=") - return @ruby.send(set_name, Rhino.to_ruby(value)) - end - end - super - end - - # override Object[] Scriptable#getIds(); - def getIds - ids = [] - @ruby.public_methods(false).each do |name| - name = name[0...-1] if name[-1, 1] == '=' # 'foo=' ... 'foo' - name = name.to_java # java.lang.String - ids << name unless ids.include?(name) - end - super.each { |id| ids.unshift(id) } - ids.to_java - end - # protected Object ScriptableObject#equivalentValues(Object value) def equivalentValues(other) # JS == operator other.is_a?(Object) && unwrap.eql?(other.unwrap) end + # override Scriptable Scriptable#getPrototype(); + def getPrototype + # TODO needs to be revisited to that ruby.constructor works ... + if ! (proto = super) && @scope + JS::ScriptRuntime.setObjectProtoAndParent(self, @scope) + unless proto = super + setPrototype(proto = JS::ScriptableObject.getObjectPrototype(@scope)) + end + end + proto + end + end class Function < JS::BaseFunction - + include Scriptable + # wrap a callable (Method/Proc) def self.wrap(callable, scope = nil) Rhino::Ruby.cache(callable) { new(callable, scope) } @@ -141,15 +157,6 @@ module Rhino unwrap.to_s == other.unwrap.to_s # "#" end - # override Object ScriptableObject#getPrototype() - def getPrototype - unless proto = super - #proto = ScriptableObject.getFunctionPrototype(getParentScope) - #setPrototype(proto) - end - proto - end - # override Object BaseFunction#call(Context context, Scriptable scope, # Scriptable thisObj, Object[] args) def call(context, scope, this, args)