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

add native object wrapper for easy access to js objects from ruby

This commit is contained in:
Charles Lowell 2009-10-06 08:52:45 -05:00
parent 20493a6c48
commit 33ef76f85e
6 changed files with 143 additions and 15 deletions

View file

@ -6,4 +6,5 @@ module Rhino
VERSION = '1.72.0' VERSION = '1.72.0'
require 'rhino/java' require 'rhino/java'
require 'rhino/context' require 'rhino/context'
require 'rhino/native_object'
end end

View file

@ -7,22 +7,45 @@ module Rhino
class Context class Context
class << self class << self
def open
J::ContextFactory.new.call do |native|
yield new(native)
end
end
def to_scriptable(object)
case object
when NativeObject then object.j
when J::Scriptable then object
else
#wrap ruby object into ScriptableRubyObject
end
end
def to_ruby(object)
object.class <= J::Scriptable ? NativeObject.new(object) : object
end
private :new private :new
end end
def initialize(native) #:nodoc: def initialize(native) #:nodoc:
@native = native @native = native
end end
def self.open def init_standard_objects(options = {})
J::ContextFactory.new.call do |native| NativeObject.new(@native.initStandardObjects(nil, options[:sealed] == true)).tap do |objects|
yield new(native) unless options[:java]
for package in ["Packages", "java", "org", "com"]
objects.j.delete(package)
end
end
end end
end end
def evaljs(str, scope = @native.initStandardObjects()) def evaljs(str, scope = @native.initStandardObjects())
begin begin
@native.evaluateString(scope, str, "<eval>", 1, nil) Context.to_ruby(@native.evaluateString(Context.to_scriptable(scope), str, "<eval>", 1, nil))
rescue J::RhinoException => e rescue J::RhinoException => e
raise Rhino::RhinoError, e raise Rhino::RhinoError, e
end end
@ -33,7 +56,7 @@ module Rhino
end end
end end
class Function < J::BaseFunction class Function < J::BaseFunction
def initialize(&block) def initialize(&block)
@block = block @block = block
@ -55,7 +78,7 @@ module Rhino
end end
def javascript_backtrace def javascript_backtrace
@native.script_stack_trace @native.getScriptStackTrace()
end end
end end
end end

View file

@ -5,4 +5,13 @@ module Rhino
module J module J
import "org.mozilla.javascript" import "org.mozilla.javascript"
end end
end
unless Object.method_defined?(:tap)
class Object
def tap
yield self
self
end
end
end end

View file

@ -0,0 +1,19 @@
module Rhino
class NativeObject
attr_reader :j
def initialize(j)
@j = j
end
def [](k)
if v = @j.get(k.to_s,@j)
v == J::Scriptable::NOT_FOUND ? nil : Context.to_ruby(v)
end
end
def []=(k,v)
@j.put(k.to_s,@j,v)
end
end
end

View file

@ -1,25 +1,71 @@
require File.dirname(__FILE__) + '/../spec_helper' require File.dirname(__FILE__) + '/../spec_helper'
include Rhino
describe Rhino::Context do describe Rhino::Context do
include Rhino
it "can evaluate some javascript" do it "can evaluate some javascript" do
Rhino::Context.open do |cxt| Context.open do |cxt|
cxt.evaljs("5 + 3").should == 8 cxt.evaljs("5 + 3").should == 8
end end
end end
it "can embed ruby object into javascript" do it "can embed ruby object into javascript" do
Rhino::Context.open do |cxt| Context.open do |cxt|
cxt.standard do |scope| cxt.init_standard_objects.tap do |scope|
scope.put("foo", scope, "Hello World") scope["foo"] = "Hello World"
cxt.evaljs("foo", scope).should == "Hello World" cxt.evaljs("foo", scope).should == "Hello World"
end end
end end
end
describe "Initalizing Standard Javascript Objects" do
it "provides the standard objects without java integration by default" do
Context.open do |cxt|
cxt.init_standard_objects.tap do |scope|
scope["Object"].should_not be_nil
scope["Math"].should_not be_nil
scope["String"].should_not be_nil
scope["Function"].should_not be_nil
scope["Packages"].should be_nil
scope["java"].should be_nil
scope["org"].should be_nil
scope["com"].should be_nil
end
end
end
it "provides unsealed standard object by default" do
Context.open do |cxt|
cxt.init_standard_objects.tap do |scope|
cxt.evaljs("Object.foop = 'blort'", scope)
scope["Object"]['foop'].should == 'blort'
end
end
end
it "allows you to seal the standard objects so that they cannot be modified" do
Context.open do |cxt|
cxt.init_standard_objects(:sealed => true).tap do |scope|
lambda {
cxt.evaljs("Object.foop = 'blort'", scope)
}.should raise_error(Rhino::RhinoError)
end
end
end
it "allows java integration to be turned on when initializing standard objects" do
Context.open do |cxt|
cxt.init_standard_objects(:java => true).tap do |scope|
scope["Packages"].should_not be_nil
end
end
end
end end
it "can call ruby functions from javascript" do it "can call ruby functions from javascript" do
Rhino::Context.open do |cxt| Context.open do |cxt|
cxt.standard do |scope| cxt.standard do |scope|
scope.put("say", scope, function {|word, times| word * times}) scope.put("say", scope, function {|word, times| word * times})
cxt.evaljs("say('Hello',2)", scope).should == "HelloHello" cxt.evaljs("say('Hello',2)", scope).should == "HelloHello"
@ -29,8 +75,7 @@ describe Rhino::Context do
it "has a private constructor" do it "has a private constructor" do
lambda { lambda {
Rhino::Context.new(nil) Context.new(nil)
}.should raise_error }.should raise_error
end end
end end

View file

@ -0,0 +1,31 @@
require File.dirname(__FILE__) + '/../spec_helper'
include Rhino
describe Rhino::NativeObject do
before(:each) do
@j = J::NativeObject.new
@o = NativeObject.new(@j)
end
it "wraps a native javascript object" do
@o["foo"] = 'bar'
@j.get("foo", @j).should == "bar"
@j.put("blue",@j, "blam")
@o["blue"].should == "blam"
end
it "doesn't matter if you use a symbol or a string to set a value" do
@o[:foo] = "bar"
@o['foo'].should == "bar"
@o['baz'] = "bang"
@o[:baz].should == "bang"
end
it "returns nil when the value is null, null, or not defined" do
@o[:foo].should be_nil
end
end