| Index: webkit/port/bindings/v8/V8DOMMap.cpp
|
| ===================================================================
|
| --- webkit/port/bindings/v8/V8DOMMap.cpp (revision 12533)
|
| +++ webkit/port/bindings/v8/V8DOMMap.cpp (working copy)
|
| @@ -1,510 +0,0 @@
|
| -/*
|
| - * Copyright (C) 2009 Google Inc. All rights reserved.
|
| - *
|
| - * Redistribution and use in source and binary forms, with or without
|
| - * modification, are permitted provided that the following conditions are
|
| - * met:
|
| - *
|
| - * * Redistributions of source code must retain the above copyright
|
| - * notice, this list of conditions and the following disclaimer.
|
| - * * 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.
|
| - * * Neither the name of Google Inc. nor the names of its
|
| - * contributors may be used to endorse or promote products derived from
|
| - * this software without specific prior written permission.
|
| - *
|
| - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
| - * "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 THE COPYRIGHT
|
| - * OWNER 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.
|
| - */
|
| -
|
| -#include "config.h"
|
| -
|
| -#include <v8.h>
|
| -
|
| -#include "DOMObjectsInclude.h"
|
| -#include "V8DOMMap.h"
|
| -
|
| -#include <wtf/HashMap.h>
|
| -#include <wtf/MainThread.h>
|
| -#include <wtf/Threading.h>
|
| -#include <wtf/ThreadSpecific.h>
|
| -
|
| -namespace WebCore {
|
| -
|
| -// DOM binding algorithm:
|
| -//
|
| -// There are two kinds of DOM objects:
|
| -// 1. DOM tree nodes, such as Document, HTMLElement, ...
|
| -// there classes implements TreeShared<T> interface;
|
| -// 2. Non-node DOM objects, such as CSSRule, Location, etc.
|
| -// these classes implement a ref-counted scheme.
|
| -//
|
| -// A DOM object may have a JS wrapper object. If a tree node
|
| -// is alive, its JS wrapper must be kept alive even it is not
|
| -// reachable from JS roots.
|
| -// However, JS wrappers of non-node objects can go away if
|
| -// not reachable from other JS objects. It works like a cache.
|
| -//
|
| -// DOM objects are ref-counted, and JS objects are traced from
|
| -// a set of root objects. They can create a cycle. To break
|
| -// cycles, we do following:
|
| -// Handles from DOM objects to JS wrappers are always weak,
|
| -// so JS wrappers of non-node object cannot create a cycle.
|
| -// Before starting a global GC, we create a virtual connection
|
| -// between nodes in the same tree in the JS heap. If the wrapper
|
| -// of one node in a tree is alive, wrappers of all nodes in
|
| -// the same tree are considered alive. This is done by creating
|
| -// object groups in GC prologue callbacks. The mark-compact
|
| -// collector will remove these groups after each GC.
|
| -//
|
| -// DOM objects should be deref-ed from the owning thread, not the GC thread
|
| -// that does not own them. In V8, GC can kick in from any thread. To ensure
|
| -// that DOM objects are always deref-ed from the owning thread when running
|
| -// V8 in multi-threading environment, we do following:
|
| -// 1. Maintain a thread specific DOM wrapper map for each object map.
|
| -// (We're using TLS support from WTF instead of base since V8Bindings
|
| -// does not depend on base. We further assume that all child threads
|
| -// running V8 instances are created by WTF and thus a destructor will
|
| -// be called to clean up all thread specific data.)
|
| -// 2. When GC happens:
|
| -// 2.1. If the dead object is in GC thread's map, remove the JS reference
|
| -// and deref the DOM object.
|
| -// 2.2. Otherwise, go through all thread maps to find the owning thread.
|
| -// Remove the JS reference from the owning thread's map and move the
|
| -// DOM object to a delayed queue. Post a task to the owning thread
|
| -// to have it deref-ed from the owning thread at later time.
|
| -// 3. When a thread is tearing down, invoke a cleanup routine to go through
|
| -// all objects in the delayed queue and the thread map and deref all of
|
| -// them.
|
| -
|
| -static void weakDOMObjectCallback(v8::Persistent<v8::Value> obj, void* param);
|
| -static void weakNodeCallback(v8::Persistent<v8::Value> obj, void* param);
|
| -
|
| -#if ENABLE(SVG)
|
| -static void weakSVGElementInstanceCallback(v8::Persistent<v8::Value> obj, void* param);
|
| -
|
| -// SVG non-node elements may have a reference to a context node which should be notified when the element is change
|
| -static void weakSVGObjectWithContextCallback(v8::Persistent<v8::Value> obj, void* domObj);
|
| -#endif
|
| -
|
| -// This is to ensure that we will deref DOM objects from the owning thread, not the GC thread.
|
| -// The helper function will be scheduled by the GC thread to get called from the owning thread.
|
| -static void derefDelayedObjectsInCurrentThread(void*);
|
| -
|
| -// This should be called to remove all DOM objects associated with the current thread when it is tearing down.
|
| -static void removeAllDOMObjectsInCurrentThread();
|
| -
|
| -// A map from a thread ID to thread's specific data.
|
| -class ThreadSpecificDOMData;
|
| -typedef WTF::HashMap<WTF::ThreadIdentifier, ThreadSpecificDOMData*> DOMThreadMap;
|
| -static DOMThreadMap domThreadMap;
|
| -
|
| -// Mutex to protect against concurrent access of domThreadMap.
|
| -static WTF::Mutex domThreadMapMutex;
|
| -
|
| -class ThreadSpecificDOMData {
|
| -public:
|
| - enum DOMWrapperMapType
|
| - {
|
| - DOMNodeMap,
|
| - DOMObjectMap,
|
| - ActiveDOMObjectMap,
|
| -#if ENABLE(SVG)
|
| - DOMSVGElementInstanceMap,
|
| - DOMSVGObjectWithContextMap
|
| -#endif
|
| - };
|
| -
|
| - typedef WTF::HashMap<void*, V8ClassIndex::V8WrapperType> DelayedObjectMap;
|
| -
|
| - template <class KeyType>
|
| - class InternalDOMWrapperMap : public DOMWrapperMap<KeyType> {
|
| - public:
|
| - InternalDOMWrapperMap(v8::WeakReferenceCallback callback)
|
| - : DOMWrapperMap<KeyType>(callback) { }
|
| -
|
| - virtual void forget(KeyType* obj);
|
| -
|
| - void forgetOnly(KeyType* obj)
|
| - {
|
| - DOMWrapperMap<KeyType>::forget(obj);
|
| - }
|
| - };
|
| -
|
| - ThreadSpecificDOMData()
|
| - : m_domNodeMap(new InternalDOMWrapperMap<Node>(&weakNodeCallback))
|
| - , m_domObjectMap(new InternalDOMWrapperMap<void>(weakDOMObjectCallback))
|
| - , m_activeDomObjectMap(new InternalDOMWrapperMap<void>(weakActiveDOMObjectCallback))
|
| -#if ENABLE(SVG)
|
| - , m_domSvgElementInstanceMap(new InternalDOMWrapperMap<SVGElementInstance>(weakSVGElementInstanceCallback))
|
| - , m_domSvgObjectWithContextMap(new InternalDOMWrapperMap<void>(weakSVGObjectWithContextCallback))
|
| -#endif
|
| - , m_delayedProcessingScheduled(false)
|
| - , m_isMainThread(WTF::isMainThread())
|
| - {
|
| - WTF::MutexLocker locker(domThreadMapMutex);
|
| - domThreadMap.set(WTF::currentThread(), this);
|
| - }
|
| -
|
| - // This is called when WTF thread is tearing down.
|
| - // We assume that all child threads running V8 instances are created by WTF.
|
| - ~ThreadSpecificDOMData()
|
| - {
|
| - removeAllDOMObjectsInCurrentThread();
|
| -
|
| - delete m_domNodeMap;
|
| - delete m_domObjectMap;
|
| - delete m_activeDomObjectMap;
|
| -#if ENABLE(SVG)
|
| - delete m_domSvgElementInstanceMap;
|
| - delete m_domSvgObjectWithContextMap;
|
| -#endif
|
| -
|
| - WTF::MutexLocker locker(domThreadMapMutex);
|
| - domThreadMap.remove(WTF::currentThread());
|
| - }
|
| -
|
| - void* getDOMWrapperMap(DOMWrapperMapType type)
|
| - {
|
| - switch (type) {
|
| - case DOMNodeMap:
|
| - return m_domNodeMap;
|
| - case DOMObjectMap:
|
| - return m_domObjectMap;
|
| - case ActiveDOMObjectMap:
|
| - return m_activeDomObjectMap;
|
| -#if ENABLE(SVG)
|
| - case DOMSVGElementInstanceMap:
|
| - return m_domSvgElementInstanceMap;
|
| - case DOMSVGObjectWithContextMap:
|
| - return m_domSvgObjectWithContextMap;
|
| -#endif
|
| - default:
|
| - ASSERT(false);
|
| - return NULL;
|
| - }
|
| - }
|
| -
|
| - InternalDOMWrapperMap<Node>& domNodeMap() { return *m_domNodeMap; }
|
| - InternalDOMWrapperMap<void>& domObjectMap() { return *m_domObjectMap; }
|
| - InternalDOMWrapperMap<void>& activeDomObjectMap() { return *m_activeDomObjectMap; }
|
| -#if ENABLE(SVG)
|
| - InternalDOMWrapperMap<SVGElementInstance>& domSvgElementInstanceMap() { return *m_domSvgElementInstanceMap; }
|
| - InternalDOMWrapperMap<void>& domSvgObjectWithContextMap() { return *m_domSvgObjectWithContextMap; }
|
| -#endif
|
| -
|
| - DelayedObjectMap& delayedObjectMap() { return m_delayedObjectMap; }
|
| - bool delayedProcessingScheduled() const { return m_delayedProcessingScheduled; }
|
| - void setDelayedProcessingScheduled(bool value) { m_delayedProcessingScheduled = value; }
|
| - bool isMainThread() const { return m_isMainThread; }
|
| -
|
| -private:
|
| - InternalDOMWrapperMap<Node>* m_domNodeMap;
|
| - InternalDOMWrapperMap<void>* m_domObjectMap;
|
| - InternalDOMWrapperMap<void>* m_activeDomObjectMap;
|
| -#if ENABLE(SVG)
|
| - InternalDOMWrapperMap<SVGElementInstance>* m_domSvgElementInstanceMap;
|
| - InternalDOMWrapperMap<void>* m_domSvgObjectWithContextMap;
|
| -#endif
|
| -
|
| - // Stores all the DOM objects that are delayed to be processed when the owning thread gains control.
|
| - DelayedObjectMap m_delayedObjectMap;
|
| -
|
| - // The flag to indicate if the task to do the delayed process has already been posted.
|
| - bool m_delayedProcessingScheduled;
|
| -
|
| - bool m_isMainThread;
|
| -};
|
| -
|
| -static WTF::ThreadSpecific<ThreadSpecificDOMData> threadSpecificDOMData;
|
| -
|
| -template<typename T>
|
| -static void handleWeakObjectInOwningThread(ThreadSpecificDOMData::DOMWrapperMapType mapType, V8ClassIndex::V8WrapperType objType, T* obj);
|
| -
|
| -template <class KeyType>
|
| -void ThreadSpecificDOMData::InternalDOMWrapperMap<KeyType>::forget(KeyType* obj)
|
| -{
|
| - DOMWrapperMap<KeyType>::forget(obj);
|
| -
|
| - ThreadSpecificDOMData::DelayedObjectMap& delayedObjectMap = (*threadSpecificDOMData).delayedObjectMap();
|
| - delayedObjectMap.take(obj);
|
| -}
|
| -
|
| -DOMWrapperMap<Node>& getDOMNodeMap()
|
| -{
|
| - return (*threadSpecificDOMData).domNodeMap();
|
| -}
|
| -
|
| -DOMWrapperMap<void>& getDOMObjectMap()
|
| -{
|
| - return (*threadSpecificDOMData).domObjectMap();
|
| -}
|
| -
|
| -DOMWrapperMap<void>& getActiveDOMObjectMap()
|
| -{
|
| - return (*threadSpecificDOMData).activeDomObjectMap();
|
| -}
|
| -
|
| -#if ENABLE(SVG)
|
| -DOMWrapperMap<SVGElementInstance>& getDOMSVGElementInstanceMap()
|
| -{
|
| - return (*threadSpecificDOMData).domSvgElementInstanceMap();
|
| -}
|
| -
|
| -static void weakSVGElementInstanceCallback(v8::Persistent<v8::Value> obj, void* param)
|
| -{
|
| - SVGElementInstance* instance = static_cast<SVGElementInstance*>(param);
|
| -
|
| - ThreadSpecificDOMData::InternalDOMWrapperMap<SVGElementInstance>& map = static_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<SVGElementInstance>&>(getDOMSVGElementInstanceMap());
|
| - if (map.contains(instance)) {
|
| - instance->deref();
|
| - map.forgetOnly(instance);
|
| - } else {
|
| - handleWeakObjectInOwningThread(ThreadSpecificDOMData::DOMSVGElementInstanceMap, V8ClassIndex::SVGELEMENTINSTANCE, instance);
|
| - }
|
| -}
|
| -
|
| -// Map of SVG objects with contexts to V8 objects
|
| -DOMWrapperMap<void>& getDOMSVGObjectWithContextMap()
|
| -{
|
| - return (*threadSpecificDOMData).domSvgObjectWithContextMap();
|
| -}
|
| -
|
| -static void weakSVGObjectWithContextCallback(v8::Persistent<v8::Value> obj, void* domObj)
|
| -{
|
| - v8::HandleScope scope;
|
| - ASSERT(obj->IsObject());
|
| -
|
| - V8ClassIndex::V8WrapperType type = V8Proxy::GetDOMWrapperType(v8::Handle<v8::Object>::Cast(obj));
|
| -
|
| - ThreadSpecificDOMData::InternalDOMWrapperMap<void>& map = static_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<void>&>(getDOMSVGObjectWithContextMap());
|
| - if (map.contains(domObj)) {
|
| - // Forget function removes object from the map and dispose the wrapper.
|
| - map.forgetOnly(domObj);
|
| -
|
| - switch (type) {
|
| -#define MakeCase(TYPE, NAME) \
|
| - case V8ClassIndex::TYPE: static_cast<NAME*>(domObj)->deref(); break;
|
| - SVG_OBJECT_TYPES(MakeCase)
|
| -#undef MakeCase
|
| -#define MakeCase(TYPE, NAME) \
|
| - case V8ClassIndex::TYPE: \
|
| - static_cast<V8SVGPODTypeWrapper<NAME>*>(domObj)->deref(); break;
|
| - SVG_POD_NATIVE_TYPES(MakeCase)
|
| -#undef MakeCase
|
| - default:
|
| - ASSERT(false);
|
| - }
|
| - } else {
|
| - handleWeakObjectInOwningThread(ThreadSpecificDOMData::DOMSVGObjectWithContextMap, type, domObj);
|
| - }
|
| -}
|
| -#endif
|
| -
|
| -// Called when the dead object is not in GC thread's map. Go through all thread maps to find the one containing it.
|
| -// Then clear the JS reference and push the DOM object into the delayed queue for it to be deref-ed at later time from the owning thread.
|
| -// * This is called when the GC thread is not the owning thread.
|
| -// * This can be called on any thread that has GC running.
|
| -// * Only one V8 instance is running at a time due to V8::Locker. So we don't need to worry about concurrency.
|
| -template<typename T>
|
| -static void handleWeakObjectInOwningThread(ThreadSpecificDOMData::DOMWrapperMapType mapType, V8ClassIndex::V8WrapperType objType, T* obj)
|
| -{
|
| - WTF::MutexLocker locker(domThreadMapMutex);
|
| - for (typename DOMThreadMap::iterator iter(domThreadMap.begin()); iter != domThreadMap.end(); ++iter) {
|
| - WTF::ThreadIdentifier threadID = iter->first;
|
| - ThreadSpecificDOMData* threadData = iter->second;
|
| -
|
| - // Skip the current thread that is GC thread.
|
| - if (threadID == WTF::currentThread()) {
|
| - ASSERT(!static_cast<DOMWrapperMap<T>*>(threadData->getDOMWrapperMap(mapType))->contains(obj));
|
| - continue;
|
| - }
|
| -
|
| - ThreadSpecificDOMData::InternalDOMWrapperMap<T>* domMap = static_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<T>*>(threadData->getDOMWrapperMap(mapType));
|
| - if (domMap->contains(obj)) {
|
| - // Clear the JS reference.
|
| - domMap->forgetOnly(obj);
|
| -
|
| - // Push into the delayed queue.
|
| - threadData->delayedObjectMap().set(obj, objType);
|
| -
|
| - // Post a task to the owning thread in order to process the delayed queue.
|
| - // FIXME(jianli): For now, we can only post to main thread due to WTF task posting limitation. We will fix this when we work on nested worker.
|
| - if (!threadData->delayedProcessingScheduled()) {
|
| - threadData->setDelayedProcessingScheduled(true);
|
| - if (threadData->isMainThread())
|
| - WTF::callOnMainThread(&derefDelayedObjectsInCurrentThread, NULL);
|
| - }
|
| -
|
| - break;
|
| - }
|
| - }
|
| -}
|
| -
|
| -// Called when obj is near death (not reachable from JS roots).
|
| -// It is time to remove the entry from the table and dispose the handle.
|
| -static void weakDOMObjectCallback(v8::Persistent<v8::Value> obj, void* domObj)
|
| -{
|
| - v8::HandleScope scope;
|
| - ASSERT(obj->IsObject());
|
| -
|
| - V8ClassIndex::V8WrapperType type = V8Proxy::GetDOMWrapperType(v8::Handle<v8::Object>::Cast(obj));
|
| -
|
| - ThreadSpecificDOMData::InternalDOMWrapperMap<void>& map = static_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<void>&>(getDOMObjectMap());
|
| - if (map.contains(domObj)) {
|
| - // Forget function removes object from the map and dispose the wrapper.
|
| - map.forgetOnly(domObj);
|
| -
|
| - switch (type) {
|
| -#define MakeCase(TYPE, NAME) \
|
| - case V8ClassIndex::TYPE: static_cast<NAME*>(domObj)->deref(); break;
|
| - DOM_OBJECT_TYPES(MakeCase)
|
| -#undef MakeCase
|
| - default:
|
| - ASSERT(false);
|
| - }
|
| - } else {
|
| - handleWeakObjectInOwningThread(ThreadSpecificDOMData::DOMObjectMap, type, domObj);
|
| - }
|
| -}
|
| -
|
| -void weakActiveDOMObjectCallback(v8::Persistent<v8::Value> obj, void* domObj)
|
| -{
|
| - v8::HandleScope scope;
|
| - ASSERT(obj->IsObject());
|
| -
|
| - V8ClassIndex::V8WrapperType type = V8Proxy::GetDOMWrapperType(v8::Handle<v8::Object>::Cast(obj));
|
| -
|
| - ThreadSpecificDOMData::InternalDOMWrapperMap<void>& map = static_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<void>&>(getActiveDOMObjectMap());
|
| - if (map.contains(domObj)) {
|
| - // Forget function removes object from the map and dispose the wrapper.
|
| - map.forgetOnly(domObj);
|
| -
|
| - switch (type) {
|
| -#define MakeCase(TYPE, NAME) \
|
| - case V8ClassIndex::TYPE: static_cast<NAME*>(domObj)->deref(); break;
|
| - ACTIVE_DOM_OBJECT_TYPES(MakeCase)
|
| -#undef MakeCase
|
| - default:
|
| - ASSERT(false);
|
| - }
|
| - } else {
|
| - handleWeakObjectInOwningThread(ThreadSpecificDOMData::ActiveDOMObjectMap, type, domObj);
|
| - }
|
| -}
|
| -
|
| -static void weakNodeCallback(v8::Persistent<v8::Value> obj, void* param)
|
| -{
|
| - Node* node = static_cast<Node*>(param);
|
| -
|
| - ThreadSpecificDOMData::InternalDOMWrapperMap<Node>& map = static_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<Node>&>(getDOMNodeMap());
|
| - if (map.contains(node)) {
|
| - map.forgetOnly(node);
|
| - node->deref();
|
| - } else {
|
| - handleWeakObjectInOwningThread<Node>(ThreadSpecificDOMData::DOMNodeMap, V8ClassIndex::NODE, node);
|
| - }
|
| -}
|
| -
|
| -static void derefObject(V8ClassIndex::V8WrapperType type, void* domObj)
|
| -{
|
| - switch (type) {
|
| - case V8ClassIndex::NODE:
|
| - static_cast<Node*>(domObj)->deref();
|
| - break;
|
| -
|
| -#define MakeCase(TYPE, NAME) \
|
| - case V8ClassIndex::TYPE: static_cast<NAME*>(domObj)->deref(); break;
|
| - DOM_OBJECT_TYPES(MakeCase) // This includes both active and non-active.
|
| -#undef MakeCase
|
| -
|
| -#if ENABLE(SVG)
|
| -#define MakeCase(TYPE, NAME) \
|
| - case V8ClassIndex::TYPE: static_cast<NAME*>(domObj)->deref(); break;
|
| - SVG_OBJECT_TYPES(MakeCase) // This also includes SVGElementInstance.
|
| -#undef MakeCase
|
| -
|
| -#define MakeCase(TYPE, NAME) \
|
| - case V8ClassIndex::TYPE: \
|
| - static_cast<V8SVGPODTypeWrapper<NAME>*>(domObj)->deref(); break;
|
| - SVG_POD_NATIVE_TYPES(MakeCase)
|
| -#undef MakeCase
|
| -#endif
|
| -
|
| - default:
|
| - ASSERT(false);
|
| - }
|
| -}
|
| -
|
| -static void derefDelayedObjects()
|
| -{
|
| - WTF::MutexLocker locker(domThreadMapMutex);
|
| - ThreadSpecificDOMData::DelayedObjectMap& delayedObjectMap = (*threadSpecificDOMData).delayedObjectMap();
|
| - for (ThreadSpecificDOMData::DelayedObjectMap::iterator iter(delayedObjectMap.begin()); iter != delayedObjectMap.end(); ++iter) {
|
| - derefObject(iter->second, iter->first);
|
| - }
|
| - delayedObjectMap.clear();
|
| -}
|
| -
|
| -static void derefDelayedObjectsInCurrentThread(void*)
|
| -{
|
| - (*threadSpecificDOMData).setDelayedProcessingScheduled(false);
|
| - derefDelayedObjects();
|
| -}
|
| -
|
| -template<typename T>
|
| -static void removeObjectsFromWrapperMap(DOMWrapperMap<T>& domMap)
|
| -{
|
| - for (typename WTF::HashMap<T*, v8::Object*>::iterator iter(domMap.impl().begin()); iter != domMap.impl().end(); ++iter) {
|
| - T* domObj = static_cast<T*>(iter->first);
|
| - v8::Persistent<v8::Object> obj(iter->second);
|
| -
|
| - V8ClassIndex::V8WrapperType type = V8Proxy::GetDOMWrapperType(v8::Handle<v8::Object>::Cast(obj));
|
| -
|
| - // Deref the DOM object.
|
| - derefObject(type, domObj);
|
| -
|
| - // Clear the JS wrapper.
|
| - obj.Dispose();
|
| - }
|
| - domMap.impl().clear();
|
| -}
|
| -
|
| -static void removeAllDOMObjectsInCurrentThread()
|
| -{
|
| - v8::Locker locker;
|
| - v8::HandleScope scope;
|
| -
|
| - // Deref all objects in the delayed queue.
|
| - derefDelayedObjects();
|
| -
|
| - // Remove all DOM nodes.
|
| - removeObjectsFromWrapperMap<Node>(getDOMNodeMap());
|
| -
|
| - // Remove all DOM objects in the wrapper map.
|
| - removeObjectsFromWrapperMap<void>(getDOMObjectMap());
|
| -
|
| - // Remove all active DOM objects in the wrapper map.
|
| - removeObjectsFromWrapperMap<void>(getActiveDOMObjectMap());
|
| -
|
| -#if ENABLE(SVG)
|
| - // Remove all SVG element instances in the wrapper map.
|
| - removeObjectsFromWrapperMap<SVGElementInstance>(getDOMSVGElementInstanceMap());
|
| -
|
| - // Remove all SVG objects with context in the wrapper map.
|
| - removeObjectsFromWrapperMap<void>(getDOMSVGObjectWithContextMap());
|
| -#endif
|
| -}
|
| -
|
| -} // namespace WebCore
|
|
|