1
0
Fork 0
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:
Charles Lowell 2012-06-11 05:06:07 -05:00
parent 6dbd647680
commit 6157d35d4a
5 changed files with 78 additions and 16 deletions

View file

@ -2,11 +2,18 @@
namespace rr { namespace rr {
void Template::Init() { void Template::Init() {
ClassBuilder("Template"); ClassBuilder("Template").
defineMethod("Set", &Set);
ObjectTemplate::Init(); ObjectTemplate::Init();
FunctionTemplate::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() { void ObjectTemplate::Init() {
ClassBuilder("ObjectTemplate", "Template"). ClassBuilder("ObjectTemplate", "Template").
defineSingletonMethod("New", &New). defineSingletonMethod("New", &New).

View file

@ -1,6 +1,6 @@
module V8 module V8
class Context class Context
attr_reader :native attr_reader :native, :conversion
def initialize def initialize
@native = V8::C::Context::New() @native = V8::C::Context::New()
@ -15,6 +15,14 @@ module V8
@conversion.to_v8(ruby_object) @conversion.to_v8(ruby_object)
end 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) def enter(&block)
if !entered? if !entered?
lock_scope_and_enter(&block) lock_scope_and_enter(&block)

View file

@ -1,30 +1,57 @@
class V8::Conversion class V8::Conversion
module Identity module Identity
def to_ruby(v8_object) 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 end
def v8_idmap def v8_idmap
@v8_idmap ||= V8IDMap.new @v8_idmap ||= V8IDMap.new
end end
class V8IDMap def rb_idmap
@ruby_idmap ||= RubyIDMap.new
end
class IDMap
def initialize def initialize
@storage = {} @map = {}
end end
def lookup(v8_object) def [](object)
if v8_object.is_a?(V8::C::Object) weakref = @map[to_key(object)]
weakref = @storage[v8_object.GetIdentityHash()] if weakref && weakref.weakref_alive?
if weakref && weakref.weakref_alive? weakref.__getobj__
weakref.__getobj__
else
@storage[v8_object.GetIdentityHash()] = WeakRef.new(yield)
end
else
yield
end end
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 end
end end

View file

@ -1,12 +1,31 @@
class V8::Conversion class V8::Conversion
module Object module Object
def to_v8 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 end
def to_ruby def to_ruby
self self
end 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 end
module NativeObject module NativeObject

View file

@ -6,6 +6,7 @@ class V8::Object
def initialize(native = nil) def initialize(native = nil)
@context = V8::Context.current or fail "tried to initialize a #{self.class} without being in an entered V8::Context" @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() @native = native || V8::C::Object::New()
@context.link self, @native
end end
def [](key) def [](key)