| Index: gin/wrappable.h
|
| diff --git a/gin/wrappable.h b/gin/wrappable.h
|
| index 741bf8ff6d11b72ef7a3ffc4297868aa2346adf4..3f9ebe3c19697ad9391e98bbddbdc18ae2839ffd 100644
|
| --- a/gin/wrappable.h
|
| +++ b/gin/wrappable.h
|
| @@ -11,91 +11,93 @@
|
|
|
| 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;
|
| -
|
| - // 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.
|
| -
|
| - // 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);
|
| +namespace internal {
|
| +
|
| +void* FromV8Impl(v8::Isolate* isolate, v8::Handle<v8::Value> val,
|
| + WrapperInfo* info);
|
| +
|
| +} // namespace internal
|
| +
|
| +
|
| +// Wrappable is a base class for C++ objects that have corresponding v8 wrapper
|
| +// objects. To retain a Wrappable object on the stack, use a gin::Handle.
|
| +//
|
| +// USAGE:
|
| +// // my_class.h
|
| +// class MyClass : Wrappable<MyClass> {
|
| +// ...
|
| +// };
|
| +//
|
| +// // my_class.cc
|
| +// INIT_WRAPABLE(MyClass);
|
| +//
|
| +// Subclasses should also typically 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;
|
|
|
| - // 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.
|
|
|
| +// Non-template base class to share code between templates instances.
|
| +class WrappableBase {
|
| protected:
|
| - Wrappable();
|
| - virtual ~Wrappable();
|
| + WrappableBase();
|
| + ~WrappableBase();
|
| + v8::Handle<v8::Object> GetWrapperImpl(v8::Isolate* isolate,
|
| + WrapperInfo* wrapper_info);
|
| + v8::Handle<v8::Object> CreateWrapper(v8::Isolate* isolate,
|
| + WrapperInfo* wrapper_info);
|
| + v8::Persistent<v8::Object> wrapper_; // Weak
|
|
|
| private:
|
| static void WeakCallback(
|
| - const v8::WeakCallbackData<v8::Object, Wrappable>& data);
|
| - v8::Handle<v8::Object> CreateWrapper(v8::Isolate* isolate);
|
| + const v8::WeakCallbackData<v8::Object, WrappableBase>& data);
|
|
|
| - v8::Persistent<v8::Object> wrapper_; // Weak
|
| + DISALLOW_COPY_AND_ASSIGN(WrappableBase);
|
| +};
|
| +
|
| +
|
| +template<typename T>
|
| +class Wrappable : public WrappableBase {
|
| + public:
|
| + static WrapperInfo kWrapperInfo;
|
|
|
| + // 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) {
|
| + return GetWrapperImpl(isolate, &kWrapperInfo);
|
| + }
|
| +
|
| + protected:
|
| + Wrappable() {}
|
| + ~Wrappable() {}
|
| DISALLOW_COPY_AND_ASSIGN(Wrappable);
|
| };
|
|
|
| +
|
| +// Subclasses of Wrappable must call this within a cc file to initialize their
|
| +// WrapperInfo.
|
| +#define INIT_WRAPPABLE(TYPE) \
|
| +template<> \
|
| +gin::WrapperInfo gin::Wrappable<TYPE>::kWrapperInfo = { kEmbedderNativeGin };
|
| +
|
| +
|
| // 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);
|
| }
|
|
|
| static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val, T** out) {
|
| - if (!val->IsObject())
|
| - return false;
|
| - v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(val);
|
| - WrapperInfo* info = WrapperInfo::From(obj);
|
| -
|
| - // If this fails, the object is not managed by Gin. It is either a normal JS
|
| - // object that's not wrapping any external C++ object, or it is wrapping
|
| - // some C++ object, but that object isn't managed by Gin (maybe Blink).
|
| - if (!info)
|
| - return false;
|
| -
|
| - // If this fails, the object is managed by Gin, but it's not wrapping an
|
| - // instance of T.
|
| - if (info != &T::kWrapperInfo)
|
| - return false;
|
| -
|
| - void* pointer = obj->GetAlignedPointerFromInternalField(kEncodedValueIndex);
|
| - T* result = static_cast<T*>(pointer);
|
| -
|
| - // If this fails, something fishy is going on. |info| should have come from
|
| - // T::GetWrapperInfo(), but somehow is now different than it. So panic.
|
| - CHECK(result->GetWrapperInfo() == info);
|
| - *out = result;
|
| - return true;
|
| + *out = static_cast<T*>(internal::FromV8Impl(isolate, val,
|
| + &T::kWrapperInfo));
|
| + return *out != NULL;
|
| }
|
| };
|
|
|
|
|