Chromium Code Reviews| Index: gin/wrappable.h |
| diff --git a/gin/wrappable.h b/gin/wrappable.h |
| index 0fa3697863fde2c453e3077c515e89dcc6386471..741bf8ff6d11b72ef7a3ffc4297868aa2346adf4 100644 |
| --- a/gin/wrappable.h |
| +++ b/gin/wrappable.h |
| @@ -5,6 +5,7 @@ |
| #ifndef GIN_WRAPPABLE_H_ |
| #define GIN_WRAPPABLE_H_ |
| +#include "base/template_util.h" |
| #include "gin/converter.h" |
| #include "gin/public/wrapper_info.h" |
| @@ -53,8 +54,6 @@ class Wrappable { |
| virtual ~Wrappable(); |
| private: |
| - friend struct Converter<Wrappable*>; |
| - |
| static void WeakCallback( |
| const v8::WeakCallbackData<v8::Object, Wrappable>& data); |
| v8::Handle<v8::Object> CreateWrapper(v8::Isolate* isolate); |
| @@ -64,28 +63,38 @@ class Wrappable { |
| DISALLOW_COPY_AND_ASSIGN(Wrappable); |
| }; |
| -template<> |
| -struct Converter<Wrappable*> { |
| - static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate, |
| - Wrappable* val); |
| - static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val, |
| - Wrappable** out); |
| -}; |
| - |
| +// This converter handles any subclass of Wrappable. |
| template<typename T> |
| -struct WrappableConverter { |
| +struct Converter<T*, typename base::enable_if< |
| + base::is_convertible<T*, Wrappable*>::value>::type> { |
| static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate, T* val) { |
| - return Converter<Wrappable*>::ToV8(isolate, val); |
| + return val->GetWrapper(isolate); |
| } |
| + |
| static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val, T** out) { |
| - Wrappable* wrappable = NULL; |
| - if (!Converter<Wrappable*>::FromV8(isolate, val, &wrappable) |
| - || wrappable->GetWrapperInfo() != &T::kWrapperInfo) |
| + 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; |
| - // Currently we require that you unwrap to the exact runtime type of the |
| - // wrapped object. |
| - // TODO(abarth): Support unwrapping to a base class. |
| - *out = static_cast<T*>(wrappable); |
| + |
| + 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; |
|
abarth-chromium
2013/12/06 03:35:08
Perfect.
|
| } |
| }; |