diff options
Diffstat (limited to 'WebCore/bindings/js/JSDOMBinding.cpp')
-rw-r--r-- | WebCore/bindings/js/JSDOMBinding.cpp | 222 |
1 files changed, 56 insertions, 166 deletions
diff --git a/WebCore/bindings/js/JSDOMBinding.cpp b/WebCore/bindings/js/JSDOMBinding.cpp index abba405..a4c3d6a 100644 --- a/WebCore/bindings/js/JSDOMBinding.cpp +++ b/WebCore/bindings/js/JSDOMBinding.cpp @@ -24,7 +24,9 @@ #include "debugger/DebuggerCallFrame.h" #include "ActiveDOMObject.h" +#include "CSSHelper.h" #include "DOMCoreException.h" +#include "DOMObjectHashTableMap.h" #include "Document.h" #include "EventException.h" #include "ExceptionBase.h" @@ -32,11 +34,13 @@ #include "Frame.h" #include "HTMLAudioElement.h" #include "HTMLCanvasElement.h" +#include "HTMLFrameElementBase.h" #include "HTMLImageElement.h" -#include "HTMLScriptElement.h" #include "HTMLNames.h" +#include "HTMLScriptElement.h" #include "JSDOMCoreException.h" #include "JSDOMWindowCustom.h" +#include "JSDebugWrapperSet.h" #include "JSEventException.h" #include "JSExceptionBase.h" #include "JSNode.h" @@ -48,6 +52,7 @@ #include "ScriptCachedFrameData.h" #include "ScriptController.h" #include "Settings.h" +#include "WebCoreJSClientData.h" #include "XMLHttpRequestException.h" #include <runtime/DateInstance.h> #include <runtime/Error.h> @@ -66,11 +71,6 @@ #include "XPathException.h" #endif -#if ENABLE(WORKERS) -#include <wtf/ThreadSpecific.h> -using namespace WTF; -#endif - using namespace JSC; namespace WebCore { @@ -80,85 +80,6 @@ using namespace HTMLNames; typedef Document::JSWrapperCache JSWrapperCache; typedef Document::JSWrapperCacheMap JSWrapperCacheMap; -inline JSWrapperCache* Document::getWrapperCache(DOMWrapperWorld* world) -{ - if (world->isNormal()) { - if (JSWrapperCache* wrapperCache = m_normalWorldWrapperCache) - return wrapperCache; - ASSERT(!m_wrapperCacheMap.contains(world)); - } else if (JSWrapperCache* wrapperCache = m_wrapperCacheMap.get(world)) - return wrapperCache; - return createWrapperCache(world); -} - -// For debugging, keep a set of wrappers currently cached, and check that -// all are uncached before they are destroyed. This helps us catch bugs like: -// - wrappers being deleted without being removed from the cache -// - wrappers being cached twice - -static void willCacheWrapper(DOMObject* wrapper); -static void didUncacheWrapper(DOMObject* wrapper); - -#ifdef NDEBUG - -static inline void willCacheWrapper(DOMObject*) -{ -} - -static inline void didUncacheWrapper(DOMObject*) -{ -} - -#else - -static 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 willCacheWrapper(DOMObject* wrapper) -{ - ASSERT(!wrapperSet().contains(wrapper)); - wrapperSet().add(wrapper); -} - -static void didUncacheWrapper(DOMObject* wrapper) -{ - if (!wrapper) - return; - ASSERT(wrapperSet().contains(wrapper)); - wrapperSet().remove(wrapper); -} - -DOMObject::~DOMObject() -{ - ASSERT(!wrapperSet().contains(this)); -} - -#endif - -DOMWrapperWorld::DOMWrapperWorld(JSC::JSGlobalData* globalData, bool isNormal) - : m_globalData(globalData) - , m_isNormal(isNormal) -{ -} - -DOMWrapperWorld::~DOMWrapperWorld() -{ - JSGlobalData::ClientData* clientData = m_globalData->clientData; - ASSERT(clientData); - static_cast<WebCoreJSClientData*>(clientData)->forgetWorld(this); - - for (HashSet<Document*>::iterator iter = documentsWithWrappers.begin(); iter != documentsWithWrappers.end(); ++iter) - forgetWorldOfDOMNodesForDocument(*iter, this); -} - class JSGlobalDataWorldIterator { public: JSGlobalDataWorldIterator(JSGlobalData* globalData) @@ -195,37 +116,11 @@ private: HashSet<DOMWrapperWorld*>::iterator m_end; }; -DOMWrapperWorld* normalWorld(JSC::JSGlobalData& globalData) -{ - JSGlobalData::ClientData* clientData = globalData.clientData; - ASSERT(clientData); - return static_cast<WebCoreJSClientData*>(clientData)->normalWorld(); -} - -DOMWrapperWorld* mainThreadNormalWorld() -{ - ASSERT(isMainThread()); - static DOMWrapperWorld* cachedNormalWorld = normalWorld(*JSDOMWindow::commonJSGlobalData()); - return cachedNormalWorld; -} - -DOMObjectHashTableMap& DOMObjectHashTableMap::mapFor(JSGlobalData& globalData) -{ - JSGlobalData::ClientData* clientData = globalData.clientData; - ASSERT(clientData); - return static_cast<WebCoreJSClientData*>(clientData)->hashTableMap; -} - const JSC::HashTable* getHashTableForGlobalData(JSGlobalData& globalData, const JSC::HashTable* staticTable) { return DOMObjectHashTableMap::mapFor(globalData).get(staticTable); } -static inline DOMObjectWrapperMap& DOMObjectWrapperMapFor(JSC::ExecState* exec) -{ - return currentWorld(exec)->m_wrappers; -} - bool hasCachedDOMObjectWrapperUnchecked(JSGlobalData* globalData, void* objectHandle) { for (JSGlobalDataWorldIterator worldIter(globalData); worldIter; ++worldIter) { @@ -246,13 +141,13 @@ bool hasCachedDOMObjectWrapper(JSGlobalData* globalData, void* objectHandle) DOMObject* getCachedDOMObjectWrapper(JSC::ExecState* exec, void* objectHandle) { - return DOMObjectWrapperMapFor(exec).get(objectHandle); + return domObjectWrapperMapFor(exec).get(objectHandle); } void cacheDOMObjectWrapper(JSC::ExecState* exec, void* objectHandle, DOMObject* wrapper) { - willCacheWrapper(wrapper); - DOMObjectWrapperMapFor(exec).set(objectHandle, wrapper); + JSDebugWrapperSet::willCacheWrapper(wrapper); + domObjectWrapperMapFor(exec).set(objectHandle, wrapper); } bool hasCachedDOMNodeWrapperUnchecked(Document* document, Node* node) @@ -268,13 +163,6 @@ bool hasCachedDOMNodeWrapperUnchecked(Document* document, Node* node) return false; } -JSNode* getCachedDOMNodeWrapper(JSC::ExecState* exec, Document* document, Node* node) -{ - if (document) - return document->getWrapperCache(currentWorld(exec))->get(node); - return static_cast<JSNode*>(DOMObjectWrapperMapFor(exec).get(node)); -} - void forgetDOMObject(DOMObject* wrapper, void* objectHandle) { JSC::JSGlobalData* globalData = Heap::heap(wrapper)->globalData(); @@ -284,7 +172,7 @@ void forgetDOMObject(DOMObject* wrapper, void* objectHandle) ASSERT(clientData); DOMObjectWrapperMap& wrappers = static_cast<WebCoreJSClientData*>(clientData)->normalWorld()->m_wrappers; if (wrappers.uncheckedRemove(objectHandle, wrapper)) { - didUncacheWrapper(wrapper); + JSDebugWrapperSet::didUncacheWrapper(wrapper); return; } @@ -294,11 +182,13 @@ void forgetDOMObject(DOMObject* wrapper, void* objectHandle) if (worldIter->m_wrappers.uncheckedRemove(objectHandle, wrapper)) break; } - didUncacheWrapper(wrapper); + JSDebugWrapperSet::didUncacheWrapper(wrapper); } void forgetDOMNode(JSNode* wrapper, Node* node, Document* document) { + node->clearWrapper(wrapper); + if (!document) { forgetDOMObject(wrapper, node); return; @@ -311,36 +201,20 @@ void forgetDOMNode(JSNode* wrapper, Node* node, Document* document) if (wrappersIter->second->uncheckedRemove(node, wrapper)) break; } - didUncacheWrapper(wrapper); + JSDebugWrapperSet::didUncacheWrapper(wrapper); } void cacheDOMNodeWrapper(JSC::ExecState* exec, Document* document, Node* node, JSNode* wrapper) { - if (!document) { - willCacheWrapper(wrapper); - DOMObjectWrapperMapFor(exec).set(node, wrapper); - return; - } - willCacheWrapper(wrapper); - document->getWrapperCache(currentWorld(exec))->set(node, wrapper); -} + JSDebugWrapperSet::willCacheWrapper(wrapper); -void forgetAllDOMNodesForDocument(Document* document) -{ - ASSERT(document); - JSWrapperCacheMap& wrapperCacheMap = document->wrapperCacheMap(); - JSWrapperCacheMap::const_iterator wrappersMapEnd = wrapperCacheMap.end(); - for (JSWrapperCacheMap::const_iterator wrappersMapIter = wrapperCacheMap.begin(); wrappersMapIter != wrappersMapEnd; ++wrappersMapIter) { - delete wrappersMapIter->second; - wrappersMapIter->first->forgetDocument(document); - } -} + if (!document) + domObjectWrapperMapFor(exec).set(node, wrapper); + else + document->getWrapperCache(currentWorld(exec))->set(node, wrapper); -void forgetWorldOfDOMNodesForDocument(Document* document, DOMWrapperWorld* world) -{ - JSWrapperCache* wrappers = document->wrapperCacheMap().take(world); - ASSERT(wrappers); // 'world' should only know about 'document' if 'document' knows about 'world'! - delete wrappers; + if (currentWorld(exec)->isNormal()) + node->setWrapper(wrapper); } static inline bool isObservableThroughDOM(JSNode* jsNode, DOMWrapperWorld* world) @@ -464,7 +338,7 @@ static inline void takeWrappers(Node* node, Document* document, WrapperSet& wrap JSWrapperCacheMap& wrapperCacheMap = document->wrapperCacheMap(); for (JSWrapperCacheMap::iterator iter = wrapperCacheMap.begin(); iter != wrapperCacheMap.end(); ++iter) { if (JSNode* wrapper = iter->second->take(node)) { - didUncacheWrapper(wrapper); + JSDebugWrapperSet::didUncacheWrapper(wrapper); wrapperSet.append(WrapperAndWorld(wrapper, iter->first)); } } @@ -472,7 +346,7 @@ static inline void takeWrappers(Node* node, Document* document, WrapperSet& wrap for (JSGlobalDataWorldIterator worldIter(JSDOMWindow::commonJSGlobalData()); worldIter; ++worldIter) { DOMWrapperWorld* world = *worldIter; if (JSNode* wrapper = static_cast<JSNode*>(world->m_wrappers.take(node))) { - didUncacheWrapper(wrapper); + JSDebugWrapperSet::didUncacheWrapper(wrapper); wrapperSet.append(WrapperAndWorld(wrapper, world)); } } @@ -488,7 +362,7 @@ void updateDOMNodeDocument(Node* node, Document* oldDocument, Document* newDocum for (unsigned i = 0; i < wrapperSet.size(); ++i) { JSNode* wrapper = wrapperSet[i].first; - willCacheWrapper(wrapper); + JSDebugWrapperSet::willCacheWrapper(wrapper); if (newDocument) newDocument->getWrapperCache(wrapperSet[i].second)->set(node, wrapper); else @@ -556,7 +430,7 @@ JSValue jsStringSlowCase(ExecState* exec, JSStringCache& stringCache, StringImpl if (JSString* wrapper = stringCache.uncheckedGet(stringImpl)) stringCache.uncheckedRemove(stringImpl, wrapper); - JSString* wrapper = jsStringWithFinalizer(exec, stringImpl->ustring(), stringWrapperDestroyed, stringImpl); + JSString* wrapper = jsStringWithFinalizer(exec, UString(stringImpl), stringWrapperDestroyed, stringImpl); stringCache.set(stringImpl, wrapper); // ref explicitly instead of using a RefPtr-keyed hashtable because the wrapper can // outlive the cache, so the stringImpl has to match the wrapper's lifetime. @@ -618,18 +492,27 @@ JSValue jsStringOrFalse(ExecState* exec, const KURL& url) return jsString(exec, url.string()); } -UString valueToStringWithNullCheck(ExecState* exec, JSValue value) +AtomicStringImpl* findAtomicString(const Identifier& identifier) +{ + if (identifier.isNull()) + return 0; + UStringImpl* impl = identifier.ustring().rep(); + ASSERT(impl->existingHash()); + return AtomicString::find(impl->characters(), impl->length(), impl->existingHash()); +} + +String valueToStringWithNullCheck(ExecState* exec, JSValue value) { if (value.isNull()) - return UString(); - return value.toString(exec); + return String(); + return ustringToString(value.toString(exec)); } -UString valueToStringWithUndefinedOrNullCheck(ExecState* exec, JSValue value) +String valueToStringWithUndefinedOrNullCheck(ExecState* exec, JSValue value) { if (value.isUndefinedOrNull()) - return UString(); - return value.toString(exec); + return String(); + return ustringToString(value.toString(exec)); } JSValue jsDateOrNull(ExecState* exec, double value) @@ -650,6 +533,9 @@ double valueToDate(ExecState* exec, JSValue value) void reportException(ExecState* exec, JSValue exception) { + if (exception.isObject() && asObject(exception)->exceptionType() == Terminated) + return; + UString errorMessage = exception.toString(exec); JSObject* exceptionObject = exception.toObject(exec); int lineNumber = exceptionObject->get(exec, Identifier(exec, "line")).toInt32(exec); @@ -657,7 +543,7 @@ void reportException(ExecState* exec, JSValue exception) exec->clearException(); if (ExceptionBase* exceptionBase = toExceptionBase(exception)) - errorMessage = exceptionBase->message() + ": " + exceptionBase->description(); + errorMessage = stringToUString(exceptionBase->message() + ": " + exceptionBase->description()); ScriptExecutionContext* scriptExecutionContext = static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->scriptExecutionContext(); ASSERT(scriptExecutionContext); @@ -667,7 +553,7 @@ void reportException(ExecState* exec, JSValue exception) if (!scriptExecutionContext) return; - scriptExecutionContext->reportException(errorMessage, lineNumber, exceptionSourceURL); + scriptExecutionContext->reportException(ustringToString(errorMessage), lineNumber, ustringToString(exceptionSourceURL)); } void reportCurrentException(ExecState* exec) @@ -747,6 +633,16 @@ bool shouldAllowNavigation(ExecState* exec, Frame* frame) return lexicalFrame && lexicalFrame->loader()->shouldAllowNavigation(frame); } +bool allowSettingSrcToJavascriptURL(ExecState* exec, Element* element, const String& name, const String& value) +{ + if ((element->hasTagName(iframeTag) || element->hasTagName(frameTag)) && equalIgnoringCase(name, "src") && protocolIsJavaScript(deprecatedParseURL(value))) { + Document* contentDocument = static_cast<HTMLFrameElementBase*>(element)->contentDocument(); + if (contentDocument && !checkNodeSecurity(exec, contentDocument)) + return false; + } + return true; +} + void printErrorMessageForFrame(Frame* frame, const String& message) { if (!frame) @@ -788,7 +684,7 @@ KURL completeURL(ExecState* exec, const String& relativeURL) return frame->loader()->completeURL(relativeURL); } -JSValue objectToStringFunctionGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot&) +JSValue objectToStringFunctionGetter(ExecState* exec, JSValue, const Identifier& propertyName) { return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), 0, propertyName, objectProtoFuncToString); } @@ -852,10 +748,4 @@ JSC::JSObject* toJSSequence(ExecState* exec, JSValue value, unsigned& length) return object; } -bool DOMObject::defineOwnProperty(ExecState* exec, const Identifier&, PropertyDescriptor&, bool) -{ - throwError(exec, TypeError, "defineProperty is not supported on DOM Objects"); - return false; -} - } // namespace WebCore |