mirror of
https://github.com/rubyjs/therubyracer
synced 2023-03-27 23:21:42 -04:00
support two-way identity mapping
This commit is contained in:
parent
6dbd647680
commit
6157d35d4a
5 changed files with 78 additions and 16 deletions
|
@ -2,11 +2,18 @@
|
|||
|
||||
namespace rr {
|
||||
void Template::Init() {
|
||||
ClassBuilder("Template");
|
||||
ClassBuilder("Template").
|
||||
defineMethod("Set", &Set);
|
||||
ObjectTemplate::Init();
|
||||
FunctionTemplate::Init();
|
||||
}
|
||||
|
||||
VALUE Template::Set(int argc, VALUE argv[], VALUE self) {
|
||||
VALUE name; VALUE value; VALUE attributes;
|
||||
rb_scan_args(argc, argv, "21", &name, &value, &attributes);
|
||||
Void(Template(self)->Set(*String(name), *Value(value), PropertyAttribute(attributes)));
|
||||
}
|
||||
|
||||
void ObjectTemplate::Init() {
|
||||
ClassBuilder("ObjectTemplate", "Template").
|
||||
defineSingletonMethod("New", &New).
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
module V8
|
||||
class Context
|
||||
attr_reader :native
|
||||
attr_reader :native, :conversion
|
||||
|
||||
def initialize
|
||||
@native = V8::C::Context::New()
|
||||
|
@ -15,6 +15,14 @@ module V8
|
|||
@conversion.to_v8(ruby_object)
|
||||
end
|
||||
|
||||
def link(ruby_object, v8_object)
|
||||
@conversion.equate ruby_object, v8_object
|
||||
end
|
||||
|
||||
def self.link(*args)
|
||||
current.link *args
|
||||
end
|
||||
|
||||
def enter(&block)
|
||||
if !entered?
|
||||
lock_scope_and_enter(&block)
|
||||
|
|
|
@ -1,30 +1,57 @@
|
|||
class V8::Conversion
|
||||
module Identity
|
||||
def to_ruby(v8_object)
|
||||
v8_idmap.lookup(v8_object) {super}
|
||||
v8_idmap[v8_object] || super
|
||||
end
|
||||
|
||||
def to_v8(ruby_object)
|
||||
rb_idmap[ruby_object] || super
|
||||
end
|
||||
|
||||
def equate(ruby_object, v8_object)
|
||||
v8_idmap.equate(v8_object, ruby_object)
|
||||
rb_idmap.equate(ruby_object, v8_object)
|
||||
end
|
||||
|
||||
def v8_idmap
|
||||
@v8_idmap ||= V8IDMap.new
|
||||
end
|
||||
|
||||
class V8IDMap
|
||||
def rb_idmap
|
||||
@ruby_idmap ||= RubyIDMap.new
|
||||
end
|
||||
|
||||
class IDMap
|
||||
def initialize
|
||||
@storage = {}
|
||||
@map = {}
|
||||
end
|
||||
|
||||
def lookup(v8_object)
|
||||
if v8_object.is_a?(V8::C::Object)
|
||||
weakref = @storage[v8_object.GetIdentityHash()]
|
||||
if weakref && weakref.weakref_alive?
|
||||
weakref.__getobj__
|
||||
else
|
||||
@storage[v8_object.GetIdentityHash()] = WeakRef.new(yield)
|
||||
end
|
||||
else
|
||||
yield
|
||||
def [](object)
|
||||
weakref = @map[to_key(object)]
|
||||
if weakref && weakref.weakref_alive?
|
||||
weakref.__getobj__
|
||||
end
|
||||
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
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,12 +1,31 @@
|
|||
class V8::Conversion
|
||||
module Object
|
||||
def to_v8
|
||||
V8::C::Object::New()
|
||||
template = V8::C::ObjectTemplate::New()
|
||||
template.SetNamedPropertyHandler(Get, nil, nil, nil, nil, V8::C::External::New(self))
|
||||
instance = template.NewInstance()
|
||||
V8::Context.link self, instance
|
||||
return instance
|
||||
end
|
||||
|
||||
def to_ruby
|
||||
self
|
||||
end
|
||||
|
||||
class Get
|
||||
def self.call(property, info)
|
||||
context = V8::Context.current
|
||||
object = info.Data().Value()
|
||||
name = property.Utf8Value()
|
||||
if object.respond_to?(name) && object.method(name).arity <= 0
|
||||
context.to_v8 object.send(name)
|
||||
else
|
||||
V8::C::Value::Empty
|
||||
end
|
||||
rescue Exception => e
|
||||
warn "uncaught exception: #{e.class}: #{e.message} while accessing object property: #{e.backtrace.join('\n')}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module NativeObject
|
||||
|
|
|
@ -6,6 +6,7 @@ class V8::Object
|
|||
def initialize(native = nil)
|
||||
@context = V8::Context.current or fail "tried to initialize a #{self.class} without being in an entered V8::Context"
|
||||
@native = native || V8::C::Object::New()
|
||||
@context.link self, @native
|
||||
end
|
||||
|
||||
def [](key)
|
||||
|
|
Loading…
Reference in a new issue