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:
parent
0e2274a685
commit
8e6b51cfb4
2 changed files with 66 additions and 5 deletions
|
@ -162,7 +162,8 @@ module Rhino
|
||||||
|
|
||||||
# override int BaseFunction#getLength()
|
# override int BaseFunction#getLength()
|
||||||
def getLength
|
def getLength
|
||||||
@callable.arity
|
arity = @callable.arity
|
||||||
|
arity < 0 ? 0 : arity # -1 for `lambda { 42 }`
|
||||||
end
|
end
|
||||||
|
|
||||||
# #deprecated int BaseFunction#getArity()
|
# #deprecated int BaseFunction#getArity()
|
||||||
|
@ -187,7 +188,16 @@ module Rhino
|
||||||
# override Object BaseFunction#call(Context context, Scriptable scope,
|
# override Object BaseFunction#call(Context context, Scriptable scope,
|
||||||
# Scriptable thisObj, Object[] args)
|
# Scriptable thisObj, Object[] args)
|
||||||
def call(context, scope, this, 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
|
begin
|
||||||
result = @callable.call(*rb_args)
|
result = @callable.call(*rb_args)
|
||||||
rescue => e
|
rescue => e
|
||||||
|
@ -218,7 +228,8 @@ module Rhino
|
||||||
|
|
||||||
# override int BaseFunction#getLength()
|
# override int BaseFunction#getLength()
|
||||||
def getLength
|
def getLength
|
||||||
@klass.instance_method(:initialize).arity
|
arity = @klass.instance_method(:initialize).arity
|
||||||
|
arity < 0 ? 0 : arity # -1 for `initialize(*args)`
|
||||||
end
|
end
|
||||||
|
|
||||||
# override boolean Scriptable#hasInstance(Scriptable instance);
|
# override boolean Scriptable#hasInstance(Scriptable instance);
|
||||||
|
@ -231,7 +242,7 @@ module Rhino
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.cache(key)
|
def self.cache(key)
|
||||||
fetch(key) || write(key, yield)
|
fetch(key) || store(key, yield)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -245,7 +256,7 @@ module Rhino
|
||||||
ref ? ref.get : nil
|
ref ? ref.get : nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.write(key, value)
|
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)) if @@cache
|
||||||
value
|
value
|
||||||
end
|
end
|
||||||
|
|
|
@ -255,6 +255,38 @@ describe Rhino::Ruby::Function do
|
||||||
context = nil; scope = nil; this = nil; args = [].to_java
|
context = nil; scope = nil; this = nil; args = [].to_java
|
||||||
rb_function.call(context, scope, this, args).should be_a(Rhino::JS::NativeArray)
|
rb_function.call(context, scope, this, args).should be_a(Rhino::JS::NativeArray)
|
||||||
end
|
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
|
it "returns correct arity and length" do
|
||||||
klass = Class.new(Object) do
|
klass = Class.new(Object) do
|
||||||
|
@ -267,6 +299,15 @@ describe Rhino::Ruby::Function do
|
||||||
rb_function.getLength.should == 2
|
rb_function.getLength.should == 2
|
||||||
end
|
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
|
describe 'with scope' do
|
||||||
|
|
||||||
before do
|
before do
|
||||||
|
@ -326,6 +367,15 @@ describe Rhino::Ruby::Constructor do
|
||||||
rb_new.getLength.should == 0
|
rb_new.getLength.should == 0
|
||||||
end
|
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
|
describe 'with scope' do
|
||||||
|
|
||||||
before do
|
before do
|
||||||
|
|
Loading…
Reference in a new issue