summaryrefslogtreecommitdiffstats
path: root/WebCore/bindings/js/JSDOMBinding.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/bindings/js/JSDOMBinding.cpp')
-rw-r--r--WebCore/bindings/js/JSDOMBinding.cpp222
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