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

Side by Side 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: blah 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « gin/object_template_builder.h ('k') | gin/wrappable.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "base/template_util.h"
9 #include "gin/converter.h" 9 #include "gin/converter.h"
10 #include "gin/public/wrapper_info.h" 10 #include "gin/public/wrapper_info.h"
11 11
12 namespace gin { 12 namespace gin {
13 13
14 // Wrappable is an abstract base class for C++ objects that have cooresponding 14 template<typename T>
15 // v8 wrapper objects. To retain a Wrappable object on the stack, use a 15 struct WrappableTraits {
16 // gin::Handle. 16 static WrapperInfo kWrapperInfo;
17 class Wrappable { 17 };
18
19 template<typename T>
20 WrapperInfo WrappableTraits<T>::kWrapperInfo = {
21 gin::kEmbedderNativeGin
22 };
23
24 struct WrappableTraitsTest {
25 static WrapperInfo* GetWrapperInfo();
26 };
27
28
29 // Wrappable is a base class for C++ objects that have cooresponding v8 wrapper
30 // objects. To retain a Wrappable object on the stack, use a gin::Handle.
31 //
32 // Usage:
33 // class MyClass : Wrappable<MyClass> {
34 // ...
35 // };
36 //
37 // Subclasses should have private constructors and expose a static Create
38 // function that returns a gin::Handle. Forcing creators through this static
39 // Create function will enforce that clients actually create a wrapper for the
40 // object. If clients fail to create a wrapper for a wrappable object, the
41 // object will leak because we use the weak callback from the wrapper as the
42 // signal to delete the wrapped object.
43 template<typename T>
44 class Wrappable;
45
46
47 class WrappableBase {
18 public: 48 public:
19 // Subclasses must return the WrapperInfo object associated with the
20 // v8::ObjectTemplate for their subclass. When creating a v8 wrapper for
21 // this object, we'll look up the appropriate v8::ObjectTemplate in the
22 // PerIsolateData using this WrapperInfo pointer.
23 virtual WrapperInfo* GetWrapperInfo() = 0;
24
25 // Subclasses much also contain a static member variable named |kWrapperInfo|
26 // of type WrapperInfo:
27 //
28 // static WrapperInfo kWrapperInfo;
29 //
30 // If |obj| is a concrete instance of the subclass, then obj->GetWrapperInfo()
31 // must return &kWrapperInfo.
32 //
33 // We use both the dynamic |GetWrapperInfo| function and the static
34 // |kWrapperInfo| member variable during wrapping and the unwrapping. During
35 // wrapping, we use GetWrapperInfo() to make sure we use the correct
36 // v8::ObjectTemplate for the object regardless of the declared C++ type.
37 // During unwrapping, we use the static member variable to prevent type errors
38 // during the downcast from Wrappable to the subclass.
39
40 // Retrieve (or create) the v8 wrapper object cooresponding to this object. 49 // Retrieve (or create) the v8 wrapper object cooresponding to this object.
41 // To customize the wrapper created for a subclass, override GetWrapperInfo() 50 // To customize the wrapper created for a subclass, override GetWrapperInfo()
42 // instead of overriding this function. 51 // instead of overriding this function.
43 v8::Handle<v8::Object> GetWrapper(v8::Isolate* isolate); 52 v8::Handle<v8::Object> GetWrapper(v8::Isolate* isolate);
44 53
45 // Subclasses should have private constructors and expose a static Create 54 virtual WrapperInfo* GetWrapperInfo() = 0;
46 // function that returns a gin::Handle. Forcing creators through this static
47 // Create function will enforce that clients actually create a wrapper for
48 // the object. If clients fail to create a wrapper for a wrappable object,
49 // the object will leak because we use the weak callback from the wrapper
50 // as the signal to delete the wrapped object.
51 55
52 protected: 56 protected:
53 Wrappable(); 57 WrappableBase();
54 virtual ~Wrappable(); 58 virtual ~WrappableBase();
55 59
56 private: 60 private:
57 static void WeakCallback( 61 static void WeakCallback(
58 const v8::WeakCallbackData<v8::Object, Wrappable>& data); 62 const v8::WeakCallbackData<v8::Object, WrappableBase>& data);
59 v8::Handle<v8::Object> CreateWrapper(v8::Isolate* isolate); 63 v8::Handle<v8::Object> CreateWrapper(v8::Isolate* isolate);
60 64
61 v8::Persistent<v8::Object> wrapper_; // Weak 65 v8::Persistent<v8::Object> wrapper_; // Weak
62 66
63 DISALLOW_COPY_AND_ASSIGN(Wrappable); 67 DISALLOW_COPY_AND_ASSIGN(WrappableBase);
64 }; 68 };
65 69
70
71 template<typename T>
72 class Wrappable : public WrappableBase {
73 public:
74 virtual WrapperInfo* GetWrapperInfo() {
Aaron Boodman 2013/12/06 22:40:55 I am kind of grumpy about the extra inheritance an
abarth-chromium 2013/12/06 23:03:10 It's a security check to catch a class of use-afte
75 return &WrappableTraits<T>::kWrapperInfo;
76 }
77 };
78
79
66 // This converter handles any subclass of Wrappable. 80 // This converter handles any subclass of Wrappable.
67 template<typename T> 81 template<typename T>
68 struct Converter<T*, typename base::enable_if< 82 struct Converter<T*, typename base::enable_if<
69 base::is_convertible<T*, Wrappable*>::value>::type> { 83 base::is_convertible<T*, Wrappable<T>*>::value>::type> {
70 static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate, T* val) { 84 static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate, T* val) {
71 return val->GetWrapper(isolate); 85 return val->GetWrapper(isolate);
72 } 86 }
73 87
74 static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val, T** out) { 88 static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val, T** out) {
75 if (!val->IsObject()) 89 if (!val->IsObject())
76 return false; 90 return false;
77 v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(val); 91 v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(val);
78 WrapperInfo* info = WrapperInfo::From(obj); 92 WrapperInfo* info = WrapperInfo::From(obj);
79 93
80 // If this fails, the object is not managed by Gin. It is either a normal JS 94 // 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 95 // 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). 96 // some C++ object, but that object isn't managed by Gin (maybe Blink).
83 if (!info) 97 if (!info)
84 return false; 98 return false;
85 99
86 // If this fails, the object is managed by Gin, but it's not wrapping an 100 // If this fails, the object is managed by Gin, but it's not wrapping an
87 // instance of T. 101 // instance of T.
88 if (info != &T::kWrapperInfo) 102 if (info != &WrappableTraits<T>::kWrapperInfo)
89 return false; 103 return false;
90 104
91 void* pointer = obj->GetAlignedPointerFromInternalField(kEncodedValueIndex); 105 void* pointer = obj->GetAlignedPointerFromInternalField(kEncodedValueIndex);
92 T* result = static_cast<T*>(pointer); 106 T* result = static_cast<T*>(pointer);
93 107
94 // If this fails, something fishy is going on. |info| should have come from 108 // 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. 109 // T::GetWrapperInfo(), but somehow is now different than it. So panic.
96 CHECK(result->GetWrapperInfo() == info); 110 CHECK(result->GetWrapperInfo() == info);
97 *out = result; 111 *out = result;
98 return true; 112 return true;
99 } 113 }
100 }; 114 };
101 115
102 } // namespace gin 116 } // namespace gin
103 117
104 #endif // GIN_WRAPPABLE_H_ 118 #endif // GIN_WRAPPABLE_H_
OLDNEW
« 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