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:
parent
20493a6c48
commit
33ef76f85e
6 changed files with 143 additions and 15 deletions
|
@ -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
|
|
@ -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
|
|
@ -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
|
19
lib/rhino/native_object.rb
Normal file
19
lib/rhino/native_object.rb
Normal 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
|
|
@ -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
|
31
spec/rhino/native_object_spec.rb
Normal file
31
spec/rhino/native_object_spec.rb
Normal 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
|
Loading…
Reference in a new issue