2015-03-20 20:47:57 +00:00
|
|
|
#include "rr.h"
|
|
|
|
|
|
|
|
namespace rr {
|
|
|
|
|
|
|
|
void Object::Init() {
|
|
|
|
ClassBuilder("Object", Value::Class).
|
|
|
|
defineSingletonMethod("New", &New).
|
|
|
|
|
|
|
|
defineMethod("Set", &Set).
|
|
|
|
defineMethod("Get", &Get).
|
|
|
|
|
|
|
|
store(&Class);
|
|
|
|
}
|
|
|
|
|
2015-04-04 14:03:06 +00:00
|
|
|
VALUE Object::New(VALUE self, VALUE rb_isolate) {
|
|
|
|
Isolate isolate(rb_isolate);
|
|
|
|
Locker lock(isolate);
|
|
|
|
|
|
|
|
return Object(isolate, v8::Object::New(isolate));
|
2015-03-20 20:47:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: Allow setting of property attributes
|
|
|
|
VALUE Object::Set(VALUE self, VALUE key, VALUE value) {
|
2015-04-04 14:03:06 +00:00
|
|
|
Object object(self);
|
|
|
|
Locker lock(object.getIsolate());
|
|
|
|
|
2015-03-20 20:47:57 +00:00
|
|
|
if (rb_obj_is_kind_of(key, rb_cNumeric)) {
|
2015-04-04 14:03:06 +00:00
|
|
|
return Bool(object->Set(UInt32(key), Value::rubyObjectToHandle(object.getIsolate(), value)));
|
2015-03-20 20:47:57 +00:00
|
|
|
} else {
|
2015-04-04 14:03:06 +00:00
|
|
|
return Bool(object->Set(*Value(key), Value::rubyObjectToHandle(object.getIsolate(), value)));
|
2015-03-20 20:47:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VALUE Object::Get(VALUE self, VALUE key) {
|
2015-04-04 14:03:06 +00:00
|
|
|
Object object(self);
|
|
|
|
Locker lock(object.getIsolate());
|
|
|
|
|
2015-03-20 20:47:57 +00:00
|
|
|
if (rb_obj_is_kind_of(key, rb_cNumeric)) {
|
2015-04-04 14:03:06 +00:00
|
|
|
return Value::handleToRubyObject(object.getIsolate(), object->Get(UInt32(key)));
|
2015-03-20 20:47:57 +00:00
|
|
|
} else {
|
2015-04-04 14:03:06 +00:00
|
|
|
return Value::handleToRubyObject(object.getIsolate(), object->Get(*Value(key)));
|
2015-03-20 20:47:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Object::operator VALUE() {
|
2015-04-04 14:16:15 +00:00
|
|
|
Locker lock(getIsolate());
|
|
|
|
|
2015-03-20 20:47:57 +00:00
|
|
|
if (handle.IsEmpty()) {
|
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
|
|
|
|
Backref* backref;
|
|
|
|
|
2015-04-04 14:03:06 +00:00
|
|
|
v8::Local<v8::String> key(v8::String::NewFromUtf8(getIsolate(), "rr::Backref"));
|
2015-03-20 20:47:57 +00:00
|
|
|
v8::Local<v8::Value> external = handle->GetHiddenValue(key);
|
|
|
|
|
|
|
|
VALUE value;
|
|
|
|
|
|
|
|
if (external.IsEmpty()) {
|
|
|
|
value = downcast();
|
|
|
|
backref = new Backref(value);
|
|
|
|
|
2015-04-04 14:16:15 +00:00
|
|
|
handle->SetHiddenValue(key, backref->toExternal(getIsolate()));
|
2015-03-20 20:47:57 +00:00
|
|
|
} else {
|
|
|
|
v8::External* wrapper = v8::External::Cast(*external);
|
|
|
|
backref = (Backref*)wrapper->Value();
|
|
|
|
value = backref->get();
|
|
|
|
|
|
|
|
if (!RTEST(value)) {
|
|
|
|
value = downcast();
|
|
|
|
backref->set(value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
VALUE Object::downcast() {
|
2015-04-04 14:16:15 +00:00
|
|
|
Locker lock(getIsolate());
|
|
|
|
|
2015-03-20 20:47:57 +00:00
|
|
|
// TODO: Enable this when the methods are implemented
|
|
|
|
// if (handle->IsFunction()) {
|
|
|
|
// return Function((v8::Handle<v8::Function>) v8::Function::Cast(*handle));
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// if (handle->IsArray()) {
|
|
|
|
// return Array((v8::Handle<v8::Array>)v8::Array::Cast(*handle));
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// if (handle->IsDate()) {
|
|
|
|
// // return Date(handle);
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// if (handle->IsBooleanObject()) {
|
|
|
|
// // return BooleanObject(handle);
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// if (handle->IsNumberObject()) {
|
|
|
|
// // return NumberObject(handle);
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// if (handle->IsStringObject()) {
|
|
|
|
// // return StringObject(handle);
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// if (handle->IsRegExp()) {
|
|
|
|
// // return RegExp(handle);
|
|
|
|
// }
|
|
|
|
|
|
|
|
return Ref<v8::Object>::operator VALUE();
|
|
|
|
}
|
|
|
|
}
|