#include "rr.h" namespace rr { VALUE Accessor::Info::Class; void Accessor::Init() { ClassBuilder("AccessorInfo"). defineMethod("This", &Info::This). defineMethod("Holder", &Info::Holder). defineMethod("Data", &Info::Data). store(&Info::Class); } Accessor::Accessor(VALUE getter, VALUE setter, VALUE data_) : get(getter), set(setter), data(data_) {} Accessor::Accessor(VALUE get, VALUE set, VALUE query, VALUE deleter, VALUE enumerator, VALUE data) { this->get = get; this->set = set; this->query = query; this->deleter = deleter; this->enumerator = enumerator; this->data = data; } Accessor::Accessor(v8::Handle value) { v8::Local wrapper = value->ToObject(); this->get = unwrap(wrapper, 0); this->set = unwrap(wrapper, 1); this->query = unwrap(wrapper, 2); this->deleter = unwrap(wrapper, 3); this->enumerator = unwrap(wrapper, 4); v8::Handle data = wrapper->Get(5); if (!data.IsEmpty()) { this->data = Value(data); } } Accessor::operator v8::Handle() { v8::Local wrapper = v8::Object::New(); wrap(wrapper, 0, this->get); wrap(wrapper, 1, this->set); wrap(wrapper, 2, this->query); wrap(wrapper, 3, this->deleter); wrap(wrapper, 4, this->enumerator); if (RTEST(this->data)) { wrapper->Set(5, Value(this->data)); } return wrapper; } void Accessor::wrap(v8::Handle wrapper, int index, VALUE value) { if (RTEST(value)) { wrapper->Set(index, External::wrap(value)); } } VALUE Accessor::unwrap(v8::Handle wrapper, int index) { v8::Handle value = wrapper->Get(index); if (value.IsEmpty()) { return Qnil; } else { v8::Handle external(v8::External::Cast(*value)); return External::unwrap(external); } } VALUE Accessor::Info::This(VALUE self) { return Object(Info(self)->This()); } VALUE Accessor::Info::Holder(VALUE self) { return Object(Info(self)->Holder()); } VALUE Accessor::Info::Data(VALUE self) { return Accessor(Info(self)->Data()).data; } v8::Handle Accessor::AccessorGetter(v8::Local property, const v8::AccessorInfo& info) { return Info(info).get(property); } void Accessor::AccessorSetter(v8::Local property, v8::Local value, const v8::AccessorInfo& info) { Info(info).set(property, value); } v8::Handle Accessor::NamedPropertyGetter(v8::Local property, const v8::AccessorInfo& info) { return Info(info).get(property); } v8::Handle Accessor::NamedPropertySetter(v8::Local property, v8::Local value, const v8::AccessorInfo& info) { return Info(info).set(property, value); } v8::Handle Accessor::NamedPropertyQuery(v8::Local property, const v8::AccessorInfo& info) { return Info(info).query(property); } v8::Handle Accessor::NamedPropertyDeleter(v8::Local property, const v8::AccessorInfo& info) { return Info(info).remove(property); } v8::Handle Accessor::NamedPropertyEnumerator(const v8::AccessorInfo& info) { return Info(info).enumerateNames(); } v8::Handle Accessor::IndexedPropertyGetter(uint32_t index, const v8::AccessorInfo& info) { return Info(info).get(index); } v8::Handle Accessor::IndexedPropertySetter(uint32_t index, v8::Local value, const v8::AccessorInfo& info) { return Info(info).set(index, value); } v8::Handle Accessor::IndexedPropertyQuery(uint32_t index, const v8::AccessorInfo& info) { return Info(info).query(index); } v8::Handle Accessor::IndexedPropertyDeleter(uint32_t index, const v8::AccessorInfo& info) { return Info(info).remove(index); } v8::Handle Accessor::IndexedPropertyEnumerator(const v8::AccessorInfo& info) { return Info(info).enumerateIndices(); } Accessor::Info::Info(const v8::AccessorInfo& info) { this->info = &info; } Accessor::Info::Info(VALUE value) { Data_Get_Struct(value, class v8::AccessorInfo, info); } v8::Handle Accessor::Info::get(v8::Local property) { Accessor accessor(info->Data()); return Value(rb_funcall(accessor.get, rb_intern("call"), 2, (VALUE)String(property), (VALUE)*this)); } v8::Handle Accessor::Info::set(v8::Local property, v8::Local value) { Accessor accessor(info->Data()); return Value(rb_funcall(accessor.set, rb_intern("call"), 3, (VALUE)String(property), (VALUE)Value(value), (VALUE)*this)); } v8::Handle Accessor::Info::query(v8::Local property) { Accessor accessor(info->Data()); return v8::Integer::New(NUM2INT(rb_funcall(accessor.query, rb_intern("call"), 2, (VALUE)String(property), (VALUE)*this))); } v8::Handle Accessor::Info::remove(v8::Local property) { Accessor accessor(info->Data()); return v8::Boolean::New(Bool(rb_funcall(accessor.deleter, rb_intern("call"), 2, (VALUE)String(property), (VALUE)*this))); } v8::Handle Accessor::Info::enumerateNames() { Accessor accessor(info->Data()); return Array(rb_funcall(accessor.enumerator, rb_intern("call"), 1, (VALUE)*this)); } v8::Handle Accessor::Info::get(uint32_t index) { Accessor accessor(info->Data()); return Value(rb_funcall(accessor.get, rb_intern("call"), 2, UINT2NUM(index), (VALUE)*this)); } v8::Handle Accessor::Info::set(uint32_t index, v8::Local value) { Accessor accessor(info->Data()); return Value(rb_funcall(accessor.set, rb_intern("call"), 3, UINT2NUM(index), (VALUE)Value(value), (VALUE)*this)); } v8::Handle Accessor::Info::query(uint32_t index) { Accessor accessor(info->Data()); return v8::Integer::New(NUM2INT(rb_funcall(accessor.query, rb_intern("call"), 2, UINT2NUM(index), (VALUE)*this))); } v8::Handle Accessor::Info::remove(uint32_t index) { Accessor accessor(info->Data()); return v8::Boolean::New(Bool(rb_funcall(accessor.deleter, rb_intern("call"), 2, UINT2NUM(index), (VALUE)*this))); } v8::Handle Accessor::Info::enumerateIndices() { Accessor accessor(info->Data()); return Array(rb_funcall(accessor.enumerator, rb_intern("call"), 1, (VALUE)*this)); } Accessor::Info::operator VALUE() { return Data_Wrap_Struct(Class, 0, 0, (void*)this->info); } }