mirror of
https://github.com/rubyjs/therubyracer
synced 2023-03-27 23:21:42 -04:00
Implement Object.SetAccessor, Has and Delete
This commit is contained in:
parent
905037ea50
commit
07352d62c1
9 changed files with 387 additions and 55 deletions
27
ext/v8/enums.h
Normal file
27
ext/v8/enums.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
#include "rr.h"
|
||||
|
||||
namespace rr {
|
||||
|
||||
class Enums {
|
||||
public:
|
||||
static void Init() {
|
||||
ClassBuilder("AccessControl").
|
||||
defineConst("DEFAULT", INT2FIX(v8::DEFAULT)).
|
||||
defineConst("ALL_CAN_READ", INT2FIX(v8::ALL_CAN_READ)).
|
||||
defineConst("ALL_CAN_WRITE", INT2FIX(v8::ALL_CAN_WRITE)).
|
||||
defineConst("PROHIBITS_OVERWRITING", INT2FIX(v8::PROHIBITS_OVERWRITING));
|
||||
|
||||
ClassBuilder("PropertyAttribute").
|
||||
defineConst("None", INT2FIX(v8::None)).
|
||||
defineConst("ReadOnly", INT2FIX(v8::ReadOnly)).
|
||||
defineConst("DontEnum", INT2FIX(v8::DontEnum)).
|
||||
defineConst("DontDelete", INT2FIX(v8::DontDelete));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static T fromRubyValue(VALUE rb_int) {
|
||||
return (T)NUM2INT(rb_int);
|
||||
}
|
||||
};
|
||||
|
||||
};
|
|
@ -9,6 +9,7 @@ using namespace rr;
|
|||
extern "C" {
|
||||
void Init_init() {
|
||||
V8::Init();
|
||||
Enums::Init();
|
||||
Isolate::Init();
|
||||
Handles::Init();
|
||||
Context::Init();
|
||||
|
@ -26,13 +27,14 @@ extern "C" {
|
|||
Symbol::Init();
|
||||
Function::Init();
|
||||
FunctionCallbackInfo::Init();
|
||||
PropertyCallbackInfo::Init();
|
||||
PropertyCallbackInfoVoid::Init();
|
||||
ReturnValue::Init();
|
||||
Script::Init();
|
||||
ScriptOrigin::Init();
|
||||
Array::Init();
|
||||
External::Init();
|
||||
|
||||
// Accessor::Init();
|
||||
// Invocation::Init();
|
||||
// Signature::Init();
|
||||
// Date::Init();
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#include "rr.h"
|
||||
|
||||
namespace rr {
|
||||
|
||||
void Object::Init() {
|
||||
ClassBuilder("Object", Value::Class).
|
||||
defineSingletonMethod("New", &New).
|
||||
|
@ -9,6 +8,9 @@ namespace rr {
|
|||
defineMethod("Set", &Set).
|
||||
defineMethod("Get", &Get).
|
||||
defineMethod("GetIdentityHash", &GetIdentityHash).
|
||||
defineMethod("Has", &Has).
|
||||
defineMethod("Delete", &Delete).
|
||||
defineMethod("SetAccessor", &SetAccessor).
|
||||
|
||||
store(&Class);
|
||||
}
|
||||
|
@ -49,11 +51,53 @@ namespace rr {
|
|||
|
||||
VALUE Object::GetIdentityHash(VALUE self) {
|
||||
Object object(self);
|
||||
Locker lock(object.getIsolate());
|
||||
Locker lock(object);
|
||||
|
||||
return INT2FIX(object->GetIdentityHash());
|
||||
}
|
||||
|
||||
VALUE Object::Has(VALUE self, VALUE r_context, VALUE key) {
|
||||
Object object(self);
|
||||
Locker lock(object);
|
||||
|
||||
if (rb_obj_is_kind_of(key, rb_cNumeric)) {
|
||||
return Bool::Maybe(object->Has(Context(r_context), Uint32_t(key)));
|
||||
} else {
|
||||
return Bool::Maybe(object->Has(Context(r_context), *Value(key)));
|
||||
}
|
||||
}
|
||||
|
||||
VALUE Object::Delete(VALUE self, VALUE r_context, VALUE key) {
|
||||
Object object(self);
|
||||
Locker lock(object);
|
||||
|
||||
if (rb_obj_is_kind_of(key, rb_cNumeric)) {
|
||||
return Bool::Maybe(object->Delete(Context(r_context), Uint32_t(key)));
|
||||
} else {
|
||||
return Bool::Maybe(object->Delete(Context(r_context), *Value(key)));
|
||||
}
|
||||
}
|
||||
|
||||
VALUE Object::SetAccessor(int argc, VALUE* argv, VALUE self) {
|
||||
VALUE r_context, name, getter, setter, data, settings, attribute;
|
||||
rb_scan_args(argc, argv, "52", &r_context, &name, &getter, &setter, &data, &settings, &attribute);
|
||||
|
||||
Object object(self);
|
||||
Context context(r_context);
|
||||
Isolate isolate(object.getIsolate());
|
||||
Locker lock(isolate);
|
||||
|
||||
return Bool::Maybe(object->SetAccessor(
|
||||
context,
|
||||
Name(name),
|
||||
&PropertyCallbackInfo::invokeGetter,
|
||||
RTEST(setter) ? &PropertyCallbackInfoVoid::invokeSetter : 0,
|
||||
v8::MaybeLocal<v8::Value>(PropertyCallbackInfo::wrapData(isolate, getter, setter, data)),
|
||||
RTEST(settings) ? Enums::fromRubyValue<v8::AccessControl>(settings) : v8::DEFAULT,
|
||||
RTEST(attribute) ? Enums::fromRubyValue<v8::PropertyAttribute>(attribute) : v8::None
|
||||
));
|
||||
}
|
||||
|
||||
Object::operator VALUE() {
|
||||
Isolate isolate(getIsolate());
|
||||
Locker lock(isolate);
|
||||
|
@ -89,4 +133,5 @@ namespace rr {
|
|||
|
||||
return Ref<v8::Object>::operator VALUE();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,53 +6,14 @@ namespace rr {
|
|||
class Object : public Ref<v8::Object> {
|
||||
public:
|
||||
static void Init();
|
||||
static VALUE New(VALUE self, VALUE isolate);
|
||||
static VALUE Set(VALUE self, VALUE context, VALUE key, VALUE value);
|
||||
// static VALUE ForceSet(VALUE self, VALUE key, VALUE value);
|
||||
static VALUE Get(VALUE self, VALUE context, VALUE key);
|
||||
// static VALUE GetPropertyAttributes(VALUE self, VALUE key);
|
||||
// static VALUE Has(VALUE self, VALUE key);
|
||||
// static VALUE Delete(VALUE self, VALUE key);
|
||||
// static VALUE ForceDelete(VALUE self, VALUE key);
|
||||
// static VALUE SetAccessor(int argc, VALUE* argv, VALUE self);
|
||||
// static VALUE GetPropertyNames(VALUE self);
|
||||
// static VALUE GetOwnPropertyNames(VALUE self);
|
||||
// static VALUE GetPrototype(VALUE self);
|
||||
// static VALUE SetPrototype(VALUE self, VALUE prototype);
|
||||
// static VALUE FindInstanceInPrototypeChain(VALUE self, VALUE impl);
|
||||
// static VALUE ObjectProtoToString(VALUE self);
|
||||
// static VALUE GetConstructorName(VALUE self);
|
||||
// static VALUE InternalFieldCount(VALUE self);
|
||||
// static VALUE GetInternalField(VALUE self, VALUE idx);
|
||||
// static VALUE SetInternalField(VALUE self, VALUE idx, VALUE value);
|
||||
// static VALUE HasOwnProperty(VALUE self, VALUE key);
|
||||
// static VALUE HasRealNamedProperty(VALUE self, VALUE key);
|
||||
// static VALUE HasRealIndexedProperty(VALUE self, VALUE idx);
|
||||
// static VALUE HasRealNamedCallbackProperty(VALUE self, VALUE key);
|
||||
// static VALUE GetRealNamedPropertyInPrototypeChain(VALUE self, VALUE key);
|
||||
// static VALUE GetRealNamedProperty(VALUE self, VALUE key);
|
||||
// static VALUE HasNamedLookupInterceptor(VALUE self);
|
||||
// static VALUE HasIndexedLookupInterceptor(VALUE self);
|
||||
// static VALUE TurnOnAccessCheck(VALUE self);
|
||||
|
||||
static VALUE New(VALUE self, VALUE rb_isolate);
|
||||
static VALUE Set(VALUE self, VALUE r_context, VALUE key, VALUE value);
|
||||
static VALUE Get(VALUE self, VALUE r_context, VALUE key);
|
||||
static VALUE GetIdentityHash(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 IsDirty(VALUE self);
|
||||
// static VALUE Clone(VALUE self);
|
||||
// static VALUE CreationContext(VALUE self);
|
||||
// static VALUE SetIndexedPropertiesToPixelData(VALUE self, VALUE data, VALUE length);
|
||||
// static VALUE GetIndexedPropertiesPixelData(VALUE self);
|
||||
// static VALUE HasIndexedPropertiesInPixelData(VALUE self);
|
||||
// static VALUE GetIndexedPropertiesPixelDataLength(VALUE self);
|
||||
// static VALUE SetIndexedPropertiesToExternalArrayData(VALUE self);
|
||||
// static VALUE HasIndexedPropertiesInExternalArrayData(VALUE self);
|
||||
// static VALUE GetIndexedPropertiesExternalArrayData(VALUE self);
|
||||
// static VALUE GetIndexedPropertiesExternalArrayDataType(VALUE self);
|
||||
// static VALUE GetIndexedPropertiesExternalArrayDataLength(VALUE self);
|
||||
// static VALUE IsCallable(VALUE self);
|
||||
// static VALUE CallAsFunction(VALUE self, VALUE recv, VALUE argv);
|
||||
// static VALUE CallAsConstructor(VALUE self, VALUE argv);
|
||||
static VALUE Has(VALUE self, VALUE r_context, VALUE key);
|
||||
static VALUE Delete(VALUE self, VALUE r_context, VALUE key);
|
||||
static VALUE SetAccessor(int argc, VALUE* argv, VALUE self);
|
||||
|
||||
inline Object(VALUE value) : Ref<v8::Object>(value) {}
|
||||
inline Object(v8::Isolate* isolate, v8::Handle<v8::Object> object) : Ref<v8::Object>(isolate, object) {}
|
||||
|
|
84
ext/v8/property-callback-void.h
Normal file
84
ext/v8/property-callback-void.h
Normal file
|
@ -0,0 +1,84 @@
|
|||
// -*- mode: c++ -*-
|
||||
#ifndef RR_PROPERTY_CALLBACK_VOID_H
|
||||
#define RR_PROPERTY_CALLBACK_VOID_H
|
||||
|
||||
namespace rr {
|
||||
|
||||
typedef Wrapper<v8::PropertyCallbackInfo<void>> PropertyCallbackInfoVoidWrapper;
|
||||
|
||||
class PropertyCallbackInfoVoid : public PropertyCallbackInfoVoidWrapper {
|
||||
public:
|
||||
|
||||
inline PropertyCallbackInfoVoid(v8::PropertyCallbackInfo<void> info) :
|
||||
PropertyCallbackInfoVoidWrapper(info) {}
|
||||
|
||||
inline PropertyCallbackInfoVoid(VALUE self) : PropertyCallbackInfoVoidWrapper(self) {}
|
||||
|
||||
/**
|
||||
* Call the Ruby code associated with this callback.
|
||||
*
|
||||
* Unpack the Ruby code, and the callback data from the C++
|
||||
* callback data, and then invoke that code.
|
||||
*
|
||||
* Note: This function implements the `v8::AccessorNameSetterCallback` API.
|
||||
*/
|
||||
static void invokeSetter(v8::Local<v8::Name> property, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) {
|
||||
v8::Isolate* isolate = info.GetIsolate();
|
||||
|
||||
v8::Local<v8::Object> holder = v8::Local<v8::Object>::Cast<v8::Value>(info.Data());
|
||||
v8::Local<v8::String> callback_key = v8::String::NewFromUtf8(isolate, "rr::setter");
|
||||
|
||||
VALUE code(External::unwrap(holder->GetHiddenValue(callback_key)));
|
||||
|
||||
VALUE rb_property;
|
||||
if (property->IsSymbol()) {
|
||||
rb_property = Symbol(isolate, v8::Local<v8::Symbol>::Cast(property));
|
||||
} else {
|
||||
rb_property = String(isolate, property->ToString());
|
||||
}
|
||||
|
||||
Unlocker unlock(info.GetIsolate());
|
||||
rb_funcall(
|
||||
code, rb_intern("call"), 3,
|
||||
rb_property,
|
||||
(VALUE)Value::handleToRubyObject(isolate, value),
|
||||
(VALUE)PropertyCallbackInfoVoid(info)
|
||||
);
|
||||
}
|
||||
|
||||
static VALUE This(VALUE self) {
|
||||
PropertyCallbackInfoVoid info(self);
|
||||
Locker lock(info->GetIsolate());
|
||||
return Object(info->GetIsolate(), info->This());
|
||||
}
|
||||
|
||||
static VALUE Data(VALUE self) {
|
||||
PropertyCallbackInfoVoid info(self);
|
||||
Isolate isolate(info->GetIsolate());
|
||||
Locker lock(isolate);
|
||||
|
||||
v8::Local<v8::Object> holder = v8::Local<v8::Object>::Cast<v8::Value>(info->Data());
|
||||
v8::Local<v8::String> data_key = v8::String::NewFromUtf8(isolate, "rr::data");
|
||||
v8::Local<v8::Value> data(holder->GetHiddenValue(data_key));
|
||||
|
||||
return Value::handleToRubyObject(info->GetIsolate(), data);
|
||||
}
|
||||
|
||||
static VALUE GetIsolate(VALUE self) {
|
||||
PropertyCallbackInfoVoid info(self);
|
||||
return Isolate(info->GetIsolate());
|
||||
}
|
||||
|
||||
static inline void Init() {
|
||||
ClassBuilder("PropertyCallbackVoidInfo").
|
||||
defineMethod("This", &This).
|
||||
defineMethod("Data", &Data).
|
||||
defineMethod("GetIsolate", &GetIsolate).
|
||||
store(&Class);
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> data;
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* RR_PROPERTY_CALLBACK_VOID_H */
|
107
ext/v8/property-callback.h
Normal file
107
ext/v8/property-callback.h
Normal file
|
@ -0,0 +1,107 @@
|
|||
// -*- mode: c++ -*-
|
||||
#ifndef RR_PROPERTY_CALLBACK_H
|
||||
#define RR_PROPERTY_CALLBACK_H
|
||||
|
||||
namespace rr {
|
||||
|
||||
typedef Wrapper<v8::PropertyCallbackInfo<v8::Value>> PropertyCallbackInfoWrapper;
|
||||
|
||||
class PropertyCallbackInfo : public PropertyCallbackInfoWrapper {
|
||||
public:
|
||||
|
||||
inline PropertyCallbackInfo(v8::PropertyCallbackInfo<v8::Value> info) :
|
||||
PropertyCallbackInfoWrapper(info) {}
|
||||
|
||||
inline PropertyCallbackInfo(VALUE self) : PropertyCallbackInfoWrapper(self) {}
|
||||
|
||||
/**
|
||||
* Package up the callback data for this object so that it can
|
||||
* invoke Ruby callables.
|
||||
*
|
||||
* Each accessor can have one `v8::Value` associated with it
|
||||
* that is passed to the `SetAccessor` method. To support this
|
||||
* same API from ruby, we take the passed data constructor *and*
|
||||
* the callbacks and store them *both* in a single `v8::Object`
|
||||
* which we use for the C++ level callback data.
|
||||
*/
|
||||
static v8::Local<v8::Value> wrapData(v8::Isolate* isolate, VALUE r_getter, VALUE r_setter, VALUE r_data) {
|
||||
v8::Local<v8::Object> holder = v8::Object::New(isolate);
|
||||
|
||||
v8::Local<v8::String> getter_key = v8::String::NewFromUtf8(isolate, "rr::getter");
|
||||
v8::Local<v8::String> setter_key = v8::String::NewFromUtf8(isolate, "rr::setter");
|
||||
v8::Local<v8::String> data_key = v8::String::NewFromUtf8(isolate, "rr::data");
|
||||
|
||||
holder->SetHiddenValue(getter_key, External::wrap(isolate, r_getter));
|
||||
holder->SetHiddenValue(setter_key, External::wrap(isolate, r_setter));
|
||||
holder->SetHiddenValue(data_key, Value(r_data));
|
||||
|
||||
return holder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the Ruby code associated with this callback.
|
||||
*
|
||||
* Unpack the Ruby code, and the callback data from the C++
|
||||
* callback data, and then invoke that code.
|
||||
*
|
||||
* Note: This function implements the `v8::AccessorNameGetterCallback` API.
|
||||
*/
|
||||
static void invokeGetter(v8::Local<v8::Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
|
||||
v8::Isolate* isolate = info.GetIsolate();
|
||||
v8::Local<v8::Object> holder = v8::Local<v8::Object>::Cast<v8::Value>(info.Data());
|
||||
v8::Local<v8::String> callback_key = v8::String::NewFromUtf8(isolate, "rr::getter");
|
||||
|
||||
VALUE code(External::unwrap(holder->GetHiddenValue(callback_key)));
|
||||
|
||||
VALUE rb_property;
|
||||
if (property->IsSymbol()) {
|
||||
rb_property = Symbol(isolate, v8::Local<v8::Symbol>::Cast(property));
|
||||
} else {
|
||||
rb_property = String(isolate, property->ToString());
|
||||
}
|
||||
|
||||
Unlocker unlock(info.GetIsolate());
|
||||
rb_funcall(code, rb_intern("call"), 2, rb_property, (VALUE)PropertyCallbackInfo(info));
|
||||
}
|
||||
|
||||
static VALUE This(VALUE self) {
|
||||
PropertyCallbackInfo info(self);
|
||||
Locker lock(info->GetIsolate());
|
||||
return Object(info->GetIsolate(), info->This());
|
||||
}
|
||||
|
||||
static VALUE Data(VALUE self) {
|
||||
PropertyCallbackInfo info(self);
|
||||
Isolate isolate(info->GetIsolate());
|
||||
Locker lock(isolate);
|
||||
|
||||
v8::Local<v8::Object> holder = v8::Local<v8::Object>::Cast<v8::Value>(info->Data());
|
||||
v8::Local<v8::String> data_key = v8::String::NewFromUtf8(isolate, "rr::data");
|
||||
v8::Local<v8::Value> data(holder->GetHiddenValue(data_key));
|
||||
|
||||
return Value::handleToRubyObject(info->GetIsolate(), data);
|
||||
}
|
||||
|
||||
static VALUE GetIsolate(VALUE self) {
|
||||
PropertyCallbackInfo info(self);
|
||||
return Isolate(info->GetIsolate());
|
||||
}
|
||||
|
||||
static VALUE GetReturnValue(VALUE self) {
|
||||
PropertyCallbackInfo info(self);
|
||||
Locker lock(info->GetIsolate());
|
||||
return ReturnValue(info->GetReturnValue());
|
||||
}
|
||||
|
||||
static inline void Init() {
|
||||
ClassBuilder("PropertyCallbackInfo").
|
||||
defineMethod("This", &This).
|
||||
defineMethod("Data", &Data).
|
||||
defineMethod("GetIsolate", &GetIsolate).
|
||||
defineMethod("GetReturnValue", &GetReturnValue).
|
||||
store(&Class);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* RR_PROPERTY_CALLBACK_H */
|
18
ext/v8/rr.h
18
ext/v8/rr.h
|
@ -17,6 +17,8 @@ inline VALUE not_implemented(const char* message) {
|
|||
}
|
||||
|
||||
#include "class_builder.h"
|
||||
#include "enums.h"
|
||||
|
||||
#include "maybe.h"
|
||||
#include "equiv.h"
|
||||
#include "bool.h"
|
||||
|
@ -34,25 +36,29 @@ inline VALUE not_implemented(const char* message) {
|
|||
|
||||
#include "value.h"
|
||||
#include "boolean.h"
|
||||
#include "object.h"
|
||||
#include "array.h"
|
||||
|
||||
#include "primitive.h"
|
||||
#include "undefined.h"
|
||||
#include "null.h"
|
||||
#include "number.h"
|
||||
#include "integer.h"
|
||||
|
||||
|
||||
#include "external.h"
|
||||
// This one is named v8_string to avoid name collisions with C's string.h
|
||||
#include "name.h"
|
||||
// This one is named v8_string to avoid name collisions with C's string.h
|
||||
#include "rr_string.h"
|
||||
#include "symbol.h"
|
||||
|
||||
#include "function.h"
|
||||
|
||||
#include "object.h"
|
||||
#include "return-value.h"
|
||||
#include "property-callback-void.h"
|
||||
#include "property-callback.h"
|
||||
#include "array.h"
|
||||
|
||||
#include "script.h"
|
||||
#include "script-origin.h"
|
||||
#include "function.h"
|
||||
#include "return-value.h"
|
||||
#include "function-callback.h"
|
||||
|
||||
#endif
|
||||
|
|
21
spec/c/enum_spec.rb
Normal file
21
spec/c/enum_spec.rb
Normal file
|
@ -0,0 +1,21 @@
|
|||
require 'c_spec_helper'
|
||||
|
||||
describe V8::C do
|
||||
describe 'AccessControl' do
|
||||
it 'has all enum values' do
|
||||
expect(V8::C::AccessControl.const_defined? 'DEFAULT').to be true
|
||||
expect(V8::C::AccessControl.const_defined? 'ALL_CAN_READ').to be true
|
||||
expect(V8::C::AccessControl.const_defined? 'ALL_CAN_WRITE').to be true
|
||||
expect(V8::C::AccessControl.const_defined? 'PROHIBITS_OVERWRITING').to be true
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PropertyAttribute' do
|
||||
it 'has all enum values' do
|
||||
expect(V8::C::PropertyAttribute.const_defined? 'None').to be true
|
||||
expect(V8::C::PropertyAttribute.const_defined? 'ReadOnly').to be true
|
||||
expect(V8::C::PropertyAttribute.const_defined? 'DontEnum').to be true
|
||||
expect(V8::C::PropertyAttribute.const_defined? 'DontDelete').to be true
|
||||
end
|
||||
end
|
||||
end
|
|
@ -21,6 +21,85 @@ describe V8::C::Object do
|
|||
expect(maybe.FromJust().Utf8Value).to eq 'bar'
|
||||
end
|
||||
|
||||
it 'can determine if a key has been set' do
|
||||
o = V8::C::Object.New(@isolate)
|
||||
key = V8::C::String.NewFromUtf8(@isolate, 'foo')
|
||||
|
||||
o.Set(@ctx, key, key)
|
||||
|
||||
maybe = o.Has(@ctx, key)
|
||||
expect(maybe.IsJust()).to be true
|
||||
expect(maybe.FromJust()).to eq true
|
||||
end
|
||||
|
||||
it 'can delete keys' do
|
||||
o = V8::C::Object.New(@isolate)
|
||||
key = V8::C::String.NewFromUtf8(@isolate, 'foo')
|
||||
|
||||
o.Set(@ctx, key, key)
|
||||
|
||||
maybe = o.Delete(@ctx, key)
|
||||
expect(maybe.IsJust()).to be true
|
||||
expect(maybe.FromJust()).to eq true
|
||||
|
||||
maybe = o.Has(@ctx, key)
|
||||
expect(maybe.IsJust()).to be true
|
||||
expect(maybe.FromJust()).to eq false
|
||||
end
|
||||
|
||||
describe '#SetAccessor' do
|
||||
it 'can set getters' do
|
||||
o = V8::C::Object.New(@isolate)
|
||||
key = V8::C::String.NewFromUtf8(@isolate, 'foo')
|
||||
|
||||
data = V8::C::String.NewFromUtf8(@isolate, 'data')
|
||||
get_value = V8::C::String.NewFromUtf8(@isolate, 'bar')
|
||||
|
||||
get_name = nil
|
||||
get_data = nil
|
||||
|
||||
getter = proc do |name, info|
|
||||
get_name = name
|
||||
get_data = info.Data
|
||||
|
||||
info.GetReturnValue.Set(get_value)
|
||||
end
|
||||
|
||||
o.SetAccessor(@ctx, key, getter, nil, data)
|
||||
|
||||
maybe = o.Get(@ctx, key)
|
||||
expect(maybe.IsJust).to be true
|
||||
expect(maybe.FromJust.StrictEquals(get_value)).to be true
|
||||
|
||||
expect(get_name.Equals(key)).to be true
|
||||
expect(get_data.StrictEquals(data)).to be true
|
||||
end
|
||||
|
||||
it 'can set setters' do
|
||||
o = V8::C::Object.New(@isolate)
|
||||
key = V8::C::String.NewFromUtf8(@isolate, 'foo')
|
||||
data = V8::C::String.NewFromUtf8(@isolate, 'data')
|
||||
|
||||
set_value = nil
|
||||
set_data = nil
|
||||
|
||||
setter = proc do |name, value, info|
|
||||
set_data = info.Data
|
||||
|
||||
set_value = value
|
||||
end
|
||||
|
||||
o.SetAccessor(@ctx, key, proc { }, setter, data)
|
||||
|
||||
maybe = o.Set(@ctx, key, data)
|
||||
expect(maybe.IsJust).to be true
|
||||
expect(maybe.FromJust).to be true
|
||||
|
||||
expect(set_data.StrictEquals(data)).to be true
|
||||
expect(set_value.StrictEquals(data)).to be true
|
||||
end
|
||||
end
|
||||
|
||||
# TODO: Enable this when the methods are implemented in the extension
|
||||
# it 'can retrieve all property names' do
|
||||
# o = V8::C::Object.New
|
||||
|
|
Loading…
Add table
Reference in a new issue