From 7e3c2e8e1dce43efc19c4da3748981bd14ed2eb1 Mon Sep 17 00:00:00 2001 From: kares Date: Tue, 10 Jan 2012 17:24:12 +0100 Subject: [PATCH] JS === for wrapped object (now unbound) methods; a better optimization_level writer and adding a reader as well --- lib/rhino/context.rb | 14 ++++++++++-- lib/rhino/ruby.rb | 35 +++++++++++++++--------------- lib/rhino/ruby/attribute_access.rb | 2 +- lib/rhino/ruby/default_access.rb | 2 +- 4 files changed, 31 insertions(+), 22 deletions(-) diff --git a/lib/rhino/context.rb b/lib/rhino/context.rb index fa558e7..b17cc73 100644 --- a/lib/rhino/context.rb +++ b/lib/rhino/context.rb @@ -125,12 +125,22 @@ module Rhino @factory.instruction_limit = limit end + def optimization_level + @native.getOptimizationLevel + end + # Set the optimization level that this context will use. This is sometimes necessary # in Rhino, if the bytecode size of the compiled javascript exceeds the 64KB limit. # By using the -1 optimization level, you tell Rhino to run in interpretative mode, # taking a hit to performance but escaping the Java bytecode limit. def optimization_level=(level) - @native.setOptimizationLevel(level) + if @native.class.isValidOptimizationLevel(level) + @native.setOptimizationLevel(level) + level + else + @native.setOptimizationLevel(0) + nil + end end # Get the JS interpreter version. @@ -191,7 +201,7 @@ module Rhino begin str = @io.read(length) rescue StandardError => e - raise java.io.IOException.new, "Failed reading from ruby IO object" + raise java.io.IOException.new("failed reading from ruby IO object") end if str.nil? return -1 diff --git a/lib/rhino/ruby.rb b/lib/rhino/ruby.rb index cb78f22..42067fa 100644 --- a/lib/rhino/ruby.rb +++ b/lib/rhino/ruby.rb @@ -46,7 +46,7 @@ module Rhino end def self.access - @@access ||= Rhino::Ruby::DefaultAccess + @@access ||= Ruby::DefaultAccess end private @@ -63,7 +63,7 @@ module Rhino # wrap an arbitrary (ruby) object def self.wrap(object, scope = nil) - Rhino::Ruby.cache(object) { new(object, scope) } + Ruby.cache(object) { new(object, scope) } end TYPE = JS::TopLevel::Builtins::Object @@ -97,22 +97,14 @@ module Rhino end class Function < JS::BaseFunction + include JS::Wrapper include Scriptable # wrap a callable (Method/Proc) def self.wrap(callable, scope = nil) - # NOTE: === seems 'correctly' impossible without having multiple - # instances of the 'same' wrapper function (even with an UnboundMethod), - # suppose : - # - # var foo1 = one.foo; - # var foo2 = two.foo; - # foo1 === foo2; // expect 'same' reference - # foo1(); foo2(); // one ref but different implicit 'this' objects - # - # returns different instances as obj1.method(:foo) != obj2.method(:foo) - # - new(callable, scope) + # NOTE: include JS::Wrapper & Ruby.cache(callable.to_s) guarantees === + # in Rhino although if a bind Method gets passed it might get confusing + Ruby.cache(callable.to_s) { new(callable, scope) } end def initialize(callable, scope) @@ -166,10 +158,15 @@ module Rhino end rb_args = Rhino.args_to_ruby(args) begin - result = @callable.call(*rb_args) + callable = + if @callable.is_a?(UnboundMethod) + @callable.bind(Rhino.to_ruby(this)) + else + @callable + end + result = callable.call(*rb_args) rescue => e - # ... correct wrapping thus it's try { } catch (e) works in JS : - raise Rhino::Ruby.wrap_error(e) + raise Ruby.wrap_error(e) # thus `try { } catch (e)` works in JS end Rhino.to_javascript(result, scope) end @@ -181,7 +178,9 @@ module Rhino # wrap a ruby class as as constructor function def self.wrap(klass, scope = nil) - new(klass, scope) + # NOTE: caching here seems redundant since we implemented JS::Wrapper + # and a ruby class objects seems always the same ref under JRuby ... + Ruby.cache(klass) { new(klass, scope) } end def initialize(klass, scope) diff --git a/lib/rhino/ruby/attribute_access.rb b/lib/rhino/ruby/attribute_access.rb index 0a63f78..7b5e6b3 100644 --- a/lib/rhino/ruby/attribute_access.rb +++ b/lib/rhino/ruby/attribute_access.rb @@ -25,7 +25,7 @@ module Rhino raise Rhino::Ruby.wrap_error(e) end else - return Function.wrap(method) + return Function.wrap(method.unbind) end elsif object.respond_to?("#{name}=") return nil # it does have the property but is non readable diff --git a/lib/rhino/ruby/default_access.rb b/lib/rhino/ruby/default_access.rb index f9a4e55..344d012 100644 --- a/lib/rhino/ruby/default_access.rb +++ b/lib/rhino/ruby/default_access.rb @@ -24,7 +24,7 @@ module Rhino raise Rhino::Ruby.wrap_error(e) end else - return Function.wrap(method) + return Function.wrap(method.unbind) end elsif object.respond_to?("#{name}=") return nil