1 /* 2 * Copyright (C) 2009 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #ifndef V8DOMMap_h 32 #define V8DOMMap_h 33 34 #include <wtf/HashMap.h> 35 #include <wtf/OwnPtr.h> 36 #include <v8.h> 37 38 namespace WebCore { 39 class DOMDataStore; 40 class Node; 41 #if ENABLE(SVG) 42 class SVGElementInstance; 43 #endif 44 45 template <class KeyType, class ValueType> class AbstractWeakReferenceMap { 46 public: AbstractWeakReferenceMap(v8::WeakReferenceCallback callback)47 AbstractWeakReferenceMap(v8::WeakReferenceCallback callback) : m_weakReferenceCallback(callback) { } ~AbstractWeakReferenceMap()48 virtual ~AbstractWeakReferenceMap() { } 49 50 class Visitor { 51 public: startMap()52 virtual void startMap() { } endMap()53 virtual void endMap() { } 54 virtual void visitDOMWrapper(DOMDataStore* store, KeyType* key, v8::Persistent<ValueType> object) = 0; 55 protected: ~Visitor()56 virtual ~Visitor() { } 57 }; 58 59 virtual v8::Persistent<ValueType> get(KeyType* obj) = 0; 60 virtual void set(KeyType* obj, v8::Persistent<ValueType> wrapper) = 0; 61 virtual bool contains(KeyType* obj) = 0; 62 virtual void visit(DOMDataStore* store, Visitor* visitor) = 0; 63 virtual bool removeIfPresent(KeyType*, v8::Persistent<ValueType>) = 0; 64 virtual void clear() = 0; 65 weakReferenceCallback()66 v8::WeakReferenceCallback weakReferenceCallback() { return m_weakReferenceCallback; } 67 private: 68 v8::WeakReferenceCallback m_weakReferenceCallback; 69 }; 70 71 typedef AbstractWeakReferenceMap<Node, v8::Object> DOMNodeMapping; 72 73 // A table of wrappers with weak pointers. 74 // This table allows us to avoid track wrapped objects for debugging 75 // and for ensuring that we don't double wrap the same object. 76 template<class KeyType, class ValueType> class WeakReferenceMap : public AbstractWeakReferenceMap<KeyType, ValueType> { 77 public: 78 typedef AbstractWeakReferenceMap<KeyType, ValueType> Parent; WeakReferenceMap(v8::WeakReferenceCallback callback)79 WeakReferenceMap(v8::WeakReferenceCallback callback) : Parent(callback) { } ~WeakReferenceMap()80 virtual ~WeakReferenceMap() { } 81 82 // Get the JS wrapper object of an object. get(KeyType * obj)83 virtual v8::Persistent<ValueType> get(KeyType* obj) 84 { 85 ValueType* wrapper = m_map.get(obj); 86 return wrapper ? v8::Persistent<ValueType>(wrapper) : v8::Persistent<ValueType>(); 87 } 88 set(KeyType * obj,v8::Persistent<ValueType> wrapper)89 virtual void set(KeyType* obj, v8::Persistent<ValueType> wrapper) 90 { 91 ASSERT(!m_map.contains(obj)); 92 wrapper.MakeWeak(obj, Parent::weakReferenceCallback()); 93 m_map.set(obj, *wrapper); 94 } 95 forget(KeyType * obj)96 virtual void forget(KeyType* obj) 97 { 98 ASSERT(obj); 99 ValueType* wrapper = m_map.take(obj); 100 if (!wrapper) 101 return; 102 103 v8::Persistent<ValueType> handle(wrapper); 104 handle.Dispose(); 105 handle.Clear(); 106 } 107 removeIfPresent(KeyType * key,v8::Persistent<ValueType> value)108 bool removeIfPresent(KeyType* key, v8::Persistent<ValueType> value) 109 { 110 typename HashMap<KeyType*, ValueType*>::iterator it = m_map.find(key); 111 if (it == m_map.end() || it->second != *value) 112 return false; 113 114 m_map.remove(it); 115 value.Dispose(); 116 return true; 117 } 118 clear()119 void clear() 120 { 121 m_map.clear(); 122 } 123 contains(KeyType * obj)124 bool contains(KeyType* obj) { return m_map.contains(obj); } 125 visit(DOMDataStore * store,typename Parent::Visitor * visitor)126 virtual void visit(DOMDataStore* store, typename Parent::Visitor* visitor) 127 { 128 visitor->startMap(); 129 typename HashMap<KeyType*, ValueType*>::iterator it = m_map.begin(); 130 for (; it != m_map.end(); ++it) 131 visitor->visitDOMWrapper(store, it->first, v8::Persistent<ValueType>(it->second)); 132 visitor->endMap(); 133 } 134 135 protected: 136 HashMap<KeyType*, ValueType*> m_map; 137 }; 138 139 template <class KeyType> class DOMWrapperMap : public WeakReferenceMap<KeyType, v8::Object> { 140 public: DOMWrapperMap(v8::WeakReferenceCallback callback)141 DOMWrapperMap(v8::WeakReferenceCallback callback) : WeakReferenceMap<KeyType, v8::Object>(callback) { } 142 }; 143 144 // An opaque class that represents a set of DOM wrappers. 145 class DOMDataStore; 146 147 // A utility class to manage the lifetime of set of DOM wrappers. 148 class DOMDataStoreHandle { 149 public: 150 DOMDataStoreHandle(); 151 ~DOMDataStoreHandle(); 152 getStore()153 DOMDataStore* getStore() const { return m_store.get(); } 154 155 private: 156 OwnPtr<DOMDataStore> m_store; 157 }; 158 159 // A map from DOM node to its JS wrapper. 160 DOMNodeMapping& getDOMNodeMap(); 161 void visitDOMNodesInCurrentThread(DOMWrapperMap<Node>::Visitor*); 162 163 // A map from a DOM object (non-node) to its JS wrapper. This map does not contain the DOM objects which can have pending activity (active dom objects). 164 DOMWrapperMap<void>& getDOMObjectMap(); 165 void visitDOMObjectsInCurrentThread(DOMWrapperMap<void>::Visitor*); 166 167 // A map from a DOM object to its JS wrapper for DOM objects which can have pending activity. 168 DOMWrapperMap<void>& getActiveDOMObjectMap(); 169 void visitActiveDOMObjectsInCurrentThread(DOMWrapperMap<void>::Visitor*); 170 171 // This should be called to remove all DOM objects associated with the current thread when it is tearing down. 172 void removeAllDOMObjectsInCurrentThread(); 173 174 #if ENABLE(SVG) 175 // A map for SVGElementInstances to its JS wrapper. 176 DOMWrapperMap<SVGElementInstance>& getDOMSVGElementInstanceMap(); 177 void visitSVGElementInstancesInCurrentThread(DOMWrapperMap<SVGElementInstance>::Visitor*); 178 #endif 179 180 void enableFasterDOMStoreAccess(); 181 } // namespace WebCore 182 183 #endif // V8DOMMap_h 184