📄 jsdombinding.cpp
字号:
/* * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. * Copyright (C) 2007 Samuel Weinig <sam@webkit.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */// gcc 3.x can't handle including the HashMap pointer specialization in this file#if defined __GNUC__ && !defined __GLIBCXX__ // less than gcc 3.4#define HASH_MAP_PTR_SPEC_WORKAROUND 1#endif#include "config.h"#include "JSDOMBinding.h"#include "ActiveDOMObject.h"#include "DOMCoreException.h"#include "Document.h"#include "EventException.h"#include "ExceptionCode.h"#include "Frame.h"#include "HTMLImageElement.h"#include "HTMLNames.h"#include "JSDOMCoreException.h"#include "JSDOMWindowCustom.h"#include "JSEventException.h"#include "JSNode.h"#include "JSRangeException.h"#include "JSXMLHttpRequestException.h"#include "KURL.h"#include "MessagePort.h"#include "RangeException.h"#include "ScriptController.h"#include "XMLHttpRequestException.h"#include <runtime/PrototypeFunction.h>#include <wtf/StdLibExtras.h>#if ENABLE(SVG)#include "JSSVGException.h"#include "SVGException.h"#endif#if ENABLE(XPATH)#include "JSXPathException.h"#include "XPathException.h"#endif#if ENABLE(WORKERS)#include <wtf/ThreadSpecific.h>using namespace WTF;#endifusing namespace JSC;namespace WebCore {using namespace HTMLNames;typedef Document::JSWrapperCache JSWrapperCache;// For debugging, keep a set of wrappers currently registered, and check that// all are unregistered before they are destroyed. This has helped us fix at// least one bug.static void addWrapper(DOMObject* wrapper);static void removeWrapper(DOMObject* wrapper);static void removeWrappers(const JSWrapperCache& wrappers);#ifdef NDEBUGstatic inline void addWrapper(DOMObject*){}static inline void removeWrapper(DOMObject*){}static inline void removeWrappers(const JSWrapperCache&){}#elsestatic HashSet<DOMObject*>& wrapperSet(){#if ENABLE(WORKERS) DEFINE_STATIC_LOCAL(ThreadSpecific<HashSet<DOMObject*> >, staticWrapperSet, ()); return *staticWrapperSet;#else DEFINE_STATIC_LOCAL(HashSet<DOMObject*>, staticWrapperSet, ()); return staticWrapperSet;#endif}static void addWrapper(DOMObject* wrapper){ ASSERT(!wrapperSet().contains(wrapper)); wrapperSet().add(wrapper);}static void removeWrapper(DOMObject* wrapper){ if (!wrapper) return; ASSERT(wrapperSet().contains(wrapper)); wrapperSet().remove(wrapper);}static void removeWrappers(const JSWrapperCache& wrappers){ for (JSWrapperCache::const_iterator it = wrappers.begin(); it != wrappers.end(); ++it) removeWrapper(it->second);}DOMObject::~DOMObject(){ ASSERT(!wrapperSet().contains(this));}#endifclass DOMObjectWrapperMap {public: static DOMObjectWrapperMap& mapFor(JSGlobalData&); DOMObject* get(void* objectHandle) { return m_map.get(objectHandle); } void set(void* objectHandle, DOMObject* wrapper) { addWrapper(wrapper); m_map.set(objectHandle, wrapper); } void remove(void* objectHandle) { removeWrapper(m_map.take(objectHandle)); }private: HashMap<void*, DOMObject*> m_map;};// Map from static HashTable instances to per-GlobalData ones.class DOMObjectHashTableMap {public: static DOMObjectHashTableMap& mapFor(JSGlobalData&); ~DOMObjectHashTableMap() { HashMap<const JSC::HashTable*, JSC::HashTable>::iterator mapEnd = m_map.end(); for (HashMap<const JSC::HashTable*, JSC::HashTable>::iterator iter = m_map.begin(); iter != m_map.end(); ++iter) iter->second.deleteTable(); } const JSC::HashTable* get(const JSC::HashTable* staticTable) { HashMap<const JSC::HashTable*, JSC::HashTable>::iterator iter = m_map.find(staticTable); if (iter != m_map.end()) return &iter->second; return &m_map.set(staticTable, JSC::HashTable(*staticTable)).first->second; }private: HashMap<const JSC::HashTable*, JSC::HashTable> m_map;};class WebCoreJSClientData : public JSGlobalData::ClientData {public: DOMObjectHashTableMap hashTableMap; DOMObjectWrapperMap wrapperMap;};DOMObjectHashTableMap& DOMObjectHashTableMap::mapFor(JSGlobalData& globalData){ JSGlobalData::ClientData* clientData = globalData.clientData; if (!clientData) { clientData = new WebCoreJSClientData; globalData.clientData = clientData; } return static_cast<WebCoreJSClientData*>(clientData)->hashTableMap;}const JSC::HashTable* getHashTableForGlobalData(JSGlobalData& globalData, const JSC::HashTable* staticTable){ return DOMObjectHashTableMap::mapFor(globalData).get(staticTable);}inline DOMObjectWrapperMap& DOMObjectWrapperMap::mapFor(JSGlobalData& globalData){ JSGlobalData::ClientData* clientData = globalData.clientData; if (!clientData) { clientData = new WebCoreJSClientData; globalData.clientData = clientData; } return static_cast<WebCoreJSClientData*>(clientData)->wrapperMap;}DOMObject* getCachedDOMObjectWrapper(JSGlobalData& globalData, void* objectHandle) { return DOMObjectWrapperMap::mapFor(globalData).get(objectHandle);}void cacheDOMObjectWrapper(JSGlobalData& globalData, void* objectHandle, DOMObject* wrapper) { DOMObjectWrapperMap::mapFor(globalData).set(objectHandle, wrapper);}void forgetDOMObject(JSGlobalData& globalData, void* objectHandle){ DOMObjectWrapperMap::mapFor(globalData).remove(objectHandle);}JSNode* getCachedDOMNodeWrapper(Document* document, Node* node){ if (!document) return static_cast<JSNode*>(DOMObjectWrapperMap::mapFor(*JSDOMWindow::commonJSGlobalData()).get(node)); return document->wrapperCache().get(node);}void forgetDOMNode(Document* document, Node* node){ if (!document) { DOMObjectWrapperMap::mapFor(*JSDOMWindow::commonJSGlobalData()).remove(node); return; } removeWrapper(document->wrapperCache().take(node));}void cacheDOMNodeWrapper(Document* document, Node* node, JSNode* wrapper){ if (!document) { DOMObjectWrapperMap::mapFor(*JSDOMWindow::commonJSGlobalData()).set(node, wrapper); return; } addWrapper(wrapper); document->wrapperCache().set(node, wrapper);}void forgetAllDOMNodesForDocument(Document* document){ ASSERT(document); removeWrappers(document->wrapperCache());}void markDOMNodesForDocument(Document* doc){ // If a node's JS wrapper holds custom properties, those properties must // persist every time the node is fetched from the DOM. So, we keep JS // wrappers like that from being garbage collected. JSWrapperCache& nodeDict = doc->wrapperCache(); JSWrapperCache::iterator nodeEnd = nodeDict.end(); for (JSWrapperCache::iterator nodeIt = nodeDict.begin(); nodeIt != nodeEnd; ++nodeIt) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -