From 82134aecf2d2d8fd56576614397cf6b9b3d009cb Mon Sep 17 00:00:00 2001 From: kares Date: Sat, 8 Sep 2012 15:39:57 +0200 Subject: [PATCH] make sure Ruby function wrapper has (Ruby) #call semantics just like JavaScript functions exposed into the Ruby side have --- lib/rhino/ruby.rb | 6 ++++- spec/rhino/ruby_spec.rb | 53 ++++++++++++++++++------------------- spec/rhino/wormhole_spec.rb | 4 +-- spec/spec_helper.rb | 24 +++++++++++++++-- 4 files changed, 55 insertions(+), 32 deletions(-) diff --git a/lib/rhino/ruby.rb b/lib/rhino/ruby.rb index 689a902..2b29ea6 100644 --- a/lib/rhino/ruby.rb +++ b/lib/rhino/ruby.rb @@ -176,7 +176,11 @@ module Rhino # override Object BaseFunction#call(Context context, Scriptable scope, # 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 # JS function style : if ( arity = @callable.arity ) != -1 # (a1, *a).arity == -2 diff --git a/spec/rhino/ruby_spec.rb b/spec/rhino/ruby_spec.rb index 056a212..eb43ac2 100644 --- a/spec/rhino/ruby_spec.rb +++ b/spec/rhino/ruby_spec.rb @@ -172,13 +172,23 @@ describe Rhino::Ruby::Function do end it_should_behave_like Rhino::Ruby::Scriptable - - it "is callable as a function" do - rb_function = Rhino::Ruby::Function.wrap method = 'foo'.method(:to_s) - context = nil; scope = nil; this = nil; args = nil - rb_function.call(context, scope, this, args).should == 'foo' + + it "is (JavaScript) callable as a function" do + rb_function = Rhino::Ruby::Function.wrap 'foo'.method(:upcase) + this = nil; args = nil + rb_function.call(context, scope, this, args).should == 'FOO' 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 klass = Class.new(Object) do def foo(array) @@ -186,7 +196,7 @@ describe Rhino::Ruby::Function do end end 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 = [ Rhino::JS::NativeArray.new(args) ].to_java rb_function.call(context, scope, this, args).should be(true) @@ -199,7 +209,7 @@ describe Rhino::Ruby::Function do end end 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) end @@ -209,8 +219,8 @@ describe Rhino::Ruby::Function do a1 end end - rb_function = Rhino::Ruby::Function.wrap method = klass.new.method(:foo) - context = nil; scope = nil; this = nil + rb_function = Rhino::Ruby::Function.wrap klass.new.method(:foo) + 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 @@ -224,7 +234,7 @@ describe Rhino::Ruby::Function do end end 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 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 rb_function = Rhino::Ruby::Function.wrap klass.new.method(:foo) - context = nil; scope = nil; this = nil + this = nil args = [ ].to_java; js_return = nil 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 - before do - factory = Rhino::JS::ContextFactory.new - 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 + before { context_factory.enterContext(context) } + after { Rhino::JS::Context.exit } 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 be_a(Rhino::JS::Function) end @@ -338,7 +337,7 @@ describe Rhino::Ruby::Constructor do it "is callable as a function" do 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).unwrap.should be_a(Foo) end @@ -398,7 +397,7 @@ describe Rhino::Ruby::Exception do end end 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 rb_function.call(context, scope, this, args) rescue java.lang.Exception => e diff --git a/spec/rhino/wormhole_spec.rb b/spec/rhino/wormhole_spec.rb index 0c0689b..b3e7df5 100644 --- a/spec/rhino/wormhole_spec.rb +++ b/spec/rhino/wormhole_spec.rb @@ -168,12 +168,12 @@ describe Rhino::To do it "converts procs and methods into native functions" do Rhino.to_javascript(lambda {|lhs,rhs| lhs * rhs}).tap do |f| 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 Rhino.to_javascript("foo,bar,baz".method(:split)).tap do |f| 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 diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 1e5994e..57b1951 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -10,6 +10,26 @@ module RedJS Error = Rhino::JSError end -RSpec.configure do |config| - config.filter_run_excluding :compat => /(0.5.0)|(0.6.0)/ +module Rhino + 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