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

make sure Ruby function wrapper has (Ruby) #call semantics

just like JavaScript functions exposed into the Ruby side have
This commit is contained in:
kares 2012-09-08 15:39:57 +02:00
parent 0a38ab3f0a
commit 82134aecf2
4 changed files with 55 additions and 32 deletions

View file

@ -176,7 +176,11 @@ 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(*args)
unless args.first.is_a?(JS::Context)
return super # assume a Ruby #call
end
_, scope, this, args = *args # Java Function#call dispatch
args = args.to_a # java.lang.Object[] -> Array args = args.to_a # java.lang.Object[] -> Array
# JS function style : # JS function style :
if ( arity = @callable.arity ) != -1 # (a1, *a).arity == -2 if ( arity = @callable.arity ) != -1 # (a1, *a).arity == -2

View file

@ -172,13 +172,23 @@ describe Rhino::Ruby::Function do
end end
it_should_behave_like Rhino::Ruby::Scriptable it_should_behave_like Rhino::Ruby::Scriptable
it "is callable as a function" do it "is (JavaScript) callable as a function" do
rb_function = Rhino::Ruby::Function.wrap method = 'foo'.method(:to_s) rb_function = Rhino::Ruby::Function.wrap 'foo'.method(:upcase)
context = nil; scope = nil; this = nil; args = nil this = nil; args = nil
rb_function.call(context, scope, this, args).should == 'foo' rb_function.call(context, scope, this, args).should == 'FOO'
end end
it 'is Ruby callable' do
rb_function = Rhino::Ruby::Function.wrap 'foo'.method(:upcase)
rb_function.call.should == 'FOO'
end
it 'is Ruby callable passing arguments' do
rb_function = Rhino::Ruby::Function.wrap 'foo'.method(:scan)
rb_function.call('o').should == ['o', 'o']
end
it "args get converted before delegating a ruby function call" do it "args get converted before delegating a ruby function call" do
klass = Class.new(Object) do klass = Class.new(Object) do
def foo(array) def foo(array)
@ -186,7 +196,7 @@ describe Rhino::Ruby::Function do
end end
end end
rb_function = Rhino::Ruby::Function.wrap method = klass.new.method(:foo) rb_function = Rhino::Ruby::Function.wrap method = klass.new.method(:foo)
context = nil; scope = nil; this = nil this = nil
args = [ '1'.to_java, java.lang.String.new('2') ].to_java args = [ '1'.to_java, java.lang.String.new('2') ].to_java
args = [ Rhino::JS::NativeArray.new(args) ].to_java args = [ Rhino::JS::NativeArray.new(args) ].to_java
rb_function.call(context, scope, this, args).should be(true) rb_function.call(context, scope, this, args).should be(true)
@ -199,7 +209,7 @@ describe Rhino::Ruby::Function do
end end
end end
rb_function = Rhino::Ruby::Function.wrap method = klass.new.method(:foo) rb_function = Rhino::Ruby::Function.wrap method = klass.new.method(:foo)
context = nil; scope = nil; this = nil; args = [].to_java 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
@ -209,8 +219,8 @@ describe Rhino::Ruby::Function do
a1 a1
end end
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 this = nil
args = [ 1.to_java, 2.to_java, 3.to_java ].to_java; js_return = 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 lambda { js_return = rb_function.call(context, scope, this, args) }.should_not raise_error
@ -224,7 +234,7 @@ describe Rhino::Ruby::Function do
end end
end end
rb_function = Rhino::Ruby::Function.wrap klass.new.method(:foo) rb_function = Rhino::Ruby::Function.wrap klass.new.method(:foo)
context = nil; scope = nil; this = nil this = nil
args = [ 1.to_java ].to_java; js_return = nil args = [ 1.to_java ].to_java; js_return = nil
lambda { js_return = rb_function.call(context, scope, this, args) }.should_not raise_error lambda { js_return = rb_function.call(context, scope, this, args) }.should_not raise_error
@ -242,7 +252,7 @@ describe Rhino::Ruby::Function do
end end
end end
rb_function = Rhino::Ruby::Function.wrap klass.new.method(:foo) rb_function = Rhino::Ruby::Function.wrap klass.new.method(:foo)
context = nil; scope = nil; this = nil this = nil
args = [ ].to_java; js_return = nil args = [ ].to_java; js_return = nil
lambda { js_return = rb_function.call(context, scope, this, args) }.should_not raise_error lambda { js_return = rb_function.call(context, scope, this, args) }.should_not raise_error
@ -292,22 +302,11 @@ describe Rhino::Ruby::Function do
describe 'with scope' do describe 'with scope' do
before do before { context_factory.enterContext(context) }
factory = Rhino::JS::ContextFactory.new after { Rhino::JS::Context.exit }
context = nil
factory.call do |ctx|
context = ctx
@scope = context.initStandardObjects(nil, false)
end
factory.enterContext(context)
end
after do
Rhino::JS::Context.exit
end
it "sets up correct prototype" do it "sets up correct prototype" do
rb_function = Rhino::Ruby::Function.wrap 'foo'.method(:concat), @scope rb_function = Rhino::Ruby::Function.wrap 'foo'.method(:concat), scope
rb_function.getPrototype.should_not be(nil) rb_function.getPrototype.should_not be(nil)
rb_function.getPrototype.should be_a(Rhino::JS::Function) rb_function.getPrototype.should be_a(Rhino::JS::Function)
end end
@ -338,7 +337,7 @@ describe Rhino::Ruby::Constructor do
it "is callable as a function" do it "is callable as a function" do
rb_new = Rhino::Ruby::Constructor.wrap Foo rb_new = Rhino::Ruby::Constructor.wrap Foo
context = nil; scope = nil; this = nil; args = nil this = nil; args = nil
rb_new.call(context, scope, this, args).should be_a(Rhino::Ruby::Object) rb_new.call(context, scope, this, args).should be_a(Rhino::Ruby::Object)
rb_new.call(context, scope, this, args).unwrap.should be_a(Foo) rb_new.call(context, scope, this, args).unwrap.should be_a(Foo)
end end
@ -398,7 +397,7 @@ describe Rhino::Ruby::Exception do
end end
end end
rb_function = Rhino::Ruby::Function.wrap klass.new.method(:foo) rb_function = Rhino::Ruby::Function.wrap klass.new.method(:foo)
context = nil; scope = nil; this = nil; args = [ 42.to_java ].to_java this = nil; args = [ 42.to_java ].to_java
begin begin
rb_function.call(context, scope, this, args) rb_function.call(context, scope, this, args)
rescue java.lang.Exception => e rescue java.lang.Exception => e

View file

@ -168,12 +168,12 @@ describe Rhino::To do
it "converts procs and methods into native functions" do it "converts procs and methods into native functions" do
Rhino.to_javascript(lambda {|lhs,rhs| lhs * rhs}).tap do |f| Rhino.to_javascript(lambda {|lhs,rhs| lhs * rhs}).tap do |f|
f.should be_kind_of(Rhino::JS::Function) f.should be_kind_of(Rhino::JS::Function)
f.call(nil, nil, nil, [7, 6].to_java).should be(42) f.call(context, scope, nil, [7, 6].to_java).should be(42)
end end
Rhino.to_javascript("foo,bar,baz".method(:split)).tap do |f| Rhino.to_javascript("foo,bar,baz".method(:split)).tap do |f|
f.should be_kind_of(Rhino::JS::Function) f.should be_kind_of(Rhino::JS::Function)
Rhino.to_ruby(f.call(nil, nil, nil, [','].to_java)).should == ['foo', 'bar', 'baz'] Rhino.to_ruby(f.call(context, scope, nil, [','].to_java)).should == ['foo', 'bar', 'baz']
end end
end end

View file

@ -10,6 +10,26 @@ module RedJS
Error = Rhino::JSError Error = Rhino::JSError
end end
RSpec.configure do |config| module Rhino
config.filter_run_excluding :compat => /(0.5.0)|(0.6.0)/ module SpecHelpers
def context_factory
@context_factory ||= Rhino::JS::ContextFactory.new
end
def context
@context || context_factory.call { |ctx| @context = ctx }
@context
end
def scope
context.initStandardObjects(nil, false)
end
end
end
RSpec.configure do |config|
config.filter_run_excluding :compat => /(0.5.0)|(0.6.0)/ # RedJS
config.include Rhino::SpecHelpers
end end