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 "platform/heap/Handle.h" 36 #include "wtf/Assertions.h" 37 #include <v8.h> 38 39 namespace WebCore { 40 41 class ActiveDOMObject; 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 typedef v8::Handle<v8::FunctionTemplate> (*DomTemplateFunction)(v8::Isolate*); 55 typedef void (*DerefObjectFunction)(void*); 56 typedef ActiveDOMObject* (*ToActiveDOMObjectFunction)(v8::Handle<v8::Object>); 57 typedef EventTarget* (*ToEventTargetFunction)(v8::Handle<v8::Object>); 58 typedef void (*ResolveWrapperReachabilityFunction)(void*, const v8::Persistent<v8::Object>&, v8::Isolate*); 59 typedef void (*InstallPerContextEnabledPrototypePropertiesFunction)(v8::Handle<v8::Object>, v8::Isolate*); 60 61 enum WrapperTypePrototype { 62 WrapperTypeObjectPrototype, 63 WrapperTypeExceptionPrototype 64 }; 65 66 enum GCType { 67 GarbageCollectedObject, 68 WillBeGarbageCollectedObject, 69 RefCountedObject, 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) const 104 { 105 return domTemplateFunction(isolate); 106 } 107 108 void installPerContextEnabledMethods(v8::Handle<v8::Object> prototypeTemplate, v8::Isolate* isolate) const 109 { 110 if (installPerContextEnabledMethodsFunction) 111 installPerContextEnabledMethodsFunction(prototypeTemplate, isolate); 112 } 113 114 ActiveDOMObject* toActiveDOMObject(v8::Handle<v8::Object> object) const 115 { 116 if (!toActiveDOMObjectFunction) 117 return 0; 118 return toActiveDOMObjectFunction(object); 119 } 120 121 EventTarget* toEventTarget(v8::Handle<v8::Object> object) const 122 { 123 if (!toEventTargetFunction) 124 return 0; 125 return toEventTargetFunction(object); 126 } 127 128 void visitDOMWrapper(void* object, const v8::Persistent<v8::Object>& wrapper, v8::Isolate* isolate) const 129 { 130 if (!visitDOMWrapperFunction) 131 setObjectGroup(object, wrapper, isolate); 132 else 133 visitDOMWrapperFunction(object, wrapper, isolate); 134 } 135 136 // This field must be the first member of the struct WrapperTypeInfo. This is also checked by a COMPILE_ASSERT() below. 137 const gin::GinEmbedder ginEmbedder; 138 139 const DomTemplateFunction domTemplateFunction; 140 const DerefObjectFunction derefObjectFunction; 141 const ToActiveDOMObjectFunction toActiveDOMObjectFunction; 142 const ToEventTargetFunction toEventTargetFunction; 143 const ResolveWrapperReachabilityFunction visitDOMWrapperFunction; 144 const InstallPerContextEnabledPrototypePropertiesFunction installPerContextEnabledMethodsFunction; 145 const WrapperTypeInfo* parentClass; 146 const WrapperTypePrototype wrapperTypePrototype; 147 const GCType gcType; 148 }; 149 150 151 COMPILE_ASSERT(offsetof(struct WrapperTypeInfo, ginEmbedder) == offsetof(struct gin::WrapperInfo, embedder), wrapper_type_info_compatible_to_gin); 152 153 template<typename T, int offset> 154 inline T* getInternalField(const v8::Persistent<v8::Object>& persistent) 155 { 156 // This would be unsafe, but InternalFieldCount and GetAlignedPointerFromInternalField are guaranteed not to allocate 157 const v8::Handle<v8::Object>& object = reinterpret_cast<const v8::Handle<v8::Object>&>(persistent); 158 ASSERT(offset < object->InternalFieldCount()); 159 return static_cast<T*>(object->GetAlignedPointerFromInternalField(offset)); 160 } 161 162 template<typename T, int offset> 163 inline T* getInternalField(v8::Handle<v8::Object> wrapper) 164 { 165 ASSERT(offset < wrapper->InternalFieldCount()); 166 return static_cast<T*>(wrapper->GetAlignedPointerFromInternalField(offset)); 167 } 168 169 inline void* toNative(const v8::Persistent<v8::Object>& wrapper) 170 { 171 return getInternalField<void, v8DOMWrapperObjectIndex>(wrapper); 172 } 173 174 inline void* toNative(v8::Handle<v8::Object> wrapper) 175 { 176 return getInternalField<void, v8DOMWrapperObjectIndex>(wrapper); 177 } 178 179 inline const WrapperTypeInfo* toWrapperTypeInfo(const v8::Persistent<v8::Object>& wrapper) 180 { 181 return getInternalField<WrapperTypeInfo, v8DOMWrapperTypeIndex>(wrapper); 182 } 183 184 inline const WrapperTypeInfo* toWrapperTypeInfo(v8::Handle<v8::Object> wrapper) 185 { 186 return getInternalField<WrapperTypeInfo, v8DOMWrapperTypeIndex>(wrapper); 187 } 188 189 inline const PersistentNode* toPersistentHandle(const v8::Handle<v8::Object>& wrapper) 190 { 191 // Persistent handle is stored in the last internal field. 192 return static_cast<PersistentNode*>(wrapper->GetAlignedPointerFromInternalField(wrapper->InternalFieldCount() - 1)); 193 } 194 195 inline void releaseObject(v8::Handle<v8::Object> wrapper) 196 { 197 const WrapperTypeInfo* typeInfo = toWrapperTypeInfo(wrapper); 198 if (typeInfo->gcType == GarbageCollectedObject) { 199 const PersistentNode* handle = toPersistentHandle(wrapper); 200 // This will be null iff a wrapper for a hidden wrapper object, 201 // see V8DOMWrapper::setNativeInfoForHiddenWrapper(). 202 delete handle; 203 } else if (typeInfo->gcType == WillBeGarbageCollectedObject) { 204 #if ENABLE(OILPAN) 205 const PersistentNode* handle = toPersistentHandle(wrapper); 206 // This will be null iff a wrapper for a hidden wrapper object, 207 // see V8DOMWrapper::setNativeInfoForHiddenWrapper(). 208 delete handle; 209 #else 210 ASSERT(typeInfo->derefObjectFunction); 211 typeInfo->derefObjectFunction(toNative(wrapper)); 212 #endif 213 } else { 214 ASSERT(typeInfo->derefObjectFunction); 215 typeInfo->derefObjectFunction(toNative(wrapper)); 216 } 217 } 218 219 struct WrapperConfiguration { 220 221 enum Lifetime { 222 Dependent, Independent 223 }; 224 225 void configureWrapper(v8::PersistentBase<v8::Object>* wrapper) const 226 { 227 wrapper->SetWrapperClassId(classId); 228 if (lifetime == Independent) 229 wrapper->MarkIndependent(); 230 } 231 232 const uint16_t classId; 233 const Lifetime lifetime; 234 }; 235 236 inline WrapperConfiguration buildWrapperConfiguration(void*, WrapperConfiguration::Lifetime lifetime) 237 { 238 WrapperConfiguration configuration = {v8DOMObjectClassId, lifetime}; 239 return configuration; 240 } 241 242 inline WrapperConfiguration buildWrapperConfiguration(Node*, WrapperConfiguration::Lifetime lifetime) 243 { 244 WrapperConfiguration configuration = {v8DOMNodeClassId, lifetime}; 245 return configuration; 246 } 247 } 248 249 #endif // WrapperTypeInfo_h 250