mirror of
https://github.com/rubyjs/therubyracer
synced 2023-03-27 23:21:42 -04:00
Implement the rest of the Object mehods:
- GetConstructorName - InternalFieldCount - GetInternalField - SetInternalField - HasOwnProperty - HasRealNamedProperty - HasRealIndexedProperty - HasRealNamedCallbackProperty - GetRealNamedPropertyInPrototypeChain - GetRealNamedProperty - GetRealNamedPropertyAttributes - GetRealNamedPropertyAttributesInPrototypeChain - HasNamedLookupInterceptor - HasIndexedLookupInterceptor - SetHiddenValue - GetHiddenValue - DeleteHiddenValue - Clone - CreationContext - IsCallable - CallAsFunction - CallAsConstructor
This commit is contained in:
parent
200d617089
commit
5ac3483215
4 changed files with 388 additions and 5 deletions
|
@ -8,10 +8,12 @@ namespace rr {
|
|||
ObjectTemplate(VALUE self) : Ref<v8::ObjectTemplate>(self) {}
|
||||
ObjectTemplate(v8::Isolate* isolate, v8::Handle<v8::ObjectTemplate> tmpl) :
|
||||
Ref<v8::ObjectTemplate>(isolate, tmpl) {}
|
||||
|
||||
inline static void Init() {
|
||||
ClassBuilder("ObjectTemplate", Template::Class).
|
||||
defineSingletonMethod("New", &New).
|
||||
defineMethod("NewInstance", &NewInstance).
|
||||
defineMethod("SetInternalFieldCount", &SetInternalFieldCount).
|
||||
store(&Class);
|
||||
}
|
||||
|
||||
|
@ -20,6 +22,7 @@ namespace rr {
|
|||
rb_scan_args(argc, argv, "11", &r_isolate, &r_constructor);
|
||||
Isolate isolate(r_isolate);
|
||||
Locker lock(isolate);
|
||||
|
||||
return ObjectTemplate(isolate, v8::ObjectTemplate::New(isolate));
|
||||
}
|
||||
|
||||
|
@ -28,8 +31,17 @@ namespace rr {
|
|||
Context context(r_context);
|
||||
Isolate isolate(context.getIsolate());
|
||||
Locker lock(isolate);
|
||||
v8::MaybeLocal<v8::Object> object(t->NewInstance());
|
||||
return Object::Maybe(isolate, ObjectTemplate(self)->NewInstance(context));
|
||||
|
||||
return Object::Maybe(isolate, t->NewInstance(context));
|
||||
}
|
||||
|
||||
static VALUE SetInternalFieldCount(VALUE self, VALUE value) {
|
||||
ObjectTemplate t(self);
|
||||
Locker lock(t);
|
||||
|
||||
t->SetInternalFieldCount(NUM2INT(value));
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
208
ext/v8/object.cc
208
ext/v8/object.cc
|
@ -21,6 +21,28 @@ namespace rr {
|
|||
defineMethod("GetPrototype", &GetPrototype).
|
||||
defineMethod("SetPrototype", &SetPrototype).
|
||||
defineMethod("ObjectProtoToString", &ObjectProtoToString).
|
||||
defineMethod("GetConstructorName", &GetConstructorName).
|
||||
defineMethod("InternalFieldCount", &InternalFieldCount).
|
||||
defineMethod("GetInternalField", &GetInternalField).
|
||||
defineMethod("SetInternalField", &SetInternalField).
|
||||
defineMethod("HasOwnProperty", &HasOwnProperty).
|
||||
defineMethod("HasRealNamedProperty", &HasRealNamedProperty).
|
||||
defineMethod("HasRealIndexedProperty", &HasRealIndexedProperty).
|
||||
defineMethod("HasRealNamedCallbackProperty", &HasRealNamedCallbackProperty).
|
||||
defineMethod("GetRealNamedPropertyInPrototypeChain", &GetRealNamedPropertyInPrototypeChain).
|
||||
defineMethod("GetRealNamedProperty", &GetRealNamedProperty).
|
||||
defineMethod("GetRealNamedPropertyAttributes", &GetRealNamedPropertyAttributes).
|
||||
defineMethod("GetRealNamedPropertyAttributesInPrototypeChain", &GetRealNamedPropertyAttributesInPrototypeChain).
|
||||
defineMethod("HasNamedLookupInterceptor", &HasNamedLookupInterceptor).
|
||||
defineMethod("HasIndexedLookupInterceptor", &HasIndexedLookupInterceptor).
|
||||
defineMethod("SetHiddenValue", &SetHiddenValue).
|
||||
defineMethod("GetHiddenValue", &GetHiddenValue).
|
||||
defineMethod("DeleteHiddenValue", &DeleteHiddenValue).
|
||||
defineMethod("Clone", &Clone).
|
||||
defineMethod("CreationContext", &CreationContext).
|
||||
defineMethod("IsCallable", &IsCallable).
|
||||
defineMethod("CallAsFunction", &CallAsFunction).
|
||||
defineMethod("CallAsConstructor", &CallAsConstructor).
|
||||
|
||||
store(&Class);
|
||||
}
|
||||
|
@ -210,6 +232,192 @@ namespace rr {
|
|||
return String::Maybe(object.getIsolate(), object->ObjectProtoToString(Context(r_context)));
|
||||
}
|
||||
|
||||
VALUE Object::GetConstructorName(VALUE self) {
|
||||
Object object(self);
|
||||
Locker lock(object);
|
||||
|
||||
return String(object.getIsolate(), object->GetConstructorName());
|
||||
}
|
||||
|
||||
VALUE Object::InternalFieldCount(VALUE self) {
|
||||
Object object(self);
|
||||
Locker lock(object);
|
||||
|
||||
return INT2FIX(object->InternalFieldCount());
|
||||
}
|
||||
|
||||
VALUE Object::GetInternalField(VALUE self, VALUE index) {
|
||||
Object object(self);
|
||||
Locker lock(object);
|
||||
|
||||
return Value(object.getIsolate(), object->GetInternalField(NUM2INT(index)));
|
||||
}
|
||||
|
||||
VALUE Object::SetInternalField(VALUE self, VALUE index, VALUE value) {
|
||||
Object object(self);
|
||||
Locker lock(object);
|
||||
|
||||
object->SetInternalField(NUM2INT(index), *Value(value));
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE Object::HasOwnProperty(VALUE self, VALUE r_context, VALUE key) {
|
||||
Object object(self);
|
||||
Locker lock(object);
|
||||
|
||||
return Bool::Maybe(object->HasOwnProperty(Context(r_context), *Name(key)));
|
||||
}
|
||||
|
||||
VALUE Object::HasRealNamedProperty(VALUE self, VALUE r_context, VALUE key) {
|
||||
Object object(self);
|
||||
Locker lock(object);
|
||||
|
||||
return Bool::Maybe(object->HasRealNamedProperty(Context(r_context), *Name(key)));
|
||||
}
|
||||
|
||||
VALUE Object::HasRealIndexedProperty(VALUE self, VALUE r_context, VALUE index) {
|
||||
Object object(self);
|
||||
Locker lock(object);
|
||||
|
||||
return Bool::Maybe(object->HasRealIndexedProperty(Context(r_context), NUM2INT(index)));
|
||||
}
|
||||
|
||||
VALUE Object::HasRealNamedCallbackProperty(VALUE self, VALUE r_context, VALUE key) {
|
||||
Object object(self);
|
||||
Locker lock(object);
|
||||
|
||||
return Bool::Maybe(object->HasRealNamedCallbackProperty(Context(r_context), *Name(key)));
|
||||
}
|
||||
|
||||
VALUE Object::GetRealNamedPropertyInPrototypeChain(VALUE self, VALUE r_context, VALUE key) {
|
||||
Object object(self);
|
||||
Locker lock(object);
|
||||
|
||||
return Value::Maybe(object.getIsolate(), object->GetRealNamedPropertyInPrototypeChain(
|
||||
Context(r_context),
|
||||
*Name(key)
|
||||
));
|
||||
}
|
||||
|
||||
VALUE Object::GetRealNamedProperty(VALUE self, VALUE r_context, VALUE key) {
|
||||
Object object(self);
|
||||
Locker lock(object);
|
||||
|
||||
return Value::Maybe(object.getIsolate(), object->GetRealNamedProperty(
|
||||
Context(r_context),
|
||||
*Name(key)
|
||||
));
|
||||
}
|
||||
|
||||
VALUE Object::GetRealNamedPropertyAttributes(VALUE self, VALUE r_context, VALUE key) {
|
||||
Object object(self);
|
||||
Locker lock(object);
|
||||
|
||||
return Enum<v8::PropertyAttribute>::Maybe(object->GetRealNamedPropertyAttributes(
|
||||
Context(r_context),
|
||||
*Name(key)
|
||||
));
|
||||
}
|
||||
|
||||
VALUE Object::GetRealNamedPropertyAttributesInPrototypeChain(VALUE self, VALUE r_context, VALUE key) {
|
||||
Object object(self);
|
||||
Locker lock(object);
|
||||
|
||||
return Enum<v8::PropertyAttribute>::Maybe(object->GetRealNamedPropertyAttributesInPrototypeChain(
|
||||
Context(r_context),
|
||||
*Name(key)
|
||||
));
|
||||
}
|
||||
|
||||
VALUE Object::HasNamedLookupInterceptor(VALUE self) {
|
||||
Object object(self);
|
||||
Locker lock(object);
|
||||
|
||||
return Bool(object->HasNamedLookupInterceptor());
|
||||
}
|
||||
|
||||
VALUE Object::HasIndexedLookupInterceptor(VALUE self) {
|
||||
Object object(self);
|
||||
Locker lock(object);
|
||||
|
||||
return Bool(object->HasIndexedLookupInterceptor());
|
||||
}
|
||||
|
||||
VALUE Object::SetHiddenValue(VALUE self, VALUE key, VALUE value) {
|
||||
Object object(self);
|
||||
Locker lock(object);
|
||||
|
||||
return Bool(object->SetHiddenValue(String(key), Value(value)));
|
||||
}
|
||||
|
||||
VALUE Object::GetHiddenValue(VALUE self, VALUE key) {
|
||||
Object object(self);
|
||||
Locker lock(object);
|
||||
|
||||
return Value(object.getIsolate(), object->GetHiddenValue(String(key)));
|
||||
}
|
||||
|
||||
VALUE Object::DeleteHiddenValue(VALUE self, VALUE key) {
|
||||
Object object(self);
|
||||
Locker lock(object);
|
||||
|
||||
return Bool(object->DeleteHiddenValue(String(key)));
|
||||
}
|
||||
|
||||
VALUE Object::Clone(VALUE self) {
|
||||
Object object(self);
|
||||
Locker lock(object);
|
||||
|
||||
return Object(object.getIsolate(), object->Clone());
|
||||
}
|
||||
|
||||
VALUE Object::CreationContext(VALUE self) {
|
||||
Object object(self);
|
||||
Locker lock(object);
|
||||
|
||||
return Context(object->CreationContext());
|
||||
}
|
||||
|
||||
VALUE Object::IsCallable(VALUE self) {
|
||||
Object object(self);
|
||||
Locker lock(object);
|
||||
|
||||
return Bool(object->IsCallable());
|
||||
}
|
||||
|
||||
VALUE Object::CallAsFunction(int argc, VALUE* argv, VALUE self) {
|
||||
VALUE r_context, recv, r_argv;
|
||||
rb_scan_args(argc, argv, "30", &r_context, &recv, &r_argv);
|
||||
|
||||
Object object(self);
|
||||
v8::Isolate* isolate = object.getIsolate();
|
||||
Locker lock(isolate);
|
||||
|
||||
std::vector< v8::Handle<v8::Value> > vector(Value::convertRubyArray(isolate, r_argv));
|
||||
|
||||
return Value::Maybe(isolate, object->CallAsFunction(
|
||||
Context(r_context),
|
||||
Value(recv),
|
||||
RARRAY_LENINT(r_argv),
|
||||
&vector[0]
|
||||
));
|
||||
}
|
||||
|
||||
VALUE Object::CallAsConstructor(VALUE self, VALUE r_context, VALUE argv) {
|
||||
Object object(self);
|
||||
v8::Isolate* isolate = object.getIsolate();
|
||||
Locker lock(isolate);
|
||||
|
||||
std::vector< v8::Handle<v8::Value> > vector(Value::convertRubyArray(isolate, argv));
|
||||
|
||||
return Value::Maybe(isolate, object->CallAsConstructor(
|
||||
Context(r_context),
|
||||
RARRAY_LENINT(argv),
|
||||
&vector[0]
|
||||
));
|
||||
}
|
||||
|
||||
Object::operator VALUE() {
|
||||
Isolate isolate(getIsolate());
|
||||
Locker lock(isolate);
|
||||
|
|
|
@ -27,6 +27,35 @@ namespace rr {
|
|||
static VALUE SetPrototype(VALUE self, VALUE r_context, VALUE prototype);
|
||||
|
||||
static VALUE ObjectProtoToString(VALUE self, VALUE r_context);
|
||||
static VALUE GetConstructorName(VALUE self);
|
||||
|
||||
static VALUE InternalFieldCount(VALUE self);
|
||||
static VALUE GetInternalField(VALUE self, VALUE index);
|
||||
static VALUE SetInternalField(VALUE self, VALUE index, VALUE value);
|
||||
|
||||
static VALUE HasOwnProperty(VALUE self, VALUE r_context, VALUE key);
|
||||
static VALUE HasRealNamedProperty(VALUE self, VALUE r_context, VALUE key);
|
||||
static VALUE HasRealIndexedProperty(VALUE self, VALUE r_context, VALUE index);
|
||||
static VALUE HasRealNamedCallbackProperty(VALUE self, VALUE r_context, VALUE key);
|
||||
static VALUE GetRealNamedPropertyInPrototypeChain(VALUE self, VALUE r_context, VALUE key);
|
||||
static VALUE GetRealNamedProperty(VALUE self, VALUE r_context, VALUE key);
|
||||
static VALUE GetRealNamedPropertyAttributes(VALUE self, VALUE r_context, VALUE key);
|
||||
static VALUE GetRealNamedPropertyAttributesInPrototypeChain(VALUE self, VALUE r_context, VALUE key);
|
||||
|
||||
static VALUE HasNamedLookupInterceptor(VALUE self);
|
||||
static VALUE HasIndexedLookupInterceptor(VALUE self);
|
||||
|
||||
static VALUE SetHiddenValue(VALUE self, VALUE key, VALUE value);
|
||||
static VALUE GetHiddenValue(VALUE self, VALUE key);
|
||||
static VALUE DeleteHiddenValue(VALUE self, VALUE key);
|
||||
|
||||
static VALUE Clone(VALUE self);
|
||||
static VALUE CreationContext(VALUE self);
|
||||
|
||||
static VALUE IsCallable(VALUE self);
|
||||
|
||||
static VALUE CallAsFunction(int argc, VALUE* argv, VALUE self);
|
||||
static VALUE CallAsConstructor(VALUE self, VALUE r_context, VALUE argv);
|
||||
|
||||
inline Object(VALUE value) : Ref<v8::Object>(value) {}
|
||||
inline Object(v8::Isolate* isolate, v8::Handle<v8::Object> object) : Ref<v8::Object>(isolate, object) {}
|
||||
|
|
|
@ -272,6 +272,14 @@ describe V8::C::Object do
|
|||
|
||||
expect(names).to be_successful
|
||||
expect(names.FromJust.Get(@ctx, 0)).to v8_eq o_key
|
||||
|
||||
has_own = o.HasOwnProperty(@ctx, o_key)
|
||||
expect(has_own.IsJust).to be true
|
||||
expect(has_own.FromJust).to be true
|
||||
|
||||
has_own = o.HasOwnProperty(@ctx, prototype_key)
|
||||
expect(has_own.IsJust).to be true
|
||||
expect(has_own.FromJust).to be false
|
||||
end
|
||||
|
||||
it 'can enumerate all properties' do
|
||||
|
@ -294,12 +302,138 @@ describe V8::C::Object do
|
|||
|
||||
it 'can return a string representation of simple objects' do
|
||||
a = V8::C::Array.New(@isolate)
|
||||
a.Set(@ctx, 0, 2)
|
||||
a.Set(@ctx, 1, 3)
|
||||
|
||||
str = a.ObjectProtoToString(@ctx)
|
||||
expect(str).to be_successful
|
||||
expect(str.FromJust.Utf8Value).to eq '[object Array]'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#GetConstructorName' do
|
||||
it 'can return the constructor name of an array' do
|
||||
a = V8::C::Array.New(@isolate)
|
||||
|
||||
expect(a.GetConstructorName().Utf8Value).to eq 'Array'
|
||||
end
|
||||
end
|
||||
|
||||
context 'with internal fields' do
|
||||
let(:o) do
|
||||
template = V8::C::ObjectTemplate.New(@isolate)
|
||||
template.SetInternalFieldCount(2)
|
||||
|
||||
template.NewInstance(@ctx).FromJust
|
||||
end
|
||||
|
||||
let(:value_one) { V8::C::String.NewFromUtf8(@isolate, 'value 1') }
|
||||
let(:value_two) { V8::C::String.NewFromUtf8(@isolate, 'value 2') }
|
||||
|
||||
before do
|
||||
o.SetInternalField(0, value_one)
|
||||
o.SetInternalField(1, value_two)
|
||||
end
|
||||
|
||||
it 'can get and set internal fields' do
|
||||
expect(o.GetInternalField(0)).to strict_eq value_one
|
||||
expect(o.GetInternalField(1)).to strict_eq value_two
|
||||
end
|
||||
|
||||
it 'can get the internal field count' do
|
||||
expect(o.InternalFieldCount).to eq 2
|
||||
end
|
||||
end
|
||||
|
||||
context 'with hidden values' do
|
||||
let(:o) { V8::C::Object.New @isolate }
|
||||
|
||||
let(:key_one) { V8::C::String.NewFromUtf8(@isolate, 'key 1') }
|
||||
let(:key_two) { V8::C::String.NewFromUtf8(@isolate, 'key 2') }
|
||||
let(:value_one) { V8::C::String.NewFromUtf8(@isolate, 'value 1') }
|
||||
let(:value_two) { V8::C::String.NewFromUtf8(@isolate, 'value 2') }
|
||||
|
||||
before do
|
||||
o.SetHiddenValue(key_one, value_one)
|
||||
o.SetHiddenValue(key_two, value_two)
|
||||
end
|
||||
|
||||
it 'can get and set hidden values' do
|
||||
expect(o.GetHiddenValue(key_one)).to strict_eq value_one
|
||||
expect(o.GetHiddenValue(key_two)).to strict_eq value_two
|
||||
end
|
||||
|
||||
it 'can delete hidden values' do
|
||||
expect(o.DeleteHiddenValue(key_one)).to be true
|
||||
expect(o.GetHiddenValue(key_one)).to be nil
|
||||
end
|
||||
end
|
||||
|
||||
describe '#Clone' do
|
||||
let(:o) { V8::C::Object.New @isolate }
|
||||
|
||||
let(:key) { V8::C::String.NewFromUtf8(@isolate, 'key') }
|
||||
let(:value) { V8::C::String.NewFromUtf8(@isolate, 'value') }
|
||||
|
||||
before do
|
||||
o.Set(@ctx, key, value)
|
||||
end
|
||||
|
||||
it 'can clone an object' do
|
||||
clone = o.Clone
|
||||
|
||||
expect(clone).to_not strict_eq o
|
||||
|
||||
expect(clone.Get(@ctx, key)).to strict_eq value
|
||||
end
|
||||
end
|
||||
|
||||
describe '#CreationContext' do
|
||||
it 'returns a context' do
|
||||
o = V8::C::Object.New @isolate
|
||||
expect(o.CreationContext).to be_a V8::C::Context
|
||||
end
|
||||
end
|
||||
|
||||
describe '#IsCallable' do
|
||||
it 'returns false for plain objects' do
|
||||
o = V8::C::Object.New @isolate
|
||||
expect(o.IsCallable).to be false
|
||||
end
|
||||
|
||||
it 'returns true for functions' do
|
||||
fn = V8::C::Function.New @isolate, proc { }, V8::C::Object::New(@isolate)
|
||||
expect(fn.IsCallable).to be true
|
||||
end
|
||||
end
|
||||
|
||||
describe 'callable objects' do
|
||||
let(:value) { V8::C::String.NewFromUtf8(@isolate, 'value') }
|
||||
let(:one) { V8::C::String.NewFromUtf8(@isolate, 'one') }
|
||||
let(:two) { V8::C::String.NewFromUtf8(@isolate, 'two') }
|
||||
|
||||
let(:fn) do
|
||||
source = '(function(one, two) {this.one = one; this.two = two; return this;})'
|
||||
source = V8::C::String.NewFromUtf8(@isolate, source.to_s)
|
||||
script = V8::C::Script.Compile(@ctx, source)
|
||||
result = script.FromJust.Run(@ctx)
|
||||
|
||||
result.FromJust
|
||||
end
|
||||
|
||||
it 'can be called as functions' do
|
||||
object = V8::C::Object::New(@isolate)
|
||||
result = fn.CallAsFunction(@ctx, object, [one, two]).FromJust
|
||||
|
||||
expect(result).to strict_eq object
|
||||
expect(object.Get(@ctx, one)).to strict_eq one
|
||||
expect(object.Get(@ctx, two)).to strict_eq two
|
||||
end
|
||||
|
||||
it 'can be called as constructors' do
|
||||
result = fn.CallAsConstructor(@ctx, [one, two]).FromJust
|
||||
|
||||
expect(result).to be_a V8::C::Object
|
||||
expect(result.Get(@ctx, one)).to strict_eq one
|
||||
expect(result.Get(@ctx, two)).to strict_eq two
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Reference in a new issue