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:
parent
1705a34000
commit
a9eec635a7
3 changed files with 49 additions and 19 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue