Do not manually destroy native resources

This commit is contained in:
Cheng Zhao 2015-12-03 15:37:27 +08:00
parent 9398494100
commit e859228db1
6 changed files with 37 additions and 47 deletions

View file

@ -20,6 +20,10 @@ class Arguments {
explicit Arguments(const MATE_METHOD_ARGS_TYPE& info);
~Arguments();
v8::Local<v8::Object> GetHolder() const {
return info_->Holder();
}
template<typename T>
bool GetHolder(T* out) {
return ConvertFromV8(isolate_, info_->Holder(), out);

View file

@ -15,27 +15,20 @@ namespace mate {
enum CreateFunctionTemplateFlags {
HolderIsFirstArgument = 1 << 0,
SafeAfterDestroyed = 1 << 1,
};
namespace internal {
// Check if the class has been destroyed.
template<typename T, typename Enable = void>
struct DestroyedChecker {
static bool IsDestroyed(Arguments* args) {
return false;
struct Destroyable {
static void Destroy(Arguments* args) {
v8::Local<v8::Object> holder = args->GetHolder();
delete static_cast<Wrappable*>(holder->GetAlignedPointerFromInternalField(0));
holder->SetAlignedPointerInInternalField(0, nullptr);
}
};
template<typename T>
struct DestroyedChecker<T*, typename enable_if<
is_convertible<T*, Wrappable*>::value>::type> {
static bool IsDestroyed(Arguments* args) {
T* object;
if (args->GetHolder(&object))
return static_cast<Wrappable*>(object)->IsDestroyed();
else
return false;
v8::Local<v8::Object> holder = args->GetHolder();
return holder->InternalFieldCount() == 0 ||
holder->GetAlignedPointerFromInternalField(0) == nullptr;
}
};
@ -149,8 +142,7 @@ struct ArgumentHolder {
: ok(false) {
if (index == 0 &&
(create_flags & HolderIsFirstArgument) &&
!(create_flags & SafeAfterDestroyed) &&
DestroyedChecker<ArgLocalType>::IsDestroyed(args)) {
Destroyable::IsDestroyed(args)) {
args->ThrowError("Object has been destroyed");
return;
}

View file

@ -32,6 +32,12 @@ ObjectTemplateBuilder& ObjectTemplateBuilder::SetPropertyImpl(
return *this;
}
ObjectTemplateBuilder& ObjectTemplateBuilder::MakeDestroyable() {
SetMethod("destroy", base::Bind(internal::Destroyable::Destroy));
SetMethod("isDestroy", base::Bind(internal::Destroyable::IsDestroyed));
return *this;
}
v8::Local<v8::ObjectTemplate> ObjectTemplateBuilder::Build() {
v8::Local<v8::ObjectTemplate> result = template_;
template_.Clear();

View file

@ -22,9 +22,8 @@ namespace {
// because of base::Bind().
template<typename T, typename Enable = void>
struct CallbackTraits {
static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate,
T callback,
bool = true) {
static v8::Local<v8::FunctionTemplate> CreateTemplate(
v8::Isolate* isolate, T callback) {
return CreateFunctionTemplate(isolate, base::Bind(callback));
}
};
@ -33,7 +32,7 @@ struct CallbackTraits {
template<typename T>
struct CallbackTraits<base::Callback<T> > {
static v8::Local<v8::FunctionTemplate> CreateTemplate(
v8::Isolate* isolate, const base::Callback<T>& callback, bool = true) {
v8::Isolate* isolate, const base::Callback<T>& callback) {
return CreateFunctionTemplate(isolate, callback);
}
};
@ -46,10 +45,8 @@ template<typename T>
struct CallbackTraits<T, typename enable_if<
is_member_function_pointer<T>::value>::type> {
static v8::Local<v8::FunctionTemplate> CreateTemplate(
v8::Isolate* isolate, T callback, bool safe_after_destroyed = false) {
v8::Isolate* isolate, T callback) {
int flags = HolderIsFirstArgument;
if (safe_after_destroyed)
flags |= SafeAfterDestroyed;
return CreateFunctionTemplate(isolate, base::Bind(callback), flags);
}
};
@ -90,36 +87,31 @@ class ObjectTemplateBuilder {
// for creating raw function templates.
template<typename T>
ObjectTemplateBuilder& SetMethod(const base::StringPiece& name,
T callback,
bool safe_after_destroyed = false) {
T callback) {
return SetImpl(name,
CallbackTraits<T>::CreateTemplate(isolate_,
callback,
safe_after_destroyed));
CallbackTraits<T>::CreateTemplate(isolate_, callback));
}
template<typename T>
ObjectTemplateBuilder& SetProperty(const base::StringPiece& name,
T getter,
bool safe_after_destroyed = false) {
T getter) {
return SetPropertyImpl(
name,
CallbackTraits<T>::CreateTemplate(isolate_, getter,
safe_after_destroyed),
CallbackTraits<T>::CreateTemplate(isolate_, getter),
v8::Local<v8::FunctionTemplate>());
}
template<typename T, typename U>
ObjectTemplateBuilder& SetProperty(const base::StringPiece& name,
T getter,
U setter,
bool safe_after_destroyed = false) {
U setter) {
return SetPropertyImpl(
name,
CallbackTraits<T>::CreateTemplate(isolate_, getter,
safe_after_destroyed),
CallbackTraits<U>::CreateTemplate(isolate_, setter,
safe_after_destroyed));
CallbackTraits<T>::CreateTemplate(isolate_, getter),
CallbackTraits<U>::CreateTemplate(isolate_, setter));
}
// Add "destroy" and "isDestroyed" methods.
ObjectTemplateBuilder& MakeDestroyable();
v8::Local<v8::ObjectTemplate> Build();
private:

View file

@ -78,10 +78,6 @@ v8::Local<v8::Object> Wrappable::GetWrapper(v8::Isolate* isolate) {
return wrapper;
}
bool Wrappable::IsDestroyed() const {
return false;
}
namespace internal {
void* FromV8Impl(v8::Isolate* isolate, v8::Local<v8::Value> val) {

View file

@ -13,6 +13,8 @@ namespace mate {
namespace internal {
struct Destroyable;
void* FromV8Impl(v8::Isolate* isolate, v8::Local<v8::Value> val);
} // namespace internal
@ -54,10 +56,6 @@ class Wrappable {
// object constructed by GetObjectTemplateBuilder.
v8::Local<v8::Object> GetWrapper(v8::Isolate* isolate);
// Returns whether this class has been destroyed, users should override this
// method to indicate the native type's state.
virtual bool IsDestroyed() const;
// Returns the Isolate this object is created in.
v8::Isolate* isolate() const { return isolate_; }
@ -79,6 +77,8 @@ class Wrappable {
virtual void AfterInit(v8::Isolate* isolate) {}
private:
friend struct internal::Destroyable;
static void FirstWeakCallback(const v8::WeakCallbackInfo<Wrappable>& data);
static void SecondWeakCallback(const v8::WeakCallbackInfo<Wrappable>& data);