• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006, 2008 Nikolas Zimmermann <zimmermann@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:
V8SVGPODTypeWrapper()50     V8SVGPODTypeWrapper() { }
~V8SVGPODTypeWrapper()51     virtual ~V8SVGPODTypeWrapper() { }
52     virtual operator PODType() = 0;
53     virtual void commitChange(PODType, SVGElement*) = 0;
54 
toNative(v8::Handle<v8::Object> object)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 
create(PassRefPtr<PODListItemPtrType> creator,const QualifiedName & attributeName)69     static PassRefPtr<V8SVGPODTypeWrapperCreatorForList> create(PassRefPtr<PODListItemPtrType> creator, const QualifiedName& attributeName)
70     {
71         return adoptRef(new V8SVGPODTypeWrapperCreatorForList(creator, attributeName));
72     }
73 
~V8SVGPODTypeWrapperCreatorForList()74     virtual ~V8SVGPODTypeWrapperCreatorForList() { }
75 
76     // Getter wrapper
PODType()77     virtual operator PODType() { return (m_creator.get()->*m_getter)(); }
78 
79     // Setter wrapper
commitChange(PODType type,SVGElement * context)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:
V8SVGPODTypeWrapperCreatorForList(PassRefPtr<PODListItemPtrType> creator,const QualifiedName & attributeName)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:
create(PODType type)113     static PassRefPtr<V8SVGStaticPODTypeWrapper> create(PODType type)
114     {
115         return adoptRef(new V8SVGStaticPODTypeWrapper(type));
116     }
117 
~V8SVGStaticPODTypeWrapper()118     virtual ~V8SVGStaticPODTypeWrapper() { }
119 
120     // Getter wrapper
PODType()121     virtual operator PODType() { return m_podType; }
122 
123     // Setter wrapper
commitChange(PODType type,SVGElement *)124     virtual void commitChange(PODType type, SVGElement*)
125     {
126         m_podType = type;
127     }
128 
129 protected:
V8SVGStaticPODTypeWrapper(PODType type)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 
create(PODType type,PassRefPtr<ParentType> parent)143     static PassRefPtr<V8SVGStaticPODTypeWrapperWithPODTypeParent> create(PODType type, PassRefPtr<ParentType> parent)
144     {
145         return adoptRef(new V8SVGStaticPODTypeWrapperWithPODTypeParent(type, parent));
146     }
147 
commitChange(PODType type,SVGElement * context)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:
V8SVGStaticPODTypeWrapperWithPODTypeParent(PODType type,PassRefPtr<ParentType> parent)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 
create(PassRefPtr<ParentType> parent,GetterMethod getter,SetterMethod setter)170     static PassRefPtr<V8SVGStaticPODTypeWrapperWithParent> create(PassRefPtr<ParentType> parent, GetterMethod getter, SetterMethod setter)
171     {
172         return adoptRef(new V8SVGStaticPODTypeWrapperWithParent(parent, getter, setter));
173     }
174 
PODType()175     virtual operator PODType()
176     {
177         return (m_parent.get()->*m_getter)();
178     }
179 
commitChange(PODType type,SVGElement * context)180     virtual void commitChange(PODType type, SVGElement* context)
181     {
182         (m_parent.get()->*m_setter)(type);
183     }
184 
185 private:
V8SVGStaticPODTypeWrapperWithParent(PassRefPtr<ParentType> parent,GetterMethod getter,SetterMethod setter)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 
create(PassRefPtr<PODTypeCreator> creator,GetterMethod getter,SetterMethod setter,CacheRemovalCallback cacheRemovalCallback)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 
~V8SVGDynamicPODTypeWrapper()213     virtual ~V8SVGDynamicPODTypeWrapper() {
214         ASSERT(m_cacheRemovalCallback);
215 
216         (*m_cacheRemovalCallback)(this);
217     }
218 
219     // Getter wrapper
PODType()220     virtual operator PODType() { return (m_creator.get()->*m_getter)(); }
221 
222     // Setter wrapper
commitChange(PODType type,SVGElement * context)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:
V8SVGDynamicPODTypeWrapper(PassRefPtr<PODTypeCreator> creator,GetterMethod getter,SetterMethod setter,CacheRemovalCallback cacheRemovalCallback)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
PODTypeWrapperCacheInfoPODTypeWrapperCacheInfo258     PODTypeWrapperCacheInfo()
259         : creator(0)
260         , getter(0)
261         , setter(0)
262         , fieldHash(0)
263     { }
264 
265     // Deleted value
PODTypeWrapperCacheInfoPODTypeWrapperCacheInfo266     explicit PODTypeWrapperCacheInfo(WTF::HashTableDeletedValueType)
267         : creator(reinterpret_cast<PODTypeCreator*>(-1))
268         , getter(0)
269         , setter(0)
270         , fieldHash(0)
271     {
272     }
273 
isHashTableDeletedValuePODTypeWrapperCacheInfo274     bool isHashTableDeletedValue() const
275     {
276         return creator == reinterpret_cast<PODTypeCreator*>(-1);
277     }
278 
PODTypeWrapperCacheInfoPODTypeWrapperCacheInfo279     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 {
hashPODTypeWrapperCacheInfoHash302     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 
equalPODTypeWrapperCacheInfoHash310     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 
emptyValuePODTypeWrapperCacheInfoTraits325     static const CacheInfo& emptyValue()
326     {
327         DEFINE_STATIC_LOCAL(CacheInfo, key, ());
328         return key;
329     }
330 
constructDeletedValuePODTypeWrapperCacheInfoTraits331     static void constructDeletedValue(CacheInfo& slot)
332     {
333         new (&slot) CacheInfo(WTF::HashTableDeletedValue);
334     }
335 
isDeletedValuePODTypeWrapperCacheInfoTraits336     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 
dynamicWrapperHashMap()358     static DynamicWrapperHashMap& dynamicWrapperHashMap()
359     {
360         DEFINE_STATIC_LOCAL(DynamicWrapperHashMap, dynamicWrapperHashMap, ());
361         return dynamicWrapperHashMap;
362     }
363 
364     // Used for readwrite attributes only
lookupOrCreateWrapper(PODTypeCreator * creator,GetterMethod getter,SetterMethod setter,unsigned fieldHash)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 
forgetWrapper(V8SVGPODTypeWrapper<PODType> * wrapper)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>
toSVGPODType(V8ClassIndex::V8WrapperType type,v8::Handle<v8::Value> object,bool & ok)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