/* * Copyright (C) 2006, 2008 Nikolas Zimmermann * Copyright (C) 2008 Apple Inc. All rights reserved. * Copyright (C) 2008, 2009 Google. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef V8SVGPODTypeWrapper_h #define V8SVGPODTypeWrapper_h #if ENABLE(SVG) #include #include "SVGElement.h" #include "SVGList.h" #include "V8Proxy.h" #include #include #include #include #include namespace WebCore { template class V8SVGPODTypeWrapper : public RefCounted > { public: V8SVGPODTypeWrapper() { } virtual ~V8SVGPODTypeWrapper() { } virtual operator PODType() = 0; virtual void commitChange(PODType, SVGElement*) = 0; static V8SVGPODTypeWrapper* toNative(v8::Handle object) { return reinterpret_cast*>(object->GetPointerFromInternalField(v8DOMWrapperObjectIndex)); } }; template class V8SVGPODTypeWrapperCreatorForList : public V8SVGPODTypeWrapper { public: typedef SVGPODListItem PODListItemPtrType; typedef PODType (SVGPODListItem::*GetterMethod)() const; typedef void (SVGPODListItem::*SetterMethod)(const PODType&); static PassRefPtr create(PassRefPtr creator, const QualifiedName& attributeName) { return adoptRef(new V8SVGPODTypeWrapperCreatorForList(creator, attributeName)); } virtual ~V8SVGPODTypeWrapperCreatorForList() { } // Getter wrapper virtual operator PODType() { return (m_creator.get()->*m_getter)(); } // Setter wrapper virtual void commitChange(PODType type, SVGElement* context) { if (!m_setter) return; (m_creator.get()->*m_setter)(type); if (context) context->svgAttributeChanged(m_associatedAttributeName); } private: V8SVGPODTypeWrapperCreatorForList(PassRefPtr creator, const QualifiedName& attributeName) : m_creator(creator) , m_getter(&SVGPODListItem::value) , m_setter(&SVGPODListItem::setValue) , m_associatedAttributeName(attributeName) { ASSERT(m_creator); ASSERT(m_getter); ASSERT(m_setter); } // Update callbacks RefPtr > m_creator; GetterMethod m_getter; SetterMethod m_setter; const QualifiedName& m_associatedAttributeName; }; template class V8SVGStaticPODTypeWrapper : public V8SVGPODTypeWrapper { public: static PassRefPtr create(PODType type) { return adoptRef(new V8SVGStaticPODTypeWrapper(type)); } virtual ~V8SVGStaticPODTypeWrapper() { } // Getter wrapper virtual operator PODType() { return m_podType; } // Setter wrapper virtual void commitChange(PODType type, SVGElement*) { m_podType = type; } protected: V8SVGStaticPODTypeWrapper(PODType type) : m_podType(type) { } PODType m_podType; }; template class V8SVGStaticPODTypeWrapperWithPODTypeParent : public V8SVGStaticPODTypeWrapper { public: typedef V8SVGPODTypeWrapper ParentType; static PassRefPtr create(PODType type, PassRefPtr parent) { return adoptRef(new V8SVGStaticPODTypeWrapperWithPODTypeParent(type, parent)); } virtual void commitChange(PODType type, SVGElement* context) { V8SVGStaticPODTypeWrapper::commitChange(type, context); m_parentType->commitChange(ParentTypeArg(type), context); } private: V8SVGStaticPODTypeWrapperWithPODTypeParent(PODType type, PassRefPtr parent) : V8SVGStaticPODTypeWrapper(type) , m_parentType(parent) { } RefPtr m_parentType; }; template class V8SVGStaticPODTypeWrapperWithParent : public V8SVGPODTypeWrapper { public: typedef PODType (ParentType::*GetterMethod)() const; typedef void (ParentType::*SetterMethod)(const PODType&); static PassRefPtr create(PassRefPtr parent, GetterMethod getter, SetterMethod setter) { return adoptRef(new V8SVGStaticPODTypeWrapperWithParent(parent, getter, setter)); } virtual operator PODType() { return (m_parent.get()->*m_getter)(); } virtual void commitChange(PODType type, SVGElement* context) { (m_parent.get()->*m_setter)(type); } private: V8SVGStaticPODTypeWrapperWithParent(PassRefPtr parent, GetterMethod getter, SetterMethod setter) : m_parent(parent) , m_getter(getter) , m_setter(setter) { ASSERT(m_parent); ASSERT(m_getter); ASSERT(m_setter); } RefPtr m_parent; GetterMethod m_getter; SetterMethod m_setter; }; template class V8SVGDynamicPODTypeWrapper : public V8SVGPODTypeWrapper { public: typedef PODType (PODTypeCreator::*GetterMethod)() const; typedef void (PODTypeCreator::*SetterMethod)(const PODType&); typedef void (*CacheRemovalCallback)(V8SVGPODTypeWrapper*); static PassRefPtr create(PassRefPtr creator, GetterMethod getter, SetterMethod setter, CacheRemovalCallback cacheRemovalCallback) { return adoptRef(new V8SVGDynamicPODTypeWrapper(creator, getter, setter, cacheRemovalCallback)); } virtual ~V8SVGDynamicPODTypeWrapper() { ASSERT(m_cacheRemovalCallback); (*m_cacheRemovalCallback)(this); } // Getter wrapper virtual operator PODType() { return (m_creator.get()->*m_getter)(); } // Setter wrapper virtual void commitChange(PODType type, SVGElement* context) { (m_creator.get()->*m_setter)(type); if (context) context->svgAttributeChanged(m_creator->associatedAttributeName()); } private: V8SVGDynamicPODTypeWrapper(PassRefPtr creator, GetterMethod getter, SetterMethod setter, CacheRemovalCallback cacheRemovalCallback) : m_creator(creator) , m_getter(getter) , m_setter(setter) , m_cacheRemovalCallback(cacheRemovalCallback) { ASSERT(m_creator); // |creator|'s pointer was taken by m_creator. ASSERT(getter); ASSERT(setter); ASSERT(cacheRemovalCallback); } // Update callbacks RefPtr m_creator; GetterMethod m_getter; SetterMethod m_setter; CacheRemovalCallback m_cacheRemovalCallback; }; // Caching facilities template struct PODTypeWrapperCacheInfo { typedef PODType (PODTypeCreator::*GetterMethod)() const; typedef void (PODTypeCreator::*SetterMethod)(const PODType&); // Empty value PODTypeWrapperCacheInfo() : creator(0) , getter(0) , setter(0) , fieldHash(0) { } // Deleted value explicit PODTypeWrapperCacheInfo(WTF::HashTableDeletedValueType) : creator(reinterpret_cast(-1)) , getter(0) , setter(0) , fieldHash(0) { } bool isHashTableDeletedValue() const { return creator == reinterpret_cast(-1); } PODTypeWrapperCacheInfo(PODTypeCreator* _creator, GetterMethod _getter, SetterMethod _setter, unsigned _fieldHash) : creator(_creator) , getter(_getter) , setter(_setter) , fieldHash(_fieldHash) { ASSERT(creator); ASSERT(getter); } bool operator==(const PODTypeWrapperCacheInfo& other) const { return creator == other.creator && fieldHash == other.fieldHash && getter == other.getter && setter == other.setter; } PODTypeCreator* creator; GetterMethod getter; SetterMethod setter; unsigned fieldHash; }; template struct PODTypeWrapperCacheInfoHash { static unsigned hash(const PODTypeWrapperCacheInfo& info) { // We can't hash member function pointers, but we have enough material // to hash the pointer and field identifier, and on a collision // operator== will still differentiate the member function pointers. return WTF::PairHash::hash(std::pair(info.creator, info.fieldHash)); } static bool equal(const PODTypeWrapperCacheInfo& a, const PODTypeWrapperCacheInfo& b) { return a == b; } static const bool safeToCompareToEmptyOrDeleted = true; }; template struct PODTypeWrapperCacheInfoTraits : WTF::GenericHashTraits > { typedef PODTypeWrapperCacheInfo CacheInfo; static const bool emptyValueIsZero = true; static const bool needsDestruction = false; static const CacheInfo& emptyValue() { DEFINE_STATIC_LOCAL(CacheInfo, key, ()); return key; } static void constructDeletedValue(CacheInfo& slot) { new (&slot) CacheInfo(WTF::HashTableDeletedValue); } static bool isDeletedValue(const CacheInfo& value) { return value.isHashTableDeletedValue(); } }; template class V8SVGDynamicPODTypeWrapperCache { public: typedef PODType (PODTypeCreator::*GetterMethod)() const; typedef void (PODTypeCreator::*SetterMethod)(const PODType&); typedef PODTypeWrapperCacheInfo CacheInfo; typedef PODTypeWrapperCacheInfoHash CacheInfoHash; typedef PODTypeWrapperCacheInfoTraits CacheInfoTraits; typedef V8SVGPODTypeWrapper WrapperBase; typedef V8SVGDynamicPODTypeWrapper DynamicWrapper; typedef HashMap DynamicWrapperHashMap; typedef typename DynamicWrapperHashMap::const_iterator DynamicWrapperHashMapIterator; static DynamicWrapperHashMap& dynamicWrapperHashMap() { DEFINE_STATIC_LOCAL(DynamicWrapperHashMap, dynamicWrapperHashMap, ()); return dynamicWrapperHashMap; } // Used for readwrite attributes only static PassRefPtr lookupOrCreateWrapper(PODTypeCreator* creator, GetterMethod getter, SetterMethod setter, unsigned fieldHash) { DynamicWrapperHashMap& map(dynamicWrapperHashMap()); CacheInfo info(creator, getter, setter, fieldHash); if (map.contains(info)) return map.get(info); RefPtr wrapper = V8SVGDynamicPODTypeWrapper::create(creator, getter, setter, forgetWrapper); map.set(info, wrapper.get()); return wrapper.release(); } static void forgetWrapper(V8SVGPODTypeWrapper* wrapper) { DynamicWrapperHashMap& map(dynamicWrapperHashMap()); DynamicWrapperHashMapIterator it = map.begin(); DynamicWrapperHashMapIterator end = map.end(); for (; it != end; ++it) { if (it->second != wrapper) continue; // It's guaranteed that there's just one object we need to take care of. map.remove(it->first); break; } } }; class V8SVGPODTypeUtil { public: template static P toSVGPODType(WrapperTypeInfo* info, v8::Handle object, bool& ok); }; template P V8SVGPODTypeUtil::toSVGPODType(WrapperTypeInfo* info, v8::Handle object, bool& ok) { if (!V8DOMWrapper::isWrapperOfType(object, info)) { ok = false; return P(); } ok = true; return *V8SVGPODTypeWrapper

::toNative(v8::Handle::Cast(object)); } } // namespace WebCore #endif // ENABLE(SVG) #endif // V8SVGPODTypeWrapper_h