From 41cd6d13c9c9be164f427864277f3cc36b69eb39 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 6 Jul 2015 21:25:55 +0800 Subject: [PATCH] Allow specify methods that can be called after object is destroyed --- native_mate/function_template.h | 8 +++++ native_mate/function_template.h.pump | 2 ++ native_mate/object_template_builder.h | 47 ++++++++++++++++++--------- 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/native_mate/function_template.h b/native_mate/function_template.h index 808d4b6..59a9996 100644 --- a/native_mate/function_template.h +++ b/native_mate/function_template.h @@ -21,6 +21,7 @@ class PerIsolateData; enum CreateFunctionTemplateFlags { HolderIsFirstArgument = 1 << 0, + SafeAfterDestroyed = 1 << 1, }; namespace internal { @@ -377,6 +378,7 @@ struct Dispatcher { typename CallbackParamTraits::LocalType a1; if ((holder->flags & HolderIsFirstArgument) && + !(holder->flags & SafeAfterDestroyed) && DestroyedChecker::LocalType>::IsDestroyed(&args)) { args.ThrowError("Object has been destroyed"); @@ -406,6 +408,7 @@ struct Dispatcher { typename CallbackParamTraits::LocalType a1; typename CallbackParamTraits::LocalType a2; if ((holder->flags & HolderIsFirstArgument) && + !(holder->flags & SafeAfterDestroyed) && DestroyedChecker::LocalType>::IsDestroyed(&args)) { args.ThrowError("Object has been destroyed"); @@ -437,6 +440,7 @@ struct Dispatcher { typename CallbackParamTraits::LocalType a2; typename CallbackParamTraits::LocalType a3; if ((holder->flags & HolderIsFirstArgument) && + !(holder->flags & SafeAfterDestroyed) && DestroyedChecker::LocalType>::IsDestroyed(&args)) { args.ThrowError("Object has been destroyed"); @@ -470,6 +474,7 @@ struct Dispatcher { typename CallbackParamTraits::LocalType a3; typename CallbackParamTraits::LocalType a4; if ((holder->flags & HolderIsFirstArgument) && + !(holder->flags & SafeAfterDestroyed) && DestroyedChecker::LocalType>::IsDestroyed(&args)) { args.ThrowError("Object has been destroyed"); @@ -507,6 +512,7 @@ struct Dispatcher { typename CallbackParamTraits::LocalType a4; typename CallbackParamTraits::LocalType a5; if ((holder->flags & HolderIsFirstArgument) && + !(holder->flags & SafeAfterDestroyed) && DestroyedChecker::LocalType>::IsDestroyed(&args)) { args.ThrowError("Object has been destroyed"); @@ -546,6 +552,7 @@ struct Dispatcher { typename CallbackParamTraits::LocalType a5; typename CallbackParamTraits::LocalType a6; if ((holder->flags & HolderIsFirstArgument) && + !(holder->flags & SafeAfterDestroyed) && DestroyedChecker::LocalType>::IsDestroyed(&args)) { args.ThrowError("Object has been destroyed"); @@ -587,6 +594,7 @@ struct Dispatcher { typename CallbackParamTraits::LocalType a6; typename CallbackParamTraits::LocalType a7; if ((holder->flags & HolderIsFirstArgument) && + !(holder->flags & SafeAfterDestroyed) && DestroyedChecker::LocalType>::IsDestroyed(&args)) { args.ThrowError("Object has been destroyed"); diff --git a/native_mate/function_template.h.pump b/native_mate/function_template.h.pump index 34033bc..10e6475 100644 --- a/native_mate/function_template.h.pump +++ b/native_mate/function_template.h.pump @@ -24,6 +24,7 @@ class PerIsolateData; enum CreateFunctionTemplateFlags { HolderIsFirstArgument = 1 << 0, + SafeAfterDestroyed = 1 << 1, }; namespace internal { @@ -202,6 +203,7 @@ $for ARG [[ typename CallbackParamTraits::LocalType a$(ARG); ]] if ((holder->flags & HolderIsFirstArgument) && + !(holder->flags & SafeAfterDestroyed) && DestroyedChecker::LocalType>::IsDestroyed(&args)) { args.ThrowError("Object has been destroyed"); MATE_METHOD_RETURN_UNDEFINED(); diff --git a/native_mate/object_template_builder.h b/native_mate/object_template_builder.h index d37f009..2f30b37 100644 --- a/native_mate/object_template_builder.h +++ b/native_mate/object_template_builder.h @@ -23,7 +23,8 @@ namespace { template struct CallbackTraits { static v8::Local CreateTemplate(v8::Isolate* isolate, - T callback) { + T callback, + bool = true) { return CreateFunctionTemplate(isolate, base::Bind(callback)); } }; @@ -32,7 +33,7 @@ struct CallbackTraits { template struct CallbackTraits > { static v8::Local CreateTemplate( - v8::Isolate* isolate, const base::Callback& callback) { + v8::Isolate* isolate, const base::Callback& callback, bool = true) { return CreateFunctionTemplate(isolate, callback); } }; @@ -44,10 +45,12 @@ struct CallbackTraits > { template struct CallbackTraits::value>::type> { - static v8::Local CreateTemplate(v8::Isolate* isolate, - T callback) { - return CreateFunctionTemplate(isolate, base::Bind(callback), - HolderIsFirstArgument); + static v8::Local CreateTemplate( + v8::Isolate* isolate, T callback, bool safe_after_destroyed = false) { + int flags = 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. template ObjectTemplateBuilder& SetMethod(const base::StringPiece& name, - const T& callback) { - return SetImpl(name, CallbackTraits::CreateTemplate(isolate_, callback)); + const T& callback, + bool safe_after_destroyed = false) { + return SetImpl(name, + CallbackTraits::CreateTemplate(isolate_, + callback, + safe_after_destroyed)); } template ObjectTemplateBuilder& SetProperty(const base::StringPiece& name, - const T& getter) { - return SetPropertyImpl(name, - CallbackTraits::CreateTemplate(isolate_, getter), - v8::Local()); + const T& getter, + bool safe_after_destroyed = false) { + return SetPropertyImpl( + name, + CallbackTraits::CreateTemplate(isolate_, getter, + safe_after_destroyed), + v8::Local()); } template ObjectTemplateBuilder& SetProperty(const base::StringPiece& name, - const T& getter, const U& setter) { - return SetPropertyImpl(name, - CallbackTraits::CreateTemplate(isolate_, getter), - CallbackTraits::CreateTemplate(isolate_, setter)); + const T& getter, + const U& setter, + bool safe_after_destroyed = false) { + return SetPropertyImpl( + name, + CallbackTraits::CreateTemplate(isolate_, getter, + safe_after_destroyed), + CallbackTraits::CreateTemplate(isolate_, setter, + safe_after_destroyed)); } v8::Local Build();