Chromium Code Reviews| Index: gin/wrappable.h |
| diff --git a/gin/wrappable.h b/gin/wrappable.h |
| index 741bf8ff6d11b72ef7a3ffc4297868aa2346adf4..84187048669643e5a82eacf9186cc6249f5a2e0c 100644 |
| --- a/gin/wrappable.h |
| +++ b/gin/wrappable.h |
| @@ -11,62 +11,76 @@ |
| namespace gin { |
| -// Wrappable is an abstract base class for C++ objects that have cooresponding |
| -// v8 wrapper objects. To retain a Wrappable object on the stack, use a |
| -// gin::Handle. |
| -class Wrappable { |
| - public: |
| - // Subclasses must return the WrapperInfo object associated with the |
| - // v8::ObjectTemplate for their subclass. When creating a v8 wrapper for |
| - // this object, we'll look up the appropriate v8::ObjectTemplate in the |
| - // PerIsolateData using this WrapperInfo pointer. |
| - virtual WrapperInfo* GetWrapperInfo() = 0; |
| +template<typename T> |
| +struct WrappableTraits { |
| + static WrapperInfo kWrapperInfo; |
| +}; |
| - // Subclasses much also contain a static member variable named |kWrapperInfo| |
| - // of type WrapperInfo: |
| - // |
| - // static WrapperInfo kWrapperInfo; |
| - // |
| - // If |obj| is a concrete instance of the subclass, then obj->GetWrapperInfo() |
| - // must return &kWrapperInfo. |
| - // |
| - // We use both the dynamic |GetWrapperInfo| function and the static |
| - // |kWrapperInfo| member variable during wrapping and the unwrapping. During |
| - // wrapping, we use GetWrapperInfo() to make sure we use the correct |
| - // v8::ObjectTemplate for the object regardless of the declared C++ type. |
| - // During unwrapping, we use the static member variable to prevent type errors |
| - // during the downcast from Wrappable to the subclass. |
| +template<typename T> |
| +WrapperInfo WrappableTraits<T>::kWrapperInfo = { |
| + gin::kEmbedderNativeGin |
| +}; |
| + |
| +struct WrappableTraitsTest { |
| + static WrapperInfo* GetWrapperInfo(); |
| +}; |
| + |
| + |
| +// Wrappable is a base class for C++ objects that have cooresponding v8 wrapper |
| +// objects. To retain a Wrappable object on the stack, use a gin::Handle. |
| +// |
| +// Usage: |
| +// class MyClass : Wrappable<MyClass> { |
| +// ... |
| +// }; |
| +// |
| +// Subclasses should have private constructors and expose a static Create |
| +// function that returns a gin::Handle. Forcing creators through this static |
| +// Create function will enforce that clients actually create a wrapper for the |
| +// object. If clients fail to create a wrapper for a wrappable object, the |
| +// object will leak because we use the weak callback from the wrapper as the |
| +// signal to delete the wrapped object. |
| +template<typename T> |
| +class Wrappable; |
| + |
| +class WrappableBase { |
| + public: |
| // Retrieve (or create) the v8 wrapper object cooresponding to this object. |
| // To customize the wrapper created for a subclass, override GetWrapperInfo() |
| // instead of overriding this function. |
| v8::Handle<v8::Object> GetWrapper(v8::Isolate* isolate); |
| - // Subclasses should have private constructors and expose a static Create |
| - // function that returns a gin::Handle. Forcing creators through this static |
| - // Create function will enforce that clients actually create a wrapper for |
| - // the object. If clients fail to create a wrapper for a wrappable object, |
| - // the object will leak because we use the weak callback from the wrapper |
| - // as the signal to delete the wrapped object. |
| + virtual WrapperInfo* GetWrapperInfo() = 0; |
| protected: |
| - Wrappable(); |
| - virtual ~Wrappable(); |
| + WrappableBase(); |
| + virtual ~WrappableBase(); |
| private: |
| static void WeakCallback( |
| - const v8::WeakCallbackData<v8::Object, Wrappable>& data); |
| + const v8::WeakCallbackData<v8::Object, WrappableBase>& data); |
| v8::Handle<v8::Object> CreateWrapper(v8::Isolate* isolate); |
| v8::Persistent<v8::Object> wrapper_; // Weak |
| - DISALLOW_COPY_AND_ASSIGN(Wrappable); |
| + DISALLOW_COPY_AND_ASSIGN(WrappableBase); |
| +}; |
| + |
| + |
| +template<typename T> |
| +class Wrappable : public WrappableBase { |
| + public: |
| + virtual WrapperInfo* GetWrapperInfo() { |
|
Aaron Boodman
2013/12/06 22:40:55
I am kind of grumpy about the extra inheritance an
abarth-chromium
2013/12/06 23:03:10
It's a security check to catch a class of use-afte
|
| + return &WrappableTraits<T>::kWrapperInfo; |
| + } |
| }; |
| + |
| // This converter handles any subclass of Wrappable. |
| template<typename T> |
| struct Converter<T*, typename base::enable_if< |
| - base::is_convertible<T*, Wrappable*>::value>::type> { |
| + base::is_convertible<T*, Wrappable<T>*>::value>::type> { |
| static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate, T* val) { |
| return val->GetWrapper(isolate); |
| } |
| @@ -85,7 +99,7 @@ struct Converter<T*, typename base::enable_if< |
| // If this fails, the object is managed by Gin, but it's not wrapping an |
| // instance of T. |
| - if (info != &T::kWrapperInfo) |
| + if (info != &WrappableTraits<T>::kWrapperInfo) |
| return false; |
| void* pointer = obj->GetAlignedPointerFromInternalField(kEncodedValueIndex); |