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 Node; 40 #if ENABLE(SVG) 41 class SVGElementInstance; 42 #endif 43 44 template <class KeyType, class ValueType> class AbstractWeakReferenceMap { 45 public: 46 AbstractWeakReferenceMap(v8::WeakReferenceCallback callback) : m_weakReferenceCallback(callback) { } 47 virtual ~AbstractWeakReferenceMap() { } 48 49 class Visitor { 50 public: 51 virtual void visitDOMWrapper(KeyType* key, v8::Persistent<ValueType> object) = 0; 52 protected: 53 virtual ~Visitor() { } 54 }; 55 56 virtual v8::Persistent<ValueType> get(KeyType* obj) = 0; 57 virtual void set(KeyType* obj, v8::Persistent<ValueType> wrapper) = 0; 58 virtual bool contains(KeyType* obj) = 0; 59 virtual void visit(Visitor* visitor) = 0; 60 virtual bool removeIfPresent(KeyType* key, v8::Persistent<v8::Data> value) = 0; 61 virtual void clear() = 0; 62 63 v8::WeakReferenceCallback weakReferenceCallback() { return m_weakReferenceCallback; } 64 private: 65 v8::WeakReferenceCallback m_weakReferenceCallback; 66 }; 67 68 typedef AbstractWeakReferenceMap<Node, v8::Object> DOMNodeMapping; 69 70 // A table of wrappers with weak pointers. 71 // This table allows us to avoid track wrapped objects for debugging 72 // and for ensuring that we don't double wrap the same object. 73 template<class KeyType, class ValueType> class WeakReferenceMap : public AbstractWeakReferenceMap<KeyType, ValueType> { 74 public: 75 typedef AbstractWeakReferenceMap<KeyType, ValueType> Parent; 76 WeakReferenceMap(v8::WeakReferenceCallback callback) : Parent(callback) { } 77 virtual ~WeakReferenceMap() 78 { 79 #ifndef NDEBUG 80 if (m_map.size() > 0) 81 fprintf(stderr, "Leak %d JS wrappers.\n", m_map.size()); 82 #endif 83 } 84 85 // Get the JS wrapper object of an object. 86 virtual v8::Persistent<ValueType> get(KeyType* obj) 87 { 88 ValueType* wrapper = m_map.get(obj); 89 return wrapper ? v8::Persistent<ValueType>(wrapper) : v8::Persistent<ValueType>(); 90 } 91 92 virtual void set(KeyType* obj, v8::Persistent<ValueType> wrapper) 93 { 94 ASSERT(!m_map.contains(obj)); 95 wrapper.MakeWeak(obj, Parent::weakReferenceCallback()); 96 m_map.set(obj, *wrapper); 97 } 98 99 virtual void forget(KeyType* obj) 100 { 101 ASSERT(obj); 102 ValueType* wrapper = m_map.take(obj); 103 if (!wrapper) 104 return; 105 106 v8::Persistent<ValueType> handle(wrapper); 107 handle.Dispose(); 108 handle.Clear(); 109 } 110 111 bool removeIfPresent(KeyType* key, v8::Persistent<v8::Data> value) 112 { 113 typename HashMap<KeyType*, ValueType*>::iterator it = m_map.find(key); 114 if (it == m_map.end() || it->second != *value) 115 return false; 116 117 m_map.remove(it); 118 value.Dispose(); 119 return true; 120 } 121 122 void clear() 123 { 124 m_map.clear(); 125 } 126 127 bool contains(KeyType* obj) { return m_map.contains(obj); } 128 129 virtual void visit(typename Parent::Visitor* visitor) 130 { 131 typename HashMap<KeyType*, ValueType*>::iterator it = m_map.begin(); 132 for (; it != m_map.end(); ++it) 133 visitor->visitDOMWrapper(it->first, v8::Persistent<ValueType>(it->second)); 134 } 135 136 protected: 137 HashMap<KeyType*, ValueType*> m_map; 138 v8::WeakReferenceCallback m_weakReferenceCallback; 139 }; 140 141 template <class KeyType> class DOMWrapperMap : public WeakReferenceMap<KeyType, v8::Object> { 142 public: 143 DOMWrapperMap(v8::WeakReferenceCallback callback) : WeakReferenceMap<KeyType, v8::Object>(callback) { } 144 }; 145 146 // An opaque class that represents a set of DOM wrappers. 147 class DOMDataStore; 148 149 // A utility class to manage the lifetime of set of DOM wrappers. 150 class DOMDataStoreHandle { 151 public: 152 DOMDataStoreHandle(); 153 ~DOMDataStoreHandle(); 154 155 DOMDataStore* getStore() const { return m_store.get(); } 156 157 private: 158 OwnPtr<DOMDataStore> m_store; 159 }; 160 161 // A map from DOM node to its JS wrapper. 162 DOMNodeMapping& getDOMNodeMap(); 163 void visitDOMNodesInCurrentThread(DOMWrapperMap<Node>::Visitor*); 164 165 // 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). 166 DOMWrapperMap<void>& getDOMObjectMap(); 167 void visitDOMObjectsInCurrentThread(DOMWrapperMap<void>::Visitor*); 168 169 // A map from a DOM object to its JS wrapper for DOM objects which can have pending activity. 170 DOMWrapperMap<void>& getActiveDOMObjectMap(); 171 void visitActiveDOMObjectsInCurrentThread(DOMWrapperMap<void>::Visitor*); 172 173 // This should be called to remove all DOM objects associated with the current thread when it is tearing down. 174 void removeAllDOMObjectsInCurrentThread(); 175 176 #if ENABLE(SVG) 177 // A map for SVGElementInstances to its JS wrapper. 178 DOMWrapperMap<SVGElementInstance>& getDOMSVGElementInstanceMap(); 179 void visitSVGElementInstancesInCurrentThread(DOMWrapperMap<SVGElementInstance>::Visitor*); 180 181 // Map of SVG objects with contexts to V8 objects. 182 DOMWrapperMap<void>& getDOMSVGObjectWithContextMap(); 183 void visitDOMSVGObjectsInCurrentThread(DOMWrapperMap<void>::Visitor*); 184 #endif 185 186 void enableFasterDOMStoreAccess(); 187 } // namespace WebCore 188 189 #endif // V8DOMMap_h 190