Do not manually destroy native resources
This commit is contained in:
parent
9398494100
commit
e859228db1
6 changed files with 37 additions and 47 deletions
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue