Allow specify methods that can be called after object is destroyed

This commit is contained in:
Cheng Zhao 2015-07-06 21:25:55 +08:00
parent 7b9926807d
commit 41cd6d13c9
3 changed files with 41 additions and 16 deletions

View file

@ -21,6 +21,7 @@ class PerIsolateData;
enum CreateFunctionTemplateFlags { enum CreateFunctionTemplateFlags {
HolderIsFirstArgument = 1 << 0, HolderIsFirstArgument = 1 << 0,
SafeAfterDestroyed = 1 << 1,
}; };
namespace internal { namespace internal {
@ -377,6 +378,7 @@ struct Dispatcher<R(P1)> {
typename CallbackParamTraits<P1>::LocalType a1; typename CallbackParamTraits<P1>::LocalType a1;
if ((holder->flags & HolderIsFirstArgument) && if ((holder->flags & HolderIsFirstArgument) &&
!(holder->flags & SafeAfterDestroyed) &&
DestroyedChecker<typename DestroyedChecker<typename
CallbackParamTraits<P1>::LocalType>::IsDestroyed(&args)) { CallbackParamTraits<P1>::LocalType>::IsDestroyed(&args)) {
args.ThrowError("Object has been destroyed"); args.ThrowError("Object has been destroyed");
@ -406,6 +408,7 @@ struct Dispatcher<R(P1, P2)> {
typename CallbackParamTraits<P1>::LocalType a1; typename CallbackParamTraits<P1>::LocalType a1;
typename CallbackParamTraits<P2>::LocalType a2; typename CallbackParamTraits<P2>::LocalType a2;
if ((holder->flags & HolderIsFirstArgument) && if ((holder->flags & HolderIsFirstArgument) &&
!(holder->flags & SafeAfterDestroyed) &&
DestroyedChecker<typename DestroyedChecker<typename
CallbackParamTraits<P1>::LocalType>::IsDestroyed(&args)) { CallbackParamTraits<P1>::LocalType>::IsDestroyed(&args)) {
args.ThrowError("Object has been destroyed"); args.ThrowError("Object has been destroyed");
@ -437,6 +440,7 @@ struct Dispatcher<R(P1, P2, P3)> {
typename CallbackParamTraits<P2>::LocalType a2; typename CallbackParamTraits<P2>::LocalType a2;
typename CallbackParamTraits<P3>::LocalType a3; typename CallbackParamTraits<P3>::LocalType a3;
if ((holder->flags & HolderIsFirstArgument) && if ((holder->flags & HolderIsFirstArgument) &&
!(holder->flags & SafeAfterDestroyed) &&
DestroyedChecker<typename DestroyedChecker<typename
CallbackParamTraits<P1>::LocalType>::IsDestroyed(&args)) { CallbackParamTraits<P1>::LocalType>::IsDestroyed(&args)) {
args.ThrowError("Object has been destroyed"); args.ThrowError("Object has been destroyed");
@ -470,6 +474,7 @@ struct Dispatcher<R(P1, P2, P3, P4)> {
typename CallbackParamTraits<P3>::LocalType a3; typename CallbackParamTraits<P3>::LocalType a3;
typename CallbackParamTraits<P4>::LocalType a4; typename CallbackParamTraits<P4>::LocalType a4;
if ((holder->flags & HolderIsFirstArgument) && if ((holder->flags & HolderIsFirstArgument) &&
!(holder->flags & SafeAfterDestroyed) &&
DestroyedChecker<typename DestroyedChecker<typename
CallbackParamTraits<P1>::LocalType>::IsDestroyed(&args)) { CallbackParamTraits<P1>::LocalType>::IsDestroyed(&args)) {
args.ThrowError("Object has been destroyed"); args.ThrowError("Object has been destroyed");
@ -507,6 +512,7 @@ struct Dispatcher<R(P1, P2, P3, P4, P5)> {
typename CallbackParamTraits<P4>::LocalType a4; typename CallbackParamTraits<P4>::LocalType a4;
typename CallbackParamTraits<P5>::LocalType a5; typename CallbackParamTraits<P5>::LocalType a5;
if ((holder->flags & HolderIsFirstArgument) && if ((holder->flags & HolderIsFirstArgument) &&
!(holder->flags & SafeAfterDestroyed) &&
DestroyedChecker<typename DestroyedChecker<typename
CallbackParamTraits<P1>::LocalType>::IsDestroyed(&args)) { CallbackParamTraits<P1>::LocalType>::IsDestroyed(&args)) {
args.ThrowError("Object has been destroyed"); args.ThrowError("Object has been destroyed");
@ -546,6 +552,7 @@ struct Dispatcher<R(P1, P2, P3, P4, P5, P6)> {
typename CallbackParamTraits<P5>::LocalType a5; typename CallbackParamTraits<P5>::LocalType a5;
typename CallbackParamTraits<P6>::LocalType a6; typename CallbackParamTraits<P6>::LocalType a6;
if ((holder->flags & HolderIsFirstArgument) && if ((holder->flags & HolderIsFirstArgument) &&
!(holder->flags & SafeAfterDestroyed) &&
DestroyedChecker<typename DestroyedChecker<typename
CallbackParamTraits<P1>::LocalType>::IsDestroyed(&args)) { CallbackParamTraits<P1>::LocalType>::IsDestroyed(&args)) {
args.ThrowError("Object has been destroyed"); args.ThrowError("Object has been destroyed");
@ -587,6 +594,7 @@ struct Dispatcher<R(P1, P2, P3, P4, P5, P6, P7)> {
typename CallbackParamTraits<P6>::LocalType a6; typename CallbackParamTraits<P6>::LocalType a6;
typename CallbackParamTraits<P7>::LocalType a7; typename CallbackParamTraits<P7>::LocalType a7;
if ((holder->flags & HolderIsFirstArgument) && if ((holder->flags & HolderIsFirstArgument) &&
!(holder->flags & SafeAfterDestroyed) &&
DestroyedChecker<typename DestroyedChecker<typename
CallbackParamTraits<P1>::LocalType>::IsDestroyed(&args)) { CallbackParamTraits<P1>::LocalType>::IsDestroyed(&args)) {
args.ThrowError("Object has been destroyed"); args.ThrowError("Object has been destroyed");

View file

@ -24,6 +24,7 @@ class PerIsolateData;
enum CreateFunctionTemplateFlags { enum CreateFunctionTemplateFlags {
HolderIsFirstArgument = 1 << 0, HolderIsFirstArgument = 1 << 0,
SafeAfterDestroyed = 1 << 1,
}; };
namespace internal { namespace internal {
@ -202,6 +203,7 @@ $for ARG [[ typename CallbackParamTraits<P$(ARG)>::LocalType a$(ARG);
]] ]]
if ((holder->flags & HolderIsFirstArgument) && if ((holder->flags & HolderIsFirstArgument) &&
!(holder->flags & SafeAfterDestroyed) &&
DestroyedChecker<typename CallbackParamTraits<P1>::LocalType>::IsDestroyed(&args)) { DestroyedChecker<typename CallbackParamTraits<P1>::LocalType>::IsDestroyed(&args)) {
args.ThrowError("Object has been destroyed"); args.ThrowError("Object has been destroyed");
MATE_METHOD_RETURN_UNDEFINED(); MATE_METHOD_RETURN_UNDEFINED();

View file

@ -23,7 +23,8 @@ namespace {
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(v8::Isolate* isolate,
T callback) { T callback,
bool = true) {
return CreateFunctionTemplate(isolate, base::Bind(callback)); return CreateFunctionTemplate(isolate, base::Bind(callback));
} }
}; };
@ -32,7 +33,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) { v8::Isolate* isolate, const base::Callback<T>& callback, bool = true) {
return CreateFunctionTemplate(isolate, callback); return CreateFunctionTemplate(isolate, callback);
} }
}; };
@ -44,10 +45,12 @@ struct CallbackTraits<base::Callback<T> > {
template<typename T> 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(v8::Isolate* isolate, static v8::Local<v8::FunctionTemplate> CreateTemplate(
T callback) { v8::Isolate* isolate, T callback, bool safe_after_destroyed = false) {
return CreateFunctionTemplate(isolate, base::Bind(callback), int flags = HolderIsFirstArgument;
HolderIsFirstArgument); if (safe_after_destroyed)
flags |= SafeAfterDestroyed;
return CreateFunctionTemplate(isolate, base::Bind(callback), flags);
} }
}; };
@ -87,22 +90,34 @@ 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,
const T& callback) { const T& callback,
return SetImpl(name, CallbackTraits<T>::CreateTemplate(isolate_, callback)); bool safe_after_destroyed = false) {
return SetImpl(name,
CallbackTraits<T>::CreateTemplate(isolate_,
callback,
safe_after_destroyed));
} }
template<typename T> template<typename T>
ObjectTemplateBuilder& SetProperty(const base::StringPiece& name, ObjectTemplateBuilder& SetProperty(const base::StringPiece& name,
const T& getter) { const T& getter,
return SetPropertyImpl(name, bool safe_after_destroyed = false) {
CallbackTraits<T>::CreateTemplate(isolate_, getter), return SetPropertyImpl(
name,
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,
const T& getter, const U& setter) { const T& getter,
return SetPropertyImpl(name, const U& setter,
CallbackTraits<T>::CreateTemplate(isolate_, getter), bool safe_after_destroyed = false) {
CallbackTraits<U>::CreateTemplate(isolate_, setter)); return SetPropertyImpl(
name,
CallbackTraits<T>::CreateTemplate(isolate_, getter,
safe_after_destroyed),
CallbackTraits<U>::CreateTemplate(isolate_, setter,
safe_after_destroyed));
} }
v8::Local<v8::ObjectTemplate> Build(); v8::Local<v8::ObjectTemplate> Build();