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

add referential integrity to objects being passed into Rhino.

This commit is contained in:
Charles Lowell 2011-10-06 06:09:00 -05:00
parent 478d81831f
commit 3e31402a77
3 changed files with 47 additions and 24 deletions

View file

@ -5,23 +5,23 @@ module Rhino
# ==Overview
# All Javascript must be executed in a context which represents the execution environment in
# which scripts will run. The environment consists of the standard javascript objects
# and functions like Object, String, Array, etc... as well as any objects or functions which
# and functions like Object, String, Array, etc... as well as any objects or functions which
# have been defined in it. e.g.
#
#
# Context.open do |cxt|
# cxt['num'] = 5
# cxt.eval('num + 5') #=> 10
# end
#
#
# == Multiple Contexts.
# The same object may appear in any number of contexts, but only one context may be executing javascript code
# The same object may appear in any number of contexts, but only one context may be executing javascript code
# in any given thread. If a new context is opened in a thread in which a context is already opened, the second
# context will "mask" the old context e.g.
#
# six = 6
# Context.open do |cxt|
# cxt['num'] = 5
# cxt.eval('num') # => 5
# cxt.eval('num') # => 5
# Context.open do |cxt|
# cxt['num'] = 10
# cxt.eval('num') # => 10
@ -44,11 +44,11 @@ module Rhino
def open(options = {}, &block)
new(options).open(&block)
end
def eval(javascript)
new.eval(javascript)
end
end
# Create a new javascript environment for executing javascript and ruby code.
@ -78,8 +78,8 @@ module Rhino
@scope[k]
end
# Set a value in the global scope of this context. This value will be visible to all the
# javascript that is executed in this context.
# Set a value in the global scope of this context. This value will be visible to all the
# javascript that is executed in this context.
def []=(k, v)
@scope[k] = v
end
@ -103,7 +103,7 @@ module Rhino
end
end
end
def evaluate(*args) # :nodoc:
self.eval(*args)
end
@ -186,7 +186,7 @@ module Rhino
end
class ContextError < StandardError # :nodoc:
end
class JavascriptError < StandardError # :nodoc:
@ -203,6 +203,8 @@ module Rhino
end
end
JSError = JavascriptError
class RunawayScriptError < StandardError # :nodoc:
end
end

View file

@ -1,7 +1,7 @@
module Rhino
# Wraps a function that has been defined in Javascript so that it can
# Wraps a function that has been defined in Javascript so that it can
# be referenced and called from javascript. e.g.
#
# plus = Rhino::Context.open do |cx|
@ -9,15 +9,21 @@ module Rhino
# end
# plus.call(5,4) # => 9
#
class NativeFunction < NativeObject
class NativeFunction < NativeObject
def call(*args)
begin
cxt = J::Context.enter()
scope = @j.getParentScope() || cxt.initStandardObjects()
@j.call(cxt, scope, scope, args.map {|o| To.javascript(o)})
ensure
J::Context.exit()
end
cxt = J::Context.enter()
scope = @j.getParentScope() || cxt.initStandardObjects()
@j.call(cxt, scope, scope, args.map {|o| To.javascript(o)})
ensure
J::Context.exit()
end
def methodcall(this, *args)
cxt = J::Context.enter()
scope = @j.getParentScope() || cxt.initStandardObjects()
@j.call(cxt, scope, To.javascript(this), args.map {|o| To.javascript(o)})
ensure
J::Context.exit()
end
end
end

View file

@ -3,6 +3,8 @@ module Rhino
module To
JS_UNDEF = [J::Scriptable::NOT_FOUND, J::Undefined]
module_function
def ruby(object)
case object
when *JS_UNDEF then nil
@ -10,8 +12,8 @@ module Rhino
when J::NativeArray then array(object)
when J::NativeDate then Time.at(object.getJSTimeValue() / 1000)
when J::Regexp::NativeRegExp then object
when J::Function then NativeFunction.new(object)
when J::Scriptable then NativeObject.new(object)
when J::Function then r2j(object) {|o| NativeFunction.new(o)}
when J::Scriptable then r2j(object) {|o| NativeObject.new(o)}
else object
end
end
@ -43,6 +45,19 @@ module Rhino
native_object.j
end
module_function :ruby, :javascript, :array, :ruby_hash_to_native
@@r2j = {}
def r2j(value)
if ref = @@r2j[value.object_id]
if peer = ref.get()
return peer
end
else
yield(value).tap do |peer|
@@r2j[value.object_id] = java.lang.ref.WeakReference.new(peer)
end
end
end
end
end