Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(164)

Unified Diff: gin/wrappable.h

Issue 105743007: Gin: Make it easier to implement Wrappable (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: cleanup Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « gin/object_template_builder.h ('k') | gin/wrappable.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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;
}
};
« no previous file with comments | « gin/object_template_builder.h ('k') | gin/wrappable.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698