1
0
Fork 0
mirror of https://github.com/rubyjs/therubyrhino synced 2023-03-27 23:21:34 -04:00

handle nagative < -1 arrities; a better getClassName; a useful == for wrapper objects

This commit is contained in:
kares 2012-01-06 16:45:20 +01:00
parent 8e6b51cfb4
commit cb2016334e
2 changed files with 62 additions and 23 deletions

View file

@ -101,7 +101,7 @@ module Rhino
# abstract String Scriptable#getClassName();
def getClassName
@ruby.class.name
@ruby.class.to_s # to_s handles 'nameless' classes as well
end
def toString
@ -112,6 +112,7 @@ module Rhino
def equivalentValues(other) # JS == operator
other.is_a?(Object) && unwrap.eql?(other.unwrap)
end
alias_method :'==', :equivalentValues
# override Scriptable Scriptable#getPrototype();
def getPrototype
@ -131,7 +132,7 @@ module Rhino
include Scriptable
# wrap a callable (Method/Proc)
def self.wrap(callable, scope = nil)
def self.wrap(callable, scope = nil)
# NOTE: === seems 'correctly' impossible without having multiple
# instances of the 'same' wrapper function (even with an UnboundMethod),
# suppose :
@ -163,7 +164,7 @@ module Rhino
# override int BaseFunction#getLength()
def getLength
arity = @callable.arity
arity < 0 ? 0 : arity # -1 for `lambda { 42 }`
arity < 0 ? ( arity + 1 ).abs : arity
end
# #deprecated int BaseFunction#getArity()
@ -184,16 +185,18 @@ module Rhino
# JS == means they might be bind to different objects :
unwrap.to_s == other.unwrap.to_s # "#<Method: Foo#bar>"
end
alias_method :'==', :equivalentValues
# override Object BaseFunction#call(Context context, Scriptable scope,
# Scriptable thisObj, Object[] args)
def call(context, scope, this, args)
args = args.to_a # java.lang.Object[] -> Array
# JS function style :
if (arity = @callable.arity) >= 0
if args.size > arity # omit 'redundant' arguments
if ( arity = @callable.arity ) != -1 # (a1, *a).arity == -2
if arity > -1 && args.size > arity # omit 'redundant' arguments
args = args.slice(0, arity)
elsif arity > args.size # fill 'missing' arguments
elsif arity > args.size || # fill 'missing' arguments
( arity < -1 && (arity = arity.abs - 1) > args.size )
(arity - args.size).times { args.push(nil) }
end
end
@ -229,7 +232,7 @@ module Rhino
# override int BaseFunction#getLength()
def getLength
arity = @klass.instance_method(:initialize).arity
arity < 0 ? 0 : arity # -1 for `initialize(*args)`
arity < 0 ? ( arity + 1 ).abs : arity
end
# override boolean Scriptable#hasInstance(Scriptable instance);
@ -242,6 +245,7 @@ module Rhino
end
def self.cache(key)
return yield unless @@cache
fetch(key) || store(key, yield)
end
@ -252,12 +256,12 @@ module Rhino
@@cache = java.util.WeakHashMap.new
def self.fetch(key)
ref = @@cache && @@cache.get(key)
ref = @@cache.get(key)
ref ? ref.get : nil
end
def self.store(key, value)
@@cache.put(key, java.lang.ref.WeakReference.new(value)) if @@cache
@@cache.put(key, java.lang.ref.WeakReference.new(value))
value
end

View file

@ -146,17 +146,17 @@ describe Rhino::Ruby::Object do
rb_object.put('nonExistingAttr', start, 42)
end
it "getIds include ruby class methods" do
rb_object = Rhino::Ruby::Object.wrap UII.new
[ 'anAttr0', 'the_attr_1' ].each do |attr|
rb_object.getIds.to_a.should include(attr)
end
rb_object.getIds.to_a.should_not include('an_attr_2')
[ 'theMethod0', 'a_method1', 'the_method_2' ].each do |method|
rb_object.getIds.to_a.should include(method)
end
end
# it "getIds include ruby class methods" do
# rb_object = Rhino::Ruby::Object.wrap UII.new
#
# [ 'anAttr0', 'the_attr_1' ].each do |attr|
# rb_object.getIds.to_a.should include(attr)
# end
# rb_object.getIds.to_a.should_not include('an_attr_2')
# [ 'theMethod0', 'a_method1', 'the_method_2' ].each do |method|
# rb_object.getIds.to_a.should include(method)
# end
# end
it "getIds include ruby instance methods" do
rb_object = Rhino::Ruby::Object.wrap object = UII.new
@ -276,7 +276,7 @@ describe Rhino::Ruby::Function do
[ a1, a2 ]
end
end
rb_function = Rhino::Ruby::Function.wrap method = klass.new.method(:foo)
rb_function = Rhino::Ruby::Function.wrap klass.new.method(:foo)
context = nil; scope = nil; this = nil
args = [ 1.to_java ].to_java; js_return = nil
@ -288,6 +288,32 @@ describe Rhino::Ruby::Function do
js_return.toArray.to_a.should == [ nil, nil ]
end
it "fills missing args when delegating call that ends with varargs" do
klass = Class.new(Object) do
def foo(a1, a2, *args)
[ a1, a2, args ].flatten
end
end
rb_function = Rhino::Ruby::Function.wrap klass.new.method(:foo)
context = nil; scope = nil; this = nil
args = [ ].to_java; js_return = nil
lambda { js_return = rb_function.call(context, scope, this, args) }.should_not raise_error
js_return.toArray.to_a.should == [ nil, nil ]
args = [ 1.to_java ].to_java; js_return = nil
lambda { js_return = rb_function.call(context, scope, this, args) }.should_not raise_error
js_return.toArray.to_a.should == [ 1, nil ]
args = [ 1.to_java, 2.to_java ].to_java; js_return = nil
lambda { js_return = rb_function.call(context, scope, this, args) }.should_not raise_error
js_return.toArray.to_a.should == [ 1, 2 ]
args = [ 1.to_java, 2.to_java, 3.to_java ].to_java; js_return = nil
lambda { js_return = rb_function.call(context, scope, this, args) }.should_not raise_error
js_return.toArray.to_a.should == [ 1, 2, 3 ]
end
it "returns correct arity and length" do
klass = Class.new(Object) do
def foo(a1, a2)
@ -299,7 +325,7 @@ describe Rhino::Ruby::Function do
rb_function.getLength.should == 2
end
it "reports arity and length of 0 for varargs" do
it "reports arity and length of 0 for varargs only method" do
klass = Class.new(Object) do
def foo(*args); args; end
end
@ -308,6 +334,15 @@ describe Rhino::Ruby::Function do
rb_function.getLength.should == 0
end
it "reports correct arity and length for ending varargs" do
klass = Class.new(Object) do
def foo(a1, *args); [ a1, args ]; end
end
rb_function = Rhino::Ruby::Function.wrap klass.new.method(:foo)
rb_function.getArity.should == 1
rb_function.getLength.should == 1
end
describe 'with scope' do
before do
@ -392,7 +427,7 @@ describe Rhino::Ruby::Constructor do
Rhino::JS::Context.exit
end
it "sets up correct prototype" do
it "has a function prototype" do
rb_function = Rhino::Ruby::Function.wrap 'foo'.method(:concat), @scope
rb_function.getPrototype.should_not be(nil)
rb_function.getPrototype.should be_a(Rhino::JS::Function)