Home | History | Annotate | Download | only in v8
      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