Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef GIN_WRAPPABLE_H_ | 5 #ifndef GIN_WRAPPABLE_H_ |
| 6 #define GIN_WRAPPABLE_H_ | 6 #define GIN_WRAPPABLE_H_ |
| 7 | 7 |
| 8 #include "base/template_util.h" | |
| 8 #include "gin/converter.h" | 9 #include "gin/converter.h" |
| 9 #include "gin/public/wrapper_info.h" | 10 #include "gin/public/wrapper_info.h" |
| 10 | 11 |
| 11 namespace gin { | 12 namespace gin { |
| 12 | 13 |
| 13 // Wrappable is an abstract base class for C++ objects that have cooresponding | 14 // Wrappable is an abstract base class for C++ objects that have cooresponding |
| 14 // v8 wrapper objects. To retain a Wrappable object on the stack, use a | 15 // v8 wrapper objects. To retain a Wrappable object on the stack, use a |
| 15 // gin::Handle. | 16 // gin::Handle. |
| 16 class Wrappable { | 17 class Wrappable { |
| 17 public: | 18 public: |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 46 // Create function will enforce that clients actually create a wrapper for | 47 // Create function will enforce that clients actually create a wrapper for |
| 47 // the object. If clients fail to create a wrapper for a wrappable object, | 48 // the object. If clients fail to create a wrapper for a wrappable object, |
| 48 // the object will leak because we use the weak callback from the wrapper | 49 // the object will leak because we use the weak callback from the wrapper |
| 49 // as the signal to delete the wrapped object. | 50 // as the signal to delete the wrapped object. |
| 50 | 51 |
| 51 protected: | 52 protected: |
| 52 Wrappable(); | 53 Wrappable(); |
| 53 virtual ~Wrappable(); | 54 virtual ~Wrappable(); |
| 54 | 55 |
| 55 private: | 56 private: |
| 56 friend struct Converter<Wrappable*>; | |
| 57 | |
| 58 static void WeakCallback( | 57 static void WeakCallback( |
| 59 const v8::WeakCallbackData<v8::Object, Wrappable>& data); | 58 const v8::WeakCallbackData<v8::Object, Wrappable>& data); |
| 60 v8::Handle<v8::Object> CreateWrapper(v8::Isolate* isolate); | 59 v8::Handle<v8::Object> CreateWrapper(v8::Isolate* isolate); |
| 61 | 60 |
| 62 v8::Persistent<v8::Object> wrapper_; // Weak | 61 v8::Persistent<v8::Object> wrapper_; // Weak |
| 63 | 62 |
| 64 DISALLOW_COPY_AND_ASSIGN(Wrappable); | 63 DISALLOW_COPY_AND_ASSIGN(Wrappable); |
| 65 }; | 64 }; |
| 66 | 65 |
| 67 template<> | 66 // This converter handles any subclass of Wrappable. |
| 68 struct Converter<Wrappable*> { | 67 template<typename T> |
| 69 static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate, | 68 struct Converter<T*, typename base::enable_if< |
| 70 Wrappable* val); | 69 base::is_convertible<T*, Wrappable*>::value>::type> { |
| 71 static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val, | 70 static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate, T* val) { |
| 72 Wrappable** out); | 71 return val->GetWrapper(isolate); |
| 73 }; | 72 } |
| 74 | 73 |
| 75 template<typename T> | |
| 76 struct WrappableConverter { | |
| 77 static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate, T* val) { | |
| 78 return Converter<Wrappable*>::ToV8(isolate, val); | |
| 79 } | |
| 80 static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val, T** out) { | 74 static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val, T** out) { |
| 81 Wrappable* wrappable = NULL; | 75 if (!val->IsObject()) |
| 82 if (!Converter<Wrappable*>::FromV8(isolate, val, &wrappable) | |
| 83 || wrappable->GetWrapperInfo() != &T::kWrapperInfo) | |
| 84 return false; | 76 return false; |
| 85 // Currently we require that you unwrap to the exact runtime type of the | 77 v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(val); |
| 86 // wrapped object. | 78 WrapperInfo* info = WrapperInfo::From(obj); |
| 87 // TODO(abarth): Support unwrapping to a base class. | 79 |
| 88 *out = static_cast<T*>(wrappable); | 80 // If this fails, the object is not managed by Gin. It is either a normal JS |
| 81 // object that's not wrapping any external C++ object, or it is wrapping | |
| 82 // some C++ object, but that object isn't managed by Gin (maybe Blink). | |
| 83 if (!info) | |
| 84 return false; | |
| 85 | |
| 86 // If this fails, the object is managed by Gin, but it's not wrapping an | |
| 87 // instance of T. | |
| 88 if (info != &T::kWrapperInfo) | |
| 89 return false; | |
| 90 | |
| 91 void* pointer = obj->GetAlignedPointerFromInternalField(kEncodedValueIndex); | |
| 92 T* result = static_cast<T*>(pointer); | |
| 93 | |
| 94 // If this fails, something fishy is going on. |info| should have come from | |
| 95 // T::GetWrapperInfo(), but somehow is now different than it. So panic. | |
| 96 CHECK(result->GetWrapperInfo() == info); | |
| 97 *out = result; | |
| 89 return true; | 98 return true; |
|
abarth-chromium
2013/12/06 03:35:08
Perfect.
| |
| 90 } | 99 } |
| 91 }; | 100 }; |
| 92 | 101 |
| 93 } // namespace gin | 102 } // namespace gin |
| 94 | 103 |
| 95 #endif // GIN_WRAPPABLE_H_ | 104 #endif // GIN_WRAPPABLE_H_ |
| OLD | NEW |