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:
parent
a9eec635a7
commit
72d181ecdc
2 changed files with 101 additions and 23 deletions
|
@ -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
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue