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

JS style function call argument slicing/filling + fn.length fix to be always >= 0

This commit is contained in:
kares 2011-12-14 13:22:46 +01:00
parent 0e2274a685
commit 8e6b51cfb4
2 changed files with 66 additions and 5 deletions

View file

@ -162,7 +162,8 @@ module Rhino
# override int BaseFunction#getLength()
def getLength
@callable.arity
arity = @callable.arity
arity < 0 ? 0 : arity # -1 for `lambda { 42 }`
end
# #deprecated int BaseFunction#getArity()
@ -187,7 +188,16 @@ module Rhino
# override Object BaseFunction#call(Context context, Scriptable scope,
# Scriptable thisObj, Object[] args)
def call(context, scope, this, args)
rb_args = Rhino.args_to_ruby(args.to_a)
args = args.to_a # java.lang.Object[] -> Array
# JS function style :
if (arity = @callable.arity) >= 0
if args.size > arity # omit 'redundant' arguments
args = args.slice(0, arity)
elsif arity > args.size # fill 'missing' arguments
(arity - args.size).times { args.push(nil) }
end
end
rb_args = Rhino.args_to_ruby(args)
begin
result = @callable.call(*rb_args)
rescue => e
@ -218,7 +228,8 @@ module Rhino
# override int BaseFunction#getLength()
def getLength
@klass.instance_method(:initialize).arity
arity = @klass.instance_method(:initialize).arity
arity < 0 ? 0 : arity # -1 for `initialize(*args)`
end
# override boolean Scriptable#hasInstance(Scriptable instance);
@ -231,7 +242,7 @@ module Rhino
end
def self.cache(key)
fetch(key) || write(key, yield)
fetch(key) || store(key, yield)
end
private
@ -245,7 +256,7 @@ module Rhino
ref ? ref.get : nil
end
def self.write(key, value)
def self.store(key, value)
@@cache.put(key, java.lang.ref.WeakReference.new(value)) if @@cache
value
end

View file

@ -255,6 +255,38 @@ describe Rhino::Ruby::Function do
context = nil; scope = nil; this = nil; args = [].to_java
rb_function.call(context, scope, this, args).should be_a(Rhino::JS::NativeArray)
end
it "slices redundant args when delegating call" do
klass = Class.new(Object) do
def foo(a1)
a1
end
end
rb_function = Rhino::Ruby::Function.wrap method = klass.new.method(:foo)
context = nil; scope = nil; this = nil
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.should == 1
end
it "fills missing args when delegating call" do
klass = Class.new(Object) do
def foo(a1, a2)
[ a1, a2 ]
end
end
rb_function = Rhino::Ruby::Function.wrap method = klass.new.method(:foo)
context = nil; scope = nil; this = 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 = [ ].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 ]
end
it "returns correct arity and length" do
klass = Class.new(Object) do
@ -267,6 +299,15 @@ describe Rhino::Ruby::Function do
rb_function.getLength.should == 2
end
it "reports arity and length of 0 for varargs" do
klass = Class.new(Object) do
def foo(*args); args; end
end
rb_function = Rhino::Ruby::Function.wrap klass.new.method(:foo)
rb_function.getArity.should == 0
rb_function.getLength.should == 0
end
describe 'with scope' do
before do
@ -326,6 +367,15 @@ describe Rhino::Ruby::Constructor do
rb_new.getLength.should == 0
end
it "reports arity and length of 0 for varargs" do
klass = Class.new do
def initialize(*args); args; end
end
rb_new = Rhino::Ruby::Constructor.wrap klass
rb_new.getArity.should == 0
rb_new.getLength.should == 0
end
describe 'with scope' do
before do