1 /* 2 * Copyright (C) 2010 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #ifndef WrapperTypeInfo_h 32 #define WrapperTypeInfo_h 33 34 #include "gin/public/wrapper_info.h" 35 #include "wtf/Assertions.h" 36 #include <v8.h> 37 38 namespace WebCore { 39 40 class ActiveDOMObject; 41 class DOMDataStore; 42 class EventTarget; 43 class Node; 44 45 static const int v8DOMWrapperTypeIndex = static_cast<int>(gin::kWrapperInfoIndex); 46 static const int v8DOMWrapperObjectIndex = static_cast<int>(gin::kEncodedValueIndex); 47 static const int v8DefaultWrapperInternalFieldCount = static_cast<int>(gin::kNumberOfInternalFields); 48 static const int v8PrototypeTypeIndex = 0; 49 static const int v8PrototypeInternalFieldcount = 1; 50 51 static const uint16_t v8DOMNodeClassId = 1; 52 static const uint16_t v8DOMObjectClassId = 2; 53 54 enum WrapperWorldType { 55 MainWorld, 56 IsolatedWorld, 57 WorkerWorld 58 }; 59 60 typedef v8::Handle<v8::FunctionTemplate> (*DomTemplateFunction)(v8::Isolate*, WrapperWorldType); 61 typedef void (*DerefObjectFunction)(void*); 62 typedef ActiveDOMObject* (*ToActiveDOMObjectFunction)(v8::Handle<v8::Object>); 63 typedef EventTarget* (*ToEventTargetFunction)(v8::Handle<v8::Object>); 64 typedef void (*ResolveWrapperReachabilityFunction)(void*, const v8::Persistent<v8::Object>&, v8::Isolate*); 65 typedef void (*InstallPerContextEnabledPrototypePropertiesFunction)(v8::Handle<v8::Object>, v8::Isolate*); 66 67 enum WrapperTypePrototype { 68 WrapperTypeObjectPrototype, 69 WrapperTypeErrorPrototype 70 }; 71 72 inline void setObjectGroup(void* object, const v8::Persistent<v8::Object>& wrapper, v8::Isolate* isolate) 73 { 74 isolate->SetObjectGroupId(wrapper, v8::UniqueId(reinterpret_cast<intptr_t>(object))); 75 } 76 77 // This struct provides a way to store a bunch of information that is helpful when unwrapping 78 // v8 objects. Each v8 bindings class has exactly one static WrapperTypeInfo member, so 79 // comparing pointers is a safe way to determine if types match. 80 struct WrapperTypeInfo { 81 82 static const WrapperTypeInfo* unwrap(v8::Handle<v8::Value> typeInfoWrapper) 83 { 84 return reinterpret_cast<const WrapperTypeInfo*>(v8::External::Cast(*typeInfoWrapper)->Value()); 85 } 86 87 88 bool equals(const WrapperTypeInfo* that) const 89 { 90 return this == that; 91 } 92 93 bool isSubclass(const WrapperTypeInfo* that) const 94 { 95 for (const WrapperTypeInfo* current = this; current; current = current->parentClass) { 96 if (current == that) 97 return true; 98 } 99 100 return false; 101 } 102 103 v8::Handle<v8::FunctionTemplate> domTemplate(v8::Isolate* isolate, WrapperWorldType worldType) const { return domTemplateFunction(isolate, worldType); } 104 105 void derefObject(void* object) const 106 { 107 if (derefObjectFunction) 108 derefObjectFunction(object); 109 } 110 111 void installPerContextEnabledMethods(v8::Handle<v8::Object> prototypeTemplate, v8::Isolate* isolate) const 112 { 113 if (installPerContextEnabledMethodsFunction) 114 installPerContextEnabledMethodsFunction(prototypeTemplate, isolate); 115 } 116 117 ActiveDOMObject* toActiveDOMObject(v8::Handle<v8::Object> object) const 118 { 119 if (!toActiveDOMObjectFunction) 120 return 0; 121 return toActiveDOMObjectFunction(object); 122 } 123 124 EventTarget* toEventTarget(v8::Handle<v8::Object> object) const 125 { 126 if (!toEventTargetFunction) 127 return 0; 128 return toEventTargetFunction(object); 129 } 130 131 void visitDOMWrapper(void* object, const v8::Persistent<v8::Object>& wrapper, v8::Isolate* isolate) const 132 { 133 if (!visitDOMWrapperFunction) 134 setObjectGroup(object, wrapper, isolate); 135 else 136 visitDOMWrapperFunction(object, wrapper, isolate); 137 } 138 139 // This field must be the first member of the struct WrapperTypeInfo. This is also checked by a COMPILE_ASSERT() below. 140 const gin::GinEmbedder ginEmbedder; 141 142 const DomTemplateFunction domTemplateFunction; 143 const DerefObjectFunction derefObjectFunction; 144 const ToActiveDOMObjectFunction toActiveDOMObjectFunction; 145 const ToEventTargetFunction toEventTargetFunction; 146 const ResolveWrapperReachabilityFunction visitDOMWrapperFunction; 147 const InstallPerContextEnabledPrototypePropertiesFunction installPerContextEnabledMethodsFunction; 148 const WrapperTypeInfo* parentClass; 149 const WrapperTypePrototype wrapperTypePrototype; 150 }; 151 152 153 COMPILE_ASSERT(offsetof(struct WrapperTypeInfo, ginEmbedder) == offsetof(struct gin::WrapperInfo, embedder), wrapper_type_info_compatible_to_gin); 154 155 template<typename T, int offset> 156 inline T* getInternalField(const v8::Persistent<v8::Object>& persistent) 157 { 158 // This would be unsafe, but InternalFieldCount and GetAlignedPointerFromInternalField are guaranteed not to allocate 159 const v8::Handle<v8::Object>& object = reinterpret_cast<const v8::Handle<v8::Object>&>(persistent); 160 ASSERT(offset < object->InternalFieldCount()); 161 return static_cast<T*>(object->GetAlignedPointerFromInternalField(offset)); 162 } 163 164 template<typename T, int offset> 165 inline T* getInternalField(v8::Handle<v8::Object> object) 166 { 167 ASSERT(offset < object->InternalFieldCount()); 168 return static_cast<T*>(object->GetAlignedPointerFromInternalField(offset)); 169 } 170 171 inline void* toNative(const v8::Persistent<v8::Object>& object) 172 { 173 return getInternalField<void, v8DOMWrapperObjectIndex>(object); 174 } 175 176 inline void* toNative(v8::Handle<v8::Object> object) 177 { 178 return getInternalField<void, v8DOMWrapperObjectIndex>(object); 179 } 180 181 inline const WrapperTypeInfo* toWrapperTypeInfo(const v8::Persistent<v8::Object>& object) 182 { 183 return getInternalField<WrapperTypeInfo, v8DOMWrapperTypeIndex>(object); 184 } 185 186 inline const WrapperTypeInfo* toWrapperTypeInfo(v8::Handle<v8::Object> object) 187 { 188 return getInternalField<WrapperTypeInfo, v8DOMWrapperTypeIndex>(object); 189 } 190 191 struct WrapperConfiguration { 192 193 enum Lifetime { 194 Dependent, Independent 195 }; 196 197 void configureWrapper(v8::Persistent<v8::Object>* wrapper) const 198 { 199 wrapper->SetWrapperClassId(classId); 200 if (lifetime == Independent) 201 wrapper->MarkIndependent(); 202 } 203 204 const uint16_t classId; 205 const Lifetime lifetime; 206 }; 207 208 inline WrapperConfiguration buildWrapperConfiguration(void*, WrapperConfiguration::Lifetime lifetime) 209 { 210 WrapperConfiguration configuration = {v8DOMObjectClassId, lifetime}; 211 return configuration; 212 } 213 214 inline WrapperConfiguration buildWrapperConfiguration(Node*, WrapperConfiguration::Lifetime lifetime) 215 { 216 WrapperConfiguration configuration = {v8DOMNodeClassId, lifetime}; 217 return configuration; 218 } 219 220 template<class ElementType> 221 class WrapperTypeTraits { 222 // specialized classes have thier own functions, which are generated by binding generator. 223 }; 224 } 225 226 #endif // WrapperTypeInfo_h 227