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); explicit Arguments(const MATE_METHOD_ARGS_TYPE& info);
~Arguments(); ~Arguments();
v8::Local<v8::Object> GetHolder() const {
return info_->Holder();
}
template<typename T> template<typename T>
bool GetHolder(T* out) { bool GetHolder(T* out) {
return ConvertFromV8(isolate_, info_->Holder(), out); return ConvertFromV8(isolate_, info_->Holder(), out);

View file

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

View file

@ -32,6 +32,12 @@ ObjectTemplateBuilder& ObjectTemplateBuilder::SetPropertyImpl(
return *this; 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> ObjectTemplateBuilder::Build() {
v8::Local<v8::ObjectTemplate> result = template_; v8::Local<v8::ObjectTemplate> result = template_;
template_.Clear(); template_.Clear();

View file

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

View file

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

View file

@ -13,6 +13,8 @@ namespace mate {
namespace internal { namespace internal {
struct Destroyable;
void* FromV8Impl(v8::Isolate* isolate, v8::Local<v8::Value> val); void* FromV8Impl(v8::Isolate* isolate, v8::Local<v8::Value> val);
} // namespace internal } // namespace internal
@ -54,10 +56,6 @@ class Wrappable {
// object constructed by GetObjectTemplateBuilder. // object constructed by GetObjectTemplateBuilder.
v8::Local<v8::Object> GetWrapper(v8::Isolate* isolate); 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. // Returns the Isolate this object is created in.
v8::Isolate* isolate() const { return isolate_; } v8::Isolate* isolate() const { return isolate_; }
@ -79,6 +77,8 @@ class Wrappable {
virtual void AfterInit(v8::Isolate* isolate) {} virtual void AfterInit(v8::Isolate* isolate) {}
private: private:
friend struct internal::Destroyable;
static void FirstWeakCallback(const v8::WeakCallbackInfo<Wrappable>& data); static void FirstWeakCallback(const v8::WeakCallbackInfo<Wrappable>& data);
static void SecondWeakCallback(const v8::WeakCallbackInfo<Wrappable>& data); static void SecondWeakCallback(const v8::WeakCallbackInfo<Wrappable>& data);