diff --git a/lib/v8/portal/proxies.rb b/lib/v8/portal/proxies.rb index b8c54c0..8c81468 100644 --- a/lib/v8/portal/proxies.rb +++ b/lib/v8/portal/proxies.rb @@ -9,6 +9,30 @@ module V8 @rb_proxies_js2rb = {} end + def js2rb(js) + if rb = js_proxy_2_rb_object(js) + return rb + elsif rb = js_object_2_rb_proxy(js) + return rb + else + proxy = block_given? ? yield(js) : Object.new + register_ruby_proxy proxy, :for => js + return proxy + end + end + + def rb2js(rb) + if js = rb_proxy_2_js_object(rb) + return js + elsif js = rb_object_2_js_proxy(rb) + return js + else + proxy = block_given? ? yield(rb) : V8::C::Object::New() + register_javascript_proxy proxy, :for => rb + return proxy + end + end + def register_javascript_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 proxy.kind_of?(V8::C::Handle) @@ -35,7 +59,9 @@ module V8 end def js_object_2_rb_proxy(object) - ObjectSpace._id2ref @rb_proxies_js2rb[object] + if id = @rb_proxies_js2rb[object] + ObjectSpace._id2ref id + end end def rb_proxy_2_js_object(proxy) diff --git a/spec/v8/portal/proxies_spec.rb b/spec/v8/portal/proxies_spec.rb index ec37aaa..a286e67 100644 --- a/spec/v8/portal/proxies_spec.rb +++ b/spec/v8/portal/proxies_spec.rb @@ -76,6 +76,57 @@ describe V8::Portal::Proxies do end end end + + context "looking up a Ruby object from a random JavaScript object" do + it "checks first if it's a native Ruby object with a javascript proxy" do + target = Object.new + proxy = c::Object::New() + subject.register_javascript_proxy proxy, :for => target + subject.js2rb(proxy).should be(target) + end + it "then sees if maybe it's a native JavaScript that has a Ruby proxy" do + target = c::Object::New() + proxy = Object.new + subject.register_ruby_proxy proxy, :for => target + subject.js2rb(target).should be(proxy) + end + it "will assume that it is a native JavaScript object that needs a Ruby proxy if no corresponding Ruby object can be found" do + js = c::Object::New() + proxy = subject.js2rb(js) do |target| + {:target => target} + end + subject.js2rb(js).should be(proxy) + end + end + + context "looking up a JavaScript object from a random Ruby object" do + it "checks first if it's a native JavaScript object with a Ruby proxy" do + target = c::Object::New() + proxy = Object.new + subject.register_ruby_proxy proxy, :for => target + subject.rb2js(proxy).should be(target) + end + + it "then sees if maybe it's a native Ruby object that has a JavaScript proxy" do + target = Object.new + proxy = c::Object::New() + subject.register_javascript_proxy proxy, :for => target + subject.rb2js(target).should be(proxy) + end + + it "assumes that it is a native Ruby object that needs a JavaScript proxy if no corresponding JavaScript object can be found" do + rb = Object.new + proxy = nil + js = subject.rb2js(rb) do |target| + target.should be(rb) + proxy = c::Object::New() + end + proxy.should_not be_nil + js.should be(proxy) + subject.rb2js(rb).should be(proxy) + end + end + end private