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

add support for managing ruby proxies. Currently 1.9.2 only.

This commit is contained in:
Charles Lowell 2011-04-19 10:09:24 -05:00
parent a9eec635a7
commit 72d181ecdc
2 changed files with 101 additions and 23 deletions

View file

@ -5,6 +5,8 @@ module V8
def initialize
@js_proxies_rb2js = {}
@js_proxies_js2rb = {}
@rb_proxies_rb2js = {}
@rb_proxies_js2rb = {}
end
def register_javascript_proxy(proxy, options = {})
@ -24,6 +26,22 @@ module V8
@js_proxies_js2rb[proxy]
end
def register_ruby_proxy(proxy, options = {})
target = options[:for] or fail ArgumentError, "must specify the object that you're proxying with the :for => param"
fail ArgumentError, "javascript proxy must be a Handle to an actual V8 object" unless target.kind_of?(V8::C::Handle)
@rb_proxies_rb2js[proxy.object_id] = target
@rb_proxies_js2rb[target] = proxy.object_id
ObjectSpace.define_finalizer(proxy, method(:clear_rb_proxy))
end
def js_object_2_rb_proxy(object)
ObjectSpace._id2ref @rb_proxies_js2rb[object]
end
def rb_proxy_2_js_object(proxy)
@rb_proxies_rb2js[proxy.object_id]
end
def clear_js_proxy(proxy)
lambda do
rb = @js_proxies_js2rb[proxy]
@ -31,6 +49,12 @@ module V8
@js_proxies_rb2js.delete(rb)
end
end
def clear_rb_proxy(proxy_id)
js = @rb_proxies_rb2js[proxy_id]
@rb_proxies_rb2js.delete(proxy_id)
@rb_proxies_js2rb.delete(js)
end
end
end
end

View file

@ -6,11 +6,11 @@ describe V8::Portal::Proxies do
context "for Ruby objects which are embedded into javascript" do
it "allows you to resolve the Ruby object's JavaScript proxy" do
proxy = c::Object::New()
object = Object.new
subject.register_javascript_proxy proxy, :for => object
subject.rb_object_2_js_proxy(object).should be(proxy)
subject.js_proxy_2_rb_object(proxy).should be(object)
js_proxy = c::Object::New()
rb_object = Object.new
subject.register_javascript_proxy js_proxy, :for => rb_object
subject.rb_object_2_js_proxy(rb_object).should be(js_proxy)
subject.js_proxy_2_rb_object(js_proxy).should be(rb_object)
end
it "requires a Ruby object which is the actual object that is proxied" do
@ -20,35 +20,89 @@ describe V8::Portal::Proxies do
it "can only register proxies which are low-level JavaScript objects" do
expect {subject.register_javascript_proxy Object.new, :for => Object.new}.should raise_error(ArgumentError)
end
it "holds a hard reference to any ruby object which is linked to a javascript proxy" do
object = Object.new
ObjectSpace.define_finalizer(object, method(:finalize))
subject.register_javascript_proxy c::Object::New(), :for => object
object = nil
afterwards {@finalized.should be_false}
end
it "releases the hard reference if its corresponding javascript object has been garbage collected" do
object = Object.new
proxy = c::Object::New()
ObjectSpace.define_finalizer(object, method(:finalize))
subject.register_javascript_proxy proxy, :for => object
ruby_gc do
object = nil
v8_gc()
afterwards {@finalized.should be_true}
context "Memory Management" do
it "holds a hard reference to any ruby object which is linked to a javascript proxy" do
rb_object = Object.new
check_not_finalized(rb_object)
subject.register_javascript_proxy c::Object::New(), :for => rb_object
rb_object = nil
end
it "releases the hard reference if its corresponding javascript object has been garbage collected" do
rb_object = Object.new
js_proxy = c::Object::New()
check_finalized(rb_object)
subject.register_javascript_proxy js_proxy, :for => rb_object
rb_object = nil
ruby_gc do
v8_gc()
end
end
end
end
context "for a JavaScript objects which are embedded into Ruby" do
it "holds a weak referece to any javascript object which is "
it "allows you to resolve the JavaScript object's Ruby proxy" do
rb_proxy = Object.new
js_object = c::Object::New()
subject.register_ruby_proxy rb_proxy, :for => js_object
subject.js_object_2_rb_proxy(js_object).should be(rb_proxy)
subject.rb_proxy_2_js_object(rb_proxy).should be(js_object)
end
it "requires a JavaScript low level javascript object as the actual object that is proxied" do
expect {subject.register_javascript_proxy Object.new, :for => c::Object::New()}.should raise_error(ArgumentError)
end
context "Memory Management" do
it "holds a hard reference to any JavaScript object which is linked to a Ruby proxy" do
js_object = c::Object::New()
check_not_finalized(js_object)
subject.register_ruby_proxy Object.new, :for => js_object
js_object = nil
end
it "clears any strong references to the JavaScript object when it's Ruby proxy is garbage collected" do
js_object = c::Object::New()
rb_proxy = Object.new
subject.register_ruby_proxy rb_proxy, :for => js_object
check_finalized(js_object)
js_object = rb_proxy = nil
ruby_gc do
v8_gc
end
end
end
end
private
def finalize(object_id)
@finalized = true
@finalized ||= {}
@finalized[object_id] = true
end
def check_finalized(object)
@finalized ||= {}
ObjectSpace.define_finalizer(object, method(:finalize))
id_to_check = object.object_id
object = nil
afterwards do
@finalized[id_to_check].should be_true
end
end
def check_not_finalized(object)
@finalized ||= {}
ObjectSpace.define_finalizer(object, method(:finalize))
id_to_check = object.object_id
object = nil
afterwards do
@finalized[id_to_check].should be_false
end
end
def afterwards(&block)