mirror of
https://github.com/rubyjs/therubyracer
synced 2023-03-27 23:21:42 -04:00
remove WeakRef from the equation
It turns out that the Ruby stdlib WeakRef class is completely broken. http://bugs.ruby-lang.org/issues/4168 While it is fixed in trunk, it is not useable, so as a temporary measure, use the `ref` gem as a dependency. It appears to be both faster and more correct.
This commit is contained in:
parent
7f967d0c5e
commit
1a93c34b07
5 changed files with 20 additions and 50 deletions
|
@ -1,5 +1,6 @@
|
|||
require "v8/version"
|
||||
|
||||
require 'ref'
|
||||
require 'v8/init'
|
||||
require 'v8/util/weakcell'
|
||||
require 'v8/error'
|
||||
|
|
|
@ -1,57 +1,30 @@
|
|||
require 'ref'
|
||||
|
||||
class V8::Conversion
|
||||
module Identity
|
||||
def to_ruby(v8_object)
|
||||
v8_idmap[v8_object] || super
|
||||
if v8_object.class <= V8::C::Object
|
||||
v8_idmap[v8_object.GetIdentityHash()] || super(v8_object)
|
||||
else
|
||||
super(v8_object)
|
||||
end
|
||||
end
|
||||
|
||||
def to_v8(ruby_object)
|
||||
rb_idmap[ruby_object] || super
|
||||
rb_idmap[ruby_object.object_id] || super(ruby_object)
|
||||
end
|
||||
|
||||
def equate(ruby_object, v8_object)
|
||||
v8_idmap.equate(v8_object, ruby_object)
|
||||
rb_idmap.equate(ruby_object, v8_object)
|
||||
v8_idmap[v8_object.GetIdentityHash()] = ruby_object
|
||||
rb_idmap[ruby_object.object_id] = v8_object
|
||||
end
|
||||
|
||||
def v8_idmap
|
||||
@v8_idmap ||= V8IDMap.new
|
||||
@v8_idmap ||= Ref::WeakValueMap.new
|
||||
end
|
||||
|
||||
def rb_idmap
|
||||
@ruby_idmap ||= RubyIDMap.new
|
||||
end
|
||||
|
||||
class IDMap
|
||||
def initialize
|
||||
@map = {}
|
||||
end
|
||||
|
||||
def [](object)
|
||||
weakref = @map[to_key(object)]
|
||||
weakref.__getobj__ if weakref
|
||||
rescue WeakRef::RefError
|
||||
nil #peer was garbage collected, so no current mapping.
|
||||
end
|
||||
|
||||
def equate(key_object, value_object)
|
||||
@map[to_key(key_object)] = WeakRef.new(value_object)
|
||||
end
|
||||
end
|
||||
|
||||
class RubyIDMap < IDMap
|
||||
def to_key(object)
|
||||
object.object_id
|
||||
end
|
||||
end
|
||||
|
||||
class V8IDMap < IDMap
|
||||
def to_key(object)
|
||||
object.GetIdentityHash()
|
||||
end
|
||||
|
||||
def [](v8_object)
|
||||
super if v8_object.is_a?(V8::C::Object)
|
||||
end
|
||||
@ruby_idmap ||= Ref::WeakValueMap.new
|
||||
end
|
||||
end
|
||||
end
|
|
@ -9,18 +9,15 @@ class V8::Conversion
|
|||
|
||||
class MethodCache
|
||||
def initialize
|
||||
@map = {}
|
||||
@map = Ref::WeakValueMap.new
|
||||
end
|
||||
|
||||
def [](method)
|
||||
weakref = @map[method.to_s]
|
||||
weakref.__getobj__ if weakref
|
||||
rescue WeakRef::RefError
|
||||
nil #template was garbage collected, so no mapping
|
||||
@map[method.to_s]
|
||||
end
|
||||
|
||||
def []=(method, template)
|
||||
@map[method.to_s] = WeakRef.new(template)
|
||||
@map[method.to_s] = template
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
require 'weakref'
|
||||
module V8
|
||||
module Util
|
||||
module Weakcell
|
||||
|
@ -11,19 +10,17 @@ module V8
|
|||
class Storage
|
||||
def access(&block)
|
||||
if @ref
|
||||
@ref.__getobj__
|
||||
@ref.object || populate(block)
|
||||
else
|
||||
populate(block)
|
||||
end
|
||||
rescue WeakRef::RefError
|
||||
populate(block)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def populate(block)
|
||||
occupant = block.call()
|
||||
@ref = WeakRef.new(occupant)
|
||||
@ref = Ref::WeakReference.new(occupant)
|
||||
return occupant
|
||||
end
|
||||
end
|
||||
|
|
|
@ -15,4 +15,6 @@ Gem::Specification.new do |gem|
|
|||
gem.extensions = ["ext/v8/extconf.rb"]
|
||||
gem.require_paths = ["lib", "ext"]
|
||||
gem.version = V8::VERSION
|
||||
|
||||
gem.add_dependency 'ref'
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue