1 /* 2 * Copyright (C) 2006, 2008 Nikolas Zimmermann <zimmermann (at) kde.org> 3 * Copyright (C) 2008 Apple Inc. All rights reserved. 4 * Copyright (C) 2008, 2009 Google. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #ifndef V8SVGPODTypeWrapper_h 29 #define V8SVGPODTypeWrapper_h 30 31 #if ENABLE(SVG) 32 33 #include <utility> 34 35 #include "SVGElement.h" 36 #include "SVGList.h" 37 #include "V8Proxy.h" 38 39 #include <wtf/Assertions.h> 40 #include <wtf/HashFunctions.h> 41 #include <wtf/HashMap.h> 42 #include <wtf/RefCounted.h> 43 #include <wtf/StdLibExtras.h> 44 45 namespace WebCore { 46 47 template<typename PODType> 48 class V8SVGPODTypeWrapper : public RefCounted<V8SVGPODTypeWrapper<PODType> > { 49 public: 50 V8SVGPODTypeWrapper() { } 51 virtual ~V8SVGPODTypeWrapper() { } 52 virtual operator PODType() = 0; 53 virtual void commitChange(PODType, SVGElement*) = 0; 54 55 static V8SVGPODTypeWrapper<PODType>* toNative(v8::Handle<v8::Object> object) 56 { 57 return reinterpret_cast<V8SVGPODTypeWrapper<PODType>*>(object->GetPointerFromInternalField(v8DOMWrapperObjectIndex)); 58 } 59 }; 60 61 template<typename PODType> 62 class V8SVGPODTypeWrapperCreatorForList : public V8SVGPODTypeWrapper<PODType> { 63 public: 64 typedef SVGPODListItem<PODType> PODListItemPtrType; 65 66 typedef PODType (SVGPODListItem<PODType>::*GetterMethod)() const; 67 typedef void (SVGPODListItem<PODType>::*SetterMethod)(const PODType&); 68 69 static PassRefPtr<V8SVGPODTypeWrapperCreatorForList> create(PassRefPtr<PODListItemPtrType> creator, const QualifiedName& attributeName) 70 { 71 return adoptRef(new V8SVGPODTypeWrapperCreatorForList(creator, attributeName)); 72 } 73 74 virtual ~V8SVGPODTypeWrapperCreatorForList() { } 75 76 // Getter wrapper 77 virtual operator PODType() { return (m_creator.get()->*m_getter)(); } 78 79 // Setter wrapper 80 virtual void commitChange(PODType type, SVGElement* context) 81 { 82 if (!m_setter) 83 return; 84 85 (m_creator.get()->*m_setter)(type); 86 87 if (context) 88 context->svgAttributeChanged(m_associatedAttributeName); 89 } 90 91 private: 92 V8SVGPODTypeWrapperCreatorForList(PassRefPtr<PODListItemPtrType> creator, const QualifiedName& attributeName) 93 : m_creator(creator) 94 , m_getter(&SVGPODListItem<PODType>::value) 95 , m_setter(&SVGPODListItem<PODType>::setValue) 96 , m_associatedAttributeName(attributeName) 97 { 98 ASSERT(m_creator); 99 ASSERT(m_getter); 100 ASSERT(m_setter); 101 } 102 103 // Update callbacks 104 RefPtr<SVGPODListItem<PODType> > m_creator; 105 GetterMethod m_getter; 106 SetterMethod m_setter; 107 const QualifiedName& m_associatedAttributeName; 108 }; 109 110 template<typename PODType> 111 class V8SVGStaticPODTypeWrapper : public V8SVGPODTypeWrapper<PODType> { 112 public: 113 static PassRefPtr<V8SVGStaticPODTypeWrapper> create(PODType type) 114 { 115 return adoptRef(new V8SVGStaticPODTypeWrapper(type)); 116 } 117 118 virtual ~V8SVGStaticPODTypeWrapper() { } 119 120 // Getter wrapper 121 virtual operator PODType() { return m_podType; } 122 123 // Setter wrapper 124 virtual void commitChange(PODType type, SVGElement*) 125 { 126 m_podType = type; 127 } 128 129 protected: 130 V8SVGStaticPODTypeWrapper(PODType type) 131 : m_podType(type) 132 { 133 } 134 135 PODType m_podType; 136 }; 137 138 template<typename PODType, typename ParentTypeArg> 139 class V8SVGStaticPODTypeWrapperWithPODTypeParent : public V8SVGStaticPODTypeWrapper<PODType> { 140 public: 141 typedef V8SVGPODTypeWrapper<ParentTypeArg> ParentType; 142 143 static PassRefPtr<V8SVGStaticPODTypeWrapperWithPODTypeParent> create(PODType type, PassRefPtr<ParentType> parent) 144 { 145 return adoptRef(new V8SVGStaticPODTypeWrapperWithPODTypeParent(type, parent)); 146 } 147 148 virtual void commitChange(PODType type, SVGElement* context) 149 { 150 V8SVGStaticPODTypeWrapper<PODType>::commitChange(type, context); 151 m_parentType->commitChange(ParentTypeArg(type), context); 152 } 153 154 private: 155 V8SVGStaticPODTypeWrapperWithPODTypeParent(PODType type, PassRefPtr<ParentType> parent) 156 : V8SVGStaticPODTypeWrapper<PODType>(type) 157 , m_parentType(parent) 158 { 159 } 160 161 RefPtr<ParentType> m_parentType; 162 }; 163 164 template<typename PODType, typename ParentType> 165 class V8SVGStaticPODTypeWrapperWithParent : public V8SVGPODTypeWrapper<PODType> { 166 public: 167 typedef PODType (ParentType::*GetterMethod)() const; 168 typedef void (ParentType::*SetterMethod)(const PODType&); 169 170 static PassRefPtr<V8SVGStaticPODTypeWrapperWithParent> create(PassRefPtr<ParentType> parent, GetterMethod getter, SetterMethod setter) 171 { 172 return adoptRef(new V8SVGStaticPODTypeWrapperWithParent(parent, getter, setter)); 173 } 174 175 virtual operator PODType() 176 { 177 return (m_parent.get()->*m_getter)(); 178 } 179 180 virtual void commitChange(PODType type, SVGElement* context) 181 { 182 (m_parent.get()->*m_setter)(type); 183 } 184 185 private: 186 V8SVGStaticPODTypeWrapperWithParent(PassRefPtr<ParentType> parent, GetterMethod getter, SetterMethod setter) 187 : m_parent(parent) 188 , m_getter(getter) 189 , m_setter(setter) 190 { 191 ASSERT(m_parent); 192 ASSERT(m_getter); 193 ASSERT(m_setter); 194 } 195 196 RefPtr<ParentType> m_parent; 197 GetterMethod m_getter; 198 SetterMethod m_setter; 199 }; 200 201 template<typename PODType, typename PODTypeCreator> 202 class V8SVGDynamicPODTypeWrapper : public V8SVGPODTypeWrapper<PODType> { 203 public: 204 typedef PODType (PODTypeCreator::*GetterMethod)() const; 205 typedef void (PODTypeCreator::*SetterMethod)(const PODType&); 206 typedef void (*CacheRemovalCallback)(V8SVGPODTypeWrapper<PODType>*); 207 208 static PassRefPtr<V8SVGDynamicPODTypeWrapper> create(PassRefPtr<PODTypeCreator> creator, GetterMethod getter, SetterMethod setter, CacheRemovalCallback cacheRemovalCallback) 209 { 210 return adoptRef(new V8SVGDynamicPODTypeWrapper(creator, getter, setter, cacheRemovalCallback)); 211 } 212 213 virtual ~V8SVGDynamicPODTypeWrapper() { 214 ASSERT(m_cacheRemovalCallback); 215 216 (*m_cacheRemovalCallback)(this); 217 } 218 219 // Getter wrapper 220 virtual operator PODType() { return (m_creator.get()->*m_getter)(); } 221 222 // Setter wrapper 223 virtual void commitChange(PODType type, SVGElement* context) 224 { 225 (m_creator.get()->*m_setter)(type); 226 227 if (context) 228 context->svgAttributeChanged(m_creator->associatedAttributeName()); 229 } 230 231 private: 232 V8SVGDynamicPODTypeWrapper(PassRefPtr<PODTypeCreator> creator, GetterMethod getter, SetterMethod setter, CacheRemovalCallback cacheRemovalCallback) 233 : m_creator(creator) 234 , m_getter(getter) 235 , m_setter(setter) 236 , m_cacheRemovalCallback(cacheRemovalCallback) 237 { 238 ASSERT(m_creator); // |creator|'s pointer was taken by m_creator. 239 ASSERT(getter); 240 ASSERT(setter); 241 ASSERT(cacheRemovalCallback); 242 } 243 244 // Update callbacks 245 RefPtr<PODTypeCreator> m_creator; 246 GetterMethod m_getter; 247 SetterMethod m_setter; 248 CacheRemovalCallback m_cacheRemovalCallback; 249 }; 250 251 // Caching facilities 252 template<typename PODType, typename PODTypeCreator> 253 struct PODTypeWrapperCacheInfo { 254 typedef PODType (PODTypeCreator::*GetterMethod)() const; 255 typedef void (PODTypeCreator::*SetterMethod)(const PODType&); 256 257 // Empty value 258 PODTypeWrapperCacheInfo() 259 : creator(0) 260 , getter(0) 261 , setter(0) 262 , fieldHash(0) 263 { } 264 265 // Deleted value 266 explicit PODTypeWrapperCacheInfo(WTF::HashTableDeletedValueType) 267 : creator(reinterpret_cast<PODTypeCreator*>(-1)) 268 , getter(0) 269 , setter(0) 270 , fieldHash(0) 271 { 272 } 273 274 bool isHashTableDeletedValue() const 275 { 276 return creator == reinterpret_cast<PODTypeCreator*>(-1); 277 } 278 279 PODTypeWrapperCacheInfo(PODTypeCreator* _creator, GetterMethod _getter, SetterMethod _setter, unsigned _fieldHash) 280 : creator(_creator) 281 , getter(_getter) 282 , setter(_setter) 283 , fieldHash(_fieldHash) 284 { 285 ASSERT(creator); 286 ASSERT(getter); 287 } 288 289 bool operator==(const PODTypeWrapperCacheInfo& other) const 290 { 291 return creator == other.creator && fieldHash == other.fieldHash && getter == other.getter && setter == other.setter; 292 } 293 294 PODTypeCreator* creator; 295 GetterMethod getter; 296 SetterMethod setter; 297 unsigned fieldHash; 298 }; 299 300 template<typename PODType, typename PODTypeCreator> 301 struct PODTypeWrapperCacheInfoHash { 302 static unsigned hash(const PODTypeWrapperCacheInfo<PODType, PODTypeCreator>& info) 303 { 304 // We can't hash member function pointers, but we have enough material 305 // to hash the pointer and field identifier, and on a collision 306 // operator== will still differentiate the member function pointers. 307 return WTF::PairHash<void*, unsigned>::hash(std::pair<void*, unsigned>(info.creator, info.fieldHash)); 308 } 309 310 static bool equal(const PODTypeWrapperCacheInfo<PODType, PODTypeCreator>& a, const PODTypeWrapperCacheInfo<PODType, PODTypeCreator>& b) 311 { 312 return a == b; 313 } 314 315 static const bool safeToCompareToEmptyOrDeleted = true; 316 }; 317 318 template<typename PODType, typename PODTypeCreator> 319 struct PODTypeWrapperCacheInfoTraits : WTF::GenericHashTraits<PODTypeWrapperCacheInfo<PODType, PODTypeCreator> > { 320 typedef PODTypeWrapperCacheInfo<PODType, PODTypeCreator> CacheInfo; 321 322 static const bool emptyValueIsZero = true; 323 static const bool needsDestruction = false; 324 325 static const CacheInfo& emptyValue() 326 { 327 DEFINE_STATIC_LOCAL(CacheInfo, key, ()); 328 return key; 329 } 330 331 static void constructDeletedValue(CacheInfo& slot) 332 { 333 new (&slot) CacheInfo(WTF::HashTableDeletedValue); 334 } 335 336 static bool isDeletedValue(const CacheInfo& value) 337 { 338 return value.isHashTableDeletedValue(); 339 } 340 }; 341 342 template<typename PODType, typename PODTypeCreator> 343 class V8SVGDynamicPODTypeWrapperCache { 344 public: 345 typedef PODType (PODTypeCreator::*GetterMethod)() const; 346 typedef void (PODTypeCreator::*SetterMethod)(const PODType&); 347 348 typedef PODTypeWrapperCacheInfo<PODType, PODTypeCreator> CacheInfo; 349 typedef PODTypeWrapperCacheInfoHash<PODType, PODTypeCreator> CacheInfoHash; 350 typedef PODTypeWrapperCacheInfoTraits<PODType, PODTypeCreator> CacheInfoTraits; 351 352 typedef V8SVGPODTypeWrapper<PODType> WrapperBase; 353 typedef V8SVGDynamicPODTypeWrapper<PODType, PODTypeCreator> DynamicWrapper; 354 355 typedef HashMap<CacheInfo, DynamicWrapper*, CacheInfoHash, CacheInfoTraits> DynamicWrapperHashMap; 356 typedef typename DynamicWrapperHashMap::const_iterator DynamicWrapperHashMapIterator; 357 358 static DynamicWrapperHashMap& dynamicWrapperHashMap() 359 { 360 DEFINE_STATIC_LOCAL(DynamicWrapperHashMap, dynamicWrapperHashMap, ()); 361 return dynamicWrapperHashMap; 362 } 363 364 // Used for readwrite attributes only 365 static PassRefPtr<WrapperBase> lookupOrCreateWrapper(PODTypeCreator* creator, GetterMethod getter, SetterMethod setter, unsigned fieldHash) 366 { 367 DynamicWrapperHashMap& map(dynamicWrapperHashMap()); 368 CacheInfo info(creator, getter, setter, fieldHash); 369 370 if (map.contains(info)) 371 return map.get(info); 372 373 RefPtr<DynamicWrapper> wrapper = V8SVGDynamicPODTypeWrapper<PODType, PODTypeCreator>::create(creator, getter, setter, forgetWrapper); 374 map.set(info, wrapper.get()); 375 return wrapper.release(); 376 } 377 378 static void forgetWrapper(V8SVGPODTypeWrapper<PODType>* wrapper) 379 { 380 DynamicWrapperHashMap& map(dynamicWrapperHashMap()); 381 382 DynamicWrapperHashMapIterator it = map.begin(); 383 DynamicWrapperHashMapIterator end = map.end(); 384 385 for (; it != end; ++it) { 386 if (it->second != wrapper) 387 continue; 388 389 // It's guaranteed that there's just one object we need to take care of. 390 map.remove(it->first); 391 break; 392 } 393 } 394 }; 395 396 class V8SVGPODTypeUtil { 397 public: 398 template <class P> 399 static P toSVGPODType(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Value> object, bool& ok); 400 }; 401 402 template <class P> 403 P V8SVGPODTypeUtil::toSVGPODType(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Value> object, bool& ok) 404 { 405 if (!V8DOMWrapper::isWrapperOfType(object, type)) { 406 ok = false; 407 return P(); 408 } 409 ok = true; 410 return *V8SVGPODTypeWrapper<P>::toNative(v8::Handle<v8::Object>::Cast(object)); 411 } 412 413 } // namespace WebCore 414 415 #endif // ENABLE(SVG) 416 #endif // V8SVGPODTypeWrapper_h 417