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