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

infrastructure for managing JavaScript proxies for Ruby object at the gc level.

This commit is contained in:
Charles Lowell 2011-04-18 10:24:52 -05:00
parent 1705a34000
commit a9eec635a7
3 changed files with 49 additions and 19 deletions

View file

@ -3,16 +3,33 @@ module V8
class Proxies
def initialize
@js_proxies = {}
@rb_proxies = {}
@js_proxies_rb2js = {}
@js_proxies_js2rb = {}
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)
# handle = V8::C::Handle::New(proxy)
# handle.MakeWeak(&clear_jsproy)
@js_proxies[proxy.object_id] = target
@js_proxies_js2rb[proxy] = target
@js_proxies_rb2js[target] = proxy
proxy.MakeWeak(&clear_js_proxy(proxy))
end
def rb_object_2_js_proxy(object)
@js_proxies_rb2js[object]
end
def js_proxy_2_rb_object(proxy)
@js_proxies_js2rb[proxy]
end
def clear_js_proxy(proxy)
lambda do
rb = @js_proxies_js2rb[proxy]
@js_proxies_js2rb.delete(proxy)
@js_proxies_rb2js.delete(rb)
end
end
end
end

View file

@ -10,12 +10,13 @@ module V8::ExtSpec
end
after do
@cxt.Exit()
@cxt.Dispose()
end
end
end
def v8_eval(script)
c::Script::New(c::String::New(script), c::String::New('<eval>')).Run()
def v8_eval(script, sourcename = "<eval>")
c::Script::New(c::String::New(script), c::String::New(sourcename)).Run()
end
def c
@ -31,7 +32,8 @@ module V8::ExtSpec
end
def v8_gc
c::Script::New(c::String::New("gc()"), c::String::New("gc.js")).Run()
while !c::V8::IdleNotification();end
v8_eval('gc()', 'gc.js')
end
end

View file

@ -4,11 +4,19 @@ describe V8::Portal::Proxies do
include V8::ExtSpec
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)
end
it "requires a Ruby object which is the actual object that is proxied" do
expect {subject.register_javascript_proxy c::Object::New()}.should raise_error(ArgumentError)
end
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
@ -22,33 +30,36 @@ describe V8::Portal::Proxies do
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 c::Object::New(), :for => object
object = nil
v8_gc
afterwards {@finalized.should be_true}
subject.register_javascript_proxy proxy, :for => object
ruby_gc do
object = nil
v8_gc()
afterwards {@finalized.should be_true}
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 "
end
private
def finalize(object_id)
@finalized = true
end
def afterwards(&block)
@after ||= []
@after << block if block_given?
end
after do
ruby_gc do
@after.each(&:call) if @after
end
end
end