Index: gin/wrappable.h |
diff --git a/gin/wrappable.h b/gin/wrappable.h |
index cd4d30e91552702650b8ec995bedaea1183f1145..67512e2239f4b1f028cffc4b2740aa5bc79ed977 100644 |
--- a/gin/wrappable.h |
+++ b/gin/wrappable.h |
@@ -5,6 +5,7 @@ |
#ifndef GIN_WRAPPABLE_H_ |
#define GIN_WRAPPABLE_H_ |
+#include "base/logging.h" |
#include "base/template_util.h" |
#include "gin/converter.h" |
#include "gin/gin_export.h" |
@@ -12,15 +13,6 @@ |
namespace gin { |
-namespace internal { |
- |
-GIN_EXPORT void* FromV8Impl(v8::Isolate* isolate, |
- v8::Local<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. |
// |
@@ -51,8 +43,6 @@ GIN_EXPORT void* FromV8Impl(v8::Isolate* isolate, |
// 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 ObjectTemplateBuilder; |
@@ -65,7 +55,7 @@ class GIN_EXPORT WrappableBase { |
virtual ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate* isolate); |
v8::Local<v8::Object> GetWrapperImpl(v8::Isolate* isolate, |
- WrapperInfo* wrapper_info); |
+ WrapperInfo* wrapper_info); |
private: |
static void FirstWeakCallback( |
@@ -82,11 +72,16 @@ class GIN_EXPORT WrappableBase { |
template<typename T> |
class Wrappable : public WrappableBase { |
public: |
+ // Subclasses derived from T that override GetObjectTemplateBuilder must |
+ // also override this method. Otherwise, they will have the same WrapperInfo |
+ // as T, and share a cached v8::ObjectTemplate. That will lead to crashes. |
+ virtual WrapperInfo* GetWrapperInfo() { return &T::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::Local<v8::Object> GetWrapper(v8::Isolate* isolate) { |
- return GetWrapperImpl(isolate, &T::kWrapperInfo); |
+ return GetWrapperImpl(isolate, GetWrapperInfo()); |
} |
protected: |
@@ -97,7 +92,6 @@ class Wrappable : public WrappableBase { |
DISALLOW_COPY_AND_ASSIGN(Wrappable); |
}; |
- |
// This converter handles any subclass of Wrappable. |
template<typename T> |
struct Converter<T*, typename base::enable_if< |
@@ -107,9 +101,28 @@ struct Converter<T*, typename base::enable_if< |
} |
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val, T** out) { |
tommycli
2015/06/02 22:01:23
These changes are inspired by reverting some chang
|
- *out = static_cast<T*>(static_cast<WrappableBase*>( |
- internal::FromV8Impl(isolate, val, &T::kWrapperInfo))); |
- return *out != NULL; |
+ if (!val->IsObject()) |
+ return false; |
+ v8::Local<v8::Object> obj = v8::Local<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; |
+ |
+ // The stored pointer points to the WrappableBase portion of the object, |
+ // so we must convert to WrappableBase first, then downcast, to correctly |
+ // adjust the pointer to point to the the T object. |
+ WrappableBase* pointer = static_cast<WrappableBase*>( |
+ obj->GetAlignedPointerFromInternalField(kEncodedValueIndex)); |
+ |
+ // There is no way to detect if pointer is really of type T without RTTI. |
+ // We cannot compare to &T::kWrapperInfo, as subclasses of T can override |
+ // GetWrapperInfo(). This is unfortunate, but needed to support subclasses. |
tommycli
2015/06/02 22:01:23
I tried various methods for hours, but my conclusi
|
+ *out = static_cast<T*>(pointer); |
+ return true; |
} |
}; |